From 38a9287b0a3b45a5b0a1c7191d96bdb4f0c79f3a Mon Sep 17 00:00:00 2001 From: AykutSarac Date: Wed, 2 Oct 2024 13:38:00 +0300 Subject: [PATCH] feat: remove supabase & cloud related actions --- .env | 2 - CONTRIBUTING.md | 2 +- README.md | 1 - default.conf | 8 - package.json | 5 +- pnpm-lock.yaml | 93 ------- public/robots.txt | 1 - public/sitemap.txt | 2 - .../Editor/components/BottomBar.tsx | 11 - src/containers/Modals/AccountModal/index.tsx | 68 ----- src/containers/Modals/ClearModal/index.tsx | 35 --- src/containers/Modals/CloudModal/index.tsx | 260 ------------------ src/containers/Modals/LoginModal/index.tsx | 24 -- src/containers/Modals/NoticeModal/index.tsx | 85 ------ src/containers/Modals/index.ts | 11 +- src/containers/Toolbar/AccountMenu.tsx | 52 +--- src/containers/Toolbar/ToolsMenu.tsx | 34 ++- src/containers/Toolbar/index.tsx | 7 - src/layout/ModalController.tsx | 4 - src/layout/Navbar.tsx | 28 +- src/lib/api/document.service.ts | 50 ---- src/lib/api/supabase.ts | 8 - src/pages/_app.tsx | 10 - src/pages/docs.tsx | 21 -- src/pages/forgot-password.tsx | 225 --------------- src/pages/oauth.tsx | 25 -- src/pages/sign-in.tsx | 198 ------------- src/pages/sign-up.tsx | 54 ---- src/store/useFile.ts | 15 - src/store/useModal.ts | 17 +- src/store/useUser.ts | 43 --- 31 files changed, 54 insertions(+), 1345 deletions(-) delete mode 100644 src/containers/Modals/AccountModal/index.tsx delete mode 100644 src/containers/Modals/ClearModal/index.tsx delete mode 100644 src/containers/Modals/CloudModal/index.tsx delete mode 100644 src/containers/Modals/LoginModal/index.tsx delete mode 100644 src/containers/Modals/NoticeModal/index.tsx delete mode 100644 src/lib/api/document.service.ts delete mode 100644 src/lib/api/supabase.ts delete mode 100644 src/pages/forgot-password.tsx delete mode 100644 src/pages/oauth.tsx delete mode 100644 src/pages/sign-in.tsx delete mode 100644 src/pages/sign-up.tsx delete mode 100644 src/store/useUser.ts diff --git a/.env b/.env index f016440..b0a489c 100644 --- a/.env +++ b/.env @@ -1,3 +1 @@ NEXT_PUBLIC_GA_MEASUREMENT_ID=G-JKZEHMJBMH -NEXT_PUBLIC_SUPABASE_URL=https://bxkgqurwqjmvrqekcbws.supabase.co -NEXT_PUBLIC_SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJ4a2dxdXJ3cWptdnJxZWtjYndzIiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTA2NDU0MjUsImV4cCI6MjAwNjIyMTQyNX0.3nZ0yhuFjnI3yHbAL8S9UtK-Ny-6F5AylNHgo1tymTU diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4a8d3e6..879600e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,7 +7,7 @@ Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approacha In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR. ## Getting Started -JSON Crack is built with React, Reaflow for visualization, Mantine UI for components, Zustand for state management, and Supabase for backend integration. If you are not familiar with these technologies, we recommend you to read their documentation to get started. You can find the links to the respective documentations below: +JSON Crack is built with React, Reaflow for visualization, Mantine UI for components, Zustand for state management. If you are not familiar with these technologies, we recommend you to read their documentation to get started. You can find the links to the respective documentations below: * [React](https://reactjs.org/docs/getting-started.html) * [Reaflow](https://github.com/reaviz/reaflow) diff --git a/README.md b/README.md index 16ec16b..e2b6f18 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,6 @@ JSON Crack is a free, open-source data visualization app capable of visualizing - [Next.js](https://nextjs.org/?ref=jsoncrack.com) - [React.js](https://reactjs.org/?ref=jsoncrack.com) -- [Supabase](https://supabase.com/?ref=jsoncrack.com) - [Reaflow](https://reaflow.dev/?ref=jsoncrack.com) - [Monaco Editor](https://github.com/suren-atoyan/monaco-react) diff --git a/default.conf b/default.conf index 4f310f8..ba264f5 100644 --- a/default.conf +++ b/default.conf @@ -14,12 +14,4 @@ server { location /docs { try_files $uri /docs.html; } - - location /forgot-password { - try_files $uri /forgot-password.html; - } - - location /sign-in { - try_files $uri /sign-in.html; - } } diff --git a/package.json b/package.json index 7ee7aa1..9ab516c 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ }, "homepage": "https://jsoncrack.com", "bugs": { - "url": "https://github.com/AykutSarac/jsoncrack.com/issues" - }, + "url": "https://github.com/AykutSarac/jsoncrack.com/issues" + }, "scripts": { "dev": "next dev", "build": "next build", @@ -25,7 +25,6 @@ "@mantine/hooks": "^7.11.2", "@monaco-editor/react": "^4.6.0", "@sentry/nextjs": "^7.118.0", - "@supabase/supabase-js": "^2.44.4", "@tanstack/react-query": "^4.36.1", "allotment": "^1.20.2", "axios": "^1.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 373275d..6a38fc5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,9 +26,6 @@ importers: '@sentry/nextjs': specifier: ^7.118.0 version: 7.118.0(next@14.2.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react@18.3.1) - '@supabase/supabase-js': - specifier: ^2.44.4 - version: 2.44.4 '@tanstack/react-query': specifier: ^4.36.1 version: 4.36.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -618,28 +615,6 @@ packages: resolution: {integrity: sha512-x0PYIMWcsTauqxgl7vWUY6sANl+XGKtx7DCVnnY7aOIIlIna0jChTAPANTfA2QrK+VK+4I/4JxatCEZBnXh3Og==} engines: {node: '>= 8'} - '@supabase/auth-js@2.64.4': - resolution: {integrity: sha512-9ITagy4WP4FLl+mke1rchapOH0RQpf++DI+WSG2sO1OFOZ0rW3cwAM0nCrMOxu+Zw4vJ4zObc08uvQrXx590Tg==} - - '@supabase/functions-js@2.4.1': - resolution: {integrity: sha512-8sZ2ibwHlf+WkHDUZJUXqqmPvWQ3UHN0W30behOJngVh/qHHekhJLCFbh0AjkE9/FqqXtf9eoVvmYgfCLk5tNA==} - - '@supabase/node-fetch@2.6.15': - resolution: {integrity: sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==} - engines: {node: 4.x || >=6.0.0} - - '@supabase/postgrest-js@1.15.8': - resolution: {integrity: sha512-YunjXpoQjQ0a0/7vGAvGZA2dlMABXFdVI/8TuVKtlePxyT71sl6ERl6ay1fmIeZcqxiuFQuZw/LXUuStUG9bbg==} - - '@supabase/realtime-js@2.10.2': - resolution: {integrity: sha512-qyCQaNg90HmJstsvr2aJNxK2zgoKh9ZZA8oqb7UT2LCh3mj9zpa3Iwu167AuyNxsxrUE8eEJ2yH6wLCij4EApA==} - - '@supabase/storage-js@2.6.0': - resolution: {integrity: sha512-REAxr7myf+3utMkI2oOmZ6sdplMZZ71/2NEIEMBZHL9Fkmm3/JnaOZVSRqvG4LStYj2v5WhCruCzuMn6oD/Drw==} - - '@supabase/supabase-js@2.44.4': - resolution: {integrity: sha512-vqtUp8umqcgj+RPUc7LiEcQmgsEWFDPJdJizRJF/5tf2zSlVB+3YbUwyQE/hLagYA8TLvGXe7oAqtYyFde6llw==} - '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} @@ -706,9 +681,6 @@ packages: '@types/node@20.14.11': resolution: {integrity: sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==} - '@types/phoenix@1.6.5': - resolution: {integrity: sha512-xegpDuR+z0UqG9fwHqNoy3rI7JDlvaPh2TY47Fl80oq6g+hXT+c/LEuE43X48clZ6lOfANl5WrPur9fYO1RJ/w==} - '@types/prop-types@15.7.12': resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} @@ -724,9 +696,6 @@ packages: '@types/stylis@4.2.5': resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} - '@types/ws@8.5.11': - resolution: {integrity: sha512-4+q7P5h3SpJxaBft0Dzpbr6lmMaqh0Jr2tbhJZ/luAwvD7ohSCniYkwz/pLxuT2h0EOa6QADgJj1Ko+TzRfZ+w==} - '@typescript-eslint/eslint-plugin@7.17.0': resolution: {integrity: sha512-pyiDhEuLM3PuANxH7uNYan1AaFs5XE0zw1hq69JBvGvE7gSuEoQl1ydtEe/XQeoC3GQxLXyOVa5kNOATgM638A==} engines: {node: ^18.18.0 || >=20.0.0} @@ -2793,18 +2762,6 @@ packages: utf-8-validate: optional: true - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - xmldom@0.1.31: resolution: {integrity: sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==} engines: {node: '>=0.1'} @@ -3332,48 +3289,6 @@ snapshots: - encoding - supports-color - '@supabase/auth-js@2.64.4': - dependencies: - '@supabase/node-fetch': 2.6.15 - - '@supabase/functions-js@2.4.1': - dependencies: - '@supabase/node-fetch': 2.6.15 - - '@supabase/node-fetch@2.6.15': - dependencies: - whatwg-url: 5.0.0 - - '@supabase/postgrest-js@1.15.8': - dependencies: - '@supabase/node-fetch': 2.6.15 - - '@supabase/realtime-js@2.10.2': - dependencies: - '@supabase/node-fetch': 2.6.15 - '@types/phoenix': 1.6.5 - '@types/ws': 8.5.11 - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - - '@supabase/storage-js@2.6.0': - dependencies: - '@supabase/node-fetch': 2.6.15 - - '@supabase/supabase-js@2.44.4': - dependencies: - '@supabase/auth-js': 2.64.4 - '@supabase/functions-js': 2.4.1 - '@supabase/node-fetch': 2.6.15 - '@supabase/postgrest-js': 1.15.8 - '@supabase/realtime-js': 2.10.2 - '@supabase/storage-js': 2.6.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - '@swc/counter@0.1.3': {} '@swc/helpers@0.5.5': @@ -3431,8 +3346,6 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/phoenix@1.6.5': {} - '@types/prop-types@15.7.12': {} '@types/react-dom@18.3.0': @@ -3449,10 +3362,6 @@ snapshots: '@types/stylis@4.2.5': {} - '@types/ws@8.5.11': - dependencies: - '@types/node': 20.14.11 - '@typescript-eslint/eslint-plugin@7.17.0(@typescript-eslint/parser@7.17.0(eslint@8.56.0)(typescript@5.3.3))(eslint@8.56.0)(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.11.0 @@ -5771,8 +5680,6 @@ snapshots: ws@7.5.10: {} - ws@8.18.0: {} - xmldom@0.1.31: {} yn@3.1.1: {} diff --git a/public/robots.txt b/public/robots.txt index 37d92c8..b469530 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -2,7 +2,6 @@ User-agent: * Allow: / User-agent: * -Disallow: /forgot-password Disallow: /widget Sitemap: https://jsoncrack.com/sitemap.txt diff --git a/public/sitemap.txt b/public/sitemap.txt index ce50d54..2e6bb1f 100644 --- a/public/sitemap.txt +++ b/public/sitemap.txt @@ -1,6 +1,4 @@ https://jsoncrack.com -https://jsoncrack.com/sign-in -https://jsoncrack.com/sign-up https://jsoncrack.com/editor https://jsoncrack.com/docs https://jsoncrack.com/widget diff --git a/src/containers/Editor/components/BottomBar.tsx b/src/containers/Editor/components/BottomBar.tsx index e289e13..5533e93 100644 --- a/src/containers/Editor/components/BottomBar.tsx +++ b/src/containers/Editor/components/BottomBar.tsx @@ -9,14 +9,12 @@ import { VscError, VscFeedback, VscRunAll, - VscSourceControl, VscSync, VscSyncIgnored, } from "react-icons/vsc"; import useGraph from "src/containers/Editor/components/views/GraphView/stores/useGraph"; import useConfig from "src/store/useConfig"; import useFile from "src/store/useFile"; -import useModal from "src/store/useModal"; const StyledBottomBar = styled.div` position: relative; @@ -88,12 +86,9 @@ export const BottomBar = () => { const error = useFile(state => state.error); const setContents = useFile(state => state.setContents); const nodeCount = useGraph(state => state.nodes.length); - const fileName = useFile(state => state.fileData?.name); const toggleFullscreen = useGraph(state => state.toggleFullscreen); const fullscreen = useGraph(state => state.fullscreen); - const setVisible = useModal(state => state.setVisible); - const toggleEditor = () => { toggleFullscreen(!fullscreen); gaEvent("toggle_fullscreen"); @@ -109,12 +104,6 @@ export const BottomBar = () => { - {fileName && ( - setVisible("cloud")(true)}> - - {fileName} - - )} {error ? ( diff --git a/src/containers/Modals/AccountModal/index.tsx b/src/containers/Modals/AccountModal/index.tsx deleted file mode 100644 index b832936..0000000 --- a/src/containers/Modals/AccountModal/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from "react"; -import type { ModalProps } from "@mantine/core"; -import { Modal, Group, Button, Avatar, Text, Divider, Paper, Badge, Anchor } from "@mantine/core"; -import useUser from "src/store/useUser"; - -export const AccountModal = ({ opened, onClose }: ModalProps) => { - const user = useUser(state => state.user); - const logout = useUser(state => state.logout); - - const username = - user?.user_metadata.full_name || user?.user_metadata.display_name || user?.user_metadata.name; - - return ( - - - - - JC - -
- - {username} - - - - - {user?.email} - - - - - - - Free - - - -
-
-
- - If you're already a premium user, please login at{" "} - - ToDiagram - - . - - - - - -
- ); -}; diff --git a/src/containers/Modals/ClearModal/index.tsx b/src/containers/Modals/ClearModal/index.tsx deleted file mode 100644 index ae57d11..0000000 --- a/src/containers/Modals/ClearModal/index.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from "react"; -import { useRouter } from "next/router"; -import type { ModalProps } from "@mantine/core"; -import { Modal, Group, Button, Text, Divider } from "@mantine/core"; -import { documentSvc } from "src/lib/api/document.service"; -import useJson from "src/store/useJson"; - -export const ClearModal = ({ opened, onClose }: ModalProps) => { - const setJson = useJson(state => state.setJson); - const { query, replace } = useRouter(); - - const handleClear = () => { - setJson("{}"); - onClose(); - - if (typeof query.json === "string") { - documentSvc.delete(query.json); - replace("/editor"); - } - }; - - return ( - - - Are you sure you want to delete JSON? - - - - - - - ); -}; diff --git a/src/containers/Modals/CloudModal/index.tsx b/src/containers/Modals/CloudModal/index.tsx deleted file mode 100644 index 671f158..0000000 --- a/src/containers/Modals/CloudModal/index.tsx +++ /dev/null @@ -1,260 +0,0 @@ -import React from "react"; -import { useRouter } from "next/router"; -import type { ModalProps, DefaultMantineColor } from "@mantine/core"; -import { - Text, - ScrollArea, - Table, - ActionIcon, - Badge, - Paper, - Flex, - Button, - RingProgress, - Drawer, - LoadingOverlay, - Menu, - TextInput, - Alert, -} from "@mantine/core"; -import { useDebouncedValue } from "@mantine/hooks"; -import { useQuery } from "@tanstack/react-query"; -import dayjs from "dayjs"; -import relativeTime from "dayjs/plugin/relativeTime"; -import { event as gaEvent } from "nextjs-google-analytics"; -import toast from "react-hot-toast"; -import { BiSearch } from "react-icons/bi"; -import { FaTrash } from "react-icons/fa"; -import { LuDownload } from "react-icons/lu"; -import { SlOptionsVertical } from "react-icons/sl"; -import { VscAdd, VscWarning } from "react-icons/vsc"; -import type { FileFormat } from "src/enums/file.enum"; -import { documentSvc } from "src/lib/api/document.service"; -import type { File } from "src/store/useFile"; -import useFile from "src/store/useFile"; -import useModal from "src/store/useModal"; - -dayjs.extend(relativeTime); - -const colorByFormat: Record = { - json: "orange", - yaml: "blue", - xml: "red", - toml: "dark", - csv: "grape", -}; - -const TOTAL_QUOTA = 25; - -export const CloudModal = ({ opened, onClose }: ModalProps) => { - const setVisible = useModal(state => state.setVisible); - const setFile = useFile(state => state.setFile); - const [searchValue, setSearchValue] = React.useState(""); - const [debouncedSearchValue] = useDebouncedValue(searchValue, 1000); - const { isReady, replace } = useRouter(); - - const { data, isLoading, refetch } = useQuery( - ["allJson", debouncedSearchValue], - () => documentSvc.getAll(debouncedSearchValue), - { enabled: isReady && opened } - ); - - const isCreateDisabled = React.useMemo(() => { - if (!data?.length) return false; - return data.length >= TOTAL_QUOTA; - }, [data?.length]); - - const onCreate = async () => { - replace({ query: undefined }); - onClose(); - }; - - const openFile = React.useCallback( - async (id: string) => { - try { - const { data, error } = await documentSvc.getById(id); - if (error) throw new Error(error.message); - - if (data[0]) setFile(data[0]); - gaEvent("open_cloud_file"); - } catch (error) { - if (error instanceof Error) toast.error(error.message); - } finally { - onClose(); - } - }, - [onClose, setFile] - ); - - const downloadFile = React.useCallback(async (id: string) => { - try { - // it will fetch the file first, then download it with corresponsing format - const { data, error } = await documentSvc.getById(id); - if (error) throw new Error(error.message); - - const blob = new Blob([data[0].content], { type: "text/plain" }); - const url = URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = `${data[0].name}.${data[0].format}`; - a.click(); - URL.revokeObjectURL(url); - - gaEvent("download_cloud_file"); - - return true; - } catch (error) { - if (error instanceof Error) { - toast.error(error.message); - } - return false; - } - }, []); - - const onDeleteClick = React.useCallback( - async (file: File) => { - try { - toast.loading("Deleting file...", { id: "delete-file" }); - - const { error } = await documentSvc.delete(file.id); - if (error) throw new Error(error.message); - - await refetch(); - toast.success(`Deleted ${file.name}!`, { id: "delete-file" }); - gaEvent("delete_cloud_file"); - } catch (error) { - if (error instanceof Error) { - toast.error(error.message, { id: "delete-file" }); - } - } finally { - toast.dismiss("delete-file"); - } - }, - [refetch] - ); - - const rows = React.useMemo( - () => - data?.map(element => ( - openFile(element.id)} - style={{ cursor: "pointer" }} - > - - - {element.format.toUpperCase()} - - - {element.name} - - {dayjs(element.updated_at).fromNow()} - - e.stopPropagation()}> - - - - - - - - - downloadFile(element.id)} - leftSection={} - > - Download - - - onDeleteClick(element)} - leftSection={} - > - Delete - - - - - - - )), - [data, downloadFile, onDeleteClick, openFile] - ); - - return ( - - }> - Cloud storage will be terminated on 1 October 2024. Please download your data before - the deadline. - - - - The Cloud Save feature is primarily designed for convenient access and is not advisable for - storing sensitive data. - - - setSearchValue(e.currentTarget.value)} - size="xs" - mb="sm" - placeholder="Search" - leftSection={} - /> - - - - {rows} -
-
- {data && ( - - - - TOTAL_QUOTA / 1.5 ? "red" : "blue", - }, - ]} - /> - - {data.length} / {TOTAL_QUOTA} - - - - )} -
-
- ); -}; diff --git a/src/containers/Modals/LoginModal/index.tsx b/src/containers/Modals/LoginModal/index.tsx deleted file mode 100644 index de3b56b..0000000 --- a/src/containers/Modals/LoginModal/index.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import React from "react"; -import Link from "next/link"; -import type { ModalProps } from "@mantine/core"; -import { Modal, Stack, Button } from "@mantine/core"; - -export const LoginModal = ({ opened, onClose }: ModalProps) => { - return ( - - - - - - ); -}; diff --git a/src/containers/Modals/NoticeModal/index.tsx b/src/containers/Modals/NoticeModal/index.tsx deleted file mode 100644 index 37fff04..0000000 --- a/src/containers/Modals/NoticeModal/index.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import React from "react"; -import type { ModalProps } from "@mantine/core"; -import { Anchor, Button, Center, Divider, Group, Modal, Text } from "@mantine/core"; -import { useLocalStorage } from "@mantine/hooks"; -import useModal from "src/store/useModal"; -import useUser from "src/store/useUser"; - -export const NoticeModal = (props: ModalProps) => { - const isAuthenticated = useUser(state => state.isAuthenticated); - const setVisible = useModal(state => state.setVisible); - const [seenModal, setSeenModal] = useLocalStorage({ - key: "seenNoticeModal", - defaultValue: false, - getInitialValueInEffect: false, - }); - - const closeModal = () => { - setSeenModal(true); - props.onClose?.(); - }; - - if (!isAuthenticated) return null; - - return ( - - Important Notice: Changes to Free Version - - } - opened={!seenModal || props.opened} - onClose={closeModal} - centered - zIndex={1000} - size="lg" - > -
- - Hello, -
-
- We want to inform you that starting from 1 October 2024, the following features will - be removed from the free version of our service: -
-
- • Sign-in / Sign-up -
- • Cloud Storage -
- • Share -
-
- - Any cloud-stored data that has not been accessed in the past 4 months will be - automatically deleted at 1 October 2024. - -
- To ensure you don't lose any important data, please download your data before the - deadline. If you wish to continue using these features, we recommend upgrading to{" "} - - ToDiagram - - , which will allow you to retain full access to these services and more. -
-
- Thank you for your understanding and continued support. -
- - - - - -
- ); -}; diff --git a/src/containers/Modals/index.ts b/src/containers/Modals/index.ts index 4705e26..f581f0b 100644 --- a/src/containers/Modals/index.ts +++ b/src/containers/Modals/index.ts @@ -1,31 +1,22 @@ -export { CloudModal } from "./CloudModal"; -export { ClearModal } from "./ClearModal"; export { DownloadModal } from "./DownloadModal"; export { ImportModal } from "./ImportModal"; -export { AccountModal } from "./AccountModal"; export { NodeModal } from "./NodeModal"; -export { LoginModal } from "./LoginModal"; export { UpgradeModal } from "./UpgradeModal"; export { JWTModal } from "./JWTModal"; export { SchemaModal } from "./SchemaModal"; export { JQModal } from "./JQModal"; export { TypeModal } from "./TypeModal"; export { JPathModal } from "./JPathModal"; -export { NoticeModal } from "./NoticeModal"; type Modal = - | "cloud" | "download" | "import" - | "account" | "node" - | "login" | "upgrade" | "jwt" | "schema" | "jq" | "type" - | "jpath" - | "notice"; + | "jpath"; export type { Modal }; diff --git a/src/containers/Toolbar/AccountMenu.tsx b/src/containers/Toolbar/AccountMenu.tsx index 57dae29..4516357 100644 --- a/src/containers/Toolbar/AccountMenu.tsx +++ b/src/containers/Toolbar/AccountMenu.tsx @@ -1,56 +1,28 @@ import React from "react"; -import Link from "next/link"; import { Menu, Avatar, Text } from "@mantine/core"; -import { VscSignIn, VscFeedback, VscSignOut } from "react-icons/vsc"; -import useModal from "src/store/useModal"; -import useUser from "src/store/useUser"; +import { FaRegCircleUser } from "react-icons/fa6"; +import { VscSignIn } from "react-icons/vsc"; import { StyledToolElement } from "./styles"; export const AccountMenu = () => { - const user = useUser(state => state.user?.user_metadata); - const logout = useUser(state => state.logout); - const setVisible = useModal(state => state.setVisible); - - const username = user?.full_name || user?.display_name || user?.name; - return ( - - {user && "JC"} + + - {user ? ( - } - onClick={() => setVisible("account")(true)} - closeMenuOnClick - > - {username ?? "Account"} - - ) : ( - - }> - Sign in - - - )} - {user && ( - <> - - - } closeMenuOnClick> - Feedback - - - } onClick={() => logout()} closeMenuOnClick> - Log out - - - )} + } + > + Sign up + ); diff --git a/src/containers/Toolbar/ToolsMenu.tsx b/src/containers/Toolbar/ToolsMenu.tsx index 8ea2435..e52733d 100644 --- a/src/containers/Toolbar/ToolsMenu.tsx +++ b/src/containers/Toolbar/ToolsMenu.tsx @@ -6,6 +6,7 @@ import toast from "react-hot-toast"; import { CgChevronDown } from "react-icons/cg"; import { FaRandom } from "react-icons/fa"; import { FaWandMagicSparkles } from "react-icons/fa6"; +import { LuGlobe } from "react-icons/lu"; import { MdCompare, MdFilterListAlt } from "react-icons/md"; import { SiJsonwebtokens } from "react-icons/si"; import { VscSearchFuzzy, VscJson, VscGroupByRefType, VscLock } from "react-icons/vsc"; @@ -86,17 +87,6 @@ export const ToolsMenu = () => { JSON Path - } - rightSection={} - onClick={() => { - setVisible("upgrade")(true); - gaEvent("open_ai_filter_modal"); - }} - > - AI-Powered Filter - } @@ -120,6 +110,28 @@ export const ToolsMenu = () => { } onClick={randomizeData}> Randomize Data + } + rightSection={} + onClick={() => { + setVisible("upgrade")(true); + gaEvent("rest_client_modal"); + }} + > + REST Client + + } + rightSection={} + onClick={() => { + setVisible("upgrade")(true); + gaEvent("open_ai_filter_modal"); + }} + > + AI-Powered Filter + } diff --git a/src/containers/Toolbar/index.tsx b/src/containers/Toolbar/index.tsx index 96589fc..22ae579 100644 --- a/src/containers/Toolbar/index.tsx +++ b/src/containers/Toolbar/index.tsx @@ -10,7 +10,6 @@ import { FileFormat } from "src/enums/file.enum"; import { JSONCrackLogo } from "src/layout/JsonCrackLogo"; import useFile from "src/store/useFile"; import useModal from "src/store/useModal"; -import useUser from "src/store/useUser"; import { AccountMenu } from "./AccountMenu"; import { FileMenu } from "./FileMenu"; import { Logo } from "./Logo"; @@ -57,7 +56,6 @@ export const Toolbar = ({ isWidget = false }: ToolbarProps) => { const setVisible = useModal(state => state.setVisible); const setFormat = useFile(state => state.setFormat); const format = useFile(state => state.format); - const isAuthenticated = useUser(state => state.isAuthenticated); return ( @@ -90,11 +88,6 @@ export const Toolbar = ({ isWidget = false }: ToolbarProps) => { - {isAuthenticated && ( - setVisible("cloud")(true)}> - Cloud - - )} )} diff --git a/src/layout/ModalController.tsx b/src/layout/ModalController.tsx index 9ba8f78..47aceb7 100644 --- a/src/layout/ModalController.tsx +++ b/src/layout/ModalController.tsx @@ -9,17 +9,13 @@ type ModalComponent = { key: Modal; component: React.FC }; const modalComponents: ModalComponent[] = [ { key: "import", component: Modals.ImportModal }, { key: "download", component: Modals.DownloadModal }, - { key: "cloud", component: Modals.CloudModal }, - { key: "account", component: Modals.AccountModal }, { key: "upgrade", component: Modals.UpgradeModal }, - { key: "login", component: Modals.LoginModal }, { key: "jwt", component: Modals.JWTModal }, { key: "node", component: Modals.NodeModal }, { key: "schema", component: Modals.SchemaModal }, { key: "jq", component: Modals.JQModal }, { key: "type", component: Modals.TypeModal }, { key: "jpath", component: Modals.JPathModal }, - { key: "notice", component: Modals.NoticeModal }, ]; const ModalController = () => { diff --git a/src/layout/Navbar.tsx b/src/layout/Navbar.tsx index 13eb67b..52ea4e0 100644 --- a/src/layout/Navbar.tsx +++ b/src/layout/Navbar.tsx @@ -58,16 +58,6 @@ export const Navbar = () => {
- -
- + + + - - ) : ( -
- {errorMessage && ( - setErrorMessage(null)} - color="red" - py="xs" - mb="lg" - icon={} - withCloseButton - > - - {errorMessage} - - - )} - - - setEmail(e.target.value)} - required - label="Email" - placeholder="hello@jsoncrack.com" - radius="sm" - style={{ color: "black" }} - data-autofocus - /> - - - - - - -
- )} - - - Don't have an account? - - Sign up - - - - - )} - - ); -}; - -export default ForgotPassword; diff --git a/src/pages/oauth.tsx b/src/pages/oauth.tsx deleted file mode 100644 index f88d6a4..0000000 --- a/src/pages/oauth.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { useEffect } from "react"; -import { useRouter } from "next/router"; -import { NextSeo } from "next-seo"; -import { SEO } from "src/constants/seo"; -import { supabase } from "src/lib/api/supabase"; - -const Oauth = () => { - const { push } = useRouter(); - - useEffect(() => { - supabase.auth.getSession().then(({ data, error }) => { - if (error) return console.error(error); - if (!data.session) return; - push("/editor"); - }); - }, [push]); - - return ( - <> - - - ); -}; - -export default Oauth; diff --git a/src/pages/sign-in.tsx b/src/pages/sign-in.tsx deleted file mode 100644 index 2cbaa4d..0000000 --- a/src/pages/sign-in.tsx +++ /dev/null @@ -1,198 +0,0 @@ -import React, { useEffect } from "react"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { - TextInput, - PasswordInput, - Button, - Anchor, - Stack, - Center, - Text, - FocusTrap, - Alert, - Box, - Flex, -} from "@mantine/core"; -import { NextSeo } from "next-seo"; -import { AiOutlineGithub } from "react-icons/ai"; -import { FcGoogle } from "react-icons/fc"; -import { MdErrorOutline } from "react-icons/md"; -import { SEO } from "src/constants/seo"; -import { AuthLayout } from "src/layout/AuthLayout"; -import { supabase } from "src/lib/api/supabase"; -import useUser from "src/store/useUser"; - -export function AuthenticationForm() { - const { push } = useRouter(); - const setSession = useUser(state => state.setSession); - const isAuthenticated = useUser(state => state.isAuthenticated); - const [errorMessage, setErrorMessage] = React.useState(null); - const [loading, setLoading] = React.useState(false); - const [userData, setUserData] = React.useState({ - name: "", - email: "", - password: "", - }); - - const onSubmit = async (e: React.FormEvent) => { - e.preventDefault(); - setLoading(true); - - const { data, error } = await supabase.auth.signInWithPassword({ - email: userData.email, - password: userData.password, - }); - - if (error) { - setLoading(false); - return setErrorMessage("Incorrect email or password."); - } - - setSession(data.session); - push("/editor"); - }; - - const handleLoginClick = async (provider: "github" | "google") => { - await supabase.auth.signInWithOAuth({ - provider, - options: { redirectTo: `${window.location.origin}/oauth` }, - }); - }; - - if (isAuthenticated) { - return ( - - - You are already signed in. Click the button below to go to the editor. - - - - - - ); - } - - return ( - - {errorMessage && ( - setErrorMessage(null)} - color="red" - py="xs" - mb="lg" - icon={} - withCloseButton - > - - {errorMessage} - - - )} - -
- - setUserData(d => ({ ...d, email: event.target.value }))} - radius="sm" - style={{ color: "black" }} - withAsterisk={false} - /> - - setUserData(d => ({ ...d, password: event.target.value }))} - radius="sm" - style={{ color: "black" }} - withAsterisk={false} - /> - - - Forgot password? - - - -
-
- - - - - -
- ); -} - -const SignIn = () => { - const { push, query, pathname } = useRouter(); - - useEffect(() => { - supabase.auth.getSession().then(({ data, error }) => { - if (error) return console.error(error); - if (!data.session) return; - push("/editor"); - }); - }, [pathname, push, query.code]); - - return ( - - - -
- - Don't have an account? - - Sign up - - -
-
- ); -}; - -export default SignIn; diff --git a/src/pages/sign-up.tsx b/src/pages/sign-up.tsx deleted file mode 100644 index 3deda58..0000000 --- a/src/pages/sign-up.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useEffect } from "react"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import { Anchor, Button, Center, Text } from "@mantine/core"; -import { NextSeo } from "next-seo"; -import { SEO } from "src/constants/seo"; -import { AuthLayout } from "src/layout/AuthLayout"; -import { supabase } from "src/lib/api/supabase"; - -const SignUp = () => { - const { push } = useRouter(); - - useEffect(() => { - supabase.auth.getSession().then(({ data }) => { - if (data.session) push("/editor"); - }); - }, [push]); - - return ( - - - JSON Crack is no longer accepting new sign-ups. - - For advanced features, please visit{" "} - - ToDiagram - - , or you can continue using JSON Crack without an account. - -
- - - -
-
- - Already have an account? - - Sign in - - -
-
- ); -}; - -export default SignUp; diff --git a/src/store/useFile.ts b/src/store/useFile.ts index a962d37..9d4c35e 100644 --- a/src/store/useFile.ts +++ b/src/store/useFile.ts @@ -3,7 +3,6 @@ import { event as gaEvent } from "nextjs-google-analytics"; import { toast } from "react-hot-toast"; import { create } from "zustand"; import { FileFormat } from "src/enums/file.enum"; -import { documentSvc } from "src/lib/api/document.service"; import { isIframe } from "src/lib/utils/helpers"; import { contentToJson, jsonToContent } from "src/lib/utils/jsonAdapter"; import useGraph from "../containers/Editor/components/views/GraphView/stores/useGraph"; @@ -64,7 +63,6 @@ interface JsonActions { setError: (error: string | null) => void; setHasChanges: (hasChanges: boolean) => void; setContents: (data: SetContents) => void; - fetchFile: (fileId: string) => void; fetchUrl: (url: string) => void; setFormat: (format: FileFormat) => void; clear: () => void; @@ -182,7 +180,6 @@ const useFile = create()((set, get) => ({ checkEditorSession: (url, widget) => { if (url && typeof url === "string") { if (isURL(url)) return get().fetchUrl(url); - return get().fetchFile(url); } let contents = defaultJson; @@ -193,18 +190,6 @@ const useFile = create()((set, get) => ({ if (format) set({ format }); get().setContents({ contents, hasChanges: false }); }, - fetchFile: async id => { - try { - const { data, error } = await documentSvc.getById(id); - if (error) throw error; - - if (data?.length) get().setFile(data[0]); - if (data?.length === 0) throw new Error("Document not found"); - } catch (error: any) { - if (error?.message) toast.error(error?.message); - get().setContents({ contents: defaultJson, hasChanges: false }); - } - }, })); export default useFile; diff --git a/src/store/useModal.ts b/src/store/useModal.ts index e75692a..c40f396 100644 --- a/src/store/useModal.ts +++ b/src/store/useModal.ts @@ -1,6 +1,5 @@ import { create } from "zustand"; import type { Modal } from "src/containers/Modals"; -import useUser from "./useUser"; type ModalState = { [key in Modal]: boolean; @@ -11,34 +10,20 @@ interface ModalActions { } const initialStates: ModalState = { - cloud: false, download: false, import: false, - account: false, node: false, - login: false, upgrade: false, jwt: false, schema: false, jq: false, type: false, jpath: false, - notice: false, }; -const authModals: Modal[] = ["cloud", "account"]; - const useModal = create()(set => ({ ...initialStates, - setVisible: modal => visible => { - const user = useUser.getState(); - - if (authModals.includes(modal) && !user.isAuthenticated) { - return set({ login: true }); - } - - set({ [modal]: visible }); - }, + setVisible: modal => visible => set({ [modal]: visible }), })); export default useModal; diff --git a/src/store/useUser.ts b/src/store/useUser.ts deleted file mode 100644 index 933aa56..0000000 --- a/src/store/useUser.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { Session, User } from "@supabase/supabase-js"; -import { event as gaEvent } from "nextjs-google-analytics"; -import toast from "react-hot-toast"; -import { create } from "zustand"; -import { supabase } from "src/lib/api/supabase"; - -interface UserActions { - logout: () => void; - setSession: (session: Session) => void; -} - -interface UserStates { - user: User | null; - isAuthenticated: boolean; -} - -const initialStates: UserStates = { - user: null, - isAuthenticated: false, -}; - -const useUser = create()(set => ({ - ...initialStates, - setSession: async session => { - gaEvent("login"); - set({ user: session.user, isAuthenticated: true }); - }, - logout: async () => { - toast.loading("Logging out...", { id: "logout" }); - - const { error } = await supabase.auth.signOut({ scope: "local" }); - if (error) { - toast.error("Failed to log out."); - return; - } - - gaEvent("logout"); - set(initialStates); - toast.success("Logged out.", { id: "logout" }); - }, -})); - -export default useUser;