Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
[#169647021] added registration page 3
Browse files Browse the repository at this point in the history
added translations for page 3
moved token setting and user profile api call to DefaultContainer (as token and profile info are used in every child component of DefaultContainer)
added registration step 3
added integration with get documents api
moved loading page to default container (as it is used only after login)
added new env variable to api env file
  • Loading branch information
d-al-ibm committed Nov 13, 2019
1 parent 802e1fb commit 03840d0
Show file tree
Hide file tree
Showing 8 changed files with 651 additions and 381 deletions.
3 changes: 2 additions & 1 deletion .env.io-onboarding-pa-api.development
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ SAML_KEY_PATH=./certs/key.pem
SPID_AUTOLOGIN=
SPID_TESTENV_URL=http://localhost:8088
IDP_METADATA_URL=https://registry.spid.gov.it/metadata/idp/spid-entities-idps.xml
TOKEN_DURATION_IN_SECONDS=60
TOKEN_DURATION_IN_SECONDS=3600
INDICEPA_ADMINISTRATIONS_URL=https://raw.githubusercontent.com/teamdigitale/io-onboarding-pa-api/master/development-data/administrations.txt

EMAIL_PASSWORD=password
EMAIL_USER=portaleonboarding@gmail.com
Expand Down
12 changes: 12 additions & 0 deletions locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ translation:
logout: "Logout"
change: "Modifica"
skip: "Salta questo passaggio"
viewDocument: "Visualizza documento"
user:
roles:
delegate: "Delegato Ente"
Expand Down Expand Up @@ -109,6 +110,17 @@ translation:
fcPlaceholder: "Inserisci il CF personale del legale rappresentante"
phoneLabel: "Numero di telefono dell'ufficio del Legale Rappresentante"
phonePlaceholder: "Inserisci il numero di telefono dell'ufficio"
stepThree:
title: "Verifica e invio documenti legali"
description: "Visualizza i documenti creati e, se tutte le informazioni sono corrette, procedi all’invio della documentazione al tuo Legale Rappresentante e alla società PagoPA SpA."
additionalDescription: "Il Legale Rappresentante riceverà i documenti via PEC, dovrà procedere alla firma digitale degli stessi e inviarli nuovamente a PagoPA SpA per verifica, seguendo le istruzioni contenute nella mail."
contract:
title: "Accordo ente/PagoPA SpA"
description: "Questo documento viene generato una sola volta alla creazione di ogni profilo ente. Verificane la correttezza prima di procedere con la creazione del profilo ente."
mandate:
title: "Delega gestione profilo dell’ente su IO"
description: "Questo documento è la tua delega personale alla gestione del profilo digitale dell’ente. Ogni tuo collega che richieda una delega dovrà generare il proprio documento al primo accesso. Verificane la correttezza prima di procedere con la creazione del profilo ente."
checkboxLabel: "Confermo che le informazioni nei documenti sono complete e corrette"
userProfile:
title: "Il tuo profilo"
spidInfo:
Expand Down
12 changes: 12 additions & 0 deletions locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ translation:
logout: "Logout"
change: "Modifica"
skip: "Salta questo passaggio"
viewDocument: "Visualizza documento"
user:
roles:
delegate: "Delegato Ente"
Expand Down Expand Up @@ -109,6 +110,17 @@ translation:
fcPlaceholder: "Inserisci il CF personale del legale rappresentante"
phoneLabel: "Numero di telefono dell'ufficio del Legale Rappresentante"
phonePlaceholder: "Inserisci il numero di telefono dell'ufficio"
stepThree:
title: "Verifica e invio documenti legali"
description: "Visualizza i documenti creati e, se tutte le informazioni sono corrette, procedi all’invio della documentazione al tuo Legale Rappresentante e alla società PagoPA SpA."
additionalDescription: "Il Legale Rappresentante riceverà i documenti via PEC, dovrà procedere alla firma digitale degli stessi e inviarli nuovamente a PagoPA SpA per verifica, seguendo le istruzioni contenute nella mail."
contract:
title: "Accordo ente/PagoPA SpA"
description: "Questo documento viene generato una sola volta alla creazione di ogni profilo ente. Verificane la correttezza prima di procedere con la creazione del profilo ente."
mandate:
title: "Delega gestione profilo dell’ente su IO"
description: "Questo documento è la tua delega personale alla gestione del profilo digitale dell’ente. Ogni tuo collega che richieda una delega dovrà generare il proprio documento al primo accesso. Verificane la correttezza prima di procedere con la creazione del profilo ente."
checkboxLabel: "Confermo che le informazioni nei documenti sono complete e corrette"
userProfile:
title: "Il tuo profilo"
spidInfo:
Expand Down
19 changes: 6 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
import React, { useContext } from "react";
import React from "react";
import { BrowserRouter, Redirect, Route, Switch } from "react-router-dom";
import { DefaultContainer } from "./components/DefaultContainer/DefaultContainer";
import { Home } from "./components/Home/Home";
import { LoadingPage } from "./components/LoadingPage/LoadingPage";
import { ScrollToTop } from "./components/ScrollToTop";

import "../node_modules/bootstrap-italia/dist/css/bootstrap-italia.min.css";
import "./App.scss";
import { LoadingPageContext } from "./context/loading-page-context";

/**
* Entry point for app, with first level routing
*/
export const App = () => {
const redirectToHome = () => <Redirect to="/home" />;

const loadingPageContext = useContext(LoadingPageContext);

return (
<BrowserRouter>
<ScrollToTop>
<div className="App vh-100">
{!loadingPageContext.loadingPage.isVisible ? (
<Switch>
<Route exact={true} path="/" component={redirectToHome} />
<Route path="/home" component={Home} />
<Route path="/*" component={DefaultContainer} />
</Switch>
) : null}
{loadingPageContext.loadingPage.isVisible ? <LoadingPage /> : null}
<Switch>
<Route exact={true} path="/" component={redirectToHome} />
<Route path="/home" component={Home} />
<Route path="/*" component={DefaultContainer} />
</Switch>
</div>
</ScrollToTop>
</BrowserRouter>
Expand Down
95 changes: 3 additions & 92 deletions src/components/Dashboard/Dashboard.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,11 @@
import { NonEmptyString } from "italia-ts-commons/lib/strings";
import React, { useContext, useEffect } from "react";
import { RouteComponentProps, withRouter } from "react-router";
import React from "react";
import { withRouter } from "react-router";
import { Button, Col, Row } from "reactstrap";
import { EmailAddress } from "../../../generated/definitions/api/EmailAddress";
import { UserProfile } from "../../../generated/definitions/api/UserProfile";
import { TokenContext } from "../../context/token-context";
import { ICustomWindow } from "../../customTypes/CustomWindow";

interface IDashboardProps extends RouteComponentProps {
onGetUserProfile: (userProfile: UserProfile) => void;
spidMail: string;
onWorkMailSet: (newWorkMail: EmailAddress) => void;
toggleAddMailModal: () => void;
}

/**
* Component for delegate dashboard
*/
export const Dashboard = withRouter((props: IDashboardProps) => {
const tokenContext = useContext(TokenContext);

/**
* Create window with custom element _env_ for environment variables
*/
const customWindow = (window as unknown) as ICustomWindow;

/**
* Given a cookie key `cookieName`, returns the value of
* the cookie or empty string, if the key is not found.
*/
function getCookie(cookieName: string): string {
return (
document.cookie
.split(";")
.map(c => c.trim())
.filter(cookie => {
return (
cookie.substring(0, cookieName.length + 1) === `${cookieName}=`
);
})
.map(cookie => {
return decodeURIComponent(cookie.substring(cookieName.length + 1));
})[0] || ""
);
}

/**
* Set token in token context
*/
useEffect(() => {
const token = getCookie("sessionToken");
if (
NonEmptyString.is(token) ||
customWindow._env_.IO_ONBOARDING_PA_IS_MOCK_ENV === "1"
) {
tokenContext.setToken(token);
}
// if getCookie returns an empty string, it means the token has expired and user browser deleted it -> redirect user to login
// TODO: when available, redirect to logout page (tracked in story https://www.pivotaltracker.com/story/show/169033467)
else {
props.history.push("/home");
}
}, []);

useEffect(() => {
// make api call only after onMount -> token to string in any case, no longer undefined
if (tokenContext.token !== undefined) {
const url =
customWindow._env_.IO_ONBOARDING_PA_API_HOST +
":" +
customWindow._env_.IO_ONBOARDING_PA_API_PORT +
"/profile";
fetch(url, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${tokenContext.token}`
// 'Content-Type': 'application/json'
},
method: "GET"
})
.then(response => {
return response.json();
})
.then(responseData => {
props.onGetUserProfile(responseData);
if (!responseData.work_email) {
props.toggleAddMailModal();
}
})
.catch(error => {
// TODO: manage error in promise, tracked with story #169033467
return error;
});
}
}, [tokenContext.token]);

export const Dashboard = withRouter(props => {
/**
* Navigate to signup page
*/
Expand Down
132 changes: 112 additions & 20 deletions src/components/DefaultContainer/DefaultContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import React, { useState } from "react";
import { Route, RouteComponentProps } from "react-router";
import { NonEmptyString } from "italia-ts-commons/lib/strings";
import React, { Fragment, useContext, useEffect, useState } from "react";
import { Route, RouteComponentProps, withRouter } from "react-router";
import { EmailAddress } from "../../../generated/definitions/api/EmailAddress";
import { FiscalCode } from "../../../generated/definitions/api/FiscalCode";
import { UserProfile } from "../../../generated/definitions/api/UserProfile";
import { UserRole } from "../../../generated/definitions/api/UserRole";
import { LoadingPageContext } from "../../context/loading-page-context";
import { TokenContext } from "../../context/token-context";
import { ICustomWindow } from "../../customTypes/CustomWindow";
import { AppAlert } from "../AppAlert/AppAlert";
import { CentralHeader } from "../CentralHeader/CentralHeader";
import { Dashboard } from "../Dashboard/Dashboard";
import { LoadingPage } from "../LoadingPage/LoadingPage";
import { AddMailModal } from "../Modal/AddMailModal";
import { RegistrationContainer } from "../Registration/RegistrationContainer";
import { SlimHeader } from "../SlimHeader/SlimHeader";
Expand All @@ -28,7 +33,16 @@ interface IDefaultContainerUserProfileState {
/**
* Component containing slim header, central header and app body with second level routing
*/
export const DefaultContainer = () => {
export const DefaultContainer = withRouter(props => {
const tokenContext = useContext(TokenContext);

const loadingPageContext = useContext(LoadingPageContext);

/**
* Create window with custom element _env_ for environment variables
*/
const customWindow = (window as unknown) as ICustomWindow;

/**
* Initial state for user profile
*/
Expand Down Expand Up @@ -70,40 +84,117 @@ export const DefaultContainer = () => {
setIsVisibleAddMailModal((prevState: boolean) => !prevState);
};

const navigateToDashboard = (props: RouteComponentProps) => (
<Dashboard
{...props}
onGetUserProfile={handleGetUserProfile}
spidMail={userProfile.email}
onWorkMailSet={handleWorkMailSet}
toggleAddMailModal={toggleAddMailModal}
/**
* Given a cookie key `cookieName`, returns the value of
* the cookie or empty string, if the key is not found.
*/
function getCookie(cookieName: string): string {
return (
document.cookie
.split(";")
.map(c => c.trim())
.filter(cookie => {
return (
cookie.substring(0, cookieName.length + 1) === `${cookieName}=`
);
})
.map(cookie => {
return decodeURIComponent(cookie.substring(cookieName.length + 1));
})[0] || ""
);
}

/**
* Set token in token context
*/
useEffect(() => {
const token = getCookie("sessionToken");
// if getCookie returns an empty string and the user is not in pre login page (where token still has to be set),
// it means the token has expired and user browser deleted it -> redirect user to login, otherwise set tokenContext.token
if (
NonEmptyString.is(token) ||
location.pathname === "/spid-login" ||
customWindow._env_.IO_ONBOARDING_PA_IS_MOCK_ENV === "1"
) {
tokenContext.setToken(token);
}
// TODO: when available, redirect to logout page (tracked in story https://www.pivotaltracker.com/story/show/169033467)
else {
props.history.push("/home");
}
}, [location.pathname]);

useEffect(() => {
// make api call only after onMount because token is string in any case, no longer undefined, and only if userProfile is not set and user is not on spid login page
if (
NonEmptyString.is(tokenContext.token) &&
!NonEmptyString.is(userProfile.given_name) &&
location.pathname !== "/spid-login"
) {
const url =
customWindow._env_.IO_ONBOARDING_PA_API_HOST +
":" +
customWindow._env_.IO_ONBOARDING_PA_API_PORT +
"/profile";
fetch(url, {
headers: {
Accept: "application/json",
Authorization: `Bearer ${tokenContext.token}`
// 'Content-Type': 'application/json'
},
method: "GET"
})
.then(response => {
return response.json();
})
.then(responseData => {
handleGetUserProfile(responseData);
if (!responseData.work_email) {
toggleAddMailModal();
}
})
.catch(error => {
// TODO: manage error in promise, tracked with story #169033467
return error;
});
}
}, [tokenContext.token]);

const navigateToRegistration = (registrationProps: RouteComponentProps) => (
<RegistrationContainer
{...registrationProps}
userFiscalCode={userProfile.fiscal_code}
/>
);

const navigateToUserProfile = (props: RouteComponentProps) => (
const navigateToUserProfile = (userProfileProps: RouteComponentProps) => (
<UserProfileComponent
{...props}
{...userProfileProps}
userProfile={userProfile}
toggleAddMailModal={toggleAddMailModal}
/>
);

return (
<div className="DefaultContainer">
<SlimHeader />
<CentralHeader
userName={`${userProfile.given_name} ${userProfile.family_name}`}
userRole={userProfile.role}
/>
{!loadingPageContext.loadingPage.isVisible ? (
<Fragment>
<SlimHeader />
<CentralHeader
userName={`${userProfile.given_name} ${userProfile.family_name}`}
userRole={userProfile.role}
/>
</Fragment>
) : null}
<div>
<AppAlert />
<Route path="/spid-login" component={SpidLogin} />
<Route
path="/sign-up/:signUpStep"
exact={true}
component={RegistrationContainer}
render={navigateToRegistration}
/>
<Route path="/dashboard" render={navigateToDashboard} />
<Route path="/dashboard" component={Dashboard} />
<Route path="/profile" render={navigateToUserProfile} />
</div>
<AddMailModal
Expand All @@ -113,6 +204,7 @@ export const DefaultContainer = () => {
workMail={userProfile.work_email}
onWorkMailSet={handleWorkMailSet}
/>
{loadingPageContext.loadingPage.isVisible ? <LoadingPage /> : null}
</div>
);
};
});
Loading

0 comments on commit 03840d0

Please sign in to comment.