Skip to content

Commit

Permalink
sync: master to develop
Browse files Browse the repository at this point in the history
sync: master to develop
  • Loading branch information
ovh-ux-cds authored Dec 16, 2024
2 parents 335ee14 + 0b0f33c commit 28605bf
Show file tree
Hide file tree
Showing 21 changed files with 278 additions and 103 deletions.
2 changes: 1 addition & 1 deletion packages/components/ovh-at-internet/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const AT_INTERNET_LEVEL2: Record<string, string> = {
86: 'Manager-PublicCloud',
87: 'Manager-Telecom',
88: 'Manager-Hub',
95: 'account-creation',
95: 'Manager-account-creation',
98: 'Manager-HostedPrivateCloud',
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { v6 } from '@ovh-ux/manager-core-api';
import { DefaultPublicCloudProjectPreference, Preference } from '@/types/preferences';

export const getDefaultPublicCloudProjectId = async () => {
try {
const { data } = await v6.get<Preference>('/me/preferences/manager/PUBLIC_CLOUD_DEFAULT_PROJECT');
const defaultProject: DefaultPublicCloudProjectPreference = data?.value ? JSON.parse(data.value) : null;
return defaultProject.projectId;
}
catch (e) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DefinedInitialDataOptions, useQuery } from '@tanstack/react-query';
import { getDefaultPublicCloudProjectId } from '@/container/nav-reshuffle/data/api/defaultPublicCloudProject';
import { PciProject } from '@/container/nav-reshuffle/sidebar/ProjectSelector/PciProject';

export const useDefaultPublicCloudProject = (options?: Partial<DefinedInitialDataOptions<string | null, unknown, PciProject>>) =>
useQuery({
...options,
queryKey: ['default-pci-project'],
queryFn: getDefaultPublicCloudProjectId,
retry: false,
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const SidebarLink: React.FC<ComponentProps<SidebarLinkProps>> = ({
/>
) : (
<button
className={style['button-as-div']}
className={`${style['button-as-div']} relative`}
title={t(node.translation)}
onKeyUp={(e) => {
if (e.key === 'Enter') {
Expand All @@ -61,11 +61,11 @@ const SidebarLink: React.FC<ComponentProps<SidebarLinkProps>> = ({
{!isShortText && <span>{t(node.translation)}</span>}
</span>
<span className="flex justify-end align-items-center">
{!isShortText && (count as number) > 0 && (
{(count as number) > 0 && (
<OsdsIcon
name={ODS_ICON_NAME.SHAPE_DOT}
size={ODS_ICON_SIZE.xs}
className={style.sidebarLinkTag}
className={`${style.sidebarLinkTag} ${isShortText ? 'absolute -top-1.5 right-2.5' : ''}`}
/>
)}
{!isShortText && node.children ? (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { vi, it, describe, expect } from 'vitest';
import { render } from '@testing-library/react';
import { render, waitFor } from '@testing-library/react';
import { Node } from '../navigation-tree/node';
import { PublicCloudPanel, PublicCloudPanelProps } from './PublicCloudPanel';
import { mockShell } from '../mocks/sidebarMocks';
import { PciProject } from '../ProjectSelector/PciProject';
import { Props as ProjectSelectorProps } from '../ProjectSelector/ProjectSelector';
import { pciNode } from '../navigation-tree/services/publicCloud';

const node: Node = {
Expand Down Expand Up @@ -53,22 +54,24 @@ vi.mock('@/context', () => ({

vi.mock('@tanstack/react-query', () => ({
useQuery: ({ queryKey }: { queryKey: Array<string> }) => {
return queryKey.includes('pci-projects')
? {
data: () => pciProjects,
isError: () => false,
isSuccess: () => true,
refetch: () => {},
}
: {
data: () => pciProjects[0],
status: () => 'success',
};
return {
data: pciProjects,
isError: false,
isSuccess: true,
refetch: () => {},
};
},
}));

vi.mock('@/container/nav-reshuffle/data/hooks/defaultPublicCloudProject/useDefaultPublicCloudProject', () => ({
useDefaultPublicCloudProject: () => ({
data: pciProjects[1],
status: 'success',
}),
}));

const location = {
pathname: '/pci/projects/12345/rancher',
pathname: '/public-cloud/pci/projects',
search: '',
};

Expand All @@ -77,12 +80,29 @@ vi.mock('react-router-dom', () => ({
}));

vi.mock('../ProjectSelector/ProjectSelector', () => ({
default: () => <div data-testid="public-cloud-panel-project-selector" />,
default: ({ selectedProject }: ProjectSelectorProps) => {
return (<div data-testid="public-cloud-panel-project-selector">{selectedProject?.project_id}</div>);
},
}));

describe('PublicCloudPanel.component', () => {
it('should render', () => {
const { queryByTestId } = renderPublicCloudPanelComponent(props);
expect(queryByTestId('public-cloud-panel')).not.toBeNull();
});

it('should display default project id in project selector when url does not contain an id', () => {
const { queryByTestId } = renderPublicCloudPanelComponent(props);
const projectSelector = queryByTestId('public-cloud-panel-project-selector');
expect(projectSelector).not.toBeNull();
expect(projectSelector.innerHTML).toBe('54321');
});

it('should display project id in project selector when url contains an id', () => {
location.pathname = '/public-cloud/pci/projects/12345/rancher';
const { queryByTestId } = renderPublicCloudPanelComponent(props);
const projectSelector = queryByTestId('public-cloud-panel-project-selector');
expect(projectSelector).not.toBeNull();
expect(projectSelector.innerHTML).toBe('12345');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { Location, useLocation } from 'react-router-dom';
import style from '../style.module.scss';
import SubTreeSection from '@/container/nav-reshuffle/sidebar/SubTree/SubTreeSection';
import { PUBLICCLOUD_UNIVERSE_ID } from '../navigation-tree/services/publicCloud';
import {
useDefaultPublicCloudProject
} from '@/container/nav-reshuffle/data/hooks/defaultPublicCloudProject/useDefaultPublicCloudProject';

export interface PublicCloudPanelProps {
rootNode: Node;
Expand Down Expand Up @@ -62,19 +65,14 @@ export const PublicCloudPanel: React.FC<ComponentProps<
},
});

const { data: defaultPciProject, status: defaultPciProjectStatus } = useQuery(
const { data: defaultPciProject, status: defaultPciProjectStatus } = useDefaultPublicCloudProject(
{
queryKey: ['default-pci-project'],
queryFn: () => {
return fetchIcebergV6<PciProject>({
route: '/me/preferences/manager/PUBLIC_CLOUD_DEFAULT_PROJECT',
});
select: (defaultProjectId: string | null): PciProject | null => {
return defaultProjectId !== null
? pciProjects?.find((project: PciProject) => project.project_id === defaultProjectId) || null
: null;
},
select: (response) => {
return response?.data?.length ? (response.data[0] as PciProject) : null;
},
enabled: rootNode.id === PUBLICCLOUD_UNIVERSE_ID && !selectedPciProject,
retry: false,
enabled: rootNode.id === PUBLICCLOUD_UNIVERSE_ID && !selectedPciProject && !pciProjects,
},
);

Expand Down Expand Up @@ -106,16 +104,16 @@ export const PublicCloudPanel: React.FC<ComponentProps<
if (project) {
setSelectedPciProject(project);
}
else {
if (defaultPciProject !== null) {
setSelectedPciProject(defaultPciProject);
}
else {
setSelectedPciProject(pciProjects[0]);
}
}
}
}, [pciProjects, rootNode, containerURL]);

useEffect(() => {
if (defaultPciProjectStatus === 'success') {
setSelectedPciProject(defaultPciProject);
} else if (defaultPciProjectStatus === 'error' && pciProjects?.length) {
setSelectedPciProject(pciProjects[0]);
}
}, [defaultPciProject, defaultPciProjectStatus, pciProjects]);
}, [rootNode, containerURL, pciProjects]);

useEffect(() => {
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ hostedPrivateCloudUniverse.children = [
tag: NodeTag.NEW,
routing: {
application: 'hycu',
hash: '',
hash: '#/',
},
features: ['hycu'],
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,8 @@ export const findNodeByRouting = (root: Node, locationPath: string) => {
const nodePath = node.routing.hash
? node.routing.hash.replace('#', node.routing.application)
: '/' + node.routing.application;
const parsedPath = splitPathIntoSegmentsWithoutRouteParams(nodePath);
const parsedPath = splitPathIntoSegmentsWithoutRouteParams(nodePath).map((path) => path.includes('/') ? path.replace('/', '') : path);

return {
value: parsedPath.reduce(
(acc: boolean, segment: string) => {
Expand Down
8 changes: 8 additions & 0 deletions packages/manager/apps/container/src/types/preferences.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export type Preference = {
key: string;
value: string;
}

export type DefaultPublicCloudProjectPreference = {
projectId: string;
}
5 changes: 1 addition & 4 deletions packages/manager/apps/sign-up/src/activity/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ export const state = {
trackError('step3', field),
},
atInternet: {
rename: /* @ngInject */ ($state) => {
const me = $state.transition.injector().get('me');
return `accountcreation-step3-${me.model.legalform}`;
},
ignore: true,
},
};

Expand Down
30 changes: 30 additions & 0 deletions packages/manager/apps/sign-up/src/at-internet.constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,36 @@ export const TRACKING = {
},
};

export const CHAPTER_1 = 'Authentication';
const CHAPTER_2 = 'account-creation';
const CHAPTER_3 = 'step3';

const BUTTON_TRACKING_SUFFIX = 'page::button';
export const BUTTON_TRACKING_PREFIX = `${CHAPTER_1}::${CHAPTER_2}::${CHAPTER_3}::${BUTTON_TRACKING_SUFFIX}`;

const DISPLAY_ROOT_PAGE_TRACKING_SUFFIX =
'account-creation-step3::fill-in_contact_details';
export const DISPLAY_ROOT_PAGE_TRACKING = `${CHAPTER_1}::${CHAPTER_2}::${CHAPTER_3}::${DISPLAY_ROOT_PAGE_TRACKING_SUFFIX}`;

const ERROR_TRACKING_SUFFIX = 'create_account_step::banner-error';
export const ERROR_TRACKING_PREFIX = `${CHAPTER_1}::${CHAPTER_2}::${CHAPTER_3}::${ERROR_TRACKING_SUFFIX}`;

const SUBMIT_FORM_TRACKING_SUFFIX =
'page::button::create_account_finalstep::confirmation';
export const SUBMIT_FORM_GOAL_TYPE = 'account-creation-finalstep';
export const SUBMIT_FORM_TRACKING_PREFIX = `${CHAPTER_1}::${CHAPTER_2}::${CHAPTER_3}::${SUBMIT_FORM_TRACKING_SUFFIX}`;

const REQUEST_RESULT_TRACKING_SUFFIX =
'account-creation-finalstep::banner-success';
export const REQUEST_RESULT_TRACKING_PREFIX = `${CHAPTER_1}::${CHAPTER_2}::validation::${REQUEST_RESULT_TRACKING_SUFFIX}`;

export default {
CHAPTER_1,
BUTTON_TRACKING_PREFIX,
DISPLAY_ROOT_PAGE_TRACKING,
ERROR_TRACKING_PREFIX,
REQUEST_RESULT_TRACKING_PREFIX,
SUBMIT_FORM_GOAL_TYPE,
SUBMIT_FORM_TRACKING_PREFIX,
TRACKING,
};
2 changes: 1 addition & 1 deletion packages/manager/apps/sign-up/src/details/routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const state = {
subsidiary === INDIAN_SUBSIDIARY,
},
atInternet: {
rename: 'accountcreation-step2',
ignore: true,
},
};

Expand Down
59 changes: 53 additions & 6 deletions packages/manager/apps/sign-up/src/form/form.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ import get from 'lodash/get';
import isFunction from 'lodash/isFunction';
import some from 'lodash/some';
import { INDIAN_SUBSIDIARY } from '../constants';
import {
BUTTON_TRACKING_PREFIX,
CHAPTER_1,
DISPLAY_ROOT_PAGE_TRACKING,
REQUEST_RESULT_TRACKING_PREFIX,
SUBMIT_FORM_GOAL_TYPE,
SUBMIT_FORM_TRACKING_PREFIX,
} from '../at-internet.constants';

export default class SignUpFormAppCtrl {
/* @ngInject */
Expand Down Expand Up @@ -62,40 +70,74 @@ export default class SignUpFormAppCtrl {
}

onStepFormCancel(step) {
this.atInternet.trackPage({
name: `accountcreation-step${step === 'details' ? '2' : '3'}-${
this.me.model.legalform
}::cancel`,
const hits = [
BUTTON_TRACKING_PREFIX,
`create_account_step${step === 'details' ? '3' : '4'}`,
'cancel',
`${this.me.model.legalform}_${this.me.ovhSubsidiary}`,
];
this.atInternet.trackClick({
name: hits.join('::'),
type: 'action',
page_category: CHAPTER_1,
page: {
name: DISPLAY_ROOT_PAGE_TRACKING,
},
});
return this.cancelStep(step);
}

onStepperFinished() {
this.saveError = null;
const hits = [
SUBMIT_FORM_TRACKING_PREFIX,
`${this.me.model.legalform}_${this.me.ovhSubsidiary}`,
];

const tracking = {
name: `accountcreation-ok-${this.me.model.legalform}`,
name: hits.join('::'),
type: 'action',
goalType: SUBMIT_FORM_GOAL_TYPE,
accountcreationSiretProvided: this.me.model
.companyNationalIdentificationNumber
? 'Provided'
: '',
page_category: CHAPTER_1,
page: {
name: DISPLAY_ROOT_PAGE_TRACKING,
},
};

if (this.isSmsConsentAvailable) {
tracking.accountSmsConsent = this.smsConsent ? 'opt-in' : 'opt-out';
tracking.accountPhoneType = this.me.model.phoneType;
}

this.atInternet.trackPage(tracking);
this.atInternet.trackClick(tracking);

// call to finishSignUp binding
if (isFunction(this.finishSignUp)) {
const getTrackingHits = (status) => [
REQUEST_RESULT_TRACKING_PREFIX,
`confirmation_${status}`, // 'success' | 'error'
`${this.me.model.legalform}_${this.me.ovhSubsidiary}`,
];
return this.finishSignUp(this.smsConsent)
.then(() => {
this.atInternet.trackPage({
name: getTrackingHits('success').join('::'),
page_category: 'banner',
goalType: 'account-creation-finalstep',
});
if (this.needkyc) this.goToKycDocumentUploadPage();
})
.catch((error) => {
this.saveError = error;
this.atInternet.trackPage({
name: getTrackingHits('error').join('::'),
page_category: 'banner',
goalType: 'account-creation-finalstep',
});
});
}
if (this.needkyc) {
Expand All @@ -116,5 +158,10 @@ export default class SignUpFormAppCtrl {
if (this.me.state === 'incomplete') {
this.me.legalform = null;
}

this.atInternet.trackPage({
name: DISPLAY_ROOT_PAGE_TRACKING,
page_category: CHAPTER_1,
});
}
}
Loading

0 comments on commit 28605bf

Please sign in to comment.