1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-30 19:52:20 +01:00

linted all front code, excepted profile-completion/

and prrofile-custom-fields/
This commit is contained in:
Sylvain 2022-06-20 15:35:38 +02:00
parent 37bc2b3d43
commit 2033329342
48 changed files with 238 additions and 79 deletions

View File

@ -6,7 +6,7 @@
],
"rules": {
"semi": ["error", "always"],
"no-use-before-define": "off",
"no-use-before-define": "off"
},
"globals": {
"Application": true,

View File

@ -13,6 +13,10 @@ interface Oauth2DataMappingFormProps<TFieldValues, TContext extends object> {
index: number,
}
/**
* Partial form to set the data mapping for an OAuth 2.0 provider.
* The data mapping is the way to bind data from the authentication provider API to the Fab-manager's database
*/
export const Oauth2DataMappingForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control, index }: Oauth2DataMappingFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('admin');

View File

@ -16,6 +16,10 @@ interface OpenidConnectDataMappingFormProps<TFieldValues> {
index: number,
}
/**
* Partial form to set the data mapping for an OpenID Connect provider.
* The data mapping is the way to bind data from the OIDC claims to the Fab-manager's database
*/
export const OpenidConnectDataMappingForm = <TFieldValues extends FieldValues>({ register, setValue, currentFormValues, index }: OpenidConnectDataMappingFormProps<TFieldValues>) => {
const { t } = useTranslation('admin');

View File

@ -20,6 +20,9 @@ interface OpenidConnectFormProps<TFieldValues, TContext extends object> {
setValue: UseFormSetValue<TFieldValues>,
}
/**
* Partial form to fill the OpenID Connect (OIDC) settings for a new/existing authentication provider.
*/
export const OpenidConnectForm = <TFieldValues extends FieldValues, TContext extends object>({ register, control, currentFormValues, formState, setValue }: OpenidConnectFormProps<TFieldValues, TContext>) => {
const { t } = useTranslation('admin');

View File

@ -168,7 +168,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
>
<Quotes size={24} />
</button>
<span className='divider'></span>
<span className='menu-divider'></span>
</>)
}
<button
@ -203,7 +203,7 @@ export const MenuBar: React.FC<MenuBarProps> = ({ editor, paragraphTools, video,
>
<LinkSimpleHorizontal size={24} />
</button>
{ (video || image) && <span className='divider'></span> }
{ (video || image) && <span className='menu-divider'></span> }
{ video &&
(<>
<button

View File

@ -13,6 +13,9 @@ interface EventCardProps {
cardType: 'sm' | 'md' | 'lg'
}
/**
* This component is a box showing the picture of the given event, and a short description of it.
*/
export const EventCard: React.FC<EventCardProps> = ({ event, cardType }) => {
const { t } = useTranslation('public');

View File

@ -30,6 +30,9 @@ interface ChangeGroupProps {
*/
type selectOption = { value: number, label: string };
/**
* Component to display the group of the provided user, and allow him to change his group.
*/
export const ChangeGroup: React.FC<ChangeGroupProps> = ({ user, onSuccess, onError, allowChange, className }) => {
const { t } = useTranslation('shared');

View File

@ -40,6 +40,9 @@ const MachineCard: React.FC<MachineCardProps> = ({ user, machine, onShowMachine,
onShowMachine(machine);
};
/**
* Return the machine's picture or a placeholder
*/
const machinePicture = (): ReactNode => {
if (!machine.machine_image) {
return <div className="machine-picture no-picture" />;
@ -82,10 +85,10 @@ const MachineCard: React.FC<MachineCardProps> = ({ user, machine, onShowMachine,
);
};
const MachineCardWrapper: React.FC<MachineCardProps> = ({ user, machine, onShowMachine, onReserveMachine, onError, onSuccess, onLoginRequested, onEnrollRequested, canProposePacks }) => {
const MachineCardWrapper: React.FC<MachineCardProps> = (props) => {
return (
<Loader>
<MachineCard user={user} machine={machine} onShowMachine={onShowMachine} onReserveMachine={onReserveMachine} onError={onError} onSuccess={onSuccess} onLoginRequested={onLoginRequested} onEnrollRequested={onEnrollRequested} canProposePacks={canProposePacks} />
<MachineCard {...props} />
</Loader>
);
};

View File

@ -12,6 +12,9 @@ interface MachinesFiltersProps {
*/
type selectOption = { value: boolean, label: string };
/**
* Allows filtering on machines list
*/
export const MachinesFilters: React.FC<MachinesFiltersProps> = ({ onStatusSelected }) => {
const { t } = useTranslation('public');

View File

@ -31,7 +31,7 @@ interface ReserveButtonProps {
/**
* Button component that makes the training verification before redirecting the user to the reservation calendar
*/
const ReserveButtonComponent: React.FC<ReserveButtonProps> = ({ currentUser, machineId, onLoginRequested, onLoadingStart, onLoadingEnd, onError, onSuccess, onReserveMachine, onEnrollRequested, className, children, canProposePacks }) => {
const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machineId, onLoginRequested, onLoadingStart, onLoadingEnd, onError, onSuccess, onReserveMachine, onEnrollRequested, className, children, canProposePacks }) => {
const { t } = useTranslation('shared');
const [machine, setMachine] = useState<Machine>(null);
@ -183,14 +183,16 @@ const ReserveButtonComponent: React.FC<ReserveButtonProps> = ({ currentUser, mac
);
};
export const ReserveButton: React.FC<ReserveButtonProps> = ({ currentUser, machineId, onLoginRequested, onLoadingStart, onLoadingEnd, onError, onSuccess, onReserveMachine, onEnrollRequested, className, children, canProposePacks }) => {
const ReserveButtonWrapper: React.FC<ReserveButtonProps> = (props) => {
return (
<Loader>
<ReserveButtonComponent currentUser={currentUser} machineId={machineId} onError={onError} onSuccess={onSuccess} onLoadingStart={onLoadingStart} onLoadingEnd={onLoadingEnd} onReserveMachine={onReserveMachine} onLoginRequested={onLoginRequested} onEnrollRequested={onEnrollRequested} className={className} canProposePacks={canProposePacks}>
{children}
</ReserveButtonComponent>
<ReserveButton {...props}>
{props.children}
</ReserveButton>
</Loader>
);
};
Application.Components.component('reserveButton', react2angular(ReserveButton, ['currentUser', 'machineId', 'onLoadingStart', 'onLoadingEnd', 'onError', 'onSuccess', 'onReserveMachine', 'onLoginRequested', 'onEnrollRequested', 'className', 'canProposePacks']));
export { ReserveButtonWrapper as ReserveButton };
Application.Components.component('reserveButton', react2angular(ReserveButtonWrapper, ['currentUser', 'machineId', 'onLoadingStart', 'onLoadingEnd', 'onError', 'onSuccess', 'onReserveMachine', 'onLoginRequested', 'onEnrollRequested', 'className', 'canProposePacks']));

View File

@ -123,6 +123,9 @@ const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSc
refreshList();
};
/**
* Return the JSX table element that list all payment schedules and allows to perform actions on them.
*/
const renderPaymentSchedulesTable = (): ReactElement => {
return (
<table className="payment-schedules-table">

View File

@ -19,6 +19,9 @@ interface UpdatePaymentMeanModalProps {
*/
type selectOption = { value: PaymentMethod, label: string };
/**
* Component to allow the member to change his payment mean for the given payment schedule (e.g. from card to transfer)
*/
export const UpdatePaymentMeanModal: React.FC<UpdatePaymentMeanModalProps> = ({ isOpen, toggleModal, onError, afterSuccess, paymentSchedule }) => {
const { t } = useTranslation('admin');

View File

@ -29,7 +29,7 @@ interface CardPaymentModalProps {
* This component open a modal dialog for the configured payment gateway, allowing the user to input his card data
* to process an online payment.
*/
const CardPaymentModalComponent: React.FC<CardPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, currentUser, schedule, cart, customer }) => {
const CardPaymentModal: React.FC<CardPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, currentUser, schedule, cart, customer }) => {
const { t } = useTranslation('shared');
const [gateway, setGateway] = useState<Setting>(null);
@ -89,12 +89,14 @@ const CardPaymentModalComponent: React.FC<CardPaymentModalProps> = ({ isOpen, to
}
};
export const CardPaymentModal: React.FC<CardPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, currentUser, schedule, cart, customer }) => {
const CardPaymentModalWrapper: React.FC<CardPaymentModalProps> = (props) => {
return (
<Loader>
<CardPaymentModalComponent isOpen={isOpen} toggleModal={toggleModal} afterSuccess={afterSuccess} onError={onError} currentUser={currentUser} schedule={schedule} cart={cart} customer={customer} />
<CardPaymentModal {...props} />
</Loader>
);
};
Application.Components.component('cardPaymentModal', react2angular(CardPaymentModal, ['isOpen', 'toggleModal', 'afterSuccess', 'onError', 'currentUser', 'schedule', 'cart', 'customer']));
export { CardPaymentModalWrapper as CardPaymentModal };
Application.Components.component('cardPaymentModal', react2angular(CardPaymentModalWrapper, ['isOpen', 'toggleModal', 'afterSuccess', 'onError', 'currentUser', 'schedule', 'cart', 'customer']));

View File

@ -28,7 +28,7 @@ interface LocalPaymentModalProps {
/**
* This component enables a privileged user to confirm a local payments.
*/
const LocalPaymentModalComponent: React.FC<LocalPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, cart, updateCart, currentUser, schedule, customer }) => {
const LocalPaymentModal: React.FC<LocalPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, cart, updateCart, currentUser, schedule, customer }) => {
const { t } = useTranslation('admin');
/**
@ -93,12 +93,14 @@ const LocalPaymentModalComponent: React.FC<LocalPaymentModalProps> = ({ isOpen,
);
};
export const LocalPaymentModal: React.FC<LocalPaymentModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, currentUser, schedule, cart, updateCart, customer }) => {
const LocalPaymentModalWrapper: React.FC<LocalPaymentModalProps> = (props) => {
return (
<Loader>
<LocalPaymentModalComponent isOpen={isOpen} toggleModal={toggleModal} afterSuccess={afterSuccess} onError={onError} currentUser={currentUser} schedule={schedule} cart={cart} updateCart={updateCart} customer={customer} />
<LocalPaymentModal {...props} />
</Loader>
);
};
Application.Components.component('localPaymentModal', react2angular(LocalPaymentModal, ['isOpen', 'toggleModal', 'afterSuccess', 'onError', 'currentUser', 'schedule', 'cart', 'updateCart', 'customer']));
export { LocalPaymentModalWrapper as LocalPaymentModal };
Application.Components.component('localPaymentModal', react2angular(LocalPaymentModalWrapper, ['isOpen', 'toggleModal', 'afterSuccess', 'onError', 'currentUser', 'schedule', 'cart', 'updateCart', 'customer']));

View File

@ -16,6 +16,9 @@ interface PayzenCardUpdateModalProps {
operator: User
}
/**
* Modal dialog to allow the member to update his payment card for a payment schedule, when the PayZen gateway is used
*/
export const PayzenCardUpdateModal: React.FC<PayzenCardUpdateModalProps> = ({ isOpen, toggleModal, onSuccess, schedule, operator }) => {
const { t } = useTranslation('shared');

View File

@ -143,6 +143,9 @@ export const PayzenForm: React.FC<PayzenFormProps> = ({ onSubmit, onSuccess, onE
}
};
/**
* Return a loader
*/
const Loader: FunctionComponent = () => {
return (
<div className={`fa-3x ${loadingClass}`}>
@ -154,7 +157,7 @@ export const PayzenForm: React.FC<PayzenFormProps> = ({ onSubmit, onSuccess, onE
return (
<form onSubmit={handleSubmit} id={formId} className={`payzen-form ${className || ''}`}>
<Loader />
<div className="container">
<div className="payzen-container">
<div id="payzenPaymentForm" />
</div>
{children}

View File

@ -28,7 +28,7 @@ let pendingKeysValidation = false;
/**
* Form to set the PayZen's username, password and public key
*/
const PayzenKeysFormComponent: React.FC<PayzenKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const PayzenKeysForm: React.FC<PayzenKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const { t } = useTranslation('admin');
// values of the PayZen settings
@ -205,10 +205,12 @@ const PayzenKeysFormComponent: React.FC<PayzenKeysFormProps> = ({ onValidKeys, o
);
};
export const PayzenKeysForm: React.FC<PayzenKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const PayzenKeysFormWrapper: React.FC<PayzenKeysFormProps> = (props) => {
return (
<Loader>
<PayzenKeysFormComponent onValidKeys={onValidKeys} onInvalidKeys={onInvalidKeys} />
<PayzenKeysForm {...props} />
</Loader>
);
};
export { PayzenKeysFormWrapper as PayzenKeysForm };

View File

@ -16,6 +16,9 @@ interface StripeCardUpdateModalProps {
operator: User
}
/**
* Modal dialog to allow the member to update his payment card for a payment schedule, when the Stripe gateway is used
*/
export const StripeCardUpdateModal: React.FC<StripeCardUpdateModalProps> = ({ isOpen, toggleModal, onSuccess, schedule, operator }) => {
const { t } = useTranslation('shared');
@ -30,7 +33,7 @@ export const StripeCardUpdateModal: React.FC<StripeCardUpdateModalProps> = ({ is
const logoFooter = (): ReactNode => {
return (
<div className="stripe-modal-icons">
<i className="fa fa-lock fa-2x m-r-sm pos-rlt" />
<i className="fa fa-lock fa-2x" />
<img src={stripeLogo} alt="powered by stripe" />
<img src={mastercardLogo} alt="mastercard" />
<img src={visaLogo} alt="visa" />

View File

@ -15,7 +15,7 @@ interface StripeKeysFormProps {
/**
* Form to set the stripe's public and private keys
*/
const StripeKeysFormComponent: React.FC<StripeKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const StripeKeysForm: React.FC<StripeKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const { t } = useTranslation('admin');
// used to prevent promises from resolving if the component was unmounted
@ -153,10 +153,12 @@ const StripeKeysFormComponent: React.FC<StripeKeysFormProps> = ({ onValidKeys, o
);
};
export const StripeKeysForm: React.FC<StripeKeysFormProps> = ({ onValidKeys, onInvalidKeys }) => {
const StripeKeysFormWrapper: React.FC<StripeKeysFormProps> = (props) => {
return (
<Loader>
<StripeKeysFormComponent onValidKeys={onValidKeys} onInvalidKeys={onInvalidKeys} />
<StripeKeysForm {...props} />
</Loader>
);
};
export { StripeKeysFormWrapper as StripeKeysForm };

View File

@ -36,7 +36,7 @@ export const StripeModal: React.FC<StripeModalProps> = ({ isOpen, toggleModal, a
const logoFooter = (): ReactNode => {
return (
<div className="stripe-modal-icons">
<i className="fa fa-lock fa-2x m-r-sm pos-rlt" />
<i className="fa fa-lock fa-2x" />
<img src={stripeLogo} alt="powered by stripe" />
<img src={mastercardLogo} alt="mastercard" />
<img src={visaLogo} alt="visa" />

View File

@ -19,7 +19,7 @@ interface UpdateCardModalProps {
* This component open a modal dialog for the configured payment gateway, allowing the user to input his card data
* to process an online payment.
*/
const UpdateCardModalComponent: React.FC<UpdateCardModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, operator, schedule }) => {
const UpdateCardModal: React.FC<UpdateCardModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, operator, schedule }) => {
const { t } = useTranslation('shared');
const [gateway, setGateway] = useState<string>('');
@ -68,10 +68,12 @@ const UpdateCardModalComponent: React.FC<UpdateCardModalProps> = ({ isOpen, togg
}
};
export const UpdateCardModal: React.FC<UpdateCardModalProps> = ({ isOpen, toggleModal, afterSuccess, onError, operator, schedule }) => {
const UpdateCardModalWrapper: React.FC<UpdateCardModalProps> = (props) => {
return (
<Loader>
<UpdateCardModalComponent isOpen={isOpen} toggleModal={toggleModal} afterSuccess={afterSuccess} onError={onError} operator={operator} schedule={schedule} />
<UpdateCardModal {...props} />
</Loader>
);
};
export { UpdateCardModalWrapper as UpdateCardModal };

View File

@ -16,7 +16,7 @@ interface DeletePlanCategoryProps {
* This component shows a button.
* When clicked, we show a modal dialog to ask the user for confirmation about the deletion of the provided plan-category.
*/
const DeletePlanCategoryComponent: React.FC<DeletePlanCategoryProps> = ({ onSuccess, onError, category }) => {
const DeletePlanCategory: React.FC<DeletePlanCategoryProps> = ({ onSuccess, onError, category }) => {
const { t } = useTranslation('admin');
const [deletionModal, setDeletionModal] = useState<boolean>(false);
@ -56,10 +56,12 @@ const DeletePlanCategoryComponent: React.FC<DeletePlanCategoryProps> = ({ onSucc
);
};
export const DeletePlanCategory: React.FC<DeletePlanCategoryProps> = ({ onSuccess, onError, category }) => {
const DeletePlanCategoryWrapper: React.FC<DeletePlanCategoryProps> = (props) => {
return (
<Loader>
<DeletePlanCategoryComponent onSuccess={onSuccess} onError={onError} category={category} />
<DeletePlanCategory {...props} />
</Loader>
);
};
export { DeletePlanCategoryWrapper as DeletePlanCategory };

View File

@ -17,7 +17,7 @@ interface ManagePlanCategoryProps {
* This component shows a button.
* When clicked, we show a modal dialog allowing to fill the parameters of a plan-category (create new or update existing).
*/
const ManagePlanCategoryComponent: React.FC<ManagePlanCategoryProps> = ({ category, action, onSuccess, onError }) => {
const ManagePlanCategory: React.FC<ManagePlanCategoryProps> = ({ category, action, onSuccess, onError }) => {
const { t } = useTranslation('admin');
// is the creation modal open?
@ -61,7 +61,7 @@ const ManagePlanCategoryComponent: React.FC<ManagePlanCategoryProps> = ({ catego
return (
<FabButton type='button'
icon={<i className='fa fa-plus' />}
className="btn-warning"
className="create-button"
onClick={toggleModal}>
{t('app.admin.manage_plan_category.create_category.title')}
</FabButton>
@ -90,10 +90,12 @@ const ManagePlanCategoryComponent: React.FC<ManagePlanCategoryProps> = ({ catego
);
};
export const ManagePlanCategory: React.FC<ManagePlanCategoryProps> = ({ category, action, onSuccess, onError }) => {
const ManagePlanCategoryWrapper: React.FC<ManagePlanCategoryProps> = (props) => {
return (
<Loader>
<ManagePlanCategoryComponent category={category} action={action} onSuccess={onSuccess} onError={onError} />
<ManagePlanCategory {...props} />
</Loader>
);
};
export { ManagePlanCategoryWrapper as ManagePlanCategory };

View File

@ -16,7 +16,10 @@ interface PlanCategoryFormProps {
onError: (message: string) => void
}
const PlanCategoryFormComponent: React.FC<PlanCategoryFormProps> = ({ action, category, onSuccess, onError }) => {
/**
* Form to create/edit a plan category
*/
const PlanCategoryForm: React.FC<PlanCategoryFormProps> = ({ action, category, onSuccess, onError }) => {
const { t } = useTranslation('admin');
const { register, control, handleSubmit } = useForm<PlanCategory>({ defaultValues: { ...category } });
@ -58,10 +61,12 @@ const PlanCategoryFormComponent: React.FC<PlanCategoryFormProps> = ({ action, ca
);
};
export const PlanCategoryForm: React.FC<PlanCategoryFormProps> = ({ action, category, onSuccess, onError }) => {
const PlanCategoryFormWrapper: React.FC<PlanCategoryFormProps> = (props) => {
return (
<Loader>
<PlanCategoryFormComponent action={action} category={category} onSuccess={onSuccess} onError={onError} />
<PlanCategoryForm {...props} />
</Loader>
);
};
export { PlanCategoryFormWrapper as PlanCategoryForm };

View File

@ -20,6 +20,9 @@ interface PlansFilterProps {
*/
type selectOption = { value: number, label: string };
/**
* Allows filtering on plans list
*/
export const PlansFilter: React.FC<PlansFilterProps> = ({ user, groups, onGroupSelected, onError, onDurationSelected }) => {
const { t } = useTranslation('public');

View File

@ -14,6 +14,7 @@ import { react2angular } from 'react2angular';
import { IApplication } from '../../models/application';
import { PrepaidPack } from '../../models/prepaid-pack';
import PrepaidPackAPI from '../../api/prepaid-pack';
import { FabAlert } from '../base/fab-alert';
declare const Application: IApplication;
@ -29,7 +30,11 @@ interface PacksSummaryProps {
refresh?: Promise<void>
}
const PacksSummaryComponent: React.FC<PacksSummaryProps> = ({ item, itemType, customer, operator, onError, onSuccess, refresh }) => {
/**
* Display a short summary of the prepaid-packs already bought by the provider customer, for the given item.
* May also allows members to buy directly some new prepaid-packs.
*/
const PacksSummary: React.FC<PacksSummaryProps> = ({ item, itemType, customer, operator, onError, onSuccess, refresh }) => {
const { t } = useTranslation('logged');
const [packs, setPacks] = useState<Array<PrepaidPack>>(null);
@ -140,9 +145,9 @@ const PacksSummaryComponent: React.FC<PacksSummaryProps> = ({ item, itemType, cu
<span className="remaining-hours">
{t('app.logged.packs_summary.remaining_HOURS', { HOURS: totalHours(), ITEM: itemType })}
{isPackOnlyForSubscription && !customer.subscribed_plan &&
<div className="alert alert-warning m-t m-b">
<FabAlert level="warning">
{t('app.logged.packs_summary.unable_to_use_pack_for_subsription_is_expired')}
</div>
</FabAlert>
}
</span>
</div>
@ -178,12 +183,14 @@ const PacksSummaryComponent: React.FC<PacksSummaryProps> = ({ item, itemType, cu
);
};
export const PacksSummary: React.FC<PacksSummaryProps> = ({ item, itemType, customer, operator, onError, onSuccess, refresh }) => {
const PacksSummaryWrapper: React.FC<PacksSummaryProps> = (props) => {
return (
<Loader>
<PacksSummaryComponent item={item} itemType={itemType} customer={customer} operator={operator} onError={onError} onSuccess={onSuccess} refresh={refresh} />
<PacksSummary {...props} />
</Loader>
);
};
Application.Components.component('packsSummary', react2angular(PacksSummary, ['item', 'itemType', 'customer', 'operator', 'onError', 'onSuccess', 'refresh']));
export { PacksSummaryWrapper as PacksSummary };
Application.Components.component('packsSummary', react2angular(PacksSummaryWrapper, ['item', 'itemType', 'customer', 'operator', 'onError', 'onSuccess', 'refresh']));

View File

@ -16,7 +16,7 @@ interface DeletePackProps {
* This component shows a button.
* When clicked, we show a modal dialog to ask the user for confirmation about the deletion of the provided pack.
*/
const DeletePackComponent: React.FC<DeletePackProps> = ({ onSuccess, onError, pack }) => {
const DeletePack: React.FC<DeletePackProps> = ({ onSuccess, onError, pack }) => {
const { t } = useTranslation('admin');
const [deletionModal, setDeletionModal] = useState<boolean>(false);
@ -56,10 +56,12 @@ const DeletePackComponent: React.FC<DeletePackProps> = ({ onSuccess, onError, pa
);
};
export const DeletePack: React.FC<DeletePackProps> = ({ onSuccess, onError, pack }) => {
const DeletePackWrapper: React.FC<DeletePackProps> = (props) => {
return (
<Loader>
<DeletePackComponent onSuccess={onSuccess} onError={onError} pack={pack} />
<DeletePack {...props} />
</Loader>
);
};
export { DeletePackWrapper as DeletePack };

View File

@ -20,6 +20,13 @@ interface ProfileFormOptionProps {
onSuccess: (user: User) => void,
}
/**
* After first logged-in from a SSO, the user has two options:
* - complete his profile (*) ;
* - bind his profile to his existing account ;
* (*) This component handle the first case.
* It also deals with duplicate email addresses in database
*/
export const ProfileFormOption: React.FC<ProfileFormOptionProps> = ({ user, activeProvider, onError, onSuccess }) => {
const { t } = useTranslation('logged');

View File

@ -97,10 +97,10 @@ export const BooleanSetting: React.FC<BooleanSettingProps> = ({ name, label, cla
};
return (
<div className={`boolean-setting form-group ${className || ''}`}>
<label htmlFor={`setting-${name}`} className="control-label m-r">{label}</label>
<Switch checked={value} id={`setting-${name}}`} onChange={handleChanged} className="v-middle"></Switch>
{!hideSave && <FabButton className="btn btn-warning m-l" onClick={handleSave}>{t('app.admin.check_list_setting.save')}</FabButton> }
<div className={`boolean-setting ${className || ''}`}>
<label htmlFor={`setting-${name}`}>{label}</label>
<Switch checked={value} id={`setting-${name}}`} onChange={handleChanged} className="switch"></Switch>
{!hideSave && <FabButton className="save-btn" onClick={handleSave}>{t('app.admin.check_list_setting.save')}</FabButton> }
</div>
);
};

View File

@ -8,6 +8,7 @@ import { Loader } from '../base/loader';
import { FabButton } from '../base/fab-button';
import { BooleanSetting } from './boolean-setting';
import { CheckListSetting } from './check-list-setting';
import { FabAlert } from '../base/fab-alert';
declare const Application: IApplication;
@ -82,9 +83,9 @@ export const UserValidationSetting: React.FC<UserValidationSettingProps> = ({ on
<p>
{t('app.admin.settings.compte.user_validation_required_list_info')}
</p>
<p className="alert alert-warning">
<FabAlert level="warning">
{t('app.admin.settings.compte.user_validation_required_list_other_info')}
</p>
</FabAlert>
<CheckListSetting name={SettingName.UserValidationRequiredList}
label=""
availableOptions={userValidationRequiredOptions}
@ -96,7 +97,7 @@ export const UserValidationSetting: React.FC<UserValidationSettingProps> = ({ on
</CheckListSetting>
</div>
}
<FabButton className="btn btn-warning m-t" onClick={handleSave}>{t('app.admin.check_list_setting.save')}</FabButton>
<FabButton className="save-btn" onClick={handleSave}>{t('app.admin.check_list_setting.save')}</FabButton>
</div>
);
};

View File

@ -16,6 +16,9 @@ interface EditSocialsProps<TFieldValues> {
disabled: boolean|((id: string) => boolean),
}
/**
* Allow a user to edit its personnal social networks
*/
export const EditSocials = <TFieldValues extends FieldValues>({ register, setValue, networks, formState, disabled }: EditSocialsProps<TFieldValues>) => {
const { t } = useTranslation('shared');
// regular expression to validate the the input fields
@ -23,10 +26,17 @@ export const EditSocials = <TFieldValues extends FieldValues>({ register, setVal
const initSelectedNetworks = networks.filter(el => !['', null, undefined].includes(el.url));
const [selectedNetworks, setSelectedNetworks] = useState(initSelectedNetworks);
/**
* Callback triggered when the user adds a network, from the list of available networks, to the editable networks.
*/
const selectNetwork = (network) => {
setSelectedNetworks([...selectedNetworks, network]);
};
/**
* Return a derivated state of the selected networks list, depending on the given action.
*/
const reducer = (state, action) => {
switch (action.type) {
case 'delete':

View File

@ -20,6 +20,9 @@ interface FabSocialsProps {
onSuccess: (message: string) => void
}
/**
* Allows the Fablab to edit its corporate social networks, or to display them read-only to the end users (show=true)
*/
export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, onSuccess }) => {
const { t } = useTranslation('shared');
// regular expression to validate the the input fields
@ -42,6 +45,9 @@ export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, o
setSelectedNetworks(fabNetworks.filter(el => el.url !== ''));
}, [fabNetworks]);
/**
* Callback triggered when the social networks are saved
*/
const onSubmit = (data) => {
const updatedNetworks = new Map<SettingName, string>();
Object.keys(data).forEach(key => updatedNetworks.set(key as SettingName, data[key]));
@ -55,17 +61,24 @@ export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, o
});
};
/**
* Callback triggered when the user adds a network, from the list of available networks, to the editable networks.
*/
const selectNetwork = (network) => {
setSelectedNetworks([...selectedNetworks, network]);
};
/**
* Callback triggered when the user removes a network, from the list of editables networks, add put it back to the
* list of avaiable networks.
*/
const remove = (network) => {
setSelectedNetworks(selectedNetworks.filter(el => el !== network));
setValue(network.name, '');
};
return (
<>{show
<div className="fab-socials">{show
? (selectedNetworks.length > 0) && <>
<h2>{t('app.shared.fab_socials.follow_us')}</h2>
<div className='social-icons'>
@ -107,11 +120,11 @@ export const FabSocials: React.FC<FabSocialsProps> = ({ show = false, onError, o
)}
</div>}
<FabButton type='submit'
className='btn-warning'>
className='save-btn'>
{t('app.shared.buttons.save')}
</FabButton>
</form>
}</>
}</div>
);
};

View File

@ -6,6 +6,7 @@ import { User } from '../../models/user';
import { IApplication } from '../../models/application';
import { react2angular } from 'react2angular';
import MemberAPI from '../../api/member';
import { TDateISO } from '../../typings/date-iso';
declare const Application: IApplication;
@ -34,7 +35,7 @@ export const UserValidation: React.FC<UserValidationProps> = ({ member, onSucces
setValue(_value);
const _member = _.clone(member);
if (_value) {
_member.validated_at = new Date();
_member.validated_at = new Date().toISOString() as TDateISO;
} else {
_member.validated_at = null;
}
@ -49,8 +50,8 @@ export const UserValidation: React.FC<UserValidationProps> = ({ member, onSucces
return (
<div className="user-validation">
<label htmlFor="user-validation-switch" className="control-label m-r">{t('app.admin.members_edit.validate_account')}</label>
<Switch checked={value} id="user-validation-switch" onChange={handleChanged} className="v-middle"></Switch>
<label htmlFor="user-validation-switch">{t('app.admin.members_edit.validate_account')}</label>
<Switch checked={value} id="user-validation-switch" onChange={handleChanged} className="switch"></Switch>
</div>
);
};

View File

@ -1,13 +1,5 @@
// from https://gist.github.com/MrChocolatine/367fb2a35d02f6175cc8ccb3d3a20054
interface Date {
/**
* Give a more precise return type to the method `toISOString()`:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString
*/
toISOString(): TDateISO;
}
type TYear = `${number}${number}${number}${number}`;
type TMonth = `${number}${number}`;
type TDay = `${number}${number}`;

View File

@ -76,7 +76,10 @@
@import "modules/profile-completion/completion-header-info";
@import "modules/profile-completion/profile-form-option";
@import "modules/select-gateway-modal";
@import "modules/settings/boolean-setting";
@import "modules/settings/check-list-setting";
@import "modules/settings/user-validation-setting";
@import "modules/socials/fab-socials";
@import "modules/subscriptions/free-extend-modal";
@import "modules/subscriptions/renew-modal";
@import "modules/user/avatar";

View File

@ -39,7 +39,7 @@
}
button { @include button(4rem); }
.divider {
.menu-divider {
width: 2px;
height: 2.4rem;
background-color: var(--gray-soft-dark);

View File

@ -24,7 +24,7 @@
left: 190px;
z-index: 1;
}
.container {
.payzen-container {
display: flex;
justify-content: center;
width: inherit;

View File

@ -12,7 +12,7 @@
left: 190px;
z-index: 1;
}
.container {
.payzen-container {
display: flex;
justify-content: center;
width: inherit;

View File

@ -47,6 +47,8 @@
.fa.fa-lock {
top: 7px;
color: #9edd78;
margin-right: 10px;
position: relative;
}
img {

View File

@ -5,6 +5,8 @@
.fa.fa-lock {
top: 7px;
color: #9edd78;
margin-right: 10px;
position: relative;
}
img {

View File

@ -1,4 +1,10 @@
.manage-plan-category {
display: inline;
margin-right: 5px;
.create-button {
background-color: var(--secondary-dark);
border-color: var(--secondary-dark);
color: var(--secondary-text-color);
}
}

View File

@ -16,6 +16,13 @@
.content {
padding: 15px;
.remaining-hours {
.fab-alert {
margin-top: 15px;
margin-bottom: 15px;
}
}
.button-wrapper {
text-align: center;

View File

@ -0,0 +1,18 @@
.boolean-setting {
margin-bottom: 15px;
label {
margin-bottom: 0;
vertical-align: middle;
margin-right: 15px;
}
.switch {
vertical-align: middle;
}
.save-btn {
background-color: var(--secondary-dark);
border-color: var(--secondary-dark);
color: var(--secondary-text-color);
margin-left: 15px;
}
}

View File

@ -0,0 +1,8 @@
.user-validation-setting {
.save-btn {
background-color: var(--secondary-dark);
border-color: var(--secondary-dark);
color: var(--secondary-text-color);
margin-top: 15px;
}
}

View File

@ -0,0 +1,7 @@
.fab-socials {
.save-btn {
background-color: var(--secondary-dark);
border-color: var(--secondary-dark);
color: var(--secondary-text-color);
}
}

View File

@ -0,0 +1,11 @@
.user-validation {
label {
margin-bottom: 0;
vertical-align: middle;
margin-right: 15px;
}
.switch {
vertical-align: middle;
}
}

View File

@ -25,7 +25,7 @@
"@typescript-eslint/parser": "^5.17.0",
"eslint": "~8.12.0",
"eslint-config-standard": "~17.0.0-1",
"eslint-plugin-fabmanager": "^0.4.2",
"eslint-plugin-fabmanager": "^0.4.8",
"eslint-plugin-html-erb": "^1.0.1",
"eslint-plugin-import": "~2.25.4",
"eslint-plugin-n": "^15.1.0",

View File

@ -4082,10 +4082,10 @@ eslint-plugin-es@^4.1.0:
eslint-utils "^2.0.0"
regexpp "^3.0.0"
eslint-plugin-fabmanager@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-fabmanager/-/eslint-plugin-fabmanager-0.4.2.tgz#87f18b13a29fe77dcbb9cb8c4a996b0b108f8a07"
integrity sha512-3SKm4YXXzrgQYnaCmk0/QLh+2YaCSMAZFazC7fFB57BBo0PR70YMrGNoyiEW4oQ52qYNeIMwlFHHNPEgWfcwsw==
eslint-plugin-fabmanager@^0.4.8:
version "0.4.8"
resolved "https://registry.yarnpkg.com/eslint-plugin-fabmanager/-/eslint-plugin-fabmanager-0.4.8.tgz#2104feddee06fa0245e64a3b8491412b17dcd16e"
integrity sha512-Heey9vsr2WmRjY4JOskwWK8H2qgfR9nVX0osQyOb5bc+r6gQPci0Q0eECcN3pT9tXjLl2oL0oxWA5DFhleBi2A==
dependencies:
requireindex "^1.2.0"