web/satellite: reworked Encrypt your data component

Reworked component to have all needed warnings and info.
Removed Warning route from objects flow.
Updated tests.

Change-Id: Iced68aca7fbf4e1f7b7e5302147a51fd0e9115c8
This commit is contained in:
Vitalii Shpital 2021-11-01 18:59:40 +02:00
parent 4a530ccffd
commit 98b59fe305
14 changed files with 396 additions and 346 deletions

View File

@ -73,8 +73,8 @@ func TestNavigation(t *testing.T) {
// project dashboard route
page.MustElementR("p", "Objects").MustClick()
waitVueTick(page)
objectsTitle := page.MustElement("[aria-roledescription=title]").MustText()
require.Contains(t, objectsTitle, "Object Browser")
objectsTitle := page.MustElement("[aria-roledescription=enc-title]").MustText()
require.Contains(t, objectsTitle, "Encryption passphrase")
// access grants route
page.MustElementR("p", "Access").MustClick()
@ -124,8 +124,8 @@ func TestNavigation(t *testing.T) {
page.MustElementR("p", "Quick Start").MustClick()
page.MustElement("[aria-roledescription=objects-route]").MustClick()
waitVueTick(page)
objectsTitle1 := page.MustElement("[aria-roledescription=title]").MustText()
require.Contains(t, objectsTitle1, "Object Browser")
objectsTitle1 := page.MustElement("[aria-roledescription=enc-title]").MustText()
require.Contains(t, objectsTitle1, "Encryption passphrase")
// onboarding cli flow route
page.MustElementR("p", "Quick Start").MustClick()

View File

@ -47,20 +47,20 @@ func TestOnboardingWizardBrowser(t *testing.T) {
page.MustElementX("(//span[text()=\"Continue in web\"])").MustClick()
waitVueTick(page)
objectBrowserWarning := page.MustElement("[aria-roledescription=sub-title]").MustText()
objectBrowserWarning := page.MustElement("[aria-roledescription=objects-title]").MustText()
require.Contains(t, objectBrowserWarning, "The object browser uses server side encryption.")
page.MustElementX("(//span[text()=\"Continue\"])").MustClick()
waitVueTick(page)
encryptionPassphraseWarningTitle := page.MustElement("[aria-roledescription=warning-title]").MustText()
require.Contains(t, encryptionPassphraseWarningTitle, "The object browser uses server side encryption.")
require.Contains(t, encryptionPassphraseWarningTitle, "Save your encryption passphrase")
customPassphrase := page.MustElement("[aria-roledescription=enter-passphrase-label]")
customPassphraseLabel := customPassphrase.MustText()
require.Contains(t, customPassphraseLabel, "Enter Your Own Passphrase")
require.Contains(t, customPassphraseLabel, "Enter your own passphrase")
customPassphrase.MustClick()
waitVueTick(page)
page.MustElement("[aria-roledescription=passphrase] input").MustInput("password123")
page.MustElement(".checkmark").MustClick()
waitVueTick(page)
page.MustElementX("(//span[text()=\"Next >\"])").MustClick()
waitVueTick(page)

View File

@ -84,7 +84,7 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import * as bip39 from "bip39";
import { generateMnemonic } from "bip39";
import { RouteConfig } from '@/router';
import { MetaUtils } from '@/utils/meta';
@ -144,7 +144,7 @@ export default class CreatePassphraseStep extends Vue {
this.setWorker();
this.passphrase = bip39.generateMnemonic();
this.passphrase = generateMnemonic();
this.isLoading = false;
}
@ -241,7 +241,7 @@ export default class CreatePassphraseStep extends Vue {
public onChooseGenerate(): void {
if (this.passphrase && this.isGenerateState) return;
this.passphrase = bip39.generateMnemonic();
this.passphrase = generateMnemonic();
this.isEnterState = false;
this.isGenerateState = true;

View File

@ -4,25 +4,30 @@
<template>
<div class="encrypt-container">
<EncryptIcon />
<h1 class="encrypt-container__title">Encrypt your data</h1>
<h1 class="encrypt-container__title" aria-roledescription="enc-title">Encryption passphrase</h1>
<p class="encrypt-container__info">
The encryption passphrase is used to encrypt and access the data that you upload to Storj. We strongly
encourage you to use a mnemonic phrase, which is automatically generated on the client-side for you.
The encryption passphrase is used to encrypt and access the data that you upload to Storj.
</p>
<div class="encrypt-container__header">
<p class="encrypt-container__header__rec">RECOMMENDED</p>
<div class="encrypt-container__header__row">
<p class="encrypt-container__header__row__gen" :class="{ active: isGenerate }" @click="setToGenerate">Generate Phrase</p>
<div class="encrypt-container__header__row__right">
<p class="encrypt-container__header__row__right__enter" :class="{ active: !isGenerate }" aria-roledescription="enter-passphrase-label" @click="setToEnter">
Enter Your Own Passphrase
<div class="encrypt-container__functional">
<div class="encrypt-container__functional__header">
<p class="encrypt-container__functional__header__gen" :class="{ active: isGenerate }" @click="setToGenerate">
Generate a new passphrase
</p>
<div class="encrypt-container__functional__header__right" :class="{ active: !isGenerate }">
<p
class="encrypt-container__functional__header__right__enter"
:class="{ active: !isGenerate }"
aria-roledescription="enter-passphrase-label"
@click="setToEnter"
>
Enter your own passphrase
</p>
<VInfo class="encrypt-container__header__row__right__info-button">
<VInfo class="encrypt-container__functional__header__right__info-button">
<template #icon>
<InfoIcon class="encrypt-container__header__row__right__info-button__image" />
<InfoIcon class="encrypt-container__functional__header__right__info-button__image" :class="{ active: !isGenerate }" />
</template>
<template #message>
<p class="encrypt-container__header__row__right__info-button__message">
<p class="encrypt-container__functional__header__right__info-button__message">
We strongly encourage you to use a mnemonic phrase, which is automatically generated on
the client-side for you. Alternatively, you can enter your own passphrase.
</p>
@ -30,32 +35,42 @@
</VInfo>
</div>
</div>
</div>
<div v-if="isGenerate" class="encrypt-container__generate">
<p class="encrypt-container__generate__value">{{ passphrase }}</p>
<VButton
class="encrypt-container__generate__button"
label="Copy"
width="66px"
height="30px"
is-blue-white="true"
:on-press="onCopyClick"
/>
</div>
<div v-else class="encrypt-container__enter">
<HeaderlessInput
placeholder="Enter a passphrase here..."
:error="enterError"
role-description="passphrase"
@setData="setPassphrase"
/>
</div>
<p class="encrypt-container__download" @click="onDownloadClick">Download as a text file</p>
<div class="encrypt-container__warning">
<h2 class="encrypt-container__warning__title" aria-roledescription="warning-title">The object browser uses server side encryption.</h2>
<p class="encrypt-container__warning__msg">
If you want to use our product with only end-to-end encryption, you may want to use our command line solution.
<div v-if="isGenerate" class="encrypt-container__functional__generate">
<p class="encrypt-container__functional__generate__value">{{ passphrase }}</p>
<VButton
class="encrypt-container__functional__generate__button"
label="Copy"
width="66px"
height="30px"
is-blue-white="true"
is-uppercase="true"
:on-press="onCopyClick"
/>
</div>
<div v-else class="encrypt-container__functional__enter">
<HeaderlessInput
label="Your Passphrase"
placeholder="Enter a passphrase here..."
:error="enterError"
role-description="passphrase"
is-password="true"
@setData="setPassphrase"
/>
</div>
<h2 class="encrypt-container__functional__warning-title" aria-roledescription="warning-title">
Save your encryption passphrase
</h2>
<p class="encrypt-container__functional__warning-msg">
Please note that Storj does not know or store your encryption passphrase. If you lose it, you will not
be able to recover your files.
</p>
<p class="encrypt-container__functional__download" @click="onDownloadClick">Download as a text file</p>
<VCheckbox
class="encrypt-container__functional__checkbox"
label="I understand, and I have saved the passphrase."
:is-checkbox-error="isCheckboxError"
@setData="setSavingConfirmation"
/>
</div>
<div class="encrypt-container__buttons">
<VButton
@ -63,7 +78,7 @@
height="64px"
border-radius="62px"
:on-press="onNextButtonClick"
:is-disabled="isLoading"
:is-disabled="isLoading || !isSavingConfirmed"
/>
</div>
</div>
@ -71,7 +86,7 @@
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import * as bip39 from "bip39";
import { generateMnemonic } from "bip39";
import { LocalData, UserIDPassSalt } from "@/utils/localData";
import { Download } from "@/utils/download";
@ -79,9 +94,10 @@ import { Download } from "@/utils/download";
import VButton from '@/components/common/VButton.vue';
import VInfo from "@/components/common/VInfo.vue";
import HeaderlessInput from "@/components/common/HeaderlessInput.vue";
import VCheckbox from "@/components/common/VCheckbox.vue";
import EncryptIcon from "@/../static/images/objects/encrypt.svg";
import InfoIcon from "@/../static/images/common/greyInfo.svg";
import InfoIcon from "@/../static/images/common/smallGreyInfo.svg";
// @vue/component
@Component({
@ -91,6 +107,7 @@ import InfoIcon from "@/../static/images/common/greyInfo.svg";
VInfo,
VButton,
HeaderlessInput,
VCheckbox,
},
})
export default class GeneratePassphrase extends Vue {
@ -104,6 +121,8 @@ export default class GeneratePassphrase extends Vue {
public isGenerate = true;
public enterError = '';
public passphrase = '';
public isSavingConfirmed = false;
public isCheckboxError = false;
/**
* Lifecycle hook after initial render.
@ -117,10 +136,14 @@ export default class GeneratePassphrase extends Vue {
return;
}
this.passphrase = bip39.generateMnemonic();
this.passphrase = generateMnemonic();
this.setParentPassphrase(this.passphrase);
}
public setSavingConfirmation(value: boolean): void {
this.isSavingConfirmed = value;
}
/**
* Holds on copy button click logic.
* Copies passphrase to clipboard.
@ -171,7 +194,7 @@ export default class GeneratePassphrase extends Vue {
public setToGenerate(): void {
if (this.enterError) this.enterError = '';
this.passphrase = bip39.generateMnemonic();
this.passphrase = generateMnemonic();
this.setParentPassphrase(this.passphrase);
this.isGenerate = true;
}
@ -186,6 +209,12 @@ export default class GeneratePassphrase extends Vue {
return;
}
if (!this.isSavingConfirmed) {
this.isCheckboxError = true;
return;
}
await this.onNextClick();
}
}
@ -194,12 +223,15 @@ export default class GeneratePassphrase extends Vue {
<style scoped lang="scss">
.encrypt-container {
font-family: 'font_regular', sans-serif;
padding: 60px;
padding: 40px 60px 60px 60px;
max-width: 500px;
background: #fcfcfc;
box-shadow: 0 0 32px rgba(0, 0, 0, 0.04);
border-radius: 20px;
margin: 30px auto 0 auto;
display: flex;
flex-direction: column;
align-items: center;
&__title {
font-family: 'font_bold', sans-serif;
@ -207,55 +239,57 @@ export default class GeneratePassphrase extends Vue {
line-height: 56px;
letter-spacing: 1px;
color: #14142b;
margin: 35px 0 10px 0;
margin: 10px 0;
}
&__info {
font-size: 16px;
line-height: 32px;
line-height: 28px;
letter-spacing: 0.75px;
color: #1b2533;
margin-bottom: 20px;
text-align: center;
max-width: 420px;
}
&__header {
&__functional {
border: 1px solid #e6e9ef;
border-radius: 10px;
padding: 20px 0;
&__rec {
font-size: 12px;
line-height: 15px;
color: #1b2533;
opacity: 0.4;
margin-bottom: 15px;
}
&__row {
&__header {
width: calc(100% - 50px);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 25px;
border-bottom: 1px solid #e6e9ef;
&__gen {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
font-family: 'font_medium', sans-serif;
font-size: 14px;
line-height: 17px;
color: #a9b5c1;
padding-bottom: 10px;
border-bottom: 5px solid #fff;
padding-bottom: 20px;
border-bottom: 4px solid #fff;
cursor: pointer;
white-space: nowrap;
}
&__right {
display: flex;
align-items: flex-start;
padding-bottom: 20px;
border-bottom: 4px solid #fff;
cursor: pointer;
&__enter {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
font-family: 'font_medium', sans-serif;
font-size: 14px;
line-height: 17px;
color: #a9b5c1;
cursor: pointer;
margin-right: 10px;
padding-bottom: 10px;
border-bottom: 5px solid #fff;
white-space: nowrap;
}
&__info-button {
@ -272,59 +306,58 @@ export default class GeneratePassphrase extends Vue {
}
}
}
}
&__generate {
margin-top: 25px;
display: flex;
align-items: center;
padding: 25px;
background: #eff0f7;
border-radius: 10px;
&__generate {
display: flex;
align-items: center;
padding: 16px 22px;
background: #eff0f7;
border-radius: 10px;
margin: 25px 25px 0 25px;
&__value {
font-size: 16px;
line-height: 28px;
color: #384b65;
&__value {
font-size: 14px;
line-height: 25px;
color: #384b65;
}
&__button {
margin-left: 32px;
min-width: 66px;
}
}
&__button {
margin-left: 32px;
min-width: 66px;
&__enter {
margin: 25px 25px 0 25px;
}
}
&__enter {
margin-top: 25px;
}
&__download {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
color: #0068dc;
cursor: pointer;
margin: 20px 0;
}
&__warning {
border: 1px solid #e6e9ef;
border-radius: 10px;
padding: 25px;
&__title {
&__download {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
color: #df1616;
margin-bottom: 10px;
color: #0068dc;
cursor: pointer;
margin: 20px 25px;
display: inline-block;
}
&__msg {
&__warning-title {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
color: #1b2533;
margin: 25px 25px 10px 25px;
}
&__warning-msg {
font-size: 14px;
line-height: 20px;
color: #1b2533;
margin-bottom: 10px;
margin: 0 25px;
}
&__checkbox {
margin: 0 25px;
}
}
@ -333,11 +366,6 @@ export default class GeneratePassphrase extends Vue {
display: flex;
align-items: center;
margin-top: 30px;
&__back,
&__skip {
margin-right: 24px;
}
}
}
@ -346,6 +374,10 @@ export default class GeneratePassphrase extends Vue {
border-color: #0149ff;
}
.active svg rect {
fill: #0149ff;
}
::v-deep .info__box__message {
min-width: 440px;
}

View File

@ -2,10 +2,13 @@
// See LICENSE for copying information.
<template>
<label class="container">
<input v-model="checked" class="checkmark-input" type="checkbox" @change="onChange">
<span class="checkmark" :class="{'error': isCheckboxError}" />
</label>
<div class="wrap">
<label class="container">
<input id="checkbox" v-model="checked" class="checkmark-input" type="checkbox" @change="onChange">
<span class="checkmark" :class="{'error': isCheckboxError}" />
</label>
<label class="label" for="checkbox">{{ label }}</label>
</div>
</template>
<script lang="ts">
@ -17,6 +20,8 @@ import { Component, Prop, Vue } from 'vue-property-decorator';
export default class VCheckbox extends Vue {
@Prop({default: false})
private readonly isCheckboxError: boolean;
@Prop({default: ''})
private readonly label: string;
private checked = false;
@ -30,14 +35,19 @@ export default class VCheckbox extends Vue {
</script>
<style scoped lang="scss">
.wrap {
display: flex;
align-items: center;
width: 100%;
}
.container {
display: block;
position: relative;
padding-left: 20px;
height: 23px;
width: 23px;
padding-left: 15px;
height: 20px;
width: 20px;
cursor: pointer;
font-size: 22px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
@ -57,10 +67,11 @@ export default class VCheckbox extends Vue {
position: absolute;
top: 0;
left: 0;
height: 25px;
width: 25px;
height: 20px;
width: 20px;
border: 2px solid rgba(56, 75, 101, 0.4);
border-radius: 4px;
box-sizing: border-box;
}
.checkmark:after {
@ -70,8 +81,8 @@ export default class VCheckbox extends Vue {
}
.container .checkmark:after {
left: 9px;
top: 5px;
left: 4px;
top: 0;
width: 5px;
height: 10px;
border: solid white;
@ -86,8 +97,8 @@ export default class VCheckbox extends Vue {
}
.container .checkmark-input:checked ~ .checkmark {
border: 2px solid #2196f3;
background-color: #2196f3;
border: 2px solid #376fff;
background-color: #376fff;
}
.checkmark.error {
@ -97,4 +108,9 @@ export default class VCheckbox extends Vue {
.container .checkmark-input:checked ~ .checkmark:after {
display: block;
}
.label {
cursor: pointer;
font-size: 14px;
}
</style>

View File

@ -3,12 +3,56 @@
<template>
<div class="encrypt">
<h1 class="encrypt__title">Objects</h1>
<div class="encrypt__msg-container">
<p class="encrypt__msg-container__title" aria-roledescription="objects-title">
The object browser uses
<a
class="encrypt__msg-container__title__link"
href="https://docs.storj.io/dcs/concepts/encryption-key/design-decision-server-side-encryption"
target="_blank"
rel="noopener noreferrer"
>
server side encryption.
</a>
</p>
<p class="encrypt__msg-container__text">
If you want to use our product with only end-to-end encryption, you may want to use our
<span class="encrypt__msg-container__text__link" @click="navigateToCLIFlow">command line solution.</span>
</p>
</div>
<GeneratePassphrase
:on-next-click="onNextClick"
:set-parent-passphrase="setPassphrase"
:is-loading="isLoading"
/>
<div class="encrypt__faq">
<h2 class="encrypt__faq__title">FAQ</h2>
<FAQBullet
title="Why do I need a passphrase to upload?"
text="One very important design consideration is that data stored on Storj is encrypted. That means
only you have the encryption passphrase for your data. The service doesn't ever have access to or store
your encryption passphrase. If you lose your passphrase, you will be unable to recover your data."
/>
<FAQBullet
title="What if I enter a wrong passphrase?"
text="There is no wrong passphrase because every passphrase can have access to different files. Entering
a new or different passphrase wont have any effect on the existing files. If you enter your passphrase
and dont see the existing files, its most likely you entered a new passphrase and thats why you cant
see the encrypted data stored with a different passphrase."
/>
<FAQBullet
title="Why I have to enter a passphrase for every bucket?"
text="In general, the best practice is to use one encryption passphrase per bucket. If an object with
the same path and object name uploaded by two uplinks with encryption keys derived from the same
encryption passphrase, the most recent upload will over-write the older object."
/>
<FAQBullet
title="Why there is no “remember passphrase”?"
text="There is no wrong passphrase because every passphrase can have access to different files. Entering
a new or different passphrase wont have any effect on the existing files. If you enter a passphrase and
dont see your existing files, try to enter your passphrase again."
/>
</div>
</div>
</template>
@ -21,17 +65,31 @@ import { OBJECTS_ACTIONS } from '@/store/modules/objects';
import { LocalData } from "@/utils/localData";
import GeneratePassphrase from "@/components/common/GeneratePassphrase.vue";
import FAQBullet from "@/components/objects/FAQBullet.vue";
// @vue/component
@Component({
components: {
GeneratePassphrase,
FAQBullet,
},
})
export default class EncryptData extends Vue {
public isLoading = false;
public passphrase = '';
/**
* Sets passphrase from child component.
*/
public navigateToCLIFlow(): void {
this.$router.push({
name: RouteConfig.APIKey.name,
params: {
backRoute: this.$route.path,
}
})
}
/**
* Sets passphrase from child component.
*/
@ -86,14 +144,69 @@ export default class EncryptData extends Vue {
<style scoped lang="scss">
.encrypt {
font-family: 'font_regular', sans-serif;
padding-bottom: 60px;
padding-bottom: 30px;
&__title {
font-family: 'font_medium', sans-serif;
font-weight: bold;
font-size: 18px;
line-height: 26px;
color: #232b34;
&__msg-container {
margin: -20px auto 40px auto;
max-width: 620px;
background-color: #ffd78a;
display: flex;
flex-direction: column;
align-items: center;
border-radius: 0 0 10px 10px;
padding: 20px 0;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
text-align: center;
color: #000;
margin-bottom: 10px;
&__link {
color: #000;
text-decoration: underline !important;
text-underline-position: under;
&:visited {
color: #000;
}
}
}
&__text {
font-size: 14px;
line-height: 20px;
text-align: center;
color: #1b2533;
max-width: 400px;
&__link {
color: #1b2533;
text-decoration: underline;
text-underline-position: under;
cursor: pointer;
}
}
}
&__faq {
max-width: 620px;
// display: flex; revert this when FAQ content will be confirmed
display: none;
flex-direction: column;
align-items: center;
margin: 0 auto;
&__title {
font-family: 'font_bold', sans-serif;
font-size: 36px;
line-height: 56px;
letter-spacing: 1px;
color: #14142b;
margin: 75px 0 30px 0;
}
}
}
</style>

View File

@ -0,0 +1,76 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="bullet">
<div class="bullet__header" @click="toggle">
<h2 class="bullet__header__title">{{ title }}</h2>
<MinusIcon v-if="isExpanded" />
<PlusIcon v-else />
</div>
<p v-if="isExpanded" class="bullet__text">{{ text }}</p>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import PlusIcon from '@/../static/images/common/plus.svg';
import MinusIcon from '@/../static/images/common/minus.svg';
// @vue/component
@Component({
components: {
PlusIcon,
MinusIcon,
},
})
export default class FAQBullet extends Vue {
@Prop({default: ''})
public readonly title: string;
@Prop({default: ''})
public readonly text: string;
public isExpanded = false;
/**
* Toggles bullet text visibility.
*/
public toggle(): void {
this.isExpanded = !this.isExpanded;
}
}
</script>
<style scoped lang="scss">
.bullet {
background: #fff;
border: 2px solid #d8dee3;
border-radius: 16px;
padding: 28px 32px;
width: calc(100% - 64px);
margin-bottom: 30px;
&__header {
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
&__title {
font-family: 'font_medium', sans-serif;
font-size: 16px;
line-height: 32px;
letter-spacing: 0.75px;
color: #091c45;
}
}
&__text {
margin-top: 12px;
font-size: 16px;
line-height: 32px;
color: #56606d;
}
}
</style>

View File

@ -1,183 +0,0 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="warning-view">
<div class="warning-view__container">
<h1 class="warning-view__container__title" aria-roledescription="title">Object Browser</h1>
<div class="warning-view__container__message-container">
<h2 class="warning-view__container__message-container__sub-title" aria-roledescription="sub-title">The object browser uses server side encryption.</h2>
<p class="warning-view__container__message-container__message">
If you want to use our product with only end-to-end encryption, you may want to skip this feature.
</p>
</div>
<div class="warning-view__container__checkbox-area">
<v-checkbox @setData="setNotAskMeAgain" />
<p class="warning-view__container__checkbox-area__message">Do not ask me again</p>
</div>
<div class="warning-view__container__buttons-area">
<VButton
class="warning-view__container__buttons-area__left-button"
label="Return to dashboard"
width="50%"
height="48px"
:on-press="goToDashboard"
:is-blue-white="true"
/>
<VButton
label="Continue"
width="50%"
height="48px"
:on-press="proceed"
/>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import VButton from '@/components/common/VButton.vue';
import VCheckbox from '@/components/common/VCheckbox.vue';
import { RouteConfig } from '@/router';
import { LocalData } from '@/utils/localData';
// @vue/component
@Component({
components: {
VCheckbox,
VButton,
},
})
export default class WarningView extends Vue {
// Used for remembering confirmation of acknowledge.
public isNotAskMeAgain = false;
public setNotAskMeAgain(value: boolean): void {
this.isNotAskMeAgain = value;
}
/**
* Checks if user already acknowledged information and redirects if so.
*/
public beforeMount(): void {
if (LocalData.getServerSideEncryptionAcknowledge()) {
this.$router.push(RouteConfig.EncryptData.path);
}
}
/**
* Redirects to project dashboard page.
*/
public goToDashboard(): void {
this.$router.push(RouteConfig.ProjectDashboard.path);
}
/**
* Proceeds further into file browser flow.
*/
public proceed(): void {
if (this.isNotAskMeAgain) {
LocalData.setServerSideEncryptionAcknowledge();
}
this.$router.push(RouteConfig.EncryptData.path);
}
}
</script>
<style scoped lang="scss">
.warning-view {
font-family: 'font_regular', sans-serif;
font-style: normal;
display: flex;
align-items: center;
justify-content: center;
padding: 200px 0 40px 0;
&__container {
background: #fff;
border-radius: 6px;
padding: 35px 50px;
max-width: 515px;
&__title {
width: 100%;
text-align: center;
font-family: 'font_Bold', sans-serif;
font-size: 22px;
line-height: 27px;
color: #000;
margin: 0 0 35px 0;
}
&__message-container {
padding: 40px 30px;
width: calc(100% - 60px);
background: #fff;
border: 1px solid #e6e9ef;
border-radius: 9px;
display: flex;
flex-direction: column;
align-items: center;
&__sub-title {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 19px;
text-align: center;
color: #ce3030;
margin: 0 0 10px 0;
}
&__message {
font-weight: normal;
font-size: 16px;
line-height: 24px;
text-align: center;
color: #1b2533;
word-break: break-word;
margin: 0;
}
}
&__checkbox-area {
margin-top: 20px;
display: flex;
align-items: center;
justify-content: flex-start;
::v-deep.checkmark {
height: 20px;
width: 20px;
&:after {
left: 6px;
top: 2px;
}
}
&__message {
font-weight: normal;
font-size: 16px;
line-height: 24px;
text-align: center;
color: #1b2533;
}
}
&__buttons-area {
margin-top: 20px;
display: flex;
align-items: center;
justify-content: space-between;
&__left-button {
margin-right: 40px;
}
}
}
}
</style>

View File

@ -24,7 +24,6 @@ import BucketsView from '@/components/objects/BucketsView.vue';
import EncryptData from '@/components/objects/EncryptData.vue';
import ObjectsArea from '@/components/objects/ObjectsArea.vue';
import UploadFile from '@/components/objects/UploadFile.vue';
import WarningView from '@/components/objects/WarningView.vue';
import OnboardingTourArea from '@/components/onboardingTour/OnboardingTourArea.vue';
import OnbCLIStep from '@/components/onboardingTour/steps/CLIStep.vue';
import CreateAccessGrantStep from "@/components/onboardingTour/steps/oldFlow/CreateAccessGrantStep.vue";
@ -121,7 +120,6 @@ export abstract class RouteConfig {
public static AccessGrantGateway = new NavigationLink('gateway', 'Onboarding Access Grant Gateway');
// objects child paths.
public static Warning = new NavigationLink('warning', 'Objects Warning');
public static EncryptData = new NavigationLink('encrypt-data', 'Objects Encrypt Data');
public static BucketsManagement = new NavigationLink('buckets', 'Buckets Management');
public static UploadFile = new NavigationLink('upload/', 'Objects Upload');
@ -416,11 +414,6 @@ export const router = new Router({
name: RouteConfig.Objects.name,
component: ObjectsArea,
children: [
{
path: RouteConfig.Warning.path,
name: RouteConfig.Warning.name,
component: WarningView,
},
{
path: RouteConfig.EncryptData.path,
name: RouteConfig.EncryptData.name,
@ -500,7 +493,7 @@ router.beforeEach(async (to, from, next) => {
}
if (navigateToDefaultSubTab(to.matched, RouteConfig.Objects)) {
next(RouteConfig.Objects.with(RouteConfig.Warning).path);
next(RouteConfig.Objects.with(RouteConfig.EncryptData).path);
return;
}

View File

@ -50,14 +50,6 @@ export class LocalData {
localStorage.setItem(LocalData.userIdPassSalt, JSON.stringify(data));
}
public static getServerSideEncryptionAcknowledge(): boolean {
return Boolean(localStorage.getItem(LocalData.serverSideEncryptionAcknowledge));
}
public static setServerSideEncryptionAcknowledge(): void {
localStorage.setItem(LocalData.serverSideEncryptionAcknowledge, 'true');
}
}
/**

View File

@ -0,0 +1,3 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.45691 12L21.9224 12" stroke="#0149FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 223 B

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 3V21" stroke="#0149FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M3 12L21 12" stroke="#0149FF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 318 B

View File

@ -0,0 +1,4 @@
<svg width="13" height="14" viewBox="0 0 13 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect y="0.954102" width="13" height="12.8807" rx="6.44037" fill="#A9B5C1"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.50288 10.4956C6.90175 10.4956 7.2251 10.1723 7.2251 9.77338L7.2251 7.40131C7.2251 7.00244 6.90175 6.67909 6.50288 6.67909C6.104 6.67909 5.78065 7.00244 5.78065 7.40131L5.78065 9.77338C5.78065 10.1723 6.104 10.4956 6.50288 10.4956ZM6.50005 5.96355C6.99407 5.96355 7.40283 5.56308 7.40283 5.06906C7.40283 4.57504 6.99407 4.17456 6.50005 4.17456C6.00604 4.17456 5.59728 4.57504 5.59728 5.06906C5.59728 5.56308 6.00604 5.96355 6.50005 5.96355Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 696 B

View File

@ -1,5 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Checkbox.vue renders correctly 1`] = `<label class="container"><input type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label>`;
exports[`Checkbox.vue renders correctly 1`] = `<div class="wrap"><label class="container"><input id="checkbox" type="checkbox" class="checkmark-input"> <span class="checkmark"></span></label> <label for="checkbox" class="label"></label></div>`;
exports[`Checkbox.vue renders correctly with error 1`] = `<label class="container"><input type="checkbox" class="checkmark-input"> <span class="checkmark error"></span></label>`;
exports[`Checkbox.vue renders correctly with error 1`] = `<div class="wrap"><label class="container"><input id="checkbox" type="checkbox" class="checkmark-input"> <span class="checkmark error"></span></label> <label for="checkbox" class="label"></label></div>`;