1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-18 07:52:23 +01:00

(lint) add rule to check component class naming

This commit is contained in:
Sylvain 2022-05-24 17:55:19 +02:00 committed by Sylvain
parent 727f2d3d80
commit ca9eec8579
13 changed files with 47 additions and 20 deletions

View File

@ -6,7 +6,9 @@
], ],
"rules": { "rules": {
"semi": ["error", "always"], "semi": ["error", "always"],
"no-use-before-define": "off" "no-use-before-define": "off",
"fabmanager/component-class-named-as-component": "error",
"import/no-default-export": "error"
}, },
"globals": { "globals": {
"Application": true, "Application": true,
@ -19,7 +21,7 @@
"$": true, "$": true,
"KeyboardEvent": true "KeyboardEvent": true
}, },
"plugins": ["html-erb"], "plugins": ["html-erb", "fabmanager"],
"overrides": [ "overrides": [
{ {
"files": ["**/*.ts", "**/*.tsx"], "files": ["**/*.ts", "**/*.tsx"],

View File

@ -101,4 +101,5 @@ export const FabTextEditor: React.ForwardRefRenderFunction<FabTextEditorRef, Fab
); );
}; };
// eslint-disable-next-line import/no-default-export
export default forwardRef(FabTextEditor); export default forwardRef(FabTextEditor);

View File

@ -21,7 +21,7 @@ interface MachineCardProps {
* This component is a box showing the picture of the given machine and two buttons: one to start the reservation process * This component is a box showing the picture of the given machine and two buttons: one to start the reservation process
* and another to redirect the user to the machine description page. * and another to redirect the user to the machine description page.
*/ */
const MachineCardComponent: React.FC<MachineCardProps> = ({ user, machine, onShowMachine, onReserveMachine, onError, onSuccess, onLoginRequested, onEnrollRequested, canProposePacks }) => { const MachineCard: React.FC<MachineCardProps> = ({ user, machine, onShowMachine, onReserveMachine, onError, onSuccess, onLoginRequested, onEnrollRequested, canProposePacks }) => {
const { t } = useTranslation('public'); const { t } = useTranslation('public');
// shall we display a loader to prevent double-clicking, while the machine details are loading? // shall we display a loader to prevent double-clicking, while the machine details are loading?
@ -82,10 +82,12 @@ const MachineCardComponent: React.FC<MachineCardProps> = ({ user, machine, onSho
); );
}; };
export const MachineCard: React.FC<MachineCardProps> = ({ user, machine, onShowMachine, onReserveMachine, onError, onSuccess, onLoginRequested, onEnrollRequested, canProposePacks }) => { const MachineCardWrapper: React.FC<MachineCardProps> = ({ user, machine, onShowMachine, onReserveMachine, onError, onSuccess, onLoginRequested, onEnrollRequested, canProposePacks }) => {
return ( return (
<Loader> <Loader>
<MachineCardComponent user={user} machine={machine} onShowMachine={onShowMachine} onReserveMachine={onReserveMachine} onError={onError} onSuccess={onSuccess} onLoginRequested={onLoginRequested} onEnrollRequested={onEnrollRequested} canProposePacks={canProposePacks} /> <MachineCard user={user} machine={machine} onShowMachine={onShowMachine} onReserveMachine={onReserveMachine} onError={onError} onSuccess={onSuccess} onLoginRequested={onLoginRequested} onEnrollRequested={onEnrollRequested} canProposePacks={canProposePacks} />
</Loader> </Loader>
); );
}; };
export { MachineCardWrapper as MachineCard };

View File

@ -3,11 +3,12 @@ import { FabModal } from '../base/fab-modal';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { HtmlTranslate } from '../base/html-translate'; import { HtmlTranslate } from '../base/html-translate';
import FormatLib from '../../lib/format'; import FormatLib from '../../lib/format';
import { TDateISO } from '../../typings/date-iso';
interface PendingTrainingModalProps { interface PendingTrainingModalProps {
isOpen: boolean, isOpen: boolean,
toggleModal: () => void, toggleModal: () => void,
nextReservation: Date, nextReservation: TDateISO,
} }
/** /**
@ -20,7 +21,7 @@ export const PendingTrainingModal: React.FC<PendingTrainingModalProps> = ({ isOp
/** /**
* Return the formatted localized date for the given date * Return the formatted localized date for the given date
*/ */
const formatDateTime = (date: Date): string => { const formatDateTime = (date: TDateISO): string => {
return t('app.logged.pending_training_modal.DATE_TIME', { DATE: FormatLib.date(date), TIME: FormatLib.time(date) }); return t('app.logged.pending_training_modal.DATE_TIME', { DATE: FormatLib.date(date), TIME: FormatLib.time(date) });
}; };

View File

@ -26,7 +26,7 @@ interface PaymentSchedulesTableProps {
/** /**
* This component shows a list of all payment schedules with their associated deadlines (aka. PaymentScheduleItem) and invoices * This component shows a list of all payment schedules with their associated deadlines (aka. PaymentScheduleItem) and invoices
*/ */
const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer, refreshList, operator, onError, onCardUpdateSuccess }) => { const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer, refreshList, operator, onError, onCardUpdateSuccess }) => {
const { t } = useTranslation('shared'); const { t } = useTranslation('shared');
// for each payment schedule: are the details (all deadlines) shown or hidden? // for each payment schedule: are the details (all deadlines) shown or hidden?
@ -68,8 +68,10 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
*/ */
const expandCollapseIcon = (paymentScheduleId: number): JSX.Element => { const expandCollapseIcon = (paymentScheduleId: number): JSX.Element => {
if (isExpanded(paymentScheduleId)) { if (isExpanded(paymentScheduleId)) {
// eslint-disable-next-line fabmanager/component-class-named-as-component
return <i className="fas fa-minus-square" />; return <i className="fas fa-minus-square" />;
} else { } else {
// eslint-disable-next-line fabmanager/component-class-named-as-component
return <i className="fas fa-plus-square" />; return <i className="fas fa-plus-square" />;
} }
}; };
@ -93,6 +95,7 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
const downloadScheduleButton = (id: number): JSX.Element => { const downloadScheduleButton = (id: number): JSX.Element => {
const link = `api/payment_schedules/${id}/download`; const link = `api/payment_schedules/${id}/download`;
return ( return (
// eslint-disable-next-line fabmanager/component-class-named-as-component
<a href={link} target="_blank" className="download-button" rel="noreferrer"> <a href={link} target="_blank" className="download-button" rel="noreferrer">
<i className="fas fa-download" /> <i className="fas fa-download" />
{t('app.shared.schedules_table.download')} {t('app.shared.schedules_table.download')}
@ -109,6 +112,7 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
const key = `app.shared.schedules_table.method_${item.payment_method}`; const key = `app.shared.schedules_table.method_${item.payment_method}`;
res += ` (${t(key)})`; res += ` (${t(key)})`;
} }
// eslint-disable-next-line fabmanager/component-class-named-as-component
return <span className={`state-${item.state}`}>{res}</span>; return <span className={`state-${item.state}`}>{res}</span>;
}; };
@ -121,7 +125,7 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
const renderPaymentSchedulesTable = (): ReactElement => { const renderPaymentSchedulesTable = (): ReactElement => {
return ( return (
<table className="schedules-table"> <table className="payment-schedules-table">
<thead> <thead>
<tr> <tr>
<th className="w-35" /> <th className="w-35" />
@ -212,12 +216,14 @@ const PaymentSchedulesTableComponent: React.FC<PaymentSchedulesTableProps> = ({
return <div />; return <div />;
} }
}; };
PaymentSchedulesTableComponent.defaultProps = { showCustomer: false }; PaymentSchedulesTable.defaultProps = { showCustomer: false };
export const PaymentSchedulesTable: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer, refreshList, operator, onError, onCardUpdateSuccess }) => { const PaymentSchedulesTableWrapper: React.FC<PaymentSchedulesTableProps> = ({ paymentSchedules, showCustomer, refreshList, operator, onError, onCardUpdateSuccess }) => {
return ( return (
<Loader> <Loader>
<PaymentSchedulesTableComponent paymentSchedules={paymentSchedules} showCustomer={showCustomer} refreshList={refreshList} operator={operator} onError={onError} onCardUpdateSuccess={onCardUpdateSuccess} /> <PaymentSchedulesTable paymentSchedules={paymentSchedules} showCustomer={showCustomer} refreshList={refreshList} operator={operator} onError={onError} onCardUpdateSuccess={onCardUpdateSuccess} />
</Loader> </Loader>
); );
}; };
export { PaymentSchedulesTableWrapper as PaymentSchedulesTable };

View File

@ -203,7 +203,7 @@ export const AbstractPaymentModal: React.FC<AbstractPaymentModalProps> = ({ isOp
width={modalSize} width={modalSize}
closeButton={false} closeButton={false}
customFooter={logoFooter} customFooter={logoFooter}
className={`payment-modal ${className || ''}`}> className={`abstract-payment-modal ${className || ''}`}>
{ready && <div> {ready && <div>
<WalletInfo cart={cart} currentUser={currentUser} wallet={wallet} price={price?.price} /> <WalletInfo cart={cart} currentUser={currentUser} wallet={wallet} price={price?.price} />
<GatewayForm onSubmit={handleSubmit} <GatewayForm onSubmit={handleSubmit}

View File

@ -22,7 +22,7 @@ interface PlanCardProps {
/** /**
* This component is a "card" (visually), publicly presenting the details of a plan and allowing a user to subscribe. * This component is a "card" (visually), publicly presenting the details of a plan and allowing a user to subscribe.
*/ */
const PlanCardComponent: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected, onLoginRequested, canSelectPlan }) => { const PlanCard: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected, onLoginRequested, canSelectPlan }) => {
const { t } = useTranslation('public'); const { t } = useTranslation('public');
/** /**
* Return the formatted localized amount of the given plan (eg. 20.5 => "20,50 €") * Return the formatted localized amount of the given plan (eg. 20.5 => "20,50 €")
@ -144,10 +144,12 @@ const PlanCardComponent: React.FC<PlanCardProps> = ({ plan, userId, subscribedPl
); );
}; };
export const PlanCard: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected, onLoginRequested, canSelectPlan }) => { const PlanCardWrapper: React.FC<PlanCardProps> = ({ plan, userId, subscribedPlanId, operator, onSelectPlan, isSelected, onLoginRequested, canSelectPlan }) => {
return ( return (
<Loader> <Loader>
<PlanCardComponent plan={plan} userId={userId} subscribedPlanId={subscribedPlanId} operator={operator} isSelected={isSelected} onSelectPlan={onSelectPlan} onLoginRequested={onLoginRequested} canSelectPlan={canSelectPlan}/> <PlanCard plan={plan} userId={userId} subscribedPlanId={subscribedPlanId} operator={operator} isSelected={isSelected} onSelectPlan={onSelectPlan} onLoginRequested={onLoginRequested} canSelectPlan={canSelectPlan}/>
</Loader> </Loader>
); );
}; };
export { PlanCardWrapper as PlanCard };

View File

@ -30,6 +30,13 @@ export const EditablePrice: React.FC<EditablePriceProps> = ({ price, onSave }) =
toggleEdit(); toggleEdit();
}; };
/**
* Callback triggered when the user input a new price
*/
const handleChangePrice = (value: string): void => {
setTempPrice(value);
};
/** /**
* Enable or disable the edit mode * Enable or disable the edit mode
*/ */
@ -41,7 +48,7 @@ export const EditablePrice: React.FC<EditablePriceProps> = ({ price, onSave }) =
<span className="editable-price"> <span className="editable-price">
{!edit && <span className="display-price" onClick={toggleEdit}>{FormatLib.price(price.amount)}</span>} {!edit && <span className="display-price" onClick={toggleEdit}>{FormatLib.price(price.amount)}</span>}
{edit && <span> {edit && <span>
<FabInput id="price" type="number" step={0.01} defaultValue={price.amount} addOn={Fablab.intl_currency} onChange={setTempPrice} required/> <FabInput id="price" type="number" step={0.01} defaultValue={price.amount} addOn={Fablab.intl_currency} onChange={handleChangePrice} required/>
<FabButton icon={<i className="fas fa-check" />} className="approve-button" onClick={handleValidateEdit} /> <FabButton icon={<i className="fas fa-check" />} className="approve-button" onClick={handleValidateEdit} />
<FabButton icon={<i className="fas fa-times" />} className="cancel-button" onClick={toggleEdit} /> <FabButton icon={<i className="fas fa-times" />} className="cancel-button" onClick={toggleEdit} />
</span>} </span>}

View File

@ -44,7 +44,7 @@
@import "modules/payment-schedule/payment-schedules-list"; @import "modules/payment-schedule/payment-schedules-list";
@import "modules/payment-schedule/payment-schedules-table"; @import "modules/payment-schedule/payment-schedules-table";
@import "modules/payment/local-payment/local-payment-modal"; @import "modules/payment/local-payment/local-payment-modal";
@import "modules/payment/payment-modal"; @import "modules/payment/abstract-payment-modal";
@import "modules/payment/payzen/payzen-keys-form"; @import "modules/payment/payzen/payzen-keys-form";
@import "modules/payment/payzen/payzen-modal"; @import "modules/payment/payzen/payzen-modal";
@import "modules/payment/payzen/payzen-settings"; @import "modules/payment/payzen/payzen-settings";

View File

@ -1,4 +1,4 @@
.schedules-table { .payment-schedules-table {
table-layout: fixed; table-layout: fixed;
border: 1px solid #e9e9e9; border: 1px solid #e9e9e9;
border-top: 0; border-top: 0;

View File

@ -1,4 +1,4 @@
.payment-modal { .abstract-payment-modal {
.fab-modal-content { .fab-modal-content {
padding-bottom: 0; padding-bottom: 0;
} }

View File

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

View File

@ -4082,6 +4082,11 @@ eslint-plugin-es@^4.1.0:
eslint-utils "^2.0.0" eslint-utils "^2.0.0"
regexpp "^3.0.0" regexpp "^3.0.0"
eslint-plugin-fabmanager@^0.0.13:
version "0.0.13"
resolved "https://registry.yarnpkg.com/eslint-plugin-fabmanager/-/eslint-plugin-fabmanager-0.0.13.tgz#bf7b8beee1485a354ecfc42e2649501da25d5996"
integrity sha512-cYJecCNMG/2hJ41HM6GrfnMwb9MaMQXob7V90U8kkdt3Os4rf//cv/6lTWJiX0Wpnp9nVbQavkPKX5cJ8gYA/w==
eslint-plugin-html-erb@^1.0.1: eslint-plugin-html-erb@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-html-erb/-/eslint-plugin-html-erb-1.0.1.tgz#f4a55070d5eabe365e13dba587a1d779bfe36eb6" resolved "https://registry.yarnpkg.com/eslint-plugin-html-erb/-/eslint-plugin-html-erb-1.0.1.tgz#f4a55070d5eabe365e13dba587a1d779bfe36eb6"