web/satellite: create passphrase step for objects page
WHAT: made a common component from AG's generate passphrase component to be reused here. create passphrase step for objects page WHY: used for generating passphrase or setting user's own password for proceeding in upload flow Change-Id: Iefa106c544a1c5ff04d591d3d400cf06c4c6d853
This commit is contained in:
parent
b5f83f463b
commit
9e20cfb6e0
@ -2,87 +2,30 @@
|
|||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="create-passphrase" :class="{ 'border-radius': isOnboardingTour }">
|
<div class="create-passphrase">
|
||||||
<BackIcon class="create-passphrase__back-icon" @click="onBackClick"/>
|
<BackIcon class="create-passphrase__back-icon" @click="onBackClick"/>
|
||||||
<h1 class="create-passphrase__title">Encryption Passphrase</h1>
|
<GeneratePassphrase
|
||||||
<div class="create-passphrase__warning">
|
:is-loading="isLoading"
|
||||||
<WarningIcon/>
|
:on-button-click="onNextClick"
|
||||||
<p class="create-passphrase__warning__label" v-if="isGenerateState">Save Your Encryption Passphrase</p>
|
:set-parent-passphrase="setPassphrase"
|
||||||
<p class="create-passphrase__warning__label" v-else>Remember This Passphrase</p>
|
|
||||||
</div>
|
|
||||||
<div class="create-passphrase__choosing">
|
|
||||||
<p class="create-passphrase__choosing__label">Choose Passphrase Type</p>
|
|
||||||
<div class="create-passphrase__choosing__right">
|
|
||||||
<p
|
|
||||||
class="create-passphrase__choosing__right__option left-option"
|
|
||||||
:class="{ active: isGenerateState }"
|
|
||||||
@click="onChooseGenerate"
|
|
||||||
>
|
|
||||||
Generate Phrase
|
|
||||||
</p>
|
|
||||||
<p
|
|
||||||
class="create-passphrase__choosing__right__option"
|
|
||||||
:class="{ active: isCreateState }"
|
|
||||||
@click="onChooseCreate"
|
|
||||||
>
|
|
||||||
Create Phrase
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="create-passphrase__value-area">
|
|
||||||
<div class="create-passphrase__value-area__mnemonic" v-if="isGenerateState">
|
|
||||||
<p class="create-passphrase__value-area__mnemonic__label">12-Word Mnemonic Passphrase:</p>
|
|
||||||
<div class="create-passphrase__value-area__mnemonic__container">
|
|
||||||
<p class="create-passphrase__value-area__mnemonic__container__value">{{ passphrase }}</p>
|
|
||||||
<VButton
|
|
||||||
class="create-passphrase__value-area__mnemonic__container__button"
|
|
||||||
label="Copy"
|
|
||||||
width="66px"
|
|
||||||
height="30px"
|
|
||||||
:on-press="onCopyClick"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="create-passphrase__value-area__password" v-else>
|
|
||||||
<HeaderedInput
|
|
||||||
class="create-passphrase__value-area__password__input"
|
|
||||||
label="Create Your Passphrase"
|
|
||||||
placeholder="Strong passphrases contain 12 characters or more"
|
|
||||||
@setData="onChangePassphrase"
|
|
||||||
:error="errorMessage"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<VButton
|
|
||||||
class="create-passphrase__next-button"
|
|
||||||
label="Next"
|
|
||||||
width="100%"
|
|
||||||
height="48px"
|
|
||||||
:on-press="onNextClick"
|
|
||||||
:is-disabled="isLoading"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import * as bip39 from 'bip39';
|
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
import GeneratePassphrase from '@/components/common/GeneratePassphrase.vue';
|
||||||
import VButton from '@/components/common/VButton.vue';
|
|
||||||
|
|
||||||
import BackIcon from '@/../static/images/accessGrants/back.svg';
|
import BackIcon from '@/../static/images/accessGrants/back.svg';
|
||||||
import WarningIcon from '@/../static/images/accessGrants/warning.svg';
|
|
||||||
|
|
||||||
import { RouteConfig } from '@/router';
|
import { RouteConfig } from '@/router';
|
||||||
import { MetaUtils } from '@/utils/meta';
|
import { MetaUtils } from '@/utils/meta';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
components: {
|
components: {
|
||||||
WarningIcon,
|
|
||||||
BackIcon,
|
BackIcon,
|
||||||
VButton,
|
GeneratePassphrase,
|
||||||
HeaderedInput,
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
export default class CreatePassphraseStep extends Vue {
|
export default class CreatePassphraseStep extends Vue {
|
||||||
@ -92,10 +35,7 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
private worker: Worker;
|
private worker: Worker;
|
||||||
private isLoading: boolean = true;
|
private isLoading: boolean = true;
|
||||||
|
|
||||||
public isGenerateState: boolean = true;
|
|
||||||
public isCreateState: boolean = false;
|
|
||||||
public passphrase: string = '';
|
public passphrase: string = '';
|
||||||
public errorMessage: string = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lifecycle hook after initial render.
|
* Lifecycle hook after initial render.
|
||||||
@ -110,24 +50,12 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
|
|
||||||
this.key = this.$route.params.key;
|
this.key = this.$route.params.key;
|
||||||
this.restrictedKey = this.$route.params.restrictedKey;
|
this.restrictedKey = this.$route.params.restrictedKey;
|
||||||
this.passphrase = bip39.generateMnemonic();
|
|
||||||
|
|
||||||
this.setWorker();
|
this.setWorker();
|
||||||
|
|
||||||
this.isLoading = false;
|
this.isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes state to generate passphrase.
|
|
||||||
*/
|
|
||||||
public onChooseGenerate(): void {
|
|
||||||
if (this.passphrase && this.isGenerateState) return;
|
|
||||||
|
|
||||||
this.passphrase = bip39.generateMnemonic();
|
|
||||||
this.isCreateState = false;
|
|
||||||
this.isGenerateState = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets local worker with worker instantiated in store.
|
* Sets local worker with worker instantiated in store.
|
||||||
* Also sets worker's onmessage and onerror logic.
|
* Also sets worker's onmessage and onerror logic.
|
||||||
@ -152,33 +80,10 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes state to create passphrase.
|
* Sets passphrase from child component.
|
||||||
*/
|
*/
|
||||||
public onChooseCreate(): void {
|
public setPassphrase(passphrase: string): void {
|
||||||
if (this.passphrase && this.isCreateState) return;
|
this.passphrase = passphrase;
|
||||||
|
|
||||||
this.errorMessage = '';
|
|
||||||
this.passphrase = '';
|
|
||||||
this.isCreateState = true;
|
|
||||||
this.isGenerateState = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds on copy button click logic.
|
|
||||||
* Copies passphrase to clipboard.
|
|
||||||
*/
|
|
||||||
public onCopyClick(): void {
|
|
||||||
this.$copyText(this.passphrase);
|
|
||||||
this.$notify.success('Passphrase was copied successfully');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes passphrase data from input value.
|
|
||||||
* @param value
|
|
||||||
*/
|
|
||||||
public onChangePassphrase(value: string): void {
|
|
||||||
this.passphrase = value.trim();
|
|
||||||
this.errorMessage = '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -186,15 +91,11 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
* Generates access grant and redirects to next step.
|
* Generates access grant and redirects to next step.
|
||||||
*/
|
*/
|
||||||
public onNextClick(): void {
|
public onNextClick(): void {
|
||||||
if (!this.passphrase) {
|
if (this.isLoading) return;
|
||||||
this.errorMessage = 'Passphrase can`t be empty';
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
|
|
||||||
const satelliteNodeURL = MetaUtils.getMetaContent('satellite-nodeurl');
|
const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl');
|
||||||
|
|
||||||
this.worker.postMessage({
|
this.worker.postMessage({
|
||||||
'type': 'GenerateAccess',
|
'type': 'GenerateAccess',
|
||||||
@ -259,7 +160,7 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
/**
|
/**
|
||||||
* Indicates if current route is onboarding tour.
|
* Indicates if current route is onboarding tour.
|
||||||
*/
|
*/
|
||||||
public get isOnboardingTour(): boolean {
|
private get isOnboardingTour(): boolean {
|
||||||
return this.$route.path.includes(RouteConfig.OnboardingTour.path);
|
return this.$route.path.includes(RouteConfig.OnboardingTour.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -267,18 +168,7 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.create-passphrase {
|
.create-passphrase {
|
||||||
height: calc(100% - 60px);
|
|
||||||
padding: 30px 65px;
|
|
||||||
max-width: 475px;
|
|
||||||
min-width: 475px;
|
|
||||||
font-family: 'font_regular', sans-serif;
|
|
||||||
font-style: normal;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 0 6px 6px 0;
|
|
||||||
|
|
||||||
&__back-icon {
|
&__back-icon {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -286,150 +176,5 @@ export default class CreatePassphraseStep extends Vue {
|
|||||||
left: 65px;
|
left: 65px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__title {
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 22px;
|
|
||||||
line-height: 27px;
|
|
||||||
color: #000;
|
|
||||||
margin: 0 0 30px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__warning {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20px;
|
|
||||||
width: calc(100% - 40px);
|
|
||||||
background: #fff9f7;
|
|
||||||
border: 1px solid #f84b00;
|
|
||||||
margin-bottom: 35px;
|
|
||||||
border-radius: 8px;
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
font-style: normal;
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 19px;
|
|
||||||
color: #1b2533;
|
|
||||||
margin: 0 0 0 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__choosing {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
font-size: 16px;
|
|
||||||
line-height: 21px;
|
|
||||||
color: #354049;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__right {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
&__option {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 17px;
|
|
||||||
color: #768394;
|
|
||||||
margin: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
border-bottom: 3px solid #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__value-area {
|
|
||||||
margin: 50px 0 60px 0;
|
|
||||||
min-height: 100px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
|
|
||||||
&__mnemonic {
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 19px;
|
|
||||||
color: #7c8794;
|
|
||||||
margin: 0 0 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__container {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
background: #f5f6fa;
|
|
||||||
border-radius: 9px;
|
|
||||||
padding: 10px;
|
|
||||||
width: calc(100% - 20px);
|
|
||||||
|
|
||||||
&__value {
|
|
||||||
font-family: 'Source Code Pro', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 25px;
|
|
||||||
color: #384b65;
|
|
||||||
word-break: break-word;
|
|
||||||
margin: 0;
|
|
||||||
word-spacing: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__button {
|
|
||||||
margin-left: 10px;
|
|
||||||
min-width: 66px;
|
|
||||||
min-height: 30px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__password {
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&__input {
|
|
||||||
width: calc(100% - 8px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-option {
|
|
||||||
margin-right: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.active {
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
color: #0068dc;
|
|
||||||
border-bottom: 3px solid #0068dc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.border-radius {
|
|
||||||
border-radius: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/deep/ .label-container {
|
|
||||||
|
|
||||||
&__main {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 19px;
|
|
||||||
color: #7c8794;
|
|
||||||
font-family: 'font_bold', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__error {
|
|
||||||
margin: 0 0 0 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 19px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
352
web/satellite/src/components/common/GeneratePassphrase.vue
Normal file
352
web/satellite/src/components/common/GeneratePassphrase.vue
Normal file
@ -0,0 +1,352 @@
|
|||||||
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="generate-container">
|
||||||
|
<h1 class="generate-container__title">Encryption Passphrase</h1>
|
||||||
|
<div class="generate-container__warning">
|
||||||
|
<div class="generate-container__warning__header">
|
||||||
|
<WarningIcon/>
|
||||||
|
<p class="generate-container__warning__header__label">Save Your Encryption Passphrase</p>
|
||||||
|
</div>
|
||||||
|
<p class="generate-container__warning__message">
|
||||||
|
You’ll need this passphrase to access data in the future. This is the only time it will be displayed.
|
||||||
|
Be sure to write it down.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="generate-container__choosing">
|
||||||
|
<p class="generate-container__choosing__label">Choose Passphrase Type</p>
|
||||||
|
<div class="generate-container__choosing__right">
|
||||||
|
<p
|
||||||
|
class="generate-container__choosing__right__option left-option"
|
||||||
|
:class="{ active: isGenerateState }"
|
||||||
|
@click="onChooseGenerate"
|
||||||
|
>
|
||||||
|
Generate Phrase
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
class="generate-container__choosing__right__option"
|
||||||
|
:class="{ active: isCreateState }"
|
||||||
|
@click="onChooseCreate"
|
||||||
|
>
|
||||||
|
Create Phrase
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="generate-container__value-area">
|
||||||
|
<div class="generate-container__value-area__mnemonic" v-if="isGenerateState">
|
||||||
|
<p class="generate-container__value-area__mnemonic__value">{{ passphrase }}</p>
|
||||||
|
<VButton
|
||||||
|
class="generate-container__value-area__mnemonic__button"
|
||||||
|
label="Copy"
|
||||||
|
width="66px"
|
||||||
|
height="30px"
|
||||||
|
:on-press="onCopyClick"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="generate-container__value-area__password" v-else>
|
||||||
|
<HeaderedInput
|
||||||
|
class="generate-container__value-area__password__input"
|
||||||
|
placeholder="Strong passphrases contain 12 characters or more"
|
||||||
|
@setData="onChangePassphrase"
|
||||||
|
:error="errorMessage"
|
||||||
|
label="Create Your Passphrase"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label class="generate-container__check-area" :class="{ error: isError }" for="pass-checkbox">
|
||||||
|
<input
|
||||||
|
class="generate-container__check-area__checkbox"
|
||||||
|
id="pass-checkbox"
|
||||||
|
type="checkbox"
|
||||||
|
v-model="isChecked"
|
||||||
|
@change="isError = false"
|
||||||
|
>
|
||||||
|
Yes, I wrote this down or saved it somewhere.
|
||||||
|
</label>
|
||||||
|
<VButton
|
||||||
|
class="generate-container__next-button"
|
||||||
|
label="Next"
|
||||||
|
width="100%"
|
||||||
|
height="48px"
|
||||||
|
:on-press="onProceed"
|
||||||
|
:is-disabled="isLoading"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import * as bip39 from 'bip39';
|
||||||
|
import { Component, Prop, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import HeaderedInput from '@/components/common/HeaderedInput.vue';
|
||||||
|
import VButton from '@/components/common/VButton.vue';
|
||||||
|
|
||||||
|
import BackIcon from '@/../static/images/accessGrants/back.svg';
|
||||||
|
import WarningIcon from '@/../static/images/accessGrants/warning.svg';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
WarningIcon,
|
||||||
|
BackIcon,
|
||||||
|
VButton,
|
||||||
|
HeaderedInput,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class GeneratePassphrase extends Vue {
|
||||||
|
@Prop({ default: () => null })
|
||||||
|
public readonly onButtonClick: () => void;
|
||||||
|
@Prop({ default: () => null })
|
||||||
|
public readonly setParentPassphrase: (passphrase: string) => void;
|
||||||
|
@Prop({ default: false })
|
||||||
|
public readonly isLoading: boolean;
|
||||||
|
|
||||||
|
public isGenerateState: boolean = true;
|
||||||
|
public isCreateState: boolean = false;
|
||||||
|
public isChecked: boolean = false;
|
||||||
|
public isError: boolean = false;
|
||||||
|
public passphrase: string = '';
|
||||||
|
public errorMessage: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lifecycle hook after initial render.
|
||||||
|
* Generates mnemonic string.
|
||||||
|
*/
|
||||||
|
public mounted(): void {
|
||||||
|
this.passphrase = bip39.generateMnemonic();
|
||||||
|
this.setParentPassphrase(this.passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
public onProceed(): void {
|
||||||
|
if (!this.passphrase) {
|
||||||
|
this.errorMessage = 'Passphrase can`t be empty';
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isChecked) {
|
||||||
|
this.isError = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onButtonClick();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes state to generate passphrase.
|
||||||
|
*/
|
||||||
|
public onChooseGenerate(): void {
|
||||||
|
if (this.passphrase && this.isGenerateState) return;
|
||||||
|
|
||||||
|
this.passphrase = bip39.generateMnemonic();
|
||||||
|
this.setParentPassphrase(this.passphrase);
|
||||||
|
|
||||||
|
this.isCreateState = false;
|
||||||
|
this.isGenerateState = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes state to create passphrase.
|
||||||
|
*/
|
||||||
|
public onChooseCreate(): void {
|
||||||
|
if (this.passphrase && this.isCreateState) return;
|
||||||
|
|
||||||
|
this.errorMessage = '';
|
||||||
|
this.passphrase = '';
|
||||||
|
this.setParentPassphrase(this.passphrase);
|
||||||
|
|
||||||
|
this.isCreateState = true;
|
||||||
|
this.isGenerateState = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds on copy button click logic.
|
||||||
|
* Copies passphrase to clipboard.
|
||||||
|
*/
|
||||||
|
public onCopyClick(): void {
|
||||||
|
this.$copyText(this.passphrase);
|
||||||
|
this.$notify.success('Passphrase was copied successfully');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes passphrase data from input value.
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public onChangePassphrase(value: string): void {
|
||||||
|
this.passphrase = value.trim();
|
||||||
|
this.setParentPassphrase(this.passphrase);
|
||||||
|
this.errorMessage = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.generate-container {
|
||||||
|
padding: 25px 50px;
|
||||||
|
max-width: 515px;
|
||||||
|
min-width: 515px;
|
||||||
|
font-family: 'font_regular', sans-serif;
|
||||||
|
font-style: normal;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 22px;
|
||||||
|
line-height: 27px;
|
||||||
|
color: #000;
|
||||||
|
margin: 0 0 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__warning {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 20px;
|
||||||
|
width: calc(100% - 40px);
|
||||||
|
background: #fff9f7;
|
||||||
|
border: 1px solid #f84b00;
|
||||||
|
margin-bottom: 35px;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-style: normal;
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 19px;
|
||||||
|
color: #1b2533;
|
||||||
|
margin: 0 0 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__message {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 19px;
|
||||||
|
color: #1b2533;
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__choosing {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 21px;
|
||||||
|
color: #354049;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__right {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__option {
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 17px;
|
||||||
|
color: #768394;
|
||||||
|
margin: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
border-bottom: 3px solid #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value-area {
|
||||||
|
margin: 32px 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
&__mnemonic {
|
||||||
|
display: flex;
|
||||||
|
background: #f5f6fa;
|
||||||
|
border-radius: 9px;
|
||||||
|
padding: 10px;
|
||||||
|
width: calc(100% - 20px);
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-family: 'Source Code Pro', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 25px;
|
||||||
|
color: #384b65;
|
||||||
|
word-break: break-word;
|
||||||
|
margin: 0;
|
||||||
|
word-spacing: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__button {
|
||||||
|
margin-left: 10px;
|
||||||
|
min-width: 66px;
|
||||||
|
min-height: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__password {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&__input {
|
||||||
|
width: calc(100% - 8px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__check-area {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 19px;
|
||||||
|
color: #1b2533;
|
||||||
|
|
||||||
|
&__checkbox {
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left-option {
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
color: #0068dc;
|
||||||
|
border-bottom: 3px solid #0068dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ .label-container {
|
||||||
|
|
||||||
|
&__main {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 19px;
|
||||||
|
color: #7c8794;
|
||||||
|
font-family: 'font_bold', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__error {
|
||||||
|
margin: 0 0 0 10px;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 19px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,9 +1,51 @@
|
|||||||
// Copyright (C) 2021 Storj Labs, Inc.
|
// Copyright (C) 2021 Storj Labs, Inc.
|
||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="create-pass">
|
||||||
|
<GeneratePassphrase
|
||||||
|
:is-loading="isLoading"
|
||||||
|
:on-button-click="onNextClick"
|
||||||
|
:set-parent-passphrase="setPassphrase"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
@Component
|
import GeneratePassphrase from '@/components/common/GeneratePassphrase.vue';
|
||||||
export default class CreatePassphrase extends Vue {}
|
|
||||||
|
@Component({
|
||||||
|
components: {
|
||||||
|
GeneratePassphrase,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
export default class CreatePassphrase extends Vue {
|
||||||
|
private isLoading: boolean = false;
|
||||||
|
|
||||||
|
public passphrase: string = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets passphrase from child component.
|
||||||
|
*/
|
||||||
|
public setPassphrase(passphrase: string): void {
|
||||||
|
this.passphrase = passphrase;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds on next button click logic.
|
||||||
|
*/
|
||||||
|
public onNextClick(): void {
|
||||||
|
if (this.isLoading) return;
|
||||||
|
|
||||||
|
this.isLoading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.create-pass {
|
||||||
|
margin-top: 150px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="objects-area">
|
<div class="objects-area">
|
||||||
<div class="objects-area__header">
|
<div class="objects-area__header">
|
||||||
<h1 class="objects-area__header__title">File</h1>
|
<h1 class="objects-area__header__title">Objects</h1>
|
||||||
</div>
|
</div>
|
||||||
<router-view/>
|
<router-view/>
|
||||||
</div>
|
</div>
|
||||||
@ -13,18 +13,32 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Vue } from 'vue-property-decorator';
|
import { Component, Vue } from 'vue-property-decorator';
|
||||||
|
|
||||||
|
import { RouteConfig } from '@/router';
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class ObjectsArea extends Vue {}
|
export default class ObjectsArea extends Vue {
|
||||||
|
/**
|
||||||
|
* Lifecycle hook after initial render.
|
||||||
|
* Chooses correct route.
|
||||||
|
*/
|
||||||
|
public mounted(): void {
|
||||||
|
this.$router.push(RouteConfig.Objects.with(RouteConfig.CreatePassphrase).path);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.objects-area {
|
.objects-area {
|
||||||
padding: 20px 45px;
|
padding: 20px 45px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
&__header {
|
&__header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
&__title {
|
&__title {
|
||||||
font-family: 'font_medium', sans-serif;
|
font-family: 'font_medium', sans-serif;
|
||||||
@ -32,7 +46,7 @@ export default class ObjectsArea extends Vue {}
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
color: #232B34;
|
color: #232b34;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user