mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-07-12 07:42:55 +02:00
Upgrade eslint and fix issues
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
node_modules/
|
|
||||||
dist/
|
|
||||||
.eslintrc.cjs
|
|
||||||
.prettierrc.cjs
|
|
||||||
src-web/postcss.config.cjs
|
|
||||||
src-web/vite.config.ts
|
|
||||||
@@ -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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -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',
|
||||||
|
]),
|
||||||
|
]);
|
||||||
Generated
+773
-522
File diff suppressed because it is too large
Load Diff
+8
-5
@@ -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",
|
||||||
|
|||||||
@@ -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] }))}
|
||||||
|
|||||||
@@ -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,102 +268,56 @@ 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 ? (
|
||||||
>
|
<IconButton size="sm" icon="plus_circle" iconColor="secondary" title="Add to query" />
|
||||||
{
|
) : null}
|
||||||
options?.addable
|
<div className="flex flex-col">
|
||||||
? (
|
|
||||||
<IconButton size="sm" icon="plus_circle" iconColor="secondary" title="Add to query"/>
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
<div
|
|
||||||
className="flex flex-col"
|
|
||||||
>
|
|
||||||
<div>
|
<div>
|
||||||
<span>
|
<span> </span>
|
||||||
{ " " }
|
<button className="cursor-pointer text-primary" onClick={() => onFieldClick(field)}>
|
||||||
</span>
|
{field.name}
|
||||||
<button
|
|
||||||
className="cursor-pointer text-primary"
|
|
||||||
onClick={ () => onFieldClick(field) }
|
|
||||||
>
|
|
||||||
{ 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 */}
|
||||||
}
|
<span> </span>
|
||||||
{/* End of Arguments Block */ }
|
|
||||||
<span>{ " " }</span>
|
|
||||||
<button
|
<button
|
||||||
className="text-success underline cursor-pointer"
|
className="text-success underline cursor-pointer"
|
||||||
onClick={ () => onTypeClick(field.type) }
|
onClick={() => onTypeClick(field.type)}
|
||||||
>
|
>
|
||||||
{ 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.args}
|
||||||
{ result.name }
|
{' )'}
|
||||||
</div>
|
</div>
|
||||||
{
|
) : null}
|
||||||
result.args
|
|
||||||
? (
|
|
||||||
<div
|
|
||||||
className="cursor-pointer"
|
|
||||||
>
|
|
||||||
{ "( " }
|
|
||||||
{ result.args }
|
|
||||||
{ " )" }
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: 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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -759,7 +536,7 @@ export function GraphQLDocsExplorer() {
|
|||||||
const graphqlSchema = useAtomValue(graphqlSchemaAtom);
|
const graphqlSchema = useAtomValue(graphqlSchemaAtom);
|
||||||
|
|
||||||
if (graphqlSchema) {
|
if (graphqlSchema) {
|
||||||
return <DocsExplorer graphqlSchema={ graphqlSchema }/>;
|
return <DocsExplorer graphqlSchema={graphqlSchema} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <div>There is no schema</div>;
|
return <div>There is no schema</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,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)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user