Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(wren-ui): Asking experience enhancement #899

Merged
merged 7 commits into from
Nov 13, 2024
5 changes: 3 additions & 2 deletions wren-ui/src/components/learning/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ const Progress = styled.div<{ total: number; current: number }>`
`;

const CollapseBlock = styled.div`
transition: height 0.3s;
overflow: hidden;
`;

Expand Down Expand Up @@ -245,12 +244,14 @@ export default function SidebarSection(_props: Props) {
[stories],
);

const collapseBlock = (isActive: boolean) => {
const collapseBlock = async (isActive: boolean) => {
if ($collapseBlock.current) {
const blockHeight = $collapseBlock.current.scrollHeight;
$collapseBlock.current.style.height = isActive
? `${blockHeight}px`
: '0px';
await nextTick(300);
$collapseBlock.current.style.transition = 'height 0.3s';
}
};

Expand Down
57 changes: 34 additions & 23 deletions wren-ui/src/components/pages/home/prompt/Result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,34 @@ interface Props {
loading?: boolean;
}

const Wrapper = ({ children }) => {
return (
<StyledResult className="border border-gray-3 rounded p-4">
{children}
</StyledResult>
);
};

const makeProcessing = (text: string) => (props: Props) => {
const { onStop } = props;
return (
<div className="d-flex justify-space-between">
<span>
<LoadingOutlined className="mr-2 geekblue-6 text-lg" spin />
{text}
</span>
<Button
className="adm-btn-no-style gray-7 bg-gray-3 text-sm px-2"
type="text"
size="small"
onClick={onStop}
>
<StopOutlined className="-mr-1" />
Stop
</Button>
</div>
<Wrapper>
<div className="d-flex justify-space-between">
<span>
<LoadingOutlined className="mr-2 geekblue-6 text-lg" spin />
{text}
</span>
<Button
className="adm-btn-no-style gray-7 bg-gray-3 text-sm px-2"
type="text"
size="small"
onClick={onStop}
>
<StopOutlined className="-mr-1" />
Stop
</Button>
</div>
</Wrapper>
);
};

Expand All @@ -60,7 +70,7 @@ const makeProcessingError =
const { message, shortMessage, stacktrace } = error || {};
const hasStacktrace = !!stacktrace;
return (
<div>
<Wrapper>
<div className="d-flex justify-space-between text-medium mb-2">
<div className="d-flex align-center">
{config.icon}
Expand All @@ -80,7 +90,7 @@ const makeProcessingError =
{hasStacktrace && (
<ErrorCollapse className="mt-2" message={stacktrace.join('\n')} />
)}
</div>
</Wrapper>
);
};

Expand Down Expand Up @@ -109,7 +119,12 @@ const Finished = (props: Props) => {
}
}, [data]);

if (data.length === 0) return <NoResult {...props} />;
if (data.length === 0)
return (
<Wrapper>
<NoResult {...props} />
</Wrapper>
);
return null;
};

Expand All @@ -132,9 +147,5 @@ export default function PromptResult(props: Props) {

if (StateComponent === null) return null;

return (
<StyledResult className="border border-gray-3 rounded p-4">
<StateComponent {...props} />
</StyledResult>
);
return <StateComponent {...props} />;
}
33 changes: 21 additions & 12 deletions wren-ui/src/components/pages/home/prompt/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ interface Props {
summary?: string;
question?: string;
viewId?: number;
}) => void;
}) => Promise<void>;
onStop: () => void;
onSubmit: (value: string) => void;
onSubmit: (value: string) => Promise<void>;
data?: AskingTask;
}

Expand Down Expand Up @@ -97,17 +97,25 @@ export default forwardRef<Attributes, Props>(function Prompt(props, ref) {
}
}, [error]);

const selectResult = (payload) => {
const selectResult = async (payload) => {
const isSavedViewCandidate = !!payload.viewId;
const data = isSavedViewCandidate
? { viewId: payload.viewId }
: {
sql: payload.sql,
summary: payload.summary,
question,
};
onSelect && onSelect(data);

let data = null;
if (isSavedViewCandidate) {
data = { viewId: payload.viewId };
} else if (question) {
data = {
sql: payload.sql,
summary: payload.summary,
question,
};
}
if (!data) return;
// keep the state as generating after the result is selected
askProcessState.setState(PROCESS_STATE.GENERATING);
onSelect && (await onSelect(data));
closeResult();
askProcessState.resetState();
};

const closeResult = () => {
Expand All @@ -132,7 +140,8 @@ export default forwardRef<Attributes, Props>(function Prompt(props, ref) {

const submitAsk = async () => {
if (isProcessing || !question) return;
askProcessState.resetState();
// start the state as understanding when user submit question
askProcessState.setState(PROCESS_STATE.UNDERSTANDING);
onSubmit && (await onSubmit(question));
};

Expand Down
122 changes: 68 additions & 54 deletions wren-ui/src/components/pages/home/promptThread/AnswerResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ const StyledQuestion = styled(Row)`
}
`;

const StyledSkeleton = styled(Skeleton)`
.ant-skeleton-title {
margin-top: 0;
}
`;

interface Props {
motion: boolean;
loading: boolean;
question: string;
description: string;
Expand All @@ -49,18 +56,19 @@ interface Props {
}>;
fullSql: string;
threadResponseId: number;
onOpenSaveAsViewModal: (data: { sql: string; responseId: number }) => void;
isLastThreadResponse: boolean;
onTriggerScrollToBottom: () => void;
summary: string;
view?: {
id: number;
displayName: string;
};
onOpenSaveAsViewModal: (data: { sql: string; responseId: number }) => void;
onInitPreviewDone: () => void;
}

export default function AnswerResult(props: Props) {
const {
motion,
loading,
question,
description,
Expand All @@ -69,17 +77,19 @@ export default function AnswerResult(props: Props) {
threadResponseId,
isLastThreadResponse,
onOpenSaveAsViewModal,
onTriggerScrollToBottom,
onInitPreviewDone,
summary,
view,
} = props;

const isViewSaved = !!view;

const [ellipsis, setEllipsis] = useState(true);
const resultStyle = isLastThreadResponse
? { minHeight: 'calc(100vh - (194px))' }
: null;

return (
<Skeleton active loading={loading}>
<div style={resultStyle}>
<StyledQuestion wrap={false} onClick={() => setEllipsis(!ellipsis)}>
<Col className="text-center" flex="96px">
<QuestionCircleOutlined className="mr-2 gray-6" />
Expand All @@ -94,55 +104,59 @@ export default function AnswerResult(props: Props) {
<Title className="mb-6 text-bold gray-10" level={3}>
{summary}
</Title>
<StyledAnswer className="text-md gray-10 p-3 pr-10 pt-6">
<Text className="adm-answer-title px-2">
<CheckCircleFilled className="mr-2 green-6" />
Summary
</Text>
<div className="pl-7 pb-5">{description}</div>
{(answerResultSteps || []).map((step, index) => (
<StepContent
isLastStep={index === answerResultSteps.length - 1}
key={`${step.summary}-${index}`}
sql={step.sql}
fullSql={fullSql}
stepIndex={index}
summary={step.summary}
threadResponseId={threadResponseId}
onTriggerScrollToBottom={onTriggerScrollToBottom}
isLastThreadResponse={isLastThreadResponse}
/>
))}
</StyledAnswer>
{isViewSaved ? (
<div className="mt-2 gray-6 text-medium">
<FileDoneOutlined className="mr-2" />
Generated from saved view{' '}
<Link
className="gray-7"
href={`${Path.Modeling}?viewId=${view.id}&openMetadata=true`}
target="_blank"
rel="noreferrer noopener"
>
{view.displayName}
</Link>
<StyledSkeleton active loading={loading}>
<div className={motion ? 'promptThread-answer' : ''}>
<StyledAnswer className="text-md gray-10 p-3 pr-10 pt-6">
<Text className="adm-answer-title px-2">
<CheckCircleFilled className="mr-2 green-6" />
Summary
</Text>
<div className="pl-7 pb-5">{description}</div>
{(answerResultSteps || []).map((step, index) => (
<StepContent
isLastStep={index === answerResultSteps.length - 1}
key={`${step.summary}-${index}`}
sql={step.sql}
fullSql={fullSql}
stepIndex={index}
summary={step.summary}
threadResponseId={threadResponseId}
onInitPreviewDone={onInitPreviewDone}
isLastThreadResponse={isLastThreadResponse}
/>
))}
</StyledAnswer>
{isViewSaved ? (
<div className="mt-2 gray-6 text-medium">
<FileDoneOutlined className="mr-2" />
Generated from saved view{' '}
<Link
className="gray-7"
href={`${Path.Modeling}?viewId=${view.id}&openMetadata=true`}
target="_blank"
rel="noreferrer noopener"
>
{view.displayName}
</Link>
</div>
) : (
<Button
className="mt-2 gray-6"
type="text"
size="small"
icon={<SaveOutlined />}
onClick={() =>
onOpenSaveAsViewModal({
sql: fullSql,
responseId: threadResponseId,
})
}
>
Save as View
</Button>
)}
</div>
) : (
<Button
className="mt-2 gray-6"
type="text"
size="small"
icon={<SaveOutlined />}
onClick={() =>
onOpenSaveAsViewModal({
sql: fullSql,
responseId: threadResponseId,
})
}
>
Save as View
</Button>
)}
</Skeleton>
</StyledSkeleton>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ComponentProps } from 'react';
import Image from 'next/image';
import dynamic from 'next/dynamic';
import { Button, Switch, Typography, Empty } from 'antd';
Expand All @@ -7,7 +8,6 @@ import CloseOutlined from '@ant-design/icons/CloseOutlined';
import CopyOutlined from '@ant-design/icons/lib/icons/CopyOutlined';
import UpCircleOutlined from '@ant-design/icons/UpCircleOutlined';
import PreviewData from '@/components/dataPreview/PreviewData';
import { PreviewDataMutationResult } from '@/apollo/client/graphql/home.generated';
import { DATA_SOURCE_OPTIONS } from '@/components/pages/setup/utils';
import { NativeSQLResult } from '@/hooks/useNativeSQL';

Expand All @@ -29,14 +29,14 @@ const StyledPre = styled.pre<{ showNativeSQL: boolean }>`
}
`;

export interface Props {
interface Props {
isViewSQL?: boolean;
isViewFullSQL?: boolean;
isPreviewData?: boolean;
onCloseCollapse: () => void;
onCopyFullSQL?: () => void;
sql: string;
previewDataResult: PreviewDataMutationResult;
previewDataResult: ComponentProps<typeof PreviewData>;
attributes: {
stepNumber: number;
isLastStep: boolean;
Expand Down
Loading