feat(wren-ui): UI integrating API - preview data (#63)

* feat(wren-ui): add home preview data API schema

* feat(wren-ui): support preview data
This commit is contained in:
Freda Lai
2024-04-03 17:02:15 +08:00
committed by GitHub
parent 157aa8960e
commit b84e3655f8
12 changed files with 159 additions and 1388 deletions
@@ -82,6 +82,13 @@ export type DeleteThreadMutationVariables = Types.Exact<{
export type DeleteThreadMutation = { __typename?: 'Mutation', deleteThread: boolean };
export type PreviewDataMutationVariables = Types.Exact<{
where: Types.PreviewDataInput;
}>;
export type PreviewDataMutation = { __typename?: 'Mutation', previewData: any };
export const CommonErrorFragmentDoc = gql`
fragment CommonError on Error {
code
@@ -509,4 +516,35 @@ export function useDeleteThreadMutation(baseOptions?: Apollo.MutationHookOptions
}
export type DeleteThreadMutationHookResult = ReturnType<typeof useDeleteThreadMutation>;
export type DeleteThreadMutationResult = Apollo.MutationResult<DeleteThreadMutation>;
export type DeleteThreadMutationOptions = Apollo.BaseMutationOptions<DeleteThreadMutation, DeleteThreadMutationVariables>;
export type DeleteThreadMutationOptions = Apollo.BaseMutationOptions<DeleteThreadMutation, DeleteThreadMutationVariables>;
export const PreviewDataDocument = gql`
mutation PreviewData($where: PreviewDataInput!) {
previewData(where: $where)
}
`;
export type PreviewDataMutationFn = Apollo.MutationFunction<PreviewDataMutation, PreviewDataMutationVariables>;
/**
* __usePreviewDataMutation__
*
* To run a mutation, you first call `usePreviewDataMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `usePreviewDataMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [previewDataMutation, { data, loading, error }] = usePreviewDataMutation({
* variables: {
* where: // value for 'where'
* },
* });
*/
export function usePreviewDataMutation(baseOptions?: Apollo.MutationHookOptions<PreviewDataMutation, PreviewDataMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<PreviewDataMutation, PreviewDataMutationVariables>(PreviewDataDocument, options);
}
export type PreviewDataMutationHookResult = ReturnType<typeof usePreviewDataMutation>;
export type PreviewDataMutationResult = Apollo.MutationResult<PreviewDataMutation>;
export type PreviewDataMutationOptions = Apollo.BaseMutationOptions<PreviewDataMutation, PreviewDataMutationVariables>;
@@ -155,3 +155,9 @@ export const DELETE_THREAD = gql`
deleteThread(where: $where)
}
`;
export const PREVIEW_DATA = gql`
mutation PreviewData($where: PreviewDataInput!) {
previewData(where: $where)
}
`;
+1 -1
View File
@@ -94,7 +94,7 @@ export const defaultApolloErrorHandler = (error: GraphQLError) => {
locations: error.locations,
path: error.path,
message: error.message,
extenstions: {
extensions: {
code,
message: error.message,
shortMessage: shortMessages[code],
@@ -10,6 +10,7 @@ type TableColumn = TableColumnProps<any> & { titleText?: string };
interface Props {
columns: TableColumn[];
data: Array<any[]>;
loading: boolean;
}
const getValueByValueType = (value: any) =>
@@ -31,7 +32,7 @@ const convertResultData = (data: Array<any>, columns) => {
};
export default function PreviewDataContent(props: Props) {
const { columns = [], data = [] } = props;
const { columns = [], data = [], loading } = props;
const hasColumns = !!columns.length;
const dynamicWidth = useMemo(() => {
@@ -61,6 +62,7 @@ export default function PreviewDataContent(props: Props) {
pagination={false}
size="small"
scroll={{ y: 280, x: dynamicWidth }}
loading={loading}
/>
);
}
@@ -14,10 +14,18 @@ interface Props {
sql: string;
}>;
fullSql: string;
threadResponseId: number;
}
export default function AnswerResult(props: Props) {
const { loading, question, description, answerResultSteps, fullSql } = props;
const {
loading,
question,
description,
answerResultSteps,
fullSql,
threadResponseId,
} = props;
return (
<Skeleton active loading={loading}>
@@ -39,8 +47,9 @@ export default function AnswerResult(props: Props) {
key={`${step.summary}-${index}`}
sql={step.sql}
fullSql={fullSql}
stepNumber={index + 1}
stepIndex={index}
summary={step.summary}
threadResponseId={threadResponseId}
/>
))}
</Typography>
@@ -3,6 +3,7 @@ import { Button, Typography } from 'antd';
import CopyOutlined from '@ant-design/icons/lib/icons/CopyOutlined';
import UpCircleOutlined from '@ant-design/icons/UpCircleOutlined';
import PreviewData from '@/components/pages/home/promptThread/PreviewData';
import { PreviewDataMutationResult } from '@/apollo/client/graphql/home.generated';
const CodeBlock = dynamic(() => import('@/components/editor/CodeBlock'), {
ssr: false,
@@ -17,6 +18,7 @@ export interface Props {
onCloseCollapse: () => void;
onCopyFullSQL?: () => void;
sql: string;
previewDataResult: PreviewDataMutationResult;
}
export default function CollapseContent(props: Props) {
@@ -27,7 +29,9 @@ export default function CollapseContent(props: Props) {
onCloseCollapse,
onCopyFullSQL,
sql,
previewDataResult,
} = props;
return (
<>
{(isViewSQL || isViewFullSQL) && (
@@ -37,7 +41,7 @@ export default function CollapseContent(props: Props) {
)}
{isPreviewData && (
<div className="my-2">
<PreviewData sql={sql} />
<PreviewData {...previewDataResult} />
</div>
)}
{(isViewSQL || isPreviewData) && (
File diff suppressed because it is too large Load Diff
@@ -12,12 +12,14 @@ interface Props {
fullSql: string;
isLastStep: boolean;
sql: string;
stepNumber: number;
stepIndex: number;
summary: string;
threadResponseId: number;
}
export default function StepContent(props: Props) {
const { fullSql, isLastStep, sql, stepNumber, summary } = props;
const { fullSql, isLastStep, sql, stepIndex, summary, threadResponseId } =
props;
const {
collapseContentProps,
@@ -28,8 +30,12 @@ export default function StepContent(props: Props) {
fullSql,
isLastStep,
sql,
threadResponseId,
stepIndex,
});
const stepNumber = stepIndex + 1;
return (
<Row className="mb-3 bg-gray-2" wrap={false}>
<Col flex="32px" className="p-2">
@@ -60,6 +60,7 @@ const AnswerResultTemplate = ({
loading={status !== AskingTaskStatus.FINISHED}
question={question}
fullSql={detail?.sql}
threadResponseId={id}
/>
)}
</div>
+22 -1
View File
@@ -2,6 +2,10 @@ import { useState } from 'react';
import copy from 'copy-to-clipboard';
import { message } from 'antd';
import { COLLAPSE_CONTENT_TYPE } from '@/utils/enum';
import {
usePreviewDataMutation,
PreviewDataMutationResult,
} from '@/apollo/client/graphql/home.generated';
function getButtonProps({
isLastStep,
@@ -41,19 +45,31 @@ export default function useAnswerStepContent({
fullSql,
isLastStep,
sql,
stepIndex,
threadResponseId,
}: {
fullSql: string;
isLastStep: boolean;
sql: string;
stepIndex: number;
threadResponseId: number;
}) {
const [collapseContentType, setCollapseContentType] =
useState<COLLAPSE_CONTENT_TYPE>(COLLAPSE_CONTENT_TYPE.NONE);
const [previewData, previewDataResult] = usePreviewDataMutation({
onError: (error) => console.error(error),
});
const onViewSQL = () =>
setCollapseContentType(COLLAPSE_CONTENT_TYPE.VIEW_SQL);
const onPreviewData = () =>
const onPreviewData = () => {
setCollapseContentType(COLLAPSE_CONTENT_TYPE.PREVIEW_DATA);
previewData({
variables: { where: { responseId: threadResponseId, stepIndex } },
});
};
const onCloseCollapse = () =>
setCollapseContentType(COLLAPSE_CONTENT_TYPE.NONE);
@@ -90,6 +106,11 @@ export default function useAnswerStepContent({
isViewSQL,
sql,
}),
previewDataResult: {
error: previewDataResult.error,
loading: previewDataResult.loading,
previewData: previewDataResult?.data?.previewData,
} as unknown as PreviewDataMutationResult,
},
...buttonProps,
};
+12 -2
View File
@@ -12,7 +12,8 @@ import { COLUMN_TYPE } from './enum';
export const getColumnTypeIcon = (payload: { type: string }, attrs?: any) => {
const { type } = payload;
switch (type.toUpperCase()) {
const compareString = type.toUpperCase();
switch (compareString) {
case COLUMN_TYPE.INTEGER:
case COLUMN_TYPE.TINYINT:
case COLUMN_TYPE.SMALLINT:
@@ -49,7 +50,16 @@ export const getColumnTypeIcon = (payload: { type: string }, attrs?: any) => {
case COLUMN_TYPE.MONGO_ROW:
return <JsonBracesIcon {...attrs} />;
default:
default: {
// int* or uint* or float*
if (
compareString.startsWith('INT') ||
compareString.startsWith('UINT') ||
compareString.startsWith('FLOAT')
) {
return <NumericIcon {...attrs} />;
}
return <ColumnsIcon {...attrs} />;
}
}
};
+12
View File
@@ -1,5 +1,6 @@
import { GraphQLError } from 'graphql';
import { ErrorResponse } from '@apollo/client/link/error';
import { ApolloError } from '@apollo/client';
import { message } from 'antd';
abstract class ErrorHandler {
@@ -97,3 +98,14 @@ const errorHandler = (error: ErrorResponse) => {
};
export default errorHandler;
export const parseGraphQLError = (error: ApolloError) => {
const graphQLErrors: GraphQLError = error.graphQLErrors?.[0];
const extensions = graphQLErrors.extensions;
return {
message: extensions.message as string,
shortMessage: extensions.shortMessage as string,
code: extensions.code as string,
stacktrace: extensions?.stacktrace as Array<string> | undefined,
};
};