This commit is contained in:
Flatlogic Bot 2025-05-26 11:51:30 +00:00
parent 7a4d91e755
commit f726d51828
3 changed files with 37 additions and 23 deletions

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ import { hasPermission } from '../helpers/userPermissions';
import { fetchWidgets } from '../stores/roles/rolesSlice'; import { fetchWidgets } from '../stores/roles/rolesSlice';
import { WidgetCreator } from '../components/WidgetCreator/WidgetCreator'; import { WidgetCreator } from '../components/WidgetCreator/WidgetCreator';
import { SmartWidget } from '../components/SmartWidget/SmartWidget'; import { SmartWidget } from '../components/SmartWidget/SmartWidget';
import { askGpt } from '../stores/openAiSlice'; import { askGpt, clearResponse } from '../stores/openAiSlice';
import { useAppDispatch, useAppSelector } from '../stores/hooks'; import { useAppDispatch, useAppSelector } from '../stores/hooks';
const Dashboard = () => { const Dashboard = () => {
@ -50,6 +50,13 @@ const Dashboard = () => {
const promptForGreeting = "Write a short ironic greeting for a dashboard page, in 3-5 words."; const promptForGreeting = "Write a short ironic greeting for a dashboard page, in 3-5 words.";
const isAsking = useAppSelector((state) => state.openAi?.isAskingQuestion ?? false); const isAsking = useAppSelector((state) => state.openAi?.isAskingQuestion ?? false);
const gptResp = useAppSelector((state) => state.openAi?.gptResponse); const gptResp = useAppSelector((state) => state.openAi?.gptResponse);
const [greeting, setGreeting] = useState<string>('');
useEffect(() => {
if (!greeting && gptResp) {
setGreeting(gptResp);
dispatch(clearResponse());
}
}, [gptResp, greeting, dispatch]);
useEffect(() => { dispatch(askGpt(promptForGreeting)); }, [dispatch]); useEffect(() => { dispatch(askGpt(promptForGreeting)); }, [dispatch]);
const [widgetsRole, setWidgetsRole] = React.useState({ const [widgetsRole, setWidgetsRole] = React.useState({
@ -132,33 +139,15 @@ const Dashboard = () => {
)} )}
</title> </title>
</Head> </Head>
<form onSubmit={handleSubmit} className="mb-4">
<textarea
value={userPrompt}
onChange={e => setUserPrompt(e.target.value)}
className="w-full p-2 border rounded"
placeholder={t('pages.dashboard.chatPlaceholder', { defaultValue: 'Ask something...' })}
/>
<button
type="submit"
className="mt-2 px-4 py-2 bg-blue-500 text-white rounded"
>
{t('pages.dashboard.chatButton', { defaultValue: 'Ask GPT' })}
</button>
</form>
{chatLoading && <p>{t('pages.dashboard.loading', { defaultValue: 'Loading...' })}</p>}
{errorMessage && <p className="text-red-500">{errorMessage}</p>}
{chatResponse && (
<p className="mt-2 p-2 bg-gray-100 rounded">{chatResponse}</p>
)}
<SectionMain> <SectionMain>
<SectionTitleLineWithButton <SectionTitleLineWithButton
icon={icon.mdiChartTimelineVariant} icon={icon.mdiChartTimelineVariant}
title={isAsking ? '...' : (gptResp || t('pages.dashboard.overview', { defaultValue: 'Overview' }))} title={greeting || t('pages.dashboard.overview', { defaultValue: 'Overview' })}
main main
> >
{''} {''}
</SectionTitleLineWithButton> </SectionTitleLineWithButton>
{hasPermission(currentUser, 'CREATE_ROLES') && ( {hasPermission(currentUser, 'CREATE_ROLES') && (
@ -210,6 +199,23 @@ const Dashboard = () => {
{!!rolesWidgets.length && <hr className='my-6 ' />} {!!rolesWidgets.length && <hr className='my-6 ' />}
{/* ChatGPT Input Form - relocated above count widgets */}
<form className='max-w-xs w-full mx-auto mb-4' onSubmit={handleSubmit}>
<textarea
rows={3}
value={userPrompt}
onChange={e => setUserPrompt(e.target.value)}
className='w-full p-2 border rounded'
placeholder={t('pages.dashboard.chatPlaceholder', { defaultValue: 'Ask something...' })}
/>
<button type='submit' className='mt-1 px-3 py-1 bg-blue-500 text-white rounded'>
{t('pages.dashboard.chatButton', { defaultValue: 'Ask GPT' })}
</button>
</form>
{chatLoading && <p className='text-gray-500'>{loadingMessage}</p>}
{errorMessage && <p className='text-red-500'>{errorMessage}</p>}
{chatResponse && <p className='mt-2 p-2 bg-gray-100 rounded'>{chatResponse}</p>}
<div <div
id='dashboard' id='dashboard'
className='grid grid-cols-1 gap-6 lg:grid-cols-3 mb-6' className='grid grid-cols-1 gap-6 lg:grid-cols-3 mb-6'
@ -229,6 +235,8 @@ const Dashboard = () => {
<div className='text-3xl leading-tight font-semibold'> <div className='text-3xl leading-tight font-semibold'>
{users} {users}
</div> </div>
</div> </div>
<div> <div>
<BaseIcon <BaseIcon

View File

@ -73,6 +73,11 @@ export const openAiSlice = createSlice({
setErrorNotification: (state, action) => { setErrorNotification: (state, action) => {
fulfilledNotify(state, action.payload, 'error'); fulfilledNotify(state, action.payload, 'error');
}, },
clearResponse: (state) => {
state.gptResponse = null;
state.isAskingQuestion = false;
state.errorMessage = '';
},
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(aiPrompt.pending, (state) => { builder.addCase(aiPrompt.pending, (state) => {
@ -111,6 +116,6 @@ export const openAiSlice = createSlice({
}); });
// Action creators are generated for each case reducer function // Action creators are generated for each case reducer function
export const { resetNotify, setErrorNotification } = openAiSlice.actions; export const { resetNotify, setErrorNotification, clearResponse } = openAiSlice.actions;
export default openAiSlice.reducer; export default openAiSlice.reducer;