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:
Wilfred Asomani 2022-09-30 20:52:21 +00:00 committed by Storj Robot
parent b23b3e02e6
commit fac638fc7d
15 changed files with 155 additions and 140 deletions

View File

@ -64,7 +64,6 @@ module.exports = {
], ],
'newlines-between': 'always', 'newlines-between': 'always',
}], }],
'no-duplicate-imports': 'error', 'no-duplicate-imports': 'error',
'object-curly-spacing': ['error', 'always'], 'object-curly-spacing': ['error', 'always'],
'quotes': ['error', 'single', { 'allowTemplateLiterals': true }], 'quotes': ['error', 'single', { 'allowTemplateLiterals': true }],

View File

@ -15,7 +15,7 @@
:label="inputLabel" :label="inputLabel"
placeholder="Enter Coupon Code" placeholder="Enter Coupon Code"
height="52px" height="52px"
:with-icon="true" with-icon
@setData="setCouponCode" @setData="setCouponCode"
/> />
<CheckIcon <CheckIcon

View File

@ -10,7 +10,7 @@
<VInput <VInput
placeholder="Enter Coupon Code" placeholder="Enter Coupon Code"
height="52px" height="52px"
:with-icon="false" with-icon
@setData="setCouponCode" @setData="setCouponCode"
/> />
</div> </div>

View File

@ -53,7 +53,7 @@
placeholder="Enter a passphrase here..." placeholder="Enter a passphrase here..."
:error="enterError" :error="enterError"
role-description="passphrase" role-description="passphrase"
is-password="true" is-password
:disabled="isLoading" :disabled="isLoading"
@setData="setPassphrase" @setData="setPassphrase"
/> />

View File

@ -65,125 +65,136 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import PasswordHiddenIcon from '@/../static/images/common/passwordHidden.svg'; import { computed, defineComponent, onBeforeMount, ref } from 'vue';
import PasswordShownIcon from '@/../static/images/common/passwordShown.svg';
import ErrorIcon from '@/../static/images/register/ErrorInfo.svg'; 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 const textType = 'text';
@Component({ const passwordType = 'password';
export default defineComponent({
name: 'VInput',
components: { components: {
ErrorIcon,
PasswordHiddenIcon, PasswordHiddenIcon,
PasswordShownIcon, PasswordShownIcon,
ErrorIcon,
}, },
}) props: {
// TODO: merge these two components to have one single source of truth. additionalLabel: {
export default class VInput extends Vue { type: String,
@Prop({ default: '' }) default: '',
private readonly additionalLabel: string; },
@Prop({ default: 0 }) currentLimit: {
private readonly currentLimit: number; type: Number,
@Prop({ default: false }) default: 0,
private readonly isOptional: boolean; },
@Prop({ default: false }) isOptional: Boolean,
private readonly isLimitShown: boolean; isLimitShown: Boolean,
@Prop({ default: false }) isMultiline: Boolean,
private readonly isMultiline: boolean; isLoading: Boolean,
@Prop({ default: false }) initValue: {
private readonly isLoading: boolean; type: String,
@Prop({ default: '' }) default: '',
protected readonly initValue: string; },
@Prop({ default: '' }) label: {
protected readonly label: string; type: String,
@Prop({ default: 'default' }) default: '',
protected readonly placeholder: string; },
@Prop({ default: false }) placeholder: {
protected readonly isPassword: boolean; type: String,
@Prop({ default: '48px' }) default: 'default',
protected readonly height: string; },
@Prop({ default: '100%' }) isPassword: Boolean,
protected readonly width: string; height: {
@Prop({ default: '' }) type: String,
protected readonly error: string; default: '48px',
@Prop({ default: Number.MAX_SAFE_INTEGER }) },
protected readonly maxSymbols: number; width: {
@Prop({ default: false }) type: String,
private readonly isWhite: boolean; default: '100%',
@Prop({ default: false }) },
private readonly withIcon: boolean; error: {
@Prop({ default: false }) type: String,
private readonly disabled: boolean; default: '',
@Prop({ default: 'input-container' }) },
private readonly roleDescription: boolean; maxSymbols: {
type: Number,
private readonly textType: string = 'text'; default: Number.MAX_SAFE_INTEGER,
private readonly passwordType: string = 'password'; },
isWhite: Boolean,
private type: string = this.textType; withIcon: Boolean,
private isPasswordShown = false; disabled: Boolean,
roleDescription: {
public value: string; type: String,
default: 'input-container',
public created() { },
this.type = this.isPassword ? this.passwordType : this.textType; },
this.value = this.initValue; emits: ['showPasswordStrength', 'hidePasswordStrength', 'setData'],
} setup(props, ctx) {
const value = ref('');
public showPasswordStrength(): void { const isPasswordShown = ref(false);
this.$emit('showPasswordStrength'); const type = ref(textType);
}
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;
}
onBeforeMount(() => {
type.value = props.isPassword ? passwordType : textType;
value.value = props.initValue;
});
return {
isPasswordHiddenState: computed(() => {
return props.isPassword && !isPasswordShown.value;
}),
isPasswordShownState: computed(() => {
return props.isPassword && isPasswordShown.value;
}),
/** /**
* Returns style objects depends on props. * Returns style objects depends on props.
*/ */
protected get style(): Record<string, unknown> { style: computed(() => {
return { return {
inputStyle: { inputStyle: {
width: this.width, width: props.width,
height: this.height, height: props.height,
padding: this.withIcon ? '0 30px 0 50px' : '', padding: props.withIcon ? '0 30px 0 50px' : '',
}, },
labelStyle: { labelStyle: {
color: this.isWhite ? 'white' : '#354049', color: props.isWhite ? 'white' : '#354049',
}, },
errorStyle: { errorStyle: {
color: this.isWhite ? 'white' : '#FF5560', color: props.isWhite ? 'white' : '#FF5560',
}, },
}; };
} }),
} showPasswordStrength(): void {
ctx.emit('showPasswordStrength');
},
hidePasswordStrength(): void {
ctx.emit('hidePasswordStrength');
},
/**
* 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> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@ -13,7 +13,7 @@
class="full-input" class="full-input"
label="Old Password" label="Old Password"
placeholder="Old Password" placeholder="Old Password"
is-password="true" is-password
:error="oldPasswordError" :error="oldPasswordError"
@setData="setOldPassword" @setData="setOldPassword"
/> />
@ -22,7 +22,7 @@
class="full-input" class="full-input"
label="New Password" label="New Password"
placeholder="New Password" placeholder="New Password"
is-password="true" is-password
:error="newPasswordError" :error="newPasswordError"
@setData="setNewPassword" @setData="setNewPassword"
@showPasswordStrength="showPasswordStrength" @showPasswordStrength="showPasswordStrength"
@ -37,7 +37,7 @@
class="full-input" class="full-input"
label="Confirm Password" label="Confirm Password"
placeholder="Confirm Password" placeholder="Confirm Password"
is-password="true" is-password
:error="confirmationPasswordError" :error="confirmationPasswordError"
@setData="setPasswordConfirmation" @setData="setPasswordConfirmation"
/> />

View File

@ -18,7 +18,7 @@
additional-label="Up To 20 Characters" additional-label="Up To 20 Characters"
placeholder="Project Name" placeholder="Project Name"
class="full-input" class="full-input"
is-limit-shown="true" is-limit-shown
:current-limit="projectName.length" :current-limit="projectName.length"
:max-symbols="20" :max-symbols="20"
:error="nameError" :error="nameError"
@ -28,9 +28,9 @@
label="Description - Optional" label="Description - Optional"
placeholder="Project Description" placeholder="Project Description"
class="full-input" class="full-input"
is-multiline="true" is-multiline
height="100px" height="100px"
is-limit-shown="true" is-limit-shown
:current-limit="description.length" :current-limit="description.length"
:max-symbols="100" :max-symbols="100"
@setData="setProjectDescription" @setData="setProjectDescription"

View File

@ -15,14 +15,14 @@
label="Bucket Name" label="Bucket Name"
:init-value="bucketName" :init-value="bucketName"
role-description="bucket" role-description="bucket"
disabled="true" :disabled="true"
/> />
<VInput <VInput
label="Encryption Passphrase" label="Encryption Passphrase"
placeholder="Enter a passphrase here" placeholder="Enter a passphrase here"
:error="enterError" :error="enterError"
role-description="passphrase" role-description="passphrase"
is-password="true" is-password
:disabled="isLoading" :disabled="isLoading"
@setData="setPassphrase" @setData="setPassphrase"
/> />

View File

@ -72,7 +72,7 @@
placeholder="Enter a passphrase here..." placeholder="Enter a passphrase here..."
:error="enterError" :error="enterError"
role-description="passphrase" role-description="passphrase"
is-password="true" is-password
:disabled="isLoading" :disabled="isLoading"
@setData="setPassphrase" @setData="setPassphrase"
/> />

View File

@ -17,7 +17,7 @@
additional-label="Up To 20 Characters" additional-label="Up To 20 Characters"
placeholder="Enter Project Name" placeholder="Enter Project Name"
class="full-input" class="full-input"
is-limit-shown="true" is-limit-shown
:current-limit="projectName.length" :current-limit="projectName.length"
:max-symbols="20" :max-symbols="20"
:error="nameError" :error="nameError"
@ -28,9 +28,9 @@
placeholder="Enter Project Description" placeholder="Enter Project Description"
additional-label="Optional" additional-label="Optional"
class="full-input" class="full-input"
is-multiline="true" is-multiline
height="100px" height="100px"
is-limit-shown="true" is-limit-shown
:current-limit="description.length" :current-limit="description.length"
:max-symbols="100" :max-symbols="100"
@setData="setProjectDescription" @setData="setProjectDescription"

View File

@ -61,7 +61,7 @@
role-description="passphrase" role-description="passphrase"
placeholder="Passphrase" placeholder="Passphrase"
:error="passphraseErr" :error="passphraseErr"
is-password="true" is-password
@setData="setPassphrase" @setData="setPassphrase"
/> />
</div> </div>

View File

@ -75,7 +75,7 @@
label="Password" label="Password"
placeholder="Password" placeholder="Password"
:error="passwordError" :error="passwordError"
is-password="true" is-password
role-description="password" role-description="password"
@setData="setPassword" @setData="setPassword"
/> />

View File

@ -42,7 +42,7 @@
label="Password" label="Password"
placeholder="Enter Password" placeholder="Enter Password"
:error="passwordError" :error="passwordError"
is-password="true" is-password
@setData="setPassword" @setData="setPassword"
@showPasswordStrength="showPasswordStrength" @showPasswordStrength="showPasswordStrength"
@hidePasswordStrength="hidePasswordStrength" @hidePasswordStrength="hidePasswordStrength"
@ -57,7 +57,7 @@
label="Retype Password" label="Retype Password"
placeholder="Retype Password" placeholder="Retype Password"
:error="repeatedPasswordError" :error="repeatedPasswordError"
is-password="true" is-password
@setData="setRepeatedPassword" @setData="setRepeatedPassword"
/> />
</div> </div>

View File

@ -162,7 +162,7 @@
label="Password" label="Password"
placeholder="Enter Password" placeholder="Enter Password"
:error="passwordError" :error="passwordError"
is-password="true" is-password
role-description="password" role-description="password"
@setData="setPassword" @setData="setPassword"
@showPasswordStrength="showPasswordStrength" @showPasswordStrength="showPasswordStrength"
@ -179,7 +179,7 @@
label="Retype Password" label="Retype Password"
placeholder="Retype Password" placeholder="Retype Password"
:error="repeatedPasswordError" :error="repeatedPasswordError"
is-password="true" is-password
role-description="retype-password" role-description="retype-password"
@setData="setRepeatedPassword" @setData="setRepeatedPassword"
/> />

View File

@ -1,22 +1,23 @@
// Copyright (C) 2022 Storj Labs, Inc. // Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information. // 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'; import VInput from '@/components/common/VInput.vue';
describe('VInput.vue', () => { describe('VInput.vue', () => {
it('renders correctly with default props', () => { it('renders correctly with default props', () => {
const wrapper = shallowMount(VInput); const wrapper = shallowMount(VInput as never);
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
it('renders correctly with isMultiline props', () => { it('renders correctly with isMultiline props', () => {
const wrapper = shallowMount(VInput as never, {
const wrapper = shallowMount(VInput, { propsData: {
propsData: { isMultiline: true }, isMultiline: true,
},
}); });
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
@ -30,8 +31,13 @@ describe('VInput.vue', () => {
const width = '30px'; const width = '30px';
const height = '20px'; const height = '20px';
const wrapper = shallowMount(VInput, { const wrapper = shallowMount(VInput as never, {
propsData: { label, width, height, additionalLabel }, propsData : {
label,
additionalLabel,
width,
height,
},
}); });
const el = wrapper.find('input').element as HTMLElement; const el = wrapper.find('input').element as HTMLElement;
@ -43,8 +49,7 @@ describe('VInput.vue', () => {
}); });
it('renders correctly with isOptional props', () => { it('renders correctly with isOptional props', () => {
const wrapper = shallowMount(VInput as never, {
const wrapper = shallowMount(VInput, {
propsData: { propsData: {
isOptional: true, isOptional: true,
}, },
@ -56,7 +61,7 @@ describe('VInput.vue', () => {
it('renders correctly with input error', () => { it('renders correctly with input error', () => {
const error = 'testError'; const error = 'testError';
const wrapper = shallowMount(VInput, { const wrapper = shallowMount(VInput as never, {
propsData: { propsData: {
error, error,
}, },
@ -69,7 +74,7 @@ describe('VInput.vue', () => {
it('emit setData on input correctly', async () => { it('emit setData on input correctly', async () => {
const testData = 'testData'; const testData = 'testData';
const wrapper = mount(VInput); const wrapper = shallowMount(VInput as never);
await wrapper.find('input').trigger('input'); await wrapper.find('input').trigger('input');