update: moved input control buttons JSON Data area.
This commit is contained in:
@@ -12,6 +12,7 @@ function MainPage({
|
|||||||
const [result, setResult] = useState("");
|
const [result, setResult] = useState("");
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [jsonError, setJsonError] = useState("");
|
const [jsonError, setJsonError] = useState("");
|
||||||
|
const [copySuccess, setCopySuccess] = useState(false);
|
||||||
|
|
||||||
const evaluateExpression = () => {
|
const evaluateExpression = () => {
|
||||||
try {
|
try {
|
||||||
@@ -77,6 +78,26 @@ function MainPage({
|
|||||||
setJsonError("");
|
setJsonError("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const copyToClipboard = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(result);
|
||||||
|
setCopySuccess(true);
|
||||||
|
setTimeout(() => setCopySuccess(false), 2000);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to copy!", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadResult = () => {
|
||||||
|
const blob = new Blob([result], { type: "application/json" });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "result.json";
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
};
|
||||||
|
|
||||||
const loadSample = () => {
|
const loadSample = () => {
|
||||||
const sampleData = {
|
const sampleData = {
|
||||||
users: [
|
users: [
|
||||||
@@ -155,11 +176,54 @@ function MainPage({
|
|||||||
<div className="row mb-2">
|
<div className="row mb-2">
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<div className="card">
|
<div className="card">
|
||||||
<div className="card-header d-flex justify-content-between align-items-center py-2">
|
<div className="card-header py-2">
|
||||||
<h6 className="mb-0">
|
<h6 className="mb-0">
|
||||||
<i className="bi bi-search me-2"></i>
|
<i className="bi bi-search me-2"></i>
|
||||||
JMESPath Expression
|
JMESPath Expression
|
||||||
</h6>
|
</h6>
|
||||||
|
</div>
|
||||||
|
<div className="card-body">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={`form-control jmespath-input ${error ? "error" : "success"}`}
|
||||||
|
value={jmespathExpression}
|
||||||
|
onChange={handleJmespathChange}
|
||||||
|
placeholder="Enter JMESPath expression (e.g., people[*].name)"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className={`alert mt-2 mb-0 d-flex justify-content-between align-items-center ${error ? "alert-danger" : "alert-success"}`}
|
||||||
|
>
|
||||||
|
<small className="mb-0">
|
||||||
|
{error || "Expression is correct"}
|
||||||
|
</small>
|
||||||
|
{showReloadButton && (
|
||||||
|
<button
|
||||||
|
className="btn btn-light btn-sm ms-2 border"
|
||||||
|
onClick={() => {
|
||||||
|
onReloadSampleData();
|
||||||
|
}}
|
||||||
|
title="New sample data is available"
|
||||||
|
>
|
||||||
|
<i className="bi bi-arrow-clockwise me-1"></i>
|
||||||
|
Reload Sample Data
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Lower Middle Section: Input and Output Areas */}
|
||||||
|
<div className="row flex-grow-1" style={{ minHeight: 0 }}>
|
||||||
|
{/* Left Panel: JSON Data Input */}
|
||||||
|
<div className="col-md-6">
|
||||||
|
<div className="card h-100 d-flex flex-column">
|
||||||
|
<div className="card-header d-flex justify-content-between align-items-center py-2">
|
||||||
|
<h6 className="mb-0">
|
||||||
|
<i className="bi bi-file-earmark-code me-2"></i>
|
||||||
|
JSON Data
|
||||||
|
</h6>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
className="btn btn-outline-success btn-sm me-2"
|
className="btn btn-outline-success btn-sm me-2"
|
||||||
@@ -198,49 +262,6 @@ function MainPage({
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="card-body">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
className={`form-control jmespath-input ${error ? "error" : "success"}`}
|
|
||||||
value={jmespathExpression}
|
|
||||||
onChange={handleJmespathChange}
|
|
||||||
placeholder="Enter JMESPath expression (e.g., people[*].name)"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={`alert mt-2 mb-0 d-flex justify-content-between align-items-center ${error ? "alert-danger" : "alert-success"}`}
|
|
||||||
>
|
|
||||||
<small className="mb-0">
|
|
||||||
{error || "Expression is correct"}
|
|
||||||
</small>
|
|
||||||
{showReloadButton && (
|
|
||||||
<button
|
|
||||||
className="btn btn-light btn-sm ms-2 border"
|
|
||||||
onClick={() => {
|
|
||||||
onReloadSampleData();
|
|
||||||
}}
|
|
||||||
title="New sample data is available"
|
|
||||||
>
|
|
||||||
<i className="bi bi-arrow-clockwise me-1"></i>
|
|
||||||
Reload Sample Data
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Lower Middle Section: Input and Output Areas */}
|
|
||||||
<div className="row flex-grow-1" style={{ minHeight: 0 }}>
|
|
||||||
{/* Left Panel: JSON Data Input */}
|
|
||||||
<div className="col-md-6">
|
|
||||||
<div className="card h-100 d-flex flex-column">
|
|
||||||
<div className="card-header py-2">
|
|
||||||
<h6 className="mb-0">
|
|
||||||
<i className="bi bi-file-earmark-code me-2"></i>
|
|
||||||
JSON Data
|
|
||||||
</h6>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
className="card-body flex-grow-1 d-flex flex-column"
|
className="card-body flex-grow-1 d-flex flex-column"
|
||||||
style={{ minHeight: 0 }}
|
style={{ minHeight: 0 }}
|
||||||
@@ -264,11 +285,31 @@ function MainPage({
|
|||||||
{/* Right Panel: Results */}
|
{/* Right Panel: Results */}
|
||||||
<div className="col-md-6">
|
<div className="col-md-6">
|
||||||
<div className="card h-100 d-flex flex-column">
|
<div className="card h-100 d-flex flex-column">
|
||||||
<div className="card-header py-2">
|
<div className="card-header py-2 d-flex justify-content-between align-items-center">
|
||||||
<h6 className="mb-0">
|
<h6 className="mb-0">
|
||||||
<i className="bi bi-output me-2"></i>
|
<i className="bi bi-output me-2"></i>
|
||||||
Results
|
Results
|
||||||
</h6>
|
</h6>
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className={`btn btn-sm me-2 ${copySuccess ? "btn-success" : "btn-outline-secondary"}`}
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
disabled={!result || result === "null"}
|
||||||
|
title="Copy result to clipboard"
|
||||||
|
>
|
||||||
|
<i className={`bi ${copySuccess ? "bi-check-lg" : "bi-clipboard"} me-1`}></i>
|
||||||
|
{copySuccess ? "Copied!" : "Copy"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-outline-secondary btn-sm"
|
||||||
|
onClick={downloadResult}
|
||||||
|
disabled={!result || result === "null"}
|
||||||
|
title="Download result as JSON file"
|
||||||
|
>
|
||||||
|
<i className="bi bi-download me-1"></i>
|
||||||
|
Download
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="card-body flex-grow-1 d-flex flex-column"
|
className="card-body flex-grow-1 d-flex flex-column"
|
||||||
|
|||||||
Reference in New Issue
Block a user