ui settings view
This commit is contained in:
parent
8eb0183c78
commit
7d1621767c
@ -26,7 +26,7 @@ import {
|
|||||||
} from "@gnu-taler/web-util/browser";
|
} from "@gnu-taler/web-util/browser";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { route } from "preact-router";
|
import { route } from "preact-router";
|
||||||
import { useMemo } from "preact/hooks";
|
import { useMemo, useState } from "preact/hooks";
|
||||||
import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
|
import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
|
||||||
import { Loading } from "./components/exception/loading.js";
|
import { Loading } from "./components/exception/loading.js";
|
||||||
import {
|
import {
|
||||||
@ -42,6 +42,7 @@ import { useBackendConfig } from "./hooks/backend.js";
|
|||||||
import { strings } from "./i18n/strings.js";
|
import { strings } from "./i18n/strings.js";
|
||||||
import LoginPage from "./paths/login/index.js";
|
import LoginPage from "./paths/login/index.js";
|
||||||
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
||||||
|
import { Settings } from "./paths/settings/index.js";
|
||||||
|
|
||||||
export function Application(): VNode {
|
export function Application(): VNode {
|
||||||
return (
|
return (
|
||||||
@ -70,10 +71,19 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
: { currency: "unknown", version: "unknown" };
|
: { currency: "unknown", version: "unknown" };
|
||||||
const ctx = useMemo(() => ({ currency, version }), [currency, version]);
|
const ctx = useMemo(() => ({ currency, version }), [currency, version]);
|
||||||
|
|
||||||
|
const [showSettings, setShowSettings] = useState(false)
|
||||||
|
|
||||||
|
if (showSettings) {
|
||||||
|
return <Fragment>
|
||||||
|
<NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="UI Settings" />
|
||||||
|
<Settings />
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
if (!triedToLog) {
|
if (!triedToLog) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Welcome!" />
|
<NotYetReadyAppMenu title="Welcome!" onShowSettings={() => setShowSettings(true)} />
|
||||||
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
|
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
@ -87,7 +97,7 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Login" />
|
<NotYetReadyAppMenu title="Login" onShowSettings={() => setShowSettings(true)} />
|
||||||
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
|
<LoginPage onConfirm={updateLoginInfoAndGoToRoot} />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
@ -98,7 +108,7 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Error" />
|
<NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Server not found`,
|
message: i18n.str`Server not found`,
|
||||||
@ -112,7 +122,7 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
}
|
}
|
||||||
if (result.type === ErrorType.SERVER) {
|
if (result.type === ErrorType.SERVER) {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Error" />
|
<NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Server response with an error code`,
|
message: i18n.str`Server response with an error code`,
|
||||||
@ -125,7 +135,7 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
}
|
}
|
||||||
if (result.type === ErrorType.UNREADABLE) {
|
if (result.type === ErrorType.UNREADABLE) {
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Error" />
|
<NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
|
message: i18n.str`Response from server is unreadable, http status: ${result.status}`,
|
||||||
@ -138,7 +148,7 @@ function ApplicationStatusRoutes(): VNode {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Error" />
|
<NotYetReadyAppMenu title="Error" onShowSettings={() => setShowSettings(true)} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Unexpected Error`,
|
message: i18n.str`Unexpected Error`,
|
||||||
|
@ -33,6 +33,7 @@ import { InstanceRoutes } from "./InstanceRoutes.js";
|
|||||||
import LoginPage from "./paths/login/index.js";
|
import LoginPage from "./paths/login/index.js";
|
||||||
import { INSTANCE_ID_LOOKUP } from "./utils/constants.js";
|
import { INSTANCE_ID_LOOKUP } from "./utils/constants.js";
|
||||||
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
import { HttpStatusCode } from "@gnu-taler/taler-util";
|
||||||
|
import { Settings } from "./paths/settings/index.js";
|
||||||
|
|
||||||
export function ApplicationReadyRoutes(): VNode {
|
export function ApplicationReadyRoutes(): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
@ -48,8 +49,15 @@ export function ApplicationReadyRoutes(): VNode {
|
|||||||
clearAllTokens();
|
clearAllTokens();
|
||||||
route("/");
|
route("/");
|
||||||
};
|
};
|
||||||
|
const [showSettings, setShowSettings] = useState(false)
|
||||||
|
|
||||||
if (result.loading) return <NotYetReadyAppMenu title="Loading..." />;
|
if (showSettings) {
|
||||||
|
return <Fragment>
|
||||||
|
<NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="UI Settings" onLogout={clearTokenAndGoToRoot} />
|
||||||
|
<Settings/>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
if (result.loading) return <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="Loading..." />;
|
||||||
|
|
||||||
let admin = true;
|
let admin = true;
|
||||||
let instanceNameByBackendURL;
|
let instanceNameByBackendURL;
|
||||||
@ -61,7 +69,7 @@ export function ApplicationReadyRoutes(): VNode {
|
|||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Login" onLogout={clearTokenAndGoToRoot} />
|
<NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="Login" onLogout={clearTokenAndGoToRoot} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Access denied`,
|
message: i18n.str`Access denied`,
|
||||||
@ -81,7 +89,7 @@ export function ApplicationReadyRoutes(): VNode {
|
|||||||
// does not match our pattern
|
// does not match our pattern
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<NotYetReadyAppMenu title="Error" onLogout={clearTokenAndGoToRoot} />
|
<NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} title="Error" onLogout={clearTokenAndGoToRoot} />
|
||||||
<NotificationCard
|
<NotificationCard
|
||||||
notification={{
|
notification={{
|
||||||
message: i18n.str`Couldn't access the server.`,
|
message: i18n.str`Couldn't access the server.`,
|
||||||
|
@ -68,6 +68,7 @@ import LoginPage from "./paths/login/index.js";
|
|||||||
import NotFoundPage from "./paths/notfound/index.js";
|
import NotFoundPage from "./paths/notfound/index.js";
|
||||||
import { Notification } from "./utils/types.js";
|
import { Notification } from "./utils/types.js";
|
||||||
import { MerchantBackend } from "./declaration.js";
|
import { MerchantBackend } from "./declaration.js";
|
||||||
|
import { Settings } from "./paths/settings/index.js";
|
||||||
|
|
||||||
export enum InstancePaths {
|
export enum InstancePaths {
|
||||||
// details = '/',
|
// details = '/',
|
||||||
@ -100,6 +101,8 @@ export enum InstancePaths {
|
|||||||
webhooks_list = "/webhooks",
|
webhooks_list = "/webhooks",
|
||||||
webhooks_update = "/webhooks/:tid/update",
|
webhooks_update = "/webhooks/:tid/update",
|
||||||
webhooks_new = "/webhooks/new",
|
webhooks_new = "/webhooks/new",
|
||||||
|
|
||||||
|
settings = "/settings",
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
@ -240,6 +243,9 @@ export function InstanceRoutes({
|
|||||||
<Menu
|
<Menu
|
||||||
instance={id}
|
instance={id}
|
||||||
admin={admin}
|
admin={admin}
|
||||||
|
onShowSettings={() => {
|
||||||
|
route("/settings")
|
||||||
|
}}
|
||||||
path={path}
|
path={path}
|
||||||
onLogout={clearTokenAndGoToRoot}
|
onLogout={clearTokenAndGoToRoot}
|
||||||
setInstanceName={setInstanceName}
|
setInstanceName={setInstanceName}
|
||||||
@ -558,6 +564,7 @@ export function InstanceRoutes({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Route path={InstancePaths.kyc} component={ListKYCPage} />
|
<Route path={InstancePaths.kyc} component={ListKYCPage} />
|
||||||
|
<Route path={InstancePaths.settings} component={Settings} />
|
||||||
{/**
|
{/**
|
||||||
* Example pages
|
* Example pages
|
||||||
*/}
|
*/}
|
||||||
|
@ -229,7 +229,7 @@ export function LoginModal({ onConfirm, withMessage }: Props): VNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function AsyncButton({onClick, children}:{onClick: () => Promise<void>, children: ComponentChildren}):VNode {
|
function AsyncButton({ onClick, children }: { onClick: () => Promise<void>, children: ComponentChildren }): VNode {
|
||||||
const [running, setRunning] = useState(false)
|
const [running, setRunning] = useState(false)
|
||||||
return <button class="button is-info" disabled={running} onClick={() => {
|
return <button class="button is-info" disabled={running} onClick={() => {
|
||||||
setRunning(true)
|
setRunning(true)
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { h, VNode } from "preact";
|
import { h, VNode } from "preact";
|
||||||
import { LangSelector } from "./LangSelector.js";
|
|
||||||
import logo from "../../assets/logo-2021.svg";
|
import logo from "../../assets/logo-2021.svg";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -65,7 +64,6 @@ export function NavigationBar({ onMobileMenu, title }: Props): VNode {
|
|||||||
</a>
|
</a>
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<div class="navbar-item" style={{ paddingTop: 4, paddingBottom: 4 }}>
|
<div class="navbar-item" style={{ paddingTop: 4, paddingBottom: 4 }}>
|
||||||
<LangSelector />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -31,6 +31,7 @@ const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined;
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onLogout: () => void;
|
onLogout: () => void;
|
||||||
|
onShowSettings: () => void;
|
||||||
mobile?: boolean;
|
mobile?: boolean;
|
||||||
instance: string;
|
instance: string;
|
||||||
admin?: boolean;
|
admin?: boolean;
|
||||||
@ -40,6 +41,7 @@ interface Props {
|
|||||||
export function Sidebar({
|
export function Sidebar({
|
||||||
mobile,
|
mobile,
|
||||||
instance,
|
instance,
|
||||||
|
onShowSettings,
|
||||||
onLogout,
|
onLogout,
|
||||||
admin,
|
admin,
|
||||||
mimic,
|
mimic,
|
||||||
@ -78,21 +80,8 @@ export function Sidebar({
|
|||||||
<div class="menu is-menu-main">
|
<div class="menu is-menu-main">
|
||||||
{instance ? (
|
{instance ? (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<p class="menu-label">
|
|
||||||
<i18n.Translate>Instance</i18n.Translate>
|
|
||||||
</p>
|
|
||||||
<ul class="menu-list">
|
<ul class="menu-list">
|
||||||
<li>
|
<li>
|
||||||
<a href={"/update"} class="has-icon">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="mdi mdi-square-edit-outline" />
|
|
||||||
</span>
|
|
||||||
<span class="menu-item-label">
|
|
||||||
<i18n.Translate>Settings</i18n.Translate>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href={"/orders"} class="has-icon">
|
<a href={"/orders"} class="has-icon">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
<i class="mdi mdi-cash-register" />
|
<i class="mdi mdi-cash-register" />
|
||||||
@ -132,6 +121,31 @@ export function Sidebar({
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
{needKYC && (
|
||||||
|
<li>
|
||||||
|
<a href={"/kyc"} class="has-icon">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="mdi mdi-account-check" />
|
||||||
|
</span>
|
||||||
|
<span class="menu-item-label">KYC Status</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
<p class="menu-label">
|
||||||
|
<i18n.Translate>Configuration</i18n.Translate>
|
||||||
|
</p>
|
||||||
|
<ul class="menu-list">
|
||||||
|
<li>
|
||||||
|
<a href={"/update"} class="has-icon">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="mdi mdi-square-edit-outline" />
|
||||||
|
</span>
|
||||||
|
<span class="menu-item-label">
|
||||||
|
<i18n.Translate>Account</i18n.Translate>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href={"/reserves"} class="has-icon">
|
<a href={"/reserves"} class="has-icon">
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
@ -150,16 +164,6 @@ export function Sidebar({
|
|||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{needKYC && (
|
|
||||||
<li>
|
|
||||||
<a href={"/kyc"} class="has-icon">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="mdi mdi-account-check" />
|
|
||||||
</span>
|
|
||||||
<span class="menu-item-label">KYC Status</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
)}
|
|
||||||
</ul>
|
</ul>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : undefined}
|
) : undefined}
|
||||||
@ -167,6 +171,18 @@ export function Sidebar({
|
|||||||
<i18n.Translate>Connection</i18n.Translate>
|
<i18n.Translate>Connection</i18n.Translate>
|
||||||
</p>
|
</p>
|
||||||
<ul class="menu-list">
|
<ul class="menu-list">
|
||||||
|
<li>
|
||||||
|
<a class="has-icon is-state-info is-hoverable"
|
||||||
|
onClick={(): void => onShowSettings()}
|
||||||
|
>
|
||||||
|
<span class="icon">
|
||||||
|
<i class="mdi mdi-newspaper" />
|
||||||
|
</span>
|
||||||
|
<span class="menu-item-label">
|
||||||
|
<i18n.Translate>Settings</i18n.Translate>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<div>
|
<div>
|
||||||
<span style={{ width: "3rem" }} class="icon">
|
<span style={{ width: "3rem" }} class="icon">
|
||||||
|
@ -75,6 +75,7 @@ interface MenuProps {
|
|||||||
instance: string;
|
instance: string;
|
||||||
admin?: boolean;
|
admin?: boolean;
|
||||||
onLogout?: () => void;
|
onLogout?: () => void;
|
||||||
|
onShowSettings: () => void;
|
||||||
setInstanceName: (s: string) => void;
|
setInstanceName: (s: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +94,7 @@ function WithTitle({
|
|||||||
|
|
||||||
export function Menu({
|
export function Menu({
|
||||||
onLogout,
|
onLogout,
|
||||||
|
onShowSettings,
|
||||||
title,
|
title,
|
||||||
instance,
|
instance,
|
||||||
path,
|
path,
|
||||||
@ -121,6 +123,7 @@ export function Menu({
|
|||||||
|
|
||||||
{onLogout && (
|
{onLogout && (
|
||||||
<Sidebar
|
<Sidebar
|
||||||
|
onShowSettings={onShowSettings}
|
||||||
onLogout={onLogout}
|
onLogout={onLogout}
|
||||||
admin={admin}
|
admin={admin}
|
||||||
mimic={mimic}
|
mimic={mimic}
|
||||||
@ -159,6 +162,7 @@ export function Menu({
|
|||||||
interface NotYetReadyAppMenuProps {
|
interface NotYetReadyAppMenuProps {
|
||||||
title: string;
|
title: string;
|
||||||
onLogout?: () => void;
|
onLogout?: () => void;
|
||||||
|
onShowSettings: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NotifProps {
|
interface NotifProps {
|
||||||
@ -199,6 +203,7 @@ export function NotificationCard({
|
|||||||
|
|
||||||
export function NotYetReadyAppMenu({
|
export function NotYetReadyAppMenu({
|
||||||
onLogout,
|
onLogout,
|
||||||
|
onShowSettings,
|
||||||
title,
|
title,
|
||||||
}: NotYetReadyAppMenuProps): VNode {
|
}: NotYetReadyAppMenuProps): VNode {
|
||||||
const [mobileOpen, setMobileOpen] = useState(false);
|
const [mobileOpen, setMobileOpen] = useState(false);
|
||||||
@ -217,7 +222,7 @@ export function NotYetReadyAppMenu({
|
|||||||
title={title}
|
title={title}
|
||||||
/>
|
/>
|
||||||
{onLogout && (
|
{onLogout && (
|
||||||
<Sidebar onLogout={onLogout} instance="" mobile={mobileOpen} />
|
<Sidebar onShowSettings={onShowSettings} onLogout={onLogout} instance="" mobile={mobileOpen} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -164,7 +164,7 @@ export function ListPage({
|
|||||||
<div class="field has-addons">
|
<div class="field has-addons">
|
||||||
{jumpToDate && (
|
{jumpToDate && (
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a class="button" onClick={() => onSelectDate(undefined)}>
|
<a class="button is-fullwidth" onClick={() => onSelectDate(undefined)}>
|
||||||
<span
|
<span
|
||||||
class="icon"
|
class="icon"
|
||||||
data-tooltip={i18n.str`clear date filter`}
|
data-tooltip={i18n.str`clear date filter`}
|
||||||
@ -191,7 +191,7 @@ export function ListPage({
|
|||||||
<div class="control">
|
<div class="control">
|
||||||
<span class="has-tooltip-left" data-tooltip={dateTooltip}>
|
<span class="has-tooltip-left" data-tooltip={dateTooltip}>
|
||||||
<a
|
<a
|
||||||
class="button"
|
class="button is-fullwidth"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPickDate(true);
|
setPickDate(true);
|
||||||
}}
|
}}
|
||||||
|
@ -85,34 +85,34 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
|
|||||||
template_contract: !state.template_contract
|
template_contract: !state.template_contract
|
||||||
? undefined
|
? undefined
|
||||||
: undefinedIfEmpty({
|
: undefinedIfEmpty({
|
||||||
amount: !state.template_contract?.amount
|
amount: !state.template_contract?.amount
|
||||||
? undefined
|
? undefined
|
||||||
: !parsedPrice
|
: !parsedPrice
|
||||||
? i18n.str`not valid`
|
? i18n.str`not valid`
|
||||||
: Amounts.isZero(parsedPrice)
|
: Amounts.isZero(parsedPrice)
|
||||||
? i18n.str`must be greater than 0`
|
? i18n.str`must be greater than 0`
|
||||||
: undefined,
|
|
||||||
minimum_age:
|
|
||||||
state.template_contract.minimum_age < 0
|
|
||||||
? i18n.str`should be greater that 0`
|
|
||||||
: undefined,
|
: undefined,
|
||||||
pay_duration: !state.template_contract.pay_duration
|
minimum_age:
|
||||||
? i18n.str`can't be empty`
|
state.template_contract.minimum_age < 0
|
||||||
: state.template_contract.pay_duration.d_us === "forever"
|
? i18n.str`should be greater that 0`
|
||||||
|
: undefined,
|
||||||
|
pay_duration: !state.template_contract.pay_duration
|
||||||
|
? i18n.str`can't be empty`
|
||||||
|
: state.template_contract.pay_duration.d_us === "forever"
|
||||||
? undefined
|
? undefined
|
||||||
: state.template_contract.pay_duration.d_us < 1000 * 1000 //less than one second
|
: state.template_contract.pay_duration.d_us < 1000 * 1000 //less than one second
|
||||||
? i18n.str`to short`
|
? i18n.str`to short`
|
||||||
: undefined,
|
: undefined,
|
||||||
} as Partial<MerchantTemplateContractDetails>),
|
} as Partial<MerchantTemplateContractDetails>),
|
||||||
pos_key: !state.pos_key
|
pos_key: !state.pos_key
|
||||||
? !state.pos_algorithm
|
? !state.pos_algorithm
|
||||||
? undefined
|
? undefined
|
||||||
: i18n.str`required`
|
: i18n.str`required`
|
||||||
: !isBase32RFC3548Charset(state.pos_key)
|
: !isBase32RFC3548Charset(state.pos_key)
|
||||||
? i18n.str`just letters and numbers from 2 to 7`
|
? i18n.str`just letters and numbers from 2 to 7`
|
||||||
: state.pos_key.length !== 32
|
: state.pos_key.length !== 32
|
||||||
? i18n.str`size of the key should be 32`
|
? i18n.str`size of the key should be 32`
|
||||||
: undefined,
|
: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const hasErrors = Object.keys(errors).some(
|
const hasErrors = Object.keys(errors).some(
|
||||||
@ -139,7 +139,7 @@ export function CreatePage({ onCreate, onBack }: Props): VNode {
|
|||||||
>
|
>
|
||||||
<InputWithAddon<Entity>
|
<InputWithAddon<Entity>
|
||||||
name="template_id"
|
name="template_id"
|
||||||
addonBefore={`${backend.url}/instances/templates/`}
|
help={`${backend.url}/instances/templates/${state.template_id ?? ""}`}
|
||||||
label={i18n.str`Identifier`}
|
label={i18n.str`Identifier`}
|
||||||
tooltip={i18n.str`Name of the template in URLs.`}
|
tooltip={i18n.str`Name of the template in URLs.`}
|
||||||
/>
|
/>
|
||||||
|
15
packages/merchant-backoffice-ui/src/paths/settings/index.tsx
Normal file
15
packages/merchant-backoffice-ui/src/paths/settings/index.tsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { VNode, h } from "preact";
|
||||||
|
|
||||||
|
export function Settings(): VNode {
|
||||||
|
return <div>
|
||||||
|
<section class="section is-main-section">
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column" />
|
||||||
|
<div class="column is-four-fifths">
|
||||||
|
settings view
|
||||||
|
</div>
|
||||||
|
<div class="column" />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user