improve parsing ui

This commit is contained in:
AykutSarac 2022-12-10 17:08:42 +03:00
parent 5da20fa5be
commit 8225bc2986
16 changed files with 73 additions and 115 deletions

View File

@ -1,3 +1,3 @@
NEXT_PUBLIC_BASE_URL=http://localhost:3000
NEXT_ALTOGIC_ENV_URL=https://815e-4e5a.c5-na.altogic.com/
NEXT_ALTOGIC_CLIENT_KEY=f1e92022789f4ccf91273a345ab2bdf8
NEXT_PUBLIC_ALTOGIC_ENV_URL=https://815e-4e5a.c5-na.altogic.com/
NEXT_PUBLIC_ALTOGIC_CLIENT_KEY=f1e92022789f4ccf91273a345ab2bdf8

View File

@ -1 +1,3 @@
NEXT_PUBLIC_BASE_URL=https://jsoncrack.com
NEXT_PUBLIC_BASE_URL=https://jsoncrack.com
NEXT_PUBLIC_ALTOGIC_ENV_URL=https://815e-4e5a.c5-na.altogic.com/
NEXT_PUBLIC_ALTOGIC_CLIENT_KEY=f1e92022789f4ccf91273a345ab2bdf8

View File

@ -20,7 +20,6 @@
"allotment": "^1.17.0",
"altogic": "^2.3.8",
"axios": "^1.1.3",
"compress-json": "^2.1.2",
"dayjs": "^1.11.6",
"html-to-image": "^1.10.8",
"jsonc-parser": "^3.2.0",

8
src/api/altogic.ts Normal file
View File

@ -0,0 +1,8 @@
import { createClient } from "altogic";
let envUrl = process.env.NEXT_PUBLIC_ALTOGIC_ENV_URL as string;
let clientKey = process.env.NEXT_PUBLIC_ALTOGIC_CLIENT_KEY as string;
const altogic = createClient(envUrl, clientKey);
export { altogic };

View File

@ -35,7 +35,7 @@ const StyledButton = styled.button<{
background: ${({ status, theme }) => getButtonStatus(status, theme)};
color: #ffffff;
padding: 8px 16px;
min-width: 60px;
min-width: 70px;
min-height: 32px;
border-radius: 3px;
font-size: 14px;

View File

@ -54,14 +54,16 @@ export const MonacoEditor = () => {
const debouncedSetJson = React.useMemo(
() =>
debounce(value => {
if (!value) return;
if (!value || hasError) return;
setJson(value);
}, 1200),
[setJson]
[hasError, setJson]
);
React.useEffect(() => {
if (!hasError) debouncedSetJson(value);
return () => debouncedSetJson.cancel();
}, [debouncedSetJson, hasError, value]);
return (
@ -73,8 +75,8 @@ export const MonacoEditor = () => {
theme={lightmode}
options={editorOptions}
onChange={val => {
if (json) setConfig("hasChanges", true);
setValue(val);
if (json) setConfig("hasChanges", true);
}}
loading={<Loading message="Loading Editor..." />}
beforeMount={handleEditorWillMount}

View File

@ -10,7 +10,7 @@ import {
AiOutlineUnlock,
} from "react-icons/ai";
import { VscAccount } from "react-icons/vsc";
import { altogic } from "src/services/altogic";
import { altogic } from "src/api/altogic";
import { getJson, saveJson, updateJson } from "src/services/db/json";
import useConfig from "src/store/useConfig";
import useGraph from "src/store/useGraph";
@ -125,10 +125,12 @@ export const BottomBar = () => {
{isPrivate ? <AiOutlineLock /> : <AiOutlineUnlock />}
{isPrivate ? "Private" : "Public"}
</StyledBottomBarItem>
<StyledBottomBarItem onClick={() => setVisible("share")(true)}>
<AiOutlineLink />
Share
</StyledBottomBarItem>
{query.json && (
<StyledBottomBarItem onClick={() => setVisible("share")(true)}>
<AiOutlineLink />
Share
</StyledBottomBarItem>
)}
</StyledLeft>
<StyledRight>
<StyledBottomBarItem>

View File

@ -1,20 +1,28 @@
import React from "react";
import { useRouter } from "next/router";
import { Button } from "src/components/Button";
import { Modal, ModalProps } from "src/components/Modal";
import { deleteJson } from "src/services/db/json";
import useGraph from "src/store/useGraph";
export const ClearModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
const setJson = useGraph(state => state.setJson);
const { query, replace } = useRouter();
const handleClear = () => {
setJson("{}");
setVisible(false);
if (typeof query.json === "string") {
deleteJson(query.json);
replace("/editor");
}
};
return (
<Modal visible={visible} setVisible={setVisible}>
<Modal.Header>Clear JSON</Modal.Header>
<Modal.Content>Are you sure you want to clear JSON?</Modal.Content>
<Modal.Header>Delete JSON</Modal.Header>
<Modal.Content>Are you sure you want to delete JSON?</Modal.Content>
<Modal.Controls setVisible={setVisible}>
<Button status="DANGER" onClick={handleClear}>
Confirm

View File

@ -6,6 +6,7 @@ import { AiOutlinePlus } from "react-icons/ai";
import { Modal, ModalProps } from "src/components/Modal";
import { getAllJson } from "src/services/db/json";
import styled from "styled-components";
import { useRouter } from "next/router";
dayjs.extend(relativeTime);
@ -64,7 +65,7 @@ const GraphCard: React.FC<{ data: GraphCardProsp }> = ({
...props
}) => (
<StyledJsonCard href={`?json=${id}`} {...props}>
<StyledImg width="200" height="100" src={preview}></StyledImg>
<StyledImg width="200" height="100" src={preview} />
<StyledInfo>
<StyledTitle>{title}</StyledTitle>
<StyledDetils>{details}</StyledDetils>
@ -90,7 +91,8 @@ const CreateCard: React.FC = () => (
);
export const CloudModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
const { data, isLoading } = useQuery(["allJson"], () => getAllJson());
const { query } = useRouter();
const { data, isLoading } = useQuery(["allJson", query], () => getAllJson());
if (isLoading) return <div>loading</div>;
return (

View File

@ -1,26 +1,11 @@
import React from "react";
import { useRouter } from "next/router";
import { compress } from "compress-json";
import toast from "react-hot-toast";
import { BiErrorAlt } from "react-icons/bi";
import { Button } from "src/components/Button";
import { Input } from "src/components/Input";
import { Modal, ModalProps } from "src/components/Modal";
import { baseURL } from "src/constants/data";
import useConfig from "src/store/useConfig";
import styled from "styled-components";
const StyledWarning = styled.p``;
const StyledErrorWrapper = styled.div`
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: ${({ theme }) => theme.TEXT_DANGER};
font-weight: 600;
`;
const StyledFlex = styled.div`
display: flex;
gap: 12px;
@ -45,21 +30,8 @@ const StyledContainer = styled.div`
`;
export const ShareModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
const json = useConfig(state => state.json);
const [encodedJson, setEncodedJson] = React.useState("");
const navigate = useRouter();
const embedText = `<iframe id="jsoncrackEmbed" src="${baseURL}/widget></iframe>`;
const shareURL = `${baseURL}/editor?json=${encodedJson}`;
React.useEffect(() => {
if (visible) {
const jsonEncode = compress(JSON.parse(json));
const jsonString = JSON.stringify(jsonEncode);
setEncodedJson(encodeURIComponent(jsonString));
}
}, [json, visible]);
const { push, query } = useRouter();
const shareURL = `https://jsoncrack.com/editor?json=${query.json}`;
const handleShare = (value: string) => {
navigator.clipboard.writeText(value);
@ -71,39 +43,23 @@ export const ShareModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
<Modal visible={visible} setVisible={setVisible}>
<Modal.Header>Create a Share Link</Modal.Header>
<Modal.Content>
{encodedJson.length > 5000 ? (
<StyledErrorWrapper>
<BiErrorAlt size={60} />
<StyledWarning>
Link size exceeds 5000 characters, unable to generate link for file of
this size!
</StyledWarning>
</StyledErrorWrapper>
) : (
<>
<StyledContainer>
Share Link
<StyledFlex>
<Input value={shareURL} type="url" readOnly />
<Button status="SECONDARY" onClick={() => handleShare(shareURL)}>
Copy
</Button>
</StyledFlex>
</StyledContainer>
<StyledContainer>
Embed into your website
<StyledFlex>
<Button
status="SUCCESS"
onClick={() => navigate.push("/embed")}
block
>
Learn How to Embed
</Button>
</StyledFlex>
</StyledContainer>
</>
)}
<StyledContainer>
Share Link
<StyledFlex>
<Input value={shareURL} type="url" readOnly />
<Button status="SECONDARY" onClick={() => handleShare(shareURL)}>
Copy
</Button>
</StyledFlex>
</StyledContainer>
<StyledContainer>
Embed into your website
<StyledFlex>
<Button status="SUCCESS" onClick={() => push("/embed")} block>
Learn How to Embed
</Button>
</StyledFlex>
</StyledContainer>
</Modal.Content>
<Modal.Controls setVisible={setVisible}></Modal.Controls>
</Modal>

View File

@ -34,7 +34,7 @@ export const StyledEditorWrapper = styled.div`
const EditorPage: React.FC = () => {
const { query, isReady } = useRouter();
const checkSession = useUser(state => state.checkSession);
const { data, isLoading } = useQuery(
const { data, isLoading, status } = useQuery(
["dbJson", query.json],
() => getJson(query.json as string),
{
@ -52,12 +52,15 @@ const EditorPage: React.FC = () => {
React.useEffect(() => {
if (isReady) {
if (query.json) {
if (isLoading) return setLoading(true);
if (status || !data) setJson(defaultJson);
if (data?.data) setJson(decompressFromBase64(data.data.json) as string);
setLoading(false);
} else setJson(defaultJson);
}
}, [data, isLoading, isReady, query.json, setJson, setLoading]);
}, [data, status, isLoading, isReady, query.json, setJson, setLoading]);
return (
<StyledEditorWrapper>

View File

@ -1,14 +0,0 @@
import { createClient } from "altogic";
let envUrl = process.env.NEXT_ALTOGIC_ENV_URL as string;
let clientKey = process.env.NEXT_ALTOGIC_CLIENT_KEY as string;
const altogic = createClient(
"https://815e-4e5a.c5-na.altogic.com/",
"f1e92022789f4ccf91273a345ab2bdf8",
{
signInRedirect: "/signin",
}
);
export { altogic };

View File

@ -1,5 +1,5 @@
import { compressToBase64 } from "lz-string";
import { altogic } from "../altogic";
import { altogic } from "src/api/altogic";
type JSON = {
_id: string;
@ -35,4 +35,6 @@ const updateJson = async (id: string, data: object) =>
...data,
});
export { saveJson, getJson, getAllJson, updateJson };
const deleteJson = async (id: string) => await altogic.endpoint.delete(`json/${id}`);
export { saveJson, getJson, getAllJson, updateJson, deleteJson };

View File

@ -1,9 +0,0 @@
import axios from "axios";
const validateToken = async <T>(token: string) => {
return await axios.get<T>(
`https://oauth2.googleapis.com/tokeninfo?id_token=${token}`
);
};
export { validateToken };

View File

@ -1,5 +1,5 @@
import toast from "react-hot-toast";
import { altogic } from "src/services/altogic";
import { altogic } from "src/api/altogic";
import { AltogicAuth } from "src/typings/altogic";
import create from "zustand";
@ -31,12 +31,12 @@ const useUser = create<UserStates & UserActions>()(set => ({
...initialStates,
setUser: (key, value) => set({ [key]: value }),
logout: () => {
localStorage.removeItem("auth_token");
altogic.auth.signOut();
toast.success("Logged out.");
set(initialStates);
},
login: response => {
// localStorage.setItem("auth_token", response.session.token);
set({ user: response.user, isAuthenticated: true });
},
checkSession: () => {
@ -44,6 +44,8 @@ const useUser = create<UserStates & UserActions>()(set => ({
const currentUser = altogic.auth.getUser();
if (currentSession) {
alert("has");
altogic.auth.setSession(currentSession);
set({ user: currentUser as any, isAuthenticated: true });
}

View File

@ -2194,11 +2194,6 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
compress-json@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/compress-json/-/compress-json-2.1.2.tgz#37e0e7c7480c572fad9ad387fca5a2f36fee6f83"
integrity sha512-91247RD8bKQXzRmXUS4zGT250mhw86+J9X8w2L2SGtRE7g0CvzjOETFaFmsDdaXPWv8T7L9iiM7kdcnnH3BH7w==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"