web/satellite: rewrite VInput with composition API
This change updates VInput with composition API, and fix resulting test failures. see: https://github.com/storj/storj/issues/5115 Change-Id: Ic6870f4faef51de168ef077952b7ce6a39562e6e
This commit is contained in:
parent
b23b3e02e6
commit
fac638fc7d
@ -64,7 +64,6 @@ module.exports = {
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
}],
|
||||
|
||||
'no-duplicate-imports': 'error',
|
||||
'object-curly-spacing': ['error', 'always'],
|
||||
'quotes': ['error', 'single', { 'allowTemplateLiterals': true }],
|
||||
|
@ -15,7 +15,7 @@
|
||||
:label="inputLabel"
|
||||
placeholder="Enter Coupon Code"
|
||||
height="52px"
|
||||
:with-icon="true"
|
||||
with-icon
|
||||
@setData="setCouponCode"
|
||||
/>
|
||||
<CheckIcon
|
||||
|
@ -10,7 +10,7 @@
|
||||
<VInput
|
||||
placeholder="Enter Coupon Code"
|
||||
height="52px"
|
||||
:with-icon="false"
|
||||
with-icon
|
||||
@setData="setCouponCode"
|
||||
/>
|
||||
</div>
|
||||
|
@ -53,7 +53,7 @@
|
||||
placeholder="Enter a passphrase here..."
|
||||
:error="enterError"
|
||||
role-description="passphrase"
|
||||
is-password="true"
|
||||
is-password
|
||||
:disabled="isLoading"
|
||||
@setData="setPassphrase"
|
||||
/>
|
||||
|
@ -65,125 +65,136 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||
|
||||
import PasswordHiddenIcon from '@/../static/images/common/passwordHidden.svg';
|
||||
import PasswordShownIcon from '@/../static/images/common/passwordShown.svg';
|
||||
import { computed, defineComponent, onBeforeMount, ref } from 'vue';
|
||||
|
||||
import ErrorIcon from '@/../static/images/register/ErrorInfo.svg';
|
||||
import PasswordShownIcon from '@/../static/images/common/passwordShown.svg';
|
||||
import PasswordHiddenIcon from '@/../static/images/common/passwordHidden.svg';
|
||||
|
||||
// @vue/component
|
||||
@Component({
|
||||
const textType = 'text';
|
||||
const passwordType = 'password';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'VInput',
|
||||
components: {
|
||||
ErrorIcon,
|
||||
PasswordHiddenIcon,
|
||||
PasswordShownIcon,
|
||||
ErrorIcon,
|
||||
},
|
||||
})
|
||||
// TODO: merge these two components to have one single source of truth.
|
||||
export default class VInput extends Vue {
|
||||
@Prop({ default: '' })
|
||||
private readonly additionalLabel: string;
|
||||
@Prop({ default: 0 })
|
||||
private readonly currentLimit: number;
|
||||
@Prop({ default: false })
|
||||
private readonly isOptional: boolean;
|
||||
@Prop({ default: false })
|
||||
private readonly isLimitShown: boolean;
|
||||
@Prop({ default: false })
|
||||
private readonly isMultiline: boolean;
|
||||
@Prop({ default: false })
|
||||
private readonly isLoading: boolean;
|
||||
@Prop({ default: '' })
|
||||
protected readonly initValue: string;
|
||||
@Prop({ default: '' })
|
||||
protected readonly label: string;
|
||||
@Prop({ default: 'default' })
|
||||
protected readonly placeholder: string;
|
||||
@Prop({ default: false })
|
||||
protected readonly isPassword: boolean;
|
||||
@Prop({ default: '48px' })
|
||||
protected readonly height: string;
|
||||
@Prop({ default: '100%' })
|
||||
protected readonly width: string;
|
||||
@Prop({ default: '' })
|
||||
protected readonly error: string;
|
||||
@Prop({ default: Number.MAX_SAFE_INTEGER })
|
||||
protected readonly maxSymbols: number;
|
||||
@Prop({ default: false })
|
||||
private readonly isWhite: boolean;
|
||||
@Prop({ default: false })
|
||||
private readonly withIcon: boolean;
|
||||
@Prop({ default: false })
|
||||
private readonly disabled: boolean;
|
||||
@Prop({ default: 'input-container' })
|
||||
private readonly roleDescription: boolean;
|
||||
props: {
|
||||
additionalLabel: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
currentLimit: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isOptional: Boolean,
|
||||
isLimitShown: Boolean,
|
||||
isMultiline: Boolean,
|
||||
isLoading: Boolean,
|
||||
initValue: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
isPassword: Boolean,
|
||||
height: {
|
||||
type: String,
|
||||
default: '48px',
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default: '100%',
|
||||
},
|
||||
error: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
maxSymbols: {
|
||||
type: Number,
|
||||
default: Number.MAX_SAFE_INTEGER,
|
||||
},
|
||||
isWhite: Boolean,
|
||||
withIcon: Boolean,
|
||||
disabled: Boolean,
|
||||
roleDescription: {
|
||||
type: String,
|
||||
default: 'input-container',
|
||||
},
|
||||
},
|
||||
emits: ['showPasswordStrength', 'hidePasswordStrength', 'setData'],
|
||||
setup(props, ctx) {
|
||||
const value = ref('');
|
||||
const isPasswordShown = ref(false);
|
||||
const type = ref(textType);
|
||||
|
||||
private readonly textType: string = 'text';
|
||||
private readonly passwordType: string = 'password';
|
||||
|
||||
private type: string = this.textType;
|
||||
private isPasswordShown = false;
|
||||
|
||||
public value: string;
|
||||
|
||||
public created() {
|
||||
this.type = this.isPassword ? this.passwordType : this.textType;
|
||||
this.value = this.initValue;
|
||||
}
|
||||
|
||||
public showPasswordStrength(): void {
|
||||
this.$emit('showPasswordStrength');
|
||||
}
|
||||
|
||||
public hidePasswordStrength(): void {
|
||||
this.$emit('hidePasswordStrength');
|
||||
}
|
||||
|
||||
/**
|
||||
* triggers on input.
|
||||
*/
|
||||
public onInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
this.value = target.value;
|
||||
|
||||
this.$emit('setData', this.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers input type between text and password to show/hide symbols.
|
||||
*/
|
||||
public changeVision(): void {
|
||||
this.isPasswordShown = !this.isPasswordShown;
|
||||
this.type = this.isPasswordShown ? this.textType : this.passwordType;
|
||||
}
|
||||
|
||||
public get isPasswordHiddenState(): boolean {
|
||||
return this.isPassword && !this.isPasswordShown;
|
||||
}
|
||||
|
||||
public get isPasswordShownState(): boolean {
|
||||
return this.isPassword && this.isPasswordShown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns style objects depends on props.
|
||||
*/
|
||||
protected get style(): Record<string, unknown> {
|
||||
onBeforeMount(() => {
|
||||
type.value = props.isPassword ? passwordType : textType;
|
||||
value.value = props.initValue;
|
||||
});
|
||||
return {
|
||||
inputStyle: {
|
||||
width: this.width,
|
||||
height: this.height,
|
||||
padding: this.withIcon ? '0 30px 0 50px' : '',
|
||||
isPasswordHiddenState: computed(() => {
|
||||
return props.isPassword && !isPasswordShown.value;
|
||||
}),
|
||||
isPasswordShownState: computed(() => {
|
||||
return props.isPassword && isPasswordShown.value;
|
||||
}),
|
||||
/**
|
||||
* Returns style objects depends on props.
|
||||
*/
|
||||
style: computed(() => {
|
||||
return {
|
||||
inputStyle: {
|
||||
width: props.width,
|
||||
height: props.height,
|
||||
padding: props.withIcon ? '0 30px 0 50px' : '',
|
||||
},
|
||||
labelStyle: {
|
||||
color: props.isWhite ? 'white' : '#354049',
|
||||
},
|
||||
errorStyle: {
|
||||
color: props.isWhite ? 'white' : '#FF5560',
|
||||
},
|
||||
};
|
||||
}),
|
||||
showPasswordStrength(): void {
|
||||
ctx.emit('showPasswordStrength');
|
||||
},
|
||||
labelStyle: {
|
||||
color: this.isWhite ? 'white' : '#354049',
|
||||
hidePasswordStrength(): void {
|
||||
ctx.emit('hidePasswordStrength');
|
||||
},
|
||||
errorStyle: {
|
||||
color: this.isWhite ? 'white' : '#FF5560',
|
||||
/**
|
||||
* triggers on input.
|
||||
*/
|
||||
onInput(event: Event): void {
|
||||
const target = event.target as HTMLInputElement;
|
||||
value.value = target.value;
|
||||
|
||||
ctx.emit('setData', value.value);
|
||||
},
|
||||
/**
|
||||
* Triggers input type between text and password to show/hide symbols.
|
||||
*/
|
||||
changeVision(): void {
|
||||
isPasswordShown.value = !isPasswordShown.value;
|
||||
type.value = isPasswordShown.value ? textType : passwordType;
|
||||
},
|
||||
value,
|
||||
isPasswordShown,
|
||||
type,
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -13,7 +13,7 @@
|
||||
class="full-input"
|
||||
label="Old Password"
|
||||
placeholder="Old Password"
|
||||
is-password="true"
|
||||
is-password
|
||||
:error="oldPasswordError"
|
||||
@setData="setOldPassword"
|
||||
/>
|
||||
@ -22,7 +22,7 @@
|
||||
class="full-input"
|
||||
label="New Password"
|
||||
placeholder="New Password"
|
||||
is-password="true"
|
||||
is-password
|
||||
:error="newPasswordError"
|
||||
@setData="setNewPassword"
|
||||
@showPasswordStrength="showPasswordStrength"
|
||||
@ -37,7 +37,7 @@
|
||||
class="full-input"
|
||||
label="Confirm Password"
|
||||
placeholder="Confirm Password"
|
||||
is-password="true"
|
||||
is-password
|
||||
:error="confirmationPasswordError"
|
||||
@setData="setPasswordConfirmation"
|
||||
/>
|
||||
|
@ -18,7 +18,7 @@
|
||||
additional-label="Up To 20 Characters"
|
||||
placeholder="Project Name"
|
||||
class="full-input"
|
||||
is-limit-shown="true"
|
||||
is-limit-shown
|
||||
:current-limit="projectName.length"
|
||||
:max-symbols="20"
|
||||
:error="nameError"
|
||||
@ -28,9 +28,9 @@
|
||||
label="Description - Optional"
|
||||
placeholder="Project Description"
|
||||
class="full-input"
|
||||
is-multiline="true"
|
||||
is-multiline
|
||||
height="100px"
|
||||
is-limit-shown="true"
|
||||
is-limit-shown
|
||||
:current-limit="description.length"
|
||||
:max-symbols="100"
|
||||
@setData="setProjectDescription"
|
||||
|
@ -15,14 +15,14 @@
|
||||
label="Bucket Name"
|
||||
:init-value="bucketName"
|
||||
role-description="bucket"
|
||||
disabled="true"
|
||||
:disabled="true"
|
||||
/>
|
||||
<VInput
|
||||
label="Encryption Passphrase"
|
||||
placeholder="Enter a passphrase here"
|
||||
:error="enterError"
|
||||
role-description="passphrase"
|
||||
is-password="true"
|
||||
is-password
|
||||
:disabled="isLoading"
|
||||
@setData="setPassphrase"
|
||||
/>
|
||||
@ -150,7 +150,7 @@ export default class OpenBucketModal extends Vue {
|
||||
|
||||
const salt = await this.$store.dispatch(PROJECTS_ACTIONS.GET_SALT, this.$store.getters.selectedProject.id);
|
||||
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||
|
||||
|
||||
this.worker.postMessage({
|
||||
'type': 'GenerateAccess',
|
||||
'apiKey': grantEvent.data.value,
|
||||
|
@ -72,7 +72,7 @@
|
||||
placeholder="Enter a passphrase here..."
|
||||
:error="enterError"
|
||||
role-description="passphrase"
|
||||
is-password="true"
|
||||
is-password
|
||||
:disabled="isLoading"
|
||||
@setData="setPassphrase"
|
||||
/>
|
||||
|
@ -17,7 +17,7 @@
|
||||
additional-label="Up To 20 Characters"
|
||||
placeholder="Enter Project Name"
|
||||
class="full-input"
|
||||
is-limit-shown="true"
|
||||
is-limit-shown
|
||||
:current-limit="projectName.length"
|
||||
:max-symbols="20"
|
||||
:error="nameError"
|
||||
@ -28,9 +28,9 @@
|
||||
placeholder="Enter Project Description"
|
||||
additional-label="Optional"
|
||||
class="full-input"
|
||||
is-multiline="true"
|
||||
is-multiline
|
||||
height="100px"
|
||||
is-limit-shown="true"
|
||||
is-limit-shown
|
||||
:current-limit="description.length"
|
||||
:max-symbols="100"
|
||||
@setData="setProjectDescription"
|
||||
|
@ -61,7 +61,7 @@
|
||||
role-description="passphrase"
|
||||
placeholder="Passphrase"
|
||||
:error="passphraseErr"
|
||||
is-password="true"
|
||||
is-password
|
||||
@setData="setPassphrase"
|
||||
/>
|
||||
</div>
|
||||
|
@ -75,7 +75,7 @@
|
||||
label="Password"
|
||||
placeholder="Password"
|
||||
:error="passwordError"
|
||||
is-password="true"
|
||||
is-password
|
||||
role-description="password"
|
||||
@setData="setPassword"
|
||||
/>
|
||||
|
@ -42,7 +42,7 @@
|
||||
label="Password"
|
||||
placeholder="Enter Password"
|
||||
:error="passwordError"
|
||||
is-password="true"
|
||||
is-password
|
||||
@setData="setPassword"
|
||||
@showPasswordStrength="showPasswordStrength"
|
||||
@hidePasswordStrength="hidePasswordStrength"
|
||||
@ -57,7 +57,7 @@
|
||||
label="Retype Password"
|
||||
placeholder="Retype Password"
|
||||
:error="repeatedPasswordError"
|
||||
is-password="true"
|
||||
is-password
|
||||
@setData="setRepeatedPassword"
|
||||
/>
|
||||
</div>
|
||||
|
@ -162,7 +162,7 @@
|
||||
label="Password"
|
||||
placeholder="Enter Password"
|
||||
:error="passwordError"
|
||||
is-password="true"
|
||||
is-password
|
||||
role-description="password"
|
||||
@setData="setPassword"
|
||||
@showPasswordStrength="showPasswordStrength"
|
||||
@ -179,7 +179,7 @@
|
||||
label="Retype Password"
|
||||
placeholder="Retype Password"
|
||||
:error="repeatedPasswordError"
|
||||
is-password="true"
|
||||
is-password
|
||||
role-description="retype-password"
|
||||
@setData="setRepeatedPassword"
|
||||
/>
|
||||
|
@ -1,22 +1,23 @@
|
||||
// Copyright (C) 2022 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
import { mount, shallowMount } from '@vue/test-utils';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
import VInput from '@/components/common/VInput.vue';
|
||||
|
||||
describe('VInput.vue', () => {
|
||||
it('renders correctly with default props', () => {
|
||||
|
||||
const wrapper = shallowMount(VInput);
|
||||
const wrapper = shallowMount(VInput as never);
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('renders correctly with isMultiline props', () => {
|
||||
|
||||
const wrapper = shallowMount(VInput, {
|
||||
propsData: { isMultiline: true },
|
||||
const wrapper = shallowMount(VInput as never, {
|
||||
propsData: {
|
||||
isMultiline: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
@ -30,8 +31,13 @@ describe('VInput.vue', () => {
|
||||
const width = '30px';
|
||||
const height = '20px';
|
||||
|
||||
const wrapper = shallowMount(VInput, {
|
||||
propsData: { label, width, height, additionalLabel },
|
||||
const wrapper = shallowMount(VInput as never, {
|
||||
propsData : {
|
||||
label,
|
||||
additionalLabel,
|
||||
width,
|
||||
height,
|
||||
},
|
||||
});
|
||||
|
||||
const el = wrapper.find('input').element as HTMLElement;
|
||||
@ -43,8 +49,7 @@ describe('VInput.vue', () => {
|
||||
});
|
||||
|
||||
it('renders correctly with isOptional props', () => {
|
||||
|
||||
const wrapper = shallowMount(VInput, {
|
||||
const wrapper = shallowMount(VInput as never, {
|
||||
propsData: {
|
||||
isOptional: true,
|
||||
},
|
||||
@ -56,7 +61,7 @@ describe('VInput.vue', () => {
|
||||
it('renders correctly with input error', () => {
|
||||
const error = 'testError';
|
||||
|
||||
const wrapper = shallowMount(VInput, {
|
||||
const wrapper = shallowMount(VInput as never, {
|
||||
propsData: {
|
||||
error,
|
||||
},
|
||||
@ -69,7 +74,7 @@ describe('VInput.vue', () => {
|
||||
it('emit setData on input correctly', async () => {
|
||||
const testData = 'testData';
|
||||
|
||||
const wrapper = mount(VInput);
|
||||
const wrapper = shallowMount(VInput as never);
|
||||
|
||||
await wrapper.find('input').trigger('input');
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user