taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 1cc9592c856ecc8677a78d003bf5c350ae78fe24
parent 26686c7d696c6f98df7120d0d83537cd37c4d286
Author: Sebastian <sebasjm@taler-systems.com>
Date:   Fri, 17 Apr 2026 17:26:57 -0300

fix product form on merchant backoffice

Diffstat:
Mpackages/bank-ui/src/components/Transactions/views.tsx | 4++--
Mpackages/bank-ui/src/pages/BankFrame.tsx | 2+-
Mpackages/bank-ui/src/pages/ConversionRateClassDetails.tsx | 8++++----
Mpackages/bank-ui/src/pages/admin/AccountList.tsx | 4++--
Mpackages/bank-ui/src/pages/admin/ConversionClassList.tsx | 4++--
Mpackages/merchant-backoffice-ui/src/components/SolveMFA.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/components/form/FormProvider.tsx | 4+++-
Mpackages/merchant-backoffice-ui/src/components/modal/index.tsx | 28++++++++++++++++++++++------
Mpackages/merchant-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx | 4++--
Mpackages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx | 8++++----
Mpackages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/categories/update/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/groups/list/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/pots/update/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/paths/instance/reports/update/UpdatePage.tsx | 2+-
Mpackages/merchant-backoffice-ui/src/utils/constants.ts | 2+-
Arules/button-without-type.yaml | 14++++++++++++++
23 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/packages/bank-ui/src/components/Transactions/views.tsx b/packages/bank-ui/src/components/Transactions/views.tsx @@ -232,7 +232,7 @@ export function ReadyView({ aria-label="Pagination" > <div class="flex flex-1 justify-between sm:justify-end"> - <button + <button type="button" name="first page" class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!onGoStart} @@ -240,7 +240,7 @@ export function ReadyView({ > <i18n.Translate>First page</i18n.Translate> </button> - <button + <button type="button" name="next page" class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!onGoNext} diff --git a/packages/bank-ui/src/pages/BankFrame.tsx b/packages/bank-ui/src/pages/BankFrame.tsx @@ -346,7 +346,7 @@ function AppActivity(): VNode { <p class="ml-2 my-auto text-sm text-gray-500">{lastEvent.url}</p> {!status ? ( - <button + <button type="button" onClick={() => { if (cancelRequest) cancelRequest(lastEvent.id); }} diff --git a/packages/bank-ui/src/pages/ConversionRateClassDetails.tsx b/packages/bank-ui/src/pages/ConversionRateClassDetails.tsx @@ -1299,7 +1299,7 @@ function AccountsOnConversionClass({ classId }: { classId: number }): VNode { </td> <td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500"> {classId === item.conversion_rate_class_id ? ( - <button + <button type="button" class="disabled:opacity-50 disabled:bg-gray-600 disabled:hover:bg-gray-600 disabled:cursor-default cursor-pointer rounded-md bg-red-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-red-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-red-600" onClick={async () => { if (token) { @@ -1315,7 +1315,7 @@ function AccountsOnConversionClass({ classId }: { classId: number }): VNode { <i18n.Translate>Remove</i18n.Translate> </button> ) : ( - <button + <button type="button" class="disabled:opacity-50 disabled:bg-gray-600 disabled:hover:bg-gray-600 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600" onClick={async () => { if (token) { @@ -1345,7 +1345,7 @@ function AccountsOnConversionClass({ classId }: { classId: number }): VNode { aria-label="Pagination" > <div class="flex flex-1 justify-between sm:justify-end"> - <button + <button type="button" name="first page" class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!userListResult.loadFirst} @@ -1353,7 +1353,7 @@ function AccountsOnConversionClass({ classId }: { classId: number }): VNode { > <i18n.Translate>First page</i18n.Translate> </button> - <button + <button type="button" name="next page" class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!userListResult.loadNext} diff --git a/packages/bank-ui/src/pages/admin/AccountList.tsx b/packages/bank-ui/src/pages/admin/AccountList.tsx @@ -210,7 +210,7 @@ export function AccountList({ aria-label="Pagination" > <div class="flex flex-1 justify-between sm:justify-end"> - <button + <button type="button" name="first page" class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!result.loadFirst} @@ -218,7 +218,7 @@ export function AccountList({ > <i18n.Translate>First page</i18n.Translate> </button> - <button + <button type="button" name="next page" class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!result.loadNext} diff --git a/packages/bank-ui/src/pages/admin/ConversionClassList.tsx b/packages/bank-ui/src/pages/admin/ConversionClassList.tsx @@ -249,7 +249,7 @@ export function ConversionClassList({ aria-label="Pagination" > <div class="flex flex-1 justify-between sm:justify-end"> - <button + <button type="button" name="first page" class="relative disabled:bg-gray-100 disabled:text-gray-500 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!result.loadFirst} @@ -257,7 +257,7 @@ export function ConversionClassList({ > <i18n.Translate>First page</i18n.Translate> </button> - <button + <button type="button" name="next page" class="relative disabled:bg-gray-100 disabled:text-gray-500 ml-3 inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline-offset-0" disabled={!result.loadNext} diff --git a/packages/merchant-backoffice-ui/src/components/SolveMFA.tsx b/packages/merchant-backoffice-ui/src/components/SolveMFA.tsx @@ -621,7 +621,7 @@ export function SolveMFAChallenges({ borderTop: 0, }} > - <button class="button" onClick={onCancel}> + <button class="button" type="button" onClick={onCancel}> <i18n.Translate>Cancel</i18n.Translate> </button> <div /> diff --git a/packages/merchant-backoffice-ui/src/components/form/FormProvider.tsx b/packages/merchant-backoffice-ui/src/components/form/FormProvider.tsx @@ -65,7 +65,9 @@ export function FormProvider<T>({ const [{ showDebugInfo }] = useCommonPreferences(); return ( <FormContext.Provider value={value}> - <form>{children}</form> + <form onSubmit={(e) => { + e.preventDefault() + }}>{children}</form> {showDebugInfo ? <pre>{JSON.stringify({form: value.object, errors}, undefined, 2)}</pre> : undefined} </FormContext.Provider> ); diff --git a/packages/merchant-backoffice-ui/src/components/modal/index.tsx b/packages/merchant-backoffice-ui/src/components/modal/index.tsx @@ -108,7 +108,12 @@ export function ConfirmModal({ </ButtonBetterBulma> </Fragment> ) : noCancelButton ? undefined : ( - <button class="button " ref={doAutoFocus} onClick={onCancel}> + <button + type="button" + class="button " + ref={doAutoFocus} + onClick={onCancel} + > <i18n.Translate>Close</i18n.Translate> </button> )} @@ -141,7 +146,12 @@ export function ContinueModal({ <div class="modal-card"> <header class="modal-card-head has-background-success"> {!description ? null : <p class="modal-card-title">{description}</p>} - <button class="delete " aria-label="close" onClick={onCancel} /> + <button + type="button" + class="delete " + aria-label="close" + onClick={onCancel} + /> </header> <section class="modal-card-body">{children}</section> <footer class="modal-card-foot"> @@ -205,7 +215,12 @@ export function ClearConfirmModal({ <div class="modal-card"> <header class="modal-card-head"> {!description ? null : <p class="modal-card-title">{description}</p>} - <button class="delete " aria-label="close" onClick={onCancel} /> + <button + type="button" + class="delete " + aria-label="close" + onClick={onCancel} + /> </header> <section class="modal-card-body is-main-section">{children}</section> <footer class="modal-card-foot"> @@ -603,6 +618,7 @@ function Accordion({ return ( <div> <button + type="button" style={{ color: "#444", padding: 8, @@ -715,14 +731,14 @@ export function CopyButton({ if (!copied) { return ( - <button onClick={copyText}> + <button type="button" onClick={copyText}> <CopyIcon /> </button> ); } return ( // <TooltipLeft content="Copied"> - <button disabled> + <button type="button" disabled> <CopiedIcon /> </button> // </TooltipLeft> @@ -772,7 +788,7 @@ export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode { </section> <footer class="modal-card-foot"> <div class="buttons is-right" style={{ width: "100%" }}> - <button class="button " onClick={onCancel}> + <button type="button" class="button " onClick={onCancel}> <i18n.Translate>Cancel</i18n.Translate> </button> </div> diff --git a/packages/merchant-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx b/packages/merchant-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx @@ -49,11 +49,11 @@ export function CreatedSuccessfully({ </div> <div class="buttons is-right"> {onCreateAnother && ( - <button class="button is-info" onClick={onCreateAnother}> + <button type="button" class="button is-info" onClick={onCreateAnother}> <i18n.Translate>Create another</i18n.Translate> </button> )} - <button class="button is-info" ref={focus ? doAutoFocus : undefined} onClick={onConfirm}> + <button type="button" class="button is-info" ref={focus ? doAutoFocus : undefined} onClick={onConfirm}> <i18n.Translate>Continue</i18n.Translate> </button> </div> diff --git a/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx b/packages/merchant-backoffice-ui/src/components/product/InventoryProductForm.tsx @@ -110,7 +110,7 @@ export function InventoryProductForm({ </div> <div class="column"> <div class="buttons is-right"> - <button class="button is-success" onClick={submit}> + <button type="button" class="button is-success" onClick={submit}> <i18n.Translate>Add it to the order</i18n.Translate> </button> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx @@ -355,7 +355,7 @@ export function CreatePage({ onCreated, onBack }: Props): VNode { </FragmentPersonaFlag> <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/list/Table.tsx @@ -256,7 +256,7 @@ function Table({ accounts, onDelete, onSelect }: TableProps): VNode { <Tooltip text={i18n.str`Delete selected accounts from the database`} > - <button + <button type="button" class="button is-danger is-small" onClick={() => onDelete(acc)} > @@ -298,7 +298,7 @@ function Table({ accounts, onDelete, onSelect }: TableProps): VNode { <Tooltip text={i18n.str`Delete selected accounts from the database`} > - <button + <button type="button" class="button is-danger is-small" onClick={() => onDelete(acc)} > @@ -340,7 +340,7 @@ function Table({ accounts, onDelete, onSelect }: TableProps): VNode { <Tooltip text={i18n.str`Delete selected accounts from the database`} > - <button + <button type="button" class="button is-danger is-small" onClick={() => onDelete(acc)} > @@ -382,7 +382,7 @@ function Table({ accounts, onDelete, onSelect }: TableProps): VNode { <Tooltip text={i18n.str`Delete selected accounts from the database`} > - <button + <button type="button" class="button is-danger is-small" onClick={() => onDelete(acc)} > diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx @@ -440,7 +440,7 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/categories/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/categories/update/UpdatePage.tsx @@ -150,7 +150,7 @@ export function UpdatePage({ category, onUpdated, onBack }: Props): VNode { /> <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/groups/list/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/groups/list/UpdatePage.tsx @@ -152,7 +152,7 @@ export function UpdatePage({ group, onUpdated, onBack }: Props): VNode { /> <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx @@ -1167,7 +1167,7 @@ export function DetailPage({ <div class="column" /> <div class="column is-four-fifths"> <div class="buttons is-right mt-5"> - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Back</i18n.Translate> </button> </div> diff --git a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx @@ -188,7 +188,7 @@ function Table({ <div class=""> {onLoadMoreBefore && ( - <button class="button is-fullwidth" onClick={onLoadMoreBefore}> + <button type="button" class="button is-fullwidth" onClick={onLoadMoreBefore}> <i18n.Translate>Load first page</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/pots/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/pots/update/UpdatePage.tsx @@ -184,7 +184,7 @@ export function UpdatePage({ moneyPot, onUpdated, onBack }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx @@ -122,7 +122,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode { > <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx @@ -167,7 +167,7 @@ function Table({ return ( <div class=""> {onLoadMoreBefore && ( - <button class="button is-fullwidth" onClick={onLoadMoreBefore}> + <button type="button" class="button is-fullwidth" onClick={onLoadMoreBefore}> <i18n.Translate>Load first page</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/paths/instance/reports/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/reports/update/UpdatePage.tsx @@ -244,7 +244,7 @@ export function UpdatePage({ report, onUpdated, onBack }: Props): VNode { <div class="buttons is-right mt-5"> {onBack && ( - <button class="button" onClick={onBack}> + <button type="button" class="button" onClick={onBack}> <i18n.Translate>Cancel</i18n.Translate> </button> )} diff --git a/packages/merchant-backoffice-ui/src/utils/constants.ts b/packages/merchant-backoffice-ui/src/utils/constants.ts @@ -35,7 +35,7 @@ export const CROCKFORD_BASE32_REGEX = export const URL_REGEX = /^((https?:)(\/\/\/?)([\w]*(?::[\w]*)?@)?([\d\w\.-]+)(?::(\d+))?)\/$/; -export const PAGINATED_LIST_SIZE = 10; +export const PAGINATED_LIST_SIZE = 20; // when doing paginated request, ask for one more // and use it to know if there are more to request export const PAGINATED_LIST_REQUEST = PAGINATED_LIST_SIZE + 1; diff --git a/rules/button-without-type.yaml b/rules/button-without-type.yaml @@ -0,0 +1,14 @@ +id: find-button-missing-type +language: tsx +rule: + kind: identifier + regex: "^button$" + inside: + kind: jsx_opening_element + not: + has: + kind: jsx_attribute + has: + kind: property_identifier + regex: "^type$" +fix: "button type=\"button\""