Merge pull request #271 from bugout-dev/token-screen

Token screen
pull/278/head
Tim Pechersky 2021-09-22 18:18:12 +02:00 zatwierdzone przez GitHub
commit 49600ad1d6
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
54 zmienionych plików z 873 dodań i 225 usunięć

Wyświetl plik

@ -2,10 +2,10 @@
The Moonstream users HTTP API
"""
import logging
from typing import Any, Dict
from typing import Any, Dict, Optional
import uuid
from bugout.data import BugoutToken, BugoutUser, BugoutResource
from bugout.data import BugoutToken, BugoutUser, BugoutResource, BugoutUserTokens
from bugout.exceptions import BugoutResponseException
from fastapi import (
@ -149,23 +149,71 @@ async def delete_user_handler(
@app.post("/token", tags=["tokens"], response_model=BugoutToken)
async def login_handler(
username: str = Form(...), password: str = Form(...)
username: str = Form(...),
password: str = Form(...),
token_note: Optional[str] = Form(None),
) -> BugoutToken:
try:
token: BugoutToken = bc.create_token(
username=username,
password=password,
application_id=MOONSTREAM_APPLICATION_ID,
token_note=token_note,
)
except BugoutResponseException as e:
raise MoonstreamHTTPException(
status_code=e.status_code, detail=f"Error from Brood API: {e.detail}"
)
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
except Exception as e:
raise MoonstreamHTTPException(status_code=500, internal_error=e)
return token
@app.get("/tokens", tags=["tokens"], response_model=BugoutUserTokens)
async def tokens_handler(request: Request) -> BugoutUserTokens:
token = request.state.token
try:
response = bc.get_user_tokens(
token, timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS, active=True
)
except BugoutResponseException as e:
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
except Exception as e:
raise MoonstreamHTTPException(status_code=500, internal_error=e)
return response
@app.put("/token", tags=["tokens"], response_model=BugoutToken)
async def token_update_handler(
request: Request, token_note: str = Form(...), access_token: str = Form(...)
) -> BugoutToken:
token = request.state.token
try:
response = bc.update_token(token, token_note=token_note)
except BugoutResponseException as e:
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
except Exception as e:
raise MoonstreamHTTPException(status_code=500, internal_error=e)
return response
@app.post("/revoke/{access_token}", tags=["tokens"], response_model=uuid.UUID)
async def delete_token_by_id_handler(
request: Request, access_token: uuid.UUID
) -> uuid.UUID:
token = request.state.token
try:
response = bc.revoke_token(
token=token,
target_token=access_token,
timeout=BUGOUT_REQUEST_TIMEOUT_SECONDS,
)
except BugoutResponseException as e:
raise MoonstreamHTTPException(status_code=e.status_code, detail=e.detail)
except Exception as e:
raise MoonstreamHTTPException(status_code=500, internal_error=e)
return response
@app.delete("/token", tags=["tokens"], response_model=uuid.UUID)
async def logout_handler(request: Request) -> uuid.UUID:
token = request.state.token

Wyświetl plik

@ -3,7 +3,7 @@ asgiref==3.4.1
black==21.7b0
boto3==1.18.1
botocore==1.21.1
bugout==0.1.17
bugout==0.1.18
certifi==2021.5.30
charset-normalizer==2.0.3
click==8.0.1

Wyświetl plik

@ -12,7 +12,7 @@ setup(
packages=find_packages(),
install_requires=[
"boto3",
"bugout >= 0.1.17",
"bugout >= 0.1.18",
"fastapi",
"humbug>=0.2.7",
"python-dateutil",

Wyświetl plik

@ -23,7 +23,7 @@ const Security = () => {
pt: 2,
mb: 4,
borderBottom: "solid",
borderColor: "primary.50",
borderColor: "blue.50",
borderBottomWidth: "2px",
};
@ -91,7 +91,7 @@ const Security = () => {
<Icon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.newPassword && errors.newPassword.message}
</FormErrorMessage>
</FormControl>
@ -110,7 +110,7 @@ const Security = () => {
<Icon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.newPassword && errors.newPassword.message}
</FormErrorMessage>
</FormControl>
@ -129,7 +129,7 @@ const Security = () => {
<Icon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.confirmPassword && errors.confirmPassword.message}
</FormErrorMessage>
</FormControl>
@ -139,7 +139,7 @@ const Security = () => {
<Button
my={8}
variant="solid"
colorScheme="primary"
colorScheme="blue"
type="submit"
isLoading={isLoading}
>

Wyświetl plik

@ -0,0 +1,103 @@
import React, { useState, useEffect, useLayoutEffect } from "react";
import TokensList from "../../src/components/TokensList";
import TokenRequest from "../../src/components/TokenRequest";
import { useTokens } from "../../src/core/hooks";
import {
VStack,
Box,
Center,
Spinner,
ScaleFade,
Button,
Heading,
useDisclosure,
Modal,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
} from "@chakra-ui/react";
import { getLayout } from "../../src/layouts/AccountLayout";
const Tokens = () => {
const { onOpen, onClose, isOpen } = useDisclosure();
const [newToken, setNewToken] = useState(null);
const [tokens, setTokens] = useState();
const { list, update, revoke, isLoading, data } = useTokens();
useEffect(() => {
list();
//eslint-disable-next-line
}, []);
useLayoutEffect(() => {
if (newToken) {
const newData = { ...tokens };
newData.token.push(newToken);
setTokens(newData);
setNewToken(null);
}
}, [newToken, list, data, tokens]);
useLayoutEffect(() => {
if (data?.data?.user_id) {
setTokens(data.data);
}
}, [data?.data, isLoading]);
useEffect(() => {
document.title = `Tokens`;
}, []);
return (
<Box>
{isLoading && !tokens ? (
<Center>
<Spinner
hidden={false}
my={8}
size="lg"
color="blue.500"
thickness="4px"
speed="1.5s"
/>
</Center>
) : (
<ScaleFade in>
<Modal isOpen={isOpen} onClose={onClose} size="lg" trapFocus={false}>
<ModalOverlay />
<ModalContent>
<ModalHeader>New API access token</ModalHeader>
<ModalCloseButton />
<ModalBody>
<TokenRequest setNewToken={setNewToken} onClose={onClose} />
</ModalBody>
</ModalContent>
</Modal>
<Heading variant="tokensScreen"> My access tokens </Heading>
<VStack overflow="initial" maxH="unset" height="100%">
<Button
alignSelf="flex-end"
onClick={onOpen}
colorScheme="orange"
variant="solid"
size="sm"
>
Add new token
</Button>
<TokensList
data={tokens}
revoke={revoke}
isLoading={isLoading}
updateCallback={update}
/>
</VStack>
</ScaleFade>
)}
</Box>
);
};
Tokens.getLayout = getLayout;
export default Tokens;

Wyświetl plik

@ -30,7 +30,7 @@ const Analytics = () => {
<HubspotForm
portalId="8018701"
formId="39bc0fbe-41c4-430a-b885-46eba66c59c2"
loading={<Spinner colorScheme="primary" speed="1s" />}
loading={<Spinner colorScheme="blue" speed="1s" />}
/>
</Flex>
</Scrollable>

Wyświetl plik

@ -229,7 +229,6 @@ const Homepage = () => {
colSpan="12"
pb={[1, 2, null, 8]}
minH="100vh"
// bgColor="primary.1200"
>
<chakra.header boxSize="full" minH="100vh">
<Box
@ -261,7 +260,7 @@ const Homepage = () => {
my={12}
fontSize={["md", "2xl", "3xl", "3xl", "3xl", "4xl"]}
display="inline-block"
color="primary.200"
color="blue.200"
>
Get all the crypto data you need in a single stream.
From pending transactions in the Ethereum transaction
@ -270,7 +269,7 @@ const Homepage = () => {
<chakra.span
fontSize={["md", "2xl", "3xl", "3xl", "3xl", "4xl"]}
display="inline-block"
color="primary.300"
color="blue.300"
>
Access this data through the Moonstream dashboard or
API
@ -305,10 +304,7 @@ const Homepage = () => {
{` We believe in financial inclusion. Proprietary technologies
are not financially inclusive. That's why all our software
is `}
<chakra.span
display="inline-block"
textColor="secondary.900"
>
<chakra.span display="inline-block" textColor="orange.900">
<i>open source</i>
</chakra.span>
</Text>
@ -430,7 +426,7 @@ const Homepage = () => {
},
}}
elementName={"element1"}
colorScheme="suggested"
colorScheme="green"
badge={`For crypto traders`}
title={``}
body={``}
@ -438,21 +434,21 @@ const Homepage = () => {
{
text: `Subscribe to the defi contracts you care about`,
icon: FaFileContract,
color: "suggested.50",
bgColor: "suggested.900",
color: "green.50",
bgColor: "green.900",
},
{
text: `Make sense of how others are calling these contracts using Moonstream dashboards.
`,
icon: RiDashboardFill,
color: "suggested.50",
bgColor: "suggested.900",
color: "green.50",
bgColor: "green.900",
},
{
text: `Get data directly from the transaction pool through our global network of Ethereum nodes`,
icon: GiMeshBall,
color: "suggested.50",
bgColor: "suggested.900",
color: "green.50",
bgColor: "green.900",
},
]}
imgURL={assets["cryptoTraders"]}
@ -479,26 +475,26 @@ const Homepage = () => {
}}
elementName={"element2"}
mirror={true}
colorScheme="secondary"
colorScheme="orange"
badge={`For algorithmic funds`}
bullets={[
{
text: `Get API access to your stream`,
icon: AiFillApi,
color: "secondary.50",
bgColor: "secondary.900",
color: "orange.50",
bgColor: "orange.900",
},
{
text: `Set conditions that trigger predefined actions`,
icon: GiLogicGateXor,
color: "secondary.50",
bgColor: "secondary.900",
color: "orange.50",
bgColor: "orange.900",
},
{
text: `Execute transactions directly on Moonstream nodes`,
icon: BiTransfer,
color: "secondary.50",
bgColor: "secondary.900",
color: "orange.50",
bgColor: "orange.900",
},
]}
imgURL={assets["algorithmicFunds"]}
@ -535,26 +531,26 @@ const Homepage = () => {
},
}}
elementName={"element3"}
colorScheme="primary"
colorScheme="blue"
badge={`For smart contract developers`}
bullets={[
{
text: `See how people use your smart contracts`,
icon: IoTelescopeSharp,
color: "primary.50",
bgColor: "primary.900",
color: "blue.50",
bgColor: "blue.900",
},
{
text: `Set up alerts on suspicious activity`,
icon: GiSuspicious,
color: "primary.50",
bgColor: "primary.900",
color: "blue.50",
bgColor: "blue.900",
},
{
text: `Register webhooks to connect your off-chain infrastructure`,
icon: GiHook,
color: "primary.50",
bgColor: "primary.900",
color: "blue.50",
bgColor: "blue.900",
},
]}
imgURL={assets["smartDevelopers"]}
@ -574,7 +570,7 @@ const Homepage = () => {
href={"https://discord.gg/K56VNUQGvA"}
size="lg"
variant="solid"
colorScheme="suggested"
colorScheme="green"
id="test"
onClick={() => {
mixpanel.get_distinct_id() &&

Wyświetl plik

@ -178,7 +178,7 @@ const Product = () => {
<Text mb={3}>
You can read{" "}
<Link
textColor="secondary.900"
textColor="orange.900"
isExternal
href="https://github.com/bugout-dev/moonstream"
>
@ -186,7 +186,7 @@ const Product = () => {
</Link>{" "}
and keep track of our progress using{" "}
<Link
textColor="secondary.900"
textColor="orange.900"
isExternal
href="https://github.com/bugout-dev/moonstream/milestones"
>

Wyświetl plik

@ -53,7 +53,7 @@ const Register = () => {
<InputGroup>
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your username here"
name="username"
ref={register({ required: "Username is required!" })}
@ -62,7 +62,7 @@ const Register = () => {
<Icon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.username && errors.username.message}
</FormErrorMessage>
</FormControl>
@ -71,7 +71,7 @@ const Register = () => {
{!email && (
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your email here"
name="email"
ref={register({ required: "Email is required!" })}
@ -80,7 +80,7 @@ const Register = () => {
{email && (
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your email here"
defaultValue={email}
isReadOnly={true}
@ -92,7 +92,7 @@ const Register = () => {
<Icon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
@ -100,7 +100,7 @@ const Register = () => {
<InputGroup>
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
autoComplete="new-password"
placeholder="Add password"
name="password"
@ -111,7 +111,7 @@ const Register = () => {
<Icon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
@ -119,7 +119,7 @@ const Register = () => {
<Button
my={8}
variant="solid"
colorScheme="primary"
colorScheme="blue"
width="100%"
type="submit"
isLoading={isLoading}

Wyświetl plik

@ -54,7 +54,7 @@ const Entry = () => {
<RouteButton
variant="solid"
size="md"
colorScheme="suggested"
colorScheme="green"
href="/welcome"
>
Learn how to use moonstream

Wyświetl plik

@ -36,7 +36,7 @@ const Subscriptions = () => {
pt: 2,
mb: 4,
borderBottom: "solid",
borderColor: "primary.50",
borderColor: "blue.50",
borderBottomWidth: "2px",
};
@ -72,7 +72,7 @@ const Subscriptions = () => {
hidden={false}
my={8}
size="lg"
color="primary.500"
color="blue.500"
thickness="4px"
speed="1.5s"
/>
@ -90,7 +90,7 @@ const Subscriptions = () => {
<Flex
h="3rem"
w="100%"
bgColor="primary.50"
bgColor="blue.50"
borderTopRadius="xl"
justifyContent="flex-end"
alignItems="center"
@ -99,7 +99,7 @@ const Subscriptions = () => {
<Button
onClick={() => newSubscriptionClicked(true)}
mr={8}
colorScheme="suggested"
colorScheme="green"
variant="solid"
size="sm"
rightIcon={<AiOutlinePlusCircle />}
@ -110,7 +110,7 @@ const Subscriptions = () => {
<Button
onClick={() => newSubscriptionClicked(false)}
mr={8}
colorScheme="primary"
colorScheme="blue"
variant="solid"
size="sm"
rightIcon={<AiOutlinePlusCircle />}

Wyświetl plik

@ -194,10 +194,7 @@ const Product = () => {
We are always looking to hire new talents, regardless of their
backgrounds. If you are interested in working with us, send us a
message at{" "}
<Link
textColor="secondary.900"
href="mailto: careers@moonstream.to"
>
<Link textColor="orange.900" href="mailto: careers@moonstream.to">
careers@moonstream.to
</Link>
</Text>

Wyświetl plik

@ -82,7 +82,7 @@ const Welcome = () => {
<StepProgress
numSteps={ui.onboardingSteps.length}
currentStep={ui.onboardingStep}
colorScheme="primary"
colorScheme="blue"
buttonCallback={progressButtonCallback}
buttonTitles={[
"Moonstream basics",
@ -278,7 +278,7 @@ const Welcome = () => {
onChange={setProfile}
value={profile}
// fontWeight="bold"
colorScheme="secondary"
colorScheme="orange"
// py={0}
// my={0}
>
@ -361,7 +361,7 @@ const Welcome = () => {
)}
{!showSubscriptionForm && (
<Button
colorScheme="suggested"
colorScheme="green"
variant="solid"
onClick={() => setShowSubscriptionForm.on()}
>
@ -437,7 +437,7 @@ const Welcome = () => {
<IconButton
mr={4}
// onClick={onOpen}
colorScheme="primary"
colorScheme="blue"
variant="ghost"
icon={<FaFilter />}
/>
@ -482,7 +482,7 @@ const Welcome = () => {
<ButtonGroup>
<Button
colorScheme="secondary"
colorScheme="orange"
leftIcon={<ArrowLeftIcon />}
variant="outline"
hidden={ui.onboardingStep === 0}
@ -498,8 +498,8 @@ const Welcome = () => {
<Button
colorScheme={
ui.onboardingStep < ui.onboardingSteps.length - 1
? `secondary`
: `suggested`
? `orange`
: `green`
}
variant={
ui.onboardingStep < ui.onboardingSteps.length - 1

Wyświetl plik

@ -44,7 +44,7 @@ const baseStyleControl = (props) => {
},
_invalid: {
borderColor: mode("unsafe.500", "unsafe.300")(props),
borderColor: mode("red.500", "red.300")(props),
},
};
};
@ -55,7 +55,7 @@ const Checkbox = {
control: baseStyleControl(props),
}),
defaultProps: {
colorScheme: "primary",
colorScheme: "blue",
},
};

Wyświetl plik

@ -0,0 +1,57 @@
const baseStyle = {
fontFamily: "heading",
fontWeight: "bold",
};
const sizes = {
"4xl": {
fontSize: ["6xl", null, "7xl"],
lineHeight: 1,
},
"3xl": {
fontSize: ["5xl", null, "6xl"],
lineHeight: 1,
},
"2xl": {
fontSize: ["4xl", null, "5xl"],
lineHeight: [1.2, null, 1],
},
xl: {
fontSize: ["3xl", null, "4xl"],
lineHeight: [1.33, null, 1.2],
},
lg: {
fontSize: ["2xl", null, "3xl"],
lineHeight: [1.33, null, 1.2],
},
md: { fontSize: "xl", lineHeight: 1.2 },
sm: { fontSize: "md", lineHeight: 1.2 },
xs: { fontSize: "sm", lineHeight: 1.2 },
};
const defaultProps = {
size: "xl",
};
const variantTokensScreen = (props) => {
const { colorScheme: c } = props;
return {
as: "h2",
pt: 2,
mb: 4,
borderBottom: "solid",
borderColor: `${c}.50`,
borderBottomWidth: "2px",
};
};
const variants = {
tokensScreen: variantTokensScreen,
};
export default {
baseStyle,
sizes,
defaultProps,
variants,
};

Wyświetl plik

@ -82,7 +82,7 @@ const Input = {
},
defaultProps: {
colorScheme: "primary",
colorScheme: "blue",
size: "md",
variant: "filled",
},

Wyświetl plik

@ -11,11 +11,11 @@ const Menu = {
textColor: `${c}.900`,
_hover: {
bg: `secondary.800`,
bg: `orange.800`,
textColor: "white.100",
},
_focus: {
bg: `secondary.700`,
bg: `orange.700`,
textColor: "white.100",
},
},

Wyświetl plik

@ -1,5 +1,5 @@
const baseStyle = {
color: "primary.400",
color: "blue.400",
thickness: "4px",
speed: "1.5s",
my: 8,

Wyświetl plik

@ -19,7 +19,7 @@ const baseStyle = (props) => {
};
const variantSuggestion = (props) => {
const bg = mode("primary.700", "primary.300")(props);
const bg = mode("blue.700", "blue.300")(props);
return {
"--tooltip-bg": `colors.${bg}`,
px: "8px",
@ -37,7 +37,7 @@ const variantSuggestion = (props) => {
};
const variantOnboarding = (props) => {
const bg = mode("secondary.700", "secondary.300")(props);
const bg = mode("orange.700", "orange.300")(props);
return {
"--tooltip-bg": `colors.${bg}`,
px: "8px",

Wyświetl plik

@ -10,6 +10,7 @@ import Checkbox from "./Checkbox";
import Table from "./Table";
import Tooltip from "./Tooltip";
import Spinner from "./Spinner";
import Heading from "./Heading";
import { createBreakpoints } from "@chakra-ui/theme-tools";
const breakpointsCustom = createBreakpoints({
@ -40,7 +41,7 @@ const theme = extendTheme({
styles: {
global: {
body: {
color: "primary.1200",
color: "blue.1200",
},
},
},
@ -57,6 +58,7 @@ const theme = extendTheme({
Table,
Spinner,
Tooltip,
Heading,
},
fonts: {
@ -79,19 +81,6 @@ const theme = extendTheme({
},
colors: {
blue: {
50: "#C8CEFC",
100: "#B3BAF9",
200: "#9EA6F6",
300: "#8A92F3",
400: "#757EF0",
500: "#606AED",
600: "#4B56EA",
700: "#3742E7",
800: "#222EE4",
900: "#0D1AE1",
},
brand: {
100: "#212C8A",
200: "#111442",
@ -100,7 +89,7 @@ const theme = extendTheme({
500: "##F29C38",
},
primary: {
blue: {
0: "#FFFFFFFF",
50: "#e9eaf4",
100: "#d3d4e9",
@ -150,7 +139,7 @@ const theme = extendTheme({
200: "#F7F8FB",
300: "#EAEBF7",
},
unsafe: {
red: {
0: "#FFFFFFFF",
50: "#f9eaea",
100: "#f3d6d6",
@ -164,7 +153,7 @@ const theme = extendTheme({
900: "#C53030",
},
secondary: {
orange: {
0: "#FFFFFFFF",
50: "#ffeee6",
100: "#ffddcc",
@ -178,21 +167,7 @@ const theme = extendTheme({
900: "#FD5602",
},
teal: {
0: "#FFFFFFFF",
50: "#AEDFEA",
100: "#9ED8E5",
200: "#8ED2E1",
300: "#7ECBDD",
400: "#6EC5D8",
500: "#53B9D1",
600: "#4EB8D0",
700: "#3EB2CC",
800: "#33A7C1",
900: "#2F99B1",
},
suggested: {
green: {
0: "#FFFFFFFF",
50: "#e9f6dc",
100: "#e9f6dc", //Duplicates 50!!!!

Wyświetl plik

@ -35,6 +35,9 @@ const AccountIconButton = (props) => {
<RouterLink href="/account/security" passHref>
<MenuItem>Security</MenuItem>
</RouterLink>
<RouterLink href="/account/tokens" passHref>
<MenuItem>Access tokens</MenuItem>
</RouterLink>
</MenuGroup>
<MenuDivider />
<MenuItem

Wyświetl plik

@ -57,7 +57,7 @@ const AppNavbar = () => {
<Popover usePortal>
<PopoverTrigger>
<IconButton
colorScheme="primary"
colorScheme="blue"
variant="link"
h="32px"
size="lg"
@ -81,12 +81,12 @@ const AppNavbar = () => {
<Link
href="mailto:support@moonstream.to"
fontWeight="600"
textColor="primary.500"
textColor="blue.500"
>
support@moonstream.to
</Link>
</Text>
<Text fontWeight="700" textColor="primary.500">
<Text fontWeight="700" textColor="blue.500">
<Link href="https://discord.gg/K56VNUQGvA">Discord</Link>
</Text>
</PopoverBody>
@ -102,7 +102,7 @@ const AppNavbar = () => {
<Flex width="100%" px={2}>
<Spacer />
<Flex placeSelf="flex-end">
<ButtonGroup spacing={4} colorScheme="secondary">
<ButtonGroup spacing={4} colorScheme="orange">
{ALL_NAV_PATHES.map((item, idx) => (
<RouteButton
key={`${idx}-${item.title}-landing-all-links`}
@ -130,7 +130,7 @@ const AppNavbar = () => {
</ButtonGroup>
<SupportPopover />
<AccountIconButton
colorScheme="primary"
colorScheme="blue"
variant="link"
color="gray.100"
size="lg"
@ -234,7 +234,7 @@ const AppNavbar = () => {
alignContent="center"
h="32px"
size={iconSize}
colorScheme="primary"
colorScheme="blue"
/>
)}
</Flex>

Wyświetl plik

@ -71,7 +71,7 @@ const ChangePassword = () => {
<CustomIcon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.newPassword && errors.newPassword.message}
</FormErrorMessage>
</FormControl>
@ -90,7 +90,7 @@ const ChangePassword = () => {
<CustomIcon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.newPassword && errors.newPassword.message}
</FormErrorMessage>
</FormControl>
@ -109,7 +109,7 @@ const ChangePassword = () => {
<CustomIcon icon="password" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.confirmPassword && errors.confirmPassword.message}
</FormErrorMessage>
</FormControl>
@ -119,7 +119,7 @@ const ChangePassword = () => {
<Button
my={8}
variant="solid"
colorScheme="primary"
colorScheme="blue"
type="submit"
isLoading={isLoading}
>

Wyświetl plik

@ -58,7 +58,6 @@ const ColorSelector = (props) => {
</Text>{" "}
<IconButton
size="md"
// colorScheme="primary"
color={"white.100"}
_hover={{ bgColor: { color } }}
bgColor={color}
@ -87,7 +86,7 @@ const ColorSelector = (props) => {
props.callback(color);
onClose();
}}
colorScheme="suggested"
colorScheme="green"
variant="outline"
>
Apply

Wyświetl plik

@ -23,7 +23,7 @@ const ConfirmationRequest = (props) => {
<PopoverFooter>
<Button
onClick={onClose}
colorScheme="primary"
colorScheme="blue"
variant="outline"
size="sm"
>
@ -34,7 +34,7 @@ const ConfirmationRequest = (props) => {
props.onConfirm();
onClose();
}}
colorScheme="unsafe"
colorScheme="red"
variant="solid"
size="sm"
>

Wyświetl plik

@ -48,7 +48,7 @@ const ArrowCTA = (props) => {
ref={box1Ref}
boxShadow="md"
variant="solid"
colorScheme="suggested"
colorScheme="green"
className="MoonStockSpeciality element1"
w={["180px", "180px", "250px", null, "250px"]}
onClick={props.button1.onClick}
@ -65,7 +65,7 @@ const ArrowCTA = (props) => {
ref={box2Ref}
boxShadow="md"
variant="solid"
colorScheme="secondary"
colorScheme="orange"
className="MoonStockSpeciality element2"
w={["180px", "180px", "250px", null, "250px"]}
onClick={props.button2.onClick}
@ -82,7 +82,7 @@ const ArrowCTA = (props) => {
ref={box3Ref}
boxShadow="md"
variant="solid"
colorScheme="primary"
colorScheme="blue"
w={["180px", "180px", "250px", null, "250px"]}
onClick={props.button3.onClick}
>

Wyświetl plik

@ -29,7 +29,7 @@ const CopyButton = (props) => {
<IconButton
onClick={onCopy}
icon={<BiCopy />}
colorScheme="secondary"
colorScheme="orange"
variant="ghost"
size="sm"
/>

Wyświetl plik

@ -257,7 +257,7 @@ const EntriesNavigation = () => {
{filter.direction === DIRECTIONS.SOURCE && (
<Select
variant="solid"
colorScheme="primary"
colorScheme="blue"
name="address"
onChange={handleAddressChange(idx)}
>
@ -298,7 +298,7 @@ const EntriesNavigation = () => {
)}
<IconButton
placeItems="center"
colorScheme="primary"
colorScheme="blue"
variant="ghost"
onClick={() => dropNewFilterArrayItem(idx)}
icon={<ImCancelCircle />}
@ -311,7 +311,7 @@ const EntriesNavigation = () => {
<MenuButton
as={Button}
mt={4}
colorScheme="secondary"
colorScheme="orange"
variant="solid"
>
Add filter row
@ -357,7 +357,7 @@ const EntriesNavigation = () => {
</DrawerBody>
<DrawerFooter pb={16} placeContent="center">
<Button
colorScheme="suggested"
colorScheme="green"
variant="solid"
// type="submit"
onClick={() => handleFilterSubmit()}
@ -377,7 +377,7 @@ const EntriesNavigation = () => {
mx={1}
size="lg"
variant="solid"
colorScheme="secondary"
colorScheme="orange"
>
{filter?.type === FILTER_TYPES.ADDRESS && (
<TagLabel>
@ -401,7 +401,7 @@ const EntriesNavigation = () => {
<IconButton
mr={4}
onClick={onOpen}
colorScheme="primary"
colorScheme="blue"
variant="ghost"
icon={<FaFilter />}
/>
@ -428,7 +428,7 @@ const EntriesNavigation = () => {
loadNewesEventHandler();
}}
variant="outline"
colorScheme="suggested"
colorScheme="green"
>
Load newer events
</Button>
@ -437,7 +437,7 @@ const EntriesNavigation = () => {
isLoading
loadingText="Loading"
variant="outline"
colorScheme="suggested"
colorScheme="green"
></Button>
)}
</Stack>
@ -468,7 +468,7 @@ const EntriesNavigation = () => {
loadPreviousEventHandler();
}}
variant="outline"
colorScheme="suggested"
colorScheme="green"
>
Load older events
</Button>
@ -482,7 +482,7 @@ const EntriesNavigation = () => {
isLoading
loadingText="Loading"
variant="outline"
colorScheme="suggested"
colorScheme="green"
></Button>
)}
</Center>
@ -495,7 +495,7 @@ const EntriesNavigation = () => {
<Spinner
mt="50%"
size="lg"
color="primary.500"
color="blue.500"
thickness="4px"
speed="1.5s"
/>

Wyświetl plik

@ -110,9 +110,9 @@ const Footer = () => (
mx={2}
mb={2}
borderRadius="13px"
bg="primary.800"
bg="blue.800"
boxSize={["3rem", "4rem", "6rem", null, "6rem"]}
_hover={{ bg: "primary.600" }}
_hover={{ bg: "blue.600" }}
alignItems="center"
justifyContent="center"
href={icon.link}
@ -123,7 +123,7 @@ const Footer = () => (
</Link>
))}
</Flex>
<Text pt={24} alignSelf="flex-end" textColor="primary.500">
<Text pt={24} alignSelf="flex-end" textColor="blue.500">
All rights reserved.2021
</Text>
</Flex>

Wyświetl plik

@ -36,7 +36,7 @@ const ForgotPassword = ({ toggleModal }) => {
<FormControl isInvalid={errors.email} my={4}>
<InputGroup>
<Input
colorScheme="primary"
colorScheme="blue"
variant="filled"
placeholder="Your email here"
name="email"
@ -46,14 +46,14 @@ const ForgotPassword = ({ toggleModal }) => {
<CustomIcon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
<Button
type="submit"
variant="solid"
colorScheme="primary"
colorScheme="blue"
width="100%"
isLoading={isLoading}
>

Wyświetl plik

@ -36,7 +36,7 @@ const RequestIntegration = ({ toggleModal, title, formId }) => {
region="na1"
portalId="8018701"
formId={formId}
loading={<Spinner colorScheme="primary" speed="1s" />}
loading={<Spinner colorScheme="blue" speed="1s" />}
/>
</Modal>
);

Wyświetl plik

@ -26,7 +26,7 @@ const LandingNavbar = () => {
<>
<IconButton
alignSelf="flex-start"
colorScheme="primary"
colorScheme="blue"
variant="solid"
onClick={() => ui.setSidebarToggled(!ui.sidebarToggled)}
icon={<HamburgerIcon />}
@ -57,12 +57,7 @@ const LandingNavbar = () => {
{!ui.isMobileView && (
<>
<Spacer />
<ButtonGroup
variant="link"
colorScheme="secondary"
spacing={4}
pr={16}
>
<ButtonGroup variant="link" colorScheme="orange" spacing={4} pr={16}>
{ALL_NAV_PATHES.map((item, idx) => (
<RouteButton
key={`${idx}-${item.title}-landing-all-links`}
@ -79,7 +74,7 @@ const LandingNavbar = () => {
<RouterLink href="/stream" passHref>
<Button
as={Link}
colorScheme="secondary"
colorScheme="orange"
variant="outline"
size="sm"
fontWeight="400"
@ -111,7 +106,7 @@ const LandingNavbar = () => {
</Button>
)}
{ui.isLoggedIn && (
<ChakraAccountIconButton variant="link" colorScheme="secondary" />
<ChakraAccountIconButton variant="link" colorScheme="orange" />
)}
</ButtonGroup>
</>
@ -119,7 +114,7 @@ const LandingNavbar = () => {
{ui.isLoggedIn && ui.isMobileView && (
<>
<Spacer />
<ChakraAccountIconButton variant="link" colorScheme="secondary" />
<ChakraAccountIconButton variant="link" colorScheme="orange" />
</>
)}
</>

Wyświetl plik

@ -9,11 +9,11 @@ const Modal = ({ children, onClose }) => (
<Flex onClick={onClose} css={styles.modal} zIndex={100002}>
<Flex onClick={(e) => e.stopPropagation()} css={styles.flex}>
<Image
color="primary.900"
color="blue.900"
height="24px"
width="22px"
sx={{ filter: "grayscale: 50%" }}
fill="primary.800"
fill="blue.800"
src={
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets/logo-black.svg"
}

Wyświetl plik

@ -20,7 +20,7 @@ const Navbar = () => {
id="Navbar"
minH="3rem"
maxH="3rem"
bgColor="primary.1200"
bgColor="blue.1200"
direction="row"
w="100%"
overflow="hidden"

Wyświetl plik

@ -192,7 +192,7 @@ const _NewSubscription = ({
name="address"
ref={register({ required: "address is required!" })}
></Input>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors?.address && errors?.address.message}
</FormErrorMessage>
</FormControl>
@ -222,7 +222,7 @@ const _NewSubscription = ({
>
<IconButton
size="md"
// colorScheme="primary"
// colorScheme="blue"
color={"white.100"}
_hover={{ bgColor: { color } }}
bgColor={color}
@ -278,7 +278,7 @@ const _NewSubscription = ({
<GithubPicker onChangeComplete={handleChangeColorComplete} />
</>
)}
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors?.color && errors?.color.message}
</FormErrorMessage>
</FormControl>
@ -286,7 +286,7 @@ const _NewSubscription = ({
<ButtonGroup direction="row" justifyContent="flex-end" w="100%">
<Button
type="submit"
colorScheme="suggested"
colorScheme="green"
isLoading={createSubscription.isLoading}
>
Confirm

Wyświetl plik

@ -0,0 +1,85 @@
import React, { useEffect, useRef, Fragment } from "react";
import {
FormControl,
FormErrorMessage,
InputGroup,
Input,
Td,
Tr,
} from "@chakra-ui/react";
import { CloseIcon } from "@chakra-ui/icons";
import IconButton from "./IconButton";
const NewTokenTr = ({ isOpen, toggleSelf, errors, register, journalName }) => {
const inputRef = useRef(null);
useEffect(() => {
if (isOpen) {
//without timeout input is not catching focus on chrome and firefox..
//probably because it is hidden within accordion
setTimeout(() => {
inputRef.current.focus();
}, 100);
}
}, [inputRef, isOpen]);
return (
<Fragment>
{isOpen && (
<Tr transition="0.3s" _hover={{ bg: "white.200" }}>
<Td>New Token:</Td>
<Td>
<FormControl isInvalid={errors.appName}>
<InputGroup>
<Input
fontSize="sm"
border="none"
width="60%"
defaultValue={journalName}
height="fit-content"
placeholder="App name"
name="appName"
ref={(e) => {
register(e, { required: "app name is required" });
inputRef.current = e;
}}
/>
</InputGroup>
<FormErrorMessage color="red.400" pl="1">
{errors.appName && errors.appName.message}
</FormErrorMessage>
</FormControl>
</Td>
<Td>
<FormControl isInvalid={errors.appVersion}>
<InputGroup>
<Input
fontSize="sm"
border="none"
width="60%"
height="fit-content"
placeholder="App Version"
name="appVersion"
ref={(e) => {
register(e, { required: "app name is required" });
}}
/>
</InputGroup>
<FormErrorMessage color="red.400" pl="1">
{errors.appVersion && errors.appVersion.message}
</FormErrorMessage>
</FormControl>
</Td>
<Td>
<IconButton type="submit" />
<IconButton
onClick={() => toggleSelf(false)}
icon={<CloseIcon />}
/>
</Td>
</Tr>
)}
</Fragment>
);
};
export default NewTokenTr;

Wyświetl plik

@ -9,7 +9,7 @@ const PasswordInput = ({ placeholder, name }, ref) => {
<InputGroup>
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
autoComplete="current-password"
placeholder={placeholder}
name={name}

Wyświetl plik

@ -29,10 +29,10 @@ const RadioCard = (props) => {
borderColor: "gray.300",
}}
_checked={{
// bg: "secondary.900",
// bg: "orange.900",
color: "secondary.900",
borderColor: "secondary.900",
color: "orange.900",
borderColor: "orange.900",
borderWidth: "4px",
}}
justifyContent="center"

Wyświetl plik

@ -33,7 +33,7 @@ const Sidebar = () => {
<IconButton
ml={4}
justifySelf="flex-start"
colorScheme="primary"
colorScheme="blue"
aria-label="App navigation"
icon={
ui.isMobileView ? (

Wyświetl plik

@ -49,7 +49,7 @@ const SignIn = ({ toggleModal }) => {
_placeholder={{ textColor: "gray.1200" }}
autoComplete="username"
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your Moonstream username"
name="username"
{...register("username", { required: true })}
@ -59,7 +59,7 @@ const SignIn = ({ toggleModal }) => {
<CustomIcon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.username && errors.username.message}
</FormErrorMessage>
</FormControl>
@ -69,7 +69,7 @@ const SignIn = ({ toggleModal }) => {
name="password"
ref={register({ required: "Password is required!" })}
/>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
@ -79,7 +79,7 @@ const SignIn = ({ toggleModal }) => {
type="submit"
width="100%"
variant="solid"
colorScheme="primary"
colorScheme="blue"
isLoading={isLoading}
>
Login
@ -89,7 +89,7 @@ const SignIn = ({ toggleModal }) => {
{" "}
<Box
cursor="pointer"
color="primary.800"
color="blue.800"
as="span"
onClick={() => toggleModal("forgot")}
>
@ -100,12 +100,12 @@ const SignIn = ({ toggleModal }) => {
<Text textAlign="center" fontSize="md" color="gray.1200">
{/* Don`t have an account?{" "} */}
We are in early access. If you would like to use Moonstream,{" "}
<Link href={"https://discord.gg/V3tWaP36"} color="secondary.900">
<Link href={"https://discord.gg/V3tWaP36"} color="orange.900">
contact us on Discord.
</Link>
{/* <Box
cursor="pointer"
color="primary.800"
color="blue.800"
as="span"
onClick={() => toggleModal("register")}
>

Wyświetl plik

@ -46,7 +46,7 @@ const SignUp = ({ toggleModal }) => {
<InputGroup>
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your username here"
name="username"
ref={register({ required: "Username is required!" })}
@ -55,7 +55,7 @@ const SignUp = ({ toggleModal }) => {
<CustomIcon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.username && errors.username.message}
</FormErrorMessage>
</FormControl>
@ -63,7 +63,7 @@ const SignUp = ({ toggleModal }) => {
<InputGroup>
<Input
variant="filled"
colorScheme="primary"
colorScheme="blue"
placeholder="Your email here"
name="email"
ref={register({ required: "Email is required!" })}
@ -72,7 +72,7 @@ const SignUp = ({ toggleModal }) => {
<CustomIcon icon="name" />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.email && errors.email.message}
</FormErrorMessage>
</FormControl>
@ -82,7 +82,7 @@ const SignUp = ({ toggleModal }) => {
name="password"
ref={register({ required: "Password is required!" })}
/>
<FormErrorMessage color="unsafe.400" pl="1">
<FormErrorMessage color="red.400" pl="1">
{errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
@ -90,7 +90,7 @@ const SignUp = ({ toggleModal }) => {
<Button
my={8}
variant="solid"
colorScheme="primary"
colorScheme="blue"
width="100%"
type="submit"
isLoading={isLoading}
@ -103,7 +103,7 @@ const SignUp = ({ toggleModal }) => {
Already have an account?{" "}
<Box
cursor="pointer"
color="primary.400"
color="blue.400"
as="span"
onClick={() => toggleModal("login")}
>

Wyświetl plik

@ -133,7 +133,7 @@ const SplitWithImage = ({
</Text>
</Stack>
<Heading>{title}</Heading>
<Text color={`primary.500`} fontSize={"lg"}>
<Text color={`blue.500`} fontSize={"lg"}>
{body}
</Text>
<Stack
@ -184,7 +184,7 @@ const SplitWithImage = ({
mt={[0, 0, null, 16]}
size={socialButton ? buttonSize.double : buttonSize.single}
variant="outline"
colorScheme="primary"
colorScheme="blue"
leftIcon={<FaGithubSquare />}
>
git clone moonstream

Wyświetl plik

@ -77,7 +77,7 @@ const StreamEntry_ = ({ entry, showOnboardingTooltips, className }) => {
variant="solid"
px={0}
minW="24px"
colorScheme="secondary"
colorScheme="orange"
icon={<ArrowRightIcon w="24px" />}
/>
</Tooltip>

Wyświetl plik

@ -50,7 +50,7 @@ const SubscriptionsList = ({ emptyCTA }) => {
borderColor="gray.200"
borderWidth="1px"
variant="simple"
colorScheme="primary"
colorScheme="blue"
justifyContent="center"
borderBottomRadius="xl"
alignItems="baseline"
@ -81,7 +81,7 @@ const SubscriptionsList = ({ emptyCTA }) => {
</Td>
<Td py={0}>
<Editable
colorScheme="primary"
colorScheme="blue"
placeholder="enter note here"
defaultValue={subscription.label}
onSubmit={(nextValue) =>
@ -125,7 +125,7 @@ const SubscriptionsList = ({ emptyCTA }) => {
<IconButton
size="sm"
variant="ghost"
colorScheme="primary"
colorScheme="blue"
icon={<DeleteIcon />}
/>
</ConfirmationRequest>
@ -143,7 +143,7 @@ const SubscriptionsList = ({ emptyCTA }) => {
return (
<Container>
{` You don't have any subscriptions at the moment.`}
{emptyCTA && <Button variant="suggested">Create one</Button>}
{emptyCTA && <Button variant="green">Create one</Button>}
</Container>
);
} else if (subscriptionsCache.isLoading) {

Wyświetl plik

@ -16,7 +16,7 @@ const Tags = ({ tags }) => {
{displayTags?.map((tag, index) => (
<Tag
variant="subtle"
colorScheme="primary"
colorScheme="blue"
key={`${tag}-${index}`}
zIndex={1}
>

Wyświetl plik

@ -0,0 +1,101 @@
import React from "react";
import { IconButton } from "@chakra-ui/react";
import {
Table,
Th,
Td,
Tr,
Thead,
Tbody,
Text,
Center,
Spinner,
} from "@chakra-ui/react";
import { DeleteIcon } from "@chakra-ui/icons";
import { CopyButton, ConfirmationRequest, NewTokenTr } from ".";
import { useForm } from "react-hook-form";
const TokenList = ({
tokens,
revoke,
isLoading,
isNewTokenOpen,
toggleNewToken,
createToken,
journalName,
}) => {
const { register, handleSubmit, errors } = useForm();
if (isLoading)
return (
<Center>
<Spinner />
</Center>
);
const handleTokenSubmit = ({ appName, appVersion }) => {
createToken({ appName, appVersion }).then(() => toggleNewToken(false));
};
return (
<form onSubmit={handleSubmit(handleTokenSubmit)}>
<Table
variant="simple"
colorScheme="blue"
justifyContent="center"
alignItems="baseline"
h="auto"
size="sm"
>
<Thead>
<Tr>
<Th>Token</Th>
<Th>App Name</Th>
<Th>App version</Th>
<Th>Action</Th>
</Tr>
</Thead>
<Tbody>
{tokens.map((token, idx) => {
return (
<Tr key={`RestrictedToken-row-${idx}`}>
<Td mr={4} p={0}>
<CopyButton>{token.restricted_token_id}</CopyButton>
</Td>
<Td py={0}>{token.app_name}</Td>
<Td py={0}>{token.app_version}</Td>
<Td py={0}>
<ConfirmationRequest
bodyMessage={"please confirm"}
header={"Delete token"}
onConfirm={() => revoke(token.restricted_token_id)}
>
<IconButton
size="sm"
variant="ghost"
colorScheme="blue"
icon={<DeleteIcon />}
/>
</ConfirmationRequest>
</Td>
</Tr>
);
})}
<NewTokenTr
isOpen={isNewTokenOpen}
toggleSelf={toggleNewToken}
errors={errors}
register={register}
journalName={journalName}
/>
</Tbody>
</Table>
{tokens.length < 1 && (
<Center>
<Text my={4}>Create Usage report tokens here</Text>
</Center>
)}
</form>
);
};
export default TokenList;

Wyświetl plik

@ -0,0 +1,131 @@
import React from "react";
import {
Box,
InputGroup,
InputLeftElement,
FormControl,
FormErrorMessage,
Stack,
Button,
Input,
chakra,
} from "@chakra-ui/react";
import { useEffect, useState, useRef } from "react";
import { Icon } from "../../src/Theme";
import { useForm } from "react-hook-form";
import { useUser, useTokens } from "../core/hooks";
const TokenRequest = ({ setNewToken, onClose }) => {
const { user } = useUser();
const { createToken } = useTokens();
const { handleSubmit, errors, register } = useForm();
const [showPassword, setShowPassword] = useState("password");
const togglePassword = () => {
if (showPassword === "password") {
setShowPassword("text");
} else {
setShowPassword("password");
}
};
const PasswordRef = useRef();
useEffect(() => {
if (PasswordRef.current) {
PasswordRef.current.focus();
}
}, [PasswordRef]);
useEffect(() => {
if (createToken.data?.data) {
setNewToken(createToken.data.data);
onClose();
}
}, [createToken.data, setNewToken, onClose]);
const formStyle = {
display: "flex",
flexWrap: "wrap",
minWidth: "100px",
flexFlow: "row wrap-reverse",
aligntContent: "flex-end",
width: "100%",
};
if (!user) return ""; //loading...
return (
<Box px={1} py={4}>
<form onSubmit={handleSubmit(createToken.mutate)} style={formStyle}>
<Stack direction="column" spacing={4} w="100%">
<Stack direction="column" spacing={1}>
<chakra.label for="pwd">API key label:</chakra.label>
<Input
w="100%"
ref={register}
name="token_note"
placeholder="My API key label"
type="search"
/>
</Stack>
<Stack direction="column" spacing={1}>
<chakra.label for="pwd">Password:</chakra.label>
<FormControl isInvalid={errors.password}>
<InputGroup minWidth="300px">
<InputLeftElement onClick={togglePassword}>
<Icon icon="password" />
</InputLeftElement>
<Input
id="pwd"
colorScheme="blue"
variant="filled"
isDisabled={createToken.isLoading}
placeholder="This action requires your password to confirm"
name="password"
type={showPassword}
ref={(e) => {
register(e, { required: "Password is required!" });
PasswordRef.current = e;
}}
/>
</InputGroup>
<FormErrorMessage color="red.400" pl="1" justifyContent="Center">
{errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
</Stack>
<Input
type="hidden"
ref={register}
name="username"
defaultValue={user?.username}
/>
<Stack pt={9} direction="row" justifyContent="flex-end" w="100%">
<Button
m={0}
variant="solid"
colorScheme="blue"
type="submit"
isLoading={createToken.isLoading}
>
Submit
</Button>
<Button
variant="solid"
colorScheme="red"
type="submit"
onClick={() => onClose()}
>
Cancel
</Button>
</Stack>
</Stack>
</form>
</Box>
);
};
export default TokenRequest;

Wyświetl plik

@ -0,0 +1,88 @@
import React from "react";
import { Skeleton, IconButton } from "@chakra-ui/react";
import {
Table,
Th,
Td,
Tr,
Thead,
Tbody,
Editable,
EditableInput,
EditablePreview,
} from "@chakra-ui/react";
import { DeleteIcon } from "@chakra-ui/icons";
import moment from "moment";
import CopyButton from "./CopyButton";
const List = ({ data, revoke, isLoading, updateCallback }) => {
const userToken = localStorage.getItem("BUGOUT_ACCESS_TOKEN");
if (data) {
return (
<Table
variant="simple"
colorScheme="blue"
justifyContent="center"
alignItems="baseline"
h="auto"
size="sm"
>
<Thead>
<Tr>
<Th>Token</Th>
<Th>Date Created</Th>
<Th>Note</Th>
<Th>Actions</Th>
</Tr>
</Thead>
<Tbody>
{data.token.map((token) => {
if (token.active) {
if (userToken !== token.id) {
return (
<Tr key={`token-row-${token.id}`}>
<Td mr={4} p={0}>
<CopyButton>{token.id}</CopyButton>
</Td>
<Td py={0}>{moment(token.created_at).format("L")}</Td>
<Td py={0}>
<Editable
colorScheme="blue"
placeholder="enter note here"
defaultValue={token.note}
onSubmit={(nextValue) =>
updateCallback({ token: token.id, note: nextValue })
}
>
<EditablePreview
maxW="40rem"
_placeholder={{ color: "black" }}
/>
<EditableInput maxW="40rem" />
</Editable>
</Td>
<Td py={0}>
<IconButton
size="sm"
variant="ghost"
colorScheme="blue"
onClick={() => revoke(token.id)}
icon={<DeleteIcon />}
/>
</Td>
</Tr>
);
} else return null;
} else return null;
})}
</Tbody>
</Table>
);
} else if (isLoading) {
return <Skeleton />;
} else {
return "";
}
};
export default List;

Wyświetl plik

@ -215,7 +215,7 @@ const EthereumWhalewatchCard_ = ({
<Box boxSize="min-content">
<IconButton
onClick={() => subscribeClicked(whaleType)}
colorScheme="secondary"
colorScheme="orange"
variant="outline"
m={0}
boxSize="24px"

Wyświetl plik

@ -1,4 +1,4 @@
export { queryCacheProps as hookCommon } from "./hookCommon";
export { default as hookCommon } from "./hookCommon";
export { default as useAuthResultHandler } from "./useAuthResultHandler";
export { default as useChangePassword } from "./useChangePassword";
export { default as useClientID } from "./useClientID";
@ -15,8 +15,10 @@ export { default as useResetPassword } from "./useResetPassword";
export { default as useRouter } from "./useRouter";
export { default as useSignUp } from "./useSignUp";
export { default as useStorage } from "./useStorage";
export { default as useStream } from "./useStream";
export { default as useStripe } from "./useStripe";
export { default as useSubscriptions } from "./useSubscriptions";
export { default as useToast } from "./useToast";
export { default as useTokens } from "./useTokens";
export { default as useTxInfo } from "./useTxInfo";
export { default as useUser } from "./useUser";

Wyświetl plik

@ -1,5 +1,5 @@
import { useToast as useChakraToast, Box } from "@chakra-ui/react";
import React, { useCallback } from "react";
import { useToast as useChakraToast } from "@chakra-ui/react";
import { useCallback } from "react";
import mixpanel from "mixpanel-browser";
import { MIXPANEL_EVENTS } from "../providers/AnalyticsProvider/constants";
@ -7,37 +7,28 @@ const useToast = () => {
const chakraToast = useChakraToast();
const toast = useCallback(
(message, type) => {
(message, type, title) => {
const userTitle = title ?? message?.response?.statusText ?? type;
const userMessage =
message?.response?.data?.detail ??
message ??
(userTitle === type ? "" : type);
if (mixpanel.get_distinct_id() && type === "error") {
mixpanel.track(`${MIXPANEL_EVENTS.TOAST_ERROR_DISPLAYED}`, {
status: message?.response?.status,
detail: message?.response?.data.detail,
title: userTitle,
detail: userMessage,
});
}
const background = type === "error" ? "unsafe.500" : "suggested.500";
const userMessage =
type === "error"
? message?.response
? `${message.response.data.detail}..`
: message
? `Error:${message}`
: "Something is very wrong"
: message;
chakraToast({
position: "bottom",
title: userTitle,
description: userMessage,
status: type,
duration: 3000,
render: () => (
<Box
shadow="rgba(0, 0, 0, 0.1) 0px 10px 15px -3px, rgba(0, 0, 0, 0.05) 0px 4px 6px -2px;"
m={3}
p={3}
color="white.100"
bg={background}
>
{userMessage}
</Box>
),
});
},
[chakraToast]

Wyświetl plik

@ -0,0 +1,53 @@
import useToast from "./useToast";
import { useMutation } from "react-query";
import { AuthService } from "../services";
const useTokens = () => {
const toast = useToast();
const {
mutate: list,
isLoading,
error,
data,
} = useMutation(AuthService.getTokenList);
const { mutate: revoke } = useMutation(AuthService.revokeToken, {
onSuccess: () => {
toast("Token destroyed", "success");
list();
},
onError: (error) => {
toast(error, "error");
},
});
const { mutate: update } = useMutation(AuthService.updateToken, {
onSuccess: () => {
list();
},
onError: (error) => {
toast(error, "error");
},
});
const createToken = useMutation(AuthService.login, {
onSuccess: () => {
list();
toast("Created new token", "success");
},
onError: (error) => {
toast(error, "error");
},
});
return {
createToken,
list,
update,
revoke,
isLoading,
data,
error,
};
};
export default useTokens;

Wyświetl plik

@ -3,11 +3,13 @@ import { http } from "../utils";
const API_URL = process.env.NEXT_PUBLIC_MOONSTREAM_API_URL;
export const AUTH_URL = `${API_URL}/users`;
export const login = ({ username, password }) => {
export const login = ({ username, password, token_note }) => {
const data = new FormData();
data.append("username", username);
data.append("password", password);
if (token_note) {
data.append("token_note", token_note);
}
return http({
method: "POST",
url: `${AUTH_URL}/token`,
@ -74,3 +76,28 @@ export const changePassword = ({ currentPassword, newPassword }) => {
data,
});
};
export const getTokenList = () => {
return http({
method: "GET",
url: `${AUTH_URL}/tokens`,
});
};
export const updateToken = ({ note, token }) => {
const data = new FormData();
data.append("token_note", note);
data.append("access_token", token);
return http({
method: "PUT",
url: `${AUTH_URL}/token`,
data,
});
};
export const revokeToken = (token) => {
return http({
method: "POST",
url: `${AUTH_URL}/revoke/${token}`,
});
};

Wyświetl plik

@ -45,7 +45,7 @@ const RootLayout = (props) => {
minH={["6.5rem", "4.5rem", "3rem", null]}
h={["6.5rem", "4.5rem", "3rem", null]}
placeContent="center"
bgColor="suggested.900"
bgColor="green.900"
boxShadow="md"
position="relative"
className="banner"
@ -54,15 +54,12 @@ const RootLayout = (props) => {
{" "}
<Text
fontWeight="600"
textColor="primary.900"
textColor="blue.900"
fontSize={["sm", "sm", "md", null]}
>
Join early. Our first 1000 users get free lifetime access to
blockchain analytics. Contact our team on{" "}
<Link
href={"https://discord.gg/V3tWaP36"}
color="secondary.900"
>
<Link href={"https://discord.gg/V3tWaP36"} color="orange.900">
Discord
</Link>
</Text>
@ -73,7 +70,7 @@ const RootLayout = (props) => {
top="0"
right="0"
icon={<CloseIcon />}
colorScheme="primary"
colorScheme="blue"
variant="ghost"
onClick={() => setShowBanner(false)}
/>