[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.