mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-01-11 20:00:29 +01:00
Add toggle for pretty view
This commit is contained in:
43
package-lock.json
generated
43
package-lock.json
generated
@@ -12,6 +12,7 @@
|
||||
"@codemirror/lang-html": "^6.4.2",
|
||||
"@codemirror/lang-javascript": "^6.1.4",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/search": "^6.2.3",
|
||||
"@lezer/generator": "^1.2.2",
|
||||
@@ -497,6 +498,18 @@
|
||||
"@lezer/json": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-xml": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz",
|
||||
"integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/xml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.6.0.tgz",
|
||||
@@ -1126,6 +1139,15 @@
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha512-jMDXrV953sDAUEMI25VNrI9dz94Ai96FfeglytFINhhwQ867HKlCE2jt3AwZTCT7M528WxdDWv/Ty8e9wizwmQ==",
|
||||
"dependencies": {
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@motionone/animation": {
|
||||
"version": "10.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",
|
||||
@@ -7055,6 +7077,18 @@
|
||||
"@lezer/json": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@codemirror/lang-xml": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz",
|
||||
"integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==",
|
||||
"requires": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/xml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@codemirror/language": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.6.0.tgz",
|
||||
@@ -7450,6 +7484,15 @@
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@lezer/xml": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.1.tgz",
|
||||
"integrity": "sha512-jMDXrV953sDAUEMI25VNrI9dz94Ai96FfeglytFINhhwQ867HKlCE2jt3AwZTCT7M528WxdDWv/Ty8e9wizwmQ==",
|
||||
"requires": {
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"@motionone/animation": {
|
||||
"version": "10.15.1",
|
||||
"resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz",
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
"@codemirror/lang-html": "^6.4.2",
|
||||
"@codemirror/lang-javascript": "^6.1.4",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@codemirror/lang-xml": "^6.0.2",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/search": "^6.2.3",
|
||||
"@lezer/generator": "^1.2.2",
|
||||
|
||||
9
src-web/components/ButtonLink.tsx
Normal file
9
src-web/components/ButtonLink.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import type { LinkProps } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Button, ButtonProps } from './Button';
|
||||
|
||||
type Props = ButtonProps<typeof Link> & LinkProps;
|
||||
|
||||
export function ButtonLink({ ...props }: Props) {
|
||||
return <Button as={Link} {...props} />;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
rectangularSelection,
|
||||
} from '@codemirror/view';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { xml } from '@codemirror/lang-xml';
|
||||
import { parseMixed } from '@lezer/common';
|
||||
import { EditorState } from '@codemirror/state';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
@@ -44,15 +45,15 @@ export const myHighlightStyle = HighlightStyle.define([
|
||||
{
|
||||
tag: [t.documentMeta, t.blockComment, t.lineComment, t.docComment, t.comment],
|
||||
color: '#757b93',
|
||||
fontStyle: 'italic',
|
||||
},
|
||||
{ tag: [t.name], color: '#4699de' },
|
||||
{ tag: [t.name, t.tagName, t.angleBracket, t.docString], color: '#4699de' },
|
||||
{ tag: [t.variableName], color: '#31c434' },
|
||||
{ tag: [t.bool], color: '#e864f6' },
|
||||
{ tag: [t.attributeName], color: '#8f68ff' },
|
||||
{ tag: [t.attributeName], color: '#a773ff' },
|
||||
{ tag: [t.attributeValue], color: '#ff964b' },
|
||||
{ tag: [t.string], color: '#e8b045' },
|
||||
{ tag: [t.keyword, t.meta], color: '#45e8a4' },
|
||||
{ tag: [t.comment], color: '#cec4cc', fontStyle: 'italic' },
|
||||
]);
|
||||
|
||||
// export const defaultHighlightStyle = HighlightStyle.define([
|
||||
@@ -81,6 +82,8 @@ const syntaxExtensions: Record<string, { base: LanguageSupport; ext: any[] }> =
|
||||
'application/json': { base: json(), ext: [] },
|
||||
'application/javascript': { base: javascript(), ext: [] },
|
||||
'text/html': { base: html(), ext: [] },
|
||||
'application/xml': { base: xml(), ext: [] },
|
||||
'text/xml': { base: xml(), ext: [] },
|
||||
};
|
||||
|
||||
export function syntaxExtension({
|
||||
@@ -90,7 +93,8 @@ export function syntaxExtension({
|
||||
contentType: string;
|
||||
useTemplating?: boolean;
|
||||
}) {
|
||||
const { base, ext } = syntaxExtensions[contentType] ?? { base: json(), ext: [] };
|
||||
const justContentType = contentType.split(';')[0] ?? contentType;
|
||||
const { base, ext } = syntaxExtensions[justContentType] ?? { base: json(), ext: [] };
|
||||
if (!useTemplating) {
|
||||
return [base];
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@ import {
|
||||
ArchiveIcon,
|
||||
CameraIcon,
|
||||
CheckIcon,
|
||||
CodeIcon,
|
||||
EyeOpenIcon,
|
||||
GearIcon,
|
||||
HomeIcon,
|
||||
MoonIcon,
|
||||
PaperPlaneIcon,
|
||||
PlusCircledIcon,
|
||||
PlusIcon,
|
||||
QuestionMarkIcon,
|
||||
SunIcon,
|
||||
TriangleDownIcon,
|
||||
@@ -19,17 +23,23 @@ type IconName =
|
||||
| 'home'
|
||||
| 'camera'
|
||||
| 'gear'
|
||||
| 'eye'
|
||||
| 'triangle-down'
|
||||
| 'paper-plane'
|
||||
| 'update'
|
||||
| 'question'
|
||||
| 'check'
|
||||
| 'plus'
|
||||
| 'plus-circled'
|
||||
| 'sun'
|
||||
| 'code'
|
||||
| 'moon';
|
||||
|
||||
const icons: Record<IconName, NamedExoticComponent<{ className: string }>> = {
|
||||
'paper-plane': PaperPlaneIcon,
|
||||
'triangle-down': TriangleDownIcon,
|
||||
plus: PlusIcon,
|
||||
'plus-circled': PlusCircledIcon,
|
||||
archive: ArchiveIcon,
|
||||
camera: CameraIcon,
|
||||
check: CheckIcon,
|
||||
@@ -39,6 +49,8 @@ const icons: Record<IconName, NamedExoticComponent<{ className: string }>> = {
|
||||
sun: SunIcon,
|
||||
moon: MoonIcon,
|
||||
question: QuestionMarkIcon,
|
||||
eye: EyeOpenIcon,
|
||||
code: CodeIcon,
|
||||
};
|
||||
|
||||
export interface IconProps {
|
||||
|
||||
@@ -15,6 +15,7 @@ interface Props {
|
||||
|
||||
export function ResponsePane({ requestId, error }: Props) {
|
||||
const [activeResponseId, setActiveResponseId] = useState<string | null>(null);
|
||||
const [viewMode, setViewMode] = useState<'pretty' | 'raw'>('pretty');
|
||||
const responses = useResponses(requestId);
|
||||
const response = activeResponseId
|
||||
? responses.data.find((r) => r.id === activeResponseId)
|
||||
@@ -73,15 +74,23 @@ export function ResponsePane({ requestId, error }: Props) {
|
||||
<>
|
||||
<HStack
|
||||
items="center"
|
||||
className="italic text-gray-500 text-sm w-full pointer-events-none h-10 mb-3 flex-shrink-0"
|
||||
className="italic text-gray-500 text-sm w-full h-10 mb-3 flex-shrink-0"
|
||||
>
|
||||
{response.status}
|
||||
{response.statusReason && ` ${response.statusReason}`}
|
||||
•
|
||||
{response.elapsed}ms •
|
||||
{Math.round(response.body.length / 1000)} KB
|
||||
<div>
|
||||
{response.status}
|
||||
{response.statusReason && ` ${response.statusReason}`}
|
||||
•
|
||||
{response.elapsed}ms •
|
||||
{Math.round(response.body.length / 1000)} KB
|
||||
</div>
|
||||
<IconButton
|
||||
icon={viewMode === 'pretty' ? 'eye' : 'code'}
|
||||
size="sm"
|
||||
className="ml-auto"
|
||||
onClick={() => setViewMode((m) => (m === 'pretty' ? 'raw' : 'pretty'))}
|
||||
/>
|
||||
</HStack>
|
||||
{contentType.includes('html') ? (
|
||||
{viewMode === 'pretty' && contentType.includes('html') ? (
|
||||
<iframe
|
||||
title="Response preview"
|
||||
srcDoc={contentForIframe}
|
||||
|
||||
@@ -27,7 +27,7 @@ export function Sidebar({ className, activeRequestId, workspaceId, requests, ...
|
||||
<IconButton size="sm" icon="sun" onClick={toggleTheme} />
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon="camera"
|
||||
icon="plus-circled"
|
||||
onClick={() => createRequest.mutate({ name: 'Test Request' })}
|
||||
/>
|
||||
</HStack>
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useWorkspaces } from '../hooks/useWorkspaces';
|
||||
import { Button } from '../components/Button';
|
||||
import { ButtonLink } from '../components/ButtonLink';
|
||||
|
||||
export function Workspaces() {
|
||||
const workspaces = useWorkspaces();
|
||||
return (
|
||||
<ul className="p-12">
|
||||
{workspaces.data?.map((w) => (
|
||||
<Button as={Link} key={w.id} to={`/workspaces/${w.id}`}>
|
||||
<ButtonLink key={w.id} to={`/workspaces/${w.id}`}>
|
||||
{w.name}
|
||||
</Button>
|
||||
</ButtonLink>
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user