Skip to content

Commit 562cf08

Browse files
kyle-ssgZaimwa9
andauthored
feat: welcome page (#5426)
Co-authored-by: Zaimwa9 <wadii.zaim@flagsmith.com>
1 parent bd2e7d6 commit 562cf08

33 files changed

+823
-68
lines changed

frontend/common/services/useOnboarding.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,47 @@
11
import { Res } from 'common/types/responses'
22
import { Req } from 'common/types/requests'
33
import { service } from 'common/service'
4+
import { getProfile } from './useProfile'
5+
import { getStore } from 'common/store'
46

57
export const onboardingService = service
68
.enhanceEndpoints({ addTagTypes: ['Onboarding'] })
79
.injectEndpoints({
810
endpoints: (builder) => ({
9-
createOnboarding: builder.mutation<
11+
updateOnboarding: builder.mutation<
1012
Res['onboarding'],
11-
Req['createOnboarding']
13+
Req['updateOnboarding']
1214
>({
13-
invalidatesTags: [{ id: 'LIST', type: 'Onboarding' }],
14-
query: (query: Req['createOnboarding']) => ({
15+
invalidatesTags: (res) => [{ id: 'LIST', type: 'Onboarding' }],
16+
query: (query: Req['updateOnboarding']) => ({
1517
body: query,
16-
method: 'POST',
17-
url: `onboarding`,
18+
method: 'PATCH',
19+
url: `auth/users/me/onboarding/`,
1820
}),
21+
transformResponse: async (res) => {
22+
await getProfile(getStore(), {}, { forceRefetch: true })
23+
return res
24+
},
1925
}),
2026
// END OF ENDPOINTS
2127
}),
2228
})
2329

24-
export async function createOnboarding(
30+
export async function updateOnboarding(
2531
store: any,
26-
data: Req['createOnboarding'],
32+
data: Req['updateOnboarding'],
2733
options?: Parameters<
28-
typeof onboardingService.endpoints.createOnboarding.initiate
34+
typeof onboardingService.endpoints.updateOnboarding.initiate
2935
>[1],
3036
) {
3137
return store.dispatch(
32-
onboardingService.endpoints.createOnboarding.initiate(data, options),
38+
onboardingService.endpoints.updateOnboarding.initiate(data, options),
3339
)
3440
}
3541
// END OF FUNCTION_EXPORTS
3642

3743
export const {
38-
useCreateOnboardingMutation,
44+
useUpdateOnboardingMutation,
3945
// END OF EXPORTS
4046
} = onboardingService
4147

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Res } from 'common/types/responses'
2+
import { Req } from 'common/types/requests'
3+
import { service } from 'common/service'
4+
5+
export const profileService = service
6+
.enhanceEndpoints({ addTagTypes: ['Profile'] })
7+
.injectEndpoints({
8+
endpoints: (builder) => ({
9+
getProfile: builder.query<Res['profile'], Req['getProfile']>({
10+
providesTags: [{ id: 'LIST', type: 'Profile' }],
11+
query: () => ({
12+
url: `auth/users/me/`,
13+
}),
14+
}),
15+
// END OF ENDPOINTS
16+
}),
17+
})
18+
19+
export async function getProfile(
20+
store: any,
21+
data: Req['getProfile'],
22+
options?: Parameters<typeof profileService.endpoints.getProfile.initiate>[1],
23+
) {
24+
return store.dispatch(
25+
profileService.endpoints.getProfile.initiate(data, options),
26+
)
27+
}
28+
// END OF FUNCTION_EXPORTS
29+
30+
export const {
31+
useGetProfileQuery,
32+
// END OF EXPORTS
33+
} = profileService

frontend/common/stores/account-store.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ const controller = {
172172
store.saved()
173173
})
174174
},
175-
getOrganisations: () =>
175+
getOrganisations: (isGettingStarted) =>
176176
Promise.all([
177177
data.get(`${Project.api}organisations/`),
178178
data.get(`${Project.api}auth/users/me/`),
@@ -181,6 +181,7 @@ const controller = {
181181
.then(([res, userRes, methods]) => {
182182
controller.setUser({
183183
...userRes,
184+
isGettingStarted,
184185
organisations: res.results,
185186
twoFactorConfirmed: !!methods.length,
186187
twoFactorEnabled: !!methods.length,
@@ -245,11 +246,9 @@ const controller = {
245246
})
246247
.catch((e) => API.ajaxHandler(store, e))
247248
},
248-
onLogin: (skipCaching) => {
249-
if (!skipCaching) {
250-
API.setCookie('t', Project.cookieAuthEnabled ? 'true' : data.token)
251-
}
252-
return controller.getOrganisations()
249+
onLogin: (isGettingStarted) => {
250+
API.setCookie('t', Project.cookieAuthEnabled ? 'true' : data.token)
251+
return controller.getOrganisations(isGettingStarted)
253252
},
254253
register: ({ contact_consent_given, organisation_name, ...user }) => {
255254
store.saving()
@@ -276,7 +275,7 @@ const controller = {
276275
if (contact_consent_given) {
277276
await createOnboardingSupportOptIn(getStore(), {})
278277
}
279-
await controller.onLogin()
278+
await controller.onLogin(!API.getInvite())
280279

281280
if (user.superuser) {
282281
// Creating a superuser will update the version endpoint

frontend/common/stores/feature-list-store.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
import { updateSegmentPriorities } from 'common/services/useSegmentPriority'
99
import {
1010
createProjectFlag,
11+
projectFlagService,
1112
updateProjectFlag,
1213
} from 'common/services/useProjectFlag'
1314
import OrganisationStore from './organisation-store'
@@ -28,6 +29,7 @@ import { Req } from 'common/types/requests'
2829
import { getVersionFeatureState } from 'common/services/useVersionFeatureState'
2930
import { getFeatureStates } from 'common/services/useFeatureState'
3031
import { getSegments } from 'common/services/useSegment'
32+
import { projectService } from 'common/services/useProject'
3133

3234
const Dispatcher = require('common/dispatcher/dispatcher')
3335
const BaseStore = require('./base/_store')
@@ -133,6 +135,10 @@ const controller = {
133135
environmentFeatures && _.keyBy(environmentFeatures, 'feature'),
134136
}
135137
store.model.lastSaved = new Date().valueOf()
138+
getStore().dispatch(
139+
projectFlagService.util.invalidateTags(['ProjectFlag']),
140+
)
141+
136142
store.saved({ createdFlag: flag.name })
137143
}),
138144
)
@@ -165,6 +171,9 @@ const controller = {
165171
const index = _.findIndex(store.model.features, { id: flag.id })
166172
store.model.features[index] = controller.parseFlag(flag)
167173
store.model.lastSaved = new Date().valueOf()
174+
getStore().dispatch(
175+
projectFlagService.util.invalidateTags(['ProjectFlag']),
176+
)
168177
store.changed()
169178
}
170179
})
@@ -449,6 +458,9 @@ const controller = {
449458
store.model.lastSaved = new Date().valueOf()
450459
}
451460
onComplete && onComplete()
461+
getStore().dispatch(
462+
projectFlagService.util.invalidateTags(['ProjectFlag']),
463+
)
452464
store.saved({})
453465
})
454466
.catch((e) => {
@@ -959,6 +971,9 @@ const controller = {
959971
(f) => f.id !== flag.id,
960972
)
961973
store.model.lastSaved = new Date().valueOf()
974+
getStore().dispatch(
975+
projectFlagService.util.invalidateTags(['ProjectFlag']),
976+
)
962977
store.saved({})
963978
store.trigger('removed', flag)
964979
})

frontend/common/types/requests.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
RolePermission,
1919
Webhook,
2020
IdentityTrait,
21+
Onboarding,
2122
} from './responses'
2223

2324
export type PagedRequest<T> = T & {
@@ -653,7 +654,7 @@ export type Req = {
653654
id: string
654655
}
655656
}
656-
createOnboarding: {
657+
register: {
657658
first_name: string
658659
last_name: string
659660
email: string
@@ -673,5 +674,7 @@ export type Req = {
673674
userId: number | undefined
674675
level: PermissionLevel
675676
}
677+
getProfile: {}
678+
updateOnboarding: Partial<Onboarding>
676679
// END OF TYPES
677680
}

frontend/common/types/responses.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,25 @@ export type githubIntegration = {
239239
organisation: string
240240
}
241241

242+
export type GettingStartedTask = {
243+
name: string
244+
completed_at?: string
245+
}
246+
export type Onboarding = {
247+
tools: {
248+
completed: boolean
249+
selection: string[]
250+
}
251+
tasks: GettingStartedTask[]
252+
}
242253
export type User = {
243254
id: number
244255
email: string
245256
first_name: string
246257
last_name: string
247258
last_login: string
248259
uuid: string
260+
onboarding: Onboarding
249261
}
250262
export type GroupUser = Omit<User, 'role'> & {
251263
group_admin: boolean
@@ -935,6 +947,8 @@ export type Res = {
935947
conversionEvents: PagedResponse<ConversionEvent>
936948
splitTest: PagedResponse<SplitTestResult>
937949
onboardingSupportOptIn: { id: string }
950+
profile: User
951+
onboarding: {}
938952
userPermissions: UserPermissions
939953
// END OF TYPES
940954
}

frontend/e2e/helpers.cafe.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { RequestLogger, Selector, t } from 'testcafe'
2-
import { FlagsmithValue } from '../common/types/responses'
2+
import Project from '../common/project';
3+
import fetch from 'node-fetch';
4+
import flagsmith from 'flagsmith/isomorphic';
5+
import { IFlagsmith, FlagsmithValue } from 'flagsmith/types';
36

47
export const LONG_TIMEOUT = 40000
58

@@ -19,6 +22,11 @@ export const isElementExists = async (selector: string) => {
1922
return Selector(byId(selector)).exists
2023
}
2124

25+
const initProm = flagsmith.init({fetch,environmentID:Project.flagsmith,api:Project.flagsmithClientAPI})
26+
export const getFlagsmith = async function() {
27+
await initProm
28+
return flagsmith as IFlagsmith
29+
}
2230
export const setText = async (selector: string, text: string) => {
2331
logUsingLastSection(`Set text ${selector} : ${text}`)
2432
if (text) {

frontend/e2e/tests/initialise-tests.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import {
22
byId,
33
click,
4+
getFlagsmith,
45
log,
56
setText,
67
waitForElementVisible,
7-
} from '../helpers.cafe'
8+
} from '../helpers.cafe';
89
import { E2E_SIGN_UP_USER, PASSWORD } from '../config'
910

1011
export default async function () {
12+
const flagsmith = await getFlagsmith()
1113
log('Create Organisation')
1214
await click(byId('jsSignup'))
1315
await setText(byId('firstName'), 'Bullet') // visit the url
@@ -17,7 +19,11 @@ export default async function () {
1719
await click(byId('signup-btn'))
1820
await setText('[name="orgName"]', 'Flagsmith Ltd 0')
1921
await click('#create-org-btn')
20-
await waitForElementVisible(byId('project-manage-widget'))
22+
if(flagsmith.hasFeature("welcome_page")) {
23+
await click(byId('create-project')) // Click create project from welcome page
24+
} else {
25+
await waitForElementVisible(byId('project-manage-widget'))
26+
}
2127

2228
log('Create Project')
2329
await click(byId('create-first-project-btn'))

frontend/e2e/tests/versioning-tests.ts

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,15 @@ import {
66
createFeature,
77
createOrganisationAndProject,
88
createRemoteConfig,
9-
editRemoteConfig,
9+
editRemoteConfig, getFlagsmith,
1010
log,
1111
login, refreshUntilElementVisible,
12-
waitForElementVisible
13-
} from "../helpers.cafe";
12+
waitForElementVisible,
13+
} from '../helpers.cafe';
1414
import { E2E_USER, PASSWORD } from '../config';
15-
import fetch from 'node-fetch';
16-
import flagsmith from 'flagsmith/isomorphic';
17-
import Project from '../../common/project';
1815

1916
export default async () => {
20-
await flagsmith.init({fetch,environmentID:Project.flagsmith,api:Project.flagsmithClientAPI})
17+
const flagsmith = await getFlagsmith()
2118
const hasFeature = flagsmith.hasFeature("feature_versioning")
2219
log('Login')
2320
await login(E2E_USER, PASSWORD)

0 commit comments

Comments
 (0)