cleanup and landing page w background img

pull/40/head
Tim Pechersky 2021-08-02 19:42:31 +08:00
rodzic a82267abd6
commit 4706217332
61 zmienionych plików z 1148 dodań i 1511 usunięć

Wyświetl plik

@ -2,7 +2,5 @@ module.exports = {
reactStrictMode: true,
target: "serverless",
trailingSlash: true,
presets: [
require.resolve('next/babel')
]
};
presets: [require.resolve("next/babel")],
};

Wyświetl plik

@ -4,9 +4,10 @@
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build": "next build && next export -o build",
"start": "next start",
"lint": "next lint"
"lint": "eslint ./ --ext js,jsx,ts,tsx --fix",
"pretty": "prettier --write \"./**/*.{js,jsx,json}\""
},
"dependencies": {
"@chakra-ui/icons": "^1.0.14",

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import FourOThree from "../src/components/FourOThree";
const Page403 = () => {

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import FourOFour from "../src/components/FourOFour";
const Page404 = () => {

Wyświetl plik

@ -1,6 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import Document, { Html, Head, Main, NextScript } from "next/document";
export default class MyDocument extends Document {

Wyświetl plik

@ -1,13 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
type Data = {
name: string
}
export default function handler(
req: NextApiRequest,
res: NextApiResponse<Data>
) {
res.status(200).json({ name: 'John Doe' })
}

Wyświetl plik

@ -1,116 +1,118 @@
import React, { useState, useEffect, Suspense, useContext } from "react";
import React, { useEffect, Suspense, useContext, useState } from "react";
import {
Flex,
Heading,
Text,
Box,
Image,
Image as ChakraImage,
Button,
useBreakpointValue,
Center,
Fade,
chakra,
Stack,
Link,
SimpleGrid,
useMediaQuery,
} from "@chakra-ui/react";
import { Grid, GridItem } from "@chakra-ui/react";
import { useUser, useAnalytics, useModals, useRouter } from "../src/core/hooks";
import { getLayout } from "../src/layouts";
import SplitWithImage from "../src/components/SplitWithImage";
import {
IoAnalyticsSharp,
IoLogoBitcoin,
IoSearchSharp,
} from "react-icons/io5";
import ConnectedButtons from "../src/components/ConnectedButtons";
import UIContext from "../src/core/providers/UIProvider/context";
import { MIXPANEL_PROPS } from "../src/core/providers/AnalyticsProvider/constants";
import { FaFileContract } from "react-icons/fa";
import { RiDashboardFill } from "react-icons/ri";
import {
GiMeshBall,
GiLogicGateXor,
GiSuspicious,
GiHook,
} from "react-icons/gi";
import { AiFillApi } from "react-icons/ai";
import { BiTransfer } from "react-icons/bi";
import { IoTelescopeSharp } from "react-icons/io5";
const HEADING_PROPS = {
fontWeight: "700",
fontSize: ["4xl", "5xl", "4xl", "5xl", "6xl", "7xl"],
};
const TRIPLE_PICS_PROPS = {
fontSize: ["1xl", "2xl", "2xl", "2xl", "3xl", "3xl"],
textAlign: "center",
fontWeight: "600",
py: 4,
};
const TRIPLE_PICS_TEXT = {
fontSize: ["lg", "xl", "xl", "xl", "2xl", "3xl"],
textAlign: "center",
fontWeight: "400",
mb: ["2rem", "2rem", "0", null, "0"],
};
const CARD_CONTAINER = {
className: "CardContainer",
w: "100%",
mx: [0, 0, "2rem", null, "4rem"],
alignSelf: ["center", null, "flex-start"],
};
const IMAGE_CONTAINER = {
className: "ImageContainer",
// objectFit: "contain",
h: ["10rem", null],
// h: ["10rem", "14rem", "14rem", "15rem", "18rem", "20rem"],
justifyContent: "center",
};
const AWS_PATH =
"https://s3.amazonaws.com/static.simiotics.com/moonstream/assets";
const assets = {
background: `https://s3.amazonaws.com/static.simiotics.com/landing/landing-background-2.png`,
aviator: `https://s3.amazonaws.com/static.simiotics.com/landing/aviator-2.svg`,
icon1: `${AWS_PATH}/Image+1.png`,
icon2: `${AWS_PATH}/Image+2.png`,
icon3: `${AWS_PATH}/Image+3.png`,
icon4: `${AWS_PATH}/Image+4.png`,
icon5: `${AWS_PATH}/Image+5.png`,
icon6: `${AWS_PATH}/Image+6.png`,
background720: `${AWS_PATH}/background720.png`,
background1920: `${AWS_PATH}/background720.png`,
background2880: `${AWS_PATH}/background720.png`,
background3840: `${AWS_PATH}/background720.png`,
minedTransactions: `${AWS_PATH}/Ethereum+mined+transactions.png`,
pendingTransactions: `${AWS_PATH}/Ethereum+pending+transactions.png`,
priceInformation: `${AWS_PATH}/Price+information.png`,
socialMediaPosts: `${AWS_PATH}/Social+media+posts.png`,
algorithmicFunds: `${AWS_PATH}/algorithmic+funds.png`,
cryptoTraders: `${AWS_PATH}/crypto+traders.png`,
smartDevelopers: `${AWS_PATH}/smart+contract+developers.png`,
};
const Homepage = () => {
const ui = useContext(UIContext);
const [background, setBackground] = useState("background720");
const [backgroundLoaded720, setBackgroundLoaded720] = useState(false);
const [backgroundLoaded1920, setBackgroundLoaded1920] = useState(false);
const [backgroundLoaded2880, setBackgroundLoaded2880] = useState(false);
const [backgroundLoaded3840, setBackgroundLoaded3840] = useState(false);
const router = useRouter();
const buttonSize = useBreakpointValue({
base: "md",
sm: "md",
md: "md",
lg: "lg",
xl: "xl",
"2xl": "xl",
});
const ButtonRadius = "2xl";
const buttonWidth = ["100%", "100%", "40%", "45%", "45%", "45%"];
const buttonMinWidth = "10rem";
const { isInit } = useUser();
const { withTracking, MIXPANEL_EVENTS } = useAnalytics();
const { MIXPANEL_EVENTS, track } = useAnalytics();
const { toggleModal } = useModals();
const [scrollDepth, setScrollDepth] = useState(0);
const [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
] = useMediaQuery([
"(min-width: 720px)",
"(min-width: 1920px)",
"(min-width: 2880px)",
"(min-width: 3840px)",
]);
const getScrollPrecent = ({ currentTarget }) => {
const scroll_level =
(100 * (currentTarget.scrollTop + currentTarget.clientHeight)) /
currentTarget.scrollHeight;
return scroll_level;
};
useEffect(() => {
assets["background720"] = `${AWS_PATH}/background720.png`;
assets["background2880"] = `${AWS_PATH}/background2880.png`;
assets["background3840"] = `${AWS_PATH}/background3840.png`;
}, []);
const handleScroll = (e) => {
const currentScroll = Math.ceil(getScrollPrecent(e) / 10);
if (currentScroll > scrollDepth) {
withTracking(
setScrollDepth(currentScroll),
MIXPANEL_EVENTS.HOMEPAGE_SCROLL_DEPTH,
scrollDepth
);
useEffect(() => {
console.log(
"isLargerChanged, ",
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
backgroundLoaded720,
backgroundLoaded1920,
backgroundLoaded2880,
backgroundLoaded3840
);
if (isLargerThan3840px && backgroundLoaded3840) {
setBackground("background3840");
} else if (isLargerThan2880px && backgroundLoaded2880) {
setBackground("background2880");
} else if (isLargerThan1920px && backgroundLoaded1920) {
setBackground("background1920");
} else {
setBackground("background720");
}
};
}, [
isLargerThan720px,
isLargerThan1920px,
isLargerThan2880px,
isLargerThan3840px,
backgroundLoaded720,
backgroundLoaded1920,
backgroundLoaded2880,
backgroundLoaded3840,
]);
useEffect(() => {
if (
@ -118,19 +120,53 @@ const Homepage = () => {
router.nextRouter.asPath.slice(0, 2) !== "/?" &&
router.nextRouter.asPath.slice(0, 2) !== "/#"
) {
console.log("replacing!");
router.replace(router.nextRouter.asPath, undefined, {
shallow: true,
});
}
}, [isInit, router]);
useEffect(() => {
console.log("rerender check");
const imageLoader720 = new Image();
imageLoader720.src = `${AWS_PATH}/background720.png`;
imageLoader720.onload = () => {
setBackgroundLoaded720(true);
};
const imageLoader1920 = new Image();
imageLoader1920.src = `${AWS_PATH}/background1920.png`;
imageLoader1920.onload = () => {
setBackgroundLoaded1920(true);
};
const imageLoader2880 = new Image();
imageLoader2880.src = `${AWS_PATH}/background2880.png`;
imageLoader2880.onload = () => {
setBackgroundLoaded2880(true);
};
const imageLoader3840 = new Image();
imageLoader3840.src = `${AWS_PATH}/background3840.png`;
imageLoader3840.onload = () => {
setBackgroundLoaded3840(true);
};
}, []);
console.log("backgroundLoaded", background);
return (
<Fade in>
<Box
onLo
width="100%"
flexDirection="column"
onScroll={(e) => handleScroll(e)}
sx={{ scrollBehavior: "smooth" }}
// bgColor="primary.1900"
// backgroundImage={`url(${assets["background"]})`}
// backgroundImage={`url(https://cdn3.vectorstock.com/i/1000x1000/75/62/moon-landscape-game-background-vector-24977562.jpg)`}
bgSize="cover"
>
<Flex
direction="column"
@ -138,22 +174,43 @@ const Homepage = () => {
position="relative"
w="100%"
overflow="initial"
pt={0}
>
<Suspense fallback={""}></Suspense>
<Grid templateColumns="repeat(12,1fr)">
<GridItem px="0" colSpan="12" pb={[1, 2, null, 8]}>
<chakra.header>
<Grid
templateColumns="repeat(12,1fr)"
mt={0}
border="none"
boxSizing="content-box"
>
<GridItem
mt={0}
px="0"
colSpan="12"
pb={[1, 2, null, 8]}
minH="100vh"
// bgColor="primary.1200"
>
<chakra.header boxSize="full">
<Box
w="full"
h="container.sm"
backgroundImage={`url(${assets["background"]})`}
bgPos="center"
// h="100%"
// w="full"
// transition=""
// bgPos={["initial", "initial", "center", null, "center"]}
bgPos="bottom"
backgroundImage={`url(${assets[`${background}`]})`}
bgSize="cover"
boxSize="full"
// bgP
// h="container.sm"
// h={backgroundH}
// minH="100vh"
// minH="auto"
>
<Flex
align="center"
pos="relative"
// pos="relative"
justify="center"
boxSize="full"
// bg="blackAlpha.700"
@ -162,14 +219,16 @@ const Homepage = () => {
textAlign="center"
alignItems="center"
spacing={6}
maxW="1220px"
maxW="1620px"
px="7%"
h="100%"
pt={["10vh", null, "30vh"]}
>
<Heading
size="xl"
size="2xl"
fontWeight="semibold"
color="white"
textTransform="uppercase"
// textTransform="uppercase"
>
{/* <LoadingDots isActive> */}
All the crypto data you care about in a single stream
@ -177,6 +236,7 @@ const Homepage = () => {
</Heading>
<chakra.span
my={12}
fontSize={["lg", null, "xl"]}
display="inline-block"
color="primary.200"
textDecor="underline"
@ -186,6 +246,7 @@ const Homepage = () => {
pool to Elon Musks latest tweets.
</chakra.span>
<chakra.span
fontSize={["lg", null, "xl"]}
display="inline-block"
color="primary.300"
textDecor="underline"
@ -203,8 +264,9 @@ const Homepage = () => {
colSpan="12"
pt={["20px", "20px", "100px", null, "120px"]}
pb={["20px", "56px", null, "184px"]}
bgSize="cover"
bgImage={`url(${assets["background"]})`}
minH="100vh"
// bgSize="cover"
// bgImage={`url(${assets["background"]})`}
>
<Heading
{...HEADING_PROPS}
@ -214,91 +276,59 @@ const Homepage = () => {
Data you can add to your stream:
</Heading>
<Flex
direction={["column", null, "row"]}
flexWrap="nowrap"
justifyContent={["center", null, "space-evenly"]}
<SimpleGrid
columns={[1, 2, 2, 4, null, 4]}
// overflowY="clip"
// direction={["column", null, "row"]}
// flexWrap="nowrap"
// justifyContent={["center", null, "space-evenly"]}
>
<Box {...CARD_CONTAINER}>
<Flex {...IMAGE_CONTAINER}>
<Image
objectFit="contain"
src={assets["icon2"]}
alt="privacy is our prioriy"
/>
</Flex>
<Heading {...TRIPLE_PICS_PROPS}>
<Stack spacing={1} px={1} alignItems="center">
<ChakraImage
boxSize={["220px", "220px", "xs", null, "xs"]}
objectFit="contain"
src={assets["minedTransactions"]}
alt="mined transactions"
/>
<Heading textAlign="center ">
Ethereum mined transactions
</Heading>
<Text {...TRIPLE_PICS_TEXT}></Text>
</Box>
<Box {...CARD_CONTAINER}>
<Flex {...IMAGE_CONTAINER}>
<Image
objectFit="contain"
src={assets["icon1"]}
alt="live metrics"
/>
</Flex>
<Heading {...TRIPLE_PICS_PROPS}>
</Stack>
<Stack spacing={1} px={1} alignItems="center">
<ChakraImage
boxSize={["220px", "220px", "xs", null, "xs"]}
objectFit="contain"
src={assets["pendingTransactions"]}
alt="mined transactions"
/>
<Heading textAlign="center ">
Ethereum pending transactions
</Heading>
<Text {...TRIPLE_PICS_TEXT}></Text>
</Box>
<Box {...CARD_CONTAINER}>
<Flex {...IMAGE_CONTAINER}>
<Image
objectFit="contain"
src={assets["icon1"]}
alt="live metrics"
/>
</Flex>
<Heading {...TRIPLE_PICS_PROPS}>
Centralized exchanges
</Heading>
<Text {...TRIPLE_PICS_TEXT}></Text>
</Box>
<Box {...CARD_CONTAINER}>
<Flex {...IMAGE_CONTAINER}>
<Image
objectFit="contain"
src={assets["icon3"]}
alt="we make it simple for user"
/>
</Flex>
<Heading {...TRIPLE_PICS_PROPS}>Social media posts</Heading>
<Text {...TRIPLE_PICS_TEXT}></Text>
</Box>
</Flex>
{/* <Text
textAlign="center"
fontSize={["xl", "2xl", "2xl", "3xl", "4xl", "5xl"]}
fontWeight="600"
pt={[4, null, 12]}
>
We currently support Python, Javascript and Go!
<br />
Want us to support other programming languages?{" "}
<Button
size="2xl"
colorScheme="primary"
variant="link"
onClick={() => toggleModal("Integration")}
>
Let us know
</Button>
</Text> */}
</GridItem>
<GridItem
px={["7%", "12px", "7%", null, "7%"]}
colSpan="12"
pb={[1, 2, null, 8]}
pt="5.125rem"
mb="66px"
bgGradient="linear-gradient(to bottom, #e9eaf4, #efeff7, #f4f4f9, #fafafc, #ffffff)"
borderRadius="md"
>
</Stack>
<Stack spacing={1} px={1} alignItems="center">
<ChakraImage
boxSize={["220px", "220px", "xs", null, "xs"]}
objectFit="contain"
src={assets["priceInformation"]}
alt="mined transactions"
/>
<Heading textAlign="center ">Centralized exchanges</Heading>
</Stack>
<Stack spacing={1} px={1} alignItems="center">
<ChakraImage
boxSize={["220px", "220px", "xs", null, "xs"]}
objectFit="contain"
src={assets["socialMediaPosts"]}
alt="mined transactions"
/>
<Heading textAlign="center ">Social media posts</Heading>
</Stack>
</SimpleGrid>
<Center>
<Heading pt="160px" pb="60px">
Moonstream is ment for you if
</Heading>
</Center>
<Flex
w="100%"
direction={["column", "row", "column", null, "column"]}
@ -312,17 +342,29 @@ const Homepage = () => {
button1={{
label: "Crypto trader",
link: "/#cryptoTrader",
onClick: null,
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to CryptoTrader`,
});
},
}}
button2={{
label: "Algorithmic Fund",
link: "/#algoFund",
onClick: null,
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to AlgoFund`,
});
},
}}
button3={{
label: "Developer",
link: "/#smartDeveloper",
onClick: null,
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `scroll to Developer`,
});
},
}}
/>
</Flex>
@ -336,8 +378,15 @@ const Homepage = () => {
minH={ui.isMobileView ? "100vh" : null}
>
<SplitWithImage
// cta={"Trader early access"}
cta={"I want early access!"}
cta={{
label: "I want early access!",
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Crypto trader`,
});
toggleModal("hubspot-trader");
},
}}
elementName={"element1"}
colorScheme="suggested"
badge={`For crypto traders`}
@ -346,25 +395,25 @@ const Homepage = () => {
bullets={[
{
text: `Subscribe to the defi contracts you care about`,
icon: IoLogoBitcoin,
icon: FaFileContract,
color: "suggested.50",
bgColor: "suggested.900",
},
{
text: `Make sense of how others are calling these contracts using Moonstream dashboards.
`,
icon: IoAnalyticsSharp,
icon: RiDashboardFill,
color: "suggested.50",
bgColor: "suggested.900",
},
{
text: `Get data directly from the transaction pool through our global network of Ethereum nodes`,
icon: IoSearchSharp,
icon: GiMeshBall,
color: "suggested.50",
bgColor: "suggested.900",
},
]}
imgURL={assets["icon2"]}
imgURL={assets["cryptoTraders"]}
/>
</GridItem>
<GridItem
@ -376,37 +425,40 @@ const Homepage = () => {
minH={ui.isMobileView ? "100vh" : null}
>
<SplitWithImage
// cta={"Algoritmic fund early access"}
cta={"I want early access!"}
cta={{
label: "I want early access!",
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: Algo fund`,
});
toggleModal("hubspot-fund");
},
}}
elementName={"element2"}
mirror={true}
colorScheme="secondary"
badge={`For algorithmic funds`}
// title={`Get API access to your stream`}
// body={`Specify actions.
// Something happens on blockchain and we automatically execute for them.
// Algorithmic trading on the blockchain`}
bullets={[
{
text: `Get API access to your stream`,
icon: IoLogoBitcoin,
icon: AiFillApi,
color: "secondary.50",
bgColor: "secondary.900",
},
{
text: `Set conditions that trigger predefined actions`,
icon: IoAnalyticsSharp,
icon: GiLogicGateXor,
color: "secondary.50",
bgColor: "secondary.900",
},
{
text: `Execute transactions directly on Moonstream nodes`,
icon: IoSearchSharp,
icon: BiTransfer,
color: "secondary.50",
bgColor: "secondary.900",
},
]}
imgURL={assets["icon3"]}
imgURL={assets["algorithmicFunds"]}
/>
</GridItem>
<GridItem
@ -418,36 +470,39 @@ const Homepage = () => {
minH={ui.isMobileView ? "100vh" : null}
>
<SplitWithImage
// cta={"Developer early access"}
cta={"I want early access!"}
cta={{
label: "I want early access!",
onClick: () => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Early access CTA: developer`,
});
toggleModal("hubspot-developer");
},
}}
elementName={"element3"}
colorScheme="primary"
badge={`For smart contract developers`}
// title={`Learn how people use your smart contracts`}
// body={`
// Connect decentralized application with centralized application
// Creat Blockchain based web hooks and get full visibility of your smart contracts`}
bullets={[
{
text: `See how people use your smart contracts`,
icon: IoLogoBitcoin,
icon: IoTelescopeSharp,
color: "primary.50",
bgColor: "primary.900",
},
{
text: `Set up alerts on suspicious activity`,
icon: IoAnalyticsSharp,
icon: GiSuspicious,
color: "primary.50",
bgColor: "primary.900",
},
{
text: `Register webhooks to connect your off-chain infrastructure`,
icon: IoSearchSharp,
icon: GiHook,
color: "primary.50",
bgColor: "primary.900",
},
]}
imgURL={assets["icon6"]}
imgURL={assets["smartDevelopers"]}
/>
</GridItem>
<GridItem
@ -459,29 +514,26 @@ const Homepage = () => {
>
<Center>
<Button
as={Link}
isExternal
href={"https://discord.gg/FetK5BxD"}
size="lg"
variant="solid"
colorScheme="suggested"
id="test"
onClick={() => {
track(`${MIXPANEL_EVENTS.BUTTON_CLICKED}`, {
[`${MIXPANEL_PROPS.BUTTON_CLICKED}`]: `Join our discord`,
});
toggleModal("hubspot");
}}
>
Join our waitlist
Join our discord
</Button>
</Center>
</GridItem>
</Grid>
</Flex>
{/* <ConnectElements
selector=".MoonBadge"
overlay={100}
elements={[
{ from: ".element1", to: ".element2" },
{ from: ".element2", to: ".element3" },
// { from: ".element3", to: ".element4" },
// { from: ".element5", to: ".element4" },
// { from: ".element6", to: ".element4" },
// { from: ".element7", to: ".element4" },
]}
/> */}
</Box>
</Fade>
);

Wyświetl plik

@ -1,249 +0,0 @@
import React from "react";
import {
Box,
Stack,
HStack,
Heading,
Text,
VStack,
useColorModeValue,
List,
ListItem,
ListIcon,
Button,
} from "@chakra-ui/react";
import { FaCheckCircle } from "react-icons/fa";
import { getLayout } from "../src/layouts";
function PriceWrapper({ children }) {
return (
<Box
mb={4}
shadow="base"
borderWidth="1px"
alignSelf={{ base: "center", lg: "flex-start" }}
borderColor={useColorModeValue("gray.200", "gray.500")}
borderRadius={"xl"}
>
{children}
</Box>
);
}
const Pricing = (props) => {
return (
<Box py={12} minH="100vh">
<VStack spacing={2} textAlign="center">
<Heading as="h1" fontSize="4xl">
Plans that fit your need
</Heading>
<Text fontSize="lg" color={"gray.500"}>
Start with 14-day free trial. No credit card needed. Cancel at
anytime.
</Text>
</VStack>
<Stack
direction={{ base: "column", md: "row" }}
textAlign="center"
justify="center"
spacing={{ base: 4, lg: 10 }}
py={10}
>
<PriceWrapper>
<Box py={4} px={12}>
<Text fontWeight="500" fontSize="2xl">
Hobby
</Text>
<HStack justifyContent="center">
<Text fontSize="3xl" fontWeight="600">
$
</Text>
<Text fontSize="5xl" fontWeight="900">
79
</Text>
<Text fontSize="3xl" color="gray.500">
/month
</Text>
</HStack>
</Box>
<VStack
bg={useColorModeValue("gray.50", "gray.700")}
py={4}
borderBottomRadius={"xl"}
>
<List spacing={3} textAlign="start" px={12}>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
unlimited build minutes
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
Lorem, ipsum dolor.
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
5TB Lorem, ipsum dolor.
</ListItem>
</List>
<Box w="80%" pt={7}>
<Button w="full" colorScheme="primary" variant="outline">
Start trial
</Button>
</Box>
</VStack>
</PriceWrapper>
<PriceWrapper>
<Box position="relative">
<Box
position="absolute"
top="-16px"
left="50%"
style={{ transform: "translate(-50%)" }}
>
<Text
textTransform="uppercase"
bg={useColorModeValue("secondary.300", "secondary.700")}
px={3}
py={1}
color={useColorModeValue("white.900", "white.300")}
fontSize="sm"
fontWeight="600"
rounded="xl"
>
Most Popular
</Text>
</Box>
<Box py={4} px={12}>
<Text fontWeight="500" fontSize="2xl">
Growth
</Text>
<HStack justifyContent="center">
<Text fontSize="3xl" fontWeight="600">
$
</Text>
<Text fontSize="5xl" fontWeight="900">
149
</Text>
<Text fontSize="3xl" color="gray.500">
/month
</Text>
</HStack>
</Box>
<VStack
bg={useColorModeValue("gray.50", "gray.700")}
py={4}
borderBottomRadius={"xl"}
>
<List spacing={3} textAlign="start" px={12}>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
unlimited build minutes
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
Lorem, ipsum dolor.
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
5TB Lorem, ipsum dolor.
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
5TB Lorem, ipsum dolor.
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
5TB Lorem, ipsum dolor.
</ListItem>
</List>
<Box w="80%" pt={7}>
<Button w="full" colorScheme="suggested">
Start trial
</Button>
</Box>
</VStack>
</Box>
</PriceWrapper>
<PriceWrapper>
<Box py={4} px={12}>
<Text fontWeight="500" fontSize="2xl">
Scale
</Text>
<HStack justifyContent="center">
<Text fontSize="3xl" fontWeight="600">
$
</Text>
<Text fontSize="5xl" fontWeight="900">
349
</Text>
<Text fontSize="3xl" color="gray.500">
/month
</Text>
</HStack>
</Box>
<VStack
bg={useColorModeValue("gray.50", "gray.700")}
py={4}
borderBottomRadius={"xl"}
>
<List spacing={3} textAlign="start" px={12}>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
unlimited build minutes
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
Lorem, ipsum dolor.
</ListItem>
<ListItem>
<ListIcon as={FaCheckCircle} color="suggested.900" />
5TB Lorem, ipsum dolor.
</ListItem>
</List>
<Box w="80%" pt={7}>
<Button w="full" colorScheme="primary" variant="outline">
Start trial
</Button>
</Box>
</VStack>
</PriceWrapper>
</Stack>
</Box>
);
};
export async function getStaticProps() {
const metaTags = {
title: "Bugout: Measure the success of your dev tool",
description:
"Get usage metrics and crash reports. Improve your users' experience",
keywords:
"bugout, bugout-dev, bugout.dev, usage-metrics, analytics, dev-tool ,knowledge, docs, journal, entry, find-anything",
url: "https://bugout.dev",
image:
"https://s3.amazonaws.com/static.simiotics.com/landing/aviator-2.svg",
};
// const assetPreload = Object.keys(assets).map((key) => {
// return {
// rel: "preload",
// href: assets[key],
// as: "image",
// };
// });
// const preconnects = [
// { rel: "preconnect", href: "https://s3.amazonaws.com" },
// { rel: "preconnect", href: "https://assets.calendly.com/" },
// ];
// const preloads = assetPreload.concat(preconnects);
return {
props: { metaTags },
};
}
Pricing.getLayout = getLayout;
export default Pricing;

Wyświetl plik

@ -0,0 +1,574 @@
import React from "react";
import { Box, Heading, ListItem, Text, Link } from "@chakra-ui/react";
import { UnorderedList, OrderedList } from "@chakra-ui/react";
import { DEFAULT_METATAGS } from "../../src/components/constants";
export async function getStaticProps() {
return {
props: { metaTags: { ...DEFAULT_METATAGS } },
};
}
const TermsOfService = () => (
<Box>
<Box px="1.5rem" m="auto" mb={8} maxWidth="1199.98px" minHeight="60vh">
<Heading my={8} as="h1">
Moonstream.to Terms of Service
</Heading>
<Text fontSize="md">
Welcome to Bugout! Please read these Terms of Service before accessing
or using Bugout.
</Text>
<Heading mt={4}>Definitions</Heading>
<Text mt={4} fontSize="md">
<OrderedList>
<ListItem>
{`An "Account" represents your legal relationship with Simiotics, Inc.
A User Account represents an individual Users authorization to
log in to and use the Service and serves as a Users identity on
Bugout. Groups represent teams of users. A User Account can be a
member of any number of Groups.`}
</ListItem>
<ListItem>
{` The “Agreement” refers, collectively, to all the terms, conditions,
notices contained or referenced in this document (the Terms of
Service or the "Terms") and all other operating rules, policies
(including the Bugout.dev Privacy Statement) and procedures that we
may publish from time to time on the Website.`}
</ListItem>
<ListItem>
{` “Content” refers to content featured or displayed through the
Website, including without limitation code, text, data, articles,
images, photographs, graphics, software, applications, packages,
designs, features, and other materials that are available on the
Website or otherwise available through the Service. "Content" also
includes Services. User-Generated Content is Content, written or
otherwise, created or uploaded by our Users. "Your Content" is
Content that you create or own.`}
</ListItem>
<ListItem>
Bugout, Bugout.dev, Simiotics, We, and Us refer to
Simiotics, Inc., as well as our affiliates, directors, subsidiaries,
contractors, licensors, officers, agents, and employees.
</ListItem>
<ListItem>
The Service refers to the applications, software, products, and
services provided by Simiotics.
</ListItem>
<ListItem>
The User, You, and Your refer to the individual person,
company, or organization that has visited or is using the Website or
Service; that accesses or uses any part of the Account; or that
directs the use of the Account in the performance of its functions.
A User must be at least 13 years of age.
</ListItem>
<ListItem>
The Website refers to Bugouts website located at bugout.dev, and
all content, services, and products provided by Bugout at or through
the Website. It also refers to subdomains of bugout.dev, such as
blog.bugout.dev. Occasionally, websites owned by Bugout may provide
different or additional terms of service. If those additional terms
conflict with this Agreement, the more specific terms apply to the
relevant page or service.
</ListItem>
</OrderedList>
</Text>
<Heading mt={4}>Account Terms</Heading>
<Heading as="h3" mt={4} size="md">
Account Controls
</Heading>
<Text mt={4} fontSize="md">
Subject to these Terms, you retain ultimate administrative control over
your User Account and the Content within it.
</Text>
<Text mt={4} fontSize="md">
{` The "owner" of a Group that was created under these Terms has ultimate
administrative control over that Group and the Content within it. Within
the Service, an owner can manage User access to the Groups data and
projects. A Group may have multiple owners, but there must be at least
one User Account designated as an owner of a Group. If you are the owner
of an Group under these Terms, we consider you responsible for the
actions that are performed on or through that Group.`}
</Text>
<Heading as="h3" mt={4} size="md">
Required Information
</Heading>
<Text mt={4} fontSize="md">
You must provide a valid email address in order to complete the signup
process. Any other information requested, such as your real name, is
optional, unless you are accepting these terms on behalf of a legal
entity (in which case we need more information about the legal entity)
or if you opt for a paid Account, in which case additional information
will be necessary for billing purposes.
</Text>
<Heading as="h3" mt={4} size="md">
Account Requirements
</Heading>
<Text mt={4} fontSize="md">
{`We have a few simple rules for User Accounts on Bugout's Service. You
must be a human to create an Account. Accounts registered by "bots" or
other automated methods are not permitted.`}
</Text>
<Text mt={4} fontSize="md">
{`We do permit machine accounts. A machine account is an Account set up by
an individual human who accepts the Terms on behalf of the Account,
provides a valid email address, and is responsible for its actions. A
machine account is used exclusively for performing automated tasks.
Multiple users may direct the actions of a machine account, but the
owner of the Account is ultimately responsible for the machine's
actions. You may maintain no more than one free machine account in
addition to your free User Account.`}
</Text>
<Text mt={4} fontSize="md">
{`One person or legal entity may maintain no more than one free Account
(if you choose to control a machine account as well, that's fine, but it
can only be used for running a machine).`}
</Text>
<Text mt={4} fontSize="md">
You must be age 13 or older. If we learn of any User under the age of
13, we will terminate that Users Account immediately. If you are a
resident of a country outside the United States, your countrys minimum
age may be older; in such a case, you are responsible for complying with
your countrys laws.
</Text>
<Text mt={4} fontSize="md">
Your login may only be used by one person i.e., a single login may not
be shared by multiple people.
</Text>
<Text mt={4} fontSize="md">
A paid Group may only provide access to as many User Accounts as your
subscription allows.
</Text>
<Heading as="h3" mt={4} size="md">
User Account Security
</Heading>
<Text mt={4} fontSize="md">
You are responsible for keeping your Account secure while you use our
Service. The content of your Account and its security are up to you. You
are responsible for all content posted and activity that occurs under
your Account. You are responsible for maintaining the security of your
Account and password. Bugout cannot and will not be liable for any loss
or damage from your failure to comply with this security obligation.
</Text>
<Text mt={4} fontSize="md">
You will promptly notify Bugout if you become aware of any unauthorized
use of, or access to, our Service through your Account, including any
unauthorized use of your password or Account.
</Text>
<Heading mt={4}>Acceptable Use</Heading>
<Text mt={4} fontSize="md">
Your use of the Website and Service must not violate any applicable
laws, including copyright or trademark laws, export control or sanctions
laws, or other laws in your jurisdiction. You are responsible for making
sure that your use of the Service is in compliance with laws and any
applicable regulations.
</Text>
<Heading mt={4}>User-Generated Content</Heading>
<Heading as="h3" mt={4} size="md">
Responsibility for User-Generated Content
</Heading>
<Text mt={4} fontSize="md">
You may create or upload User-Generated Content while using the Service.
You are solely responsible for the content of, and for any harm
resulting from, any User-Generated Content that you post, upload, link
to or otherwise make available via the Service, regardless of the form
of that Content. We are not responsible for any public display or misuse
of your User-Generated Content.
</Text>
<Heading as="h3" mt={4} size="md">
Bugout May Remove Content
</Heading>
<Text mt={4} fontSize="md">
We have the right to refuse or remove any User-Generated Content that,
in our sole discretion, violates any laws or Bugout terms or policies.
</Text>
<Heading as="h3" mt={4} size="md">
Ownership of Content, Right to Post, and License Grants
</Heading>
<Text mt={4} fontSize="md">
{`You retain ownership of and responsibility for Your Content. If you're
posting anything you did not create yourself or do not own the rights
to, you agree that you are responsible for any Content you post; that
you will only submit Content that you have the right to post; and that
you will fully comply with any third party licenses relating to Content
you post.`}
</Text>
<Text mt={4} fontSize="md">
Because you retain ownership of and responsibility for Your Content, we
need you to grant us and other Bugout Users certain legal
permissions. These license grants apply to Your Content. If you upload
Content that already comes with a license granting Bugout the
permissions we need to run our Service, no additional license is
required. You understand that you will not receive any payment for any
of these granted rights. The licenses you grant to us will end when you
remove Your Content from our servers, unless other Users have cloned it.
</Text>
<Text as="h3" mt={4} size="md">
License Grant to Us
</Text>
<Text mt={4} fontSize="md">
We need the legal right to do things like host Your Content, publish it,
and share it. You grant us and our legal successors the right to store,
archive, parse, and display Your Content, and make incidental copies, as
necessary to provide the Service, including improving the Service over
time. This license includes the right to do things like copy it to our
database and make backups; show it to you and other users; parse it into
a search index or otherwise analyze it on our servers; share it with
other users; and perform it, in case Your Content is something like
music or video. This license does not grant Bugout the right to sell
Your Content. It also does not grant Bugout the right to otherwise
distribute or use Your Content outside of our provision of the Service.
</Text>
<Heading as="h3" mt={4} size="md">
License Grant to Other Users
</Heading>
<Text mt={4} fontSize="md">
{`Any User-Generated Content you post publicly may be viewed by others. By
setting your content to be viewed publicly, you agree to allow others to
view and "clone" your content (this means that others may make their own
copies of Your Content). If you set your Content to be viewed publicly,
you grant each User of Bugout a nonexclusive, worldwide license to use,
display, and perform Your Content through the Bugout Service and to
reproduce Your Content solely on Bugout as permitted through Bugout's
functionality (for example, through cloning). If you are uploading
Content you did not create or own, you are responsible for ensuring that
the Content you upload is licensed under terms that grant these
permissions to other Bugout Users.`}
</Text>
<Heading as="h3" mt={4} size="md">
Moral Rights
</Heading>
<Text mt={4} fontSize="md">
You retain all moral rights to Your Content that you upload, publish, or
submit to any part of the Service, including the rights of integrity and
attribution. However, you waive these rights and agree not to assert
them against us, to enable us to reasonably exercise the rights granted
above, but not otherwise.
</Text>
<Text mt={4} fontSize="md">
To the extent this agreement is not enforceable by applicable law, you
grant Bugout the rights we need to use Your Content without attribution
and to make reasonable adaptations of Your Content as necessary to
render the Website and provide the Service.
</Text>
<Heading mt={4}>Private Content</Heading>
<Heading as="h3" mt={4} size="md">
Control of Private Content
</Heading>
<Text mt={4} fontSize="md">
Some Accounts may have private content -- for example, groups or
journals -- which allow the User to control access to Content.
</Text>
<Heading as="h3" mt={4} size="md">
Confidentiality of Private Content
</Heading>
<Text mt={4} fontSize="md">
Bugout considers private content to be confidential to you. Bugout will
protect the contents of private repositories from unauthorized use,
access, or disclosure in the same manner that we would use to protect
our own confidential information of a similar nature and in no event
with less than a reasonable degree of care.
</Text>
<Heading as="h3" mt={4} size="md">
Access
</Heading>
<Text mt={4} fontSize="md">
Bugout personnel may only access the content of your private content in
the situations described in our{" "}
<Link color="primary.600" href="/privacy-policy">
Privacy Policy
</Link>
.
</Text>
<Text mt={4} fontSize="md">
Additionally, we may be compelled by law to disclose your private
content.
</Text>
<Heading mt={4}>Intellectual Property Notice</Heading>
<Heading as="h3" mt={4} size="md">
{`Bugout's Rights to Content`}
</Heading>
<Text mt={4} fontSize="md">
Bugout and our licensors, vendors, agents, and/or our content providers
retain ownership of all intellectual property rights of any kind related
to the Website and Service. We reserve all rights that are not expressly
granted to you under this Agreement or by law.
</Text>
<Heading mt={4}>API Terms</Heading>
<Text mt={4} fontSize="md">
{`Abuse or excessively frequent requests to Bugout via the API may result
in the temporary or permanent suspension of your Account's access to the
API. Bugout, in our sole discretion, will determine abuse or excessive
usage of the API. We will make a reasonable attempt to warn you via
email prior to suspension.`}
</Text>
<Text mt={4} fontSize="md">
{`You may not share API tokens to exceed Bugout's rate limitations.`}
</Text>
<Text mt={4} fontSize="md">
{`You may not use the API to download data or Content from Bugout for
spamming purposes, including for the purposes of selling Bugout users'
personal information, such as to recruiters, headhunters, and job
boards.`}
</Text>
<Text mt={4} fontSize="md">
All use of the Bugout API is subject to these Terms of Service and the
Bugout{" "}
<Link color="primary.600" href="/privacy-policy">
Privacy Policy
</Link>
.
</Text>
<Text mt={4} fontSize="md">
{`Bugout may offer subscription-based access to our API for those Users
who require high- throughput access or access that would result in
resale of Bugout's Service.`}
</Text>
<Heading mt={4}>Payment</Heading>
<Heading as="h3" mt={4} size="md">
Pricing
</Heading>
<Text mt={4} fontSize="md">
If you agree to a subscription price, that will remain your price for
the duration of the payment term; however, prices are subject to change
at the end of a payment term.
</Text>
<Heading as="h3" mt={4} size="md">
Authorization
</Heading>
<Text mt={4} fontSize="md">
By agreeing to these Terms, you are giving us permission to charge your
on-file credit card, PayPal account, or other approved methods of
payment for fees that you authorize for Bugout.
</Text>
<Heading as="h3" mt={4} size="md">
Responsibility for Payment
</Heading>
<Text mt={4} fontSize="md">
You are responsible for all fees, including taxes, associated with your
use of the Service. By using the Service, you agree to pay Bugout any
charge incurred in connection with your use of the Service. If you
dispute the matter, contact us. You are responsible for providing us
with a valid means of payment for paid Accounts. Free Accounts are not
required to provide payment information.
</Text>
<Heading mt={4}>Cancellation and Termination</Heading>
<Heading as="h3" mt={4} size="md">
Account Cancellation
</Heading>
<Text mt={4} fontSize="md">
It is your responsibility to properly cancel your Account with Bugout.
You can cancel your Account at any time by contacting us by email
(neeraj@simiotics.com).
</Text>
<Heading as="h3" mt={4} size="md">
Upon Cancellation
</Heading>
<Text mt={4} fontSize="md">
We will retain and use your information as necessary to comply with our
legal obligations, resolve disputes, and enforce our agreements, but
barring legal requirements, we will delete your full profile and the
Content of your repositories within 90 days of cancellation or
termination (though some information may remain in encrypted backups).
This information can not be recovered once your Account is cancelled.
</Text>
<Text mt={4} fontSize="md">
We will not delete Content that you have contributed to Groups or that
other Users have cloned.
</Text>
<Text mt={4} fontSize="md">
Upon request, we will make a reasonable effort to provide an Account
owner with a copy of your lawful, non-infringing Account contents after
Account cancellation, termination, or downgrade.
</Text>
<Text mt={4} fontSize="md">
You must make this request within 90 days of cancellation, termination,
or downgrade.
</Text>
<Heading as="h3" mt={4} size="md">
Bugout May Terminate
</Heading>
<Text mt={4} fontSize="md">
Bugout has the right to suspend or terminate your access to all or any
part of the Website at any time, with or without cause, with or without
notice, effective immediately.
</Text>
<Text mt={4} fontSize="md">
Bugout reserves the right to refuse service to anyone for any reason at
any time.
</Text>
<Heading as="h3" mt={4} size="md">
Survival
</Heading>
<Text mt={4} fontSize="md">
All provisions of this Agreement which, by their nature, should survive
termination will survive termination including, without limitation:
ownership provisions, warranty disclaimers, indemnity, and limitations
of liability.
</Text>
<Heading mt={4}>Communications with Bugout</Heading>
<Text mt={4} fontSize="md">
For contractual purposes, you (1) consent to receive communications from
us in an electronic form via the email address you have submitted or via
the Service; and (2) agree that all Terms of Service, agreements,
notices, disclosures, and other communications that we provide to you
electronically satisfy any legal requirement that those communications
would satisfy if they were on paper. This section does not affect your
non-waivable rights.
</Text>
<Heading mt={4}>Disclaimer of Warranties</Heading>
<Text mt={4} fontSize="md">
Bugout provides the Website and the Service as is and as available,
without warranty of any kind. Without limiting this, we expressly
disclaim all warranties, whether express, implied or statutory,
regarding the Website and the Service including without limitation any
warranty of merchantability, fitness for a particular purpose, title,
security, accuracy and non-infringement.
</Text>
<Text mt={4} fontSize="md">
Bugout does not warrant that the Service will meet your requirements;
that the Service will be uninterrupted, timely, secure, or error-free;
that the information provided through the Service is accurate, reliable
or correct; that any defects or errors will be corrected; that the
Service will be available at any particular time or location; or that
the Service is free of viruses or other harmful components. You assume
full responsibility and risk of loss resulting from your downloading
and/or use of files, information, content or other material obtained
from the Service.
</Text>
<Heading mt={4}>Limitation of Liability</Heading>
<Text mt={4} fontSize="md">
You understand and agree that we will not be liable to you or any third
party for any loss of profits, use, goodwill, or data, or for any
incidental, indirect, special, consequential or exemplary damages,
however arising, that result from the use, disclosure, or display of
your:
<UnorderedList pl={3}>
<ListItem>User-Generated Content;</ListItem>
<ListItem>your use or inability to use the Service;</ListItem>
<ListItem>
any modification, price change, suspension or discontinuance of the
Service;
</ListItem>
<ListItem>
the Service generally or the software or systems that make the
Service available;
</ListItem>
<ListItem>
unauthorized access to or alterations of your transmissions or data;
</ListItem>
<ListItem>
statements or conduct of any third party on the Service;
</ListItem>
<ListItem>
any other user interactions that you input or receive through your
use of the Service;
</ListItem>
<ListItem>or any other matter relating to the Service.</ListItem>
</UnorderedList>
</Text>
<Text mt={4} fontSize="md">
Our liability is limited whether or not we have been informed of the
possibility of such damages, and even if a remedy set forth in this
Agreement is found to have failed of its essential purpose. We will have
no liability for any failure or delay due to matters beyond our
reasonable control.
</Text>
<Heading mt={4}>Release and Indemnification</Heading>
<Text mt={4} fontSize="md">
If you have a dispute with one or more Users, you agree to release
Bugout from any and all claims, demands and damages (actual and
consequential) of every kind and nature, known and unknown, arising out
of or in any way connected with such disputes.
</Text>
<Text mt={4} fontSize="md">
You agree to indemnify us, defend us, and hold us harmless from and
against any and all claims, liabilities, and expenses, including
attorneys fees, arising out of your use of the Website and the Service,
including but not limited to your violation of this Agreement, provided
that Bugout (1) promptly gives you written notice of the claim, demand,
suit or proceeding; (2) gives you sole control of the defense and
settlement of the claim, demand, suit or proceeding (provided that you
may not settle any claim, demand, suit or proceeding unless the
settlement unconditionally releases Bugout of all liability); and (3)
provides to you all reasonable assistance, at your expense.
</Text>
<Heading mt={4}>Changes to These Terms</Heading>
<Text mt={4} fontSize="md">
{`We reserve the right, at our sole discretion, to amend these Terms of
Service at any time and will update these Terms of Service in the event
of any such amendments. We will notify our Users of material changes to
this Agreement, such as price increases, at least 30 days prior to the
change taking effect by posting a notice on our Website or sending email
to the primary email address specified in your Bugout account.
Customer's continued use of the Service after those 30 days constitutes
agreement to those revisions of this Agreement. For any other
modifications, your continued use of the Website constitutes agreement
to our revisions of these Terms of Service.`}
</Text>
<Heading mt={4}>Miscellaneous</Heading>
<Heading as="h3" mt={4} size="md">
Governing Law
</Heading>
<Text mt={4} fontSize="md">
Except to the extent applicable law provides otherwise, this Agreement
between you and Bugout and any access to or use of the Website or the
Service are governed by the federal laws of the United States of America
and the laws of the State of California, without regard to conflict of
law provisions. You and Bugout agree to submit to the exclusive
jurisdiction and venue of the courts located in the City and County of
San Francisco, California.
</Text>
<Heading as="h3" mt={4} size="md">
Non-Assignability
</Heading>
<Text mt={4} fontSize="md">
Bugout may assign or delegate these Terms of Service and/or the Bugout
<Link color="primary.600" href="/privacy-policy">
{" "}
Privacy Policy
</Link>
, in whole or in part, to any person or entity at any time with or
without your consent. You may not assign or delegate any rights or
obligations under the Terms of Service or Privacy Statement without our
prior written consent, and any unauthorized assignment and delegation by
you is void.
</Text>
<Text mt={4} size="md">
Severability, No Waiver, and Survival
</Text>
<Text mt={4} fontSize="md">
If any part of this Agreement is held invalid or unenforceable, that
portion of the Agreement will be construed to reflect the parties
original intent. The remaining portions will remain in full force and
effect. Any failure on the part of Bugout to enforce any provision of
this Agreement will not be considered a waiver of our right to enforce
such provision. Our rights under this Agreement will survive any
termination of this Agreement.
</Text>
<Text mt={4} size="md">
Amendments; Complete Agreement
</Text>
<Text mt={4} fontSize="md">
This Agreement may only be modified by a written amendment signed by an
authorized representative of Bugout, or by the posting by Bugout of a
revised version in accordance with Section Q. Changes to These Terms.
These Terms of Service, together with the Bugout{" "}
<Link color="primary.600" href="/privacy-policy">
Privacy Policy
</Link>
, represent the complete and exclusive statement of the agreement
between you and us. This Agreement supersedes any proposal or prior
agreement oral or written, and any other communications between you and
Bugout relating to the subject matter of these terms including any
confidentiality or nondisclosure agreements.
</Text>
</Box>
</Box>
);
export default TermsOfService;

Wyświetl plik

@ -1,6 +1,4 @@
/** @jsxRuntime classic */
/** @jsx jsx */
import { jsx } from "@emotion/react";
import React from "react";
import RouterLink from "next/link";
import {
Menu,
@ -24,7 +22,7 @@ const AccountIconButton = (props) => {
{...props}
as={IconButton}
aria-label="Account menu"
icon={<RiAccountCircleLine size="26px"/>}
icon={<RiAccountCircleLine size="26px" />}
// variant="outline"
color="gray.100"
/>

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import { useUser, useRouter } from "../core/hooks";
import { useEffect, Fragment, useState } from "react";
import { Heading, Center, Spinner, Link, Button } from "@chakra-ui/react";

Wyświetl plik

@ -21,9 +21,7 @@ import {
} from "@chakra-ui/react";
import {
HamburgerIcon,
PlusSquareIcon,
QuestionOutlineIcon,
BellIcon,
ArrowLeftIcon,
ArrowRightIcon,
} from "@chakra-ui/icons";

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { useChangePassword, useRouter } from "../core/hooks";

Wyświetl plik

@ -1,12 +1,5 @@
import React, { useEffect, useRef, useContext } from "react";
import {
Flex,
Heading,
Button,
Link,
SimpleGrid,
useBreakpointValue,
} from "@chakra-ui/react";
import { Flex, Heading, Button, Link, SimpleGrid } from "@chakra-ui/react";
import Xarrow, { useXarrow } from "react-xarrows";
import UIContext from "../core/providers/UIProvider/context";
@ -17,19 +10,11 @@ const ArrowCTA = (props) => {
const box2Ref = useRef(null);
const box3Ref = useRef(null);
const gridSetup = useBreakpointValue({
base: "column",
sm: "horizontal",
md: "grid",
lg: "grid",
xl: "grid",
"2xl": "grid",
});
const updateXarrow = useXarrow();
useEffect(() => {
updateXarrow();
// eslint-disable-next-line
}, [ui.isMobileView]);
return (

Wyświetl plik

@ -1,67 +0,0 @@
import { jsx } from "@emotion/react";
import { GridItem } from "@chakra-ui/react";
import { Heading, Text, Image } from "@chakra-ui/react";
import { Fragment } from "react";
const Block = (content) => {
const TitleRef = content.PrevTitle
? `#${content.PrevTitle}-${content.title}`
: `#${content.title}`;
var HeaderStyle = content.PrevTitle
? { as: "h2", fontSize: "3xl" }
: { as: "h1", fontSize: "4xl" };
return (
<Fragment>
{content.title && (
<GridItem colSpan="12" px="8.3%" py={1} textAlign="center">
<Heading
id={TitleRef}
pt={16}
pb={4}
fontWeight="200"
{...HeaderStyle}
>
{content.title}
</Heading>
</GridItem>
)}
{content.body.map((element, idx) => {
if ("text" in element) {
return (
<GridItem key={idx} colSpan="10" px="8.3%" py={1}>
{element.text.map((paragraph, idx) => {
return (
<Text key={idx} py={2} fontSize="xl">
{paragraph}
</Text>
);
})}
</GridItem>
);
}
if ("image" in element) {
return (
<GridItem key={idx} colSpan="10" py={1} justifySelf="center">
<Image
justifySelf="center"
key={idx}
maxHeight="48rem"
src={element.image.path}
alt={element.image.annotation}
/>
</GridItem>
);
}
if ("title" in element) {
element.PrevTitle = content.title;
return <Block key={idx} {...element} />;
}
return "";
})}
</Fragment>
);
};
export default Block;

Wyświetl plik

@ -1,6 +1,4 @@
import { Fragment } from "react";
import { jsx } from "@emotion/react";
import React, { Fragment } from "react";
import {
useClipboard,
IconButton,

Wyświetl plik

@ -1,95 +0,0 @@
import { jsx } from "@emotion/react";
import {
Button,
Menu,
MenuButton,
MenuList,
MenuItem,
MenuGroup,
MenuDivider,
} from "@chakra-ui/react";
import {
useJournalEntry,
useJournals,
useRouter,
useToast,
} from "../core/hooks";
import { EntryService } from "../core/services";
import { useQueryCache } from "react-query";
const CopyEntryButton = ({ id, journalId }) => {
const router = useRouter();
const cache = useQueryCache();
const { appScope } = router.params;
const { data: entryToCopy, isLoading: sourceIsLoading } = useJournalEntry(
journalId,
id,
appScope
);
const toast = useToast();
const { journalsCache } = useJournals();
const copyEntry = async (targetJournalId) => {
try {
const newEntry = { ...entryToCopy };
newEntry.title = "Copy of " + newEntry.title;
await EntryService.create(targetJournalId)(newEntry).then((response) => {
journalsCache.refetch();
setTimeout(
() => cache.refetchQueries(["journal-entries", { journalId }]),
500
);
if (response.status === 200) {
toast("Copied!", "success");
}
});
} catch (e) {
console.error(
"Error copying entry. Please email engineering@bugout.dev if you encounter this issue.",
e
);
}
};
if (journalsCache.isLoading || sourceIsLoading) return "";
return (
<Menu>
<MenuButton
as={Button}
size="xs"
variant="link"
colorScheme="primary"
ml={1}
>
Copy
</MenuButton>
<MenuList maxH="sm" overflow="scroll">
<MenuGroup title="Destination:">
<MenuItem value={journalId} onClick={() => copyEntry(journalId)}>
{
journalsCache?.data?.data?.journals?.filter(
(journal) => journal.id === journalId
)[0]?.name
}
</MenuItem>
<MenuDivider />
{journalsCache?.data?.data?.journals?.map((journal) => {
if (journal.id === journalId) return "";
return (
<MenuItem
key={`option-${journal.id}`}
value={journal.id}
onClick={() => copyEntry(journal.id)}
>
{journal.name}
</MenuItem>
);
})}
</MenuGroup>
</MenuList>
</Menu>
);
};
export default CopyEntryButton;

Wyświetl plik

@ -68,11 +68,6 @@ const EntriesNavigation = () => {
const [filterState, setFilterState] = useState([]);
const setNewFilterState = (props) => {
console.log(
"setNewFilterState",
props,
subscriptionsCache.data.subscriptions[0].id
);
_setNewFilterState(props);
};
const loadMoreButtonRef = useRef(null);
@ -112,6 +107,7 @@ const EntriesNavigation = () => {
value: subscriptionsCache.data.subscriptions[0].address,
});
}
// eslint-disable-next-line
}, [subscriptionsCache.isLoading]);
const entriesPagesData = EntriesPages
@ -132,7 +128,6 @@ const EntriesNavigation = () => {
};
const dropFilterArrayItem = (idx) => {
console.log("dropFilterArrayItem", idx, filterState);
const newArray = [...filterState];
newArray[idx].type = FILTER_TYPES.DISABLED;
setFilterState(newArray);
@ -148,18 +143,15 @@ const EntriesNavigation = () => {
};
const handleConditionChange = (idx) => (e) => {
console.log("handleConditionChange", idx, e.target.value);
setFilterProps(idx, { condition: parseInt(e.target.value) });
};
const handleFilterStateCallback = (props) => {
console.log("handleFilterStateCallback", props);
const newFilterState = [...filterState];
newFilterState.push({ ...props });
setFilterState(newFilterState);
};
if (subscriptionsCache.isLoading) return "";
console.log("filterstate test", filterState);
return (
<Flex
id="JournalNavigation"

Wyświetl plik

@ -92,7 +92,7 @@ const Footer = () => (
flexGrow="1"
w="100%"
maxW="40rem"
alignItems={["center", "center", null, "flex-end"]}
alignItems={["flex-end", "flex-end", null, "flex-end"]}
pr={[0, null, 8]}
>
<Text

Wyświetl plik

@ -13,8 +13,8 @@ import {
Input,
InputRightElement,
} from "@chakra-ui/react";
import CustomIcon from "./CustomIcon"
import Modal from "./Modal"
import CustomIcon from "./CustomIcon";
import Modal from "./Modal";
const ForgotPassword = ({ toggleModal }) => {
const toast = useToast();

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import { Heading, Box, Text, Center, VStack } from "@chakra-ui/react";
const Page404 = () => (
<Box pt={8} w="100%" h="100%">

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import { Heading, Box, Text, VStack, Center } from "@chakra-ui/react";
const Page403 = ({ location }) => (
<Box pt={8} w="100%" h="100%">

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import Head from "next/head";
import propTypes from "prop-types";

Wyświetl plik

@ -1,5 +1,4 @@
import { jsx } from "@emotion/react";
import React from "react";
import Head from "next/head";
import propTypes from "prop-types";

Wyświetl plik

@ -0,0 +1,45 @@
import React, { useEffect } from "react";
import { Heading, Spinner } from "@chakra-ui/react";
import Modal from "./Modal";
import { useToast } from "../core/hooks";
import HubspotForm from "react-hubspot-form";
const RequestIntegration = ({ toggleModal, title, formId }) => {
const toast = useToast();
useEffect(() => {
function handler(event) {
if (
event.data.type === "hsFormCallback" &&
event.data.eventName === "onFormSubmitted"
) {
if (event.data.id === formId) {
toggleModal(null);
toast("Request sent", "success");
}
}
}
window.addEventListener("message", handler);
return () => {
window.removeEventListener("message", handler);
};
// eslint-disable-next-line
}, [toast, toggleModal]);
return (
<Modal onClose={() => toggleModal(null)}>
<Heading my={2} as="h2" fontSize={["xl", "3xl"]}>
{title}
</Heading>
<HubspotForm
region="na1"
portalId="8018701"
formId={formId}
loading={<Spinner colorScheme="primary" speed="1s" />}
/>
</Modal>
);
};
export default RequestIntegration;

Wyświetl plik

@ -1,20 +0,0 @@
import { jsx } from "@emotion/react";
import { IconButton as IconButtonChakra } from "@chakra-ui/react";
import { CheckIcon } from "@chakra-ui/icons";
const IconButton = (props) => {
return (
<IconButtonChakra
p={0}
boxSize="24px"
icon={<CheckIcon boxSize="18px" />}
bg="none"
_hover={{ transform: "scale(1.2)" }}
_focus={{ outline: "none" }}
_active={{ bg: "none" }}
{...props}
/>
);
};
export default IconButton;

Wyświetl plik

@ -20,7 +20,18 @@ const LandingNavbar = () => {
return (
<>
<>
<Flex position="absolute" left="calc(50% - 100px)">
{ui.isMobileView && (
<>
<IconButton
alignSelf="flex-start"
colorScheme="primary"
variant="solid"
onClick={() => ui.setSidebarToggled(!ui.sidebarToggled)}
icon={<HamburgerIcon />}
/>
</>
)}
<Flex ml={ui.isMobileView ? 2 : 8} justifySelf="flex-start">
<RouterLink href="/" passHref>
<Link>
<Image
@ -81,17 +92,6 @@ const LandingNavbar = () => {
</>
)}
</>
{ui.isMobileView && (
<>
<IconButton
colorScheme="secondary"
variant="solid"
onClick={() => ui.setSidebarToggled(!ui.sidebarToggled)}
icon={<HamburgerIcon />}
/>
</>
)}
</>
);
};

Wyświetl plik

@ -2,7 +2,7 @@
/** @jsx jsx */
import { jsx } from "@emotion/react";
import { Flex } from "@chakra-ui/react";
import CustomIcon from "../CustomIcon"
import CustomIcon from "../CustomIcon";
import styles from "./styles";
const Modal = ({ children, onClose }) => (

Wyświetl plik

@ -9,11 +9,11 @@ const SignIn = React.lazy(() => import("./SignIn"));
const SignUp = React.lazy(() => import("./SignUp"));
const LandingNavbar = React.lazy(() => import("./LandingNavbar"));
const AppNavbar = React.lazy(() => import("./AppNavbar"));
const HubspotForm = React.lazy(() => import("./HubspotForm"));
const Navbar = () => {
const { modal, toggleModal, isAppView, isLoggedIn } = useContext(UIContext);
return (
<Flex
boxShadow={["sm", "md"]}
@ -23,7 +23,7 @@ const Navbar = () => {
// overflow="initial"
bgColor="primary.1200"
// flexWrap="wrap"
direction={["column", "row", "row", null, "row"]}
direction={["row", "row", "row", null, "row"]}
// zIndex={100}
w="100%"
minW="100%"
@ -33,11 +33,29 @@ const Navbar = () => {
>
<Suspense fallback={""}>
{modal === "register" && <SignUp toggleModal={toggleModal} />}
{modal === "login" && <SignIn toggleModal={toggleModal} />}
{modal === "forgot" && <ForgotPassword toggleModal={toggleModal} />}
{modal === "hubspot-trader" && (
<HubspotForm
toggleModal={toggleModal}
title={"Join the waitlist"}
formId={"29a17405-819b-405d-9563-f75bfb3774e0"}
/>
)}
{modal === "hubspot-fund" && (
<HubspotForm
toggleModal={toggleModal}
title={"Join the waitlist"}
formId={"04f0b8df-6b8f-4cd0-871f-4e872523b6f5"}
/>
)}
{modal === "hubspot-developer" && (
<HubspotForm
toggleModal={toggleModal}
title={"Join the waitlist"}
formId={"1897f4a1-3a00-475b-9bd5-5ca2725bd720"}
/>
)}
{(!isAppView || !isLoggedIn) && <LandingNavbar />}
{isAppView && isLoggedIn && <AppNavbar />}
</Suspense>

Wyświetl plik

@ -22,7 +22,7 @@ const NewSubscription = ({ isFreeOption, onClose }) => {
const { typesCache, createSubscription } = useSubscriptions();
const { handleSubmit, errors, register } = useForm();
const [radioState, setRadioState] = useState("ethereum_blockchain");
let { getRootProps, getRadioProps, ref } = useRadioGroup({
let { getRootProps, getRadioProps } = useRadioGroup({
name: "type",
defaultValue: radioState,
onChange: setRadioState,

Wyświetl plik

@ -1,6 +1,6 @@
import React, { useState } from "react";
import { InputGroup, InputRightElement, Input } from "@chakra-ui/react";
import CustomIcon from "./CustomIcon"
import CustomIcon from "./CustomIcon";
const PasswordInput = ({ placeholder, name }, ref) => {
const [showPassword, togglePassword] = useState(false);

Wyświetl plik

@ -8,7 +8,7 @@ const RadioCard = (props) => {
const checkbox = getCheckboxProps();
return (
<Flex as="label" h="fill-availible" onClick={() => console.log('hello2')}>
<Flex as="label" h="fill-availible">
<input {...input} />
<Box
justifyContent="left"

Wyświetl plik

@ -1,19 +1,44 @@
import { Flex, Box } from "@chakra-ui/react";
import React, { useEffect, useRef, useState } from "react";
import { useRouter } from "../core/hooks";
import { useRouter, useAnalytics } from "../core/hooks";
const Scrollable = (props) => {
const scrollerRef = useRef();
const router = useRouter();
const [path, setPath] = useState();
const [scrollDepth, setScrollDepth] = useState(0);
const { mixpanel } = useAnalytics();
const getScrollPrecent = ({ currentTarget }) => {
const scroll_level =
(100 * (currentTarget.scrollTop + currentTarget.clientHeight)) /
currentTarget.scrollHeight;
return scroll_level;
};
const handleScroll = (e) => {
const currentScroll = Math.ceil(getScrollPrecent(e) / 10);
if (currentScroll > scrollDepth) {
// withTracking(
setScrollDepth(currentScroll);
mixpanel.people.increment({
[`Scroll depth at: ${router.nextRouter.pathname}`]: currentScroll,
});
}
};
useEffect(() => {
setPath(router.nextRouter.pathname);
}, [router.nextRouter.pathname]);
scrollerRef?.current?.scrollTo({
top: 0,
left: 0,
behavior: path === router.nextRouter.pathname ? "smooth" : "auto",
});
useEffect(() => {
scrollerRef?.current?.scrollTo({
top: 0,
left: 0,
behavior: path === router.nextRouter.pathname ? "smooth" : "auto",
});
// eslint-disable-next-line
}, [path]);
return (
<Flex
@ -28,6 +53,7 @@ const Scrollable = (props) => {
direction="column"
ref={scrollerRef}
overflowY="scroll"
onScroll={(e) => handleScroll(e)}
>
{props.children}
</Box>

Wyświetl plik

@ -1,288 +0,0 @@
import { jsx } from "@emotion/react";
import {
useState,
useContext,
useRef,
useLayoutEffect,
useEffect,
} from "react";
import {
Input,
InputLeftElement,
InputGroup,
Box,
Flex,
chakra,
InputRightElement,
Menu,
MenuItem,
MenuList,
MenuButton,
Button,
Portal,
MenuGroup,
Spinner,
} from "@chakra-ui/react";
import { Search2Icon, CloseIcon } from "@chakra-ui/icons";
import UIContext from "../core/providers/UIProvider/context";
import { useJournalEntries, useJournals, useRouter } from "../core/hooks";
const SearchBar = (props) => {
const ui = useContext(UIContext);
const router = useRouter();
const { refetch } = useJournalEntries({
journalId: router.params.id,
journalType: router.params.appScope,
pageSize: 25,
isContent: false,
searchQuery: ui.searchTerm,
});
const [selectedJournal, setSelectedJournal] = useState();
const [showError, setShowError] = useState(false);
const [InputFieldValue, setInputFieldValue] = useState(ui.serachTerm ?? "");
const { journalsCache, publicJournalsCache } = useJournals();
const inputRef = useRef(null);
const showSearchBar = !ui.isMobileView || ui.searchBarActive;
const handleSearch = (e) => {
e.preventDefault();
const journalIdToSearchIn =
selectedJournal?.id ?? router.params.id ?? false;
const searchAtSameRoute =
router.params.id &&
journalIdToSearchIn &&
router.params.id === journalIdToSearchIn;
if (journalIdToSearchIn) {
if (searchAtSameRoute) {
ui.searchTerm === InputFieldValue
? refetch()
: ui.setSearchTerm(InputFieldValue);
} else {
const newQuery = { ...router.nextRouter.query };
newQuery.id = selectedJournal.id;
newQuery.appScope = selectedJournal.isPublic ? "public" : "personal";
delete newQuery.entryId;
ui.setSearchTerm(InputFieldValue);
router.push({ pathname: "/stream/", query: newQuery }, undefined, {
shallow: false,
});
}
} else {
setShowError(true);
}
};
useLayoutEffect(() => {
showError && setTimeout(() => setShowError(false), 200);
}, [showError]);
useEffect(() => {
const cache =
router.params.appScope === "personal"
? publicJournalsCache
: journalsCache;
if (router.params.id && !cache.isLoading) {
const newJournal = cache.data.find(
(journal) => journal.id === router.params.id
);
newJournal && setSelectedJournal(newJournal);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [router.params.id, journalsCache, publicJournalsCache]);
useLayoutEffect(() => {
if (ui.searchTerm !== InputFieldValue) {
setInputFieldValue(ui.searchTerm);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ui.searchTerm]);
const handleBlur = (e) => {
const currentTarget = e.currentTarget;
// Check the newly focused element in the next tick of the event loop
setTimeout(() => {
// Check if the new activeElement is a child of the original container
if (
!currentTarget.contains(document.activeElement) &&
!document.activeElement.className.includes("bugout-search-bar")
) {
// You can invoke a callback or add custom logic here
ui.setSearchBarActive(false);
}
}, 100);
};
const handleLeftElementClick = () => {
if (!showSearchBar) {
ui.setSearchBarActive(true);
}
inputRef.current.focus();
};
const handleCloseSearchBar = () => {
ui.setSearchBarActive(false);
ui.setSearchTerm("");
};
return (
<Flex {...props} transition="1s">
<form
onSubmit={(e) => handleSearch(e)}
style={{ width: "100%", height: "100%" }}
>
<InputGroup
bgColor={showSearchBar ? "white" : "transparent"}
borderRadius="lg"
overflow="hidden"
h="100%"
w="100%"
onFocus={() => {
ui.setSearchBarActive(true);
}}
onBlur={handleBlur}
>
<InputLeftElement
onClick={() => handleLeftElementClick()}
minW="48px"
w="fit-content"
position="static"
justifySelf="flex-start"
h="100%"
overflowY="visible"
transform="1s"
>
{!ui.searchBarActive && (
<Search2Icon
color={showSearchBar ? "primary.1200" : "white.100"}
/>
)}
{ui.searchBarActive && (
<Menu>
<MenuButton
as={Button}
variant="ghost"
colorScheme="primary"
h="100%"
m={0}
borderRightRadius={0}
transition="0.05s"
className="bugout-search-bar"
bgColor={showError ? "unsafe.900" : "primary.100"}
textColor={showError ? "white.100" : "primary.900"}
>
{`Search in: ${
router.params.id && !selectedJournal?.name
? "current"
: selectedJournal?.name ?? "Select one"
}`}
</MenuButton>
<Portal>
<MenuList
overflowY="scroll"
maxH="300px"
className="bugout-search-bar"
>
{router.params.id && (
<MenuItem
className="bugout-search-bar"
onClick={() =>
setSelectedJournal(
journalsCache.data.filter(
(journal) => journal.id === router.params.id
)[0]
)
}
>
Current
</MenuItem>
)}
<MenuGroup textColor="gray" title="personal journals">
{journalsCache.isLoading && <Spinner />}
{!journalsCache.isLoading &&
journalsCache.data.map((journal, idx) => (
<MenuItem
className="bugout-search-bar"
key={`journal-search-list-${idx}`}
onClick={() =>
setSelectedJournal({
...journal,
isPublic: false,
})
}
>
{journal.name}
</MenuItem>
))}
</MenuGroup>
<MenuGroup textColor="gray" title="public journals">
{publicJournalsCache.isLoading && <Spinner />}
{!publicJournalsCache.isLoading &&
publicJournalsCache.data.map((journal, idx) => (
<MenuItem
className="bugout-search-bar"
key={`public-journal-search-list-${idx}`}
onClick={() =>
setSelectedJournal({
...journal,
isPublic: true,
})
}
>
{journal.name}
</MenuItem>
))}
</MenuGroup>
</MenuList>
</Portal>
</Menu>
)}
</InputLeftElement>
<Input
hidden={!showSearchBar}
h="100%"
px="8px"
display="flex"
paddingInlineStart="8px !important"
sx={{
WebkitPaddingStart: "8px !important",
WebkitPaddingEnd: "8px !important",
}}
flexBasis="50px"
flexGrow={1}
textColor="black"
ref={inputRef}
_hover={{ bgColor: "white" }}
_active={{ bgColor: "white" }}
_focus={{ bgColor: "white", textColor: "black" }}
value={InputFieldValue}
onChange={(e) => setInputFieldValue(e.target.value)}
/>
<InputRightElement
h="100%"
position="static"
justifySelf="flex-end"
hidden={!ui.searchBarActive}
>
<Box
onClick={() => handleCloseSearchBar()}
transition="1s"
_hover={{ transform: "scale(1.2)" }}
>
<CloseIcon color="primary.1200" />
</Box>
</InputRightElement>
</InputGroup>
</form>
</Flex>
);
};
const ChakraSearchBar = chakra(SearchBar);
export default ChakraSearchBar;

Wyświetl plik

@ -15,7 +15,7 @@ import {
Input,
InputRightElement,
} from "@chakra-ui/react";
import CustomIcon from "./CustomIcon"
import CustomIcon from "./CustomIcon";
import { useLogin } from "../core/hooks";
import PasswordInput from "./PasswordInput";
import Modal from "./Modal";
@ -51,7 +51,7 @@ const SignIn = ({ toggleModal }) => {
colorScheme="primary"
placeholder="Your Bugout username"
name="username"
{...register('username', { required: true })}
{...register("username", { required: true })}
ref={register({ required: "Username is required!" })}
/>
<InputRightElement>

Wyświetl plik

@ -26,11 +26,11 @@ const SignUp = ({ toggleModal }) => {
const { signUp, isLoading, isSuccess } = useSignUp();
const ui = useContext(UIContext);
useEffect(() => {
if (isSuccess) {
ui.toggleModal(null);
}
// eslint-disable-next-line
}, [isSuccess, toggleModal]);
return (

Wyświetl plik

@ -14,15 +14,10 @@ import {
useBreakpointValue,
} from "@chakra-ui/react";
// import Xarrow, { useXarrow } from "react-xarrows";
import React, { useContext, useEffect } from "react";
import React, { useContext } from "react";
import UIContext from "../core/providers/UIProvider/context";
const Feature = ({ text, icon, iconBg, bullets }) => {
// const updateXarrow = useXarrow();
useEffect(() => {
// updateXarrow();
}, []);
console.log("bullets;", bullets);
return (
<Flex direction="column">
<Stack direction={"row"} align={"center"}>
@ -83,11 +78,6 @@ const SplitWithImage = ({
});
const ui = useContext(UIContext);
// const updateXarrow = useXarrow();
const iconBgColor = useColorModeValue(
`${colorScheme}.100`,
`${colorScheme}.900`
);
const [isVisible, setVisible] = React.useState(true);
const domRef = React.useRef();
@ -106,7 +96,6 @@ const SplitWithImage = ({
py={0}
className={`fade-in-section ${isVisible ? "is-visible" : ""}`}
ref={domRef}
// onAnimationIteration={() => updateXarrow()}
>
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={[0, 0, 10, null, 10]}>
{mirror && !ui.isMobileView && (
@ -119,7 +108,7 @@ const SplitWithImage = ({
/>
</Flex>
)}
<Stack spacing={4}>
<Stack spacing={4} justifyContent="center">
<Text
id={`MoonBadge ${elementName}`}
// id={`MoonBadge${elementName}`}
@ -134,17 +123,6 @@ const SplitWithImage = ({
>
{badge}
</Text>
{/* <Xarrow
dashness={{
strokeLen: 10,
nonStrokeLen: 15,
animation: -2,
}}
color="#212990"
showHead={false}
start={"CryptoTraderButton"} //can be react ref
end={`MoonBadge ${elementName}`} //or an id
/> */}
<Heading>{title}</Heading>
<Text color={`primary.500`} fontSize={"lg"}>
{body}
@ -158,7 +136,6 @@ const SplitWithImage = ({
}
>
{bullets?.map((bullet, idx) => {
console.log("bullet1", bullet?.bullets);
return (
<Feature
key={`splitWImageBullet-${idx}-${title}`}
@ -177,23 +154,24 @@ const SplitWithImage = ({
colorScheme={colorScheme}
variant="outline"
mt={[0, 0, null, 16]}
textTransform={"uppercase"}
fontSize={["xs", "sm", "lg", null, "lg"]}
size={buttonSize}
onClick={cta.onClick}
>
{cta}
{cta.label}
</Button>
</Center>
</Container>
</Stack>
</Stack>
{(!mirror || ui.isMobileView) && (
<Flex>
<Flex justifyContent="center">
<Image
rounded={"md"}
alt={"feature image"}
src={imgURL}
objectFit={"cover"}
objectFit={"contain"}
// boxSize={ui.isMobileView ? "lg" : null}
/>
</Flex>
)}

Wyświetl plik

@ -1,46 +0,0 @@
import { jsx } from "@emotion/react";
import { Tag, TagLabel, Flex, Button } from "@chakra-ui/react";
import { useState } from "react";
const TAGS_DISPLAY_NUM_DEF = 5;
const TagsList = ({ tags }) => {
const [showAllTags, toggleAllTags] = useState(false);
const tagButtonText = showAllTags ? "Show less" : "Show all";
const TagsToShow = () =>
tags
.filter((tag, i) => (showAllTags ? true : i < TAGS_DISPLAY_NUM_DEF))
.map((tag, index) => {
return (
<Tag
variant="subtle"
colorScheme="primary"
size="sm"
key={`${tag}-${index}`}
>
<TagLabel>{tag}</TagLabel>
</Tag>
);
});
return (
<Flex display="flex" flexWrap="wrap" align="center" spacing={1}>
<TagsToShow />
{tags.length > TAGS_DISPLAY_NUM_DEF && (
<Button
m={1}
onClick={() => toggleAllTags(!showAllTags)}
size="xs"
variant="link"
color="primary.600"
ml={1}
style={{ transform: "translateY(-1px)" }}
>
{tagButtonText}
</Button>
)}
</Flex>
);
};
export default TagsList;

Wyświetl plik

@ -1,103 +0,0 @@
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 from "./CopyEntryButton";
import ConfirmationRequest from "./ConfirmationRequest";
import NewTokenTr from "./NewTokenTr";
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="primary"
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="primary"
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

@ -1,109 +0,0 @@
import { jsx } from "@emotion/react";
import {
Box,
InputGroup,
InputLeftElement,
FormControl,
FormErrorMessage,
HStack,
Button,
InputRightElement,
Input,
} from "@chakra-ui/react";
import { CloseIcon } from "@chakra-ui/icons";
import { useEffect, useState, useRef } from "react";
import CustomIcon from "./CustomIcon"
import { useForm } from "react-hook-form";
import { useUser, useLogin } from "../core/hooks";
const TokenRequest = ({ newToken, toggle }) => {
const { user } = useUser();
const { login, isLoading, data } = useLogin("SendLoginProp");
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 (data) {
newToken(data.data.access_token);
toggle(null);
}
}, [data, newToken, toggle]);
const formStyle = {
display: "flex",
flexWrap: "wrap",
minWidth: "100px",
flexFlow: "row wrap-reverse",
aligntContent: "flex-end",
};
if (!user) return ""; //loading...
return (
<Box>
<form onSubmit={handleSubmit(login)} style={formStyle}>
<HStack>
<Button
variant="solid"
colorScheme="primary"
type="submit"
isLoading={isLoading}
>
Submit
</Button>
<FormControl isInvalid={errors.password}>
<InputGroup minWidth="300px">
<InputLeftElement onClick={togglePassword}>
<CustomIcon icon="password" />
</InputLeftElement>
<Input
colorScheme="primary"
variant="filled"
isDisabled={isLoading}
autoComplete="on"
placeholder="Your Bugout password"
name="password"
type={showPassword}
ref={(e) => {
register(e, { required: "Password is required!" });
PasswordRef.current = e;
}}
/>
<InputRightElement onClick={() => toggle(null)}>
<CloseIcon />
</InputRightElement>
</InputGroup>
<FormErrorMessage color="unsafe.400" pl="1" justifyContent="Center">
{errors.password && errors.password.message}
</FormErrorMessage>
</FormControl>
<Input
type="hidden"
ref={register}
name="username"
defaultValue={user?.username}
/>
</HStack>
</form>
</Box>
);
};
export default TokenRequest;

Wyświetl plik

@ -1,36 +0,0 @@
import { jsx } from "@emotion/react";
import { Flex, Image, Link } from "@chakra-ui/react";
const TrustedBadge = ({ name, caseURL, ImgURL }) => {
return (
<Flex
m={1}
justifyContent="center"
alignItems="center"
alignSelf="center"
wrap="nowrap"
p={8}
direction="column"
>
<Image
sx={{ filter: "grayscale(100%)" }}
h={["2.25rem", null, "3rem", "3rem", "4rem", "6rem"]}
src={ImgURL}
alt={name}
></Image>
{caseURL && (
// <RouterLink href={caseURL} passHref scroll={true}>
<Link
fontSize={["sm", null, "md", "lg"]}
textColor="secondary.900"
href="/case-studies/activeloop"
>
{`Read case study >`}
</Link>
// </RouterLink>
)}
</Flex>
);
};
export default TrustedBadge;

Wyświetl plik

@ -2,9 +2,8 @@ import AnalyticsContext from "../providers/AnalyticsProvider/context";
import { useContext } from "react";
import { useState, useEffect, useCallback } from "react";
const useAnalytics = () => {
const { mixpanel, isLoaded, MIXPANEL_EVENTS, MIXPANEL_PROPS } = useContext(
AnalyticsContext
);
const { mixpanel, isLoaded, MIXPANEL_EVENTS, MIXPANEL_PROPS } =
useContext(AnalyticsContext);
const [trackProps, setTrackProps] = useState({
event: null,
props: null,

Wyświetl plik

@ -8,7 +8,11 @@ const useGroup = (groupId) => {
const cache = useQueryCache();
const toast = useToast();
const { data: GroupUsersResponse, isLoading, refetch: getUsers } = useQuery(
const {
data: GroupUsersResponse,
isLoading,
refetch: getUsers,
} = useQuery(
["group-users", groupId],
GroupService.getGroupUsers,
queryCacheProps

Wyświetl plik

@ -15,11 +15,11 @@ const useGroups = () => {
return response?.data?.groups;
};
const { data, isLoading, refetch: getGroups } = useQuery(
"groups",
fetchGroups,
queryCacheProps
);
const {
data,
isLoading,
refetch: getGroups,
} = useQuery("groups", fetchGroups, queryCacheProps);
const [createGroup, createStatus] = useMutation(
(groupName) => GroupService.createGroup(groupName),

Wyświetl plik

@ -158,10 +158,6 @@ const useJournalPermissions = (journalId, journalScope) => {
}
);
const holders = data;
return {
holders,

Wyświetl plik

@ -36,10 +36,12 @@ const useLogin = (loginType) => {
getUser();
if (analytics.isLoaded) {
analytics.mixpanel.people.set_once({
[`${analytics.MIXPANEL_EVENTS.FIRST_LOGIN_DATE}`]: new Date().toISOString(),
[`${analytics.MIXPANEL_EVENTS.FIRST_LOGIN_DATE}`]:
new Date().toISOString(),
});
analytics.mixpanel.people.set({
[`${analytics.MIXPANEL_EVENTS.LAST_LOGIN_DATE}`]: new Date().toISOString(),
[`${analytics.MIXPANEL_EVENTS.LAST_LOGIN_DATE}`]:
new Date().toISOString(),
});
analytics.mixpanel.track(
`${analytics.MIXPANEL_EVENTS.USER_LOGS_IN}`,

Wyświetl plik

@ -8,7 +8,7 @@ const useLogout = () => {
const { setLoggingOut } = useContext(UIContext);
const router = useRouter();
const analytics = useAnalytics();
const {mutate: revoke, data } = useMutation(AuthService.revoke, {
const { mutate: revoke, data } = useMutation(AuthService.revoke, {
onSuccess: () => {
if (analytics.isLoaded) {
analytics.mixpanel.track(

Wyświetl plik

@ -15,7 +15,7 @@ const useSignUp = (source) => {
isLoading,
error,
data,
isSuccess
isSuccess,
} = useMutation(AuthService.register(), {
onSuccess: (response) => {
localStorage.setItem("BUGOUT_ACCESS_TOKEN", response.data.access_token);

Wyświetl plik

@ -18,13 +18,6 @@ const useJournalEntries = ({
pageParam = 0;
}
const searchTags = searchTerm.split(" ").filter(function (n) {
if (n.startsWith("#")) return n;
else {
return null;
}
});
const response = await SubscriptionsService.getStream({
searchTerm,
isContent,
@ -58,8 +51,7 @@ const useJournalEntries = ({
getNextPageParam: (lastGroup) => {
return lastGroup.next_offset === null ? false : lastGroup.next_offset;
},
onSuccess: (data) => {
},
onSuccess: () => {},
enabled: !!enabled,
});

Wyświetl plik

@ -9,22 +9,6 @@ const useSubscriptions = () => {
const toast = useToast();
const stripe = useStripe();
// const manageSubscription = useMutation(
// SubscriptionsService.manageSubscription(),
// {
// onError: (error) => toast(error, "error"),
// onSuccess: (response) => {
// const { session_id: sessionId, session_url: sessionUrl } =
// response.data;
// if (sessionId) {
// stripe.redirectToCheckout({ sessionId });
// } else if (sessionUrl) {
// window.location = sessionUrl;
// }
// },
// }
// );
const getSubscriptions = async () => {
const response = await SubscriptionsService.getSubscriptions();
return response.data.data;
@ -68,19 +52,28 @@ const useSubscriptions = () => {
const changeNote = useMutation(SubscriptionsService.modifySubscription(), {
onError: (error) => toast(error, "error"),
onSuccess: (response) => {
onSuccess: () => {
subscriptionsCache.refetch();
},
});
const deleteSubscription = useMutation(SubscriptionsService.deleteSubscription(), {
onError: (error) => toast(error, "error"),
onSuccess: (response) => {
subscriptionsCache.refetch();
},
});
const deleteSubscription = useMutation(
SubscriptionsService.deleteSubscription(),
{
onError: (error) => toast(error, "error"),
onSuccess: () => {
subscriptionsCache.refetch();
},
}
);
return { createSubscription, subscriptionsCache, typesCache, changeNote, deleteSubscription };
return {
createSubscription,
subscriptionsCache,
typesCache,
changeNote,
deleteSubscription,
};
};
export default useSubscriptions;

Wyświetl plik

@ -1,7 +1,5 @@
import { jsx } from "@emotion/react";
import { useToast as useChakraToast, Box } from "@chakra-ui/react";
import { useCallback } from "react";
import React, { useCallback } from "react";
import { useAnalytics } from ".";
const useToast = () => {

Wyświetl plik

@ -12,13 +12,14 @@ export const MIXPANEL_EVENTS = {
LAST_LOGIN_DATE: "Last login date",
LAST_VISITED: "Last visited",
TOAST_ERROR_DISPLAYED: "Error Toast",
HOMEPAGE_SCROLL_DEPTH: "Homepage scroll depth",
SCROLL_DEPTH: "Homepage scroll depth",
CONVERT_TO_USER: "User Signs up",
USER_LOGS_IN: "User Logs in",
USER_LOGS_OUT: "User Logs out",
PAGEVIEW: "Page view",
PRICING_PLAN_CLICKED: "Pricing Plan clicked",
BUTTON_CLICKED: "Button clicked",
LEFT_PAGE: "Left page",
};
export default MIXPANEL_EVENTS;

Wyświetl plik

@ -12,6 +12,37 @@ const AnalyticsProvider = ({ children }) => {
const router = useRouter();
useEffect(() => {
let durationSeconds = 0;
const intervalId =
isLoaded &&
setInterval(() => {
durationSeconds = durationSeconds + 1;
mixpanel.track(
MIXPANEL_EVENTS.LEFT_PAGE,
{
duration_seconds: durationSeconds,
url: router.nextRouter.pathname,
query: router.query,
pathParams: router.params,
},
{ transport: "sendBeacon" }
);
}, 1000);
return () => clearInterval(intervalId);
// eslint-disable-next-line
}, [isLoaded]);
useEffect(() => {
if (isLoaded) {
console.log(
"track:",
router.nextRouter.pathname,
router.query,
router.params
);
}
isLoaded &&
mixpanel.track(MIXPANEL_EVENTS.PAGEVIEW, {
url: router.nextRouter.pathname,

Wyświetl plik

@ -3,7 +3,6 @@ import { http } from "../utils";
const AUTH_URL = process.env.NEXT_PUBLIC_SIMIOTICS_AUTH_URL;
export const login = ({ username, password }) => {
console.log('login',username, password)
const data = new FormData();
data.append("username", username);
data.append("password", password);
@ -22,24 +21,26 @@ export const revoke = () => {
});
};
export const register = () => ({ username, email, password }) => {
const data = new FormData();
data.append("username", username);
data.append("email", email);
data.append("password", password);
export const register =
() =>
({ username, email, password }) => {
const data = new FormData();
data.append("username", username);
data.append("email", email);
data.append("password", password);
return http({
method: "POST",
url: `${AUTH_URL}/user`,
data,
}).then(() =>
http({
return http({
method: "POST",
url: `${AUTH_URL}/token`,
url: `${AUTH_URL}/user`,
data,
})
);
};
}).then(() =>
http({
method: "POST",
url: `${AUTH_URL}/token`,
data,
})
);
};
export const verify = ({ code }) => {
const data = new FormData();

Wyświetl plik

@ -50,20 +50,19 @@ export const getTokens = (humbugId) => {
});
};
export const createRestrictedToken = (humbugId) => ({
appName,
appVersion,
}) => {
const data = new FormData();
data.append("app_name", appName);
data.append("app_version", appVersion);
export const createRestrictedToken =
(humbugId) =>
({ appName, appVersion }) => {
const data = new FormData();
data.append("app_name", appName);
data.append("app_version", appVersion);
return http({
method: "POST",
url: `${API}/humbug/${humbugId}/tokens`,
data,
});
};
return http({
method: "POST",
url: `${API}/humbug/${humbugId}/tokens`,
data,
});
};
export const deleteRestrictedToken = (humbugId) => (tokenId) => {
const data = new FormData();

Wyświetl plik

@ -62,35 +62,31 @@ export const getJournalsScopes = () => {
});
};
export const setJournalPermission = (journalId) => ({
holder_type,
holder_id,
permission_list,
}) => {
const data = new FormData();
data.append("holder_type", holder_type);
data.append("holder_id", holder_id);
data.append("permission_list", permission_list);
export const setJournalPermission =
(journalId) =>
({ holder_type, holder_id, permission_list }) => {
const data = new FormData();
data.append("holder_type", holder_type);
data.append("holder_id", holder_id);
data.append("permission_list", permission_list);
return http({
method: "POST",
url: `${API}/journals/${journalId}/scopes`,
data: { holder_type, holder_id, permission_list },
});
};
return http({
method: "POST",
url: `${API}/journals/${journalId}/scopes`,
data: { holder_type, holder_id, permission_list },
});
};
export const deleteJournalPermission = (journalId) => ({
holder_type,
holder_id,
permission_list,
}) => {
return http({
method: "DELETE",
url: `${API}/journals/${journalId}/scopes`,
data: { holder_type, holder_id, permission_list },
// permission_list: ["read"]
});
};
export const deleteJournalPermission =
(journalId) =>
({ holder_type, holder_id, permission_list }) => {
return http({
method: "DELETE",
url: `${API}/journals/${journalId}/scopes`,
data: { holder_type, holder_id, permission_list },
// permission_list: ["read"]
});
};
export const getPublicJournals = () =>
http({
@ -98,32 +94,30 @@ export const getPublicJournals = () =>
url: `${API}/public/`,
});
export const searchEntries = ({ journalId }) => ({
searchTerm,
limit,
offset,
isContent,
journalType,
}) => {
const journalScope = journalType === "personal" ? "journals" : "public";
return http({
method: "GET",
url: `${API}/${journalScope}/${journalId}/search`,
params: {
// filters: searchTags,
q: searchTerm,
limit: encodeURIComponent(limit),
offset: encodeURIComponent(offset),
content: encodeURIComponent(isContent),
},
});
};
export const searchEntries =
({ journalId }) =>
({ searchTerm, limit, offset, isContent, journalType }) => {
const journalScope = journalType === "personal" ? "journals" : "public";
return http({
method: "GET",
url: `${API}/${journalScope}/${journalId}/search`,
params: {
// filters: searchTags,
q: searchTerm,
limit: encodeURIComponent(limit),
offset: encodeURIComponent(offset),
content: encodeURIComponent(isContent),
},
});
};
export const publicSearchEntries = ({ journalId }) => (query) =>
http({
method: "GET",
url: `${API}/public/${journalId}/search?q=${query}`,
});
export const publicSearchEntries =
({ journalId }) =>
(query) =>
http({
method: "GET",
url: `${API}/public/${journalId}/search?q=${query}`,
});
export const getPublicJournal = (key, { journalId }) =>
http({
@ -131,9 +125,11 @@ export const getPublicJournal = (key, { journalId }) =>
url: `${API}/public/${journalId}`,
});
export const getJournalStats = (key, { journalId }) => () =>
http({
method: "GET",
url: `${API}/journals/${journalId}/stats`,
params: { stats_version: 5 },
});
export const getJournalStats =
(key, { journalId }) =>
() =>
http({
method: "GET",
url: `${API}/journals/${journalId}/stats`,
params: { stats_version: 5 },
});

Wyświetl plik

@ -1,7 +1,7 @@
import moment from "moment";
const MOCK_API = process.env.NEXT_PUBLIC_SIMIOTICS_AUTH_URL;
var MockAdapter = require("axios-mock-adapter");
const makeid = (length) => {
export const makeid = (length) => {
var result = "";
var characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -12,7 +12,7 @@ const makeid = (length) => {
return result;
};
const makenum = (length) => {
export const makenum = (length) => {
var result = "";
var characters = "0123456789";
var charactersLength = characters.length;

Wyświetl plik

@ -1,4 +1,4 @@
import React from "@emotion/react";
import React from "react";
import { Box } from "@chakra-ui/react";
import { getLayout as getSiteLayout } from "./AppLayout";

Wyświetl plik

@ -1,4 +1,3 @@
import { Flex } from "@chakra-ui/react";
import { getLayout as getSiteLayout } from "./RootLayout";
import React, { useContext } from "react";

Wyświetl plik

@ -1,10 +1,10 @@
import React from "@emotion/react";
import React from "react";
import { Scrollable, Footer } from "../components";
import { getLayout as getSiteLayout } from "./index";
const DefaultLayout = (props) => {
return (
<Scrollable>
<Scrollable bgImg={""}>
{props.children}
<Footer />
</Scrollable>

Wyświetl plik

@ -1,4 +1,3 @@
import { jsx } from "@emotion/react";
import { Flex, Spinner } from "@chakra-ui/react";
import React, { Suspense, useContext, useState, useEffect } from "react";
const Sidebar = React.lazy(() => import("../components/Sidebar"));