mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
linted supporting-documents/*
This commit is contained in:
parent
4d6af2c1c0
commit
7f1cc92c43
@ -50,11 +50,11 @@
|
||||
"files": ["app/frontend/src/javascript/components/**/*.tsx"],
|
||||
"rules": {
|
||||
"import/no-default-export": "error",
|
||||
"import/no-unused-modules": ["error", { "missingExports": true }],
|
||||
"import/no-unused-modules": "error",
|
||||
"fabmanager/component-class-named-as-component": ["error", { "ignoreAbstractKeyword": true }],
|
||||
"fabmanager/component-named-like-file": "error",
|
||||
"fabmanager/component-documentation": "error",
|
||||
"fabmanager/component-methods-documentation": "error",
|
||||
"fabmanager/component-documentation": "warn",
|
||||
"fabmanager/component-methods-documentation": "warn",
|
||||
"fabmanager/no-bootstrap": "error",
|
||||
"fabmanager/no-utilities": "error",
|
||||
"fabmanager/scoped-translation": ["error", { "ignoreAbstractKeyword": false }]
|
||||
|
26
app/frontend/src/javascript/components/base/fab-panel.tsx
Normal file
26
app/frontend/src/javascript/components/base/fab-panel.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
interface FabPanelProps {
|
||||
className?: string,
|
||||
header?: ReactNode,
|
||||
size?: 'small' | 'normal'
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple styled panel component
|
||||
*/
|
||||
export const FabPanel: React.FC<FabPanelProps> = ({ className, header, size, children }) => {
|
||||
return (
|
||||
<div className={`fab-panel ${className || ''}`}>
|
||||
{header && <div>
|
||||
<div className={`panel-header ${size}`}>
|
||||
{header}
|
||||
</div>
|
||||
<div className="panel-content">
|
||||
{children}
|
||||
</div>
|
||||
</div>}
|
||||
{!header && children}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -132,7 +132,7 @@ export const LocalPaymentForm: React.FC<GatewayFormProps> = ({ onSubmit, onSucce
|
||||
value={methodToOption(method)} />
|
||||
{method === 'card' && <p>{t('app.admin.local_payment_form.card_collection_info')}</p>}
|
||||
{method === 'check' && <p>{t('app.admin.local_payment_form.check_collection_info', { DEADLINES: paymentSchedule.items.length })}</p>}
|
||||
{method === 'transfer' && <HtmlTranslate trKey="app.admin.local_payment.transfer_collection_info" options={{ DEADLINES: paymentSchedule.items.length }} />}
|
||||
{method === 'transfer' && <HtmlTranslate trKey="app.admin.local_payment_form.transfer_collection_info" options={{ DEADLINES: paymentSchedule.items.length }} />}
|
||||
</div>
|
||||
<div className="full-schedule">
|
||||
<ul>
|
||||
|
@ -83,7 +83,7 @@ export const PayzenSettings: React.FC<PayzenSettingsProps> = ({ onEditKeys, onCu
|
||||
setError('');
|
||||
updateSettings(draft => draft.set(SettingName.PayZenCurrency, value));
|
||||
} else {
|
||||
setError(t('app.admin.invoices.payment.payzen.currency_error'));
|
||||
setError(t('app.admin.invoices.payment.payzen_settings.currency_error'));
|
||||
}
|
||||
};
|
||||
|
||||
@ -97,18 +97,18 @@ export const PayzenSettings: React.FC<PayzenSettingsProps> = ({ onEditKeys, onCu
|
||||
updateSettings(draft => draft.set(SettingName.PayZenCurrency, result.value));
|
||||
onCurrencyUpdateSuccess(result.value);
|
||||
}, reason => {
|
||||
setError(t('app.admin.invoices.payment.payzen.error_while_saving') + reason);
|
||||
setError(t('app.admin.invoices.payment.payzen_settings.error_while_saving') + reason);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="payzen-settings">
|
||||
<h3 className="title">{t('app.admin.invoices.payment.payzen.payzen_keys')}</h3>
|
||||
<h3 className="title">{t('app.admin.invoices.payment.payzen_settings.payzen_keys')}</h3>
|
||||
<div className="payzen-keys">
|
||||
{payZenPublicSettings.concat(payZenPrivateSettings).map(setting => {
|
||||
return (
|
||||
<div className="key-wrapper" key={setting}>
|
||||
<label htmlFor={setting}>{t(`app.admin.invoices.payment.payzen.${setting}`)}</label>
|
||||
<label htmlFor={setting}>{t(`app.admin.invoices.payment.payzen_settings.${setting}`)}</label>
|
||||
<FabInput defaultValue={settings.get(setting)}
|
||||
id={setting}
|
||||
type={payZenPrivateSettings.indexOf(setting) > -1 ? 'password' : 'text'}
|
||||
@ -119,17 +119,17 @@ export const PayzenSettings: React.FC<PayzenSettingsProps> = ({ onEditKeys, onCu
|
||||
);
|
||||
})}
|
||||
<div className="edit-keys">
|
||||
<FabButton className="edit-keys-btn" onClick={handleKeysUpdate}>{t('app.admin.invoices.payment.edit_keys')}</FabButton>
|
||||
<FabButton className="edit-keys-btn" onClick={handleKeysUpdate}>{t('app.admin.invoices.payment.payzen_settings.edit_keys')}</FabButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className="payzen-currency">
|
||||
<h3 className="title">{t('app.admin.invoices.payment.payzen.currency')}</h3>
|
||||
<h3 className="title">{t('app.admin.invoices.payment.payzen_settings.currency')}</h3>
|
||||
<p className="currency-info">
|
||||
<HtmlTranslate trKey="app.admin.invoices.payment.payzen.currency_info_html" />
|
||||
<HtmlTranslate trKey="app.admin.invoices.payment.payzen_settings.currency_info_html" />
|
||||
</p>
|
||||
<div className="payzen-currency-form">
|
||||
<div className="currency-wrapper">
|
||||
<label htmlFor="payzen_currency">{t('app.admin.invoices.payment.payzen.payzen_currency')}</label>
|
||||
<label htmlFor="payzen_currency">{t('app.admin.invoices.payment.payzen_settings.payzen_currency')}</label>
|
||||
<FabInput defaultValue={settings.get(SettingName.PayZenCurrency)}
|
||||
id="payzen_currency"
|
||||
icon={<i className="fas fa-money-bill" />}
|
||||
@ -138,7 +138,7 @@ export const PayzenSettings: React.FC<PayzenSettingsProps> = ({ onEditKeys, onCu
|
||||
pattern="[A-Z]{3}"
|
||||
error={error} />
|
||||
</div>
|
||||
<FabButton className="save-currency" onClick={saveCurrency}>{t('app.admin.invoices.payment.payzen.save')}</FabButton>
|
||||
<FabButton className="save-currency" onClick={saveCurrency}>{t('app.admin.invoices.payment.payzen_settings.save')}</FabButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,68 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabModal } from '../base/fab-modal';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
import { ProofOfIdentityTypeForm } from './proof-of-identity-type-form';
|
||||
|
||||
interface ProofOfIdentityTypeModalProps {
|
||||
isOpen: boolean,
|
||||
toggleModal: () => void,
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
groups: Array<Group>,
|
||||
proofOfIdentityType?: ProofOfIdentityType,
|
||||
}
|
||||
|
||||
export const ProofOfIdentityTypeModal: React.FC<ProofOfIdentityTypeModalProps> = ({ isOpen, toggleModal, onSuccess, onError, proofOfIdentityType, groups }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [data, setData] = useState<ProofOfIdentityType>({ id: proofOfIdentityType?.id, group_ids: proofOfIdentityType?.group_ids || [], name: proofOfIdentityType?.name || '' });
|
||||
|
||||
useEffect(() => {
|
||||
setData({ id: proofOfIdentityType?.id, group_ids: proofOfIdentityType?.group_ids || [], name: proofOfIdentityType?.name || '' });
|
||||
}, [proofOfIdentityType]);
|
||||
|
||||
const handleProofOfIdentityTypeChanged = (field: string, value: string | Array<number>) => {
|
||||
setData({
|
||||
...data,
|
||||
[field]: value
|
||||
});
|
||||
};
|
||||
|
||||
const handleSaveProofOfIdentityType = async (): Promise<void> => {
|
||||
try {
|
||||
if (proofOfIdentityType?.id) {
|
||||
await ProofOfIdentityTypeAPI.update(data);
|
||||
onSuccess(t('app.admin.settings.account.proof_of_identity_type_successfully_updated'));
|
||||
} else {
|
||||
await ProofOfIdentityTypeAPI.create(data);
|
||||
onSuccess(t('app.admin.settings.account.proof_of_identity_type_successfully_created'));
|
||||
}
|
||||
} catch (e) {
|
||||
if (proofOfIdentityType?.id) {
|
||||
onError(t('app.admin.settings.account.proof_of_identity_type_unable_to_update') + e);
|
||||
} else {
|
||||
onError(t('app.admin.settings.account.proof_of_identity_type_unable_to_create') + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const isPreventSaveProofOfIdentityType = (): boolean => {
|
||||
return !data.name || data.group_ids.length === 0;
|
||||
};
|
||||
|
||||
return (
|
||||
<FabModal title={t(`app.admin.settings.account.${proofOfIdentityType ? 'edit' : 'new'}_proof_of_identity_type`)}
|
||||
isOpen={isOpen}
|
||||
toggleModal={toggleModal}
|
||||
closeButton={false}
|
||||
confirmButton={t(`app.admin.settings.account.${proofOfIdentityType ? 'edit' : 'create'}`)}
|
||||
onConfirm={handleSaveProofOfIdentityType}
|
||||
preventConfirm={isPreventSaveProofOfIdentityType()}
|
||||
className="proof-of-identity-type-modal">
|
||||
<ProofOfIdentityTypeForm proofOfIdentityType={proofOfIdentityType} groups={groups} onChange={handleProofOfIdentityTypeChanged}/>
|
||||
</FabModal>
|
||||
);
|
||||
};
|
@ -1,214 +0,0 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { react2angular } from 'react2angular';
|
||||
import _ from 'lodash';
|
||||
import { HtmlTranslate } from '../base/html-translate';
|
||||
import { Loader } from '../base/loader';
|
||||
import { IApplication } from '../../models/application';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
import { ProofOfIdentityTypeModal } from './proof-of-identity-type-modal';
|
||||
import { DeleteSupportingDocumentsTypeModal } from './delete-supporting-documents-type-modal';
|
||||
import GroupAPI from '../../api/group';
|
||||
import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
interface ProofOfIdentityTypesListProps {
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* This component shows a list of all payment schedules with their associated deadlines (aka. PaymentScheduleItem) and invoices
|
||||
*/
|
||||
const ProofOfIdentityTypesList: React.FC<ProofOfIdentityTypesListProps> = ({ onSuccess, onError }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
// list of displayed supporting documents type
|
||||
const [proofOfIdentityTypes, setProofOfIdentityTypes] = useState<Array<ProofOfIdentityType>>([]);
|
||||
const [proofOfIdentityType, setProofOfIdentityType] = useState<ProofOfIdentityType>(null);
|
||||
const [proofOfIdentityTypeOrder, setProofOfIdentityTypeOrder] = useState<string>(null);
|
||||
const [modalIsOpen, setModalIsOpen] = useState<boolean>(false);
|
||||
const [groups, setGroups] = useState<Array<Group>>([]);
|
||||
const [destroyModalIsOpen, setDestroyModalIsOpen] = useState<boolean>(false);
|
||||
const [proofOfIdentityTypeId, setProofOfIdentityTypeId] = useState<number>(null);
|
||||
|
||||
// get groups
|
||||
useEffect(() => {
|
||||
GroupAPI.index({ disabled: false, admins: false }).then(data => {
|
||||
setGroups(data);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setProofOfIdentityTypes(pData);
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Check if the current collection of supporting documents types is empty or not.
|
||||
*/
|
||||
const hasProofOfIdentityTypes = (): boolean => {
|
||||
return proofOfIdentityTypes.length > 0;
|
||||
};
|
||||
|
||||
const addProofOfIdentityType = (): void => {
|
||||
setProofOfIdentityType(null);
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
|
||||
const editProofOfIdentityType = (poit: ProofOfIdentityType): () => void => {
|
||||
return (): void => {
|
||||
setProofOfIdentityType(poit);
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
};
|
||||
|
||||
const toggleCreateAndEditModal = (): void => {
|
||||
setModalIsOpen(false);
|
||||
};
|
||||
|
||||
const saveProofOfIdentityTypeOnSuccess = (message: string): void => {
|
||||
setModalIsOpen(false);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setProofOfIdentityTypes(orderProofOfIdentityTypes(pData, proofOfIdentityTypeOrder));
|
||||
onSuccess(message);
|
||||
}).catch((error) => {
|
||||
onError('Unable to load proof of identity types' + error);
|
||||
});
|
||||
};
|
||||
|
||||
const destroyProofOfIdentityType = (id: number): () => void => {
|
||||
return (): void => {
|
||||
setProofOfIdentityTypeId(id);
|
||||
setDestroyModalIsOpen(true);
|
||||
};
|
||||
};
|
||||
|
||||
const toggleDestroyModal = (): void => {
|
||||
setDestroyModalIsOpen(false);
|
||||
};
|
||||
|
||||
const destroyProofOfIdentityTypeOnSuccess = (message: string): void => {
|
||||
setDestroyModalIsOpen(false);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setProofOfIdentityTypes(pData);
|
||||
setProofOfIdentityTypes(orderProofOfIdentityTypes(pData, proofOfIdentityTypeOrder));
|
||||
onSuccess(message);
|
||||
}).catch((error) => {
|
||||
onError('Unable to load proof of identity types' + error);
|
||||
});
|
||||
};
|
||||
|
||||
const setOrderProofOfIdentityType = (orderBy: string): () => void => {
|
||||
return () => {
|
||||
let order = orderBy;
|
||||
if (proofOfIdentityTypeOrder === orderBy) {
|
||||
order = `-${orderBy}`;
|
||||
}
|
||||
setProofOfIdentityTypeOrder(order);
|
||||
setProofOfIdentityTypes(orderProofOfIdentityTypes(proofOfIdentityTypes, order));
|
||||
};
|
||||
};
|
||||
|
||||
const orderProofOfIdentityTypes = (poits: Array<ProofOfIdentityType>, orderBy?: string): Array<ProofOfIdentityType> => {
|
||||
if (!orderBy) {
|
||||
return poits;
|
||||
}
|
||||
const order = orderBy[0] === '-' ? 'desc' : 'asc';
|
||||
if (orderBy.search('group_name') !== -1) {
|
||||
return _.orderBy(poits, (poit: ProofOfIdentityType) => getGroupName(poit.group_ids), order);
|
||||
} else {
|
||||
return _.orderBy(poits, 'name', order);
|
||||
}
|
||||
};
|
||||
|
||||
const orderClassName = (orderBy: string): string => {
|
||||
if (proofOfIdentityTypeOrder) {
|
||||
const order = proofOfIdentityTypeOrder[0] === '-' ? proofOfIdentityTypeOrder.substr(1) : proofOfIdentityTypeOrder;
|
||||
if (order === orderBy) {
|
||||
return `fa fa-arrows-v ${proofOfIdentityTypeOrder[0] === '-' ? 'fa-sort-alpha-desc' : 'fa-sort-alpha-asc'}`;
|
||||
}
|
||||
}
|
||||
return 'fa fa-arrows-v';
|
||||
};
|
||||
|
||||
const getGroupName = (groupIds: Array<number>): string => {
|
||||
if (groupIds.length === groups.length && groupIds.length > 0) {
|
||||
return t('app.admin.settings.account.all_groups');
|
||||
}
|
||||
const _groups = _.filter(groups, (g: Group) => { return groupIds.includes(g.id); });
|
||||
return _groups.map((g: Group) => g.name).join(', ');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="panel panel-default m-t-md">
|
||||
<div className="panel-heading">
|
||||
<span className="font-sbold">{t('app.admin.settings.account.add_proof_of_identity_types')}</span>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<div className="row">
|
||||
<p className="m-h">{t('app.admin.settings.account.proof_of_identity_type_info')}</p>
|
||||
<div className="alert alert-warning m-h-md row">
|
||||
<div className="col-md-8">
|
||||
<HtmlTranslate trKey="app.admin.settings.account.proof_of_identity_type_no_group_info" />
|
||||
</div>
|
||||
<a href="/#!/admin/members?tabs=1" className="btn btn-warning pull-right m-t m-r-md col-md-3" style={{ color: '#000', maxWidth: '200px' }}>{t('app.admin.settings.account.create_groups')}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="row">
|
||||
<h3 className="m-l inline">{t('app.admin.settings.account.proof_of_identity_type_title')}</h3>
|
||||
<button name="button" className="btn btn-warning pull-right m-t m-r-md" onClick={addProofOfIdentityType}>{t('app.admin.settings.account.add_proof_of_identity_type_button')}</button>
|
||||
</div>
|
||||
|
||||
<ProofOfIdentityTypeModal isOpen={modalIsOpen} groups={groups} proofOfIdentityType={proofOfIdentityType} toggleModal={toggleCreateAndEditModal} onSuccess={saveProofOfIdentityTypeOnSuccess} onError={onError} />
|
||||
<DeleteSupportingDocumentsTypeModal isOpen={destroyModalIsOpen} proofOfIdentityTypeId={proofOfIdentityTypeId} toggleModal={toggleDestroyModal} onSuccess={destroyProofOfIdentityTypeOnSuccess} onError={onError}/>
|
||||
|
||||
<table className="table proof-of-identity-type-list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: '40%' }}><a onClick={setOrderProofOfIdentityType('group_name')}>{t('app.admin.settings.account.proof_of_identity_type.group_name')} <i className={orderClassName('group_name')}></i></a></th>
|
||||
<th style={{ width: '40%' }}><a onClick={setOrderProofOfIdentityType('name')}>{t('app.admin.settings.account.proof_of_identity_type.name')} <i className={orderClassName('name')}></i></a></th>
|
||||
<th style={{ width: '20%' }} className="buttons-col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{proofOfIdentityTypes.map(poit => {
|
||||
return (
|
||||
<tr key={poit.id}>
|
||||
<td>{getGroupName(poit.group_ids)}</td>
|
||||
<td>{poit.name}</td>
|
||||
<td>
|
||||
<div className="buttons">
|
||||
<button className="btn btn-default edit-proof-of-identity-type m-r-xs" onClick={editProofOfIdentityType(poit)}>
|
||||
<i className="fa fa-edit"></i>
|
||||
</button>
|
||||
<button className="btn btn-danger delete-proof-of-identity-type" onClick={destroyProofOfIdentityType(poit.id)}>
|
||||
<i className="fa fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{!hasProofOfIdentityTypes() && (
|
||||
<p className="text-center">
|
||||
<HtmlTranslate trKey="app.admin.settings.account.no_proof_of_identity_types" />
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const ProofOfIdentityTypesListWrapper: React.FC<ProofOfIdentityTypesListProps> = ({ onSuccess, onError }) => {
|
||||
return (
|
||||
<Loader>
|
||||
<ProofOfIdentityTypesList onSuccess={onSuccess} onError={onError} />
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('proofOfIdentityTypesList', react2angular(ProofOfIdentityTypesListWrapper, ['onSuccess', 'onError']));
|
@ -12,6 +12,7 @@ import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
import ProofOfIdentityFileAPI from '../../api/proof-of-identity-file';
|
||||
import { IFablab } from '../../models/fablab';
|
||||
import { FabAlert } from '../base/fab-alert';
|
||||
import { FabPanel } from '../base/fab-panel';
|
||||
|
||||
declare let Fablab: IFablab;
|
||||
|
||||
@ -133,7 +134,7 @@ export const SupportingDocumentsFiles: React.FC<SupportingDocumentsFilesProps> =
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="supporting-documents-files">
|
||||
<FabPanel className="supporting-documents-files">
|
||||
<h3>{t('app.logged.dashboard.supporting_documents_files.supporting_documents_files')}</h3>
|
||||
<p className="info-area">{t('app.logged.dashboard.supporting_documents_files.my_documents_info')}</p>
|
||||
<FabAlert level="warning">
|
||||
@ -189,7 +190,7 @@ export const SupportingDocumentsFiles: React.FC<SupportingDocumentsFilesProps> =
|
||||
{t('app.logged.dashboard.supporting_documents_files.save')}
|
||||
</button>
|
||||
)}
|
||||
</section>
|
||||
</FabPanel>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -5,7 +5,7 @@ import { FabInput } from '../base/fab-input';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
|
||||
interface ProofOfIdentityTypeFormProps {
|
||||
interface SupportingDocumentsTypeFormProps {
|
||||
groups: Array<Group>,
|
||||
proofOfIdentityType?: ProofOfIdentityType,
|
||||
onChange: (field: string, value: string | Array<number>) => void,
|
||||
@ -18,13 +18,13 @@ interface ProofOfIdentityTypeFormProps {
|
||||
type selectOption = { value: number, label: string };
|
||||
|
||||
/**
|
||||
* Form to set the stripe's public and private keys
|
||||
* Form to set create/edit supporting documents type
|
||||
*/
|
||||
export const ProofOfIdentityTypeForm: React.FC<ProofOfIdentityTypeFormProps> = ({ groups, proofOfIdentityType, onChange }) => {
|
||||
export const SupportingDocumentsTypeForm: React.FC<SupportingDocumentsTypeFormProps> = ({ groups, proofOfIdentityType, onChange }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
/**
|
||||
* Convert all themes to the react-select format
|
||||
* Convert all groups to the react-select format
|
||||
*/
|
||||
const buildOptions = (): Array<selectOption> => {
|
||||
return groups.map(t => {
|
||||
@ -33,7 +33,7 @@ export const ProofOfIdentityTypeForm: React.FC<ProofOfIdentityTypeFormProps> = (
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the current groups(s), formatted to match the react-select format
|
||||
* Return the group(s) associated with the current type, formatted to match the react-select format
|
||||
*/
|
||||
const groupsValues = (): Array<selectOption> => {
|
||||
const res = [];
|
||||
@ -63,23 +63,23 @@ export const ProofOfIdentityTypeForm: React.FC<ProofOfIdentityTypeFormProps> = (
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="proof-of-identity-type-form">
|
||||
<div className="proof-of-identity-type-form-info">
|
||||
{t('app.admin.settings.account.proof_of_identity_type_form_info')}
|
||||
<div className="supporting-documents-type-form">
|
||||
<div className="info-area">
|
||||
{t('app.admin.settings.account.supporting_documents_type_form.type_form_info')}
|
||||
</div>
|
||||
<form name="proofOfIdentityTypeForm">
|
||||
<div className="proof-of-identity-type-select m-t">
|
||||
<div className="field">
|
||||
<Select defaultValue={groupsValues()}
|
||||
placeholder={t('app.admin.settings.account.proof_of_identity_type_select_group')}
|
||||
placeholder={t('app.admin.settings.account.supporting_documents_type_form.select_group')}
|
||||
onChange={handleGroupsChange}
|
||||
options={buildOptions()}
|
||||
isMulti />
|
||||
</div>
|
||||
<div className="proof-of-identity-type-input m-t">
|
||||
<div className="field">
|
||||
<FabInput id="proof_of_identity_type_name"
|
||||
icon={<i className="fa fa-edit" />}
|
||||
defaultValue={proofOfIdentityType?.name || ''}
|
||||
placeholder={t('app.admin.settings.account.proof_of_identity_type_input_name')}
|
||||
placeholder={t('app.admin.settings.account.supporting_documents_type_form.name')}
|
||||
onChange={handleNameChange}
|
||||
debounce={200}
|
||||
required/>
|
@ -0,0 +1,79 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { FabModal } from '../base/fab-modal';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
import { SupportingDocumentsTypeForm } from './supporting-documents-type-form';
|
||||
|
||||
interface SupportingDocumentsTypeModalProps {
|
||||
isOpen: boolean,
|
||||
toggleModal: () => void,
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
groups: Array<Group>,
|
||||
proofOfIdentityType?: ProofOfIdentityType,
|
||||
}
|
||||
|
||||
/**
|
||||
* Modal dialog to create/edit a supporting documents type
|
||||
*/
|
||||
export const SupportingDocumentsTypeModal: React.FC<SupportingDocumentsTypeModalProps> = ({ isOpen, toggleModal, onSuccess, onError, proofOfIdentityType, groups }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [data, setData] = useState<ProofOfIdentityType>({ id: proofOfIdentityType?.id, group_ids: proofOfIdentityType?.group_ids || [], name: proofOfIdentityType?.name || '' });
|
||||
|
||||
useEffect(() => {
|
||||
setData({ id: proofOfIdentityType?.id, group_ids: proofOfIdentityType?.group_ids || [], name: proofOfIdentityType?.name || '' });
|
||||
}, [proofOfIdentityType]);
|
||||
|
||||
/**
|
||||
* Callback triggered when an inner form field has changed: updates the internal state accordingly
|
||||
*/
|
||||
const handleTypeChanged = (field: string, value: string | Array<number>) => {
|
||||
setData({
|
||||
...data,
|
||||
[field]: value
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the current type to the API
|
||||
*/
|
||||
const handleSaveType = async (): Promise<void> => {
|
||||
try {
|
||||
if (proofOfIdentityType?.id) {
|
||||
await ProofOfIdentityTypeAPI.update(data);
|
||||
onSuccess(t('app.admin.settings.account.supporting_documents_type_modal.successfully_updated'));
|
||||
} else {
|
||||
await ProofOfIdentityTypeAPI.create(data);
|
||||
onSuccess(t('app.admin.settings.account.supporting_documents_type_modal.successfully_created'));
|
||||
}
|
||||
} catch (e) {
|
||||
if (proofOfIdentityType?.id) {
|
||||
onError(t('app.admin.settings.account.supporting_documents_type_modal.unable_to_update') + e);
|
||||
} else {
|
||||
onError(t('app.admin.settings.account.supporting_documents_type_modal.unable_to_create') + e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the form is valid (not empty)
|
||||
*/
|
||||
const isPreventedSaveType = (): boolean => {
|
||||
return !data.name || data.group_ids.length === 0;
|
||||
};
|
||||
|
||||
return (
|
||||
<FabModal title={t(`app.admin.settings.account.supporting_documents_type_modal.${proofOfIdentityType ? 'edit' : 'new'}_type`)}
|
||||
isOpen={isOpen}
|
||||
toggleModal={toggleModal}
|
||||
closeButton={false}
|
||||
confirmButton={t(`app.admin.settings.account.supporting_documents_type_modal.${proofOfIdentityType ? 'edit' : 'create'}`)}
|
||||
onConfirm={handleSaveType}
|
||||
preventConfirm={isPreventedSaveType()}>
|
||||
<SupportingDocumentsTypeForm proofOfIdentityType={proofOfIdentityType} groups={groups} onChange={handleTypeChanged}/>
|
||||
</FabModal>
|
||||
);
|
||||
};
|
@ -0,0 +1,281 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { react2angular } from 'react2angular';
|
||||
import _ from 'lodash';
|
||||
import { HtmlTranslate } from '../base/html-translate';
|
||||
import { Loader } from '../base/loader';
|
||||
import { IApplication } from '../../models/application';
|
||||
import { ProofOfIdentityType } from '../../models/proof-of-identity-type';
|
||||
import { Group } from '../../models/group';
|
||||
import { SupportingDocumentsTypeModal } from './supporting-documents-type-modal';
|
||||
import { DeleteSupportingDocumentsTypeModal } from './delete-supporting-documents-type-modal';
|
||||
import GroupAPI from '../../api/group';
|
||||
import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
import { FabPanel } from '../base/fab-panel';
|
||||
import { FabAlert } from '../base/fab-alert';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
interface SupportingDocumentsTypesListProps {
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
}
|
||||
|
||||
/**
|
||||
* This component shows a list of all types of supporting documents (e.g. student ID, Kbis extract, etc.)
|
||||
*/
|
||||
const SupportingDocumentsTypesList: React.FC<SupportingDocumentsTypesListProps> = ({ onSuccess, onError }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
// list of displayed supporting documents type
|
||||
const [supportingDocumentsTypes, setSupportingDocumentsTypes] = useState<Array<ProofOfIdentityType>>([]);
|
||||
// currently added/edited type
|
||||
const [supportingDocumentsType, setSupportingDocumentsType] = useState<ProofOfIdentityType>(null);
|
||||
// list ordering
|
||||
const [supportingDocumentsTypeOrder, setSupportingDocumentsTypeOrder] = useState<string>(null);
|
||||
// creation/edition modal
|
||||
const [modalIsOpen, setModalIsOpen] = useState<boolean>(false);
|
||||
// all groups
|
||||
const [groups, setGroups] = useState<Array<Group>>([]);
|
||||
// deletion modal
|
||||
const [destroyModalIsOpen, setDestroyModalIsOpen] = useState<boolean>(false);
|
||||
// currently deleted type
|
||||
const [supportingDocumentsTypeId, setSupportingDocumentsTypeId] = useState<number>(null);
|
||||
|
||||
// get groups
|
||||
useEffect(() => {
|
||||
GroupAPI.index({ disabled: false, admins: false }).then(data => {
|
||||
setGroups(data);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setSupportingDocumentsTypes(pData);
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Check if the current collection of supporting documents types is empty or not.
|
||||
*/
|
||||
const hasTypes = (): boolean => {
|
||||
return supportingDocumentsTypes.length > 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Init the process of creating a new supporting documents type
|
||||
*/
|
||||
const addType = (): void => {
|
||||
setSupportingDocumentsType(null);
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Init the process of editing the given type
|
||||
*/
|
||||
const editType = (type: ProofOfIdentityType): () => void => {
|
||||
return (): void => {
|
||||
setSupportingDocumentsType(type);
|
||||
setModalIsOpen(true);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Toggle the modal dialog to create/edit a type
|
||||
*/
|
||||
const toggleCreateAndEditModal = (): void => {
|
||||
setModalIsOpen(!modalIsOpen);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggred when the current type was successfully saved
|
||||
*/
|
||||
const onSaveTypeSuccess = (message: string): void => {
|
||||
setModalIsOpen(false);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setSupportingDocumentsTypes(orderTypes(pData, supportingDocumentsTypeOrder));
|
||||
onSuccess(message);
|
||||
}).catch((error) => {
|
||||
onError('Unable to load proof of identity types' + error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Init the process of deleting a supporting documents type (ask for confirmation)
|
||||
*/
|
||||
const destroyType = (id: number): () => void => {
|
||||
return (): void => {
|
||||
setSupportingDocumentsTypeId(id);
|
||||
setDestroyModalIsOpen(true);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Open/closes the confirmation before deletion modal
|
||||
*/
|
||||
const toggleDestroyModal = (): void => {
|
||||
setDestroyModalIsOpen(!destroyModalIsOpen);
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback triggred when the current type was successfully deleted
|
||||
*/
|
||||
const onDestroySuccess = (message: string): void => {
|
||||
setDestroyModalIsOpen(false);
|
||||
ProofOfIdentityTypeAPI.index().then(pData => {
|
||||
setSupportingDocumentsTypes(pData);
|
||||
setSupportingDocumentsTypes(orderTypes(pData, supportingDocumentsTypeOrder));
|
||||
onSuccess(message);
|
||||
}).catch((error) => {
|
||||
onError('Unable to load proof of identity types' + error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the list ordering, according to the provided key
|
||||
*/
|
||||
const setTypeOrder = (orderBy: string): () => void => {
|
||||
return () => {
|
||||
let order = orderBy;
|
||||
if (supportingDocumentsTypeOrder === orderBy) {
|
||||
order = `-${orderBy}`;
|
||||
}
|
||||
setSupportingDocumentsTypeOrder(order);
|
||||
setSupportingDocumentsTypes(orderTypes(supportingDocumentsTypes, order));
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Sort the provided types according to the provided ordering key and return the resulting list
|
||||
*/
|
||||
const orderTypes = (types: Array<ProofOfIdentityType>, orderBy?: string): Array<ProofOfIdentityType> => {
|
||||
if (!orderBy) {
|
||||
return types;
|
||||
}
|
||||
const order = orderBy[0] === '-' ? 'desc' : 'asc';
|
||||
if (orderBy.search('group_name') !== -1) {
|
||||
return _.orderBy(types, (type: ProofOfIdentityType) => getGroupsNames(type.group_ids), order);
|
||||
} else {
|
||||
return _.orderBy(types, 'name', order);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the icon classes to use, according to the provided ordering key
|
||||
*/
|
||||
const orderClassName = (orderBy: string): string => {
|
||||
if (supportingDocumentsTypeOrder) {
|
||||
const order = supportingDocumentsTypeOrder[0] === '-' ? supportingDocumentsTypeOrder.substr(1) : supportingDocumentsTypeOrder;
|
||||
if (order === orderBy) {
|
||||
return `fa fa-arrows-v ${supportingDocumentsTypeOrder[0] === '-' ? 'fa-sort-alpha-desc' : 'fa-sort-alpha-asc'}`;
|
||||
}
|
||||
}
|
||||
return 'fa fa-arrows-v';
|
||||
};
|
||||
|
||||
/**
|
||||
* Return a comma separated list of the names of the provided groups
|
||||
*/
|
||||
const getGroupsNames = (groupIds: Array<number>): string => {
|
||||
if (groupIds.length === groups.length && groupIds.length > 0) {
|
||||
return t('app.admin.settings.account.supporting_documents_types_list.all_groups');
|
||||
}
|
||||
const _groups = _.filter(groups, (g: Group) => { return groupIds.includes(g.id); });
|
||||
return _groups.map((g: Group) => g.name).join(', ');
|
||||
};
|
||||
|
||||
/**
|
||||
* Redirect the user to the new group page
|
||||
*/
|
||||
const addGroup = (): void => {
|
||||
window.location.href = '/#!/admin/members?tabs=1';
|
||||
};
|
||||
|
||||
return (
|
||||
<FabPanel className="supporting-documents-types-list" header={<div>
|
||||
<span>{t('app.admin.settings.account.supporting_documents_types_list.add_supporting_documents_types')}</span>
|
||||
</div>}>
|
||||
<div className="types-list">
|
||||
<div className="groups">
|
||||
<p>{t('app.admin.settings.account.supporting_documents_types_list.supporting_documents_type_info')}</p>
|
||||
<div className="no-groups">
|
||||
<FabAlert level="warning">
|
||||
<HtmlTranslate trKey="app.admin.settings.account.supporting_documents_types_list.no_groups_info" />
|
||||
</FabAlert>
|
||||
<FabButton onClick={addGroup}>{t('app.admin.settings.account.supporting_documents_types_list.create_groups')}</FabButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="title">
|
||||
<h3>{t('app.admin.settings.account.supporting_documents_types_list.supporting_documents_type_title')}</h3>
|
||||
<FabButton onClick={addType}>{t('app.admin.settings.account.supporting_documents_types_list.add_type')}</FabButton>
|
||||
</div>
|
||||
|
||||
<SupportingDocumentsTypeModal isOpen={modalIsOpen}
|
||||
groups={groups}
|
||||
proofOfIdentityType={supportingDocumentsType}
|
||||
toggleModal={toggleCreateAndEditModal}
|
||||
onSuccess={onSaveTypeSuccess}
|
||||
onError={onError} />
|
||||
<DeleteSupportingDocumentsTypeModal isOpen={destroyModalIsOpen}
|
||||
proofOfIdentityTypeId={supportingDocumentsTypeId}
|
||||
toggleModal={toggleDestroyModal}
|
||||
onSuccess={onDestroySuccess}
|
||||
onError={onError}/>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="group-name">
|
||||
<a onClick={setTypeOrder('group_name')}>
|
||||
{t('app.admin.settings.account.supporting_documents_types_list.group_name')}
|
||||
<i className={orderClassName('group_name')} />
|
||||
</a>
|
||||
</th>
|
||||
<th className="name">
|
||||
<a onClick={setTypeOrder('name')}>
|
||||
{t('app.admin.settings.account.supporting_documents_types_list.name')}
|
||||
<i className={orderClassName('name')} />
|
||||
</a>
|
||||
</th>
|
||||
<th className="actions"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{supportingDocumentsTypes.map(poit => {
|
||||
return (
|
||||
<tr key={poit.id}>
|
||||
<td>{getGroupsNames(poit.group_ids)}</td>
|
||||
<td>{poit.name}</td>
|
||||
<td>
|
||||
<div className="buttons">
|
||||
<FabButton className="edit-btn" onClick={editType(poit)}>
|
||||
<i className="fa fa-edit" />
|
||||
</FabButton>
|
||||
<FabButton className="delete-btn" onClick={destroyType(poit.id)}>
|
||||
<i className="fa fa-trash" />
|
||||
</FabButton>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
{!hasTypes() && (
|
||||
<p className="no-types-info">
|
||||
<HtmlTranslate trKey="app.admin.settings.account.supporting_documents_types_list.no_types" />
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</FabPanel>
|
||||
);
|
||||
};
|
||||
|
||||
const SupportingDocumentsTypesListWrapper: React.FC<SupportingDocumentsTypesListProps> = (props) => {
|
||||
return (
|
||||
<Loader>
|
||||
<SupportingDocumentsTypesList {...props} />
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('supportingDocumentsTypesList', react2angular(SupportingDocumentsTypesListWrapper, ['onSuccess', 'onError']));
|
@ -11,6 +11,7 @@ import ProofOfIdentityTypeAPI from '../../api/proof-of-identity-type';
|
||||
import ProofOfIdentityFileAPI from '../../api/proof-of-identity-file';
|
||||
import { SupportingDocumentsRefusalModal } from './supporting-documents-refusal-modal';
|
||||
import { FabButton } from '../base/fab-button';
|
||||
import { FabPanel } from '../base/fab-panel';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -80,7 +81,7 @@ const SupportingDocumentsValidation: React.FC<SupportingDocumentsValidationProps
|
||||
|
||||
return (
|
||||
<div className="supporting-documents-validation">
|
||||
<section>
|
||||
<FabPanel>
|
||||
<h3>{t('app.admin.supporting_documents_validation.title')}</h3>
|
||||
<p className="info-area">{t('app.admin.supporting_documents_validation.find_below_documents_files')}</p>
|
||||
{documentsTypes.map((documentType: ProofOfIdentityType) => {
|
||||
@ -99,9 +100,9 @@ const SupportingDocumentsValidation: React.FC<SupportingDocumentsValidationProps
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</section>
|
||||
</FabPanel>
|
||||
{hasSupportingDocumentsTypes() && !member.validated_at && (
|
||||
<section className="refusal">
|
||||
<FabPanel className="refusal">
|
||||
<h3>{t('app.admin.supporting_documents_validation.refuse_documents')}</h3>
|
||||
<p className="text-black">{t('app.admin.supporting_documents_validation.refuse_documents_info')}</p>
|
||||
<FabButton className="refuse-btn" onClick={toggleModal}>{t('app.admin.supporting_documents_validation.refuse_documents')}</FabButton>
|
||||
@ -113,7 +114,7 @@ const SupportingDocumentsValidation: React.FC<SupportingDocumentsValidationProps
|
||||
member={member}
|
||||
onError={onError}
|
||||
onSuccess={onSaveRefusalSuccess}/>
|
||||
</section>
|
||||
</FabPanel>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
@ -25,6 +25,7 @@
|
||||
@import "modules/base/fab-input";
|
||||
@import "modules/base/fab-modal";
|
||||
@import "modules/base/fab-output-copy";
|
||||
@import "modules/base/fab-panel";
|
||||
@import "modules/base/fab-popover";
|
||||
@import "modules/base/fab-text-editor";
|
||||
@import "modules/base/labelled-input";
|
||||
@ -86,10 +87,13 @@
|
||||
@import "modules/supporting-documents/supporting-documents-files";
|
||||
@import "modules/supporting-documents/supporting-documents-refusal-form";
|
||||
@import "modules/supporting-documents/supporting-documents-validation";
|
||||
@import "modules/supporting-documents/supporting-documents-type-form";
|
||||
@import "modules/supporting-documents/supporting-documents-types-list";
|
||||
@import "modules/user/avatar";
|
||||
@import "modules/user/avatar-input";
|
||||
@import "modules/user/gender-input";
|
||||
@import "modules/user/user-profile-form";
|
||||
@import "modules/user/user-validation";
|
||||
|
||||
@import "modules/abuses";
|
||||
@import "modules/cookies";
|
||||
|
50
app/frontend/src/stylesheets/modules/base/fab-panel.scss
Normal file
50
app/frontend/src/stylesheets/modules/base/fab-panel.scss
Normal file
@ -0,0 +1,50 @@
|
||||
.fab-panel {
|
||||
background-color: #f4f3f3;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
margin: 30px;
|
||||
min-height: 1px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
position: relative;
|
||||
display: block;
|
||||
border-spacing: 0;
|
||||
|
||||
.panel-header {
|
||||
padding: 10px 15px;
|
||||
border-bottom: 1px solid transparent;
|
||||
border-top-right-radius: 3px;
|
||||
border-top-left-radius: 3px;
|
||||
|
||||
&.small {
|
||||
padding: 15px 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.fab-panel {
|
||||
width: 58.3333333333%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.fab-panel {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.fab-panel {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
@ -1,15 +1,4 @@
|
||||
.supporting-documents-files {
|
||||
background-color: #f4f3f3;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
margin: 30px;
|
||||
min-height: 1px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
position: relative;
|
||||
display: block;
|
||||
border-spacing: 0;
|
||||
|
||||
.info-area {
|
||||
color: #000;
|
||||
@ -97,24 +86,3 @@
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.supporting-documents-files {
|
||||
width: 58.3333333333%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.supporting-documents-files {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.supporting-documents-files {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,5 @@
|
||||
.supporting-documents-type-form {
|
||||
.field {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
.supporting-documents-types-list {
|
||||
margin-top: 20px;
|
||||
|
||||
.panel-header span {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.types-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.groups {
|
||||
p {
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
.no-groups {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.fab-alert {
|
||||
margin-left: 20px;
|
||||
margin-right: 20px;
|
||||
width: 66.66666666666666%;
|
||||
}
|
||||
.fab-button {
|
||||
margin-top: 15px;
|
||||
margin-right: 20px;
|
||||
color: #000;
|
||||
max-width: 200px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
h3 {
|
||||
margin-left: 15px;
|
||||
display: inline-block;
|
||||
}
|
||||
.fab-button {
|
||||
margin-top: 15px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
thead > tr {
|
||||
th.group-name,
|
||||
th.name {
|
||||
width: 40%
|
||||
}
|
||||
th.actions {
|
||||
width: 20%;
|
||||
}
|
||||
}
|
||||
|
||||
tbody {
|
||||
.buttons {
|
||||
.edit-btn {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.no-types-info {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,4 @@
|
||||
.supporting-documents-validation {
|
||||
section {
|
||||
background-color: #f4f3f3;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||
margin: 30px;
|
||||
min-height: 1px;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
position: relative;
|
||||
display: block;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
.info-area {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
@ -44,27 +30,7 @@
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
.supporting-documents-validation section {
|
||||
width: 58.3333333333%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.supporting-documents-validation section.refusal {
|
||||
.supporting-documents-validation .fab-panel.refusal {
|
||||
width: 33.33333333333333%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.supporting-documents-validation section {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.supporting-documents-validation section {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
}
|
||||
|
@ -122,4 +122,4 @@
|
||||
</div>
|
||||
|
||||
|
||||
<proof-of-identity-types-list on-success="onSuccess" on-error="onError"/>
|
||||
<supporting-documents-types-list on-success="onSuccess" on-error="onError"/>
|
||||
|
@ -779,7 +779,8 @@ en:
|
||||
currency_alert_html: "<strong>Warning</strong>: the currency cannot be changed after the first online payment was made. Please define this setting carefully before opening Fab-manager to your members."
|
||||
stripe_currency: "Stripe currency"
|
||||
gateway_configuration_error: "An error occurred while configuring the payment gateway: "
|
||||
payzen:
|
||||
payzen_settings:
|
||||
edit_keys: "Edit keys"
|
||||
payzen_public_key: "Client public key"
|
||||
currency: "Currency"
|
||||
payzen_currency: "PayZen currency"
|
||||
@ -1535,33 +1536,35 @@ en:
|
||||
space: "Spaces"
|
||||
training: "Trainings"
|
||||
pack: "Prepaid pack"
|
||||
create_groups: "Create groups"
|
||||
add_proof_of_identity_types: "Add proof of identity"
|
||||
proof_of_identity_type_info: "You can add proof of identity according to the user groups created in order to ask your members to deposit them in their space. Each member will be informed of the proof of identity to be provided in their personal space (My proof of identity tab). On your side, you can check the proof of identity and validate their account (provided that the Account Validation option is activated)."
|
||||
proof_of_identity_type_no_group_info: "Proof of identity are necessarily applied to groups.</br>If you do not have a group yet, you can create one from the \"Users/Groups\" page (button on the right)."
|
||||
proof_of_identity_type_title: "Proof of identity"
|
||||
add_proof_of_identity_type_button: "Create proof of identity"
|
||||
no_proof_of_identity_types: "You do not have any proof of identity.</br>Make sure you have created at least one group in order to add a document."
|
||||
proof_of_identity_type:
|
||||
group_name: "Group"
|
||||
name: "Proof of identity"
|
||||
all_groups: 'All groups'
|
||||
new_proof_of_identity_type: "Create a proof of identity"
|
||||
edit_proof_of_identity_type: "Edit the proof of identity"
|
||||
proof_of_identity_type_form_info: "Field parameters"
|
||||
proof_of_identity_type_select_group: "Choose a group"
|
||||
proof_of_identity_type_input_name: "Name"
|
||||
create: "Create"
|
||||
edit: "Edit"
|
||||
confirm: "Confirm"
|
||||
confirmation_required: "Confirmation required"
|
||||
proof_of_identity_type_successfully_created: "The new proof of identity has been created."
|
||||
proof_of_identity_type_unable_to_create: "Unable to delete the proof of identity : "
|
||||
proof_of_identity_type_successfully_updated: "The proof of identity has been updated."
|
||||
proof_of_identity_type_unable_to_update: "Unable to modify the proof of identity : "
|
||||
organization: "Organization"
|
||||
organization_profile_custom_fields_info: "You can display additional fields for users who declare themselves to be an organization. You can also choose to make them mandatory at account creation."
|
||||
organization_profile_custom_fields_alert: "Attention: the activated fields will be automatically displayed on the issued invoices. Once configured, please do not modify them."
|
||||
supporting_documents_type_modal:
|
||||
successfully_created: "The new proof of identity has been created."
|
||||
unable_to_create: "Unable to delete the proof of identity : "
|
||||
successfully_updated: "The proof of identity has been updated."
|
||||
unable_to_update: "Unable to modify the proof of identity : "
|
||||
new_type: "Create a proof of identity"
|
||||
edit_type: "Edit the proof of identity"
|
||||
create: "Create"
|
||||
edit: "Edit"
|
||||
supporting_documents_type_form:
|
||||
type_form_info: "Field parameters"
|
||||
select_group: "Choose one or many group(s)"
|
||||
name: "Name"
|
||||
supporting_documents_types_list:
|
||||
add_supporting_documents_types: "Add supporting documents"
|
||||
all_groups: 'All groups'
|
||||
supporting_documents_type_info: "You can ask for supporting documents, according to the user's groups. This will ask your members to deposit those kind of documents in their personnal space. Each members will be informed that supporting documents are required to be provided in their personal space (My supporting documents tab). On your side, you'll be able to check the provided supporting documents and validate the member's account (if the Account Validation option is enabled)."
|
||||
no_groups_info: "Supporting documents are necessarily applied to groups.</br>If you do not have any group yet, you can create one from the \"Users/Groups\" page (button on the right)."
|
||||
create_groups: "Create groups"
|
||||
supporting_documents_type_title: "Supporting documents requests"
|
||||
add_type: "New supporting documents request"
|
||||
group_name: "Group"
|
||||
name: "Supporting documents"
|
||||
no_types: "You do not have any supporting documents requests.</br>Make sure you have created at least one group in order to add a request."
|
||||
delete_supporting_documents_type_modal:
|
||||
confirmation_required: "Confirmation required"
|
||||
confirm: "Confirm"
|
||||
|
Loading…
x
Reference in New Issue
Block a user