Skip to content

Commit

Permalink
Merge pull request #1 from reezpatel/react-version
Browse files Browse the repository at this point in the history
[Extension] Migrated to React
  • Loading branch information
reezpatel authored Mar 14, 2020
2 parents 78035bd + 62b4471 commit 9ff3d69
Show file tree
Hide file tree
Showing 27 changed files with 3,353 additions and 411 deletions.
36 changes: 36 additions & 0 deletions app/Components/JSONView/JArray/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as React from 'react';
import { JView } from '../JView';

const JArray = ({ label, value, isLast, isOpen }) => {
const length = value.length;

return (
<section>
{label ? (
<span>
<span className="key">"{label}"</span>
{': '}
<span className="bracket">{'['}</span>
</span>
) : (
<span className="bracket">{'['}</span>
)}
{isOpen ? (
value.map((v, i) => (
<JView
label={''}
key={`${v}_${i}`}
isLast={i + 1 === length}
value={v}
/>
))
) : (
<span>{'.. '}{length} Items{' ..'}</span>
)}
<span className="bracket">{']'}</span>
{!isLast && ','}
</section>
);
};

export { JArray };
84 changes: 84 additions & 0 deletions app/Components/JSONView/JBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import * as React from 'react';
import { MdPlayArrow } from 'react-icons/md';
import { FiGitCommit } from 'react-icons/fi';
import { FaRegClone } from 'react-icons/fa';
import { EventContext } from '../../../Context/EventsBusContext';

const JBlock = ({ children, collapsible, onArrowClick, active, copyData }) => {
const [selected, setSelected] = React.useState(false);
const id = React.useRef(Math.random());
const events = React.useContext(EventContext);

const handleSectionClick = (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();

setSelected(!selected);
events.emit('click', id);
};

const blockClickEventListener = instance => {
if (instance !== id) {
setSelected(false);
}
};

React.useEffect(() => {
events.on('click', blockClickEventListener);
return () => {
events.off('click', blockClickEventListener);
};
}, []);

const handleCopyJSONClick = () => {
if (navigator.clipboard) {
navigator.clipboard
.writeText(JSON.stringify(copyData, null, 2))
.then(() => {
events.emit('message', {
type: 'success',
message: 'JSON copied to clipboard!!!',
_id: new Date().getTime()
});
})
.catch(e => {
console.log(e);
});
}
};

return (
<section
className={`block ${selected ? 'selected' : ''}`}
onClick={handleSectionClick}
>
{collapsible && (
<button
className={`button button-white block--content__left ${
active ? 'active' : ''
}`}
onClick={onArrowClick}
>
<MdPlayArrow />
</button>
)}
{children}
{selected && (
<div className="block--content__right">
{/* <button className="button popup popup-below" data-popup="Copy Branch">
<FiGitCommit />
</button> */}
<button
className="button popup popup-below"
data-popup="Copy JSON"
onClick={handleCopyJSONClick}
>
<FaRegClone />
</button>
</div>
)}
</section>
);
};

export { JBlock };
18 changes: 18 additions & 0 deletions app/Components/JSONView/JBoolean/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';

const JBoolean = ({ label, value, isLast }) => {
return (
<section>
{label && (
<React.Fragment>
<span className="key">"{label}"</span>
{': '}
</React.Fragment>
)}
<span className="boolean">{value ? 'true' : 'false'}</span>
{!isLast && ','}
</section>
);
};

export { JBoolean };
18 changes: 18 additions & 0 deletions app/Components/JSONView/JNumber/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';

const JNumber = ({ label, value, isLast }) => {
return (
<section>
{label && (
<React.Fragment>
<span className="key">"{label}"</span>
{': '}
</React.Fragment>
)}
<span className="number">{value}</span>
{!isLast && ','}
</section>
);
};

export { JNumber };
40 changes: 40 additions & 0 deletions app/Components/JSONView/JObject/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import * as React from 'react';
import { JView } from '../JView';

const JObject = ({ label, value, isLast, isOpen }) => {
const entries = Object.entries(value);
const length = entries.length;

return (
<section>
{label ? (
<span>
<span className="key">"{label}"</span>
{': '}
<span className="bracket">{'{'}</span>
</span>
) : (
<span className="bracket">{'{'}</span>
)}
{isOpen ? (
entries.map(([key, value], index) => (
<JView
label={key}
key={key}
value={value}
isLast={index + 1 === length}
/>
))
) : (
<span>
{'.. '}
{length} Items{' ..'}
</span>
)}
<span className="bracket">{'}'}</span>
{!isLast && ','}
</section>
);
};

export { JObject };
18 changes: 18 additions & 0 deletions app/Components/JSONView/JString/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import * as React from 'react';

const JString = ({ label, value, isLast }) => {
return (
<section>
{label && (
<React.Fragment>
<span className="key">"{label}"</span>
{': '}
</React.Fragment>
)}
<span className="string">"{value}"</span>
{!isLast && ','}
</section>
);
};

export { JString };
54 changes: 54 additions & 0 deletions app/Components/JSONView/JView/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import * as React from 'react';
import { JArray } from '../JArray';
import { JString } from '../JString';
import { JBoolean } from '../JBoolean';
import { JNumber } from '../JNumber';
import { JObject } from '../JObject';
import { JBlock } from '../JBlock';

const getView = (label, value, isLast, isOpen) => {
if (Array.isArray(value)) {
return (
<JArray label={label} value={value} isLast={isLast} isOpen={isOpen} />
);
}

if (typeof value === 'object') {
return (
<JObject label={label} value={value} isLast={isLast} isOpen={isOpen} />
);
}

if (typeof value === 'number') {
return <JNumber label={label} value={value} isLast={isLast} />;
}

if (typeof value === 'boolean') {
return <JBoolean label={label} value={value} isLast={isLast} />;
}

return <JString label={label} value={value} isLast={isLast} />;
};

const JView = ({ label, value, isLast }) => {
const [active, setActive] = React.useState(false);

const handleClick = e => {
e.preventDefault();
e.stopPropagation();
setActive(!active);
};

return (
<JBlock
onArrowClick={handleClick}
active={active}
collapsible={typeof value === 'object'}
copyData={label ? { [label]: value } : value}
>
{getView(label, value, isLast, !active)}
</JBlock>
);
};

export { JView };
29 changes: 29 additions & 0 deletions app/Components/JSONView/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import * as React from 'react';
import { JView } from './JView';
import { EventEmitter } from '../../Utils/EventEmitter';
import { EventContext } from '../../Context/EventsBusContext';
import { JSONPath } from 'jsonpath-plus';
import { Snackbar } from '../Snackbar';

const JSONView = ({ initialJSON, path }) => {
const [data, setData] = React.useState({});

React.useEffect(() => {
if (!path) {
setData(initialJSON);
} else {
setData(JSONPath({ path: path, json: initialJSON }));
}
}, [path]);

return (
<EventContext.Provider value={new EventEmitter()}>
<Snackbar />
<div className="json-view">
<JView value={data} label={''} isLast={true} />
</div>
</EventContext.Provider>
);
};

export { JSONView };
58 changes: 58 additions & 0 deletions app/Components/Snackbar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { EventContext } from '../../Context/EventsBusContext';

const STATE_OPEN = 'open';
const STATE_OPENED = '';
const STATE_CLOSE = 'close';

const SnackbarItem = ({ type, message, _id, onRemove }) => {
const [state, setState] = React.useState(STATE_OPEN);

setTimeout(() => {
setState(STATE_CLOSE);
}, 4000);

setTimeout(() => {
setState(STATE_OPENED);
}, 3000);

setTimeout(() => {
onRemove(_id);
}, 4500);

return (
<div className={`snackbar-item ${type} ${state}`}>
<span>{message}</span>
</div>
);
};

const Snackbar = () => {
const events = React.useContext(EventContext);
const [items, setItems] = React.useState([]);

const removeItem = _id => {
setItems(items.filter(item => item._id !== _id));
};

events.on('message', ({ type, message, _id }) => {
setItems([...items, { type, message, _id }]);
});

if (items.length) {
const element = document.createElement('div');
document.getElementById('snackbar').appendChild(element);

return ReactDOM.createPortal(
items.map(item => (
<SnackbarItem key={item._id} {...item} onRemove={removeItem} />
)),
element
);
}

return <React.Fragment />;
};

export { Snackbar };
Loading

0 comments on commit 9ff3d69

Please sign in to comment.