gnunet-svn
[Top][All Lists]
Advanced

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

[taler-merchant-backoffice] 01/03: taking instance name from the request


From: gnunet
Subject: [taler-merchant-backoffice] 01/03: taking instance name from the request parameter
Date: Fri, 26 Mar 2021 22:09:48 +0100

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

sebasjm pushed a commit to branch master
in repository merchant-backoffice.

commit 26d5d2ccbe443184aaa68757cd33dc3e9a6d7ca6
Author: Sebastian <sebasjm@gmail.com>
AuthorDate: Fri Mar 26 14:11:11 2021 -0300

    taking instance name from the request parameter
---
 CHANGELOG.md                                       | 19 ++++++++-
 packages/frontend/preact.config.js                 | 18 --------
 packages/frontend/src/ApplicationReadyRoutes.tsx   | 14 +++++--
 packages/frontend/src/InstanceRoutes.tsx           |  9 +++-
 .../frontend/src/components/exception/login.tsx    | 10 +++--
 packages/frontend/src/components/menu/index.tsx    | 24 +++++++----
 packages/frontend/src/hooks/backend.ts             | 24 ++++++++---
 packages/frontend/src/hooks/index.ts               | 49 +++++++---------------
 packages/frontend/src/paths/admin/create/index.tsx | 14 +++----
 packages/frontend/src/paths/admin/list/Table.tsx   |  3 +-
 10 files changed, 97 insertions(+), 87 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 089f6d4..646d44e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,14 +24,29 @@ and this project adheres to [Semantic 
Versioning](https://semver.org/spec/v2.0.0
  - edit button to go to instance settings
  - check if there is a way to remove auto async for /routes 
/components/{async,routes} so it can be turned on when building 
non-single-bundle
  
- - product detail: we could have some button that brings us to thedetailed 
screen for the product
+ - product detail: we could have some button that brings us to the detailed 
screen for the product
+ - order id field to go
 
- - https://bugs.gnunet.org/view.php?id=6815
+created
+wired (if wired === true)
+refund
+
+error details
 
+fatal error: exchange error
+warning: exchange repotred problem
+ - navigation to another instance should not do full refresh
+ - cleanup instance and token management, because code is a mess and can be 
refactored 
 ## [Unreleased]
+ - fixed bug when updating token and not admin
+ - showing a yellow bar on non-default instance navigation (admin)
+ - 
+## [0.0.6] - 2021-03-25
  - complete order list information (#6793)
  - complete product list information (#6792)
  - missing fields in the instance update
+ - https://bugs.gnunet.org/view.php?id=6815
+ 
 
 ## [0.0.5] - 2021-03-18
  - change the admin title to "instances" if we are listing the instances and 
"settings: $ID" on updating instances (#6790)
diff --git a/packages/frontend/preact.config.js 
b/packages/frontend/preact.config.js
index f9f7cf1..a1898bd 100644
--- a/packages/frontend/preact.config.js
+++ b/packages/frontend/preact.config.js
@@ -61,21 +61,3 @@ export default {
     // config.plugins.push(new I18n())
   }
 }
-
-class I18n {
-  constructor(options) {
-    this.options = options
-  }
-
-  apply(compiler) {
-    compiler.hooks.normalModuleFactory.tap('I18n', (factory) => {
-      // console.log('factory', factory)
-      factory.hooks.parser.for('javascript/auto').tap('I18n', (parser, 
options) => {
-        // console.log('parser', parser)
-        parser.hooks.callAnyMember.for('console').tap('I18n', expression => {
-          console.log("expression", expression)
-        });
-      });
-    })
-  }
-}
\ No newline at end of file
diff --git a/packages/frontend/src/ApplicationReadyRoutes.tsx 
b/packages/frontend/src/ApplicationReadyRoutes.tsx
index d8a92ce..a4f3f4f 100644
--- a/packages/frontend/src/ApplicationReadyRoutes.tsx
+++ b/packages/frontend/src/ApplicationReadyRoutes.tsx
@@ -99,10 +99,16 @@ export function ApplicationReadyRoutes(): VNode {
     return <NotYetReadyAppMenu title="Loading..." />
   }
 
+  let instance
+  try {
+    const url = new URL(window.location.href)
+    instance = url.searchParams.get('instance')
+  } finally {
+    if (!instance) instance = 'default'
+  }
   return <Fragment>
-    <Menu instance="default" admin
-      onLogout={clearTokenAndGoToRoot}
-    />
-    <InstanceRoutes admin id="default" />
+    <Menu instance={instance} admin onLogout={clearTokenAndGoToRoot} />
+    <InstanceRoutes admin id={instance} />
   </Fragment>
+
 }
diff --git a/packages/frontend/src/InstanceRoutes.tsx 
b/packages/frontend/src/InstanceRoutes.tsx
index 7f16416..6e1fdd4 100644
--- a/packages/frontend/src/InstanceRoutes.tsx
+++ b/packages/frontend/src/InstanceRoutes.tsx
@@ -24,7 +24,7 @@ import { useCallback, useEffect, useMemo } from 
"preact/hooks";
 import { Route, Router, route } from 'preact-router';
 import { useMessageTemplate } from 'preact-messages';
 import { createHashHistory } from 'history';
-import { useBackendInstanceToken } from './hooks';
+import { useBackendDefaultToken, useBackendInstanceToken } from './hooks';
 import { InstanceContextProvider, useBackendContext } from './context/backend';
 import { SwrError, useInstanceDetails } from "./hooks/backend";
 // import { Notification } from './utils/types';
@@ -116,6 +116,7 @@ function AdminInstanceUpdatePage({ id, ...rest }: { id: 
string } & InstanceUpdat
 }
 
 export function InstanceRoutes({ id, admin }: Props): VNode {
+  const [_, updateDefaultToken] = useBackendDefaultToken()
   const [token, updateToken] = useBackendInstanceToken(id);
   const { changeBackend, addTokenCleaner } = useBackendContext();
   const cleaner = useCallback(() => { updateToken(undefined); }, [id]);
@@ -127,8 +128,12 @@ export function InstanceRoutes({ id, admin }: Props): 
VNode {
 
   const updateLoginStatus = (url: string, token?: string) => {
     changeBackend(url);
-    if (token)
+    if (!token) return
+    if (admin) {
       updateToken(token);
+    } else {
+      updateDefaultToken(token)
+    }
   };
 
   const value = useMemo(() => ({ id, token, admin }), [id, token])
diff --git a/packages/frontend/src/components/exception/login.tsx 
b/packages/frontend/src/components/exception/login.tsx
index fde6698..92f6bbe 100644
--- a/packages/frontend/src/components/exception/login.tsx
+++ b/packages/frontend/src/components/exception/login.tsx
@@ -22,7 +22,7 @@
 import { h, VNode } from "preact";
 import { useMessageTemplate } from "preact-messages";
 import { useState } from "preact/hooks";
-import { useBackendContext } from "../../context/backend";
+import { useBackendContext, useInstanceContext } from "../../context/backend";
 import { Notification } from "../../utils/types";
 
 interface Props {
@@ -31,9 +31,11 @@ interface Props {
 }
 
 export function LoginModal({ onConfirm, withMessage }: Props): VNode {
-  const backend = useBackendContext()
-  const [token, setToken] = useState(backend.token || '')
-  const [url, setURL] = useState(backend.url)
+  const { url: backendUrl, token: baseToken } = useBackendContext()
+  const { admin, token: instanceToken } = useInstanceContext()
+  const [token, setToken] = useState(!admin ? baseToken : instanceToken || '')
+  
+  const [url, setURL] = useState(backendUrl)
   const i18n = useMessageTemplate()
 
   return <div class="columns is-centered">
diff --git a/packages/frontend/src/components/menu/index.tsx 
b/packages/frontend/src/components/menu/index.tsx
index af0b074..36b5639 100644
--- a/packages/frontend/src/components/menu/index.tsx
+++ b/packages/frontend/src/components/menu/index.tsx
@@ -22,6 +22,7 @@ import { NavigationBar } from "./NavigationBar";
 import { Sidebar } from "./SideBar";
 import Match from 'preact-router/match';
 import { Notification } from "../../utils/types";
+import { calculateRootPath } from "../../hooks";
 
 
 function getInstanceTitle(path: string, id: string): string {
@@ -45,12 +46,10 @@ function getInstanceTitle(path: string, id: string): string 
{
 }
 
 const INSTANCE_ID_LOOKUP = /^\/instance\/([^/]*)\//
-function getAdminTitle(path: string) {
+function getAdminTitle(path: string, instance: string) {
   if (path === AdminPaths.new_instance) return `New instance`
   if (path === AdminPaths.list_instances) return `Instances`
-  const match = INSTANCE_ID_LOOKUP.exec(path)
-  if (match && match[1]) return 
getInstanceTitle(path.replace(INSTANCE_ID_LOOKUP, '/'), match[1]);
-  return getInstanceTitle(path, 'default')
+  return getInstanceTitle(path, instance)
 }
 
 interface MenuProps {
@@ -71,12 +70,19 @@ export function Menu({ onLogout, title, instance, admin }: 
MenuProps): VNode {
   const [mobileOpen, setMobileOpen] = useState(false)
 
   return <Match>{({ path }: any) => {
-    const titleWithSubtitle = title ? title : (!admin ? getInstanceTitle(path, 
instance) : getAdminTitle(path))
-
+    const titleWithSubtitle = title ? title : (!admin ? getInstanceTitle(path, 
instance) : getAdminTitle(path, instance))
+    const adminInstance = instance === "default"
     return (<WithTitle title={titleWithSubtitle}>
       <div class={mobileOpen ? "has-aside-mobile-expanded" : ""} onClick={() 
=> setMobileOpen(false)}>
         <NavigationBar onMobileMenu={() => setMobileOpen(!mobileOpen)} 
title={titleWithSubtitle} />
-        {onLogout && <Sidebar onLogout={onLogout} admin={admin} 
instance={instance} mobile={mobileOpen} />}
+        
+        {onLogout && <Sidebar onLogout={onLogout} admin={admin && 
adminInstance} instance={instance} mobile={mobileOpen} />}
+
+        { admin && !adminInstance && <nav class="level">
+          <div class="level-item has-text-centered has-background-warning">
+            <p class="is-size-5">You are viewing the instance 
<b>"{instance}"</b>. <a href={calculateRootPath()} >go back</a></p>
+          </div>
+        </nav> }
       </div>
     </WithTitle>
     )
@@ -92,7 +98,7 @@ interface NotYetReadyAppMenuProps {
 interface NotifProps {
   notification?: Notification;
 }
-export function NotificationCard({ notification:n }: NotifProps) {
+export function NotificationCard({ notification: n }: NotifProps) {
   if (!n) return null
   return <div class="notification">
     <div class="columns is-vcentered">
@@ -102,7 +108,7 @@ export function NotificationCard({ notification:n }: 
NotifProps) {
             <p>{n.message}</p>
           </div>
           <div class="message-body">
-          {n.description}
+            {n.description}
           </div>
         </article>
       </div>
diff --git a/packages/frontend/src/hooks/backend.ts 
b/packages/frontend/src/hooks/backend.ts
index 59bcdd0..99071bc 100644
--- a/packages/frontend/src/hooks/backend.ts
+++ b/packages/frontend/src/hooks/backend.ts
@@ -441,17 +441,26 @@ export function useInstanceMutateAPI(): InstaceMutateAPI {
 }
 
 export function useBackendInstances(): 
HttpResponse<MerchantBackend.Instances.InstancesResponse> {
-  const { url, token } = useBackendContext()
+  const { url } = useBackendContext()
+  const { token } = useInstanceContext();
+
   const { data, error } = useSWR<MerchantBackend.Instances.InstancesResponse, 
SwrError>(['/private/instances', token, url], fetcher)
 
   return { data, unauthorized: error?.status === 401, notfound: error?.status 
=== 404, error }
 }
 
 export function useInstanceDetails(): 
HttpResponse<MerchantBackend.Instances.QueryInstancesResponse> {
-  const { url: baseUrl } = useBackendContext();
-  const { token, id, admin } = useInstanceContext();
+  // const { url: baseUrl } = useBackendContext();
+  // const { token, id, admin } = useInstanceContext();
+  // const url = !admin ? baseUrl : `${baseUrl}/instances/${id}`
+  const { url: baseUrl, token: baseToken } = useBackendContext();
+  const { token: instanceToken, id, admin } = useInstanceContext();
 
-  const url = !admin ? baseUrl : `${baseUrl}/instances/${id}`
+  const { url, token } = !admin ? {
+    url: baseUrl, token: baseToken
+  } : {
+    url: `${baseUrl}/instances/${id}`, token: instanceToken
+  }
 
   const { data, error } = 
useSWR<MerchantBackend.Instances.QueryInstancesResponse, 
SwrError>([`/private/`, token, url], fetcher)
 
@@ -496,6 +505,12 @@ export function useInstanceOrders(args: 
InstanceOrderFilter, updateFilter: (d:Da
   const totalAfter = pageAfter * PAGE_SIZE;
   const totalBefore = args?.date ? pageBefore * PAGE_SIZE : 0;
 
+  /**
+   * FIXME: this can be cleaned up a little
+   * 
+   * 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 } = 
useSWR<MerchantBackend.Orders.OrderHistory, SwrError>(
     [`/private/orders`, token, url, args?.paid, args?.refunded, args?.wired, 
args?.date, totalBefore],
     orderFetcher,
@@ -527,7 +542,6 @@ export function useInstanceOrders(args: 
InstanceOrderFilter, updateFilter: (d:Da
       setPageAfter(pageAfter + 1)
     } else { 
       const from = 
afterData?.orders?.[afterData?.orders?.length-1]?.timestamp?.t_ms
-      // console.log(afterData?.orders?.map(d => d.row_id), PAGE_SIZE, from && 
format(new Date(from), 'yyyy/MM/dd HH:mm:ss'))     
       if (from) updateFilter(new Date(from))
     }
   }
diff --git a/packages/frontend/src/hooks/index.ts 
b/packages/frontend/src/hooks/index.ts
index e1af7de..ab268e9 100644
--- a/packages/frontend/src/hooks/index.ts
+++ b/packages/frontend/src/hooks/index.ts
@@ -32,16 +32,26 @@ export function useBackendContextState() {
   const [cleaners, setCleaners] = useState([tokenCleaner])
   const addTokenCleaner = (c: () => void) => setCleaners(cs => [...cs, c])
   const addTokenCleanerMemo = useCallback((c: () => void) => { 
addTokenCleaner(c) }, [tokenCleaner])
+
   const clearAllTokens = () => {
     cleaners.forEach(c => c())
+    for (let i = 0; i < localStorage.length; i++) {
+      const k = localStorage.key(i)
+      if (k && /^backend-token/.test(k)) localStorage.removeItem(k)
+    }
     resetBackend()
   }
 
   return { url, token, triedToLog, changeBackend, updateToken, lang, setLang, 
resetBackend, clearAllTokens, addTokenCleaner: addTokenCleanerMemo }
 }
 
+export const calculateRootPath = () => {
+  const rootPath = typeof window !== undefined ? window.location.origin + 
window.location.pathname : '/'
+  return rootPath
+}
+
 export function useBackendURL(): [string, boolean, StateUpdater<string>, () => 
void] {
-  const [value, setter] = useNotNullLocalStorage('backend-url', typeof window 
!== 'undefined' ? window.location.origin : '')
+  const [value, setter] = useNotNullLocalStorage('backend-url', 
calculateRootPath())
   const [triedToLog, setTriedToLog] = useLocalStorage('tried-login')
 
   const checkedSetter = (v: ValueOrFunction<string>) => {
@@ -59,49 +69,18 @@ export function useBackendDefaultToken(): [string | 
undefined, StateUpdater<stri
   return useLocalStorage('backend-token')
 }
 
-export function useBackendInstanceToken(id: string): [string | undefined, 
StateUpdater<string | undefined>, VoidFunction] {
+export function useBackendInstanceToken(id: string): [string | undefined, 
StateUpdater<string | undefined>] {
   const [token, setToken] = useLocalStorage(`backend-token-${id}`)
-  const [ids, setIds] = useLocalStorage(`backend-token-ids`)
-
-  function clearAllTokens() {
-    // TODO: refactor this
-    ids?.split(',').map(i => localStorage.removeItem(`backend-token-${i}`))
-  }
-
-  useEffect(() => {
-    setIds((ids: string | undefined): string | undefined => {
-      if (!ids) return ids
-      const all = ids.split(',')
-      if (all.includes(id)) return ids
-      return all.concat(id).filter(Boolean).join(',')
-    })
-  }, [id, setIds])
-
   const [defaultToken, defaultSetToken] = useBackendDefaultToken()
 
   // instance named 'default' use the default token
   if (id === 'default') {
-    return [defaultToken, defaultSetToken, clearAllTokens]
+    return [defaultToken, defaultSetToken]
   }
 
-  return [token, setToken, clearAllTokens]
+  return [token, setToken]
 }
 
-// export function useBackend(): [State, StateUpdater<State>] {
-//   const [url, setUrl] = useLocalStorage('backend-url', 
window.location.origin)
-//   const [token, setToken] = useLocalStorage('backend-token')
-
-//   const updater: StateUpdater<State> = (value: State | ((value: State) => 
State)) => {
-//     const valueToStore = value instanceof Function ? value({ token, url: 
url || window.location.origin }) : value;
-//     setUrl(valueToStore.url)
-//     setToken(valueToStore.token)
-
-//     mutate('/private/instances', null)
-//   }
-
-//   return [{ token, url: url || window.location.origin }, updater]
-// }
-
 export function useLang(): [string, StateUpdater<string>] {
   const browserLang = typeof window !== "undefined" ? navigator.language || 
(navigator as any).userLanguage : undefined;
   const defaultLang = (browserLang || 'en').substring(0,2)
diff --git a/packages/frontend/src/paths/admin/create/index.tsx 
b/packages/frontend/src/paths/admin/create/index.tsx
index 7205e12..07f6577 100644
--- a/packages/frontend/src/paths/admin/create/index.tsx
+++ b/packages/frontend/src/paths/admin/create/index.tsx
@@ -15,9 +15,6 @@
  */
 import { ComponentChildren, Fragment, h, VNode } from "preact";
 import { useState } from "preact/hooks";
-import { Loading } from "../../../components/exception/loading";
-import { FormProvider } from "../../../components/form/Field";
-import { Input } from "../../../components/form/Input";
 import { NotificationCard } from "../../../components/menu";
 import { MerchantBackend } from "../../../declaration";
 import { useAdminMutateAPI } from "../../../hooks/backend";
@@ -46,7 +43,7 @@ export default function Create({ onBack, onConfirm, onError, 
forceId }: Props):
         <div class="field-body is-flex-grow-3">
           <div class="field">
             <p class="control">
-              <input class="input" readonly value={createdOk.id} readOnly />
+              <input class="input" readonly value={createdOk.id} />
             </p>
           </div>
         </div>
@@ -58,7 +55,7 @@ export default function Create({ onBack, onConfirm, onError, 
forceId }: Props):
         <div class="field-body is-flex-grow-3">
           <div class="field">
             <p class="control">
-              <input class="input" readonly value={createdOk.name} disabled />
+              <input class="input" readonly value={createdOk.name} />
             </p>
           </div>
         </div>
@@ -70,7 +67,10 @@ export default function Create({ onBack, onConfirm, onError, 
forceId }: Props):
         <div class="field-body is-flex-grow-3">
           <div class="field">
             <p class="control">
-              <input class="input" readonly value={createdOk.auth.token} 
disabled />
+              {createdOk.auth.method === 'external' && 'external'}
+              {createdOk.auth.method === 'token' &&
+                <input class="input" readonly value={createdOk.auth.token} />
+              }
             </p>
           </div>
         </div>
@@ -107,7 +107,7 @@ interface CreatedSuccessfullyProps {
 function CreatedSuccessfully({ children, onConfirm }: 
CreatedSuccessfullyProps) {
   return <div class="columns is-fullwidth is-vcentered content-full-size">
     <div class="column" />
-    <div class="column is-half">
+    <div class="column is-three-quarters">
       <div class="card">
         <header class="card-header has-background-success">
           <p class="card-header-title has-text-white-ter">
diff --git a/packages/frontend/src/paths/admin/list/Table.tsx 
b/packages/frontend/src/paths/admin/list/Table.tsx
index 20186a6..f0c3242 100644
--- a/packages/frontend/src/paths/admin/list/Table.tsx
+++ b/packages/frontend/src/paths/admin/list/Table.tsx
@@ -24,6 +24,7 @@ import { Message } from "preact-messages"
 import { StateUpdater, useEffect, useState } from "preact/hooks"
 import { useBackendContext } from "../../../context/backend";
 import { MerchantBackend } from "../../../declaration"
+import { calculateRootPath } from "../../../hooks";
 
 interface Props {
   instances: MerchantBackend.Instances.Instance[];
@@ -121,7 +122,7 @@ function Table({ rowSelection, rowSelectionHandler, 
instances, onUpdate, onDelet
                 <span class="check" />
               </label>
             </td>
-            <td><a href={`/instances/${i.id}`} {...{ native: true }} 
onClick={() => changeBackend(`${url}/instances/${i.id}`)} >{i.id}</a></td>
+            <td><a href={`${calculateRootPath()}?instance=${i.id}`} {...{ 
native: true }} >{i.id}</a></td>
             <td >{i.name}</td>
             <td class="is-actions-cell right-sticky">
               <div class="buttons is-right">

-- 
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]