From fc32b2637ccea73a5c5ea4627df936144ef88ea1 Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Fri, 11 Jul 2025 13:33:10 +0300 Subject: [PATCH] F: Introducing AI UI pt1 --- rsconcept/frontend/src/app/global-dialogs.tsx | 5 ++ .../frontend/src/app/navigation/menu-ai.tsx | 5 +- .../frontend/src/features/ai/backend/types.ts | 8 ++ .../src/features/ai/dialogs/dlg-ai-prompt.tsx | 74 +++++++++++++++++++ .../src/features/ai/dialogs/index.tsx | 1 + .../src/features/ai/models/prompting-api.ts | 0 .../src/features/ai/models/prompting.ts | 29 ++++++++ rsconcept/frontend/src/stores/dialogs.ts | 8 +- 8 files changed, 126 insertions(+), 4 deletions(-) create mode 100644 rsconcept/frontend/src/features/ai/backend/types.ts create mode 100644 rsconcept/frontend/src/features/ai/dialogs/dlg-ai-prompt.tsx create mode 100644 rsconcept/frontend/src/features/ai/dialogs/index.tsx create mode 100644 rsconcept/frontend/src/features/ai/models/prompting-api.ts create mode 100644 rsconcept/frontend/src/features/ai/models/prompting.ts diff --git a/rsconcept/frontend/src/app/global-dialogs.tsx b/rsconcept/frontend/src/app/global-dialogs.tsx index a6bbbff6..ffc79178 100644 --- a/rsconcept/frontend/src/app/global-dialogs.tsx +++ b/rsconcept/frontend/src/app/global-dialogs.tsx @@ -140,6 +140,9 @@ const DlgCreateSchema = React.lazy(() => const DlgImportSchema = React.lazy(() => import('@/features/oss/dialogs/dlg-import-schema').then(module => ({ default: module.DlgImportSchema })) ); +const DlgAIPromptDialog = React.lazy(() => + import('@/features/ai/dialogs/dlg-ai-prompt').then(module => ({ default: module.DlgAIPromptDialog })) +); export const GlobalDialogs = () => { const active = useDialogsStore(state => state.active); @@ -208,5 +211,7 @@ export const GlobalDialogs = () => { return ; case DialogType.IMPORT_SCHEMA: return ; + case DialogType.AI_PROMPT: + return ; } }; diff --git a/rsconcept/frontend/src/app/navigation/menu-ai.tsx b/rsconcept/frontend/src/app/navigation/menu-ai.tsx index 9d8b8afb..3ddd5cf9 100644 --- a/rsconcept/frontend/src/app/navigation/menu-ai.tsx +++ b/rsconcept/frontend/src/app/navigation/menu-ai.tsx @@ -2,8 +2,8 @@ import { useAuth } from '@/features/auth/backend/use-auth'; import { Dropdown, DropdownButton, useDropdown } from '@/components/dropdown'; import { IconAssistant, IconChat, IconTemplates } from '@/components/icons'; +import { useDialogsStore } from '@/stores/dialogs'; import { globalIDs } from '@/utils/constants'; -import { notImplemented } from '@/utils/utils'; import { urls } from '../urls'; @@ -14,6 +14,7 @@ export function MenuAI() { const router = useConceptNavigation(); const menu = useDropdown(); const { user } = useAuth(); + const showAIPrompt = useDialogsStore(state => state.showAIPrompt); function navigateTemplates(event: React.MouseEvent) { menu.hide(); @@ -24,7 +25,7 @@ export function MenuAI() { event.preventDefault(); event.stopPropagation(); menu.hide(); - notImplemented(); + showAIPrompt({}); } return ( diff --git a/rsconcept/frontend/src/features/ai/backend/types.ts b/rsconcept/frontend/src/features/ai/backend/types.ts new file mode 100644 index 00000000..1bfda4b9 --- /dev/null +++ b/rsconcept/frontend/src/features/ai/backend/types.ts @@ -0,0 +1,8 @@ +/** Represents AI prompt. */ +export interface IPromptTemplate { + id: number; + owner: number | null; + label: string; + description: string; + text: string; +} diff --git a/rsconcept/frontend/src/features/ai/dialogs/dlg-ai-prompt.tsx b/rsconcept/frontend/src/features/ai/dialogs/dlg-ai-prompt.tsx new file mode 100644 index 00000000..a46ea50d --- /dev/null +++ b/rsconcept/frontend/src/features/ai/dialogs/dlg-ai-prompt.tsx @@ -0,0 +1,74 @@ +import { useState } from 'react'; + +import { ModalForm } from '@/components/modal'; + +import { type IPromptTemplate } from '../backend/types'; + +export interface DlgAIPromptDialogProps { + onPromptSelected?: (prompt: IPromptTemplate) => void; +} + +const mockPrompts: IPromptTemplate[] = [ + { + id: 1, + owner: null, + label: 'Greeting', + description: 'A simple greeting prompt.', + text: 'Hello, ${name}! How can I assist you today?' + }, + { + id: 2, + owner: null, + label: 'Summary', + description: 'Summarize the following text.', + text: 'Please summarize the following: ${text}' + } +]; + +export function DlgAIPromptDialog() { + const [selectedPrompt, setSelectedPrompt] = useState(mockPrompts[0]); + + return ( + { + e.preventDefault(); + // Placeholder for generate logic + }} + className='w-120 px-6 cc-column' + > +
+ + +
+ {selectedPrompt && ( +
+
Label:
+
{selectedPrompt.label}
+
Description:
+
{selectedPrompt.description}
+
Template Text:
+
{selectedPrompt.text}
+
+ )} +
+ ); +} diff --git a/rsconcept/frontend/src/features/ai/dialogs/index.tsx b/rsconcept/frontend/src/features/ai/dialogs/index.tsx new file mode 100644 index 00000000..8974e3aa --- /dev/null +++ b/rsconcept/frontend/src/features/ai/dialogs/index.tsx @@ -0,0 +1 @@ +export { DlgAIPromptDialog } from './dlg-ai-prompt'; diff --git a/rsconcept/frontend/src/features/ai/models/prompting-api.ts b/rsconcept/frontend/src/features/ai/models/prompting-api.ts new file mode 100644 index 00000000..e69de29b diff --git a/rsconcept/frontend/src/features/ai/models/prompting.ts b/rsconcept/frontend/src/features/ai/models/prompting.ts new file mode 100644 index 00000000..5c4d07e7 --- /dev/null +++ b/rsconcept/frontend/src/features/ai/models/prompting.ts @@ -0,0 +1,29 @@ +/** Represents prompt variable type. */ +export const PromptVariableType = { + BLOCK: 'block', + BLOCK_TITLE: 'block.title', + BLOCK_DESCRIPTION: 'block.description', + BLOCK_CONTENTS: 'block.contents', + + OSS: 'oss', + OSS_CONTENTS: 'oss.contents', + OSS_ALIAS: 'oss.alias', + OSS_TITLE: 'oss.title', + OSS_DESCRIPTION: 'oss.description', + + SCHEMA: 'schema', + SCHEMA_ALIAS: 'schema.alias', + SCHEMA_TITLE: 'schema.title', + SCHEMA_DESCRIPTION: 'schema.description', + SCHEMA_THESAURUS: 'schema.thesaurus', + SCHEMA_GRAPH: 'schema.graph', + SCHEMA_TYPE_GRAPH: 'schema.type-graph', + + CONSTITUENTA: 'constituent', + CONSTITUENTA_ALIAS: 'constituent.alias', + CONSTITUENTA_CONVENTION: 'constituent.convention', + CONSTITUENTA_DEFINITION: 'constituent.definition', + CONSTITUENTA_DEFINITION_FORMAL: 'constituent.definition-formal', + CONSTITUENTA_EXPRESSION_TREE: 'constituent.expression-tree' +} as const; +export type PromptVariableType = (typeof PromptVariableType)[keyof typeof PromptVariableType]; diff --git a/rsconcept/frontend/src/stores/dialogs.ts b/rsconcept/frontend/src/stores/dialogs.ts index 9722705a..edee5811 100644 --- a/rsconcept/frontend/src/stores/dialogs.ts +++ b/rsconcept/frontend/src/stores/dialogs.ts @@ -1,5 +1,6 @@ import { create } from 'zustand'; +import { type DlgAIPromptDialogProps } from '@/features/ai/dialogs/dlg-ai-prompt'; import { type DlgChangeLocationProps } from '@/features/library/dialogs/dlg-change-location'; import { type DlgCloneLibraryItemProps } from '@/features/library/dialogs/dlg-clone-library-item'; import { type DlgCreateVersionProps } from '@/features/library/dialogs/dlg-create-version'; @@ -67,7 +68,8 @@ export const DialogType = { GRAPH_PARAMETERS: 27, SHOW_TERM_GRAPH: 28, CREATE_SCHEMA: 29, - IMPORT_SCHEMA: 30 + IMPORT_SCHEMA: 30, + AI_PROMPT: 31 } as const; export type DialogType = (typeof DialogType)[keyof typeof DialogType]; @@ -110,6 +112,7 @@ interface DialogsStore { showEditCst: (props: DlgEditCstProps) => void; showCreateSchema: (props: DlgCreateSchemaProps) => void; showImportSchema: (props: DlgImportSchemaProps) => void; + showAIPrompt: (props: DlgAIPromptDialogProps) => void; } export const useDialogsStore = create()(set => ({ @@ -151,5 +154,6 @@ export const useDialogsStore = create()(set => ({ showUploadRSForm: props => set({ active: DialogType.UPLOAD_RSFORM, props: props }), showEditCst: props => set({ active: DialogType.EDIT_CONSTITUENTA, props: props }), showCreateSchema: props => set({ active: DialogType.CREATE_SCHEMA, props: props }), - showImportSchema: props => set({ active: DialogType.IMPORT_SCHEMA, props: props }) + showImportSchema: props => set({ active: DialogType.IMPORT_SCHEMA, props: props }), + showAIPrompt: (props: DlgAIPromptDialogProps) => set({ active: DialogType.AI_PROMPT, props: props }) }));