diff --git a/wren-ui/migrations/20241115031024_drop_thread_response_table_column.js b/wren-ui/migrations/20241115031024_drop_thread_response_table_column.js new file mode 100644 index 000000000..4b8db783e --- /dev/null +++ b/wren-ui/migrations/20241115031024_drop_thread_response_table_column.js @@ -0,0 +1,22 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function (knex) { + return knex.schema.alterTable('thread_response', function (table) { + table.dropColumn('summary'); + }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function (knex) { + return knex.schema.alterTable('thread_response', function (table) { + table + .string('summary') + .nullable() + .comment('the summary of the thread response'); + }); +}; diff --git a/wren-ui/src/apollo/client/graphql/__types__.ts b/wren-ui/src/apollo/client/graphql/__types__.ts index f15294030..f21528e50 100644 --- a/wren-ui/src/apollo/client/graphql/__types__.ts +++ b/wren-ui/src/apollo/client/graphql/__types__.ts @@ -28,6 +28,7 @@ export type AskingTaskInput = { }; export enum AskingTaskStatus { + CORRECTING = 'CORRECTING', FAILED = 'FAILED', FINISHED = 'FINISHED', GENERATING = 'GENERATING', @@ -98,14 +99,12 @@ export type CreateSimpleMetricInput = { export type CreateThreadInput = { question?: InputMaybe; sql?: InputMaybe; - summary?: InputMaybe; viewId?: InputMaybe; }; export type CreateThreadResponseInput = { question?: InputMaybe; sql?: InputMaybe; - summary?: InputMaybe; viewId?: InputMaybe; }; @@ -234,7 +233,6 @@ export type DetailedThread = { responses: Array; /** @deprecated Doesn't seem to be reasonable to put a sql in a thread */ sql: Scalars['String']; - summary: Scalars['String']; }; export type Diagram = { @@ -849,7 +847,6 @@ export type ResolveSchemaChangeWhereInput = { export type ResultCandidate = { __typename?: 'ResultCandidate'; sql: Scalars['String']; - summary: Scalars['String']; type: ResultCandidateType; view?: Maybe; }; @@ -955,7 +952,6 @@ export type ThreadResponse = { id: Scalars['Int']; question: Scalars['String']; status: AskingTaskStatus; - summary: Scalars['String']; }; export type ThreadResponseDetail = { diff --git a/wren-ui/src/apollo/client/graphql/home.generated.ts b/wren-ui/src/apollo/client/graphql/home.generated.ts index 3651aca36..57491a56a 100644 --- a/wren-ui/src/apollo/client/graphql/home.generated.ts +++ b/wren-ui/src/apollo/client/graphql/home.generated.ts @@ -5,7 +5,7 @@ import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; export type CommonErrorFragment = { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null }; -export type CommonResponseFragment = { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null }; +export type CommonResponseFragment = { __typename?: 'ThreadResponse', id: number, question: string, status: Types.AskingTaskStatus, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null }; export type SuggestedQuestionsQueryVariables = Types.Exact<{ [key: string]: never; }>; @@ -17,7 +17,7 @@ export type AskingTaskQueryVariables = Types.Exact<{ }>; -export type AskingTaskQuery = { __typename?: 'Query', askingTask: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, summary: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null } }; +export type AskingTaskQuery = { __typename?: 'Query', askingTask: { __typename?: 'AskingTask', status: Types.AskingTaskStatus, type?: Types.AskingTaskType | null, candidates: Array<{ __typename?: 'ResultCandidate', sql: string, type: Types.ResultCandidateType, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null }>, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null } }; export type ThreadsQueryVariables = Types.Exact<{ [key: string]: never; }>; @@ -29,14 +29,14 @@ export type ThreadQueryVariables = Types.Exact<{ }>; -export type ThreadQuery = { __typename?: 'Query', thread: { __typename?: 'DetailedThread', id: number, sql: string, summary: string, responses: Array<{ __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null }> } }; +export type ThreadQuery = { __typename?: 'Query', thread: { __typename?: 'DetailedThread', id: number, sql: string, responses: Array<{ __typename?: 'ThreadResponse', id: number, question: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null }> } }; export type ThreadResponseQueryVariables = Types.Exact<{ responseId: Types.Scalars['Int']; }>; -export type ThreadResponseQuery = { __typename?: 'Query', threadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null } }; +export type ThreadResponseQuery = { __typename?: 'Query', threadResponse: { __typename?: 'ThreadResponse', id: number, question: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null } }; export type CreateAskingTaskMutationVariables = Types.Exact<{ data: Types.AskingTaskInput; @@ -57,7 +57,7 @@ export type CreateThreadMutationVariables = Types.Exact<{ }>; -export type CreateThreadMutation = { __typename?: 'Mutation', createThread: { __typename?: 'Thread', id: number, sql: string, summary: string } }; +export type CreateThreadMutation = { __typename?: 'Mutation', createThread: { __typename?: 'Thread', id: number, sql: string } }; export type CreateThreadResponseMutationVariables = Types.Exact<{ threadId: Types.Scalars['Int']; @@ -65,7 +65,7 @@ export type CreateThreadResponseMutationVariables = Types.Exact<{ }>; -export type CreateThreadResponseMutation = { __typename?: 'Mutation', createThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, summary: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null } }; +export type CreateThreadResponseMutation = { __typename?: 'Mutation', createThreadResponse: { __typename?: 'ThreadResponse', id: number, question: string, status: Types.AskingTaskStatus, error?: { __typename?: 'Error', code?: string | null, shortMessage?: string | null, message?: string | null, stacktrace?: Array | null } | null, detail?: { __typename?: 'ThreadResponseDetail', sql?: string | null, description?: string | null, steps: Array<{ __typename?: 'DetailStep', summary: string, sql: string, cteName?: string | null }>, view?: { __typename?: 'ViewInfo', id: number, name: string, statement: string, displayName: string } | null } | null } }; export type UpdateThreadMutationVariables = Types.Exact<{ where: Types.ThreadUniqueWhereInput; @@ -122,7 +122,6 @@ export const CommonResponseFragmentDoc = gql` fragment CommonResponse on ThreadResponse { id question - summary status detail { sql @@ -185,7 +184,6 @@ export const AskingTaskDocument = gql` type candidates { sql - summary type view { id @@ -268,7 +266,6 @@ export const ThreadDocument = gql` thread(threadId: $threadId) { id sql - summary responses { ...CommonResponse error { @@ -415,7 +412,6 @@ export const CreateThreadDocument = gql` createThread(data: $data) { id sql - summary } } `; diff --git a/wren-ui/src/apollo/client/graphql/home.ts b/wren-ui/src/apollo/client/graphql/home.ts index 9890bcd15..61b282556 100644 --- a/wren-ui/src/apollo/client/graphql/home.ts +++ b/wren-ui/src/apollo/client/graphql/home.ts @@ -13,7 +13,6 @@ const COMMON_RESPONSE = gql` fragment CommonResponse on ThreadResponse { id question - summary status detail { sql @@ -51,7 +50,6 @@ export const ASKING_TASK = gql` type candidates { sql - summary type view { id @@ -82,7 +80,6 @@ export const THREAD = gql` thread(threadId: $threadId) { id sql - summary responses { ...CommonResponse error { @@ -127,7 +124,6 @@ export const CREATE_THREAD = gql` createThread(data: $data) { id sql - summary } } `; diff --git a/wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts b/wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts index a94d5af5f..0722cf36e 100644 --- a/wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts +++ b/wren-ui/src/apollo/server/adaptors/wrenAIAdaptor.ts @@ -34,7 +34,7 @@ export interface IWrenAIAdaptor { /** * Ask AI service a question. - * AI service will return anwser candidates containing sql and summary. + * AI service will return anwser candidates containing sql. * 1. use ask() to ask a question, AI service will return a queryId * 2. use getAskResult() to get the result of the queryId * 3. use cancelAsk() to cancel the query @@ -72,7 +72,7 @@ export class WrenAIAdaptor implements IWrenAIAdaptor { /** * Ask AI service a question. - * AI service will return anwser candidates containing sql and summary. + * AI service will return anwser candidates containing sql. */ public async ask(input: AskInput): Promise { @@ -307,7 +307,6 @@ export class WrenAIAdaptor implements IWrenAIAdaptor { const candidates = (body?.response || []).map((candidate: any) => ({ type: candidate?.type?.toUpperCase() as AskCandidateType, sql: candidate.sql, - summary: candidate.summary, viewId: candidate?.viewId ? Number(candidate.viewId) : null, })); diff --git a/wren-ui/src/apollo/server/models/adaptor.ts b/wren-ui/src/apollo/server/models/adaptor.ts index ec00c81c6..10a869be8 100644 --- a/wren-ui/src/apollo/server/models/adaptor.ts +++ b/wren-ui/src/apollo/server/models/adaptor.ts @@ -50,7 +50,6 @@ export interface AskStep { export interface AskHistory { sql: string; - summary: string; steps: Array; } @@ -73,6 +72,7 @@ export enum AskResultStatus { UNDERSTANDING = 'UNDERSTANDING', SEARCHING = 'SEARCHING', GENERATING = 'GENERATING', + CORRECTING = 'CORRECTING', FINISHED = 'FINISHED', FAILED = 'FAILED', STOPPED = 'STOPPED', @@ -101,7 +101,6 @@ export interface AskResponse { export interface AskDetailInput { query: string; sql: string; - summary: string; configurations?: AskConfigurations; } @@ -117,7 +116,6 @@ export type AskResult = AskResponse< Array<{ type: AskCandidateType; sql: string; - summary: string; viewId?: number | null; }>, AskResultStatus diff --git a/wren-ui/src/apollo/server/repositories/threadResponseRepository.ts b/wren-ui/src/apollo/server/repositories/threadResponseRepository.ts index 9416cc821..6821c594d 100644 --- a/wren-ui/src/apollo/server/repositories/threadResponseRepository.ts +++ b/wren-ui/src/apollo/server/repositories/threadResponseRepository.ts @@ -24,14 +24,12 @@ export interface ThreadResponse { threadId: number; // Reference to thread.id queryId: string; // Thread response query ID question: string; // Thread response question - summary: string; // Summary comes from the user's original question status: string; // Thread response status detail: ThreadResponseDetail; // Thread response detail error: object; // Thread response error } export interface ThreadResponseWithThreadContext extends ThreadResponse { - threadSummary: string; // Thread summary is generated by AI first, and can be updated by the user sql: string; } @@ -55,7 +53,6 @@ export class ThreadResponseRepository const query = this.knex(this.tableName) .select('thread_response.*') .select('thread.sql as sql') - .select('thread.summary as thread_summary') .where({ thread_id: threadId }) .leftJoin('thread', 'thread.id', 'thread_response.thread_id'); diff --git a/wren-ui/src/apollo/server/resolvers/askingResolver.ts b/wren-ui/src/apollo/server/resolvers/askingResolver.ts index 0b302bfa6..174267e40 100644 --- a/wren-ui/src/apollo/server/resolvers/askingResolver.ts +++ b/wren-ui/src/apollo/server/resolvers/askingResolver.ts @@ -41,7 +41,6 @@ export interface AskingTask { status: AskResultStatus; candidates: Array<{ sql: string; - summary: string; }>; error: WrenAIError | null; } @@ -50,7 +49,6 @@ export interface AskingTask { export interface DetailedThread { id: number; // ID sql: string; // SQL - summary: string; // Thread summary responses: ThreadResponse[]; } @@ -207,7 +205,6 @@ export class AskingResolver { return { type: response.type, sql: response.sql, - summary: response.summary, view, }; }), @@ -227,7 +224,6 @@ export class AskingResolver { data: { question?: string; sql?: string; - summary?: string; viewId?: number; }; }, @@ -272,20 +268,12 @@ export class AskingResolver { if (!acc.id) { acc.id = response.threadId; acc.sql = response.sql; - acc.summary = response.threadSummary; acc.responses = []; } acc.responses.push({ id: response.id, question: response.question, - - // we added summary in version 0.3.0. - // if summary is not available, we use description and question instead. - summary: - response.summary || - response.detail?.description || - response.question, status: response.status, detail: response.detail, error: response.error, @@ -357,7 +345,6 @@ export class AskingResolver { data: { question?: string; sql?: string; - summary?: string; viewId?: number; }; }, @@ -395,13 +382,7 @@ export class AskingResolver { const askingService = ctx.askingService; const response = await askingService.getResponse(responseId); - // we added summary in version 0.3.0. - // if summary is not available, we use description and question instead. - return { - ...response, - summary: - response.summary || response.detail?.description || response.question, - }; + return response; } public async previewData( diff --git a/wren-ui/src/apollo/server/resolvers/modelResolver.ts b/wren-ui/src/apollo/server/resolvers/modelResolver.ts index 566edb6e3..ccbd5d391 100644 --- a/wren-ui/src/apollo/server/resolvers/modelResolver.ts +++ b/wren-ui/src/apollo/server/resolvers/modelResolver.ts @@ -842,7 +842,6 @@ export class ModelResolver { // properties from the thread response responseId, // helpful for mapping back to the thread response question: response.question, - summary: response.summary, // detail is not going to send to AI service for indexing, but useful if we want display on UI detail: response.detail, }; diff --git a/wren-ui/src/apollo/server/schema.ts b/wren-ui/src/apollo/server/schema.ts index 7b2c2d45b..9fccbb548 100644 --- a/wren-ui/src/apollo/server/schema.ts +++ b/wren-ui/src/apollo/server/schema.ts @@ -537,6 +537,7 @@ export const typeDefs = gql` UNDERSTANDING SEARCHING GENERATING + CORRECTING FINISHED FAILED STOPPED @@ -556,7 +557,6 @@ export const typeDefs = gql` type ResultCandidate { type: ResultCandidateType! sql: String! - summary: String! view: ViewInfo } @@ -594,14 +594,12 @@ export const typeDefs = gql` input CreateThreadInput { question: String sql: String - summary: String viewId: Int } input CreateThreadResponseInput { question: String sql: String - summary: String viewId: Int } @@ -638,7 +636,6 @@ export const typeDefs = gql` type ThreadResponse { id: Int! question: String! - summary: String! status: AskingTaskStatus! detail: ThreadResponseDetail error: Error @@ -661,7 +658,6 @@ export const typeDefs = gql` @deprecated( reason: "Doesn't seem to be reasonable to put a sql in a thread" ) - summary: String! responses: [ThreadResponse!]! } diff --git a/wren-ui/src/apollo/server/services/askingService.ts b/wren-ui/src/apollo/server/services/askingService.ts index 61521a1ee..4dac12524 100644 --- a/wren-ui/src/apollo/server/services/askingService.ts +++ b/wren-ui/src/apollo/server/services/askingService.ts @@ -51,10 +51,13 @@ export interface AskingTaskInput { export interface AskingDetailTaskInput { question?: string; sql?: string; - summary?: string; viewId?: number; } +export interface AskingDetailTaskUpdateInput { + summary?: string; +} + export enum RecommendQuestionResultStatus { NOT_STARTED = 'NOT_STARTED', GENERATING = 'GENERATING', @@ -92,7 +95,7 @@ export interface IAskingService { ): Promise; updateThread( threadId: number, - input: Partial, + input: Partial, ): Promise; deleteThread(threadId: number): Promise; listThreads(): Promise; @@ -460,7 +463,7 @@ export class AskingService implements IAskingService { const deployId = await this.getDeployId(); // if it's a follow-up question, then the input will have a threadId - // then use the threadId to get the sql, summary and get the steps of last thread response + // then use the threadId to get the sql and get the steps of last thread response // construct it into AskHistory and pass to ask const history: AskHistory = threadId ? await this.getHistory(threadId) @@ -514,7 +517,6 @@ export class AskingService implements IAskingService { const response = await this.wrenAIAdaptor.generateAskDetail({ query: input.question, sql: input.sql, - summary: input.summary, configurations: { language }, }); @@ -523,15 +525,13 @@ export class AskingService implements IAskingService { const thread = await this.threadRepository.createOne({ projectId: id, sql: input.sql, - summary: input.summary, + summary: input.question, }); - // in follow-up questions, we still need to save the summary const threadResponse = await this.threadResponseRepository.createOne({ threadId: thread.id, queryId: response.queryId, question: input.question, - summary: input.summary, status: AskResultStatus.UNDERSTANDING, }); @@ -549,7 +549,7 @@ export class AskingService implements IAskingService { public async updateThread( threadId: number, - input: Partial, + input: Partial, ): Promise { // if input is empty, throw error if (isEmpty(input)) { @@ -594,18 +594,15 @@ export class AskingService implements IAskingService { const response = await this.wrenAIAdaptor.generateAskDetail({ query: input.question, sql: input.sql, - summary: input.summary, configurations: { language }, }); // 2. create a thread and the first thread response - // in follow-up questions, we still need to save the summary // insert question first, another API all the asked questions to generate the next recommendation questions const threadResponse = await this.threadResponseRepository.createOne({ threadId: thread.id, queryId: response.queryId, question: input.question, - summary: input.summary, status: AskResultStatus.UNDERSTANDING, }); @@ -718,7 +715,6 @@ export class AskingService implements IAskingService { const latestResponse = responses[0]; return { sql: latestResponse.sql, - summary: latestResponse.summary, steps: latestResponse.detail.steps, }; } @@ -747,7 +743,6 @@ export class AskingService implements IAskingService { threadId: thread.id, queryId: QUERY_ID_PLACEHOLDER, question: properties.question, - summary: properties.summary, status: AskResultStatus.FINISHED, detail: { ...properties.detail, diff --git a/wren-ui/src/components/pages/home/prompt/Result.tsx b/wren-ui/src/components/pages/home/prompt/Result.tsx index ed96078ee..e2f1f7b6e 100644 --- a/wren-ui/src/components/pages/home/prompt/Result.tsx +++ b/wren-ui/src/components/pages/home/prompt/Result.tsx @@ -41,7 +41,7 @@ interface Props { recommendedQuestions: RecommendedQuestionsTask; }; error?: any; - onSelectResult: (payload: { sql: string; summary: string }) => void; + onSelectResult: (payload: { sql: string }) => void; onSelectQuestion: (question: string) => void; onClose: () => void; onStop: () => void; @@ -160,8 +160,7 @@ const Finished = (props: Props) => { useEffect(() => { if (candidates.length) { const [result] = candidates; - onSelectResult && - onSelectResult({ sql: result.sql, summary: result.summary }); + onSelectResult && onSelectResult({ sql: result.sql }); } }, [data]); diff --git a/wren-ui/src/components/pages/home/prompt/index.tsx b/wren-ui/src/components/pages/home/prompt/index.tsx index 5a4d39c85..d7bc84ecc 100644 --- a/wren-ui/src/components/pages/home/prompt/index.tsx +++ b/wren-ui/src/components/pages/home/prompt/index.tsx @@ -23,7 +23,6 @@ import { interface Props { onSelect: (payload: { sql?: string; - summary?: string; question?: string; viewId?: number; }) => Promise; @@ -63,6 +62,8 @@ const convertAskingTaskToProcessState = (data: AskingTask) => { [AskingTaskStatus.UNDERSTANDING]: PROCESS_STATE.UNDERSTANDING, [AskingTaskStatus.SEARCHING]: PROCESS_STATE.SEARCHING, [AskingTaskStatus.GENERATING]: PROCESS_STATE.GENERATING, + // Show generating state component when AI correcting + [AskingTaskStatus.CORRECTING]: PROCESS_STATE.GENERATING, [AskingTaskStatus.FINISHED]: PROCESS_STATE.FINISHED, }[data.status]; @@ -147,7 +148,6 @@ export default forwardRef(function Prompt(props, ref) { } else if (question) { data = { sql: payload.sql, - summary: payload.summary, question, }; } diff --git a/wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx b/wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx index 784e84d76..de3c33365 100644 --- a/wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx +++ b/wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx @@ -1,13 +1,15 @@ -import { useState } from 'react'; +import clsx from 'clsx'; import Link from 'next/link'; -import { Col, Button, Row, Skeleton, Typography } from 'antd'; +import { Button, Skeleton, Typography, Alert } from 'antd'; import styled from 'styled-components'; import { Path } from '@/utils/enum'; import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'; -import QuestionCircleOutlined from '@ant-design/icons/QuestionCircleOutlined'; +import MessageOutlined from '@ant-design/icons/MessageOutlined'; import SaveOutlined from '@ant-design/icons/SaveOutlined'; import FileDoneOutlined from '@ant-design/icons/FileDoneOutlined'; import StepContent from '@/components/pages/home/promptThread/StepContent'; +import { getIsFinished } from '@/hooks/useAskPrompt'; +import { ThreadResponse } from '@/apollo/client/graphql/__types__'; const { Title, Text } = Typography; @@ -25,20 +27,6 @@ const StyledAnswer = styled(Typography)` } `; -const StyledQuestion = styled(Row)` - padding: 4px 8px; - border-radius: 4px; - color: var(--gray-6); - background-color: var(--gray-3); - margin-bottom: 8px; - font-size: 14px; - - &:hover { - background-color: var(--gray-4) !important; - cursor: pointer; - } -`; - const StyledSkeleton = styled(Skeleton)` .ant-skeleton-title { margin-top: 0; @@ -47,116 +35,111 @@ const StyledSkeleton = styled(Skeleton)` interface Props { motion: boolean; - loading: boolean; - question: string; - description: string; - answerResultSteps: Array<{ - summary: string; - sql: string; - }>; - fullSql: string; - threadResponseId: number; + threadResponse: ThreadResponse; isLastThreadResponse: boolean; - summary: string; - view?: { - id: number; - displayName: string; - }; onOpenSaveAsViewModal: (data: { sql: string; responseId: number }) => void; onInitPreviewDone: () => void; } +const QuestionTitle = (props) => { + const { question, className } = props; + return ( + + <MessageOutlined className="geekblue-5 mt-1 mr-3" /> + <Text className="text-medium gray-8">{question}</Text> + + ); +}; + export default function AnswerResult(props: Props) { const { motion, - loading, - question, - description, - answerResultSteps, - fullSql, - threadResponseId, + threadResponse, isLastThreadResponse, onOpenSaveAsViewModal, onInitPreviewDone, - summary, - view, } = props; + + const { question, status, error } = threadResponse; + + const { steps, description, view, sql } = threadResponse?.detail || {}; + + const loading = !getIsFinished(status); + const isViewSaved = !!view; - const [ellipsis, setEllipsis] = useState(true); const resultStyle = isLastThreadResponse ? { minHeight: 'calc(100vh - (194px))' } : null; return (
- setEllipsis(!ellipsis)}> - - - Question: - - - - {question} - - - - - {summary} - - -
- - - - Summary - -
{description}
- {(answerResultSteps || []).map((step, index) => ( - - ))} -
- {isViewSaved ? ( -
- - Generated from saved view{' '} - + {error ? ( + + ) : ( + +
+ + + + Summary + +
{description}
+ {(steps || []).map((step, index) => ( + + ))} +
+ {isViewSaved ? ( +
+ + Generated from saved view{' '} + + {view.displayName} + +
+ ) : ( +
- ) : ( - - )} -
- + Save as View + + )} +
+
+ )}
); } diff --git a/wren-ui/src/components/pages/home/promptThread/index.tsx b/wren-ui/src/components/pages/home/promptThread/index.tsx index f847b1cad..5f596d3d6 100644 --- a/wren-ui/src/components/pages/home/promptThread/index.tsx +++ b/wren-ui/src/components/pages/home/promptThread/index.tsx @@ -1,12 +1,12 @@ import { useRouter } from 'next/router'; import { useEffect, useMemo, useRef } from 'react'; -import { Alert, Divider } from 'antd'; +import { Divider } from 'antd'; import styled from 'styled-components'; import AnswerResult from './AnswerResult'; -import { makeIterable } from '@/utils/iteration'; +import { makeIterable, IterableComponent } from '@/utils/iteration'; import { - AskingTaskStatus, DetailedThread, + ThreadResponse, } from '@/apollo/client/graphql/__types__'; import { getIsFinished } from '@/hooks/useAskPrompt'; @@ -39,49 +39,34 @@ const StyledPromptThread = styled.div` } `; -const AnswerResultTemplate = ({ - id, +const AnswerResultTemplate: React.FC< + IterableComponent & { + motion: boolean; + onOpenSaveAsViewModal: (data: { sql: string; responseId: number }) => void; + onInitPreviewDone: () => void; + } +> = ({ data, index, - error, - status, - detail, - summary, - question, motion, - // callbacks onOpenSaveAsViewModal, onInitPreviewDone, + ...threadResponse }) => { + const { id } = threadResponse; const lastResponseId = data[data.length - 1].id; const isLastThreadResponse = id === lastResponseId; return (
{index > 0 && } - {error ? ( - - ) : ( - - )} +
); }; diff --git a/wren-ui/src/hooks/useAskPrompt.tsx b/wren-ui/src/hooks/useAskPrompt.tsx index fa8d9130a..6a8f87bd4 100644 --- a/wren-ui/src/hooks/useAskPrompt.tsx +++ b/wren-ui/src/hooks/useAskPrompt.tsx @@ -150,7 +150,8 @@ export default function useAskPrompt(threadId?: number) { const onStopRecommend = () => instantRecommendedQuestionsResult.stopPolling(); - const onStoreThreadQuestions = (questions: string[]) => setThreadQuestions(questions); + const onStoreThreadQuestions = (questions: string[]) => + setThreadQuestions(questions); return { data, diff --git a/wren-ui/src/pages/home/[id].tsx b/wren-ui/src/pages/home/[id].tsx index 2c073297e..34a8d22a3 100644 --- a/wren-ui/src/pages/home/[id].tsx +++ b/wren-ui/src/pages/home/[id].tsx @@ -94,8 +94,8 @@ export default function HomeThread() { } // store thread questions for instant recommended questions - const questions = thread?.responses.flatMap((res) => res.question || []) - if(questions) askPrompt.onStoreThreadQuestions(questions); + const questions = thread?.responses.flatMap((res) => res.question || []); + if (questions) askPrompt.onStoreThreadQuestions(questions); }, [thread]); useEffect(() => {