From 65e3cfb9c6a0ea4429e44d8410dfa60ccaad2eae Mon Sep 17 00:00:00 2001 From: Vitalii Date: Tue, 7 Feb 2023 16:52:20 +0200 Subject: [PATCH] satellite/{web, console}: feature flag for new access grant flow Added a feature flag for new create access grant flow. Also added some initial setup. Change-Id: I7f738181c8a83f5a724f9e562427445cae146b6f --- satellite/console/consoleweb/server.go | 3 ++ scripts/testdata/satellite-config.yaml.lock | 3 ++ web/satellite/index.html | 1 + web/satellite/src/App.vue | 6 +++ .../components/accessGrants/AccessGrants.vue | 38 +++++++++++++++++++ .../newCreateFlow/CreateAccessGrantFlow.vue | 24 ++++++++++++ .../components/navigation/QuickStartLinks.vue | 30 ++++++++++++++- web/satellite/src/router/index.ts | 7 ++++ web/satellite/src/store/modules/appState.ts | 4 ++ web/satellite/src/store/mutationConstants.ts | 1 + web/satellite/src/types/createAccessGrant.ts | 8 ++++ 11 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 web/satellite/src/components/accessGrants/newCreateFlow/CreateAccessGrantFlow.vue create mode 100644 web/satellite/src/types/createAccessGrant.ts diff --git a/satellite/console/consoleweb/server.go b/satellite/console/consoleweb/server.go index 69c297995..d804ed290 100644 --- a/satellite/console/consoleweb/server.go +++ b/satellite/console/consoleweb/server.go @@ -92,6 +92,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:"true"` NewBillingScreen bool `help:"indicates if new billing screens should be used" default:"true"` + 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"` OptionalSignupSuccessURL string `help:"optional url to external registration success page" default:""` HomepageURL string `help:"url link to storj.io homepage" default:"https://www.storj.io"` @@ -457,6 +458,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) { DefaultPaidStorageLimit memory.Size DefaultPaidBandwidthLimit memory.Size NewBillingScreen bool + NewAccessGrantFlow bool InactivityTimerEnabled bool InactivityTimerDuration int InactivityTimerViewerEnabled bool @@ -507,6 +509,7 @@ func (server *Server) appHandler(w http.ResponseWriter, r *http.Request) { data.PasswordMinimumLength = console.PasswordMinimumLength data.PasswordMaximumLength = console.PasswordMaximumLength data.ABTestingEnabled = server.config.ABTesting.Enabled + data.NewAccessGrantFlow = server.config.NewAccessGrantFlow templates, err := server.loadTemplates() if err != nil || templates.index == nil { diff --git a/scripts/testdata/satellite-config.yaml.lock b/scripts/testdata/satellite-config.yaml.lock index edb1a247e..634394813 100755 --- a/scripts/testdata/satellite-config.yaml.lock +++ b/scripts/testdata/satellite-config.yaml.lock @@ -244,6 +244,9 @@ compensation.withheld-percents: 75,75,75,50,50,50,25,25,25,0,0,0,0,0,0 # indicates if storj native token payments system is enabled # console.native-token-payments-enabled: false +# indicates if new access grant flow should be used +# console.new-access-grant-flow: false + # indicates if new billing screens should be used # console.new-billing-screen: true diff --git a/web/satellite/index.html b/web/satellite/index.html index ac20c90fc..31038ff50 100644 --- a/web/satellite/index.html +++ b/web/satellite/index.html @@ -32,6 +32,7 @@ + diff --git a/web/satellite/src/App.vue b/web/satellite/src/App.vue index 87ff7a803..be8c3f4b0 100644 --- a/web/satellite/src/App.vue +++ b/web/satellite/src/App.vue @@ -14,6 +14,7 @@ import { Component, Vue } from 'vue-property-decorator'; import { PartneredSatellite } from '@/types/common'; import { APP_STATE_ACTIONS } from '@/utils/constants/actionNames'; +import { APP_STATE_MUTATIONS } from '@/store/mutationConstants'; import { MetaUtils } from '@/utils/meta'; import NotificationArea from '@/components/notifications/NotificationArea.vue'; @@ -40,6 +41,7 @@ export default class App extends Vue { const couponCodeBillingUIEnabled = MetaUtils.getMetaContent('coupon-code-billing-ui-enabled'); const couponCodeSignupUIEnabled = MetaUtils.getMetaContent('coupon-code-signup-ui-enabled'); const isNewProjectDashboard = MetaUtils.getMetaContent('new-project-dashboard'); + const isNewAccessGrantFlow = MetaUtils.getMetaContent('new-access-grant-flow'); if (satelliteName) { this.$store.dispatch(APP_STATE_ACTIONS.SET_SATELLITE_NAME, satelliteName); @@ -72,6 +74,10 @@ export default class App extends Vue { this.$store.dispatch(APP_STATE_ACTIONS.SET_PROJECT_DASHBOARD_STATUS, isNewProjectDashboard === 'true'); } + if (isNewAccessGrantFlow) { + this.$store.commit(APP_STATE_MUTATIONS.SET_ACCESS_GRANT_FLOW_STATUS, isNewAccessGrantFlow === 'true'); + } + this.fixViewportHeight(); } diff --git a/web/satellite/src/components/accessGrants/AccessGrants.vue b/web/satellite/src/components/accessGrants/AccessGrants.vue index 8e11d1398..290462f69 100644 --- a/web/satellite/src/components/accessGrants/AccessGrants.vue +++ b/web/satellite/src/components/accessGrants/AccessGrants.vue @@ -168,6 +168,7 @@ import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants'; import { AccessGrant } from '@/types/accessGrants'; import { AnalyticsHttpApi } from '@/api/analytics'; import { AnalyticsErrorEventSource, AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; +import { AccessType } from '@/types/createAccessGrant'; import AccessGrantsItem from '@/components/accessGrants/AccessGrantsItem.vue'; import ConfirmDeletePopup from '@/components/accessGrants/ConfirmDeletePopup.vue'; @@ -342,6 +343,16 @@ export default class AccessGrants extends Vue { */ public accessGrantClick(): void { this.analytics.eventTriggered(AnalyticsEvent.CREATE_ACCESS_GRANT_CLICKED); + + if (this.isNewAccessGrantFlow) { + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.NewCreateAccessModal).path); + this.$router.push({ + name: RouteConfig.NewCreateAccessModal.name, + params: { accessType: AccessType.AccessGrant }, + }); + return; + } + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path); this.$router.push({ name: RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).name, @@ -354,6 +365,16 @@ export default class AccessGrants extends Vue { */ public s3Click(): void { this.analytics.eventTriggered(AnalyticsEvent.CREATE_S3_CREDENTIALS_CLICKED); + + if (this.isNewAccessGrantFlow) { + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.NewCreateAccessModal).path); + this.$router.push({ + name: RouteConfig.NewCreateAccessModal.name, + params: { accessType: AccessType.S3 }, + }); + return; + } + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path); this.$router.push({ name: RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).name, @@ -366,6 +387,16 @@ export default class AccessGrants extends Vue { */ public cliClick(): void { this.analytics.eventTriggered(AnalyticsEvent.CREATE_KEYS_FOR_CLI_CLICKED); + + if (this.isNewAccessGrantFlow) { + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.NewCreateAccessModal).path); + this.$router.push({ + name: RouteConfig.NewCreateAccessModal.name, + params: { accessType: AccessType.APIKey }, + }); + return; + } + this.trackPageVisit(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).path); this.$router.push({ name: RouteConfig.AccessGrants.with(RouteConfig.CreateAccessModal).name, @@ -379,6 +410,13 @@ export default class AccessGrants extends Vue { public trackPageVisit(link: string): void { this.analytics.pageVisit(link); } + + /** + * Indicates if new access grant flow should be used. + */ + private get isNewAccessGrantFlow(): boolean { + return this.$store.state.appStateModule.isNewAccessGrantFlow; + } } \ No newline at end of file + diff --git a/web/satellite/src/router/index.ts b/web/satellite/src/router/index.ts index c740c9594..e65636e6c 100644 --- a/web/satellite/src/router/index.ts +++ b/web/satellite/src/router/index.ts @@ -9,6 +9,7 @@ import { MetaUtils } from '@/utils/meta'; import AccessGrants from '@/components/accessGrants/AccessGrants.vue'; import CreateAccessModal from '@/components/accessGrants/CreateAccessModal.vue'; +import CreateAccessGrantFlow from '@/components/accessGrants/newCreateFlow/CreateAccessGrantFlow.vue'; import AccountArea from '@/components/account/AccountArea.vue'; import AccountBilling from '@/components/account/billing/BillingArea.vue'; import BillingOverview from '@/components/account/billing/billingTabs/Overview.vue'; @@ -92,6 +93,7 @@ export abstract class RouteConfig { // access grant child paths public static CreateAccessModal = new NavigationLink('create-access-modal', 'Create Access Modal'); + public static NewCreateAccessModal = new NavigationLink('new-create-access-modal', 'New Create Access Modal'); // onboarding tour child paths public static OverviewStep = new NavigationLink('overview', 'Onboarding Overview'); @@ -352,6 +354,11 @@ export const router = new Router({ name: RouteConfig.CreateAccessModal.name, component: CreateAccessModal, }, + { + path: RouteConfig.NewCreateAccessModal.path, + name: RouteConfig.NewCreateAccessModal.name, + component: CreateAccessGrantFlow, + }, ], }, { diff --git a/web/satellite/src/store/modules/appState.ts b/web/satellite/src/store/modules/appState.ts index 3c3d56447..8a0b75dd4 100644 --- a/web/satellite/src/store/modules/appState.ts +++ b/web/satellite/src/store/modules/appState.ts @@ -70,6 +70,7 @@ class State { public couponCodeBillingUIEnabled = false, public couponCodeSignupUIEnabled = false, public isNewProjectDashboard = false, + public isNewAccessGrantFlow = false, ){} } @@ -271,6 +272,9 @@ export const appStateModule = { [APP_STATE_MUTATIONS.SET_PROJECT_DASHBOARD_STATUS](state: State, isNewProjectDashboard: boolean): void { state.isNewProjectDashboard = isNewProjectDashboard; }, + [APP_STATE_MUTATIONS.SET_ACCESS_GRANT_FLOW_STATUS](state: State, isNewAccessGrantFlow: boolean): void { + state.isNewAccessGrantFlow = isNewAccessGrantFlow; + }, [APP_STATE_MUTATIONS.SET_ONB_AG_NAME_STEP_BACK_ROUTE](state: State, backRoute: string): void { state.appState.onbAGStepBackRoute = backRoute; }, diff --git a/web/satellite/src/store/mutationConstants.ts b/web/satellite/src/store/mutationConstants.ts index 71b35c3ed..a7bdbd67b 100644 --- a/web/satellite/src/store/mutationConstants.ts +++ b/web/satellite/src/store/mutationConstants.ts @@ -62,6 +62,7 @@ export const APP_STATE_MUTATIONS = { SET_COUPON_CODE_BILLING_UI_STATUS: 'SET_COUPON_CODE_BILLING_UI_STATUS', SET_COUPON_CODE_SIGNUP_UI_STATUS: 'SET_COUPON_CODE_SIGNUP_UI_STATUS', SET_PROJECT_DASHBOARD_STATUS: 'SET_PROJECT_DASHBOARD_STATUS', + SET_ACCESS_GRANT_FLOW_STATUS: 'SET_ACCESS_GRANT_FLOW_STATUS', SET_ONB_AG_NAME_STEP_BACK_ROUTE: 'SET_ONB_AG_NAME_STEP_BACK_ROUTE', SET_ONB_API_KEY_STEP_BACK_ROUTE: 'SET_ONB_API_KEY_STEP_BACK_ROUTE', SET_ONB_API_KEY: 'SET_ONB_API_KEY', diff --git a/web/satellite/src/types/createAccessGrant.ts b/web/satellite/src/types/createAccessGrant.ts new file mode 100644 index 000000000..54ac2ecc0 --- /dev/null +++ b/web/satellite/src/types/createAccessGrant.ts @@ -0,0 +1,8 @@ +// Copyright (C) 2023 Storj Labs, Inc. +// See LICENSE for copying information. + +export enum AccessType { + APIKey = 'apikey', + S3 = 's3', + AccessGrant = 'accessGrant', +}