Compare commits

...

14 Commits

Author SHA1 Message Date
muzam1l
04e2274dbf some refactoring 2022-04-06 14:42:39 +05:30
muzam1l
842b8a5226 Set debug stream default account from transaction account 2022-04-04 21:29:08 +05:30
Vaclav Barta
234832138f fixes #155 2022-04-01 08:42:10 +02:00
Valtteri Karesto
28d94a1475 Merge pull request #152 from eqlabs/fix/cloud-upload-button
Fix/cloud upload button
2022-03-31 10:15:31 +03:00
Valtteri Karesto
594aee6cd2 Merge pull request #154 from eqlabs/feat/add-header-templates
Feat/add header templates
2022-03-30 12:31:08 +03:00
Valtteri Karesto
d75910972f Change order 2022-03-30 12:09:16 +03:00
Valtteri Karesto
589c604a12 Add header files as hard coded 2022-03-30 12:00:27 +03:00
Valtteri Karesto
8394a11705 Merge pull request #151 from eqlabs/fix/disable-delete-hook
Fixes issue #148
2022-03-29 23:34:12 +03:00
Valtteri Karesto
4ad329882c Add tooltips to navigation items 2022-03-29 16:52:48 +03:00
Valtteri Karesto
ee86b91e82 Add tooltip component 2022-03-29 16:52:39 +03:00
Valtteri Karesto
d2addf782e Add extra isDisabled style for button 2022-03-29 16:52:24 +03:00
Valtteri Karesto
51f7bd509b Add radix tooltip 2022-03-29 16:52:02 +03:00
Valtteri Karesto
e064251ff9 Merge pull request #150 from eqlabs/feat/fix-newlines
Fixes issue #86 again, regressed in #107 for Firefox
2022-03-29 15:29:51 +03:00
Valtteri Karesto
95022ef121 Fixes issue #86 again, regressed in #107 for Firefox 2022-03-29 13:55:10 +03:00
12 changed files with 1640 additions and 78 deletions

View File

@@ -171,6 +171,16 @@ export const StyledButton = styled("button", {
color: "$textMuted",
},
},
isDisabled: {
true: {
opacity: 0.6,
// pointerEvents: "none",
cursor: "auto",
"&:hover": {
boxShadow: "inherit",
},
},
},
outline: {
true: {
backgroundColor: "transparent",

View File

@@ -10,7 +10,7 @@ interface ISelect<T = string> {
value: T;
}
const streamState = proxy({
export const streamState = proxy({
selectedAccount: null as ISelect | null,
logs: [] as ILog[],
socket: undefined as WebSocket | undefined,

View File

@@ -25,6 +25,7 @@ import {
import NewWindow from "react-new-window";
import { signOut, useSession } from "next-auth/react";
import { useSnapshot } from "valtio";
import toast from "react-hot-toast";
import {
createNewFile,
@@ -48,7 +49,7 @@ import Flex from "./Flex";
import Stack from "./Stack";
import Input from "./Input";
import Text from "./Text";
import toast from "react-hot-toast";
import Tooltip from "./Tooltip";
import {
AlertDialog,
AlertDialogContent,
@@ -367,44 +368,65 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
},
}}
>
<Button
isLoading={snap.zipLoading}
onClick={downloadAsZip}
outline
size="sm"
css={{ alignItems: "center" }}
<Tooltip content="Download as ZIP">
<Button
isLoading={snap.zipLoading}
onClick={downloadAsZip}
outline
size="sm"
css={{ alignItems: "center" }}
>
<DownloadSimple size="16px" />
</Button>
</Tooltip>
<Tooltip content="Copy share link to clipboard">
<Button
outline
size="sm"
css={{ alignItems: "center" }}
onClick={() => {
navigator.clipboard.writeText(
`${window.location.origin}/develop/${snap.gistId}`
);
toast.success("Copied share link to clipboard!");
}}
>
<Share size="16px" />
</Button>
</Tooltip>
<Tooltip
content={
session && session.user
? snap.gistOwner === session?.user.username
? "Sync to Gist"
: "Create as a new Gist"
: "You need to be logged in to sync with Gist"
}
>
<DownloadSimple size="16px" />
</Button>
<Button
outline
size="sm"
css={{ alignItems: "center" }}
onClick={() => {
navigator.clipboard.writeText(
`${window.location.origin}/develop/${snap.gistId}`
);
toast.success("Copied share link to clipboard!");
}}
>
<Share size="16px" />
</Button>
<Button
outline
size="sm"
disabled={!session || !session.user}
isLoading={snap.gistLoading}
css={{ alignItems: "center" }}
onClick={() => {
if (snap.gistOwner === session?.user.username) {
syncToGist(session);
} else {
setCreateNewAlertOpen(true);
}
}}
>
<CloudArrowUp size="16px" />
</Button>
<Button
outline
size="sm"
isDisabled={!session || !session.user}
isLoading={snap.gistLoading}
css={{ alignItems: "center" }}
onClick={() => {
if (!session || !session.user) {
return;
}
if (snap.gistOwner === session?.user.username) {
syncToGist(session);
} else {
setCreateNewAlertOpen(true);
}
}}
>
{snap.gistOwner === session?.user.username ? (
<CloudArrowUp size="16px" />
) : (
<FilePlus size="16px" />
)}
</Button>
</Tooltip>
<DropdownMenu>
<DropdownMenuTrigger asChild>

View File

@@ -215,6 +215,7 @@ export const Log: FC<ILog> = ({
)}
{expanded && jsonData && <Pre block>{jsonData}</Pre>}
</LogText>
<br />
</>
);
};

View File

@@ -228,7 +228,7 @@ const Navigation = () => {
as="a"
rel="noreferrer noopener"
target="_blank"
href="https://xrpl-hooks.readme.io/docs"
href="https://xrpl-hooks.readme.io/v2.0/docs"
>
<ArrowUpRight size="15px" /> Hooks documentation
</Text>
@@ -400,7 +400,7 @@ const Navigation = () => {
</Button>
</Link>
</ButtonGroup>
<Link href="https://xrpl-hooks.readme.io/" passHref>
<Link href="https://xrpl-hooks.readme.io/v2.0" passHref>
<a target="_blank" rel="noreferrer noopener">
<Button outline>
<BookOpen size="15px" />

89
components/Tooltip.tsx Normal file
View File

@@ -0,0 +1,89 @@
import React from "react";
import { styled, keyframes } from "../stitches.config";
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
const slideUpAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideRightAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(-2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const slideDownAndFade = keyframes({
"0%": { opacity: 0, transform: "translateY(-2px)" },
"100%": { opacity: 1, transform: "translateY(0)" },
});
const slideLeftAndFade = keyframes({
"0%": { opacity: 0, transform: "translateX(2px)" },
"100%": { opacity: 1, transform: "translateX(0)" },
});
const StyledContent = styled(TooltipPrimitive.Content, {
borderRadius: 4,
padding: "$2 $3",
fontSize: 12,
lineHeight: 1,
color: "$text",
backgroundColor: "$background",
boxShadow:
"hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px",
"@media (prefers-reduced-motion: no-preference)": {
animationDuration: "400ms",
animationTimingFunction: "cubic-bezier(0.16, 1, 0.3, 1)",
animationFillMode: "forwards",
willChange: "transform, opacity",
'&[data-state="delayed-open"]': {
'&[data-side="top"]': { animationName: slideDownAndFade },
'&[data-side="right"]': { animationName: slideLeftAndFade },
'&[data-side="bottom"]': { animationName: slideUpAndFade },
'&[data-side="left"]': { animationName: slideRightAndFade },
},
},
".dark &": {
boxShadow:
"0px 0px 10px 2px rgba(255,255,255,.15), hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px",
},
".light &": {
boxShadow:
"0px 0px 10px 2px rgba(0,0,0,.15), hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px",
},
});
const StyledArrow = styled(TooltipPrimitive.Arrow, {
fill: "$background",
});
interface ITooltip {
content: string;
open?: boolean;
defaultOpen?: boolean;
onOpenChange?: (open: boolean) => void;
}
const Tooltip: React.FC<ITooltip> = ({
children,
content,
open,
defaultOpen = false,
onOpenChange,
}) => {
return (
<TooltipPrimitive.Root
open={open}
defaultOpen={defaultOpen}
onOpenChange={onOpenChange}
>
<TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
<StyledContent side="bottom" align="center">
{content}
<StyledArrow offset={5} width={11} height={5} />
</StyledContent>
</TooltipPrimitive.Root>
);
};
export default Tooltip;

View File

@@ -19,6 +19,7 @@
"@radix-ui/react-dialog": "^0.1.1",
"@radix-ui/react-dropdown-menu": "^0.1.1",
"@radix-ui/react-id": "^0.1.1",
"@radix-ui/react-tooltip": "^0.1.7",
"@stitches/react": "^1.2.6-0",
"base64-js": "^1.5.1",
"dinero.js": "^1.9.1",

View File

@@ -18,6 +18,7 @@ import transactionsData from "../../content/transactions.json";
import state from "../../state";
import { sendTransaction } from "../../state/actions";
import { getSplit, saveSplit } from "../../state/actions/persistSplits";
import { streamState } from "../../components/DebugStream";
const DebugStream = dynamic(() => import("../../components/DebugStream"), {
ssr: false,
@@ -37,6 +38,11 @@ type TxFields = Omit<
>;
type OtherFields = (keyof Omit<TxFields, "Destination">)[];
interface AccountOption {
label: string;
value: string;
}
interface Props {
header?: string;
}
@@ -44,7 +50,7 @@ interface Props {
const Transaction: FC<Props> = ({ header, ...props }) => {
const snap = useSnapshot(state);
const transactionsOptions = transactionsData.map((tx) => ({
const transactionsOptions = transactionsData.map(tx => ({
value: tx.TransactionType,
label: tx.TransactionType,
}));
@@ -52,23 +58,24 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
typeof transactionsOptions[0] | null
>(null);
const accountOptions = snap.accounts.map((acc) => ({
const accountOptions: AccountOption[] = snap.accounts.map(acc => ({
label: acc.name,
value: acc.address,
}));
const [selectedAccount, setSelectedAccount] = useState<
typeof accountOptions[0] | null
>(null);
const destAccountOptions = snap.accounts
.map((acc) => ({
const [selectedAccount, setSelectedAccount] = useState<AccountOption | null>(
null
);
const destAccountOptions: AccountOption[] = snap.accounts
.map(acc => ({
label: acc.name,
value: acc.address,
}))
.filter((acc) => acc.value !== selectedAccount?.value);
const [selectedDestAccount, setSelectedDestAccount] = useState<
typeof destAccountOptions[0] | null
>(null);
.filter(acc => acc.value !== selectedAccount?.value);
const [selectedDestAccount, setSelectedDestAccount] =
useState<AccountOption | null>(null);
const [txIsLoading, setTxIsLoading] = useState(false);
const [txIsDisabled, setTxIsDisabled] = useState(false);
@@ -77,7 +84,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
useEffect(() => {
const transactionType = selectedTransaction?.value;
const account = snap.accounts.find(
(acc) => acc.address === selectedAccount?.value
acc => acc.address === selectedAccount?.value
);
if (!account || !transactionType || txIsLoading) {
setTxIsDisabled(true);
@@ -88,7 +95,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
useEffect(() => {
let _txFields: TxFields | undefined = transactionsData.find(
(tx) => tx.TransactionType === selectedTransaction?.value
tx => tx.TransactionType === selectedTransaction?.value
);
if (!_txFields) return setTxFields({});
_txFields = { ..._txFields } as TxFields;
@@ -105,7 +112,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
const submitTest = useCallback(async () => {
const account = snap.accounts.find(
(acc) => acc.address === selectedAccount?.value
acc => acc.address === selectedAccount?.value
);
const TransactionType = selectedTransaction?.value;
if (!account || !TransactionType || txIsDisabled) return;
@@ -116,7 +123,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
let options = { ...txFields };
options.Destination = selectedDestAccount?.value;
(Object.keys(options) as (keyof TxFields)[]).forEach((field) => {
(Object.keys(options) as (keyof TxFields)[]).forEach(field => {
let _value = options[field];
// convert currency
if (typeof _value === "object" && _value.type === "currency") {
@@ -182,9 +189,14 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
setTxIsLoading(false);
}, []);
const handleSetAccount = (acc: AccountOption) => {
setSelectedAccount(acc);
streamState.selectedAccount = acc;
};
const usualFields = ["TransactionType", "Amount", "Account", "Destination"];
const otherFields = Object.keys(txFields).filter(
(k) => !usualFields.includes(k)
k => !usualFields.includes(k)
) as OtherFields;
return (
<Box css={{ position: "relative", height: "calc(100% - 28px)" }} {...props}>
@@ -217,7 +229,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
hideSelectedOptions
css={{ width: "70%" }}
value={selectedTransaction}
onChange={(tt) => setSelectedTransaction(tt as any)}
onChange={(tt: any) => setSelectedTransaction(tt)}
/>
</Flex>
<Flex
@@ -239,7 +251,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
css={{ width: "70%" }}
options={accountOptions}
value={selectedAccount}
onChange={(acc) => setSelectedAccount(acc as any)}
onChange={(acc: any) => handleSetAccount(acc)} // TODO make react-select have correct types for acc
/>
</Flex>
{txFields.Amount !== undefined && (
@@ -258,7 +270,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
</Text>
<Input
value={txFields.Amount.value}
onChange={(e) =>
onChange={e =>
setTxFields({
...txFields,
Amount: { type: "currency", value: e.target.value },
@@ -289,11 +301,11 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
options={destAccountOptions}
value={selectedDestAccount}
isClearable
onChange={(acc) => setSelectedDestAccount(acc as any)}
onChange={(acc: any) => setSelectedDestAccount(acc)}
/>
</Flex>
)}
{otherFields.map((field) => {
{otherFields.map(field => {
let _value = txFields[field];
let value = typeof _value === "object" ? _value.value : _value;
value =
@@ -319,7 +331,7 @@ const Transaction: FC<Props> = ({ header, ...props }) => {
</Text>
<Input
value={value}
onChange={(e) =>
onChange={e =>
setTxFields({
...txFields,
[field]:
@@ -376,7 +388,7 @@ const Test = () => {
gutterSize={4}
gutterAlign="center"
style={{ height: "calc(100vh - 60px)" }}
onDragEnd={(e) => saveSplit("testVertical", e)}
onDragEnd={e => saveSplit("testVertical", e)}
>
<Flex
row
@@ -398,21 +410,19 @@ const Test = () => {
width: "100%",
height: "100%",
}}
onDragEnd={(e) => saveSplit("testHorizontal", e)}
onDragEnd={e => saveSplit("testHorizontal", e)}
>
<Box css={{ width: "55%", px: "$2" }}>
<Tabs
keepAllAlive
forceDefaultExtension
defaultExtension=".json"
onCreateNewTab={(name) =>
setTabHeaders(tabHeaders.concat(name))
}
onCloseTab={(index) =>
onCreateNewTab={name => setTabHeaders(tabHeaders.concat(name))}
onCloseTab={index =>
setTabHeaders(tabHeaders.filter((_, idx) => idx !== index))
}
>
{tabHeaders.map((header) => (
{tabHeaders.map(header => (
<Tab key={header} header={header}>
<Transaction header={header} />
</Tab>

View File

@@ -2,6 +2,7 @@ import { Octokit } from "@octokit/core";
import Router from "next/router";
import state from '../index';
import { templateFileIds } from '../constants';
import { hookapiH, hookmacroH, sfcodesH } from '../constants/headerTemplates';
const octokit = new Octokit();
@@ -24,16 +25,26 @@ export const fetchFiles = (gistId: string) => {
return res
}
// in case of templates, fetch header file(s) and append to res
return octokit.request("GET /gists/{gist_id}", { gist_id: templateFileIds.headers }).then(({ data: { files: headerFiles } }) => {
const files = { ...res.data.files, ...headerFiles }
res.data.files = files
return res
})
const files = {
...res.data.files,
'hookapi.h': res.data.files?.['hookapi.h'] || { filename: 'hookapi.h', content: hookapiH, language: 'C' },
'hookmacro.h': res.data.files?.['hookmacro.h'] || { filename: 'hookmacro.h', content: hookmacroH, language: 'C' },
'sfcodes.h': res.data.files?.['sfcodes.h'] || { filename: 'sfcodes.h', content: sfcodesH, language: 'C' },
};
res.data.files = files;
return res;
// If you want to load templates from GIST instad, uncomment the code below and comment the code above.
// return octokit.request("GET /gists/{gist_id}", { gist_id: templateFileIds.headers }).then(({ data: { files: headerFiles } }) => {
// const files = { ...res.data.files, ...headerFiles }
// console.log(headerFiles)
// res.data.files = files
// return res
// })
})
.then((res) => {
if (res.data.files && Object.keys(res.data.files).length > 0) {
const files = Object.keys(res.data.files).map((filename) => ({
name: res.data.files?.[filename]?.filename || "noname.c",
name: res.data.files?.[filename]?.filename || "untitled.c",
language: res.data.files?.[filename]?.language?.toLowerCase() || "",
content: res.data.files?.[filename]?.content || "",
}));

File diff suppressed because it is too large Load Diff

View File

@@ -14,8 +14,7 @@ export const templateFileIds = {
'carbon': 'a9fbcaf1b816b198c7fc0f62962bebf2',
'doubler': '56b86174aeb70b2b48eee962bad3e355',
'peggy': 'd21298a37e1550b781682014762a567b',
'headers': '9b448e8a55fab11ef5d1274cb59f9cf3'
'headers': '55f639bce59a49c58c45e663776b5138'
}
export const apiHeaderFiles = ['hookapi.h', 'sfcodes.h', 'hookmacro.h']

View File

@@ -762,6 +762,27 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-tooltip@^0.1.7":
version "0.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-0.1.7.tgz#6f8c00d6e489565d14abf209ce0fb8853c8c8ee3"
integrity sha512-eiBUsVOHenZ0JR16tl970bB0DafJBz6mFgSGfIGIVpflFj0LIsIDiLMsYyvYdx1KwwsIUDTEZtxcPm/sWjPzqA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "0.1.0"
"@radix-ui/react-compose-refs" "0.1.0"
"@radix-ui/react-context" "0.1.1"
"@radix-ui/react-id" "0.1.5"
"@radix-ui/react-popper" "0.1.4"
"@radix-ui/react-portal" "0.1.4"
"@radix-ui/react-presence" "0.1.2"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/react-slot" "0.1.2"
"@radix-ui/react-use-controllable-state" "0.1.0"
"@radix-ui/react-use-escape-keydown" "0.1.0"
"@radix-ui/react-use-previous" "0.1.1"
"@radix-ui/react-use-rect" "0.1.1"
"@radix-ui/react-visually-hidden" "0.1.4"
"@radix-ui/react-use-body-pointer-events@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-body-pointer-events/-/react-use-body-pointer-events-0.1.1.tgz#63e7fd81ca7ffd30841deb584cd2b7f460df2597"
@@ -807,6 +828,13 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-previous@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-previous/-/react-use-previous-0.1.1.tgz#0226017f72267200f6e832a7103760e96a6db5d0"
integrity sha512-O/ZgrDBr11dR8rhO59ED8s5zIXBRFi8MiS+CmFGfi7MJYdLbfqVOmQU90Ghf87aifEgWe6380LA69KBneaShAg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-use-rect@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-0.1.1.tgz#6c15384beee59c086e75b89a7e66f3d2e583a856"
@@ -822,6 +850,14 @@
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-visually-hidden@0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-0.1.4.tgz#6c75eae34fb5d084b503506fbfc05587ced05f03"
integrity sha512-K/q6AEEzqeeEq/T0NPChvBqnwlp8Tl4NnQdrI/y8IOY7BRR+Ug0PEsVk6g48HJ7cA1//COugdxXXVVK/m0X1mA==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "0.1.4"
"@radix-ui/rect@0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-0.1.1.tgz#95b5ba51f469bea6b1b841e2d427e17e37d38419"