- added cache faq items;

- added terms pdf;
- added redirect to 'add company' for new users;
This commit is contained in:
Vitalii Kiiko
2024-10-11 12:51:15 +02:00
parent 8fb1551880
commit bd64a34347
26 changed files with 168 additions and 36 deletions

View File

@@ -2,10 +2,10 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<link rel="icon" href="%PUBLIC_URL%/favicon.ico"/> <link rel="icon" href="%PUBLIC_URL%/loaded-files/favicon.ico"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="description" content="Gepafin"/> <meta name="description" content="Gepafin"/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png"/> <link rel="apple-touch-icon" href="%PUBLIC_URL%/loaded-files/logo.svg"/>
<link rel="manifest" href="%PUBLIC_URL%/manifest.json"/> <link rel="manifest" href="%PUBLIC_URL%/manifest.json"/>
<title>%REACT_APP_TAB_TITLE%</title> <title>%REACT_APP_TAB_TITLE%</title>
</head> </head>

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

View File

@@ -8,13 +8,13 @@
"type": "image/x-icon" "type": "image/x-icon"
}, },
{ {
"src": "logo192.png", "src": "logo.svg",
"type": "image/png", "type": "image/svg+xml",
"sizes": "192x192" "sizes": "192x192"
}, },
{ {
"src": "logo512.png", "src": "logo.svg",
"type": "image/png", "type": "image/svg+xml",
"sizes": "512x512" "sizes": "512x512"
} }
], ],

View File

@@ -4,7 +4,7 @@ import Routes from './routes';
import { createI18n, setLocaleData } from '@wordpress/i18n'; import { createI18n, setLocaleData } from '@wordpress/i18n';
import { I18nProvider } from '@wordpress/react-i18n'; import { I18nProvider } from '@wordpress/react-i18n';
import './assets/scss/theme.scss'; import './assets/scss/theme.scss';
import { isEmpty } from 'ramda' import { isEmpty, head } from 'ramda'
// store // store
import { useStore, storeSet, storeGet } from './store'; import { useStore, storeSet, storeGet } from './store';
@@ -17,6 +17,7 @@ const i18n = createI18n({}, 'gepafin');
function App() { function App() {
const role = useStore().main.getRole(); const role = useStore().main.getRole();
const chosenCompanyId = useStore().main.chosenCompanyId(); const chosenCompanyId = useStore().main.chosenCompanyId();
const isRedirectedOnceNoCompany = useStore().main.isRedirectedOnceNoCompany();
const callback = (data) => { const callback = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
@@ -36,9 +37,23 @@ function App() {
const userData = storeGet.main.userData(); const userData = storeGet.main.userData();
if (userData.companies && !isEmpty(userData.companies)) { if (userData.companies && !isEmpty(userData.companies)) {
storeSet.main.companies(userData.companies); storeSet.main.companies(userData.companies);
const company = head(userData.companies.filter(o => o.id === chosenCompanyId));
if (!company) {
storeSet.main.chosenCompanyId(userData.companies[0].id);
}
} else {
storeSet.main.chosenCompanyId(0);
const { origin, href } = window.location;
const url = `${origin}/agguingi-azienda`;
if (!isRedirectedOnceNoCompany && url !== href) {
storeSet.main.isRedirectedOnceNoCompany(true);
window.location.replace('/agguingi-azienda')
} }
} }
}, [role]) }
}, [role]);
useEffect(() => { useEffect(() => {
storeSet.main.setAsyncRequest(); storeSet.main.setAsyncRequest();

View File

@@ -25,6 +25,15 @@ body {
flex-grow: 1; flex-grow: 1;
} }
iframe {
width: 100%;
height: 100%;
}
img {
max-width: 100%;
}
.inner { .inner {
display: flex; display: flex;
height: 100%; height: 100%;

View File

@@ -27,6 +27,7 @@ const Switch = ({
rules={config} rules={config}
render={({ field, fieldState }) => ( render={({ field, fieldState }) => (
<InputSwitch <InputSwitch
inputId={fieldName}
checked={field.value} checked={field.value}
disabled={disabled} disabled={disabled}
onChange={(e) => field.onChange(e.value)} onChange={(e) => field.onChange(e.value)}

View File

@@ -86,6 +86,7 @@ const TopBarProfileMenu = ({ menuLeftRef }) => {
const switchCompany = (id) => { const switchCompany = (id) => {
if (chosenCompanyId !== id) { if (chosenCompanyId !== id) {
storeSet.main.chosenCompanyId(id); storeSet.main.chosenCompanyId(id);
console.log('set company 2', id)
if (toast.current) { if (toast.current) {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',

View File

@@ -5,7 +5,10 @@ export const mimeTypes = [
{ name: 'Immagine', code: 'image/*' }, { name: 'Immagine', code: 'image/*' },
{ {
name: 'Word', name: 'Word',
code: 'application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document' code: '.doc,.docx,.odt,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document,application/vnd.oasis.opendocument.text'
}, },
{ name: 'Excel doc', code: 'application/vnd.ms-excel' } {
name: 'Excel',
code: '.xls,.xlsx,.ods,application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet'
}
]; ];

View File

@@ -75,6 +75,7 @@ const AddCompany = () => {
} else { } else {
newCompanies = [...companies, company]; newCompanies = [...companies, company];
storeSet.main.chosenCompanyId(company.id); storeSet.main.chosenCompanyId(company.id);
console.log('set company 1', company.id)
} }
storeSet.main.companies(newCompanies); storeSet.main.companies(newCompanies);

View File

@@ -140,7 +140,8 @@ const AllBandiTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} <Column field="name" header={__('Nome Bando', 'gepafin')}
filter filterPlaceholder={__('Cerca', 'gepafin')} filter filterPlaceholder={__('Cerca', 'gepafin')}
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>

View File

@@ -126,8 +126,13 @@ const AllBandiAccordion = () => {
return( return(
<div className="appPageSection__table"> <div className="appPageSection__table">
<DataTable value={items} paginator rows={10} loading={isAsyncRequest} dataKey="id" <DataTable value={items}
filters={filters} emptyMessage="Nothing found." paginator
rows={10}
loading={isAsyncRequest}
dataKey="id"
filters={filters}
emptyMessage={__('Nessun dato disponibile', 'gepafin')}
expandedRows={expandedRows} expandedRows={expandedRows}
onRowToggle={(e) => setExpandedRows(e.data)} onRowToggle={(e) => setExpandedRows(e.data)}
rowExpansionTemplate={rowExpansionTemplate} rowExpansionTemplate={rowExpansionTemplate}

View File

@@ -42,7 +42,7 @@ const ElementSetting = ({ setting, changeFn, updateDataFn }) => {
}; };
const header = renderHeader(); const header = renderHeader();
console.log('setting', setting)
const getProperField = (setting) => { const getProperField = (setting) => {
if (setting.name === 'options') { if (setting.name === 'options') {
return <ElementSettingRepeater return <ElementSettingRepeater

View File

@@ -112,19 +112,6 @@ const BandoViewBeneficiario = () => {
const createCallBack = (data) => { const createCallBack = (data) => {
if (data.status === 'SUCCESS') { if (data.status === 'SUCCESS') {
setNewQuestion(''); setNewQuestion('');
/*if (bandoMsgs.current && data.message) {
bandoMsgs.current.show([
{
sticky: true, severity: 'success', summary: '',
detail: data.message,
closable: true
}
]);
setTimeout(() => {
bandoMsgs.current.clear();
}, 5000);
}*/
if (toast.current) { if (toast.current) {
toast.current.show({ toast.current.show({
severity: 'success', severity: 'success',
@@ -355,7 +342,7 @@ const BandoViewBeneficiario = () => {
label={__('Salva', 'gepafin')}/> label={__('Salva', 'gepafin')}/>
</div> </div>
{chosenCompanyId === 0 {!chosenCompanyId || chosenCompanyId === 0
? <> ? <>
<Message severity="error" <Message severity="error"
text={__('Devi creare un\'azienda prima di partecipare nei bandi. Vai nel profilo aziendale.', 'gepafin')}/> text={__('Devi creare un\'azienda prima di partecipare nei bandi. Vai nel profilo aziendale.', 'gepafin')}/>

View File

@@ -183,7 +183,8 @@ const LatestBandiTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name"
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date" <Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"

View File

@@ -107,7 +107,8 @@ const LatestUsersActivityTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column header={__('Timestamp', 'gepafin')} filterField="date" dataType="date" <Column header={__('Timestamp', 'gepafin')} filterField="date" dataType="date"
style={{ minWidth: '10rem' }} style={{ minWidth: '10rem' }}
body={dateBodyTemplate} filter filterElement={dateFilterTemplate}/> body={dateBodyTemplate} filter filterElement={dateFilterTemplate}/>

View File

@@ -151,7 +151,8 @@ const LatestBandiTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="name" header={__('Nome Bando', 'gepafin')} filter filterPlaceholder="Search by name"
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date" <Column header={__('Data Pubblicazione', 'gepafin')} filterField="start_date" dataType="date"

View File

@@ -166,7 +166,8 @@ const MyLatestSubmissionsTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="callTitle" header={__('Bando', 'gepafin')} filter filterPlaceholder="Search by name"
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date" <Column header={__('Scadenza', 'gepafin')} filterField="callEndDate" dataType="date"

View File

@@ -6,11 +6,16 @@ import { isEmpty, isNil } from 'ramda';
// store // store
import { storeSet, useStore } from '../../store'; import { storeSet, useStore } from '../../store';
// api
import AuthenticationService from '../../service/authentication-service';
// components // components
import LogoIcon from '../../icons/LogoIcon'; import LogoIcon from '../../icons/LogoIcon';
import { Messages } from 'primereact/messages'; import { Messages } from 'primereact/messages';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import AuthenticationService from '../../service/authentication-service'; import { Dialog } from 'primereact/dialog';
import { Accordion } from 'primereact/accordion';
import { AccordionTab } from 'primereact/accordion';
const API_BASE_URL = process.env.REACT_APP_API_ADDRESS; const API_BASE_URL = process.env.REACT_APP_API_ADDRESS;
@@ -18,7 +23,9 @@ const Login = () => {
const token = useStore().main.token(); const token = useStore().main.token();
const errorMsgs = useRef(null); const errorMsgs = useRef(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [visibleCacheFaq, setVisibleCacheFaq] = useState(false);
let [searchParams] = useSearchParams(); let [searchParams] = useSearchParams();
const { origin } = window.location;
const loginWithSpid = () => { const loginWithSpid = () => {
if (!loading) { if (!loading) {
@@ -56,6 +63,15 @@ const Login = () => {
setLoading(false); setLoading(false);
} }
const openCacheFaq = (e) => {
e.preventDefault();
setVisibleCacheFaq(true);
}
const hideCacheFaq = () => {
setVisibleCacheFaq(false);
}
useEffect(() => { useEffect(() => {
if (!isEmpty(token)) { if (!isEmpty(token)) {
window.location.replace('/') window.location.replace('/')
@@ -104,6 +120,72 @@ const Login = () => {
<span>{__('Entra con SPID', 'gepafin')}</span> <span>{__('Entra con SPID', 'gepafin')}</span>
</button> </button>
<div className="appPage__spacer"></div>
<p><a href={origin} onClick={openCacheFaq}>{__('Hai problemi di accesso con SPID?', 'gepafin')}</a></p>
<Dialog header={__('Termini e condizioni', 'gepafin')} visible={visibleCacheFaq} style={{
width: '70vw',
minHeight: 500
}} onHide={hideCacheFaq}>
<p>
{__('Se rilevi problemi di accesso allo sportello telematico utilizzando le tue credenziali SPID, solitamente si tratta di un esaurimento dello spazio dedicato alla cache, cioè linsieme dei dati che i software salvano sul browser per rendere il caricamento di determinate pagine internet più rapido.', 'gepafin')}
</p>
<Accordion>
<AccordionTab header={__('Come svuotare la cache su Google Chrome', 'gepafin')}>
<p>Se solitamente navighi in internet utilizzando Google Chrome, per svuotare la cache
devi:</p>
<ul>
<li>cliccare sui tre puntini verticali in alto a destra
</li>
<li>selezionare la voce Impostazioni</li>
<li>accedere al menu Privacy e sicurezza > Cancella dati di navigazione</li>
<li>selezionare la voce Immagini e file memorizzati nella cache e poi premere sul
pulsante Cancella dati.
</li>
</ul>
<img src={`${origin}/loaded-files/empty-cache-chrome.png`}
alt={__('Come svuotare la cache su Google Chrome', 'gepafin')}/>
</AccordionTab>
<AccordionTab header={__('Come svuotare la cache su Mozilla Firefox', 'gepafin')}>
<p>Se solitamente navighi in internet utilizzando Mozilla Firefox, per svuotare la cache
devi:</p>
<ul>
<li>cliccare sulle tre linee orizzontali in alto a destra</li>
<li>selezionare la voce Impostazioni</li>
<li>accedere al menu Privacy e sicurezza > Cookie e dati dei siti web > Elimina
dati...
</li>
<li>selezionare la voce Contenuti web in cache e poi premere sul pulsante Elimina.</li>
</ul>
<img src={`${origin}/loaded-files/empty-cache-firefox.png`}
alt={__('Come svuotare la cache su Mozilla Firefox', 'gepafin')}/>
</AccordionTab>
<AccordionTab header={__('Come svuotare la cache su Microsoft Edge', 'gepafin')}>
<p>Se solitamente navighi in internet utilizzando Microsoft Edge, per svuotare la cache
devi:</p>
<ul>
<li>cliccare sui tre puntini orizzontali in alto a destra</li>
<li>selezionare la voce Impostazioni</li>
<li>accedere al menu Privacy, ricerca e servizi > Cancella i dati di navigazione >
Scegli cosa cancellare
</li>
<li>selezionare la voce Immagini e file memorizzati nella cache e poi premere sul
pulsante Cancella ora.
</li>
</ul>
<img src={`${origin}/loaded-files/empty-cache-edge.png`}
alt={__('Come svuotare la cache su Microsoft Edge', 'gepafin')}/>
</AccordionTab>
</Accordion>
</Dialog>
</div> </div>
</div> </div>
) )

View File

@@ -82,6 +82,7 @@ const ProfileCompany = () => {
} else { } else {
newCompanies = [...companies, company]; newCompanies = [...companies, company];
storeSet.main.chosenCompanyId(company.id); storeSet.main.chosenCompanyId(company.id);
console.log('set company 3', company.id)
} }
storeSet.main.companies(newCompanies); storeSet.main.companies(newCompanies);

View File

@@ -20,10 +20,12 @@ import LogoIcon from '../../icons/LogoIcon';
import { Button } from 'primereact/button'; import { Button } from 'primereact/button';
import { Messages } from 'primereact/messages'; import { Messages } from 'primereact/messages';
import { Panel } from 'primereact/panel'; import { Panel } from 'primereact/panel';
import { Dialog } from 'primereact/dialog';
const Registration = () => { const Registration = () => {
const token = useStore().main.token(); const token = useStore().main.token();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [visibleTerms, setVisibleTerms] = useState(false);
const errorMsgs = useRef(null); const errorMsgs = useRef(null);
let [searchParams] = useSearchParams(); let [searchParams] = useSearchParams();
const { const {
@@ -34,6 +36,8 @@ const Registration = () => {
getValues getValues
} = useForm({ mode: 'onChange' }); } = useForm({ mode: 'onChange' });
const values = getValues(); const values = getValues();
const { origin } = window.location;
const urlTermsPdf = `${origin}/loaded-files/termini-e-condizioni.pdf`;
const onSubmit = (formData) => { const onSubmit = (formData) => {
errorMsgs.current.clear(); errorMsgs.current.clear();
@@ -117,6 +121,15 @@ const Registration = () => {
setValue('thirdParty', true); setValue('thirdParty', true);
} }
const openTermsDoc = (e) => {
e.preventDefault();
setVisibleTerms(true);
}
const hideTerms = () => {
setVisibleTerms(false);
}
useEffect(() => { useEffect(() => {
if (!isEmpty(token)) { if (!isEmpty(token)) {
setLoading(true); setLoading(true);
@@ -279,7 +292,7 @@ const Registration = () => {
}} }}
toggleable> toggleable>
<p className="m-0"> <p className="m-0">
{__('Termini e condizioni', 'gepafin')} <a href={urlTermsPdf} onClick={openTermsDoc}>{__('Termini e condizioni', 'gepafin')}</a>
</p> </p>
</Panel> </Panel>
@@ -350,9 +363,16 @@ const Registration = () => {
</Panel> </Panel>
<Button <Button
label={__('Accedi', 'gepafin')} label={__('Invia', 'gepafin')}
disabled={loading}/> disabled={loading}/>
</form> </form>
<Dialog header={__('Termini e condizioni', 'gepafin')} visible={visibleTerms} style={{
width: '70vw',
minHeight: 500
}} onHide={hideTerms}>
<iframe src={urlTermsPdf} title={__('Termini e condizioni', 'gepafin')}></iframe>
</Dialog>
</div> </div>
</div> </div>
) )

View File

@@ -150,7 +150,8 @@ const AllUsersTable = () => {
filters={filters} filters={filters}
globalFilterFields={['name', 'status']} globalFilterFields={['name', 'status']}
header={header} header={header}
emptyMessage="Nothing found." onFilter={(e) => setFilters(e.filters)}> emptyMessage={__('Nessun dato disponibile', 'gepafin')}
onFilter={(e) => setFilters(e.filters)}>
<Column field="name" header={__('Nome utente', 'gepafin')} filter filterPlaceholder="Search by name" <Column field="name" header={__('Nome utente', 'gepafin')} filter filterPlaceholder="Search by name"
style={{ minWidth: '12rem' }}/> style={{ minWidth: '12rem' }}/>
<Column field="email" header={__('Email', 'gepafin')} filter filterPlaceholder="Search by email" <Column field="email" header={__('Email', 'gepafin')} filter filterPlaceholder="Search by email"

View File

@@ -2,6 +2,7 @@ const initialStore = {
// ui related // ui related
isAsyncRequest: 0, // number isAsyncRequest: 0, // number
isError404: false, isError404: false,
isRedirectedOnceNoCompany: false,
// user // user
userData: {}, userData: {},
token: '', token: '',