Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
cb502a3b6e Version 1 2026-03-05 06:47:26 +00:00
3 changed files with 114 additions and 89 deletions

View File

@ -2,234 +2,178 @@ import * as icon from '@mdi/js';
import { MenuAsideItem } from './interfaces' import { MenuAsideItem } from './interfaces'
const menuAside: MenuAsideItem[] = [ const menuAside: MenuAsideItem[] = [
{ href: '/story-studio', label: 'Story Studio', icon: icon.mdiRobot },
{ {
href: '/dashboard', href: '/dashboard',
icon: icon.mdiViewDashboardOutline, icon: icon.mdiViewDashboardOutline,
label: 'Dashboard', label: 'Dashboard',
}, },
{ {
href: '/users/users-list', href: '/users/users-list',
label: 'Users', label: 'Users',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAccountGroup,
// @ts-ignore
icon: icon.mdiAccountGroup ?? icon.mdiTable,
permissions: 'READ_USERS' permissions: 'READ_USERS'
}, },
{ {
href: '/roles/roles-list', href: '/roles/roles-list',
label: 'Roles', label: 'Roles',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiShieldAccountVariantOutline,
// @ts-ignore
icon: icon.mdiShieldAccountVariantOutline ?? icon.mdiTable,
permissions: 'READ_ROLES' permissions: 'READ_ROLES'
}, },
{ {
href: '/permissions/permissions-list', href: '/permissions/permissions-list',
label: 'Permissions', label: 'Permissions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiShieldAccountOutline,
// @ts-ignore
icon: icon.mdiShieldAccountOutline ?? icon.mdiTable,
permissions: 'READ_PERMISSIONS' permissions: 'READ_PERMISSIONS'
}, },
{ {
href: '/organizations/organizations-list', href: '/organizations/organizations-list',
label: 'Organizations', label: 'Organizations',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiTable,
// @ts-ignore
icon: icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ORGANIZATIONS' permissions: 'READ_ORGANIZATIONS'
}, },
{ {
href: '/teams/teams-list', href: '/teams/teams-list',
label: 'Teams', label: 'Teams',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAccountGroup,
// @ts-ignore
icon: 'mdiAccountGroup' in icon ? icon['mdiAccountGroup' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_TEAMS' permissions: 'READ_TEAMS'
}, },
{ {
href: '/oauth_accounts/oauth_accounts-list', href: '/oauth_accounts/oauth_accounts-list',
label: 'Oauth accounts', label: 'Oauth accounts',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiKey,
// @ts-ignore
icon: 'mdiKey' in icon ? icon['mdiKey' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_OAUTH_ACCOUNTS' permissions: 'READ_OAUTH_ACCOUNTS'
}, },
{ {
href: '/integrations/integrations-list', href: '/integrations/integrations-list',
label: 'Integrations', label: 'Integrations',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiPuzzle,
// @ts-ignore
icon: 'mdiPuzzle' in icon ? icon['mdiPuzzle' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_INTEGRATIONS' permissions: 'READ_INTEGRATIONS'
}, },
{ {
href: '/user_stories/user_stories-list', href: '/user_stories/user_stories-list',
label: 'User stories', label: 'User stories',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiBookOpenPageVariant,
// @ts-ignore
icon: 'mdiBookOpenPageVariant' in icon ? icon['mdiBookOpenPageVariant' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_USER_STORIES' permissions: 'READ_USER_STORIES'
}, },
{ {
href: '/acceptance_criteria/acceptance_criteria-list', href: '/acceptance_criteria/acceptance_criteria-list',
label: 'Acceptance criteria', label: 'Acceptance criteria',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiFormatListChecks,
// @ts-ignore
icon: 'mdiFormatListChecks' in icon ? icon['mdiFormatListChecks' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ACCEPTANCE_CRITERIA' permissions: 'READ_ACCEPTANCE_CRITERIA'
}, },
{ {
href: '/documents/documents-list', href: '/documents/documents-list',
label: 'Documents', label: 'Documents',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiFileDocumentEditOutline,
// @ts-ignore
icon: 'mdiFileDocumentEditOutline' in icon ? icon['mdiFileDocumentEditOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_DOCUMENTS' permissions: 'READ_DOCUMENTS'
}, },
{ {
href: '/document_folders/document_folders-list', href: '/document_folders/document_folders-list',
label: 'Document folders', label: 'Document folders',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiSitemap,
// @ts-ignore
icon: 'mdiFolderTree' in icon ? icon['mdiFolderTree' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_DOCUMENT_FOLDERS' permissions: 'READ_DOCUMENT_FOLDERS'
}, },
{ {
href: '/document_versions/document_versions-list', href: '/document_versions/document_versions-list',
label: 'Document versions', label: 'Document versions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiSourceBranch,
// @ts-ignore
icon: 'mdiSourceBranch' in icon ? icon['mdiSourceBranch' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_DOCUMENT_VERSIONS' permissions: 'READ_DOCUMENT_VERSIONS'
}, },
{ {
href: '/story_document_links/story_document_links-list', href: '/story_document_links/story_document_links-list',
label: 'Story document links', label: 'Story document links',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiLinkVariant,
// @ts-ignore
icon: 'mdiLinkVariant' in icon ? icon['mdiLinkVariant' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_STORY_DOCUMENT_LINKS' permissions: 'READ_STORY_DOCUMENT_LINKS'
}, },
{ {
href: '/collaboration_sessions/collaboration_sessions-list', href: '/collaboration_sessions/collaboration_sessions-list',
label: 'Collaboration sessions', label: 'Collaboration sessions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAccountMultipleOutline,
// @ts-ignore
icon: 'mdiAccountMultipleOutline' in icon ? icon['mdiAccountMultipleOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COLLABORATION_SESSIONS' permissions: 'READ_COLLABORATION_SESSIONS'
}, },
{ {
href: '/comment_threads/comment_threads-list', href: '/comment_threads/comment_threads-list',
label: 'Comment threads', label: 'Comment threads',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiCommentQuoteOutline,
// @ts-ignore
icon: 'mdiCommentQuoteOutline' in icon ? icon['mdiCommentQuoteOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COMMENT_THREADS' permissions: 'READ_COMMENT_THREADS'
}, },
{ {
href: '/comments/comments-list', href: '/comments/comments-list',
label: 'Comments', label: 'Comments',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiCommentTextOutline,
// @ts-ignore
icon: 'mdiCommentTextOutline' in icon ? icon['mdiCommentTextOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COMMENTS' permissions: 'READ_COMMENTS'
}, },
{ {
href: '/comment_reactions/comment_reactions-list', href: '/comment_reactions/comment_reactions-list',
label: 'Comment reactions', label: 'Comment reactions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiEmoticonOutline,
// @ts-ignore
icon: 'mdiEmoticonOutline' in icon ? icon['mdiEmoticonOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_COMMENT_REACTIONS' permissions: 'READ_COMMENT_REACTIONS'
}, },
{ {
href: '/mentions/mentions-list', href: '/mentions/mentions-list',
label: 'Mentions', label: 'Mentions',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAt,
// @ts-ignore
icon: 'mdiAt' in icon ? icon['mdiAt' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_MENTIONS' permissions: 'READ_MENTIONS'
}, },
{ {
href: '/approval_workflows/approval_workflows-list', href: '/approval_workflows/approval_workflows-list',
label: 'Approval workflows', label: 'Approval workflows',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiClipboardCheckOutline,
// @ts-ignore
icon: 'mdiClipboardCheckOutline' in icon ? icon['mdiClipboardCheckOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_APPROVAL_WORKFLOWS' permissions: 'READ_APPROVAL_WORKFLOWS'
}, },
{ {
href: '/approvals/approvals-list', href: '/approvals/approvals-list',
label: 'Approvals', label: 'Approvals',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiCheckDecagramOutline,
// @ts-ignore
icon: 'mdiCheckDecagramOutline' in icon ? icon['mdiCheckDecagramOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_APPROVALS' permissions: 'READ_APPROVALS'
}, },
{ {
href: '/approval_reviewers/approval_reviewers-list', href: '/approval_reviewers/approval_reviewers-list',
label: 'Approval reviewers', label: 'Approval reviewers',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAccountCheckOutline,
// @ts-ignore
icon: 'mdiAccountCheckOutline' in icon ? icon['mdiAccountCheckOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_APPROVAL_REVIEWERS' permissions: 'READ_APPROVAL_REVIEWERS'
}, },
{ {
href: '/audit_events/audit_events-list', href: '/audit_events/audit_events-list',
label: 'Audit events', label: 'Audit events',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiShieldSearch,
// @ts-ignore
icon: 'mdiShieldSearch' in icon ? icon['mdiShieldSearch' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_AUDIT_EVENTS' permissions: 'READ_AUDIT_EVENTS'
}, },
{ {
href: '/notifications/notifications-list', href: '/notifications/notifications-list',
label: 'Notifications', label: 'Notifications',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiBellOutline,
// @ts-ignore
icon: 'mdiBellOutline' in icon ? icon['mdiBellOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_NOTIFICATIONS' permissions: 'READ_NOTIFICATIONS'
}, },
{ {
href: '/sprints/sprints-list', href: '/sprints/sprints-list',
label: 'Sprints', label: 'Sprints',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiRunFast,
// @ts-ignore
icon: 'mdiRunFast' in icon ? icon['mdiRunFast' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_SPRINTS' permissions: 'READ_SPRINTS'
}, },
{ {
href: '/sprint_items/sprint_items-list', href: '/sprint_items/sprint_items-list',
label: 'Sprint items', label: 'Sprint items',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiClipboardListOutline,
// @ts-ignore
icon: 'mdiClipboardListOutline' in icon ? icon['mdiClipboardListOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_SPRINT_ITEMS' permissions: 'READ_SPRINT_ITEMS'
}, },
{ {
href: '/blockers/blockers-list', href: '/blockers/blockers-list',
label: 'Blockers', label: 'Blockers',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiAlertOctagonOutline,
// @ts-ignore
icon: 'mdiAlertOctagonOutline' in icon ? icon['mdiAlertOctagonOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_BLOCKERS' permissions: 'READ_BLOCKERS'
}, },
{ {
href: '/activity_feed_items/activity_feed_items-list', href: '/activity_feed_items/activity_feed_items-list',
label: 'Activity feed items', label: 'Activity feed items',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiTimelineTextOutline,
// @ts-ignore
icon: 'mdiTimelineTextOutline' in icon ? icon['mdiTimelineTextOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_ACTIVITY_FEED_ITEMS' permissions: 'READ_ACTIVITY_FEED_ITEMS'
}, },
{ {
href: '/ai_generations/ai_generations-list', href: '/ai_generations/ai_generations-list',
label: 'Ai generations', label: 'Ai generations',
// eslint-disable-next-line @typescript-eslint/ban-ts-comment icon: icon.mdiRobotOutline,
// @ts-ignore
icon: 'mdiRobotOutline' in icon ? icon['mdiRobotOutline' as keyof typeof icon] : icon.mdiTable ?? icon.mdiTable,
permissions: 'READ_AI_GENERATIONS' permissions: 'READ_AI_GENERATIONS'
}, },
{ {
@ -237,8 +181,6 @@ const menuAside: MenuAsideItem[] = [
label: 'Profile', label: 'Profile',
icon: icon.mdiAccountCircle, icon: icon.mdiAccountCircle,
}, },
{ {
href: '/api-docs', href: '/api-docs',
target: '_blank', target: '_blank',
@ -248,4 +190,4 @@ const menuAside: MenuAsideItem[] = [
}, },
] ]
export default menuAside export default menuAside

View File

@ -466,7 +466,7 @@ const Dashboard = () => {
size={48} size={48}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
path={'mdiFolderTree' in icon ? icon['mdiFolderTree' as keyof typeof icon] : icon.mdiTable || icon.mdiTable} path={'mdiSitemap' in icon ? icon['mdiSitemap' as keyof typeof icon] : icon.mdiTable || icon.mdiTable}
/> />
</div> </div>
</div> </div>

View File

@ -0,0 +1,83 @@
import { mdiRobot, mdiContentSave } from '@mdi/js';
import Head from 'next/head';
import React, { ReactElement, useState } from 'react';
import CardBox from '../components/CardBox';
import LayoutAuthenticated from '../layouts/Authenticated';
import SectionMain from '../components/SectionMain';
import SectionTitleLineWithButton from '../components/SectionTitleLineWithButton';
import FormField from '../components/FormField';
import BaseButton from '../components/BaseButton';
import BaseButtons from '../components/BaseButtons';
import { getPageTitle } from '../config';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import { aiResponse } from '../stores/openAiSlice';
import axios from 'axios';
const StoryStudio = () => {
const [idea, setIdea] = useState('');
const dispatch = useAppDispatch();
const { aiResponse: aiData, isAskingResponse } = useAppSelector((state) => state.openAi);
const handleGenerate = () => {
dispatch(aiResponse({
input: [
{ role: 'system', content: 'You are an expert Agile Product Owner. Convert raw product ideas into a structured User Story (As a, I want, So that) and provide 3 Acceptance Criteria.' },
{ role: 'user', content: idea },
],
options: { poll_interval: 5, poll_timeout: 300 }
}));
};
const handleSave = async () => {
// Basic extraction
const storyText = aiData?.output?.[0]?.content?.[0]?.text || '';
await axios.post('/user_stories', {
title: idea.substring(0, 50),
asA: 'User',
iWant: idea,
soThat: 'Value',
status: 'Draft'
});
alert('Story saved!');
};
return (
<>
<Head><title>{getPageTitle('Story Studio')}</title></Head>
<SectionMain>
<SectionTitleLineWithButton icon={mdiRobot} title="Story Studio" main />
<CardBox>
<FormField label="Raw Idea" labelFor="idea">
<textarea
id="idea"
className="w-full p-3 border border-gray-300 rounded"
rows={4}
value={idea}
onChange={(e) => setIdea(e.target.value)}
placeholder="e.g. Users should be able to reset their passwords..."
/>
</FormField>
<BaseButtons>
<BaseButton color="info" label={isAskingResponse ? 'Generating...' : 'Generate Story'} onClick={handleGenerate} disabled={isAskingResponse} />
</BaseButtons>
</CardBox>
{aiData && (
<CardBox className="mt-6">
<h2 className="text-xl font-bold mb-4 text-emerald-600">AI Generated Story</h2>
<div className="whitespace-pre-wrap">{aiData?.output?.[0]?.content?.[0]?.text}</div>
<BaseButtons className="mt-4">
<BaseButton color="success" icon={mdiContentSave} label="Save Story" onClick={handleSave} />
</BaseButtons>
</CardBox>
)}
</SectionMain>
</>
);
};
StoryStudio.getLayout = function getLayout(page: ReactElement) {
return <LayoutAuthenticated>{page}</LayoutAuthenticated>;
};
export default StoryStudio;