diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 77e1fa944..e80ed10cc 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -94,7 +94,7 @@ type Config struct { PathwayOverviewEnabled bool `help:"indicates if the overview onboarding step should render with pathways" default:"true"` NewProjectDashboard bool `help:"indicates if new project dashboard should be used" default:"false"` NewNavigation bool `help:"indicates if new navigation structure should be rendered" default:"true"` - NewObjectsFlow bool `help:"indicates if new objects flow should be used" default:"true"` + NewObjectsFlow bool `help:"indicates if new objects flow should be used" default:"false"` NewAccessGrantFlow bool `help:"indicates if new access grant flow should be used" default:"false"` GeneratedAPIEnabled bool `help:"indicates if generated console api should be used" default:"false"` InactivityTimerEnabled bool `help:"indicates if session can be timed out due inactivity" default:"false"` diff --git a/scripts/testdata/satellite-config.yaml.lock b/scripts/testdata/satellite-config.yaml.lock index 1c999b9ce..0319f6d76 100755 --- a/scripts/testdata/satellite-config.yaml.lock +++ b/scripts/testdata/satellite-config.yaml.lock @@ -242,7 +242,7 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0 # console.new-navigation: true # indicates if new objects flow should be used -# console.new-objects-flow: true +# console.new-objects-flow: false # indicates if new project dashboard should be used # console.new-project-dashboard: false diff --git a/testsuite/ui/satellite/browser_test.go b/testsuite/ui/satellite/browser_test.go index 479f280fc..c7674aa2c 100644 --- a/testsuite/ui/satellite/browser_test.go +++ b/testsuite/ui/satellite/browser_test.go @@ -28,11 +28,15 @@ func TestBrowser_Features(t *testing.T) { // Navigate into browser with new onboarding. page.MustElementR("a", "Skip and go directly to dashboard").MustClick() page.MustElementR("p", "Buckets").MustClick() - wait := page.MustWaitRequestIdle() - page.MustElementR("p", "demo-bucket").MustClick() - wait() + page.MustElementR("[aria-roledescription=title]", "Create a bucket") + page.MustElementR("span", "Continue").MustClick() + waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Encrypt your bucket") + page.MustElementR("span", "Continue").MustClick() + waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Generate a passphrase") page.MustElementR("label", "I understand, and I have saved the passphrase.").MustClick() - page.MustElementR("span", "Next >").MustClick() + page.MustElementR("span", "Continue").MustClick() // Verify that browser component has loaded and that the dropzone is present. page.MustElementR("p", "Drop Files Here to Upload") @@ -64,6 +68,7 @@ func TestBrowser_Features(t *testing.T) { page.MustElementR("button", "Cancel").MustClick() // Add a file into folder and check that dropzone is still visible. + page.MustElementR("button", "Upload").MustClick() wait1 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/img.png") wait1() @@ -74,7 +79,7 @@ func TestBrowser_Features(t *testing.T) { // Click on the file name. page.MustElementR("[aria-roledescription=file]", "img.png").MustClick() - require.Contains(t, page.MustElement("[aria-roledescription=image-preview]").MustProperty("src").Str(), "img.png", "The modal did not open on file click") + page.MustElement("[aria-roledescription=image-preview]") // Share a file. page.MustElementR("span", "Share").MustClick() @@ -90,7 +95,7 @@ func TestBrowser_Features(t *testing.T) { // Click on the hamburger and then details. page.MustElement("button[aria-roledescription=dropdown]").MustClick() page.MustElementR("button", "Details").MustClick() - require.Contains(t, page.MustElement("[aria-roledescription=image-preview]").MustProperty("src").Str(), "img.png", "The dropdown details functionality is not working") + page.MustElement("[aria-roledescription=image-preview]") page.MustElementR("span", "Share").MustClick() page.MustElement("#generateShareLink") page.MustElement("#close-modal").MustClick() @@ -106,6 +111,7 @@ func TestBrowser_Features(t *testing.T) { page.MustElementR("[aria-roledescription=folder]", "go-rod-test3") // Add two files. + page.MustElementR("button", "Upload").MustClick() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/img2.png") page.MustElement("#close-modal").MustClick() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/img.png") @@ -225,6 +231,7 @@ func TestBrowser_Features(t *testing.T) { page.MustElementR("[aria-roledescription=folder]", "Свобода") // upload a video. + page.MustElementR("button", "Upload").MustClick() wait3 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/movie.mp4") wait3() @@ -234,7 +241,7 @@ func TestBrowser_Features(t *testing.T) { page.MustElementR("[aria-roledescription=file-size]", "1.48 kB") page.MustElement("[aria-roledescription=file-upload-date]") page.MustElementR("[aria-roledescription=file]", "movie.mp4").MustClick() - require.Contains(t, page.MustElement("[aria-roledescription=video-preview]").MustProperty("src").Str(), "movie.mp4", "The modal did not open on video file click") + page.MustElement("[aria-roledescription=video-preview]") page.MustElement("#close-modal").MustClick() // Upload an audio file. @@ -242,7 +249,7 @@ func TestBrowser_Features(t *testing.T) { page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/audio.mp3") wait4() page.MustElementR("[aria-roledescription=file]", "audio.mp3").MustClick() - require.Contains(t, page.MustElement("[aria-roledescription=audio-preview]").MustProperty("src").Str(), "audio.mp3", "The modal did not open on video file click") + page.MustElement("[aria-roledescription=audio-preview]") page.MustElement("#close-modal").MustClick() // Navigate out of nested folder and delete everything. @@ -266,11 +273,15 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { // Navigate into browser with new onboarding. page.MustElementR("a", "Skip and go directly to dashboard").MustClick() page.MustElementR("p", "Buckets").MustClick() - wait := page.MustWaitRequestIdle() - page.MustElementR("p", "demo-bucket").MustClick() - wait() + page.MustElementR("[aria-roledescription=title]", "Create a bucket") + page.MustElementR("span", "Continue").MustClick() + waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Encrypt your bucket") + page.MustElementR("span", "Continue").MustClick() + waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Generate a passphrase") page.MustElementR("label", "I understand, and I have saved the passphrase.").MustClick() - page.MustElementR("span", "Next >").MustClick() + page.MustElementR("span", "Continue").MustClick() // Verify that browser component has loaded and that the dropzone is present. page.MustElementR("p", "Drop Files Here to Upload") @@ -307,6 +318,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { require.Equal(t, " ", page.MustElement("[placeholder=\"Name of the folder\"]").MustText(), "Folder input does not contain the empty invalid name") page.MustElementR("button", "Cancel").MustClick() + page.MustElementR("button", "Upload").MustClick() wait1 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/test0bytes.txt") wait1() @@ -315,6 +327,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { page.MustElementR("[aria-roledescription=file]", "test0bytes.txt").MustClick() require.Contains(t, page.MustElement("[aria-roledescription=preview-placeholder]").String(), "svg", "The modal did not open upon clicking the test0bytes.txt file") } else { + page.MustElementR("button", "Upload").MustClick() wait2 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=folder-upload]").MustSetFiles("./testdata") wait2() @@ -345,6 +358,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { require.Equal(t, " ", page.MustElement("[placeholder=\"Name of the folder\"]").MustText(), "Folder input does not contain the empty invalid name") page.MustElementR("button", "Cancel").MustClick() + page.MustElementR("button", "Upload").MustClick() wait3 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/test0bytes.txt") wait3() @@ -353,11 +367,13 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { page.MustElementR("[aria-roledescription=file]", "test0bytes.txt").MustClick() require.Contains(t, page.MustElement("[aria-roledescription=preview-placeholder]").String(), "svg", "The modal did not open upon clicking the test0bytes.txt file") } else { + page.MustElementR("button", "Upload").MustClick() wait4 := page.MustWaitRequestIdle() page.MustElement("input[aria-roledescription=folder-upload]").MustSetFiles("./testdata") wait4() page.MustElementR("table > tbody > tr:nth-child(1) > td", "..") page.MustElementR("[aria-roledescription=folder]", "testdata \\(1\\)").MustClick() + waitVueTick(page) page.MustElementR("[aria-roledescription=file]", "test0bytes.txt").MustClick() require.Contains(t, page.MustElement("[aria-roledescription=preview-placeholder]").String(), "svg", "The uploaded folder did not upload the files correctly") } @@ -366,6 +382,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { page.MustElement("#navigate-back").MustClick() // Upload a 0 byte file. + page.MustElementR("button", "Upload").MustClick() page.MustElement("input[aria-roledescription=file-upload]").MustSetFiles("./testdata/test0bytes.txt") page.MustElementR("span", "testing/test0bytes.txt") page.MustElement("#close-modal").MustClick() @@ -382,7 +399,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { if !testing.Short() { slowpage := page.Sleeper(uitest.MaxDuration(20 * time.Second)) - // Upload a 50 MB file. + // Upload a 5 MB file. testFile := generateEmptyFile(t, ctx, "testFile", 5*memory.MiB) wait5 := slowpage.MustWaitRequestIdle() slowpage.MustElement("input[aria-roledescription=file-upload]").MustSetFiles(testFile) @@ -403,6 +420,7 @@ func TestBrowser_FolderAndDifferentFileSizesUpload(t *testing.T) { slowpage.MustElement("#close-modal").MustClick() // Upload a 130MB file. + page.MustElementR("button", "Upload").MustClick() wait6 := slowpage.MustWaitRequestIdle() slowpage.MustElement("input[aria-roledescription=file-upload]").MustSetFiles(testFile2) require.Equal(t, " testing/testFile2", slowpage.MustElement("[aria-roledescription=file-uploading]").MustText(), "The testFile2 file has not started uploading") diff --git a/testsuite/ui/satellite/onboarding_test.go b/testsuite/ui/satellite/onboarding_test.go index 949d8d943..f41afce1c 100644 --- a/testsuite/ui/satellite/onboarding_test.go +++ b/testsuite/ui/satellite/onboarding_test.go @@ -29,25 +29,26 @@ func TestOnboarding_WizardBrowser(t *testing.T) { // Buckets Page bucketsTitle := page.MustElement("[aria-roledescription=title]").MustText() - require.Contains(t, bucketsTitle, "Buckets") - page.Race().ElementR("p", "demo-bucket").MustHandle(func(el *rod.Element) { - el.MustClick() - waitVueTick(page) - }).MustDo() - - // Passphrase screen - encryptionTitle := page.MustElement("[aria-roledescription=objects-title]").MustText() - require.Contains(t, encryptionTitle, "The object browser uses server side encryption.") - customPassphrase := page.MustElement("[aria-roledescription=enter-passphrase-label]") - customPassphraseLabel := customPassphrase.MustText() - require.Contains(t, customPassphraseLabel, "Enter your own passphrase") - customPassphrase.MustClick() + require.Contains(t, bucketsTitle, "Create a bucket") + page.MustElementR("[aria-roledescription=title]", "Create a bucket") + page.MustElementR("span", "Continue").MustClick() waitVueTick(page) - page.MustElement("[aria-roledescription=passphrase] input").MustInput("password123") - page.MustElement(".checkmark").MustClick() + page.MustElementR("[aria-roledescription=title]", "Encrypt your bucket") + page.MustElementR("span", "Continue").MustClick() waitVueTick(page) - page.MustElementX("(//span[text()=\"Next >\"])").MustClick() + page.MustElementR("[aria-roledescription=title]", "Generate a passphrase") + mnemonic := page.MustElement("[aria-roledescription=mnemonic]").MustText() + require.NotEmpty(t, mnemonic) + page.MustElementR("span", "Back").MustClick() waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Encrypt your bucket") + page.MustElement("[aria-roledescription=manual]").MustClick() + page.MustElementR("span", "Continue").MustClick() + waitVueTick(page) + page.MustElementR("[aria-roledescription=title]", "Enter a passphrase") + page.MustElement("[aria-roledescription=passphrase] input").MustInput("1") + page.MustElementR("label", "I understand, and I have saved the passphrase.").MustClick() + page.MustElementR("span", "Continue").MustClick() // Verify that browser component has loaded and that the dropzone is present page.MustElementR("p", "Drop Files Here to Upload") diff --git a/web/satellite/src/components/common/HeaderedInput.vue b/web/satellite/src/components/common/HeaderedInput.vue index 64fd73cce..c0353d8ac 100644 --- a/web/satellite/src/components/common/HeaderedInput.vue +++ b/web/satellite/src/components/common/HeaderedInput.vue @@ -58,9 +58,8 @@ import HeaderlessInput from './HeaderlessInput.vue'; ErrorIcon, }, }) +// TODO: merge these two components to have one single source of truth. export default class HeaderedInput extends HeaderlessInput { - @Prop({default: ''}) - private readonly initValue: string; @Prop({default: ''}) private readonly additionalLabel: string; @Prop({default: 0}) @@ -73,10 +72,6 @@ export default class HeaderedInput extends HeaderlessInput { private readonly isMultiline: boolean; @Prop({default: false}) private readonly isLoading: boolean; - - public created() { - this.setValue(this.initValue); - } } diff --git a/web/satellite/src/components/common/HeaderlessInput.vue b/web/satellite/src/components/common/HeaderlessInput.vue index 09e11f1e5..1236af7f8 100644 --- a/web/satellite/src/components/common/HeaderlessInput.vue +++ b/web/satellite/src/components/common/HeaderlessInput.vue @@ -78,8 +78,10 @@ export default class HeaderlessInput extends Vue { private type: string = this.textType; private isPasswordShown = false; + public value: string; + @Prop({default: ''}) - protected value: string; + protected readonly initValue: string; @Prop({default: ''}) protected readonly label: string; @@ -111,6 +113,7 @@ export default class HeaderlessInput extends Vue { public created() { this.type = this.isPassword ? this.passwordType : this.textType; + this.value = this.initValue; } /** diff --git a/web/satellite/src/components/objects/BucketCreation.vue b/web/satellite/src/components/objects/BucketCreation.vue new file mode 100644 index 000000000..c8a266e18 --- /dev/null +++ b/web/satellite/src/components/objects/BucketCreation.vue @@ -0,0 +1,203 @@ +// Copyright (C) 2022 Storj Labs, Inc. +// See LICENSE for copying information. + + + + + + diff --git a/web/satellite/src/components/objects/BucketCreationGeneratePassphrase.vue b/web/satellite/src/components/objects/BucketCreationGeneratePassphrase.vue new file mode 100644 index 000000000..442ad1aee --- /dev/null +++ b/web/satellite/src/components/objects/BucketCreationGeneratePassphrase.vue @@ -0,0 +1,399 @@ +// Copyright (C) 2022 Storj Labs, Inc. +// See LICENSE for copying information. + + + + + + diff --git a/web/satellite/src/components/objects/BucketCreationNameStep.vue b/web/satellite/src/components/objects/BucketCreationNameStep.vue new file mode 100644 index 000000000..c039571a0 --- /dev/null +++ b/web/satellite/src/components/objects/BucketCreationNameStep.vue @@ -0,0 +1,204 @@ +// Copyright (C) 2022 Storj Labs, Inc. +// See LICENSE for copying information. + + + + + + diff --git a/web/satellite/src/components/objects/BucketCreationProgress.vue b/web/satellite/src/components/objects/BucketCreationProgress.vue new file mode 100644 index 000000000..431d7c1ef --- /dev/null +++ b/web/satellite/src/components/objects/BucketCreationProgress.vue @@ -0,0 +1,134 @@ +// Copyright (C) 2022 Storj Labs, Inc. +// See LICENSE for copying information. + + + + + + diff --git a/web/satellite/src/components/objects/BucketsView.vue b/web/satellite/src/components/objects/BucketsView.vue index af98fd40c..189dbdbc5 100644 --- a/web/satellite/src/components/objects/BucketsView.vue +++ b/web/satellite/src/components/objects/BucketsView.vue @@ -5,7 +5,7 @@

Buckets

-
+

New Bucket

@@ -62,20 +62,20 @@ import { Bucket } from 'aws-sdk/clients/s3'; import { Component, Vue, Watch } from 'vue-property-decorator'; +import { RouteConfig } from '@/router'; +import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants'; +import { OBJECTS_ACTIONS } from '@/store/modules/objects'; +import { AccessGrant, EdgeCredentials } from '@/types/accessGrants'; +import { MetaUtils } from '@/utils/meta'; +import { Validator } from '@/utils/validation'; +import { LocalData } from "@/utils/localData"; + import VLoader from '@/components/common/VLoader.vue'; import BucketItem from '@/components/objects/BucketItem.vue'; import ObjectsPopup from '@/components/objects/ObjectsPopup.vue'; import BucketIcon from '@/../static/images/objects/bucket.svg'; -import { RouteConfig } from '@/router'; -import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants'; -import { DEMO_BUCKET_NAME, OBJECTS_ACTIONS } from '@/store/modules/objects'; -import { AccessGrant, EdgeCredentials } from '@/types/accessGrants'; -import { MetaUtils } from '@/utils/meta'; -import { Validator } from '@/utils/validation'; -import { LocalData } from "@/utils/localData"; - // @vue/component @Component({ components: { @@ -104,23 +104,15 @@ export default class BucketsView extends Vue { * Setup gateway credentials. */ public async mounted(): Promise { - if (!this.$store.state.objectsModule.passphrase && !this.isNewObjectsFlow) { - await this.$router.push(RouteConfig.Buckets.with(RouteConfig.EncryptData).path); - - return; - } - await this.setBucketsView(); } @Watch('selectedProjectID') public async handleProjectChange(): Promise { - if (this.isNewObjectsFlow) { - this.isLoading = true; + this.isLoading = true; - await this.$store.dispatch(OBJECTS_ACTIONS.CLEAR); - await this.setBucketsView(); - } + await this.$store.dispatch(OBJECTS_ACTIONS.CLEAR); + await this.setBucketsView(); } /** @@ -147,7 +139,14 @@ export default class BucketsView extends Vue { return; } - if (!wasDemoBucketCreated) await this.createDemoBucket(); + if (!this.bucketsList.length && !wasDemoBucketCreated) { + if (this.isNewObjectsFlow) { + await this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketCreation).path); + return; + } + + await this.createDemoBucket(); + } } catch (error) { await this.$notify.error(`Failed to setup Buckets view. ${error.message}`); } finally { @@ -183,14 +182,10 @@ export default class BucketsView extends Vue { } const satelliteNodeURL: string = MetaUtils.getMetaContent('satellite-nodeurl'); - let passphrase = ''; - if (!this.isNewObjectsFlow) { - passphrase = this.passphrase; - } this.worker.postMessage({ 'type': 'GenerateAccess', 'apiKey': this.grantWithPermissions, - 'passphrase': passphrase, + 'passphrase': '', 'projectID': this.$store.getters.selectedProject.id, 'satelliteNodeURL': satelliteNodeURL, }); @@ -224,6 +219,12 @@ export default class BucketsView extends Vue { }; } + public onNewBucketButtonClick(): void { + this.isNewObjectsFlow + ? this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketCreation).path) + : this.showCreateBucketPopup(); + } + /** * Holds create bucket click logic. */ @@ -239,14 +240,9 @@ export default class BucketsView extends Vue { await this.setAccess(); } await this.$store.dispatch(OBJECTS_ACTIONS.CREATE_BUCKET, this.createBucketName); - if (this.isNewObjectsFlow) { - await this.$store.dispatch(OBJECTS_ACTIONS.FETCH_BUCKETS); - this.createBucketName = ''; - this.isRequestProcessing = false; - this.hideCreateBucketPopup(); - - return; - } + await this.$store.dispatch(OBJECTS_ACTIONS.FETCH_BUCKETS); + this.createBucketName = ''; + this.hideCreateBucketPopup(); } catch (error) { const BUCKET_ALREADY_EXISTS_ERROR = 'BucketAlreadyExists'; @@ -255,17 +251,9 @@ export default class BucketsView extends Vue { } else { await this.$notify.error(error.message); } - + } finally { this.isRequestProcessing = false; - - return; } - - const bucket = this.createBucketName; - this.createBucketName = ''; - this.isRequestProcessing = false; - - this.openBucket(bucket); } /** @@ -278,25 +266,14 @@ export default class BucketsView extends Vue { try { await this.$store.dispatch(OBJECTS_ACTIONS.CREATE_DEMO_BUCKET); - if (this.isNewObjectsFlow) { - await this.$store.dispatch(OBJECTS_ACTIONS.FETCH_BUCKETS); + await this.$store.dispatch(OBJECTS_ACTIONS.FETCH_BUCKETS); - LocalData.setDemoBucketCreatedStatus(); - this.isRequestProcessing = false; - - return; - } + LocalData.setDemoBucketCreatedStatus(); } catch (error) { await this.$notify.error(error.message); + } finally { this.isRequestProcessing = false; - - return; } - - LocalData.setDemoBucketCreatedStatus(); - this.isRequestProcessing = false; - - this.openBucket(DEMO_BUCKET_NAME); } /** @@ -317,17 +294,27 @@ export default class BucketsView extends Vue { await this.$store.dispatch(OBJECTS_ACTIONS.FETCH_BUCKETS); } catch (error) { await this.$notify.error(error.message); - - this.isRequestProcessing = false; - return; + } finally { + this.isRequestProcessing = false; } - this.isRequestProcessing = false; this.deleteBucketName = ''; this.hideDeleteBucketPopup(); } + /** + * Removes temporary created access grant. + */ + public async removeTemporaryAccessGrant(): Promise { + try { + await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE_BY_NAME_AND_PROJECT_ID, this.FILE_BROWSER_AG_NAME); + await this.$store.dispatch(OBJECTS_ACTIONS.CLEAR); + } catch (error) { + await this.$notify.error(error.message); + } + } + /** * Opens utils dropdown. */ @@ -389,31 +376,12 @@ export default class BucketsView extends Vue { this.createBucketName = name; } - /** - * Removes temporary created access grant. - */ - public async removeTemporaryAccessGrant(): Promise { - try { - await this.$store.dispatch(ACCESS_GRANTS_ACTIONS.DELETE_BY_NAME_AND_PROJECT_ID, this.FILE_BROWSER_AG_NAME); - await this.$store.dispatch(OBJECTS_ACTIONS.CLEAR); - } catch (error) { - await this.$notify.error(error.message); - } - } - /** * Holds on bucket click. Proceeds to file browser. */ public openBucket(bucketName: string): void { this.$store.dispatch(OBJECTS_ACTIONS.SET_FILE_COMPONENT_BUCKET_NAME, bucketName); - - if (this.isNewObjectsFlow) { - this.$router.push(RouteConfig.Buckets.with(RouteConfig.EncryptData).path); - - return; - } - - this.$router.push(RouteConfig.Buckets.with(RouteConfig.UploadFile).path); + this.$router.push(RouteConfig.Buckets.with(RouteConfig.EncryptData).path); } /** @@ -423,13 +391,6 @@ export default class BucketsView extends Vue { return this.$store.state.objectsModule.bucketsList; } - /** - * Returns passphrase from store. - */ - private get passphrase(): string { - return this.$store.state.objectsModule.passphrase; - } - /** * Returns objects flow status from store. */ diff --git a/web/satellite/src/components/objects/EncryptData.vue b/web/satellite/src/components/objects/EncryptData.vue index e764f560d..c5980710f 100644 --- a/web/satellite/src/components/objects/EncryptData.vue +++ b/web/satellite/src/components/objects/EncryptData.vue @@ -98,13 +98,11 @@ export default class EncryptData extends Vue { * Sets local worker if new flow is used. */ public mounted(): void { - if (this.isNewObjectsFlow) { - if (!this.apiKey) { - this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path) - } - - this.setWorker(); + if (!this.apiKey) { + this.$router.push(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path) } + + this.setWorker(); } /** @@ -142,27 +140,19 @@ export default class EncryptData extends Vue { return; } - const keyToBeStored = await result.toString('hex'); + const keyToBeStored = result.toString('hex'); await LocalData.setUserIDPassSalt(this.$store.getters.user.id, keyToBeStored, SALT); await this.$store.dispatch(OBJECTS_ACTIONS.SET_PASSPHRASE, this.passphrase); - if (this.isNewObjectsFlow) { - try { - await this.setAccess(); - await this.$router.push(RouteConfig.UploadFile.path); - } catch (e) { - await this.$notify.error(e.message); - } - + try { + await this.setAccess(); + await this.$router.push(RouteConfig.UploadFile.path); + } catch (e) { + await this.$notify.error(e.message); + } finally { this.isLoading = false; - - return; } - - this.isLoading = false; - - await this.$router.push(RouteConfig.BucketsManagement.path); } /** @@ -242,13 +232,6 @@ export default class EncryptData extends Vue { private get bucket(): string { return this.$store.state.objectsModule.fileComponentBucketName; } - - /** - * Returns objects flow status from store. - */ - private get isNewObjectsFlow(): string { - return this.$store.state.appStateModule.isNewObjectsFlow; - } } diff --git a/web/satellite/src/components/objects/ObjectsArea.vue b/web/satellite/src/components/objects/ObjectsArea.vue index 6e1b2deb2..c6e20e4ea 100644 --- a/web/satellite/src/components/objects/ObjectsArea.vue +++ b/web/satellite/src/components/objects/ObjectsArea.vue @@ -22,8 +22,8 @@ export default class ObjectsArea extends Vue { * Redirects if flow is disabled. */ public async mounted(): Promise { - const value = MetaUtils.getMetaContent('file-browser-flow-disabled'); - if (value === "true") { + const isFileBrowserFlowDisabled = MetaUtils.getMetaContent('file-browser-flow-disabled'); + if (isFileBrowserFlowDisabled === "true") { await this.$router.push(RouteConfig.ProjectDashboard.path); } } diff --git a/web/satellite/src/router/index.ts b/web/satellite/src/router/index.ts index ce9407b8d..79a225bc4 100644 --- a/web/satellite/src/router/index.ts +++ b/web/satellite/src/router/index.ts @@ -45,6 +45,7 @@ import RegistrationSuccess from "@/components/common/RegistrationSuccess.vue"; import SuccessScreen from "@/components/onboardingTour/steps/cliFlow/SuccessScreen.vue"; import AGName from "@/components/onboardingTour/steps/cliFlow/AGName.vue"; import AGPermissions from "@/components/onboardingTour/steps/cliFlow/AGPermissions.vue"; +import BucketCreation from "@/components/objects/BucketCreation.vue"; import { NavigationLink } from '@/types/navigation'; import { MetaUtils } from "@/utils/meta"; @@ -121,6 +122,7 @@ export abstract class RouteConfig { public static BucketsManagement = new NavigationLink('management', 'Buckets Management'); public static UploadFile = new NavigationLink('upload/', 'Objects Upload'); public static UploadFileChildren = new NavigationLink('*', 'Objects Upload Children'); + public static BucketCreation = new NavigationLink('creation', 'Bucket Creation') } const isNewProjectDashboard = MetaUtils.getMetaContent('new-project-dashboard') === 'true'; @@ -419,6 +421,11 @@ export const router = new Router({ }, ], }, + { + path: RouteConfig.BucketCreation.path, + name: RouteConfig.BucketCreation.name, + component: BucketCreation, + }, ], }, ], diff --git a/web/satellite/src/store/index.ts b/web/satellite/src/store/index.ts index b503042cd..aa278ee1b 100644 --- a/web/satellite/src/store/index.ts +++ b/web/satellite/src/store/index.ts @@ -95,7 +95,6 @@ export default store; store and the router. Many of the tests require router, however, this implementation relies on store state for the routing behavior. */ - router.beforeEach(async (to, _, next) => { if (!to.path.includes(RouteConfig.UploadFile.path) && !store.state.appStateModule.appState.isUploadCancelPopupVisible) { const areUploadsInProgress: boolean = await store.dispatch(OBJECTS_ACTIONS.CHECK_ONGOING_UPLOADS, to.path); @@ -127,13 +126,7 @@ router.beforeEach(async (to, _, next) => { } if (navigateToDefaultSubTab(to.matched, RouteConfig.Buckets)) { - if (store.state.appStateModule.isNewObjectsFlow) { - next(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path); - - return; - } - - next(RouteConfig.Buckets.with(RouteConfig.EncryptData).path); + next(RouteConfig.Buckets.with(RouteConfig.BucketsManagement).path); return; } diff --git a/web/satellite/static/images/objects/bucketCreation.svg b/web/satellite/static/images/objects/bucketCreation.svg new file mode 100644 index 000000000..e89ba5114 --- /dev/null +++ b/web/satellite/static/images/objects/bucketCreation.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/web/satellite/static/images/objects/check.svg b/web/satellite/static/images/objects/check.svg new file mode 100644 index 000000000..97d15a100 --- /dev/null +++ b/web/satellite/static/images/objects/check.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/satellite/static/images/objects/fingerprint.svg b/web/satellite/static/images/objects/fingerprint.svg new file mode 100644 index 000000000..cef81bdf6 --- /dev/null +++ b/web/satellite/static/images/objects/fingerprint.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/satellite/static/images/objects/key.svg b/web/satellite/static/images/objects/key.svg new file mode 100644 index 000000000..d4a31f912 --- /dev/null +++ b/web/satellite/static/images/objects/key.svg @@ -0,0 +1,3 @@ + + +