gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: backoffice ui


From: gnunet
Subject: [taler-wallet-core] branch master updated: backoffice ui
Date: Fri, 06 Oct 2023 15:38:52 +0200

This is an automated email from the git hooks/post-receive script.

sebasjm pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 98013322d backoffice ui
98013322d is described below

commit 98013322db6b912ac50d72353dbd8b5f7fbc0435
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Oct 6 10:38:09 2023 -0300

    backoffice ui
---
 packages/merchant-backoffice-ui/package.json       |   2 +-
 .../merchant-backoffice-ui/src/Application.tsx     |   2 +-
 .../merchant-backoffice-ui/src/InstanceRoutes.tsx  |  24 ++---
 .../src/components/form/InputWithAddon.tsx         |   3 +-
 .../src/components/form/JumpToElementById.tsx      |  59 +++++++++++
 .../src/components/menu/SideBar.tsx                |   4 +-
 .../src/components/menu/index.tsx                  |   6 +-
 .../merchant-backoffice-ui/src/hooks/backend.ts    |  34 ++++++-
 packages/merchant-backoffice-ui/src/hooks/index.ts |   8 +-
 .../merchant-backoffice-ui/src/hooks/templates.ts  | 112 ++++++++++++---------
 .../merchant-backoffice-ui/src/hooks/webhooks.ts   |   4 +-
 .../src/paths/instance/orders/list/ListPage.tsx    |  51 ++--------
 .../src/paths/instance/orders/list/Table.tsx       |   6 +-
 .../src/paths/instance/orders/list/index.tsx       |  31 ++----
 .../src/paths/instance/products/list/Table.tsx     |   5 +-
 .../src/paths/instance/products/list/index.tsx     |  56 ++---------
 .../src/paths/instance/templates/list/ListPage.tsx |   2 -
 .../src/paths/instance/templates/list/Table.tsx    |   8 +-
 .../src/paths/instance/templates/list/index.tsx    |  16 ++-
 .../src/paths/instance/transfers/list/ListPage.tsx |   2 +-
 .../src/paths/instance/transfers/list/Table.tsx    |   6 +-
 .../src/paths/instance/transfers/list/index.tsx    |  11 +-
 .../instance/validators/create/CreatePage.tsx      |   1 +
 .../src/paths/instance/validators/list/Table.tsx   |   6 +-
 .../src/paths/instance/webhooks/list/Table.tsx     |   6 +-
 .../src/paths/login/index.tsx                      |  23 +----
 26 files changed, 256 insertions(+), 232 deletions(-)

diff --git a/packages/merchant-backoffice-ui/package.json 
b/packages/merchant-backoffice-ui/package.json
index 66e03a65c..23b258792 100644
--- a/packages/merchant-backoffice-ui/package.json
+++ b/packages/merchant-backoffice-ui/package.json
@@ -1,7 +1,7 @@
 {
   "private": true,
   "name": "@gnu-taler/merchant-backoffice-ui",
-  "version": "0.1.0",
+  "version": "0.9.3-dev.27",
   "license": "AGPL-3.0-or-later",
   "type": "module",
   "scripts": {
diff --git a/packages/merchant-backoffice-ui/src/Application.tsx 
b/packages/merchant-backoffice-ui/src/Application.tsx
index f0a7de53b..4210192ae 100644
--- a/packages/merchant-backoffice-ui/src/Application.tsx
+++ b/packages/merchant-backoffice-ui/src/Application.tsx
@@ -64,7 +64,7 @@ function ApplicationStatusRoutes(): VNode {
   const result = useBackendConfig();
   const { i18n } = useTranslationContext();
 
-  const { currency, version } = result.ok
+  const { currency, version } = result.ok && result.data
     ? result.data
     : { currency: "unknown", version: "unknown" };
   const ctx = useMemo(() => ({ currency, version }), [currency, version]);
diff --git a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx 
b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
index f5372db8d..95be49c9d 100644
--- a/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
+++ b/packages/merchant-backoffice-ui/src/InstanceRoutes.tsx
@@ -80,7 +80,7 @@ import { dateFormatForSettings, useSettings } from 
"./hooks/useSettings.js";
 
 export enum InstancePaths {
   error = "/error",
-  server = "/server",
+  settings = "/settings",
   token = "/token",
 
   bank_list = "/bank",
@@ -118,7 +118,7 @@ export enum InstancePaths {
   validators_update = "/validators/:vid/update",
   validators_new = "/validators/new",
 
-  settings = "/interface",
+  interface = "/interface",
 }
 
 // eslint-disable-next-line @typescript-eslint/no-empty-function
@@ -255,7 +255,7 @@ export function InstanceRoutes({
         instance={id}
         admin={admin}
         onShowSettings={() => {
-          route(InstancePaths.settings)
+          route(InstancePaths.interface)
         }}
         path={path}
         onLogout={clearTokenAndGoToRoot}
@@ -320,7 +320,7 @@ export function InstanceRoutes({
          * Update instance page
          */}
         <Route
-          path={InstancePaths.server}
+          path={InstancePaths.settings}
           component={InstanceUpdatePage}
           onBack={() => {
             route(`/`);
@@ -353,7 +353,7 @@ export function InstanceRoutes({
           path={InstancePaths.inventory_list}
           component={ProductListPage}
           onUnauthorized={LoginPageAccessDenied}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.inventory_new);
           }}
@@ -392,7 +392,7 @@ export function InstanceRoutes({
           path={InstancePaths.bank_list}
           component={BankAccountListPage}
           onUnauthorized={LoginPageAccessDenied}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.bank_new);
           }}
@@ -437,7 +437,7 @@ export function InstanceRoutes({
             route(InstancePaths.order_details.replace(":oid", id));
           }}
           onUnauthorized={LoginPageAccessDenied}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
         />
         <Route
@@ -468,7 +468,7 @@ export function InstanceRoutes({
           component={TransferListPage}
           onUnauthorized={LoginPageAccessDenied}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.transfers_new);
           }}
@@ -491,7 +491,7 @@ export function InstanceRoutes({
           component={WebhookListPage}
           onUnauthorized={LoginPageAccessDenied}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.webhooks_new);
           }}
@@ -530,7 +530,7 @@ export function InstanceRoutes({
           component={ValidatorListPage}
           onUnauthorized={LoginPageAccessDenied}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.validators_new);
           }}
@@ -569,7 +569,7 @@ export function InstanceRoutes({
           component={TemplateListPage}
           onUnauthorized={LoginPageAccessDenied}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onCreate={() => {
             route(InstancePaths.templates_new);
           }}
@@ -638,7 +638,7 @@ export function InstanceRoutes({
           component={ReservesListPage}
           onUnauthorized={LoginPageAccessDenied}
           onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
-          onLoadError={ServerErrorRedirectTo(InstancePaths.server)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
           onSelect={(id: string) => {
             route(InstancePaths.reserves_details.replace(":rid", id));
           }}
diff --git 
a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx 
b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx
index 34feec202..d7b490a5d 100644
--- a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx
+++ b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx
@@ -107,8 +107,9 @@ export function InputWithAddon<T>({
           {error && <p class="help is-danger">{error}</p>}
           <span class="has-text-grey">{help}</span>
         </div>
-        {side}
+        {expand ? <div>{side}</div> : side}
       </div>
+      
     </div>
   );
 }
diff --git 
a/packages/merchant-backoffice-ui/src/components/form/JumpToElementById.tsx 
b/packages/merchant-backoffice-ui/src/components/form/JumpToElementById.tsx
new file mode 100644
index 000000000..2ff23dfd3
--- /dev/null
+++ b/packages/merchant-backoffice-ui/src/components/form/JumpToElementById.tsx
@@ -0,0 +1,59 @@
+import { TranslatedString } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+
+export function JumpToElementById({ testIfExist, onSelect, palceholder, 
description }: { palceholder: TranslatedString, description: TranslatedString, 
testIfExist: (id: string) => Promise<any>, onSelect: (id: string) => void }): 
VNode {
+  const { i18n } = useTranslationContext()
+
+  const [error, setError] = useState<string | undefined>(
+    undefined,
+  );
+
+  const [id, setId] = useState<string>()
+  async function check(currentId: string | undefined): Promise<void> {
+    if (!currentId) {
+      setError(i18n.str`missing id`);
+      return;
+    }
+    try {
+      await testIfExist(currentId);
+      onSelect(currentId);
+      setError(undefined);
+    } catch {
+      setError(i18n.str`not found`);
+    }
+  }
+
+  return <div class="level">
+    <div class="level-left">
+      <div class="level-item">
+        <div class="field has-addons">
+          <div class="control">
+            <input
+              class={error ? "input is-danger" : "input"}
+              type="text"
+              value={id ?? ""}
+              onChange={(e) => setId(e.currentTarget.value)}
+              placeholder={palceholder}
+            />
+            {error && <p class="help is-danger">{error}</p>}
+          </div>
+          <span
+            class="has-tooltip-bottom"
+            data-tooltip={description}
+          >
+            <button
+              class="button"
+              onClick={(e) => check(id)}
+            >
+              <span class="icon">
+                <i class="mdi mdi-arrow-right" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </div>
+    </div>
+  </div>
+}
diff --git a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx 
b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
index 402134096..6905cb4d0 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/SideBar.tsx
@@ -177,12 +177,12 @@ export function Sidebar({
                 </a>
               </li>
               <li>
-                <a href={"/server"} class="has-icon">
+                <a href={"/settings"} class="has-icon">
                   <span class="icon">
                     <i class="mdi mdi-square-edit-outline" />
                   </span>
                   <span class="menu-item-label">
-                    <i18n.Translate>Server</i18n.Translate>
+                    <i18n.Translate>Settings</i18n.Translate>
                   </span>
                 </a>
               </li>
diff --git a/packages/merchant-backoffice-ui/src/components/menu/index.tsx 
b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
index b8ac2c9ab..0e881d7a5 100644
--- a/packages/merchant-backoffice-ui/src/components/menu/index.tsx
+++ b/packages/merchant-backoffice-ui/src/components/menu/index.tsx
@@ -24,7 +24,7 @@ import { Sidebar } from "./SideBar.js";
 
 function getInstanceTitle(path: string, id: string): string {
   switch (path) {
-    case InstancePaths.server:
+    case InstancePaths.settings:
       return `${id}: Settings`;
     case InstancePaths.order_list:
       return `${id}: Orders`;
@@ -64,9 +64,7 @@ function getInstanceTitle(path: string, id: string): string {
       return `${id}: Templates`;
     case InstancePaths.templates_use:
       return `${id}: Use template`;
-    case InstancePaths.settings:
-      return `${id}: Interface`;
-    case InstancePaths.settings:
+    case InstancePaths.interface:
       return `${id}: Interface`;
     default:
       return "";
diff --git a/packages/merchant-backoffice-ui/src/hooks/backend.ts 
b/packages/merchant-backoffice-ui/src/hooks/backend.ts
index eaeede103..4515f0557 100644
--- a/packages/merchant-backoffice-ui/src/hooks/backend.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/backend.ts
@@ -91,7 +91,7 @@ const CHECK_CONFIG_INTERVAL_OK = 5 * 60 * 1000;
 const CHECK_CONFIG_INTERVAL_FAIL = 2 * 1000;
 
 export function useBackendConfig(): HttpResponse<
-  MerchantBackend.VersionResponse,
+  MerchantBackend.VersionResponse | undefined,
   RequestError<MerchantBackend.ErrorDetail>
 > {
   const { request } = useBackendBaseRequest();
@@ -340,6 +340,14 @@ export function useBackendInstanceRequest(): 
useBackendInstanceRequestType {
       if (refunded !== undefined) params.refunded = refunded;
       if (wired !== undefined) params.wired = wired;
       if (date_s !== undefined) params.date_s = date_s;
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: {orders:[]} as T,
+        })
+      }
       return requestHandler<T>(baseUrl, endpoint, { params, token });
     },
     [baseUrl, token],
@@ -385,6 +393,14 @@ export function useBackendInstanceRequest(): 
useBackendInstanceRequestType {
       const params: any = {};
       if (payto_uri !== undefined) params.payto_uri = payto_uri;
       if (verified !== undefined) params.verified = verified;
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: {transfers:[]} as T,
+        })
+      }
       if (delta !== undefined) {
         params.limit = delta;
       }
@@ -403,6 +419,14 @@ export function useBackendInstanceRequest(): 
useBackendInstanceRequestType {
     ): Promise<HttpResponseOk<T>> {
       const [endpoint, position, delta] = args
       const params: any = {};
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: {templates:[]} as T,
+        })
+      }
       if (delta !== undefined) {
         params.limit = delta;
       }
@@ -421,6 +445,14 @@ export function useBackendInstanceRequest(): 
useBackendInstanceRequestType {
     ): Promise<HttpResponseOk<T>> {
       const [endpoint, position, delta] = args
       const params: any = {};
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: {webhooks:[]} as T,
+        })
+      }
       if (delta !== undefined) {
         params.limit = delta;
       }
diff --git a/packages/merchant-backoffice-ui/src/hooks/index.ts 
b/packages/merchant-backoffice-ui/src/hooks/index.ts
index 498e4eb78..3c8ef15ed 100644
--- a/packages/merchant-backoffice-ui/src/hooks/index.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/index.ts
@@ -32,7 +32,13 @@ const calculateRootPath = () => {
       ? window.location.origin + window.location.pathname
       : "/";
 
-  return rootPath.replace("webui/","");
+  /**
+   * By default, merchant backend serves the html content
+   * from the /webui root. This should cover most of the 
+   * cases and the rootPath will be the merchant backend
+   * URL where the instances are
+   */
+  return rootPath.replace("/webui/", "");
 };
 
 const loginTokenCodec = buildCodecForObject<LoginToken>()
diff --git a/packages/merchant-backoffice-ui/src/hooks/templates.ts 
b/packages/merchant-backoffice-ui/src/hooks/templates.ts
index 56cdd3046..ee8728cc8 100644
--- a/packages/merchant-backoffice-ui/src/hooks/templates.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/templates.ts
@@ -82,10 +82,19 @@ export function useTemplateAPI(): TemplateAPI {
     return res;
   };
 
+  const testTemplateExist = async (
+    templateId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/templates/${templateId}`, { 
method: "GET", });
+    return res;
+  };
+
+
   return {
     createTemplate,
     updateTemplate,
     deleteTemplate,
+    testTemplateExist,
     createOrderFromTemplate,
   };
 }
@@ -98,6 +107,9 @@ export interface TemplateAPI {
     id: string,
     data: MerchantBackend.Template.TemplatePatchDetails,
   ) => Promise<HttpResponseOk<void>>;
+  testTemplateExist: (
+    id: string
+  ) => Promise<HttpResponseOk<void>>;
   deleteTemplate: (id: string) => Promise<HttpResponseOk<void>>;
   createOrderFromTemplate: (
     id: string,
@@ -119,11 +131,11 @@ export function useInstanceTemplates(
 > {
   const { templateFetcher } = useBackendInstanceRequest();
 
-  // const [pageBefore, setPageBefore] = useState(1);
+  const [pageBefore, setPageBefore] = useState(1);
   const [pageAfter, setPageAfter] = useState(1);
 
   const totalAfter = pageAfter * PAGE_SIZE;
-  // const totalBefore = args?.position !== undefined ? pageBefore * PAGE_SIZE 
: 0;
+  const totalBefore = args?.position ? pageBefore * PAGE_SIZE : 0;
 
   /**
    * FIXME: this can be cleaned up a little
@@ -131,20 +143,20 @@ export function useInstanceTemplates(
    * the logic of double query should be inside the orderFetch so from the 
hook perspective and cache
    * is just one query and one error status
    */
-  // const {
-  //   data: beforeData,
-  //   error: beforeError,
-  //   isValidating: loadingBefore,
-  // } = 
useSWR<HttpResponseOk<MerchantBackend.Template.TemplateSummaryResponse>, 
HttpError>(
-  //   [
-  //     `/private/templates`,
-  //     token,
-  //     url,
-  //     args?.position,
-  //     totalBefore,
-  //   ],
-  //   templateFetcher,
-  // );
+  const {
+    data: beforeData,
+    error: beforeError,
+    isValidating: loadingBefore,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Template.TemplateSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>>(
+      [
+        `/private/templates`,
+        args?.position,
+        totalBefore,
+      ],
+      templateFetcher,
+    );
   const {
     data: afterData,
     error: afterError,
@@ -155,9 +167,13 @@ export function useInstanceTemplates(
   >([`/private/templates`, args?.position, -totalAfter], templateFetcher);
 
   //this will save last result
-  // const [lastBefore, setLastBefore] = useState<
-  //   HttpResponse<MerchantBackend.Template.TemplateSummaryResponse, 
MerchantBackend.ErrorDetail>
-  // >({ loading: true });
+  const [lastBefore, setLastBefore] = useState<
+    HttpResponse<
+      MerchantBackend.Template.TemplateSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+
   const [lastAfter, setLastAfter] = useState<
     HttpResponse<
       MerchantBackend.Template.TemplateSummaryResponse,
@@ -166,19 +182,18 @@ export function useInstanceTemplates(
   >({ loading: true });
   useEffect(() => {
     if (afterData) setLastAfter(afterData);
-    // if (beforeData) setLastBefore(beforeData);
-  }, [afterData /*, beforeData*/]);
+    if (beforeData) setLastBefore(beforeData);
+  }, [afterData, beforeData]);
 
-  // if (beforeError) return beforeError;
+  if (beforeError) return beforeError.cause;
   if (afterError) return afterError.cause;
 
   // if the query returns less that we ask, then we have reach the end or 
beginning
   const isReachingEnd =
     afterData && afterData.data.templates.length < totalAfter;
-  const isReachingStart = false;
-  // args?.position === undefined
-  // ||
-  // (beforeData && beforeData.data.templates.length < totalBefore);
+  const isReachingStart = args?.position === undefined
+    ||
+    (beforeData && beforeData.data.templates.length < totalBefore);
 
   const pagination = {
     isReachingEnd,
@@ -188,37 +203,36 @@ export function useInstanceTemplates(
       if (afterData.data.templates.length < MAX_RESULT_SIZE) {
         setPageAfter(pageAfter + 1);
       } else {
-        const from = `${
-          afterData.data.templates[afterData.data.templates.length - 1]
-            .template_id
-        }`;
+        const from = 
`${afterData.data.templates[afterData.data.templates.length - 1]
+          .template_id
+          }`;
         if (from && updatePosition) updatePosition(from);
       }
     },
     loadMorePrev: () => {
-      // if (!beforeData || isReachingStart) return;
-      // if (beforeData.data.templates.length < MAX_RESULT_SIZE) {
-      //   setPageBefore(pageBefore + 1);
-      // } else if (beforeData) {
-      //   const from = 
`${beforeData.data.templates[beforeData.data.templates.length - 1]
-      //     .template_id
-      //     }`;
-      //   if (from && updatePosition) updatePosition(from);
-      // }
+      if (!beforeData || isReachingStart) return;
+      if (beforeData.data.templates.length < MAX_RESULT_SIZE) {
+        setPageBefore(pageBefore + 1);
+      } else if (beforeData) {
+        const from = 
`${beforeData.data.templates[beforeData.data.templates.length - 1]
+          .template_id
+          }`;
+        if (from && updatePosition) updatePosition(from);
+      }
     },
   };
 
-  const templates = !afterData ? [] : (afterData || lastAfter).data.templates;
-  // const templates =
-  //   !beforeData || !afterData
-  //     ? []
-  //     : (beforeData || lastBefore).data.templates
-  //       .slice()
-  //       .reverse()
-  //       .concat((afterData || lastAfter).data.templates);
-  if (loadingAfter /* || loadingBefore */)
+  // const templates = !afterData ? [] : (afterData || 
lastAfter).data.templates;
+  const templates =
+    !beforeData || !afterData
+      ? []
+      : (beforeData || lastBefore).data.templates
+        .slice()
+        .reverse()
+        .concat((afterData || lastAfter).data.templates);
+  if (loadingAfter || loadingBefore)
     return { loading: true, data: { templates } };
-  if (/*beforeData &&*/ afterData) {
+  if (beforeData && afterData) {
     return { ok: true, data: { templates }, ...pagination };
   }
   return { loading: true };
diff --git a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts 
b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
index c91fff8b4..ad6bf96e2 100644
--- a/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
+++ b/packages/merchant-backoffice-ui/src/hooks/webhooks.ts
@@ -93,9 +93,11 @@ export function useInstanceWebhooks(
 > {
   const { webhookFetcher } = useBackendInstanceRequest();
 
+  const [pageBefore, setPageBefore] = useState(1);
   const [pageAfter, setPageAfter] = useState(1);
 
   const totalAfter = pageAfter * PAGE_SIZE;
+  const totalBefore = args?.position ? pageBefore * PAGE_SIZE : 0;
 
   const {
     data: afterData,
@@ -120,7 +122,7 @@ export function useInstanceWebhooks(
 
   const isReachingEnd =
     afterData && afterData.data.webhooks.length < totalAfter;
-  const isReachingStart = false;
+  const isReachingStart = true;
 
   const pagination = {
     isReachingEnd,
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx
index c29a6fa6e..9f80719a1 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx
@@ -21,7 +21,7 @@
 
 import { useTranslationContext } from "@gnu-taler/web-util/browser";
 import { format } from "date-fns";
-import { h, VNode } from "preact";
+import { h, VNode, Fragment } from "preact";
 import { useState } from "preact/hooks";
 import { DatePicker } from "../../../../components/picker/DatePicker.js";
 import { MerchantBackend, WithId } from "../../../../declaration.js";
@@ -29,8 +29,6 @@ import { CardTable } from "./Table.js";
 import { dateFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
 
 export interface ListPageProps {
-  errorOrderId: string | undefined;
-
   onShowAll: () => void;
   onShowNotPaid: () => void;
   onShowPaid: () => void;
@@ -56,17 +54,18 @@ export interface ListPageProps {
 
   onSelectOrder: (o: MerchantBackend.Orders.OrderHistoryEntry & WithId) => 
void;
   onRefundOrder: (o: MerchantBackend.Orders.OrderHistoryEntry & WithId) => 
void;
-  onSearchOrderById: (id: string) => void;
   onCreate: () => void;
 }
 
 export function ListPage({
+  hasMoreAfter,
+  hasMoreBefore,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
   orders,
-  errorOrderId,
   isAllActive,
   onSelectOrder,
   onRefundOrder,
-  onSearchOrderById,
   jumpToDate,
   onCopyURL,
   onShowAll,
@@ -86,42 +85,10 @@ export function ListPage({
   const { i18n } = useTranslationContext();
   const dateTooltip = i18n.str`select date to show nearby orders`;
   const [pickDate, setPickDate] = useState(false);
-  const [orderId, setOrderId] = useState<string>("");
   const [settings] = useSettings();
 
   return (
-    <section class="section is-main-section">
-      <div class="level">
-        <div class="level-left">
-          <div class="level-item">
-            <div class="field has-addons">
-              <div class="control">
-                <input
-                  class={errorOrderId ? "input is-danger" : "input"}
-                  type="text"
-                  value={orderId}
-                  onChange={(e) => setOrderId(e.currentTarget.value)}
-                  placeholder={i18n.str`order id`}
-                />
-                {errorOrderId && <p class="help is-danger">{errorOrderId}</p>}
-              </div>
-              <span
-                class="has-tooltip-bottom"
-                data-tooltip={i18n.str`jump to order with the given order ID`}
-              >
-                <button
-                  class="button"
-                  onClick={(e) => onSearchOrderById(orderId)}
-                >
-                  <span class="icon">
-                    <i class="mdi mdi-arrow-right" />
-                  </span>
-                </button>
-              </span>
-            </div>
-          </div>
-        </div>
-      </div>
+    <Fragment>
       <div class="columns">
         <div class="column is-two-thirds">
           <div class="tabs" style={{ overflow: "inherit" }}>
@@ -249,7 +216,11 @@ export function ListPage({
         onCopyURL={onCopyURL}
         onSelect={onSelectOrder}
         onRefund={onRefundOrder}
+        hasMoreAfter={hasMoreAfter}
+        hasMoreBefore={hasMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        onLoadMoreBefore={onLoadMoreBefore}
       />
-    </section>
+    </Fragment>
   );
 }
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
index 608c9b20d..b2806bb79 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/Table.tsx
@@ -140,10 +140,9 @@ function Table({
   const [settings] = useSettings();
   return (
     <div class="table-container">
-      {onLoadMoreBefore && (
+      {hasMoreBefore && (
         <button
           class="button is-fullwidth"
-          disabled={!hasMoreBefore}
           onClick={onLoadMoreBefore}
         >
           <i18n.Translate>load newer orders</i18n.Translate>
@@ -218,10 +217,9 @@ function Table({
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && (
+      {hasMoreAfter && (
         <button
           class="button is-fullwidth"
-          disabled={!hasMoreAfter}
           onClick={onLoadMoreAfter}
         >
           <i18n.Translate>load older orders</i18n.Translate>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
index 48f77e3d3..34c7d348a 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/orders/list/index.tsx
@@ -39,6 +39,7 @@ import { Notification } from "../../../../utils/types.js";
 import { ListPage } from "./ListPage.js";
 import { RefundModal } from "./Table.js";
 import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
 
 interface Props {
   onUnauthorized: () => VNode;
@@ -69,9 +70,6 @@ export default function OrderList({
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
 
   const { i18n } = useTranslationContext();
-  const [errorOrderId, setErrorOrderId] = useState<string | undefined>(
-    undefined,
-  );
 
   if (result.loading) return <Loading />;
   if (!result.ok) {
@@ -100,24 +98,17 @@ export default function OrderList({
       ? "is-active"
       : "";
 
-  async function testIfOrderExistAndSelect(orderId: string): Promise<void> {
-    if (!orderId) {
-      setErrorOrderId(i18n.str`Enter an order id`);
-      return;
-    }
-    try {
-      await getPaymentURL(orderId);
-      onSelect(orderId);
-      setErrorOrderId(undefined);
-    } catch {
-      setErrorOrderId(i18n.str`order not found`);
-    }
-  }
-
   return (
-    <Fragment>
+    <section class="section is-main-section">
       <NotificationCard notification={notif} />
 
+      <JumpToElementById
+        testIfExist={getPaymentURL} 
+        onSelect={onSelect}
+        description={i18n.str`jump to order with the given product ID`}
+        palceholder={i18n.str`order id`}
+      />
+
       <ListPage
         orders={result.data.orders.map((o) => ({ ...o, id: o.order_id }))}
         onLoadMoreBefore={result.loadMorePrev}
@@ -126,7 +117,6 @@ export default function OrderList({
         hasMoreAfter={!result.isReachingEnd}
         onSelectOrder={(order) => onSelect(order.id)}
         onRefundOrder={(value) => setOrderToBeRefunded(value)}
-        errorOrderId={errorOrderId}
         isAllActive={isAllActive}
         isNotWiredActive={isNotWiredActive}
         isWiredActive={isWiredActive}
@@ -138,7 +128,6 @@ export default function OrderList({
           getPaymentURL(id).then((resp) => copyToClipboard(resp.data))
         }
         onCreate={onCreate}
-        onSearchOrderById={testIfOrderExistAndSelect}
         onSelectDate={setNewDate}
         onShowAll={() => setFilter({})}
         onShowNotPaid={() => setFilter({ paid: "no" })}
@@ -190,7 +179,7 @@ export default function OrderList({
           }}
         />
       )}
-    </Fragment>
+    </section>
   );
 }
 
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
index db73217ed..275f855cb 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/Table.tsx
@@ -244,7 +244,10 @@ function Table({
                     }
                     style={{ cursor: "pointer" }}
                   >
+                    <span style={{"whiteSpace":"nowrap"}}>
+
                     {i.total_sold} {i.unit}
+                    </span>
                   </td>
                   <td class="is-actions-cell right-sticky">
                     <div class="buttons is-right">
@@ -341,7 +344,7 @@ function FastProductWithInfiniteStockUpdateForm({
 
         <div class="buttons mt-5">
 
-          <button class="button " onClick={onCancel}>
+          <button class="button mt-5" onClick={onCancel}>
             <i18n.Translate>Clone</i18n.Translate>
           </button>
         </div>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
index 274a7c2ea..942b5d0ac 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/products/list/index.tsx
@@ -37,6 +37,7 @@ import { Notification } from "../../../../utils/types.js";
 import { CardTable } from "./Table.js";
 import { HttpStatusCode } from "@gnu-taler/taler-util";
 import { ConfirmModal, DeleteModal } from 
"../../../../components/modal/index.js";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
 
 interface Props {
   onUnauthorized: () => VNode;
@@ -74,60 +75,17 @@ export default function ProductList({
       return onNotFound();
     return onLoadError(result);
   }
-  const [errorId, setErrorId] = useState<string | undefined>(
-    undefined,
-  );
-
-  const [productId, setProductId] = useState<string>()
-  async function testIfProductExistAndSelect(orderId: string | undefined): 
Promise<void> {
-    if (!orderId) {
-      setErrorId(i18n.str`Enter a product id`);
-      return;
-    }
-    try {
-      await getProduct(orderId);
-      onSelect(orderId);
-      setErrorId(undefined);
-    } catch {
-      setErrorId(i18n.str`product not found`);
-    }
-  }
 
   return (
     <section class="section is-main-section">
       <NotificationCard notification={notif} />
 
-      <div class="level">
-        <div class="level-left">
-          <div class="level-item">
-            <div class="field has-addons">
-              <div class="control">
-                <input
-                  class={errorId ? "input is-danger" : "input"}
-                  type="text"
-                  value={productId ?? ""}
-                  onChange={(e) => setProductId(e.currentTarget.value)}
-                  placeholder={i18n.str`product id`}
-                />
-                {errorId && <p class="help is-danger">{errorId}</p>}
-              </div>
-              <span
-                class="has-tooltip-bottom"
-                data-tooltip={i18n.str`jump to product with the given product 
ID`}
-              >
-                <button
-                  class="button"
-                  onClick={(e) => testIfProductExistAndSelect(productId)}
-                >
-                  <span class="icon">
-                    <i class="mdi mdi-arrow-right" />
-                  </span>
-                </button>
-              </span>
-            </div>
-          </div>
-        </div>
-      </div>
+      <JumpToElementById
+        testIfExist={getProduct} 
+        onSelect={onSelect}
+        description={i18n.str`jump to product with the given product ID`}
+        palceholder={i18n.str`product id`}
+      />
 
       <CardTable
         instances={result.data}
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
index ab1d5ef91..bf6062c34 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
@@ -49,7 +49,6 @@ export function ListPage({
 
   const { i18n } = useTranslationContext();
   return (
-    <section class="section is-main-section">
       <CardTable
         templates={templates.map((o) => ({
           ...o,
@@ -65,6 +64,5 @@ export function ListPage({
         onLoadMoreAfter={onLoadMoreAfter}
         hasMoreAfter={!onLoadMoreAfter}
       />
-    </section>
   );
 }
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx
index 3bea9abe8..9fdf4ead9 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/Table.tsx
@@ -136,11 +136,10 @@ function Table({
   const { i18n } = useTranslationContext();
   return (
     <div class="table-container">
-      {onLoadMoreBefore && (
+      {hasMoreBefore && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more templates before the first one`}
-          disabled={!hasMoreBefore}
           onClick={onLoadMoreBefore}
         >
           <i18n.Translate>load newer templates</i18n.Translate>
@@ -188,7 +187,7 @@ function Table({
                       data-tooltip={i18n.str`use template to create new order`}
                       onClick={() => onNewOrder(i)}
                     >
-                      New order
+                      Use template
                     </button>
                     <button
                       class="button is-info is-small has-tooltip-left"
@@ -204,11 +203,10 @@ function Table({
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && (
+      {hasMoreAfter && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more templates after the last one`}
-          disabled={!hasMoreAfter}
           onClick={onLoadMoreAfter}
         >
           <i18n.Translate>load older templates</i18n.Translate>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
index 3c9bb231c..b9767442f 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/templates/list/index.tsx
@@ -35,8 +35,9 @@ import {
 } from "../../../../hooks/templates.js";
 import { Notification } from "../../../../utils/types.js";
 import { ListPage } from "./ListPage.js";
-import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { HttpStatusCode, TranslatedString } from "@gnu-taler/taler-util";
 import { ConfirmModal } from "../../../../components/modal/index.js";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
 
 interface Props {
   onUnauthorized: () => VNode;
@@ -60,7 +61,7 @@ export default function ListTemplates({
   const [position, setPosition] = useState<string | undefined>(undefined);
   const { i18n } = useTranslationContext();
   const [notif, setNotif] = useState<Notification | undefined>(undefined);
-  const { deleteTemplate } = useTemplateAPI();
+  const { deleteTemplate, testTemplateExist } = useTemplateAPI();
   const result = useInstanceTemplates({ position }, (id) => setPosition(id));
   const [deleting, setDeleting] =
     useState<MerchantBackend.Template.TemplateEntry | null>(null);
@@ -81,9 +82,16 @@ export default function ListTemplates({
   }
 
   return (
-    <Fragment>
+    <section class="section is-main-section">
       <NotificationCard notification={notif} />
 
+      <JumpToElementById
+        testIfExist={testTemplateExist} 
+        onSelect={onSelect}
+        description={i18n.str`jump to template with the given template ID`}
+        palceholder={i18n.str`template id`}
+      />
+
       <ListPage
         templates={result.data.templates}
         onLoadMoreBefore={
@@ -139,6 +147,6 @@ export default function ListTemplates({
           </p>
         </ConfirmModal>
       )}
-    </Fragment>
+    </section>
   );
 }
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
index db2533ecc..02b12c4c2 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
@@ -73,7 +73,7 @@ export function ListPage({
           >
             <InputSelector
               name="payto_uri"
-              label={i18n.str`Address`}
+              label={i18n.str`Account URI`}
               values={accounts}
               placeholder={i18n.str`Select one account`}
               tooltip={i18n.str`filter by account address`}
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
index 1c464cbc7..b6b1cf328 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
@@ -125,11 +125,10 @@ function Table({
   const [settings] = useSettings();
   return (
     <div class="table-container">
-      {onLoadMoreBefore && (
+      {hasMoreBefore && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more transfers before the first one`}
-          disabled={!hasMoreBefore}
           onClick={onLoadMoreBefore}
         >
           <i18n.Translate>load newer transfers</i18n.Translate>
@@ -198,11 +197,10 @@ function Table({
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && (
+      {hasMoreAfter && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more transfer after the last one`}
-          disabled={!hasMoreAfter}
           onClick={onLoadMoreAfter}
         >
           <i18n.Translate>load older transfers</i18n.Translate>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx
index 1bc1673ba..0fdbb9bc3 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/transfers/list/index.tsx
@@ -21,7 +21,7 @@
 
 import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
 import { h, VNode } from "preact";
-import { useState } from "preact/hooks";
+import { useEffect, useState } from "preact/hooks";
 import { Loading } from "../../../../components/exception/loading.js";
 import { MerchantBackend } from "../../../../declaration.js";
 import { useInstanceDetails } from "../../../../hooks/instance.js";
@@ -47,7 +47,6 @@ export default function ListTransfer({
   onCreate,
   onNotFound,
 }: Props): VNode {
-  const [form, setForm] = useState<Form>({ payto_uri: "" });
   const setFilter = (s?: "yes" | "no") => setForm({ ...form, verified: s });
 
   const [position, setPosition] = useState<string | undefined>(undefined);
@@ -56,6 +55,14 @@ export default function ListTransfer({
   const accounts = !instance.ok
     ? []
     : instance.data.accounts.map((a) => a.payto_uri);
+  const [form, setForm] = useState<Form>({ payto_uri: "" });
+
+  const shoulUseDefaultAccount = accounts.length === 1
+  useEffect(() => {
+    if (shoulUseDefaultAccount) {
+      setForm({...form, payto_uri: accounts[0]})
+    }
+  }, [shoulUseDefaultAccount])
 
   const isVerifiedTransfers = form.verified === "yes";
   const isNonVerifiedTransfers = form.verified === "no";
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx
 
b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx
index cebc1ade6..4e813d777 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/validators/create/CreatePage.tsx
@@ -118,6 +118,7 @@ export function CreatePage({ onCreate, onBack }: Props): 
VNode {
               {state.otp_algorithm && state.otp_algorithm > 0 ? (
                 <Fragment>
                   <InputWithAddon<Entity>
+                    expand
                     name="otp_key"
                     label={i18n.str`Device key`}
                     inputType={showKey ? "text" : "password"}
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/validators/list/Table.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/validators/list/Table.tsx
index b639a6134..0c28027fe 100644
--- 
a/packages/merchant-backoffice-ui/src/paths/instance/validators/list/Table.tsx
+++ 
b/packages/merchant-backoffice-ui/src/paths/instance/validators/list/Table.tsx
@@ -126,11 +126,10 @@ function Table({
   const { i18n } = useTranslationContext();
   return (
     <div class="table-container">
-      {onLoadMoreBefore && (
+      {hasMoreBefore && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more devices before the first one`}
-          disabled={!hasMoreBefore}
           onClick={onLoadMoreBefore}
         >
           <i18n.Translate>load newer devices</i18n.Translate>
@@ -180,11 +179,10 @@ function Table({
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && (
+      {hasMoreAfter && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more devices after the last one`}
-          disabled={!hasMoreAfter}
           onClick={onLoadMoreAfter}
         >
           <i18n.Translate>load older devices</i18n.Translate>
diff --git 
a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx 
b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx
index 124ced1f1..42a179d2c 100644
--- a/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx
@@ -126,11 +126,10 @@ function Table({
   const { i18n } = useTranslationContext();
   return (
     <div class="table-container">
-      {onLoadMoreBefore && (
+      {hasMoreBefore && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more webhooks before the first one`}
-          disabled={!hasMoreBefore}
           onClick={onLoadMoreBefore}
         >
           <i18n.Translate>load newer webhooks</i18n.Translate>
@@ -187,11 +186,10 @@ function Table({
           })}
         </tbody>
       </table>
-      {onLoadMoreAfter && (
+      {hasMoreAfter && (
         <button
           class="button is-fullwidth"
           data-tooltip={i18n.str`load more webhooks after the last one`}
-          disabled={!hasMoreAfter}
           onClick={onLoadMoreAfter}
         >
           <i18n.Translate>load older webhooks</i18n.Translate>
diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx 
b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
index a9e3c3a1b..e37ef4bef 100644
--- a/packages/merchant-backoffice-ui/src/paths/login/index.tsx
+++ b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
@@ -26,31 +26,15 @@ import { useBackendContext } from 
"../../context/backend.js";
 import { useInstanceContext } from "../../context/instance.js";
 import { AccessToken, LoginToken } from "../../declaration.js";
 import { useCredentialsChecker } from "../../hooks/backend.js";
-import { useBackendURL } from "../../hooks/index.js";
 
 interface Props {
   onConfirm: (token: LoginToken | undefined) => void;
 }
 
-function getTokenValuePart(t: string): string {
-  if (!t) return t;
-  const match = /secret-token:(.*)/.exec(t);
-  if (!match || !match[1]) return "";
-  return match[1];
-}
-
 function normalizeToken(r: string): AccessToken {
   return `secret-token:${r}` as AccessToken;
 }
 
-function cleanUp(s: string): string {
-  let result = s;
-  if (result.indexOf("webui/") !== -1) {
-    result = result.substring(0, result.indexOf("webui/"));
-  }
-  return result;
-}
-
 export function LoginPage({ onConfirm }: Props): VNode {
   const { url: backendURL, changeBackend, resetBackend } = useBackendContext();
   const { admin, id } = useInstanceContext();
@@ -245,11 +229,14 @@ function AsyncButton({ onClick, disabled, type = "", 
children }: { type?: string
 export function ConnectionPage({ onConfirm }: { onConfirm: (s: string) => void 
}): VNode {
   const { url: backendURL } = useBackendContext()
 
-  const [url, setURL] = useState(cleanUp(backendURL));
+  const [error, setError] = useState<string>();
+  const [url, setURL] = useState(backendURL ?? "");
   const { i18n } = useTranslationContext();
 
   async function doConnect() {
-    onConfirm(url)
+    const withHttp = url.startsWith("http") ? url : "https://"; + url
+    
+    onConfirm(withHttp)
   }
 
   return (

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]