mirror of
https://github.com/haveno-dex/haveno-ui.git
synced 2024-10-01 07:35:39 -04:00
chore: Account Settings screen
--- Reviewed-by: schowdhuri
This commit is contained in:
parent
d8dd987ccf
commit
7bcf36d595
@ -14,9 +14,6 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { RecoilRoot } from "recoil";
|
||||
import { HashRouter } from "react-router-dom";
|
||||
import { QueryClient, QueryClientProvider } from "react-query";
|
||||
import { AppProviders } from "@atoms/AppProviders";
|
||||
|
||||
export const parameters = {
|
||||
@ -29,10 +26,4 @@ export const parameters = {
|
||||
},
|
||||
};
|
||||
|
||||
export const decorators = [
|
||||
(Story) => (
|
||||
<HashRouter>
|
||||
<AppProviders>{Story()}</AppProviders>
|
||||
</HashRouter>
|
||||
),
|
||||
];
|
||||
export const decorators = [(Story) => <AppProviders>{Story()}</AppProviders>];
|
||||
|
1
packages/renderer/assets/setting-cloud.svg
Normal file
1
packages/renderer/assets/setting-cloud.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg fill="currentColor" width="58px" height="54px" viewBox="0 0 58 54" fill="none" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" clip-rule="evenodd" d="M43.8339 7.56984C41.5907 3.08354 36.9294 0 31.5427 0C25.2052 0 19.8717 4.2683 18.299 10.0676C17.5276 9.7233 16.672 9.53174 15.7714 9.53174C12.8205 9.53174 10.3534 11.588 9.74421 14.3362C9.47095 14.3111 9.19411 14.2983 8.91425 14.2983C3.99105 14.2983 0 18.2611 0 23.1493C0 28.0376 3.99105 32.0003 8.91425 32.0003C8.95701 32.0003 8.99969 32 9.0423 31.9994H45.1782L45.257 31.9996C52.0737 31.9996 57.5998 26.5128 57.5998 19.7444C57.5998 12.9761 52.0737 7.48926 45.257 7.48926C44.7757 7.48926 44.3008 7.51661 43.8339 7.56984Z" fill="currentColor"/> <path d="M26.2105 43.7896L22.1053 40.0001L18 43.7896" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> <path d="M22.1052 52.316V40.2739" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> <path d="M39.4713 48.8423L35.366 52.6318L31.2607 48.8423" stroke="currentColor" stroke-width="2" stroke-linecap="round"/> <path d="M35.366 40.3158V52.3579" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg>
|
After Width: | Height: | Size: 1.1 KiB |
5
packages/renderer/assets/setting-server.svg
Normal file
5
packages/renderer/assets/setting-server.svg
Normal file
@ -0,0 +1,5 @@
|
||||
<svg version="1.2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 62" width="32" height="62">
|
||||
<title>server</title>
|
||||
<path id="Layer" fill-rule="evenodd" fill="currentColor" d="m31.6 25.8v34.5c0 1-0.9 1.7-2 1.7h-27.6c-1.2 0-2-0.7-2-1.7v-34.5c0-1 0.8-1.7 2-1.7h27.6c1.1 0 2 0.7 2 1.7zm-6.9 8.8c0.6 0 1-0.3 1-0.8v-4.1c0-0.5-0.4-0.8-1-0.8h-17.8c-0.6 0-1 0.3-1 0.8v4.1c0 0.5 0.4 0.8 1 0.8zm1 4c0-0.5-0.4-0.8-1-0.8h-17.8c-0.5 0-0.9 0.3-0.9 0.8v4c0 0.5 0.4 0.9 0.9 0.9h17.8c0.6 0 1-0.4 1-0.9zm-11.8 10.2c0 1.1 0.8 2 1.9 2 1.1 0 2-0.9 2-2 0-1.1-0.9-1.9-2-1.9-1.1 0-1.9 0.8-1.9 1.9zm0 6.9c0 1.1 0.8 2 1.9 2 1.1 0 2-0.9 2-2 0-1.1-0.9-2-2-2-1.1 0-1.9 0.9-1.9 2z"/>
|
||||
<path id="Layer" stroke="currentColor" stroke-linecap="round" stroke-width="2" d="m5.4 5.8l4.1-3.8 4.1 3.8m-4.1 8.5v-12m17.3 8.5l-4.1 3.8-4.1-3.8m4.1-8.5v12.1"/>
|
||||
</svg>
|
After Width: | Height: | Size: 830 B |
@ -18,7 +18,7 @@ import { Routes, Route } from "react-router-dom";
|
||||
import { Home, Welcome } from "@pages/Onboarding";
|
||||
import { Wallet } from "@pages/Wallet";
|
||||
import { AccountPaymentAccounts } from "@pages/Account/AccountPaymentAccounts";
|
||||
import { AccountNodeSettings } from "@pages/Account/AccountNodeSettings";
|
||||
import { AccountNodeSettings } from "@pages/Account/NodeSettings";
|
||||
import { AccountBackup } from "@pages/Account/AccountBackup";
|
||||
import { AccountWallet } from "@pages/Account/AccountWallet";
|
||||
import { AccountSecurity } from "@pages/Account/Security";
|
||||
|
@ -0,0 +1,52 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import type { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
import { NodeConnectSwitch } from ".";
|
||||
import { ReactComponent as CloudIcon } from "@assets/setting-cloud.svg";
|
||||
import { ReactComponent as ServerIcon } from "@assets/setting-server.svg";
|
||||
|
||||
export default {
|
||||
title: "atoms/NodeConnectSwitch",
|
||||
component: NodeConnectSwitch,
|
||||
} as ComponentMeta<typeof NodeConnectSwitch>;
|
||||
|
||||
const Template: ComponentStory<typeof NodeConnectSwitch> = () => {
|
||||
return (
|
||||
<NodeConnectSwitch>
|
||||
<NodeConnectSwitch.Method
|
||||
active={true}
|
||||
current={true}
|
||||
tabKey={"local-node"}
|
||||
label="Local Node"
|
||||
icon={<ServerIcon width="32px" height="62px" />}
|
||||
>
|
||||
Local Node
|
||||
</NodeConnectSwitch.Method>
|
||||
|
||||
<NodeConnectSwitch.Method
|
||||
tabKey={"remote-node"}
|
||||
label="Remote Node"
|
||||
icon={<CloudIcon width="58px" height="54px" />}
|
||||
>
|
||||
Remote Node
|
||||
</NodeConnectSwitch.Method>
|
||||
</NodeConnectSwitch>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
@ -0,0 +1,102 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { createStyles } from "@mantine/core";
|
||||
|
||||
export const useTabsStyles = createStyles<string, void>(() => {
|
||||
return {
|
||||
root: {},
|
||||
tabsListWrapper: {
|
||||
display: "flex",
|
||||
},
|
||||
body: {
|
||||
marginTop: "2.5rem",
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const useControlStyles = createStyles<
|
||||
string,
|
||||
{ active: boolean; current: boolean }
|
||||
>((theme, { active }, getRef) => {
|
||||
const tabActive = { ref: getRef("tabActive") };
|
||||
|
||||
return {
|
||||
tabControl: {
|
||||
backgroundColor:
|
||||
theme.colorScheme === "dark" ? theme.colors.dark[6] : theme.white,
|
||||
color:
|
||||
theme.colorScheme === "dark"
|
||||
? theme.colors.dark[0]
|
||||
: theme.colors.gray[9],
|
||||
border: `2px solid ${
|
||||
theme.colorScheme === "dark"
|
||||
? theme.colors.dark[6]
|
||||
: theme.colors.gray[2]
|
||||
}`,
|
||||
fontSize: theme.fontSizes.md,
|
||||
padding: `${theme.spacing.lg}px ${theme.spacing.xl}px`,
|
||||
borderRadius: theme.radius.lg,
|
||||
height: "8.45rem",
|
||||
width: "13.85rem",
|
||||
|
||||
"&:not(:first-of-type)": {
|
||||
marginLeft: theme.spacing.xl,
|
||||
},
|
||||
[`&.${tabActive.ref}`]: {
|
||||
color: theme.colorScheme === "dark" ? theme.black : theme.white,
|
||||
},
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
},
|
||||
tabIcon: {
|
||||
fill: "currentColor",
|
||||
minHeight: "3.8rem",
|
||||
display: "flex",
|
||||
|
||||
svg: {
|
||||
margin: "auto",
|
||||
},
|
||||
},
|
||||
tabInner: {
|
||||
flexDirection: "column",
|
||||
},
|
||||
tabLabel: {
|
||||
fontWeight: 600,
|
||||
fontSize: theme.fontSizes.md,
|
||||
marginTop: "1rem",
|
||||
},
|
||||
tabActive: {
|
||||
backgroundColor: theme.colors.blue[6],
|
||||
borderColor: theme.colors.blue[6],
|
||||
color: theme.white,
|
||||
},
|
||||
tabCurrent: {
|
||||
display: "inline-block",
|
||||
position: "absolute",
|
||||
fontSize: theme.fontSizes.xs,
|
||||
lineHeight: 1,
|
||||
padding: "0.38rem 1.15rem",
|
||||
borderRadius: theme.radius.sm,
|
||||
top: "0.6rem",
|
||||
left: "0.7rem",
|
||||
background: active
|
||||
? theme.fn.rgba(theme.white, 0.15)
|
||||
: theme.fn.rgba(theme.colors.blue[5], 0.15),
|
||||
color: active ? theme.white : theme.black,
|
||||
},
|
||||
};
|
||||
});
|
@ -0,0 +1,53 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { render } from "@testing-library/react";
|
||||
import { AppProviders } from "@atoms/AppProviders";
|
||||
import { ReactComponent as CloudIcon } from "@assets/setting-cloud.svg";
|
||||
import { ReactComponent as ServerIcon } from "@assets/setting-server.svg";
|
||||
import { NodeConnectSwitch } from ".";
|
||||
|
||||
describe("atoms::NodeConnectSwitch", () => {
|
||||
it("renders without exploding", () => {
|
||||
const { asFragment } = render(
|
||||
<AppProviders>
|
||||
<NodeConnectSwitch>
|
||||
<NodeConnectSwitch.Method
|
||||
active={true}
|
||||
current={true}
|
||||
tabKey={"local-node"}
|
||||
label="Local Node"
|
||||
icon={<ServerIcon width="32px" height="62px" />}
|
||||
>
|
||||
Local Node
|
||||
</NodeConnectSwitch.Method>
|
||||
|
||||
<NodeConnectSwitch.Method
|
||||
tabKey={"remote-node"}
|
||||
label="Remote Node"
|
||||
icon={<CloudIcon width="58px" height="54px" />}
|
||||
active={false}
|
||||
current={false}
|
||||
>
|
||||
Remote Node
|
||||
</NodeConnectSwitch.Method>
|
||||
</NodeConnectSwitch>
|
||||
</AppProviders>
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,87 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import type { ReactElement, ReactNode } from "react";
|
||||
import { cloneElement, Children } from "react";
|
||||
import { Box } from "@mantine/core";
|
||||
import { useUncontrolled } from "@mantine/hooks";
|
||||
import { NodeConnectSwitchMethod } from "./NodeConnectSwitchMethod";
|
||||
import { useTabsStyles } from "./NodeConnectSwitch.style";
|
||||
|
||||
interface NodeConnectSwitchProps {
|
||||
/** <Tab /> components only */
|
||||
children?: ReactNode;
|
||||
|
||||
/** Key of active tab */
|
||||
active?: string;
|
||||
|
||||
/** Key of current tab */
|
||||
current?: boolean;
|
||||
|
||||
/** Called when tab control is clicked with tab index */
|
||||
onTabChange?(tabKey: string): void;
|
||||
|
||||
/** Key of initial tab */
|
||||
initialTab?: string;
|
||||
|
||||
/** Extra class name */
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function NodeConnectSwitch({
|
||||
className,
|
||||
onTabChange,
|
||||
active,
|
||||
children,
|
||||
initialTab,
|
||||
}: NodeConnectSwitchProps) {
|
||||
const { classes, cx } = useTabsStyles();
|
||||
|
||||
const tabs = Children.toArray(children) as Array<ReactElement>;
|
||||
|
||||
const [_activeTab, handleActiveTabChange] = useUncontrolled({
|
||||
value: active,
|
||||
defaultValue: initialTab,
|
||||
finalValue: "",
|
||||
rule: (value) => typeof value === "string",
|
||||
onChange: (tabKey: string) => {
|
||||
onTabChange && onTabChange(tabKey);
|
||||
},
|
||||
});
|
||||
|
||||
const panes = tabs.map((tab, index) =>
|
||||
cloneElement(tab, {
|
||||
key: index,
|
||||
active: _activeTab === tab.props.tabKey,
|
||||
onClick: () => handleActiveTabChange(tab.props.tabKey),
|
||||
})
|
||||
);
|
||||
const content = tabs.find((tab) => tab.props.tabKey === _activeTab);
|
||||
|
||||
return (
|
||||
<Box className={cx(classes.root, className)}>
|
||||
<div className={cx(classes.tabsListWrapper)}>{panes} </div>
|
||||
|
||||
{content && (
|
||||
<div role="tabpanel" className={classes.body} key={_activeTab}>
|
||||
{content.props.children}
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
NodeConnectSwitch.Method = NodeConnectSwitchMethod;
|
@ -0,0 +1,74 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { Box } from "@mantine/core";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { useControlStyles } from "./NodeConnectSwitch.style";
|
||||
|
||||
interface SettingTabProps {
|
||||
active?: boolean;
|
||||
current?: boolean;
|
||||
className?: string;
|
||||
icon?: React.ReactNode;
|
||||
label: string | React.ReactNode;
|
||||
tabKey: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function NodeConnectSwitchMethod({
|
||||
active,
|
||||
current,
|
||||
label,
|
||||
icon,
|
||||
className,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
tabKey,
|
||||
...rest
|
||||
}: SettingTabProps) {
|
||||
const { classes, cx } = useControlStyles({
|
||||
active: active || false,
|
||||
current: current || false,
|
||||
});
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="button"
|
||||
tabIndex={active ? 0 : -1}
|
||||
className={cx(
|
||||
classes.tabControl,
|
||||
{ [classes.tabActive]: active },
|
||||
className
|
||||
)}
|
||||
type="button"
|
||||
role="tab"
|
||||
{...rest}
|
||||
>
|
||||
<Box className={classes.tabInner}>
|
||||
{current && (
|
||||
<Box className={cx(classes.tabCurrent)}>
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountSettingsCurrent}
|
||||
defaultMessage={"Current"}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
{icon && <Box className={classes.tabIcon}>{icon}</Box>}
|
||||
{label && <Box className={classes.tabLabel}>{label}</Box>}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
@ -0,0 +1,121 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`atoms::NodeConnectSwitch > renders without exploding 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mantine-15po0m8"
|
||||
>
|
||||
<div
|
||||
class="mantine-17do188"
|
||||
>
|
||||
<button
|
||||
class="mantine-1lhe3fe"
|
||||
role="tab"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="mantine-199rwtt"
|
||||
>
|
||||
<div
|
||||
class="mantine-1jn9p7a"
|
||||
>
|
||||
Current
|
||||
</div>
|
||||
<div
|
||||
class="mantine-9bd5vi"
|
||||
>
|
||||
<svg
|
||||
height="62px"
|
||||
viewBox="0 0 32 62"
|
||||
width="32px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<title>
|
||||
server
|
||||
</title>
|
||||
<path
|
||||
d="m31.6 25.8v34.5c0 1-0.9 1.7-2 1.7h-27.6c-1.2 0-2-0.7-2-1.7v-34.5c0-1 0.8-1.7 2-1.7h27.6c1.1 0 2 0.7 2 1.7zm-6.9 8.8c0.6 0 1-0.3 1-0.8v-4.1c0-0.5-0.4-0.8-1-0.8h-17.8c-0.6 0-1 0.3-1 0.8v4.1c0 0.5 0.4 0.8 1 0.8zm1 4c0-0.5-0.4-0.8-1-0.8h-17.8c-0.5 0-0.9 0.3-0.9 0.8v4c0 0.5 0.4 0.9 0.9 0.9h17.8c0.6 0 1-0.4 1-0.9zm-11.8 10.2c0 1.1 0.8 2 1.9 2 1.1 0 2-0.9 2-2 0-1.1-0.9-1.9-2-1.9-1.1 0-1.9 0.8-1.9 1.9zm0 6.9c0 1.1 0.8 2 1.9 2 1.1 0 2-0.9 2-2 0-1.1-0.9-2-2-2-1.1 0-1.9 0.9-1.9 2z"
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
id="Layer"
|
||||
/>
|
||||
<path
|
||||
d="m5.4 5.8l4.1-3.8 4.1 3.8m-4.1 8.5v-12m17.3 8.5l-4.1 3.8-4.1-3.8m4.1-8.5v12.1"
|
||||
id="Layer"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-1wlt8yk"
|
||||
>
|
||||
Local Node
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
class="mantine-1lhe3fe"
|
||||
role="tab"
|
||||
tabindex="-1"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
class="mantine-199rwtt"
|
||||
>
|
||||
<div
|
||||
class="mantine-9bd5vi"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="54px"
|
||||
viewBox="0 0 58 54"
|
||||
width="58px"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M43.8339 7.56984C41.5907 3.08354 36.9294 0 31.5427 0C25.2052 0 19.8717 4.2683 18.299 10.0676C17.5276 9.7233 16.672 9.53174 15.7714 9.53174C12.8205 9.53174 10.3534 11.588 9.74421 14.3362C9.47095 14.3111 9.19411 14.2983 8.91425 14.2983C3.99105 14.2983 0 18.2611 0 23.1493C0 28.0376 3.99105 32.0003 8.91425 32.0003C8.95701 32.0003 8.99969 32 9.0423 31.9994H45.1782L45.257 31.9996C52.0737 31.9996 57.5998 26.5128 57.5998 19.7444C57.5998 12.9761 52.0737 7.48926 45.257 7.48926C44.7757 7.48926 44.3008 7.51661 43.8339 7.56984Z"
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M26.2105 43.7896L22.1053 40.0001L18 43.7896"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<path
|
||||
d="M22.1052 52.316V40.2739"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<path
|
||||
d="M39.4713 48.8423L35.366 52.6318L31.2607 48.8423"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<path
|
||||
d="M35.366 40.3158V52.3579"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-width="2"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-1wlt8yk"
|
||||
>
|
||||
Remote Node
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
@ -14,12 +14,4 @@
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { AccountLayout } from "@templates/AccountLayout";
|
||||
|
||||
export function AccountNodeSettings() {
|
||||
return (
|
||||
<AccountLayout>
|
||||
<h1>Account Node Settings</h1>
|
||||
</AccountLayout>
|
||||
);
|
||||
}
|
||||
export * from "./NodeConnectSwitch";
|
@ -0,0 +1,46 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Stack } from "@mantine/core";
|
||||
import type { ComponentStory, ComponentMeta } from "@storybook/react";
|
||||
import { NodeStatus, NodeStatusType } from ".";
|
||||
|
||||
export default {
|
||||
title: "atoms/NodeStatus",
|
||||
component: NodeStatus,
|
||||
} as ComponentMeta<typeof NodeStatus>;
|
||||
|
||||
const Template: ComponentStory<typeof NodeStatus> = () => {
|
||||
return (
|
||||
<Stack>
|
||||
<NodeStatus
|
||||
title={"node.moneroworldcom:18089"}
|
||||
status={NodeStatusType.Active}
|
||||
/>
|
||||
<NodeStatus
|
||||
title={"node.xmr.pt:18081"}
|
||||
status={NodeStatusType.Inactive}
|
||||
/>
|
||||
<NodeStatus
|
||||
title={"node.monero.net:18081"}
|
||||
status={NodeStatusType.Active}
|
||||
/>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
@ -0,0 +1,38 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { render } from "@testing-library/react";
|
||||
import { AppProviders } from "@atoms/AppProviders";
|
||||
import { NodeStatus, NodeStatusType } from "./NodeStatus";
|
||||
|
||||
describe("atoms::NodeStatus", () => {
|
||||
it("renders without exploding", () => {
|
||||
const { asFragment } = render(
|
||||
<AppProviders>
|
||||
<NodeStatus
|
||||
title={"node.moneroworldcom:18089:active"}
|
||||
status={NodeStatusType.Active}
|
||||
/>
|
||||
<NodeStatus
|
||||
title={"node.moneroworldcom:18089:inactive"}
|
||||
status={NodeStatusType.Inactive}
|
||||
/>
|
||||
</AppProviders>
|
||||
);
|
||||
expect(asFragment()).toMatchSnapshot();
|
||||
});
|
||||
});
|
@ -0,0 +1,77 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Box, createStyles, Text } from "@mantine/core";
|
||||
|
||||
export enum NodeStatusType {
|
||||
Active = "active",
|
||||
Inactive = "inactive",
|
||||
}
|
||||
export interface NodeStatusProps {
|
||||
/** Node title */
|
||||
title: string;
|
||||
|
||||
/** Node status */
|
||||
status: NodeStatusType;
|
||||
}
|
||||
|
||||
export function NodeStatus({ title, status }: NodeStatusProps) {
|
||||
const { classes } = useStyles({ status });
|
||||
|
||||
return (
|
||||
<Box className={classes.root}>
|
||||
<Text className={classes.title}>{title}</Text>
|
||||
<div className={classes.status}>
|
||||
<div className={classes.statusInner} />
|
||||
</div>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export const useStyles = createStyles<string, { status: NodeStatusType }>(
|
||||
(theme, { status }) => {
|
||||
return {
|
||||
root: {
|
||||
backgroundColor:
|
||||
theme.colorScheme === "dark" ? theme.colors.dark[8] : theme.white,
|
||||
border: `1px solid ${theme.colors.gray[2]}`,
|
||||
borderRadius: theme.radius.md,
|
||||
padding: "0.91rem",
|
||||
display: "flex",
|
||||
transition: "background-color 0.1s ease-in-out",
|
||||
},
|
||||
title: {
|
||||
fontWeight: 600,
|
||||
fontSize: theme.fontSizes.sm,
|
||||
lineHeight: 1,
|
||||
width: "100%",
|
||||
},
|
||||
status: {
|
||||
display: "flex",
|
||||
},
|
||||
statusInner: {
|
||||
height: "0.625rem",
|
||||
width: "0.625rem",
|
||||
borderRadius: "0.625rem",
|
||||
background:
|
||||
status === NodeStatusType.Active
|
||||
? theme.colors.green[4]
|
||||
: theme.colors.gray[4],
|
||||
margin: "auto",
|
||||
},
|
||||
};
|
||||
}
|
||||
);
|
@ -0,0 +1,38 @@
|
||||
// Vitest Snapshot v1
|
||||
|
||||
exports[`atoms::NodeStatus > renders without exploding 1`] = `
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="mantine-18xx7au"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-14byb36"
|
||||
>
|
||||
node.moneroworldcom:18089:active
|
||||
</div>
|
||||
<div
|
||||
class="mantine-17do188"
|
||||
>
|
||||
<div
|
||||
class="mantine-167633s"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="mantine-18xx7au"
|
||||
>
|
||||
<div
|
||||
class="mantine-Text-root mantine-14byb36"
|
||||
>
|
||||
node.moneroworldcom:18089:inactive
|
||||
</div>
|
||||
<div
|
||||
class="mantine-17do188"
|
||||
>
|
||||
<div
|
||||
class="mantine-1cipvbv"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`;
|
17
packages/renderer/src/components/atoms/NodeStatus/index.tsx
Normal file
17
packages/renderer/src/components/atoms/NodeStatus/index.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
export * from "./NodeStatus";
|
@ -29,6 +29,17 @@ export enum LangKeys {
|
||||
AccountSidebarNodeSettings = "account.sidebar.nodeSettings",
|
||||
AccountSecurityTitle = "account.security.title",
|
||||
AccountSecurityDesc = "account.security.desc",
|
||||
AccountNodeSettingsTitle = "account.nodeSecurity.title",
|
||||
AccountNodeSettingsDesc = "account.nodeSecurity.desc",
|
||||
AccountNodeSettingsLocal = "account.nodeSecurity.local.title",
|
||||
AccountNodeSettingsRemote = "account.nodeSecurity.remote.title",
|
||||
AccountNodeFieldBlockchainLocation = "account.nodeSecurity.blockchainLocation",
|
||||
AccountNodeFieldDeamonAddress = "account.nodeSecurity.deamonAddress",
|
||||
AccountNodeFieldDeamonFlags = "account.nodeSecurity.deamonFlags",
|
||||
AccountNodeFieldPort = "account.nodeSecurity.port",
|
||||
AccountNodeStopDeamon = "account.nodeSecurity.stopDeamon",
|
||||
AccountSettingsAddNode = "account.settings.addNewNode",
|
||||
AccountSettingsCurrent = "account.settings.current",
|
||||
AccountSecurityFieldPassword = "account.security.field.password",
|
||||
AccountSecurityFieldRepeatPassword = "account.security.field.repeatPassword",
|
||||
AccountSecurityFieldCurrentPassword = "account.security.field.currentPassword",
|
||||
|
@ -33,6 +33,18 @@ const LangPackEN: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AccountSecurityTitle]: "Account Security",
|
||||
[LangKeys.AccountSecurityDesc]:
|
||||
"Haveno does not store any of your data, this happens solely locally on your device. It’s not possible to restore your password when lost. Please make sure you store a copy of it on a safe place.",
|
||||
[LangKeys.AccountNodeSettingsDesc]:
|
||||
"Using a local node is recommended, but does require loading the entire blockchain. Choose ‘remote node’ if you prefer a faster but less secure experience.",
|
||||
[LangKeys.AccountNodeSettingsTitle]: "Your node settings",
|
||||
[LangKeys.AccountNodeSettingsLocal]: "Local Node",
|
||||
[LangKeys.AccountNodeSettingsRemote]: "Remote Node",
|
||||
[LangKeys.AccountNodeFieldBlockchainLocation]: "Blockchain location",
|
||||
[LangKeys.AccountNodeFieldDeamonAddress]: "Deamon Address",
|
||||
[LangKeys.AccountNodeFieldPort]: "Port",
|
||||
[LangKeys.AccountNodeFieldDeamonFlags]: "Deamon startup flags",
|
||||
[LangKeys.AccountNodeStopDeamon]: "Stop deamon",
|
||||
[LangKeys.AccountSettingsAddNode]: "Add a new node",
|
||||
[LangKeys.AccountSettingsCurrent]: "Current",
|
||||
[LangKeys.AccountSecurityFieldPassword]: "Password",
|
||||
[LangKeys.AccountSecurityFieldRepeatPassword]: "Repeat new password",
|
||||
[LangKeys.AccountSecurityFieldCurrentPassword]: "Current password",
|
||||
|
@ -33,6 +33,19 @@ const LangPackES: { [key in LangKeys]: string } = {
|
||||
[LangKeys.AccountSecurityTitle]: "Seguridad de la cuenta",
|
||||
[LangKeys.AccountSecurityDesc]:
|
||||
"Haveno no almacena ninguno de sus datos, esto ocurre únicamente localmente en su dispositivo. No es posible restaurar su contraseña cuando se pierde. Asegúrese de guardar una copia en un lugar seguro.",
|
||||
[LangKeys.AccountNodeSettingsDesc]:
|
||||
"Se recomienda usar un nodo local, pero requiere cargar toda la cadena de bloques. Elija 'nodo remoto' si prefiere una experiencia más rápida pero menos segura.",
|
||||
[LangKeys.AccountNodeSettingsTitle]: "La configuración de tu nodo",
|
||||
[LangKeys.AccountNodeSettingsLocal]: "Nodo Local",
|
||||
[LangKeys.AccountNodeSettingsRemote]: "Nodo Remoto",
|
||||
[LangKeys.AccountNodeFieldBlockchainLocation]:
|
||||
"Ubicación de cadena de bloques",
|
||||
[LangKeys.AccountNodeFieldDeamonAddress]: "Dirección del demonio",
|
||||
[LangKeys.AccountNodeFieldPort]: "Puerto",
|
||||
[LangKeys.AccountNodeFieldDeamonFlags]: "Indicadores de inicio de daemon",
|
||||
[LangKeys.AccountNodeStopDeamon]: "Detener demonio",
|
||||
[LangKeys.AccountSettingsAddNode]: "Agregar un nuevo nodo",
|
||||
[LangKeys.AccountSettingsCurrent]: "Actual",
|
||||
[LangKeys.AccountSecurityFieldPassword]: "Clave",
|
||||
[LangKeys.AccountSecurityFieldRepeatPassword]: "Repita la nueva contraseña",
|
||||
[LangKeys.AccountSecurityFieldCurrentPassword]: "Contraseña actual",
|
||||
|
@ -0,0 +1,111 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Box, Stack, Grid, createStyles } from "@mantine/core";
|
||||
import { useForm } from "@mantine/form";
|
||||
import { Button } from "@atoms/Buttons";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { TextInput } from "@atoms/TextInput";
|
||||
|
||||
export function NodeLocalForm() {
|
||||
const form = useForm({
|
||||
initialValues: {
|
||||
blockchainLocation: "",
|
||||
startupFlags: "",
|
||||
deamonAddress: "",
|
||||
port: "",
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<NodeLocalStopDeamon />
|
||||
|
||||
<form onSubmit={form.onSubmit((values) => console.log(values))}>
|
||||
<Stack spacing={"lg"}>
|
||||
<TextInput
|
||||
id={"blockchainLocation"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeFieldBlockchainLocation}
|
||||
defaultMessage={"Blockchain location"}
|
||||
/>
|
||||
}
|
||||
{...form.getInputProps("blockchainLocation")}
|
||||
/>
|
||||
<TextInput
|
||||
id={"deamonFlags"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeFieldDeamonFlags}
|
||||
defaultMessage={"Deamon startup flags"}
|
||||
/>
|
||||
}
|
||||
{...form.getInputProps("startupFlags")}
|
||||
/>
|
||||
<Grid>
|
||||
<Grid.Col span={9}>
|
||||
<TextInput
|
||||
id={"deamonAddress"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeFieldDeamonAddress}
|
||||
defaultMessage={"Deamon Address"}
|
||||
/>
|
||||
}
|
||||
{...form.getInputProps("deamonAddress")}
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col span={3}>
|
||||
<TextInput
|
||||
id={"port"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeFieldPort}
|
||||
defaultMessage={"Port"}
|
||||
/>
|
||||
}
|
||||
{...form.getInputProps("port")}
|
||||
/>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
</Stack>
|
||||
</form>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function NodeLocalStopDeamon() {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<div className={classes.actions}>
|
||||
<Button flavor={"neutral"}>
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeStopDeamon}
|
||||
defaultMessage={"Stop deamon"}
|
||||
/>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
actions: {
|
||||
marginBottom: theme.spacing.xl,
|
||||
},
|
||||
}));
|
@ -0,0 +1,79 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Stack, createStyles, Group } from "@mantine/core";
|
||||
import { Button } from "@atoms/Buttons";
|
||||
import { NodeStatus, NodeStatusType } from "@atoms/NodeStatus";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
|
||||
export function NodeRemoteStatus() {
|
||||
return (
|
||||
<Stack>
|
||||
<NodeStatus
|
||||
title={"node.moneroworldcom:18089"}
|
||||
status={NodeStatusType.Active}
|
||||
/>
|
||||
<NodeStatus
|
||||
title={"node.xmr.pt:18081"}
|
||||
status={NodeStatusType.Inactive}
|
||||
/>
|
||||
<NodeStatus
|
||||
title={"node.monero.net:18081"}
|
||||
status={NodeStatusType.Active}
|
||||
/>
|
||||
<AddNewNodeButton />
|
||||
|
||||
<Group position={"right"} mt={"sm"}>
|
||||
<Button size={"md"}>
|
||||
<FormattedMessage id={LangKeys.Save} defaultMessage={"Save"} />
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function AddNewNodeButton({ ...rest }) {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant={"subtle"}
|
||||
color={"dark"}
|
||||
classNames={{
|
||||
root: classes.root,
|
||||
inner: classes.inner,
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
+{" "}
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountSettingsAddNode}
|
||||
defaultMessage={"Add a new node"}
|
||||
/>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles(() => ({
|
||||
root: {
|
||||
padding: "0.8rem",
|
||||
height: 45,
|
||||
},
|
||||
inner: {
|
||||
justifyContent: "start",
|
||||
},
|
||||
}));
|
@ -0,0 +1,57 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { Stack, Box, createStyles } from "@mantine/core";
|
||||
import { AccountLayout } from "@templates/AccountLayout";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { NodeSettingsSwitch } from "./NodeSettingsSwitch";
|
||||
import { WIDTH } from "./_constants";
|
||||
import { BodyText, Heading } from "@atoms/Typography";
|
||||
|
||||
export function AccountNodeSettings() {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<AccountLayout>
|
||||
<Box className={classes.content}>
|
||||
<Stack spacing={"sm"}>
|
||||
<Heading stringId={LangKeys.AccountNodeSettingsTitle} order={3}>
|
||||
Your node settings
|
||||
</Heading>
|
||||
<BodyText
|
||||
stringId={LangKeys.AccountNodeSettingsDesc}
|
||||
size={"md"}
|
||||
className={classes.paragraph}
|
||||
>
|
||||
Using a local node is recommended, but does require loading the
|
||||
entire blockchain. Choose ‘remote node’ if you prefer a faster but
|
||||
less secure experience.
|
||||
</BodyText>
|
||||
<NodeSettingsSwitch />
|
||||
</Stack>
|
||||
</Box>
|
||||
</AccountLayout>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
content: {
|
||||
maxWidth: WIDTH,
|
||||
},
|
||||
paragraph: {
|
||||
marginBottom: theme.spacing.xl,
|
||||
},
|
||||
}));
|
@ -0,0 +1,69 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
import { createStyles } from "@mantine/core";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { LangKeys } from "@constants/lang";
|
||||
import { NodeConnectSwitch } from "@atoms/NodeConnectSwitch";
|
||||
import { ReactComponent as CloudIcon } from "@assets/setting-cloud.svg";
|
||||
import { ReactComponent as ServerIcon } from "@assets/setting-server.svg";
|
||||
import { NodeLocalForm } from "./NodeLocalForm";
|
||||
import { NodeRemoteStatus } from "./NodeRemoteStatus";
|
||||
|
||||
export function NodeSettingsSwitch() {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<NodeConnectSwitch
|
||||
initialTab={"local-node"}
|
||||
className={classes.connectSwitch}
|
||||
>
|
||||
<NodeConnectSwitch.Method
|
||||
active={true}
|
||||
current={true}
|
||||
tabKey={"local-node"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeSettingsLocal}
|
||||
defaultMessage={"Local Node"}
|
||||
/>
|
||||
}
|
||||
icon={<ServerIcon width={32} height={62} />}
|
||||
>
|
||||
<NodeLocalForm />
|
||||
</NodeConnectSwitch.Method>
|
||||
|
||||
<NodeConnectSwitch.Method
|
||||
tabKey={"remote-node"}
|
||||
label={
|
||||
<FormattedMessage
|
||||
id={LangKeys.AccountNodeSettingsRemote}
|
||||
defaultMessage={"Remote Node"}
|
||||
/>
|
||||
}
|
||||
icon={<CloudIcon width={58} height={54} />}
|
||||
>
|
||||
<NodeRemoteStatus />
|
||||
</NodeConnectSwitch.Method>
|
||||
</NodeConnectSwitch>
|
||||
);
|
||||
}
|
||||
|
||||
const useStyles = createStyles(() => ({
|
||||
connectSwitch: {
|
||||
marginBottom: "2rem",
|
||||
},
|
||||
}));
|
@ -0,0 +1,17 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
export const WIDTH = 470;
|
17
packages/renderer/src/pages/Account/NodeSettings/index.ts
Normal file
17
packages/renderer/src/pages/Account/NodeSettings/index.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// =============================================================================
|
||||
// Copyright 2022 Haveno
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
|
||||
export * from "./NodeSettings";
|
Loading…
Reference in New Issue
Block a user