web/satellite/vuetify-poc: update access grant creation dialog

This change updates the access grant creation dialog to align with our
new designs. It also fixes an issue that would occur if the web worker
was initialized after the dialog was mounted.

Resolves #6169

Change-Id: Ic557766e6fcf57cc79c72e670a0e83c7eb2834ba
This commit is contained in:
Jeremy Wharton 2023-08-22 20:14:57 -05:00 committed by Storj Robot
parent e44365d265
commit 61fe95c44a
3 changed files with 66 additions and 65 deletions

View File

@ -69,14 +69,6 @@
/> />
</v-window-item> </v-window-item>
<v-window-item :value="CreateAccessStep.EnterMyPassphrase">
<enter-passphrase-step
:ref="stepInfos[CreateAccessStep.EnterMyPassphrase].ref"
:passphrase-type="CreateAccessStep.EnterMyPassphrase"
@passphrase-changed="newPass => passphrase = newPass"
/>
</v-window-item>
<v-window-item :value="CreateAccessStep.EnterNewPassphrase"> <v-window-item :value="CreateAccessStep.EnterNewPassphrase">
<enter-passphrase-step <enter-passphrase-step
:ref="stepInfos[CreateAccessStep.EnterNewPassphrase].ref" :ref="stepInfos[CreateAccessStep.EnterNewPassphrase].ref"
@ -320,16 +312,13 @@ const stepInfos: Record<CreateAccessStep, StepInfo> = {
switch (passphraseOption.value) { switch (passphraseOption.value) {
case PassphraseOption.EnterNewPassphrase: return CreateAccessStep.EnterNewPassphrase; case PassphraseOption.EnterNewPassphrase: return CreateAccessStep.EnterNewPassphrase;
case PassphraseOption.GenerateNewPassphrase: return CreateAccessStep.PassphraseGenerated; case PassphraseOption.GenerateNewPassphrase: return CreateAccessStep.PassphraseGenerated;
case PassphraseOption.SetMyProjectPassphrase: return CreateAccessStep.EnterMyPassphrase;
default: return CreateAccessStep.ConfirmDetails; default: return CreateAccessStep.ConfirmDetails;
} }
}, },
), ),
[CreateAccessStep.EnterMyPassphrase]: new StepInfo( [CreateAccessStep.EnterMyPassphrase]: new StepInfo(), // unused
CreateAccessStep.AccessEncryption,
CreateAccessStep.ConfirmDetails,
),
[CreateAccessStep.EnterNewPassphrase]: new StepInfo( [CreateAccessStep.EnterNewPassphrase]: new StepInfo(
CreateAccessStep.AccessEncryption, CreateAccessStep.AccessEncryption,
CreateAccessStep.ConfirmDetails, CreateAccessStep.ConfirmDetails,
@ -344,7 +333,6 @@ const stepInfos: Record<CreateAccessStep, StepInfo> = {
switch (passphraseOption.value) { switch (passphraseOption.value) {
case PassphraseOption.EnterNewPassphrase: return CreateAccessStep.EnterNewPassphrase; case PassphraseOption.EnterNewPassphrase: return CreateAccessStep.EnterNewPassphrase;
case PassphraseOption.GenerateNewPassphrase: return CreateAccessStep.PassphraseGenerated; case PassphraseOption.GenerateNewPassphrase: return CreateAccessStep.PassphraseGenerated;
case PassphraseOption.SetMyProjectPassphrase: return CreateAccessStep.EnterMyPassphrase;
default: return CreateAccessStep.AccessEncryption; default: return CreateAccessStep.AccessEncryption;
} }
}, },
@ -570,6 +558,13 @@ watch(innerContent, async (comp: Component): Promise<void> => {
return; return;
} }
worker.value = agStore.state.accessGrantsWebWorker;
if (worker.value) {
worker.value.onerror = (error: ErrorEvent) => {
notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
};
}
isFetching.value = true; isFetching.value = true;
const projectID = projectsStore.state.selectedProject.id; const projectID = projectsStore.state.selectedProject.id;
@ -584,14 +579,6 @@ watch(innerContent, async (comp: Component): Promise<void> => {
stepInfos[step.value].ref.value?.onEnter?.(); stepInfos[step.value].ref.value?.onEnter?.();
}); });
onMounted(() => {
worker.value = agStore.state.accessGrantsWebWorker;
if (!worker.value) return;
worker.value.onerror = (error: ErrorEvent) => {
notify.error(error.message, AnalyticsErrorEventSource.CREATE_AG_MODAL);
};
});
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -2,21 +2,34 @@
// See LICENSE for copying information. // See LICENSE for copying information.
<template> <template>
<v-form ref="form" class="pa-8"> <v-form ref="form" class="pa-8 pb-4">
<v-row> <v-row>
<v-col cols="12"> <v-col cols="12">
<p class="text-subtitle-2 font-weight-bold mb-2">Encryption Passphrase</p> <p class="text-subtitle-2 font-weight-bold mb-2">Encryption Passphrase</p>
<v-radio-group v-model="passphraseOption" :rules="[ RequiredRule ]" hide-details="auto"> <v-radio-group v-model="passphraseOption" hide-details="auto">
<v-radio v-if="isPromptForPassphrase" label="Enter your project passphrase" :value="PassphraseOption.SetMyProjectPassphrase"> <template v-if="isPromptForPassphrase">
<template #label> <v-radio v-if="isPromptForPassphrase" label="Enter your project passphrase" :value="PassphraseOption.SetMyProjectPassphrase">
Enter your project passphrase <template #label>
<info-tooltip> Enter my project passphrase
You will enter your encryption passphrase on the next step. <info-tooltip>
Make sure it's the same one you use for this project. You will enter your encryption passphrase on the next step.
This will allow you to manage existing data you have uploaded with the same passphrase. Make sure it's the same one you use for this project.
</info-tooltip> This will allow you to manage existing data you have uploaded with the same passphrase.
</template> </info-tooltip>
</v-radio> </template>
</v-radio>
<v-text-field
v-model="passphrase"
class="mt-3"
variant="outlined"
label="Enter Encryption Passphrase"
:append-inner-icon="isPassphraseVisible ? 'mdi-eye-off' : 'mdi-eye'"
:type="isPassphraseVisible ? 'text' : 'password'"
:rules="passphraseRules"
@click:append-inner="isPassphraseVisible = !isPassphraseVisible"
/>
<v-divider class="my-4" />
</template>
<v-radio v-else :value="PassphraseOption.UseExistingPassphrase"> <v-radio v-else :value="PassphraseOption.UseExistingPassphrase">
<template #label> <template #label>
Use the current passphrase Use the current passphrase
@ -62,7 +75,7 @@
</v-col> </v-col>
<v-expand-transition> <v-expand-transition>
<v-col v-show="areAdvancedOptionsShown" cols="12"> <v-col v-show="areAdvancedOptionsShown" cols="12">
<v-alert type="warning" variant="tonal" rounded="xlg"> <v-alert class="mb-4" type="warning" variant="tonal" rounded="xlg">
Creating a new passphrase for this access will prevent it from accessing any data Creating a new passphrase for this access will prevent it from accessing any data
that has been uploaded with the current passphrase. that has been uploaded with the current passphrase.
</v-alert> </v-alert>
@ -83,12 +96,14 @@ import {
VBtn, VBtn,
VExpandTransition, VExpandTransition,
VAlert, VAlert,
VTextField,
VDivider,
} from 'vuetify/components'; } from 'vuetify/components';
import { PassphraseOption } from '@/types/createAccessGrant'; import { PassphraseOption } from '@/types/createAccessGrant';
import { CreateAccessStepComponent } from '@poc/types/createAccessGrant'; import { CreateAccessStepComponent } from '@poc/types/createAccessGrant';
import { useBucketsStore } from '@/store/modules/bucketsStore'; import { useBucketsStore } from '@/store/modules/bucketsStore';
import { RequiredRule } from '@poc/types/common'; import { RequiredRule, ValidationRule } from '@poc/types/common';
import InfoTooltip from '@poc/components/dialogs/createAccessSteps/InfoTooltip.vue'; import InfoTooltip from '@poc/components/dialogs/createAccessSteps/InfoTooltip.vue';
@ -99,6 +114,9 @@ const emit = defineEmits<{
const form = ref<VForm | null>(null); const form = ref<VForm | null>(null);
const passphraseOption = ref<PassphraseOption>(); const passphraseOption = ref<PassphraseOption>();
const passphrase = ref<string>('');
const isPassphraseVisible = ref<boolean>(false);
const areAdvancedOptionsShown = ref<boolean>(false);
watch(passphraseOption, value => value && emit('selectOption', value)); watch(passphraseOption, value => value && emit('selectOption', value));
@ -109,8 +127,6 @@ const bucketsStore = useBucketsStore();
*/ */
const isPromptForPassphrase = computed<boolean>(() => bucketsStore.state.promptForPassphrase); const isPromptForPassphrase = computed<boolean>(() => bucketsStore.state.promptForPassphrase);
const areAdvancedOptionsShown = ref<boolean>(isPromptForPassphrase.value);
/** /**
* Indicates whether an option in the Advanced menu has been selected. * Indicates whether an option in the Advanced menu has been selected.
*/ */
@ -119,15 +135,33 @@ const isAdvancedOptionSelected = computed<boolean>(() => {
|| passphraseOption.value === PassphraseOption.GenerateNewPassphrase; || passphraseOption.value === PassphraseOption.GenerateNewPassphrase;
}); });
const passphraseRules = computed<ValidationRule<string>[]>(() => {
const required = passphraseOption.value === PassphraseOption.SetMyProjectPassphrase;
return [ v => !required || !!v || 'Required' ];
});
defineExpose<CreateAccessStepComponent>({ defineExpose<CreateAccessStepComponent>({
title: 'Access Encryption', title: 'Access Encryption',
validate: () => { validate: () => {
form.value?.validate(); form.value?.validate();
return !!form.value?.isValid; const passphraseRequired = passphraseOption.value === PassphraseOption.SetMyProjectPassphrase;
return !!form.value?.isValid && (!passphraseRequired || !!passphrase.value);
},
onEnter: () => {
if (passphraseOption.value) return;
passphraseOption.value = isPromptForPassphrase.value ?
PassphraseOption.SetMyProjectPassphrase :
PassphraseOption.UseExistingPassphrase;
}, },
onExit: () => { onExit: () => {
if (passphraseOption.value !== PassphraseOption.UseExistingPassphrase) return; switch (passphraseOption.value) {
emit('passphraseChanged', bucketsStore.state.passphrase); case PassphraseOption.UseExistingPassphrase:
emit('passphraseChanged', bucketsStore.state.passphrase);
break;
case PassphraseOption.SetMyProjectPassphrase:
emit('passphraseChanged', passphrase.value);
break;
}
}, },
}); });
</script> </script>

View File

@ -5,13 +5,8 @@
<v-form ref="form" class="pa-8" @submit.prevent> <v-form ref="form" class="pa-8" @submit.prevent>
<v-row> <v-row>
<v-col cols="12"> <v-col cols="12">
<p v-if="passphraseType === CreateAccessStep.EnterMyPassphrase"> This passphrase will be used to encrypt all the files you upload using this access grant.
Enter the encryption passphrase used for this project to create this access grant. You will need it to access these files in the future.
</p>
<p v-else>
This passphrase will be used to encrypt all the files you upload using this access grant.
You will need it to access these files in the future.
</p>
</v-col> </v-col>
<v-col cols="12"> <v-col cols="12">
@ -26,32 +21,17 @@
@click:append-inner="isPassphraseVisible = !isPassphraseVisible" @click:append-inner="isPassphraseVisible = !isPassphraseVisible"
/> />
</v-col> </v-col>
<v-col v-if="passphraseType !== CreateAccessStep.EnterMyPassphrase" cols="12">
<v-checkbox
density="compact"
color="primary"
label="Yes, I saved my encryption passphrase."
hide-details="auto"
:rules="[ RequiredRule ]"
/>
</v-col>
</v-row> </v-row>
</v-form> </v-form>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, watch } from 'vue'; import { ref, watch } from 'vue';
import { VForm, VRow, VCol, VTextField, VCheckbox } from 'vuetify/components'; import { VForm, VRow, VCol, VTextField } from 'vuetify/components';
import { CreateAccessStep } from '@/types/createAccessGrant';
import { CreateAccessStepComponent } from '@poc/types/createAccessGrant'; import { CreateAccessStepComponent } from '@poc/types/createAccessGrant';
import { RequiredRule } from '@poc/types/common'; import { RequiredRule } from '@poc/types/common';
const props = defineProps<{
passphraseType: CreateAccessStep.EnterMyPassphrase | CreateAccessStep.EnterNewPassphrase,
}>();
const form = ref<VForm | null>(null); const form = ref<VForm | null>(null);
const passphrase = ref<string>(''); const passphrase = ref<string>('');
@ -64,7 +44,7 @@ const emit = defineEmits<{
watch(passphrase, value => emit('passphraseChanged', value)); watch(passphrase, value => emit('passphraseChanged', value));
defineExpose<CreateAccessStepComponent>({ defineExpose<CreateAccessStepComponent>({
title: props.passphraseType === CreateAccessStep.EnterMyPassphrase ? 'Enter Passphrase' : 'Enter New Passphrase', title: 'Enter New Passphrase',
validate: () => { validate: () => {
form.value?.validate(); form.value?.validate();
return !!form.value?.isValid; return !!form.value?.isValid;