mirror of
https://github.com/AykutSarac/jsoncrack.com.git
synced 2025-01-12 19:02:53 +08:00
improve embeds
This commit is contained in:
parent
1548d6d4dd
commit
458723b2d6
@ -33,13 +33,11 @@ export const GraphCanvas = ({ isWidget = false }: { isWidget?: boolean }) => {
|
||||
return (
|
||||
<>
|
||||
<Graph openModal={openModal} setSelectedNode={setSelectedNode} isWidget={isWidget} />
|
||||
{!isWidget && (
|
||||
<NodeModal
|
||||
selectedNode={selectedNode}
|
||||
visible={isModalVisible}
|
||||
closeModal={() => setModalVisible(false)}
|
||||
/>
|
||||
)}
|
||||
<NodeModal
|
||||
selectedNode={selectedNode}
|
||||
visible={isModalVisible}
|
||||
closeModal={() => setModalVisible(false)}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -15,7 +15,7 @@ import { CarbonAds } from "src/components/CarbonAds";
|
||||
import { Producthunt } from "src/components/Producthunt";
|
||||
import { Sponsors } from "src/components/Sponsors";
|
||||
import { SupportButton } from "src/components/SupportButton";
|
||||
import { defaultJson } from "src/constants/data";
|
||||
import { baseURL } from "src/constants/data";
|
||||
import { GoalsModal } from "src/containers/Modals/GoalsModal";
|
||||
import pkg from "../../../package.json";
|
||||
import * as Styles from "./styles";
|
||||
@ -52,9 +52,9 @@ const HeroSection = () => {
|
||||
<Styles.StyledHighlightedText>instantly</Styles.StyledHighlightedText> into graphs.
|
||||
</Styles.StyledSubTitle>
|
||||
|
||||
<Styles.StyledButton rel="prefetch" href="/editor" link>
|
||||
<Styles.StyledButton href="/editor" link>
|
||||
GO TO EDITOR
|
||||
<AiOutlineRight strokeWidth="30px" />
|
||||
<AiOutlineRight strokeWidth="80" />
|
||||
</Styles.StyledButton>
|
||||
|
||||
<Styles.StyledButtonWrapper>
|
||||
@ -149,8 +149,9 @@ const GitHubSection = () => (
|
||||
Looking to understand or explore some JSON? Just paste or upload to visualize it as a
|
||||
graph with <a href="https://t.co/HlKSrhKryJ">https://t.co/HlKSrhKryJ</a> 😍 <br />
|
||||
<br />
|
||||
Thanks to <a href="https://twitter.com/aykutsarach?ref_src=twsrc%5Etfw">@aykutsarach</a>!{" "}
|
||||
<a href="https://t.co/0LyPUL8Ezz">pic.twitter.com/0LyPUL8Ezz</a>
|
||||
Thanks to <a href="https://twitter.com/aykutsarach?ref_src=twsrc%5Etfw">
|
||||
@aykutsarach
|
||||
</a>! <a href="https://t.co/0LyPUL8Ezz">pic.twitter.com/0LyPUL8Ezz</a>
|
||||
</p>
|
||||
— GitHub (@github){" "}
|
||||
<a href="https://twitter.com/github/status/1519363257794015233?ref_src=twsrc%5Etfw">
|
||||
@ -207,16 +208,21 @@ const EmbedSection = () => (
|
||||
</Styles.StyledSectionArea>
|
||||
<div>
|
||||
<Styles.StyledIframge
|
||||
src="https://jsoncrack.com/widget"
|
||||
src={`${baseURL}/widget`}
|
||||
onLoad={e => {
|
||||
const frame = e.currentTarget.contentWindow;
|
||||
setTimeout(() => {
|
||||
frame?.postMessage(
|
||||
{
|
||||
json: defaultJson,
|
||||
json: JSON.stringify({
|
||||
"random images": [
|
||||
"https://random.imagecdn.app/50/50?.png",
|
||||
"https://random.imagecdn.app/80/80?.png",
|
||||
"https://random.imagecdn.app/100/100?.png",
|
||||
],
|
||||
}),
|
||||
options: {
|
||||
theme: "dark",
|
||||
direction: "DOWN",
|
||||
},
|
||||
},
|
||||
"*"
|
||||
|
@ -39,6 +39,11 @@ export const ShareModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
const onEmbedClick = () => {
|
||||
push("/embed");
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal visible={visible} setVisible={setVisible}>
|
||||
<Modal.Header>Create a Share Link</Modal.Header>
|
||||
@ -55,7 +60,7 @@ export const ShareModal: React.FC<ModalProps> = ({ visible, setVisible }) => {
|
||||
<StyledContainer>
|
||||
Embed into your website
|
||||
<StyledFlex>
|
||||
<Button status="SUCCESS" onClick={() => push("/embed")} block>
|
||||
<Button status="SUCCESS" onClick={onEmbedClick} block>
|
||||
Learn How to Embed
|
||||
</Button>
|
||||
</StyledFlex>
|
||||
|
@ -15,7 +15,7 @@ const StyledNotFound = styled.div`
|
||||
const StyledMessage = styled.h4`
|
||||
color: ${({ theme }) => theme.FULL_WHITE};
|
||||
font-size: 25px;
|
||||
font-weight: 600;
|
||||
font-weight: 800;
|
||||
margin: 10px 0;
|
||||
`;
|
||||
|
||||
|
@ -4,14 +4,16 @@ import { useRouter } from "next/router";
|
||||
import toast from "react-hot-toast";
|
||||
import { baseURL } from "src/constants/data";
|
||||
import { darkTheme, lightTheme } from "src/constants/theme";
|
||||
import { NodeModal } from "src/containers/Modals/NodeModal";
|
||||
import useGraph from "src/store/useGraph";
|
||||
import { parser } from "src/utils/jsonParser";
|
||||
import useJson from "src/store/useJson";
|
||||
import styled, { ThemeProvider } from "styled-components";
|
||||
|
||||
const Graph = dynamic<any>(() => import("src/components/Graph").then(c => c.Graph), {
|
||||
ssr: false,
|
||||
});
|
||||
const GraphCanvas = dynamic(
|
||||
() => import("src/containers/Editor/LiveEditor/GraphCanvas").then(c => c.GraphCanvas),
|
||||
{
|
||||
ssr: false,
|
||||
}
|
||||
);
|
||||
|
||||
const StyledAttribute = styled.a`
|
||||
position: fixed;
|
||||
@ -45,71 +47,28 @@ interface EmbedMessage {
|
||||
};
|
||||
}
|
||||
|
||||
const StyledDeprecated = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
`;
|
||||
|
||||
const WidgetPage = () => {
|
||||
const { query, push } = useRouter();
|
||||
|
||||
const [isModalVisible, setModalVisible] = React.useState(false);
|
||||
const [selectedNode, setSelectedNode] = React.useState<[string, string][]>([]);
|
||||
const { query, push, isReady } = useRouter();
|
||||
const [theme, setTheme] = React.useState("dark");
|
||||
|
||||
const collapsedNodes = useGraph(state => state.collapsedNodes);
|
||||
const collapsedEdges = useGraph(state => state.collapsedEdges);
|
||||
const loading = useGraph(state => state.loading);
|
||||
const setNodeEdges = useGraph(state => state.setNodeEdges);
|
||||
const setDirection = useGraph(state => state.setDirection);
|
||||
|
||||
const openModal = React.useCallback(() => setModalVisible(true), []);
|
||||
const fetchJson = useJson(state => state.fetchJson);
|
||||
const setGraph = useGraph(state => state.setGraph);
|
||||
|
||||
React.useEffect(() => {
|
||||
const nodeList = collapsedNodes.map(id => `[id$="node-${id}"]`);
|
||||
const edgeList = collapsedEdges.map(id => `[class$="edge-${id}"]`);
|
||||
|
||||
const hiddenItems = document.querySelectorAll(".hide");
|
||||
hiddenItems.forEach(item => item.classList.remove("hide"));
|
||||
|
||||
if (nodeList.length) {
|
||||
const selectedNodes = document.querySelectorAll(nodeList.join(","));
|
||||
selectedNodes.forEach(node => node.classList.add("hide"));
|
||||
if (isReady) {
|
||||
fetchJson(query.json);
|
||||
if (!inIframe()) push("/");
|
||||
}
|
||||
|
||||
if (edgeList.length) {
|
||||
const selectedEdges = document.querySelectorAll(edgeList.join(","));
|
||||
selectedEdges.forEach(edge => edge.classList.add("hide"));
|
||||
}
|
||||
|
||||
if (!inIframe()) push("/");
|
||||
}, [collapsedNodes, collapsedEdges, loading, push]);
|
||||
}, [fetchJson, isReady, push, query.json]);
|
||||
|
||||
React.useEffect(() => {
|
||||
const handler = (event: EmbedMessage) => {
|
||||
try {
|
||||
if (!event.data?.json) return;
|
||||
if (event.data?.options?.theme === "light" || event.data?.options?.theme === "dark") {
|
||||
setTheme(event.data.options.theme);
|
||||
}
|
||||
|
||||
const { nodes, edges } = parser(event.data.json);
|
||||
|
||||
const options = {
|
||||
direction: "RIGHT",
|
||||
theme,
|
||||
...event.data.options,
|
||||
};
|
||||
|
||||
setDirection(options.direction);
|
||||
if (options.theme === "light" || options.theme === "dark") setTheme(options.theme);
|
||||
|
||||
setNodeEdges(nodes, edges);
|
||||
setGraph(event.data.json, event.data.options);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
toast.error("Invalid JSON!");
|
||||
@ -118,27 +77,11 @@ const WidgetPage = () => {
|
||||
|
||||
window.addEventListener("message", handler);
|
||||
return () => window.removeEventListener("message", handler);
|
||||
}, [setDirection, setNodeEdges, theme]);
|
||||
|
||||
if (query.json)
|
||||
return (
|
||||
<StyledDeprecated>
|
||||
<h1>⚠️ Deprecated ⚠️</h1>
|
||||
<br />
|
||||
<a href="https://jsoncrack.com/embed" target="_blank" rel="noreferrer">
|
||||
https://jsoncrack.com/embed
|
||||
</a>
|
||||
</StyledDeprecated>
|
||||
);
|
||||
}, [setGraph, theme]);
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={theme === "dark" ? darkTheme : lightTheme}>
|
||||
<Graph openModal={openModal} setSelectedNode={setSelectedNode} isWidget />
|
||||
<NodeModal
|
||||
selectedNode={selectedNode}
|
||||
visible={isModalVisible}
|
||||
closeModal={() => setModalVisible(false)}
|
||||
/>
|
||||
<GraphCanvas isWidget />
|
||||
<StyledAttribute href={`${baseURL}/editor`} target="_blank" rel="noreferrer">
|
||||
jsoncrack.com
|
||||
</StyledAttribute>
|
||||
|
@ -25,8 +25,7 @@ const initialStates = {
|
||||
export type Graph = typeof initialStates;
|
||||
|
||||
interface GraphActions {
|
||||
setGraph: (json?: string) => void;
|
||||
setNodeEdges: (nodes: NodeData[], edges: EdgeData[]) => void;
|
||||
setGraph: (json?: string, options?: Partial<Graph>[]) => void;
|
||||
setLoading: (loading: boolean) => void;
|
||||
setDirection: (direction: CanvasDirection) => void;
|
||||
setZoomPanPinch: (ref: ReactZoomPanPinchRef) => void;
|
||||
@ -44,7 +43,7 @@ interface GraphActions {
|
||||
|
||||
const useGraph = create<Graph & GraphActions>((set, get) => ({
|
||||
...initialStates,
|
||||
setGraph: (data?: string) => {
|
||||
setGraph: (data, options) => {
|
||||
const { nodes, edges } = parser(data ?? useJson.getState().json);
|
||||
|
||||
set({
|
||||
@ -55,19 +54,10 @@ const useGraph = create<Graph & GraphActions>((set, get) => ({
|
||||
collapsedEdges: [],
|
||||
graphCollapsed: false,
|
||||
loading: true,
|
||||
...options,
|
||||
});
|
||||
},
|
||||
setDirection: direction => set({ direction }),
|
||||
setNodeEdges: (nodes, edges) =>
|
||||
set({
|
||||
nodes,
|
||||
edges,
|
||||
collapsedParents: [],
|
||||
collapsedNodes: [],
|
||||
collapsedEdges: [],
|
||||
graphCollapsed: false,
|
||||
loading: true,
|
||||
}),
|
||||
setLoading: loading => set({ loading }),
|
||||
expandNodes: nodeId => {
|
||||
const [childrenNodes, matchingNodes] = getOutgoers(
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { decompressFromBase64 } from "lz-string";
|
||||
import toast from "react-hot-toast";
|
||||
import { altogic } from "src/api/altogic";
|
||||
import { defaultJson } from "src/constants/data";
|
||||
import useGraph from "src/store/useGraph";
|
||||
@ -35,7 +36,24 @@ const useJson = create<JsonStates & JsonActions>()((set, get) => ({
|
||||
...initialStates,
|
||||
getJson: () => get().json,
|
||||
fetchJson: async jsonId => {
|
||||
if (jsonId) {
|
||||
const isURL = new RegExp(
|
||||
/^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_\+.~#?&\/=]*)$/
|
||||
);
|
||||
|
||||
if (typeof jsonId === "string" && isURL.test(jsonId)) {
|
||||
try {
|
||||
const res = await fetch(jsonId);
|
||||
const json = await res.json();
|
||||
const jsonStr = JSON.stringify(json, null, 2);
|
||||
|
||||
useGraph.getState().setGraph(jsonStr);
|
||||
set({ json: jsonStr, loading: false });
|
||||
} catch (error) {
|
||||
useGraph.getState().setGraph(defaultJson);
|
||||
set({ json: defaultJson, loading: false });
|
||||
toast.error('Failed to fetch JSON from URL!');
|
||||
}
|
||||
} else if (jsonId) {
|
||||
const { data, errors } = await altogic.endpoint.get(`json/${jsonId}`);
|
||||
|
||||
if (!errors) {
|
||||
@ -49,10 +67,10 @@ const useJson = create<JsonStates & JsonActions>()((set, get) => ({
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
useGraph.getState().setGraph(defaultJson);
|
||||
set({ json: defaultJson, loading: false });
|
||||
}
|
||||
|
||||
useGraph.getState().setGraph(defaultJson);
|
||||
set({ json: defaultJson, loading: false });
|
||||
},
|
||||
setJson: json => {
|
||||
useGraph.getState().setGraph(json);
|
||||
|
Loading…
x
Reference in New Issue
Block a user