mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-23 00:58:32 +02:00
Very basic CSV viewer
This commit is contained in:
30
package-lock.json
generated
30
package-lock.json
generated
@@ -34,6 +34,7 @@
|
|||||||
"focus-trap-react": "^10.1.1",
|
"focus-trap-react": "^10.1.1",
|
||||||
"format-graphql": "^1.4.0",
|
"format-graphql": "^1.4.0",
|
||||||
"framer-motion": "^9.0.4",
|
"framer-motion": "^9.0.4",
|
||||||
|
"papaparse": "^5.4.1",
|
||||||
"parse-color": "^1.0.0",
|
"parse-color": "^1.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
@@ -48,6 +49,7 @@
|
|||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
|
"@types/papaparse": "^5.3.7",
|
||||||
"@types/parse-color": "^1.0.1",
|
"@types/parse-color": "^1.0.1",
|
||||||
"@types/parse-json": "^4.0.0",
|
"@types/parse-json": "^4.0.0",
|
||||||
"@types/react": "^18.0.31",
|
"@types/react": "^18.0.31",
|
||||||
@@ -2118,6 +2120,15 @@
|
|||||||
"integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==",
|
"integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/papaparse": {
|
||||||
|
"version": "5.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.7.tgz",
|
||||||
|
"integrity": "sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/parse-color": {
|
"node_modules/@types/parse-color": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse-color/-/parse-color-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse-color/-/parse-color-1.0.1.tgz",
|
||||||
@@ -5829,6 +5840,11 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/papaparse": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
|
||||||
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
@@ -8886,6 +8902,15 @@
|
|||||||
"integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==",
|
"integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==",
|
||||||
"devOptional": true
|
"devOptional": true
|
||||||
},
|
},
|
||||||
|
"@types/papaparse": {
|
||||||
|
"version": "5.3.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.7.tgz",
|
||||||
|
"integrity": "sha512-f2HKmlnPdCvS0WI33WtCs5GD7X1cxzzS/aduaxSu3I7TbhWlENjSPs6z5TaB9K0J+BH1jbmqTaM+ja5puis4wg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/parse-color": {
|
"@types/parse-color": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/parse-color/-/parse-color-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/parse-color/-/parse-color-1.0.1.tgz",
|
||||||
@@ -11587,6 +11612,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||||
},
|
},
|
||||||
|
"papaparse": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
|
||||||
|
"integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
|
||||||
|
},
|
||||||
"parent-module": {
|
"parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
"focus-trap-react": "^10.1.1",
|
"focus-trap-react": "^10.1.1",
|
||||||
"format-graphql": "^1.4.0",
|
"format-graphql": "^1.4.0",
|
||||||
"framer-motion": "^9.0.4",
|
"framer-motion": "^9.0.4",
|
||||||
|
"papaparse": "^5.4.1",
|
||||||
"parse-color": "^1.0.0",
|
"parse-color": "^1.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dnd": "^16.0.1",
|
"react-dnd": "^16.0.1",
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
|
||||||
"@tauri-apps/cli": "^1.2.2",
|
"@tauri-apps/cli": "^1.2.2",
|
||||||
"@types/node": "^18.7.10",
|
"@types/node": "^18.7.10",
|
||||||
|
"@types/papaparse": "^5.3.7",
|
||||||
"@types/parse-color": "^1.0.1",
|
"@types/parse-color": "^1.0.1",
|
||||||
"@types/parse-json": "^4.0.0",
|
"@types/parse-json": "^4.0.0",
|
||||||
"@types/react": "^18.0.31",
|
"@types/react": "^18.0.31",
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import type { TabItem } from './core/Tabs/Tabs';
|
|||||||
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
import { TabContent, Tabs } from './core/Tabs/Tabs';
|
||||||
import { EmptyStateText } from './EmptyStateText';
|
import { EmptyStateText } from './EmptyStateText';
|
||||||
import { ResponseHeaders } from './ResponseHeaders';
|
import { ResponseHeaders } from './ResponseHeaders';
|
||||||
|
import { CsvViewer } from './responseViewers/CsvViewer';
|
||||||
import { ImageViewer } from './responseViewers/ImageViewer';
|
import { ImageViewer } from './responseViewers/ImageViewer';
|
||||||
import { TextViewer } from './responseViewers/TextViewer';
|
import { TextViewer } from './responseViewers/TextViewer';
|
||||||
import { WebPageViewer } from './responseViewers/WebPageViewer';
|
import { WebPageViewer } from './responseViewers/WebPageViewer';
|
||||||
@@ -184,6 +185,8 @@ export const ResponsePane = memo(function ResponsePane({ style, className }: Pro
|
|||||||
<WebPageViewer response={activeResponse} />
|
<WebPageViewer response={activeResponse} />
|
||||||
) : contentType?.startsWith('image') ? (
|
) : contentType?.startsWith('image') ? (
|
||||||
<ImageViewer className="pb-2" response={activeResponse} />
|
<ImageViewer className="pb-2" response={activeResponse} />
|
||||||
|
) : contentType?.match(/csv|tab-separated/) ? (
|
||||||
|
<CsvViewer className="pb-2" response={activeResponse} />
|
||||||
) : (
|
) : (
|
||||||
<TextViewer response={activeResponse} pretty={viewMode === 'pretty'} />
|
<TextViewer response={activeResponse} pretty={viewMode === 'pretty'} />
|
||||||
)}
|
)}
|
||||||
|
|||||||
39
src-web/components/responseViewers/CsvViewer.tsx
Normal file
39
src-web/components/responseViewers/CsvViewer.tsx
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import classnames from 'classnames';
|
||||||
|
import Papa from 'papaparse';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useResponseBodyText } from '../../hooks/useResponseBodyText';
|
||||||
|
import type { HttpResponse } from '../../lib/models';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
response: HttpResponse;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CsvViewer({ response, className }: Props) {
|
||||||
|
const body = useResponseBodyText(response);
|
||||||
|
|
||||||
|
const parsed = useMemo(() => {
|
||||||
|
if (body === null) return null;
|
||||||
|
return Papa.parse<string[]>(body);
|
||||||
|
}, [body]);
|
||||||
|
|
||||||
|
if (parsed === null) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="overflow-auto h-full">
|
||||||
|
<table className={classnames(className, 'text-sm')}>
|
||||||
|
<tbody>
|
||||||
|
{parsed.data.map((row, i) => (
|
||||||
|
<tr key={i} className={classnames('border-l border-t', i > 0 && 'border-b')}>
|
||||||
|
{row.map((col, j) => (
|
||||||
|
<td key={j} className="border-r px-1.5">
|
||||||
|
{col}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user