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',
|
'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 }],
|
||||||
|
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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">
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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"
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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"
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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>
|
||||||
|
@ -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"
|
||||||
/>
|
/>
|
||||||
|
@ -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');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user