Upgrade eslint and fix issues

This commit is contained in:
Gregory Schier
2025-06-23 14:09:09 -07:00
parent 7be2767527
commit 1438e8bacc
11 changed files with 1326 additions and 1267 deletions
-6
View File
@@ -1,6 +0,0 @@
node_modules/
dist/
.eslintrc.cjs
.prettierrc.cjs
src-web/postcss.config.cjs
src-web/vite.config.ts
-49
View File
@@ -1,49 +0,0 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:import/recommended',
'plugin:jsx-a11y/recommended',
'plugin:@typescript-eslint/recommended',
'eslint-config-prettier',
],
plugins: ['react-refresh'],
parser: '@typescript-eslint/parser',
parserOptions: {
project: ['./tsconfig.json'],
},
ignorePatterns: [
'scripts/**/*',
'packages/plugin-runtime/**/*',
'packages/plugin-runtime-types/**/*',
'src-tauri/**/*',
'src-web/tailwind.config.cjs',
'src-web/vite.config.ts',
],
settings: {
react: {
version: 'detect',
},
'import/resolver': {
node: {
paths: ['src-web'],
extensions: ['.ts', '.tsx'],
},
},
},
rules: {
'react-refresh/only-export-components': 'error',
'jsx-a11y/no-autofocus': 'off',
'react/react-in-jsx-scope': 'off',
'import/no-unresolved': 'off',
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
},
],
},
};
+88
View File
@@ -0,0 +1,88 @@
const { defineConfig, globalIgnores } = require('eslint/config');
const { fixupConfigRules } = require('@eslint/compat');
const reactRefresh = require('eslint-plugin-react-refresh');
const tsParser = require('@typescript-eslint/parser');
const js = require('@eslint/js');
const { FlatCompat } = require('@eslint/eslintrc');
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
module.exports = defineConfig([
{
extends: fixupConfigRules(
compat.extends(
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:import/recommended',
'plugin:jsx-a11y/recommended',
'plugin:@typescript-eslint/recommended',
'eslint-config-prettier',
),
),
plugins: {
'react-refresh': reactRefresh,
},
languageOptions: {
parser: tsParser,
parserOptions: {
project: ['./tsconfig.json'],
},
},
settings: {
react: {
version: 'detect',
},
'import/resolver': {
node: {
paths: ['src-web'],
extensions: ['.ts', '.tsx'],
},
},
},
rules: {
'react-refresh/only-export-components': 'error',
'jsx-a11y/no-autofocus': 'off',
'react/react-in-jsx-scope': 'off',
'import/no-unresolved': 'off',
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
},
],
},
},
globalIgnores([
'scripts/**/*',
'packages/plugin-runtime/**/*',
'packages/plugin-runtime-types/**/*',
'src-tauri/**/*',
'src-web/tailwind.config.cjs',
'src-web/vite.config.ts',
]),
globalIgnores([
'**/node_modules/',
'**/dist/',
'**/.eslintrc.cjs',
'**/.prettierrc.cjs',
'src-web/postcss.config.cjs',
'src-web/vite.config.ts',
]),
]);
+773 -522
View File
File diff suppressed because it is too large Load Diff
+8 -5
View File
@@ -67,16 +67,19 @@
"jotai": "^2.12.2" "jotai": "^2.12.2"
}, },
"devDependencies": { "devDependencies": {
"@eslint/compat": "^1.3.0",
"@eslint/eslintrc": "^3.3.1",
"@eslint/js": "^9.29.0",
"@tauri-apps/cli": "2.4.1", "@tauri-apps/cli": "2.4.1",
"@typescript-eslint/eslint-plugin": "^8.27.0", "@typescript-eslint/eslint-plugin": "^8.27.0",
"@typescript-eslint/parser": "^8.27.0", "@typescript-eslint/parser": "^8.27.0",
"@yaakapp/cli": "^0.1.5", "@yaakapp/cli": "^0.1.5",
"eslint": "^8", "eslint": "^9.29.0",
"eslint-config-prettier": "^8", "eslint-config-prettier": "^10.1.5",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.2", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-hooks": "^5.2.0",
"nodejs-file-downloader": "^4.13.0", "nodejs-file-downloader": "^4.13.0",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.4.2", "prettier": "^3.4.2",
-1
View File
@@ -113,7 +113,6 @@ function ExportDataDialogContent({
} }
/> />
</td> </td>
{/* eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions,jsx-a11y/click-events-have-key-events */}
<td <td
className="py-1 pl-4 text whitespace-nowrap overflow-x-auto hide-scrollbars" className="py-1 pl-4 text whitespace-nowrap overflow-x-auto hide-scrollbars"
onClick={() => setSelectedWorkspaces((prev) => ({ ...prev, [w.id]: !prev[w.id] }))} onClick={() => setSelectedWorkspaces((prev) => ({ ...prev, [w.id]: !prev[w.id] }))}
+162 -385
View File
@@ -1,8 +1,6 @@
import { import { useAtomValue } from 'jotai';
useAtomValue import { graphqlSchemaAtom } from '../atoms/graphqlSchemaAtom';
} from 'jotai'; import { Input } from './core/Input';
import { graphqlSchemaAtom } from "../atoms/graphqlSchemaAtom";
import { Input } from "./core/Input";
import type { import type {
GraphQLSchema, GraphQLSchema,
GraphQLOutputType, GraphQLOutputType,
@@ -11,38 +9,35 @@ import type {
GraphQLList, GraphQLList,
GraphQLInputType, GraphQLInputType,
GraphQLNonNull, GraphQLNonNull,
GraphQLObjectType GraphQLObjectType,
} from "graphql"; } from 'graphql';
import { isNonNullType, isListType } from "graphql"; import { isNonNullType, isListType } from 'graphql';
import { Button } from "./core/Button"; import { Button } from './core/Button';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { IconButton } from "./core/IconButton"; import { IconButton } from './core/IconButton';
import { fuzzyFilter } from 'fuzzbunny'; import { fuzzyFilter } from 'fuzzbunny';
function getRootTypes(graphqlSchema: GraphQLSchema) { function getRootTypes(graphqlSchema: GraphQLSchema) {
return ([ return (
[
graphqlSchema.getQueryType(), graphqlSchema.getQueryType(),
graphqlSchema.getMutationType(), graphqlSchema.getMutationType(),
graphqlSchema.getSubscriptionType(), graphqlSchema.getSubscriptionType(),
] ].filter(Boolean) as NonNullable<ReturnType<GraphQLSchema['getQueryType']>>[]
.filter(Boolean) as NonNullable<ReturnType<GraphQLSchema['getQueryType']>>[]) ).reduce(
.reduce( (prev, curr) => {
(
prev,
curr
) => {
return { return {
...prev, ...prev,
[curr.name]: curr, [curr.name]: curr,
}; };
}, },
{} as Record<string, NonNullable<ReturnType<GraphQLSchema['getQueryType']>>> {} as Record<string, NonNullable<ReturnType<GraphQLSchema['getQueryType']>>>,
) );
} }
function getTypeIndices( function getTypeIndices(
type: GraphQLAnyType, type: GraphQLAnyType,
context: IndexGenerationContext context: IndexGenerationContext,
): SearchIndexRecord[] { ): SearchIndexRecord[] {
const indices: SearchIndexRecord[] = []; const indices: SearchIndexRecord[] = [];
@@ -54,60 +49,48 @@ function getTypeIndices(
name: (type as GraphQLObjectType).name, name: (type as GraphQLObjectType).name,
type: 'type', type: 'type',
schemaPointer: type, schemaPointer: type,
args: '' args: '',
}); });
if ((type as GraphQLObjectType).getFields) { if ((type as GraphQLObjectType).getFields) {
indices.push( indices.push(...getFieldsIndices((type as GraphQLObjectType).getFields(), context));
...getFieldsIndices((type as GraphQLObjectType).getFields(), context)
)
} }
// remove duplicates from index // remove duplicates from index
return indices.filter( return indices.filter(
(x, i, array) => array.findIndex( (x, i, array) => array.findIndex((y) => y.name === x.name && y.type === x.type) === i,
(y) => y.name === x.name && y.type === x.type
) === i
); );
} }
function getFieldsIndices( function getFieldsIndices(
fieldMap: FieldsMap, fieldMap: FieldsMap,
context: IndexGenerationContext context: IndexGenerationContext,
): SearchIndexRecord[] { ): SearchIndexRecord[] {
const indices: SearchIndexRecord[] = []; const indices: SearchIndexRecord[] = [];
Object.values(fieldMap) Object.values(fieldMap).forEach((field) => {
.forEach(
(field) => {
if (!field.name) { if (!field.name) {
return; return;
} }
const args = field.args && field.args.length > 0 const args =
? field.args.map((arg) => arg.name).join(', ') field.args && field.args.length > 0 ? field.args.map((arg) => arg.name).join(', ') : '';
: '';
indices.push({ indices.push({
name: field.name, name: field.name,
type: context.rootType, type: context.rootType,
schemaPointer: field as unknown as Field, schemaPointer: field as unknown as Field,
args args,
}); });
if (field.type) { if (field.type) {
indices.push( indices.push(...getTypeIndices(field.type, context));
...getTypeIndices(field.type, context)
)
} }
} });
);
// remove duplicates from index // remove duplicates from index
return indices.filter( return indices.filter(
(x, i, array) => array.findIndex( (x, i, array) => array.findIndex((y) => y.name === x.name && y.type === x.type) === i,
(y) => y.name === x.name && y.type === x.type
) === i
); );
} }
@@ -116,10 +99,10 @@ type FieldsMap = ReturnType<Field['getFields']>;
type GraphQLAnyType = FieldsMap[string]['type']; type GraphQLAnyType = FieldsMap[string]['type'];
type SearchIndexRecord = { type SearchIndexRecord = {
name: string, name: string;
args: string, args: string;
type: 'field' | 'type' | 'Query' | 'Mutation' | 'Subscription', type: 'field' | 'type' | 'Query' | 'Mutation' | 'Subscription';
schemaPointer: SchemaPointer schemaPointer: SchemaPointer;
}; };
type IndexGenerationContext = { type IndexGenerationContext = {
@@ -131,13 +114,11 @@ type SchemaPointer = Field | GraphQLOutputType | GraphQLInputType | null;
type ViewMode = 'explorer' | 'search' | 'field'; type ViewMode = 'explorer' | 'search' | 'field';
type HistoryRecord = { type HistoryRecord = {
schemaPointer: SchemaPointer, schemaPointer: SchemaPointer;
viewMode: ViewMode viewMode: ViewMode;
}; };
function DocsExplorer({ function DocsExplorer({ graphqlSchema }: { graphqlSchema: GraphQLSchema }) {
graphqlSchema
}: { graphqlSchema: GraphQLSchema }) {
const [rootTypes, setRootTypes] = useState(getRootTypes(graphqlSchema)); const [rootTypes, setRootTypes] = useState(getRootTypes(graphqlSchema));
const [schemaPointer, setSchemaPointer] = useState<SchemaPointer>(null); const [schemaPointer, setSchemaPointer] = useState<SchemaPointer>(null);
const [history, setHistory] = useState<HistoryRecord[]>([]); const [history, setHistory] = useState<HistoryRecord[]>([]);
@@ -154,56 +135,41 @@ function DocsExplorer({
const typeMap = graphqlSchema.getTypeMap(); const typeMap = graphqlSchema.getTypeMap();
const index: SearchIndexRecord[] = Object.values(typeMap) const index: SearchIndexRecord[] = Object.values(typeMap)
.filter( .filter((x) => !x.name.startsWith('__'))
(x) => !x.name.startsWith('__') .map((x) => ({
)
.map(
(x) => ({
name: x.name, name: x.name,
type: 'type', type: 'type',
schemaPointer: x, schemaPointer: x,
args: '' args: '',
}) }));
);
Object.values(rootTypes) Object.values(rootTypes).forEach((type) => {
.forEach(
(type) => {
index.push( index.push(
...getFieldsIndices(type.getFields(), { rootType: type.name as any }) ...getFieldsIndices(type.getFields(), {
) rootType: type.name as IndexGenerationContext['rootType'],
} }),
) );
});
setSearchIndex( setSearchIndex(
index index.filter(
.filter( (x, i, array) => array.findIndex((y) => y.name === x.name && y.type === x.type) === i,
(x, i, array) => array.findIndex( ),
(y) => y.name === x.name && y.type === x.type
) === i
)
); );
}, [graphqlSchema, rootTypes]); }, [graphqlSchema, rootTypes]);
useEffect( useEffect(() => {
() => {
if (!searchQuery) { if (!searchQuery) {
setSearchResults([]); setSearchResults([]);
return; return;
} }
const results = fuzzyFilter( const results = fuzzyFilter(searchIndex, searchQuery, { fields: ['name', 'args'] })
searchIndex,
searchQuery,
{ fields: ['name', 'args'] }
)
.sort((a, b) => b.score - a.score) .sort((a, b) => b.score - a.score)
.map((v) => v.item); .map((v) => v.item);
setSearchResults(results); setSearchResults(results);
}, }, [searchIndex, searchQuery]);
[searchIndex, searchQuery]
);
const goBack = () => { const goBack = () => {
if (history.length === 0) { if (history.length === 0) {
@@ -224,67 +190,53 @@ function DocsExplorer({
} }
goHome(); goHome();
} };
const addToHistory = (historyRecord: HistoryRecord) => { const addToHistory = (historyRecord: HistoryRecord) => {
setHistory([...history, historyRecord]); setHistory([...history, historyRecord]);
} };
const goHome = () => { const goHome = () => {
setHistory([]); setHistory([]);
setSchemaPointer(null); setSchemaPointer(null);
setViewMode('explorer'); setViewMode('explorer');
} };
const renderRootTypes = () => { const renderRootTypes = () => {
return ( return (
<div <div className="mt-5 flex flex-col gap-3">
className="mt-5 flex flex-col gap-3" {Object.values(rootTypes).map((x) => (
>
{
Object
.values(rootTypes)
.map(
(x) => (
<button <button
key={x.name} key={x.name}
className="block text-primary cursor-pointer w-fit" className="block text-primary cursor-pointer w-fit"
onClick={ onClick={() => {
() => {
addToHistory({ addToHistory({
schemaPointer: x, schemaPointer: x,
viewMode: 'explorer', viewMode: 'explorer',
}); });
setSchemaPointer(x); setSchemaPointer(x);
} }}
}
> >
{x.name} {x.name}
</button> </button>
) ))}
)
}
</div> </div>
); );
} };
const extractActualType = ( const extractActualType = (type: GraphQLField<never, never>['type'] | GraphQLInputType) => {
type: GraphQLField<never, never>['type'] | GraphQLInputType
) => {
// check if non-null // check if non-null
if (isNonNullType(type) || isListType(type)) { if (isNonNullType(type) || isListType(type)) {
return extractActualType((type as GraphQLNonNull<GraphQLOutputType>).ofType) return extractActualType((type as GraphQLNonNull<GraphQLOutputType>).ofType);
} }
return type; return type;
} };
const onTypeClick = ( const onTypeClick = (type: GraphQLField<never, never>['type'] | GraphQLInputType) => {
type: GraphQLField<never, never>['type'] | GraphQLInputType
) => {
// check if non-null // check if non-null
if (isNonNullType(type)) { if (isNonNullType(type)) {
onTypeClick((type as GraphQLNonNull<GraphQLOutputType>).ofType) onTypeClick((type as GraphQLNonNull<GraphQLOutputType>).ofType);
return; return;
} }
@@ -304,7 +256,7 @@ function DocsExplorer({
setViewMode('explorer'); setViewMode('explorer');
}; };
const onFieldClick = (field: GraphQLField<any, any>) => { const onFieldClick = (field: GraphQLField<unknown, unknown>) => {
setSchemaPointer(field as unknown as Field); setSchemaPointer(field as unknown as Field);
setViewMode('field'); setViewMode('field');
addToHistory({ addToHistory({
@@ -316,86 +268,48 @@ function DocsExplorer({
const renderSubFieldRecord = ( const renderSubFieldRecord = (
field: FieldsMap[string], field: FieldsMap[string],
options?: { options?: {
addable?: boolean, addable?: boolean;
} },
) => { ) => {
return ( return (
<div <div className="flex flex-row justify-start items-center">
className="flex flex-row justify-start items-center" {options?.addable ? (
>
{
options?.addable
? (
<IconButton size="sm" icon="plus_circle" iconColor="secondary" title="Add to query" /> <IconButton size="sm" icon="plus_circle" iconColor="secondary" title="Add to query" />
) ) : null}
: null <div className="flex flex-col">
}
<div
className="flex flex-col"
>
<div> <div>
<span> <span> </span>
{ " " } <button className="cursor-pointer text-primary" onClick={() => onFieldClick(field)}>
</span>
<button
className="cursor-pointer text-primary"
onClick={ () => onFieldClick(field) }
>
{field.name} {field.name}
</button> </button>
{/* Arguments block */} {/* Arguments block */}
{ {field.args && field.args.length > 0 ? (
field.args && field.args.length > 0
? (
<> <>
<span> <span> ( </span>
{ " " } {field.args.map((arg, i, array) => (
( <>
{ " " } <button key={arg.name} onClick={() => onTypeClick(arg.type)}>
<span className="text-primary cursor-pointer">{arg.name}</span>
<span> </span>
<span className="text-success underline cursor-pointer">
{arg.type.toString()}
</span> </span>
{ {i < array.length - 1 ? (
field.args.map(
(arg, i, array) => (
<> <>
<button <span> </span>
key={ arg.name }
onClick={ () => onTypeClick(arg.type) }
>
<span
className="text-primary cursor-pointer"
>
{ arg.name }
</span>
<span>{ " " }</span>
<span
className="text-success underline cursor-pointer"
>{ arg.type.toString() }</span>
{
i < array.length - 1
? (
<>
<span>{ " " }</span>
<span> , </span> <span> , </span>
<span>{ " " }</span> <span> </span>
</> </>
) ) : null}
: null
}
</button> </button>
<span>{ " " }</span> <span> </span>
</> </>
) ))}
) <span>)</span>
}
<span>
)
</span>
</> </>
) ) : null}
: null
}
{/* End of Arguments Block */} {/* End of Arguments Block */}
<span>{ " " }</span> <span> </span>
<button <button
className="text-success underline cursor-pointer" className="text-success underline cursor-pointer"
onClick={() => onTypeClick(field.type)} onClick={() => onTypeClick(field.type)}
@@ -403,15 +317,7 @@ function DocsExplorer({
{field.type.toString()} {field.type.toString()}
</button> </button>
</div> </div>
{ {field.description ? <div>{field.description}</div> : null}
field.description
? (
<div>
{ field.description }
</div>
)
: null
}
</div> </div>
</div> </div>
); );
@@ -420,11 +326,7 @@ function DocsExplorer({
const renderScalarField = () => { const renderScalarField = () => {
const scalarField = schemaPointer as GraphQLScalarType; const scalarField = schemaPointer as GraphQLScalarType;
return ( return <div>{scalarField.toConfig().description}</div>;
<div>
{ scalarField.toConfig().description }
</div>
);
}; };
const renderSubFields = () => { const renderSubFields = () => {
@@ -432,9 +334,7 @@ function DocsExplorer({
return null; return null;
} }
if ( if (!(schemaPointer as Field).getFields) {
!(schemaPointer as Field).getFields
) {
// Scalar field // Scalar field
return renderScalarField(); return renderScalarField();
} }
@@ -443,10 +343,9 @@ function DocsExplorer({
return null; return null;
} }
return Object.values((schemaPointer as Field).getFields()) return Object.values((schemaPointer as Field).getFields()).map((x) =>
.map( renderSubFieldRecord(x, { addable: true }),
(x) => renderSubFieldRecord(x, { addable: true }) );
)
}; };
const renderFieldDocView = () => { const renderFieldDocView = () => {
@@ -456,37 +355,19 @@ function DocsExplorer({
return ( return (
<div> <div>
<div <div className="text-primary mt-5">{(schemaPointer as Field).name}</div>
className="text-primary mt-5" {(schemaPointer as Field).getFields ? <div className="my-3">Fields</div> : null}
> <div className="flex flex-col gap-7">{renderSubFields()}</div>
{ (schemaPointer as Field).name }
</div> </div>
{ );
(schemaPointer as Field).getFields };
? (
<div
className="my-3"
>
Fields
</div>
)
: null
}
<div
className="flex flex-col gap-7"
>
{ renderSubFields() }
</div>
</div>
)
}
const renderExplorerView = () => { const renderExplorerView = () => {
if (history.length === 0) { if (history.length === 0) {
return renderRootTypes(); return renderRootTypes();
} }
return renderFieldDocView() return renderFieldDocView();
}; };
const renderFieldView = () => { const renderFieldView = () => {
@@ -494,109 +375,60 @@ function DocsExplorer({
return null; return null;
} }
const field = schemaPointer as unknown as GraphQLField<any, any>; const field = schemaPointer as unknown as GraphQLField<unknown, unknown>;
const returnType = extractActualType(field.type); const returnType = extractActualType(field.type);
return ( return (
<div> <div>
<div <div className="text-primary mt-10">{field.name}</div>
className="text-primary mt-10"
>
{ field.name }
</div>
{/* Arguments */} {/* Arguments */}
{ {field.args && field.args.length > 0 ? (
field.args && field.args.length > 0 <div className="mt-8">
? ( <div>Arguments</div>
<div <div className="mt-2">
className="mt-8"
>
<div> <div>
Arguments {field.args.map((arg, i, array) => (
</div>
<div
className="mt-2"
>
<div>
{
field.args.map(
(arg, i, array) => (
<> <>
<button <button key={arg.name} onClick={() => onTypeClick(arg.type)}>
key={ arg.name } <span className="text-primary cursor-pointer">{arg.name}</span>
onClick={ () => onTypeClick(arg.type) } <span> </span>
> <span className="text-success underline cursor-pointer">
<span {arg.type.toString()}
className="text-primary cursor-pointer"
>
{ arg.name }
</span> </span>
<span>{ " " }</span> {i < array.length - 1 ? (
<span
className="text-success underline cursor-pointer"
>{ arg.type.toString() }</span>
{
i < array.length - 1
? (
<> <>
<span>{ " " }</span> <span> </span>
<span> , </span> <span> , </span>
<span>{ " " }</span> <span> </span>
</> </>
) ) : null}
: null
}
</button> </button>
<span>{ " " }</span> <span> </span>
</> </>
) ))}
)
}
</div> </div>
</div> </div>
</div> </div>
) ) : null}
: null
}
{/* End of Arguments */} {/* End of Arguments */}
{/* Return type */} {/* Return type */}
<div <div className="mt-8">
className="mt-8" <div>Type</div>
> <div className="text-primary mt-2">{returnType.name}</div>
<div>
Type
</div>
<div
className="text-primary mt-2"
>
{ returnType.name }
</div>
</div> </div>
{/* End of Return type */} {/* End of Return type */}
{/* Fields */} {/* Fields */}
{ {(returnType as GraphQLObjectType).getFields &&
(returnType as GraphQLObjectType).getFields && Object.values((returnType as GraphQLObjectType).getFields()).length > 0 Object.values((returnType as GraphQLObjectType).getFields()).length > 0 ? (
? ( <div className="mt-8">
<div <div>Fields</div>
className="mt-8" <div className="flex flex-col gap-3 mt-2">
> {Object.values((returnType as GraphQLObjectType).getFields()).map((x) =>
<div> renderSubFieldRecord(x),
Fields )}
</div>
<div
className="flex flex-col gap-3 mt-2"
>
{
Object.values((returnType as GraphQLObjectType).getFields())
.map(
(x) => renderSubFieldRecord(x)
)
}
</div> </div>
</div> </div>
) ) : null}
: null
}
{/* End of Fields */} {/* End of Fields */}
</div> </div>
); );
@@ -604,19 +436,9 @@ function DocsExplorer({
const renderTopBar = () => { const renderTopBar = () => {
return ( return (
<div <div className="flex flex-row gap-2">
className="flex flex-row gap-2" <Button onClick={goBack}>Back</Button>
> <IconButton onClick={goHome} icon="house" title="Go to beginning" />
<Button
onClick={ goBack }
>
Back
</Button>
<IconButton
onClick={ goHome }
icon="house"
title="Go to beginning"
/>
</div> </div>
); );
}; };
@@ -624,23 +446,13 @@ function DocsExplorer({
const renderSearchView = () => { const renderSearchView = () => {
return ( return (
<div> <div>
<div <div className="mt-5 text-primary">Search results</div>
className="mt-5 text-primary" <div className="mt-4 flex flex-col gap-3">
> {searchResults.map((result) => (
Search results
</div>
<div
className="mt-4 flex flex-col gap-3"
>
{
searchResults
.map(
(result) => (
<button <button
key={`${result.name}-${result.type}`} key={`${result.name}-${result.type}`}
className="cursor-pointer border border-1 border-border-subtle rounded-md p-2 flex flex-row justify-between hover:bg-surface-highlight transition-colors" className="cursor-pointer border border-1 border-border-subtle rounded-md p-2 flex flex-row justify-between hover:bg-surface-highlight transition-colors"
onClick={ onClick={() => {
() => {
if (!result.schemaPointer) { if (!result.schemaPointer) {
throw new Error('somehow search result record contains no schema pointer'); throw new Error('somehow search result record contains no schema pointer');
} }
@@ -653,41 +465,22 @@ function DocsExplorer({
return; return;
} }
onFieldClick(result.schemaPointer as unknown as GraphQLField<any, any>); onFieldClick(result.schemaPointer as unknown as GraphQLField<unknown, unknown>);
} }}
}
> >
<div <div className="flex flex-row">
className="flex flex-row" <div className="cursor-pointer">{result.name}</div>
> {result.args ? (
<div <div className="cursor-pointer">
className="cursor-pointer" {'( '}
>
{ result.name }
</div>
{
result.args
? (
<div
className="cursor-pointer"
>
{ "( " }
{result.args} {result.args}
{ " )" } {' )'}
</div> </div>
) ) : null}
: null
}
</div>
<div
className="cursor-pointer"
>
{ result.type }
</div> </div>
<div className="cursor-pointer">{result.type}</div>
</button> </button>
) ))}
)
}
</div> </div>
</div> </div>
); );
@@ -706,51 +499,35 @@ function DocsExplorer({
}; };
return ( return (
<div <div className="overflow-y-auto pe-3">
className="overflow-y-auto pe-3" <div className="min-h-[35px]">
> {history.length > 0 || viewMode === 'search' ? renderTopBar() : null}
<div
className="min-h-[35px]"
>
{
history.length > 0 || viewMode === 'search'
? renderTopBar()
: null
}
</div> </div>
{/* Search bar */} {/* Search bar */}
<div <div className="relative">
className="relative"
>
<Input <Input
label="Search docs" label="Search docs"
stateKey="search_graphql_docs" stateKey="search_graphql_docs"
placeholder="Search docs" placeholder="Search docs"
hideLabel hideLabel
defaultValue={searchQuery} defaultValue={searchQuery}
onChange={ onChange={(value) => {
(value) => {
setSearchQuery(value); setSearchQuery(value);
} }}
} onKeyDown={(e) => {
onKeyDown={
(e) => {
// check if enter // check if enter
if (e.key === 'Enter' && viewMode !== 'search') { if (e.key === 'Enter' && viewMode !== 'search') {
addToHistory({ addToHistory({
schemaPointer: null, schemaPointer: null,
viewMode: 'search', viewMode: 'search',
}) });
setViewMode('search'); setViewMode('search');
} }
} }}
}
/> />
</div> </div>
{/* End of search bar */} {/* End of search bar */}
<div> <div>{renderView()}</div>
{ renderView() }
</div>
</div> </div>
); );
} }
@@ -1,13 +1,10 @@
import { useMutation, useQuery } from '@tanstack/react-query'; import { useMutation, useQuery } from '@tanstack/react-query';
import { openUrl } from '@tauri-apps/plugin-opener'; import { openUrl } from '@tauri-apps/plugin-opener';
import { Plugin, pluginsAtom } from '@yaakapp-internal/models'; import type { Plugin } from '@yaakapp-internal/models';
import { import { pluginsAtom } from '@yaakapp-internal/models';
checkPluginUpdates, import type { PluginVersion } from '@yaakapp-internal/plugins';
installPlugin, import { checkPluginUpdates, installPlugin, searchPlugins } from '@yaakapp-internal/plugins';
PluginVersion, import type { PluginUpdatesResponse } from '@yaakapp-internal/plugins/bindings/gen_api';
searchPlugins,
} from '@yaakapp-internal/plugins';
import { PluginUpdatesResponse } from '@yaakapp-internal/plugins/bindings/gen_api';
import { useAtomValue } from 'jotai'; import { useAtomValue } from 'jotai';
import React, { useState } from 'react'; import React, { useState } from 'react';
import { useDebouncedValue } from '../../hooks/useDebouncedValue'; import { useDebouncedValue } from '../../hooks/useDebouncedValue';
@@ -190,7 +187,7 @@ function PluginSearch() {
<TableHeaderCell>Name</TableHeaderCell> <TableHeaderCell>Name</TableHeaderCell>
<TableHeaderCell>Version</TableHeaderCell> <TableHeaderCell>Version</TableHeaderCell>
<TableHeaderCell>Description</TableHeaderCell> <TableHeaderCell>Description</TableHeaderCell>
<TableHeaderCell children="" /> <TableHeaderCell />
</TableRow> </TableRow>
</TableHead> </TableHead>
<TableBody> <TableBody>
+3 -2
View File
@@ -3,7 +3,8 @@ import type { ReactNode } from 'react';
import { memo, useEffect, useRef } from 'react'; import { memo, useEffect, useRef } from 'react';
import { ErrorBoundary } from '../../ErrorBoundary'; import { ErrorBoundary } from '../../ErrorBoundary';
import { Icon } from '../Icon'; import { Icon } from '../Icon';
import { RadioDropdown, RadioDropdownProps } from '../RadioDropdown'; import type { RadioDropdownProps } from '../RadioDropdown';
import { RadioDropdown } from '../RadioDropdown';
export type TabItem = export type TabItem =
| { | {
@@ -49,7 +50,7 @@ export function Tabs({
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`); const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
for (const tab of tabs ?? []) { for (const tab of tabs ?? []) {
const v = tab.getAttribute('data-tab'); const v = tab.getAttribute('data-tab');
let parent = tab.closest('.tabs-container'); const parent = tab.closest('.tabs-container');
if (parent !== ref.current) { if (parent !== ref.current) {
// Tab is part of a nested tab container, so ignore it // Tab is part of a nested tab container, so ignore it
} else if (v === value) { } else if (v === value) {
@@ -18,7 +18,6 @@ export function useSyncWorkspaceRequestTitle() {
newTitle += ` [${activeEnvironment.name}]`; newTitle += ` [${activeEnvironment.name}]`;
} }
if (activeRequest) { if (activeRequest) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
newTitle += ` ${resolvedModelName(activeRequest)}`; newTitle += ` ${resolvedModelName(activeRequest)}`;
} }
+1 -2
View File
@@ -9,9 +9,8 @@ export async function tryFormatJson(text: string): Promise<string> {
try { try {
const result = await invokeCmd<string>('cmd_format_json', { text }); const result = await invokeCmd<string>('cmd_format_json', { text });
return result; return result;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (err) { } catch (err) {
console.warn("Failed to format JSON", err); console.warn('Failed to format JSON', err);
// Nothing // Nothing
} }