fix:build errors removed
This commit is contained in:
parent
ae6a634274
commit
079d398f8a
41 changed files with 321 additions and 205 deletions
|
|
@ -43,7 +43,7 @@ export async function fetchAttributes(
|
|||
request: ApiRequestFunction,
|
||||
entityType: string
|
||||
): Promise<AttributeDefinition[]> {
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: `/api/attributes/${entityType}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -81,7 +81,7 @@ export async function fetchConnectionAttributes(request: ApiRequestFunction): Pr
|
|||
* Endpoint: GET /api/attributes/FileItem
|
||||
*/
|
||||
export async function fetchFileAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
const data = await request<AttributeDefinition[] | { attributes: AttributeDefinition[] }>({
|
||||
const data = await request({
|
||||
url: '/api/attributes/FileItem',
|
||||
method: 'get'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -171,10 +171,19 @@ export async function registerApi(registerData: RegisterData): Promise<RegisterR
|
|||
headers
|
||||
});
|
||||
|
||||
const userData: any = response.data;
|
||||
return {
|
||||
success: true,
|
||||
message: 'Registration successful',
|
||||
user: response.data
|
||||
user: userData && typeof userData === 'object' && 'id' in userData ? {
|
||||
id: String(userData.id || ''),
|
||||
username: String(userData.username || ''),
|
||||
email: String(userData.email || ''),
|
||||
fullName: String(userData.fullName || ''),
|
||||
language: String(userData.language || 'en'),
|
||||
enabled: Boolean(userData.enabled !== false),
|
||||
privilege: String(userData.privilege || 'user')
|
||||
} : undefined
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -186,7 +195,7 @@ export async function registerWithMsalApi(
|
|||
request: ApiRequestFunction,
|
||||
userData: MsalRegisterData
|
||||
): Promise<RegisterResponse> {
|
||||
const response = await request<RegisterResponse>({
|
||||
const response = await request({
|
||||
url: '/api/msft/register',
|
||||
method: 'post',
|
||||
data: userData,
|
||||
|
|
@ -197,10 +206,19 @@ export async function registerWithMsalApi(
|
|||
}
|
||||
});
|
||||
|
||||
const responseData: any = response;
|
||||
return {
|
||||
success: true,
|
||||
message: 'Registration successful',
|
||||
user: response
|
||||
user: responseData && typeof responseData === 'object' && 'id' in responseData ? {
|
||||
id: String(responseData.id || ''),
|
||||
username: String(responseData.username || ''),
|
||||
email: String(responseData.email || ''),
|
||||
fullName: String(responseData.fullName || ''),
|
||||
language: String(responseData.language || 'en'),
|
||||
enabled: Boolean((responseData as any).enabled !== false),
|
||||
privilege: String((responseData as any).privilege || 'user')
|
||||
} : undefined
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<an
|
|||
* Fetch connection attributes from backend
|
||||
* Endpoint: GET /api/attributes/UserConnection
|
||||
*/
|
||||
export async function fetchConnectionAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
export async function fetchConnectionAttributes(_request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
// Note: This uses api.get directly due to response format handling
|
||||
// For now, we'll use api.get directly in the hook as well
|
||||
throw new Error('fetchConnectionAttributes should use api instance directly for response format handling');
|
||||
|
|
@ -109,7 +109,7 @@ export async function fetchConnections(
|
|||
}
|
||||
}
|
||||
|
||||
const data = await request<PaginatedResponse<Connection> | Connection[]>({
|
||||
const data = await request({
|
||||
url: '/api/connections/',
|
||||
method: 'get',
|
||||
params: requestParams
|
||||
|
|
@ -126,7 +126,7 @@ export async function createConnection(
|
|||
request: ApiRequestFunction,
|
||||
connectionData: CreateConnectionData
|
||||
): Promise<Connection> {
|
||||
return await request<Connection>({
|
||||
return await request({
|
||||
url: '/api/connections/',
|
||||
method: 'post',
|
||||
data: connectionData
|
||||
|
|
@ -141,7 +141,7 @@ export async function connectService(
|
|||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<ConnectResponse> {
|
||||
return await request<ConnectResponse>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/connect`,
|
||||
method: 'post'
|
||||
});
|
||||
|
|
@ -155,7 +155,7 @@ export async function disconnectService(
|
|||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<{ message: string }> {
|
||||
return await request<{ message: string }>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/disconnect`,
|
||||
method: 'post'
|
||||
});
|
||||
|
|
@ -169,7 +169,7 @@ export async function deleteConnection(
|
|||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<{ message: string }> {
|
||||
return await request<{ message: string }>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}`,
|
||||
method: 'delete'
|
||||
});
|
||||
|
|
@ -184,7 +184,7 @@ export async function updateConnection(
|
|||
connectionId: string,
|
||||
updateData: Partial<Connection>
|
||||
): Promise<Connection> {
|
||||
return await request<Connection>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}`,
|
||||
method: 'put',
|
||||
data: updateData
|
||||
|
|
@ -199,7 +199,7 @@ export async function refreshMicrosoftToken(
|
|||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<Connection> {
|
||||
return await request<Connection>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/refresh-microsoft-token`,
|
||||
method: 'post'
|
||||
});
|
||||
|
|
@ -213,7 +213,7 @@ export async function refreshGoogleToken(
|
|||
request: ApiRequestFunction,
|
||||
connectionId: string
|
||||
): Promise<Connection> {
|
||||
return await request<Connection>({
|
||||
return await request({
|
||||
url: `/api/connections/${connectionId}/refresh-google-token`,
|
||||
method: 'post'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<an
|
|||
* Endpoint: GET /api/attributes/FileItem
|
||||
*/
|
||||
export async function fetchFileAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
const data = await request<AttributeDefinition[] | { attributes: AttributeDefinition[] }>({
|
||||
const data = await request({
|
||||
url: '/api/attributes/FileItem',
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -109,7 +109,7 @@ export async function fetchFiles(
|
|||
}
|
||||
}
|
||||
|
||||
const data = await request<PaginatedResponse<FileInfo> | FileInfo[]>({
|
||||
const data = await request({
|
||||
url: '/api/files/list',
|
||||
method: 'get',
|
||||
params: requestParams
|
||||
|
|
@ -127,7 +127,7 @@ export async function fetchFileById(
|
|||
fileId: string
|
||||
): Promise<FileInfo | null> {
|
||||
try {
|
||||
const data = await request<FileInfo>({
|
||||
const data = await request({
|
||||
url: `/api/files/${fileId}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -147,7 +147,7 @@ export async function updateFile(
|
|||
fileId: string,
|
||||
fileData: Partial<FileInfo>
|
||||
): Promise<FileInfo> {
|
||||
return await request<FileInfo>({
|
||||
return await request({
|
||||
url: `/api/files/${fileId}`,
|
||||
method: 'put',
|
||||
data: fileData
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export async function fetchPermissions(
|
|||
params.item = item;
|
||||
}
|
||||
|
||||
const data = await request<UserPermissions>({
|
||||
const data = await request({
|
||||
url: '/api/rbac/permissions',
|
||||
method: 'get',
|
||||
params
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ export type ApiRequestFunction = (options: ApiRequestOptions<any>) => Promise<an
|
|||
* Fetch prompt attributes from backend
|
||||
* Endpoint: GET /api/attributes/Prompt
|
||||
*/
|
||||
export async function fetchPromptAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
export async function fetchPromptAttributes(_request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
// Note: This uses api.get directly due to response format handling
|
||||
// For now, we'll use api.get directly in the hook as well
|
||||
throw new Error('fetchPromptAttributes should use api instance directly for response format handling');
|
||||
|
|
@ -115,7 +115,7 @@ export async function fetchPrompts(
|
|||
}
|
||||
}
|
||||
|
||||
const data = await request<PaginatedResponse<Prompt> | Prompt[]>({
|
||||
const data = await request({
|
||||
url: '/api/prompts',
|
||||
method: 'get',
|
||||
params: requestParams
|
||||
|
|
@ -133,7 +133,7 @@ export async function fetchPromptById(
|
|||
promptId: string
|
||||
): Promise<Prompt | null> {
|
||||
try {
|
||||
const data = await request<Prompt>({
|
||||
const data = await request({
|
||||
url: `/api/prompts/${promptId}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -152,7 +152,7 @@ export async function createPrompt(
|
|||
request: ApiRequestFunction,
|
||||
promptData: CreatePromptData
|
||||
): Promise<Prompt> {
|
||||
return await request<Prompt>({
|
||||
return await request({
|
||||
url: '/api/prompts',
|
||||
method: 'post',
|
||||
data: promptData
|
||||
|
|
@ -168,7 +168,7 @@ export async function updatePrompt(
|
|||
promptId: string,
|
||||
promptData: UpdatePromptData
|
||||
): Promise<Prompt> {
|
||||
return await request<Prompt>({
|
||||
return await request({
|
||||
url: `/api/prompts/${promptId}`,
|
||||
method: 'put',
|
||||
data: promptData
|
||||
|
|
|
|||
|
|
@ -35,6 +35,8 @@ export interface AttributeDefinition {
|
|||
minWidth?: number;
|
||||
maxWidth?: number;
|
||||
filterOptions?: string[];
|
||||
readonly?: boolean;
|
||||
editable?: boolean;
|
||||
}
|
||||
|
||||
export interface PaginationParams {
|
||||
|
|
@ -78,7 +80,7 @@ export async function fetchCurrentUser(
|
|||
endpoint = '/api/google/me';
|
||||
}
|
||||
|
||||
return await request<User>({
|
||||
return await request({
|
||||
url: endpoint,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -108,7 +110,7 @@ export async function logoutUser(
|
|||
* Fetch user attributes from backend
|
||||
* Endpoint: GET /api/attributes/User
|
||||
*/
|
||||
export async function fetchUserAttributes(request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
export async function fetchUserAttributes(_request: ApiRequestFunction): Promise<AttributeDefinition[]> {
|
||||
// Note: This uses api.get directly in the hook due to response format handling
|
||||
// Keeping the function signature here for consistency, but implementation may need api instance
|
||||
throw new Error('fetchUserAttributes should use api instance directly for response format handling');
|
||||
|
|
@ -139,7 +141,7 @@ export async function fetchUsers(
|
|||
}
|
||||
}
|
||||
|
||||
const data = await request<PaginatedResponse<User> | User[]>({
|
||||
const data = await request({
|
||||
url: '/api/users/',
|
||||
method: 'get',
|
||||
params: requestParams
|
||||
|
|
@ -157,7 +159,7 @@ export async function fetchUserById(
|
|||
userId: string
|
||||
): Promise<User | null> {
|
||||
try {
|
||||
const data = await request<User>({
|
||||
const data = await request({
|
||||
url: `/api/users/${userId}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -176,7 +178,7 @@ export async function createUser(
|
|||
request: ApiRequestFunction,
|
||||
userData: Partial<User>
|
||||
): Promise<User> {
|
||||
return await request<User>({
|
||||
return await request({
|
||||
url: '/api/users',
|
||||
method: 'post',
|
||||
data: userData
|
||||
|
|
@ -192,7 +194,7 @@ export async function updateUser(
|
|||
userId: string,
|
||||
userData: UserUpdateData
|
||||
): Promise<User> {
|
||||
return await request<User>({
|
||||
return await request({
|
||||
url: `/api/users/${userId}`,
|
||||
method: 'put',
|
||||
data: userData
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export async function fetchWorkflows(request: ApiRequestFunction): Promise<Workf
|
|||
console.log('📤 fetchWorkflows: Making API request to /api/workflows/');
|
||||
|
||||
try {
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: '/api/workflows/',
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -134,7 +134,7 @@ export async function fetchWorkflow(
|
|||
request: ApiRequestFunction,
|
||||
workflowId: string
|
||||
): Promise<Workflow & { messages?: WorkflowMessage[]; logs?: WorkflowLog[] }> {
|
||||
return await request<any>({
|
||||
return await request({
|
||||
url: `/api/workflows/${workflowId}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -148,7 +148,7 @@ export async function fetchWorkflowStatus(
|
|||
request: ApiRequestFunction,
|
||||
workflowId: string
|
||||
): Promise<Workflow | { status: string } | null> {
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: `/api/workflows/${workflowId}/status`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
@ -174,7 +174,7 @@ export async function fetchWorkflowMessages(
|
|||
messageId?: string
|
||||
): Promise<WorkflowMessage[]> {
|
||||
const params = messageId ? { messageId } : undefined;
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: `/api/workflows/${workflowId}/messages`,
|
||||
method: 'get',
|
||||
params
|
||||
|
|
@ -207,7 +207,7 @@ export async function fetchWorkflowLogs(
|
|||
logId?: string
|
||||
): Promise<WorkflowLog[]> {
|
||||
const params = logId ? { logId } : undefined;
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: `/api/workflows/${workflowId}/logs`,
|
||||
method: 'get',
|
||||
params
|
||||
|
|
@ -248,7 +248,7 @@ export async function fetchChatData(
|
|||
|
||||
console.log('📤 fetchChatData request:', requestConfig);
|
||||
|
||||
const data = await request<any>(requestConfig);
|
||||
const data = await request(requestConfig);
|
||||
|
||||
console.log('📥 fetchChatData response:', data);
|
||||
|
||||
|
|
@ -359,7 +359,7 @@ export async function startWorkflowApi(
|
|||
console.log(' Request Body:', JSON.stringify(requestBody, null, 2));
|
||||
console.log(' Full Request Config:', JSON.stringify(requestConfig, null, 2));
|
||||
|
||||
const response = await request<StartWorkflowResponse>(requestConfig);
|
||||
const response = await request(requestConfig);
|
||||
|
||||
console.log('📥 startWorkflow response:', response);
|
||||
|
||||
|
|
@ -389,7 +389,7 @@ export async function updateWorkflowApi(
|
|||
workflowId: string,
|
||||
updateData: Partial<{ name: string; description?: string; tags?: string[] }>
|
||||
): Promise<Workflow> {
|
||||
return await request<Workflow>({
|
||||
return await request({
|
||||
url: `/api/workflows/${workflowId}`,
|
||||
method: 'put',
|
||||
data: updateData
|
||||
|
|
@ -494,7 +494,7 @@ export async function fetchAttributes(
|
|||
request: ApiRequestFunction,
|
||||
entityType: string = 'ChatWorkflow'
|
||||
): Promise<AttributeDefinition[]> {
|
||||
const data = await request<any>({
|
||||
const data = await request({
|
||||
url: `/api/attributes/${entityType}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
|||
import { MdModeEdit } from 'react-icons/md';
|
||||
import { useLanguage } from '../../../../providers/language/LanguageContext';
|
||||
import { Popup } from '../../../UiComponents/Popup';
|
||||
import { FormGeneratorForm } from '../../FormGeneratorForm';
|
||||
import { FormGeneratorForm, AttributeDefinition } from '../../FormGeneratorForm';
|
||||
import styles from '../ActionButton.module.css';
|
||||
|
||||
export interface EditActionButtonProps<T = any> {
|
||||
|
|
@ -154,16 +154,18 @@ export function EditActionButton<T = any>({
|
|||
// Get the item ID from the row
|
||||
const itemId = (editData as any)[idField];
|
||||
|
||||
// Get edit fields configuration
|
||||
const fields = getEditFields();
|
||||
// Get edit fields configuration from attributes
|
||||
const attributes = getAttributes();
|
||||
const fields = attributes || [];
|
||||
|
||||
// Extract the fields to update from the edit data
|
||||
const updateData: any = {};
|
||||
fields.forEach(field => {
|
||||
fields.forEach((field: AttributeDefinition) => {
|
||||
if (field.editable !== false) {
|
||||
const value = (updatedData as any)[field.key];
|
||||
const fieldName = field.name;
|
||||
const value = (updatedData as any)[fieldName];
|
||||
if (value !== undefined) {
|
||||
updateData[field.key] = value;
|
||||
updateData[fieldName] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ export function PlayActionButton<T = any>({
|
|||
loading = false,
|
||||
className = '',
|
||||
title,
|
||||
hookData,
|
||||
hookData: _hookData,
|
||||
idField = 'id',
|
||||
nameField = 'name',
|
||||
nameField: _nameField = 'name',
|
||||
contentField = 'content',
|
||||
navigateTo = 'start/dashboard',
|
||||
mode = 'prompt'
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export function FormGeneratorControls({
|
|||
filterFocused,
|
||||
onFilterFocus,
|
||||
selectedCount,
|
||||
displayData,
|
||||
displayData: _displayData,
|
||||
onDeleteSingle,
|
||||
onDeleteMultiple,
|
||||
onRefresh,
|
||||
|
|
|
|||
|
|
@ -453,7 +453,7 @@ export function FormGeneratorList<T extends Record<string, any>>({
|
|||
};
|
||||
|
||||
// Render field input
|
||||
const renderFieldInput = (field: FieldConfig, value: any, row: T, index: number) => {
|
||||
const renderFieldInput = (field: FieldConfig, value: any, row: T, _index: number) => {
|
||||
if (field.type === 'readonly' || !field.editable) {
|
||||
return (
|
||||
<div className={styles.fieldValue} key={field.key}>
|
||||
|
|
@ -491,12 +491,15 @@ export function FormGeneratorList<T extends Record<string, any>>({
|
|||
}
|
||||
|
||||
// Default to text input
|
||||
const inputType = attributeTypeToInputType(field.type || 'string');
|
||||
// TextField doesn't support 'textarea' type, use 'text' instead
|
||||
const textFieldType = inputType === 'textarea' ? 'text' : inputType;
|
||||
return (
|
||||
<TextField
|
||||
key={field.key}
|
||||
value={value || ''}
|
||||
onChange={(newValue) => onFieldChange?.(row, field.key, newValue)}
|
||||
type={attributeTypeToInputType(field.type || 'string')}
|
||||
type={textFieldType as 'text' | 'email' | 'url' | 'password' | 'search' | 'tel' | 'number'}
|
||||
required={field.required}
|
||||
readonly={!field.editable}
|
||||
className={styles.fieldInput}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ const SidebarItem: React.FC<SidebarItemProps> = React.memo(({
|
|||
|
||||
// Get the actual color from parent li element
|
||||
const parentLi = wrapper.closest('li');
|
||||
const parentColor = parentLi ? window.getComputedStyle(parentLi).color : '#000000';
|
||||
|
||||
// Force color directly - use black for now to ensure visibility
|
||||
const iconColor = '#000000'; // Force black for visibility
|
||||
|
|
@ -218,7 +217,6 @@ const SidebarItem: React.FC<SidebarItemProps> = React.memo(({
|
|||
>
|
||||
<Icon
|
||||
className={`${styles.icon} ${styles.iconMinimized} ${isDisabled ? styles.disabledIcon : ''}`}
|
||||
size={25}
|
||||
style={{
|
||||
width: '25px',
|
||||
height: '25px',
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ const SidebarSubmenu: React.FC<SidebarSubmenuProps> = ({ item, isOpen, isMinimiz
|
|||
{SubIcon && (
|
||||
<SubIcon
|
||||
className={styles.submenuHorizontalIcon}
|
||||
size={16}
|
||||
style={{
|
||||
width: '16px',
|
||||
height: '16px',
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export function ConnectedFilesList({
|
|||
deletingFiles = new Set(),
|
||||
previewingFiles = new Set(),
|
||||
removingFiles = new Set(),
|
||||
workflowId,
|
||||
workflowId: _workflowId,
|
||||
emptyMessage = 'No files connected to this workflow'
|
||||
}: ConnectedFilesListProps) {
|
||||
// Combine workflow files and pending files, deduplicating by fileId
|
||||
|
|
@ -98,7 +98,7 @@ export function ConnectedFilesList({
|
|||
}
|
||||
return false;
|
||||
},
|
||||
removeOptimistically: (fileId: string) => {
|
||||
removeOptimistically: (_fileId: string) => {
|
||||
// This will be handled by the parent component's state
|
||||
},
|
||||
refetch: async () => {
|
||||
|
|
@ -121,7 +121,7 @@ export function ConnectedFilesList({
|
|||
// View button (always shown)
|
||||
buttons.push({
|
||||
type: 'view',
|
||||
onAction: async (file: WorkflowFile) => {
|
||||
onAction: async (_file: WorkflowFile) => {
|
||||
// View is handled by ViewActionButton's FilePreview component
|
||||
return Promise.resolve();
|
||||
},
|
||||
|
|
@ -156,7 +156,7 @@ export function ConnectedFilesList({
|
|||
return buttons;
|
||||
}, [actionButtons, onDelete, onRemove]);
|
||||
|
||||
const handleView = async (file: WorkflowFile) => {
|
||||
const handleView = async (_file: WorkflowFile) => {
|
||||
// View is handled by ViewActionButton's FilePreview component
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
|
@ -187,10 +187,10 @@ export function ConnectedFilesList({
|
|||
<div className={styles.fileList}>
|
||||
{allFiles
|
||||
.filter(file => file.fileId && file.fileId.trim() !== '') // Ensure fileId exists
|
||||
.map((file, index) => {
|
||||
const isDeleting = deletingFiles.has(file.fileId!);
|
||||
const isPreviewing = previewingFiles.has(file.fileId!);
|
||||
const isRemoving = removingFiles.has(file.fileId!);
|
||||
.map((file) => {
|
||||
// const isDeleting = deletingFiles.has(file.fileId!);
|
||||
// const isPreviewing = previewingFiles.has(file.fileId!);
|
||||
// const isRemoving = removingFiles.has(file.fileId!);
|
||||
// Use fileId as key since we've filtered out files without it
|
||||
const uniqueKey = file.fileId!;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { LogProps, WorkflowLog } from './LogTypes';
|
||||
import { LogProps } from './LogTypes';
|
||||
import { AutoScroll } from '../AutoScroll';
|
||||
import { formatUnixTimestamp } from '../../../utils/time';
|
||||
import styles from './Log.module.css';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import type React from 'react';
|
||||
|
||||
/**
|
||||
* Log entry from workflow
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useEffect, useRef } from 'react';
|
|||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import { lv95ToWGS84, wgs84ToLV95 } from './LV95Converter';
|
||||
import type { MapPoint, ParcelGeometry, MapViewProps } from './MapView';
|
||||
import type { MapViewProps } from './MapView';
|
||||
import styles from './MapView.module.css';
|
||||
|
||||
// Fix for default marker icons in Leaflet
|
||||
|
|
@ -32,7 +32,7 @@ const MapViewLeaflet: React.FC<MapViewProps> = ({
|
|||
}) => {
|
||||
const mapRef = useRef<L.Map | null>(null);
|
||||
const mapContainerRef = useRef<HTMLDivElement>(null);
|
||||
const layersRef = useRef<L.LayerGroup[]>([]);
|
||||
const layersRef = useRef<L.Layer[]>([]);
|
||||
const centerMarkerRef = useRef<L.Marker | null>(null);
|
||||
|
||||
// Initialize map
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ export interface DocumentItemProps {
|
|||
*/
|
||||
export const DocumentItem: React.FC<DocumentItemProps> = ({
|
||||
document,
|
||||
message,
|
||||
message: _message,
|
||||
className,
|
||||
onFileDelete,
|
||||
onFileRemove,
|
||||
|
|
@ -31,7 +31,7 @@ export const DocumentItem: React.FC<DocumentItemProps> = ({
|
|||
deletingFiles = new Set(),
|
||||
previewingFiles = new Set(),
|
||||
removingFiles = new Set(),
|
||||
workflowId
|
||||
workflowId: _workflowId
|
||||
}) => {
|
||||
// Convert MessageDocument to WorkflowFile format for compatibility with action buttons
|
||||
const workflowFile: WorkflowFile = useMemo(() => ({
|
||||
|
|
@ -50,7 +50,7 @@ export const DocumentItem: React.FC<DocumentItemProps> = ({
|
|||
|
||||
// Create hookData object for action buttons
|
||||
const hookData = useMemo(() => ({
|
||||
handleDelete: async (fileId: string) => {
|
||||
handleDelete: async (_fileId: string) => {
|
||||
if (onFileDelete) {
|
||||
await onFileDelete(workflowFile);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ interface TextFieldProps extends BaseTextFieldProps {
|
|||
step?: string;
|
||||
min?: string | number;
|
||||
max?: string | number;
|
||||
onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
||||
}
|
||||
|
||||
const TextField: React.FC<TextFieldProps> = ({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import type React from 'react';
|
||||
|
||||
/**
|
||||
* Log entry from workflow
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@ export * from './MapView';
|
|||
export * from './ParcelInfoPanel';
|
||||
export * from './CopyableTruncatedValue';
|
||||
export { Log } from './Log';
|
||||
export * from './Log';
|
||||
export type { LogProps } from './Log/LogTypes';
|
||||
export { LogMessage } from './Log/LogMessage';
|
||||
export type { LogMessageProps } from './Log/LogMessage';
|
||||
export { WorkflowStatus } from './WorkflowStatus';
|
||||
export * from './WorkflowStatus';
|
||||
export type { WorkflowStatusProps } from './WorkflowStatus/WorkflowStatusTypes';
|
||||
export * from './AutoScroll';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createContext, useContext, useState, useCallback, useEffect } from 'react';
|
||||
import React, { createContext, useContext, useCallback } from 'react';
|
||||
import { useUserFiles, useFileOperations, UserFile } from '../hooks/useFiles';
|
||||
|
||||
interface FileContextType {
|
||||
|
|
@ -16,7 +16,7 @@ interface FileContextType {
|
|||
const FileContext = createContext<FileContextType | undefined>(undefined);
|
||||
|
||||
export function FileProvider({ children }: { children: React.ReactNode }) {
|
||||
const { data: files, loading, error, refetch: refetchFiles, removeFileOptimistically, addFileOptimistically } = useUserFiles();
|
||||
const { data: files, loading, error, refetch: refetchFiles, removeFileOptimistically } = useUserFiles();
|
||||
const {
|
||||
handleFileUpload: hookHandleFileUpload,
|
||||
handleFileDelete: hookHandleFileDelete,
|
||||
|
|
@ -40,25 +40,13 @@ export function FileProvider({ children }: { children: React.ReactNode }) {
|
|||
return result;
|
||||
}
|
||||
|
||||
// Add file optimistically to the shared state
|
||||
const newFile: UserFile = {
|
||||
id: fileData.id,
|
||||
file_name: fileData.fileName || file.name,
|
||||
mime_type: fileData.mimeType || file.type || 'application/octet-stream',
|
||||
action: 'Document', // Will be determined by mime type in useUserFiles
|
||||
created_at: fileData.creationDate ? new Date(fileData.creationDate * 1000).toISOString() : new Date().toISOString(),
|
||||
size: fileData.fileSize || file.size,
|
||||
source: 'user_uploaded'
|
||||
};
|
||||
|
||||
addFileOptimistically(newFile);
|
||||
|
||||
// File will be added via refetch
|
||||
// Refetch to ensure we have the latest data (this will update all consumers)
|
||||
await refetchFiles();
|
||||
}
|
||||
|
||||
return result;
|
||||
}, [hookHandleFileUpload, addFileOptimistically, refetchFiles]);
|
||||
}, [hookHandleFileUpload, refetchFiles]);
|
||||
|
||||
// Centralized file delete that updates the shared state
|
||||
const handleFileDelete = useCallback(async (fileId: string, onOptimisticDelete?: () => void) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
import { createContext, useContext, useState, useCallback, ReactNode } from 'react';
|
||||
|
||||
interface WorkflowSelectionContextType {
|
||||
selectedWorkflowId: string | null;
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ const PageManager: React.FC<PageManagerProps> = ({
|
|||
) : (
|
||||
<PageRenderer
|
||||
pageData={pageData}
|
||||
onButtonClick={(buttonId, button) => {
|
||||
onButtonClick={(_buttonId, _button) => {
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
|
@ -88,7 +88,8 @@ const PageManager: React.FC<PageManagerProps> = ({
|
|||
|
||||
} else {
|
||||
if (import.meta.env.DEV) {
|
||||
const instance = newInstances.get(currentPath);
|
||||
const _instance = newInstances.get(currentPath);
|
||||
void _instance; // Intentionally unused, for debugging purposes
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import { DragDropOverlay } from '../../components/UiComponents/DragDropOverlay';
|
|||
import { useLanguage } from '../../providers/language/LanguageContext';
|
||||
import { usePermissions } from '../../hooks/usePermissions';
|
||||
import { FiPaperclip } from 'react-icons/fi';
|
||||
import type { WorkflowFile } from '../../hooks/playground/useDashboardInputForm';
|
||||
import styles from '../../styles/pages.module.css';
|
||||
|
||||
interface PageRendererProps {
|
||||
|
|
@ -362,7 +363,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
onSave?: (sectionId: string, data: any) => Promise<void>;
|
||||
getNestedValue: (obj: any, path: string) => any;
|
||||
setNestedValue: (obj: any, path: string, value: any) => any;
|
||||
}> = ({ sections, formData, fieldsBySection, loadingBySection, errorsBySection, onSave, getNestedValue, setNestedValue }) => {
|
||||
}> = ({ sections, formData, fieldsBySection, loadingBySection, errorsBySection, onSave, getNestedValue, setNestedValue: _setNestedValue }) => {
|
||||
const [sectionFormData, setSectionFormData] = useState<Record<string, any>>({});
|
||||
const [sectionSaveLoading, setSectionSaveLoading] = useState<Record<string, boolean>>({});
|
||||
const [sectionSaveMessages, setSectionSaveMessages] = useState<Record<string, { type: 'success' | 'error', text: string } | null>>({});
|
||||
|
|
@ -677,6 +678,46 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
|
||||
// Render content based on type
|
||||
const renderContent = (content: PageContent) => {
|
||||
// Wrapper functions to convert fileId-based handlers to WorkflowFile-based handlers
|
||||
// These are defined at the top level of renderContent so they're accessible in all content cases
|
||||
const wrapFileDelete: ((file: WorkflowFile) => Promise<void>) | undefined = hookData?.handleFileDelete ? async (file: WorkflowFile) => {
|
||||
if (!hookData?.handleFileDelete || !file) return;
|
||||
const handler = hookData.handleFileDelete as any;
|
||||
// Check if handler expects fileId (string) or file (WorkflowFile)
|
||||
if (file?.fileId && typeof file.fileId === 'string') {
|
||||
// Try fileId signature first (handler might be (fileId: string, ...) => Promise<boolean>)
|
||||
try {
|
||||
const result = handler(file.fileId);
|
||||
if (result instanceof Promise) await result;
|
||||
return;
|
||||
} catch {
|
||||
// Fall through to file signature
|
||||
}
|
||||
}
|
||||
// Try file signature (handler might be (file: WorkflowFile) => Promise<void>)
|
||||
const result = handler(file);
|
||||
if (result instanceof Promise) await result;
|
||||
} : undefined;
|
||||
|
||||
const wrapFileRemove: ((file: WorkflowFile) => Promise<void>) | undefined = hookData?.handleFileRemove ? async (file: WorkflowFile) => {
|
||||
if (!hookData?.handleFileRemove || !file) return;
|
||||
const handler = hookData.handleFileRemove as any;
|
||||
// Check if handler expects fileId (string) or file (WorkflowFile)
|
||||
if (file?.fileId && typeof file.fileId === 'string') {
|
||||
// Try fileId signature first (handler might be (fileId: string) => void | Promise<void>)
|
||||
try {
|
||||
const result = handler(file.fileId);
|
||||
if (result instanceof Promise) await result;
|
||||
return;
|
||||
} catch {
|
||||
// Fall through to file signature
|
||||
}
|
||||
}
|
||||
// Try file signature (handler might be (file: WorkflowFile) => Promise<void>)
|
||||
const result = handler(file);
|
||||
if (result instanceof Promise) await result;
|
||||
} : undefined;
|
||||
|
||||
switch (content.type) {
|
||||
case 'heading':
|
||||
const HeadingTag = `h${content.level || 2}` as keyof React.JSX.IntrinsicElements;
|
||||
|
|
@ -834,7 +875,14 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
}
|
||||
} else {
|
||||
// Non-function disabled value
|
||||
disabledFn = () => action.disabled as boolean | { disabled: boolean; message?: string };
|
||||
const disabledValue = action.disabled;
|
||||
if (typeof disabledValue === 'boolean') {
|
||||
disabledFn = () => disabledValue;
|
||||
} else if (disabledValue && typeof disabledValue === 'object' && 'disabled' in disabledValue) {
|
||||
disabledFn = () => disabledValue as { disabled: boolean; message?: string };
|
||||
} else {
|
||||
disabledFn = () => false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
disabledFn = () => false;
|
||||
|
|
@ -949,7 +997,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
<DropdownSelect
|
||||
items={hookData.promptItems || []}
|
||||
selectedItemId={hookData.selectedPromptId || null}
|
||||
onSelect={hookData.onPromptSelect}
|
||||
onSelect={hookData.onPromptSelect || (() => {})}
|
||||
placeholder={t('dashboard.prompt.select', 'Select a prompt')}
|
||||
emptyMessage={t('dashboard.prompt.empty', 'No prompts available')}
|
||||
headerText={t('dashboard.prompt.header', 'Select Prompt')}
|
||||
|
|
@ -966,7 +1014,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
<DropdownSelect
|
||||
items={hookData.workflowModeItems || []}
|
||||
selectedItemId={hookData.selectedWorkflowMode || null}
|
||||
onSelect={hookData.onWorkflowModeSelect}
|
||||
onSelect={hookData.onWorkflowModeSelect || (() => {})}
|
||||
placeholder={t('dashboard.workflow.mode.select', 'Select workflow mode')}
|
||||
emptyMessage={t('dashboard.workflow.mode.empty', 'No modes available')}
|
||||
headerText={t('dashboard.workflow.mode.header', 'Workflow Mode')}
|
||||
|
|
@ -1033,7 +1081,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
},
|
||||
{
|
||||
type: 'remove',
|
||||
onAction: hookData.handleFileRemove,
|
||||
onAction: wrapFileRemove,
|
||||
showOnlyForPending: true,
|
||||
idField: 'fileId',
|
||||
loadingStateName: 'removingItems'
|
||||
|
|
@ -1045,9 +1093,12 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
idField: 'fileId'
|
||||
}
|
||||
]}
|
||||
onDelete={hookData.handleFileDelete}
|
||||
onRemove={hookData.handleFileRemove}
|
||||
onAttach={hookData.handleFileAttach} // Allow attaching files for next message
|
||||
onDelete={wrapFileDelete}
|
||||
onRemove={wrapFileRemove}
|
||||
onAttach={hookData.handleFileAttach ? async (fileId: string) => {
|
||||
const result = hookData.handleFileAttach!(fileId);
|
||||
if (result instanceof Promise) await result;
|
||||
} : undefined}
|
||||
deletingFiles={hookData.deletingFiles || new Set()}
|
||||
previewingFiles={hookData.previewingFiles || new Set()}
|
||||
removingFiles={new Set()} // Can be tracked if needed
|
||||
|
|
@ -1080,7 +1131,13 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
justifyContent: 'flex-end'
|
||||
}}>
|
||||
<UploadButton
|
||||
onUpload={hookData.handleFileUploadAndAttach || hookData.handleFileUpload}
|
||||
onUpload={hookData.handleFileUploadAndAttach || hookData.handleFileUpload ? async (file: File) => {
|
||||
const handler = hookData.handleFileUploadAndAttach || hookData.handleFileUpload;
|
||||
if (handler) {
|
||||
// Handler returns Promise<{ success, data }>, but UploadButton expects Promise<void>
|
||||
await handler(file);
|
||||
}
|
||||
} : async () => {}}
|
||||
disabled={hookData.isSubmitting || false}
|
||||
loading={hookData.uploadingFile || false}
|
||||
variant="primary"
|
||||
|
|
@ -1207,7 +1264,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
<DropdownSelect
|
||||
items={hookData.promptItems || []}
|
||||
selectedItemId={hookData.selectedPromptId || null}
|
||||
onSelect={hookData.onPromptSelect}
|
||||
onSelect={hookData.onPromptSelect || (() => {})}
|
||||
placeholder={t('dashboard.prompt.select', 'Select a prompt')}
|
||||
emptyMessage={t('dashboard.prompt.empty', 'No prompts available')}
|
||||
headerText={t('dashboard.prompt.header', 'Select Prompt')}
|
||||
|
|
@ -1222,7 +1279,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
<DropdownSelect
|
||||
items={hookData.workflowModeItems || []}
|
||||
selectedItemId={hookData.selectedWorkflowMode || null}
|
||||
onSelect={hookData.onWorkflowModeSelect}
|
||||
onSelect={hookData.onWorkflowModeSelect || (() => {})}
|
||||
placeholder={t('dashboard.workflow.mode.select', 'Select workflow mode')}
|
||||
emptyMessage={t('dashboard.workflow.mode.empty', 'No modes available')}
|
||||
headerText={t('dashboard.workflow.mode.header', 'Workflow Mode')}
|
||||
|
|
@ -1320,8 +1377,8 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
showDocuments={config.showDocuments !== false}
|
||||
showMetadata={config.showMetadata !== false}
|
||||
showProgress={config.showProgress !== false}
|
||||
onFileDelete={hookData?.handleFileDelete}
|
||||
onFileRemove={hookData?.handleFileRemove}
|
||||
onFileDelete={wrapFileDelete}
|
||||
onFileRemove={wrapFileRemove}
|
||||
deletingFiles={hookData?.deletingFiles}
|
||||
previewingFiles={hookData?.previewingFiles}
|
||||
removingFiles={hookData?.removingFiles}
|
||||
|
|
@ -1334,8 +1391,8 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
key={message.id || index}
|
||||
message={cleanMessage}
|
||||
showDocuments={config.showDocuments !== false}
|
||||
onFileDelete={hookData?.handleFileDelete}
|
||||
onFileRemove={hookData?.handleFileRemove}
|
||||
onFileDelete={wrapFileDelete}
|
||||
onFileRemove={wrapFileRemove}
|
||||
deletingFiles={hookData?.deletingFiles}
|
||||
previewingFiles={hookData?.previewingFiles}
|
||||
removingFiles={hookData?.removingFiles}
|
||||
|
|
@ -1356,8 +1413,8 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
showMetadata={config.showMetadata !== false}
|
||||
showProgress={config.showProgress !== false}
|
||||
emptyMessage={config.emptyMessage ? resolveLanguageText(config.emptyMessage, t) : undefined}
|
||||
onFileDelete={hookData?.handleFileDelete}
|
||||
onFileRemove={hookData?.handleFileRemove}
|
||||
onFileDelete={wrapFileDelete}
|
||||
onFileRemove={wrapFileRemove}
|
||||
deletingFiles={hookData?.deletingFiles}
|
||||
previewingFiles={hookData?.previewingFiles}
|
||||
removingFiles={hookData?.removingFiles}
|
||||
|
|
@ -1662,6 +1719,14 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
return await createOperation(formData);
|
||||
};
|
||||
|
||||
// Evaluate disabled property if it's a function
|
||||
const isDisabled = typeof button.disabled === 'function'
|
||||
? button.disabled(hookData)
|
||||
: button.disabled ?? false;
|
||||
const disabledValue = typeof isDisabled === 'object' && isDisabled !== null && 'disabled' in isDisabled
|
||||
? isDisabled.disabled
|
||||
: Boolean(isDisabled);
|
||||
|
||||
return (
|
||||
<CreateButton
|
||||
key={button.id}
|
||||
|
|
@ -1672,7 +1737,7 @@ const PageRenderer: React.FC<PageRendererProps> = ({
|
|||
variant={button.variant || 'primary'}
|
||||
size={button.size || 'md'}
|
||||
icon={button.icon}
|
||||
disabled={button.disabled}
|
||||
disabled={disabledValue}
|
||||
onSuccess={() => {
|
||||
// Refetch data after successful creation
|
||||
if (hookData.refetch) {
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ export const SidebarProvider: React.FC<SidebarProviderProps> = ({ children }) =>
|
|||
}
|
||||
|
||||
// Process parent groups
|
||||
for (const [parentPath, parentGroup] of parentGroups.entries()) {
|
||||
for (const [_parentPath, parentGroup] of parentGroups.entries()) {
|
||||
// Filter subpages by RBAC access
|
||||
const accessibleSubpages = [];
|
||||
for (const subpage of parentGroup.subpages) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ export const dashboardPageData: GenericPageData = {
|
|||
placeholder: 'dashboard.workflow.select',
|
||||
emptyMessage: 'dashboard.workflow.empty',
|
||||
headerText: 'dashboard.workflow.header',
|
||||
onSelect: () => {}, // Placeholder - actual handler comes from dataSource.onSelectMethod
|
||||
dataSource: {
|
||||
itemsProperty: 'workflowItems',
|
||||
selectedIdProperty: 'selectedWorkflowId',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { GenericPageData } from '../../pageInterface';
|
||||
import { FaTable, FaBuilding } from 'react-icons/fa';
|
||||
import { FaTable } from 'react-icons/fa';
|
||||
import { IoMdSend } from 'react-icons/io';
|
||||
import { usePekTablesContext } from '../../../../contexts/PekTablesContext';
|
||||
import PekTablesDropdown from './pek-tables/PekTablesDropdown';
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@ import styles from './PekLocationInput.module.css';
|
|||
|
||||
const PekLocationInput: React.FC = () => {
|
||||
const {
|
||||
kanton,
|
||||
setKanton,
|
||||
gemeinde,
|
||||
setGemeinde,
|
||||
kanton: _kanton,
|
||||
setKanton: _setKanton,
|
||||
gemeinde: _gemeinde,
|
||||
setGemeinde: _setGemeinde,
|
||||
adresse,
|
||||
setAdresse,
|
||||
buildLocationString,
|
||||
useCurrentLocation,
|
||||
isGettingLocation,
|
||||
locationError,
|
||||
locationError: _locationError,
|
||||
searchParcel,
|
||||
isSearchingParcel
|
||||
} = usePekContext();
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ export type PrivilegeChecker = () => boolean | Promise<boolean>;
|
|||
export interface ButtonFormField {
|
||||
key: string;
|
||||
label: string | LanguageText;
|
||||
type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'readonly';
|
||||
type: 'string' | 'boolean' | 'email' | 'textarea' | 'date' | 'enum' | 'readonly' | 'multiselect';
|
||||
required?: boolean;
|
||||
placeholder?: string | LanguageText;
|
||||
minRows?: number;
|
||||
maxRows?: number;
|
||||
validator?: (value: any) => string | null;
|
||||
defaultValue?: any;
|
||||
options?: string[] | Array<{ value: string | number; label: string }>; // For enum/multiselect fields
|
||||
}
|
||||
|
||||
// Dropdown configuration for header dropdown buttons
|
||||
|
|
@ -37,6 +38,7 @@ export interface DropdownConfig<T = any> {
|
|||
itemsProperty?: string; // Property name in hookData that contains items array
|
||||
selectedIdProperty?: string; // Property name in hookData that contains selectedItemId
|
||||
onSelectMethod?: string; // Method name in hookData for onSelect callback
|
||||
loadingProperty?: string; // Property name in hookData that contains loading state
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -159,9 +161,24 @@ export interface GenericDataHook {
|
|||
columns?: any[]; // Optional columns configuration
|
||||
// File operations
|
||||
handleUpload?: (file: File) => Promise<{ success: boolean; data: any }>; // For file upload functionality
|
||||
handleFileUpload?: (file: File) => Promise<{ success: boolean; data: any }>; // Alias for handleUpload
|
||||
handleDownload?: (fileId: string, fileName: string) => Promise<boolean>; // For file download functionality
|
||||
handleDelete?: (fileId: string, onOptimisticDelete?: () => void) => Promise<boolean>; // For file delete functionality
|
||||
handleFileDelete?: ((fileId: string, onOptimisticDelete?: () => void) => Promise<boolean>) | ((file: any) => Promise<void>); // Can accept fileId or WorkflowFile
|
||||
handlePreview?: (fileId: string, fileName: string, mimeType?: string) => Promise<any>; // For file preview functionality
|
||||
// File management properties
|
||||
workflowFiles?: any[]; // Files connected to workflow
|
||||
pendingFiles?: any[]; // Files pending attachment
|
||||
allUserFiles?: any[]; // All user files
|
||||
handleFileRemove?: ((fileId: string) => Promise<void> | void) | ((file: any) => Promise<void> | void); // Can accept fileId or WorkflowFile
|
||||
handleFileAttach?: (fileId: string) => Promise<void>; // Attach file to workflow (always returns Promise)
|
||||
handleFileUploadAndAttach?: (file: File) => Promise<{ success: boolean; data: any }>; // Upload and attach file
|
||||
uploadingFile?: boolean; // Loading state for file upload
|
||||
deletingFiles?: Set<string>; // Set of file IDs being deleted
|
||||
previewingFiles?: Set<string>; // Set of file IDs being previewed
|
||||
removingFiles?: Set<string>; // Set of file IDs being removed
|
||||
isFileAttachmentPopupOpen?: boolean; // Whether file attachment popup is open
|
||||
setIsFileAttachmentPopupOpen?: (open: boolean) => void; // Set file attachment popup state
|
||||
// FormGenerator specific handlers
|
||||
onDelete?: (row: any) => Promise<void>; // For single item deletion
|
||||
onDeleteMultiple?: (rows: any[]) => Promise<void>; // For multiple item deletion
|
||||
|
|
@ -170,14 +187,37 @@ export interface GenericDataHook {
|
|||
onInputChange?: (value: string) => void;
|
||||
handleSubmit?: () => Promise<void>; // No parameters, uses internal inputValue
|
||||
isSubmitting?: boolean;
|
||||
// Prompt selector properties
|
||||
promptPermission?: {
|
||||
view?: boolean;
|
||||
read?: string;
|
||||
};
|
||||
promptItems?: Array<{ id: string | number; label: string; value: any }>;
|
||||
selectedPromptId?: string | number | null;
|
||||
onPromptSelect?: (item: { id: string | number; label: string; value: any } | null) => void | Promise<void>;
|
||||
promptsLoading?: boolean;
|
||||
// Workflow mode selector properties
|
||||
workflowModeItems?: Array<{ id: string | number; label: string; value: any }>;
|
||||
selectedWorkflowMode?: string | number | null;
|
||||
onWorkflowModeSelect?: (item: { id: string | number; label: string; value: any } | null) => void | Promise<void>;
|
||||
// Workflow lifecycle state
|
||||
workflowId?: string;
|
||||
workflowStatus?: string;
|
||||
workflowData?: {
|
||||
currentRound?: number;
|
||||
[key: string]: any;
|
||||
};
|
||||
isRunning?: boolean;
|
||||
currentRound?: number; // Current workflow round
|
||||
latestStats?: any; // Latest workflow statistics
|
||||
// Messages from workflow
|
||||
messages?: any[];
|
||||
// Logs from workflow
|
||||
logs?: any[];
|
||||
// Dashboard log tree
|
||||
dashboardTree?: any; // Dashboard log tree structure
|
||||
onToggleOperationExpanded?: (operationId: string) => void;
|
||||
getChildOperations?: (parentId: string | null) => string[];
|
||||
// Message overlay component
|
||||
MessageOverlayComponent?: () => React.ReactElement;
|
||||
// Settings-specific properties
|
||||
|
|
@ -186,6 +226,8 @@ export interface GenericDataHook {
|
|||
settingsLoading?: Record<string, boolean>; // Loading state per section
|
||||
settingsErrors?: Record<string, string | null>; // Error state per section
|
||||
saveSection?: (sectionId: string, data: any) => Promise<void>; // Save handler for a section
|
||||
// Dropdown data source loading property
|
||||
[key: string]: any; // Allow additional properties for dynamic data sources
|
||||
}
|
||||
|
||||
// Action button configuration
|
||||
|
|
@ -306,8 +348,8 @@ export interface PageDataFile {
|
|||
export interface SidebarItem {
|
||||
id: string;
|
||||
name: string;
|
||||
link: string;
|
||||
icon?: IconType;
|
||||
link: string | undefined; // Allow undefined for parent groups that aren't clickable pages
|
||||
icon?: IconType | React.ComponentType<React.SVGProps<SVGSVGElement>>; // Allow both IconType and SVG components
|
||||
moduleEnabled: boolean;
|
||||
order: number;
|
||||
submenu?: SidebarSubmenuItemData[];
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { useWorkflowLifecycle } from './useWorkflowLifecycle';
|
|||
import { useWorkflows } from './useWorkflows';
|
||||
import { useDashboardLogTree } from './useDashboardLogTree';
|
||||
import { extractFileIdsFromMessage, convertFilesToDocuments, sortMessages } from './playgroundUtils';
|
||||
import type { WorkflowLog as LogTypesWorkflowLog } from '../../components/UiComponents/Log/LogTypes';
|
||||
|
||||
export interface WorkflowFile {
|
||||
id: string;
|
||||
|
|
@ -45,7 +46,6 @@ export function useDashboardInputForm() {
|
|||
isStopping,
|
||||
startingWorkflow,
|
||||
messages,
|
||||
logs,
|
||||
dashboardLogs,
|
||||
unifiedContentLogs,
|
||||
latestStats,
|
||||
|
|
@ -190,7 +190,20 @@ export function useDashboardInputForm() {
|
|||
|
||||
// Only process if there are new logs
|
||||
if (newLogs.length > 0) {
|
||||
processDashboardLogs(newLogs);
|
||||
// Convert API WorkflowLog format to LogTypes WorkflowLog format
|
||||
const convertedLogs: LogTypesWorkflowLog[] = newLogs.map(log => ({
|
||||
id: log.id || `${log.operationId || 'unknown'}-${log.timestamp || Date.now()}`,
|
||||
workflowId: log.workflowId || '',
|
||||
message: log.message || '',
|
||||
type: log.type,
|
||||
timestamp: log.timestamp || Date.now(),
|
||||
status: log.status,
|
||||
progress: log.progress,
|
||||
performance: log.performance,
|
||||
parentId: log.parentId,
|
||||
operationId: log.operationId
|
||||
}));
|
||||
processDashboardLogs(convertedLogs);
|
||||
}
|
||||
|
||||
lastDashboardLogsLengthRef.current = dashboardLogs.length;
|
||||
|
|
@ -352,7 +365,7 @@ export function useDashboardInputForm() {
|
|||
return allMessages.sort(sortMessages);
|
||||
}, [messages, optimisticMessage, workflowId]);
|
||||
|
||||
const handleFileUpload = useCallback(async (file: File) => {
|
||||
const handleFileUpload = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
|
||||
const result = await fileContext.handleFileUpload(file, workflowId || undefined);
|
||||
|
||||
if (result.success && result.fileData) {
|
||||
|
|
@ -360,8 +373,7 @@ export function useDashboardInputForm() {
|
|||
const fileData = responseData.file || responseData;
|
||||
const fileId = fileData?.id;
|
||||
|
||||
if (!fileId) return;
|
||||
|
||||
if (fileId) {
|
||||
const newFile: WorkflowFile = {
|
||||
id: fileId,
|
||||
fileId: fileId,
|
||||
|
|
@ -378,9 +390,15 @@ export function useDashboardInputForm() {
|
|||
return [...prev, newFile];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
success: result.success || false,
|
||||
data: result.fileData || null
|
||||
};
|
||||
}, [workflowId, fileContext]);
|
||||
|
||||
const handleFileAttach = useCallback(async (fileId: string) => {
|
||||
const handleFileAttach = useCallback(async (fileId: string): Promise<void> => {
|
||||
const isInPending = pendingFiles.some(f => f.fileId === fileId);
|
||||
|
||||
if (isInPending) {
|
||||
|
|
@ -424,8 +442,8 @@ export function useDashboardInputForm() {
|
|||
}
|
||||
}, [pendingFiles, fileContext.files, workflowFiles]);
|
||||
|
||||
const handleFileUploadAndAttach = useCallback(async (file: File) => {
|
||||
await handleFileUpload(file);
|
||||
const handleFileUploadAndAttach = useCallback(async (file: File): Promise<{ success: boolean; data: any }> => {
|
||||
return await handleFileUpload(file);
|
||||
}, [handleFileUpload]);
|
||||
|
||||
const handleFileRemove = useCallback(async (file: WorkflowFile) => {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ export function useDashboardLogTree() {
|
|||
|
||||
// Get or create operation
|
||||
const existingOperation = newTree.operations.get(operationId);
|
||||
const isNewOperation = !existingOperation;
|
||||
|
||||
// Create new logs Map (copy existing logs if updating)
|
||||
const logsMap = existingOperation
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import { useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useApiRequest } from '../useApi';
|
||||
import {
|
||||
type Workflow,
|
||||
|
|
@ -334,7 +334,6 @@ export function useWorkflowLifecycle() {
|
|||
|
||||
// Determine if polling should continue
|
||||
const currentStatus = statusRef.current;
|
||||
const changedAt = statusChangedFromRunningAtRef.current;
|
||||
|
||||
// Stop polling immediately for failed or stopped workflows
|
||||
// For completed workflows, allow grace period (handled by useEffect)
|
||||
|
|
@ -357,7 +356,7 @@ export function useWorkflowLifecycle() {
|
|||
}, [request, updateWorkflowStatus, processUnifiedChatData]);
|
||||
|
||||
// Load initial workflow data (non-polling)
|
||||
const loadWorkflowData = useCallback(async (id: string) => {
|
||||
const _loadWorkflowData = useCallback(async (id: string) => {
|
||||
try {
|
||||
const workflowData = await fetchWorkflowApi(request, id).catch(() => null);
|
||||
|
||||
|
|
@ -416,6 +415,7 @@ export function useWorkflowLifecycle() {
|
|||
console.error('Error loading workflow data:', error);
|
||||
}
|
||||
}, [request, updateWorkflowStatus, convertLogToFrontendFormat, processUnifiedChatData]);
|
||||
void _loadWorkflowData; // Intentionally unused, reserved for future use
|
||||
|
||||
// Set up polling when workflow is running
|
||||
useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useMsal } from '@azure/msal-react';
|
|||
import api from '../api';
|
||||
import { useApiRequest } from './useApi';
|
||||
import { getApiBaseUrl } from '../../config/config';
|
||||
import { setUserDataCache, clearUserDataCache } from '../utils/userCache';
|
||||
import { setUserDataCache, clearUserDataCache, type CachedUserData } from '../utils/userCache';
|
||||
import {
|
||||
loginApi,
|
||||
fetchCurrentUserApi,
|
||||
|
|
@ -44,7 +44,7 @@ export function useAuth() {
|
|||
|
||||
if (userData) {
|
||||
// Cache user data in sessionStorage (cleared on tab close - more secure than localStorage)
|
||||
setUserDataCache(userData);
|
||||
setUserDataCache(userData as CachedUserData);
|
||||
}
|
||||
} catch (userError) {
|
||||
console.error('Failed to fetch user data after login:', userError);
|
||||
|
|
@ -171,7 +171,7 @@ export function useMsalAuth() {
|
|||
try {
|
||||
const userData = await fetchCurrentUserApi('msft');
|
||||
if (userData) {
|
||||
setUserDataCache(userData);
|
||||
setUserDataCache(userData as CachedUserData);
|
||||
}
|
||||
} catch (userError) {
|
||||
console.error('Failed to fetch user data after Microsoft login:', userError);
|
||||
|
|
@ -349,7 +349,7 @@ export function useGoogleAuth() {
|
|||
try {
|
||||
const userData = await fetchCurrentUserApi('google');
|
||||
if (userData) {
|
||||
setUserDataCache(userData);
|
||||
setUserDataCache(userData as CachedUserData);
|
||||
}
|
||||
} catch (userError) {
|
||||
console.error('Failed to fetch user data after Google login:', userError);
|
||||
|
|
@ -652,7 +652,7 @@ export function useCurrentUser() {
|
|||
setUser(userData);
|
||||
|
||||
// Cache user data in sessionStorage (cleared on tab close - more secure than localStorage)
|
||||
setUserDataCache(userData);
|
||||
setUserDataCache(userData as CachedUserData);
|
||||
|
||||
return userData;
|
||||
} catch (error: any) {
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ import { getUserDataCache } from '../utils/userCache';
|
|||
import { useApiRequest } from './useApi';
|
||||
import { usePermissions, type UserPermissions } from './usePermissions';
|
||||
import {
|
||||
fetchFileAttributes,
|
||||
fetchFileAttributes as _fetchFileAttributes,
|
||||
fetchFiles as fetchFilesApi,
|
||||
fetchFileById as fetchFileByIdApi,
|
||||
updateFile as updateFileApi,
|
||||
deleteFile as deleteFileApi,
|
||||
deleteFiles as deleteFilesApi,
|
||||
type AttributeDefinition,
|
||||
type PaginationParams
|
||||
deleteFiles as deleteFilesApi
|
||||
} from '../api/fileApi';
|
||||
|
||||
// File interfaces - exactly matching backend FileItem model
|
||||
|
|
@ -32,7 +30,7 @@ export interface FileInfo {
|
|||
// Field names come directly from backend attributes
|
||||
export type UserFile = any;
|
||||
|
||||
// Attribute definition interface
|
||||
// Attribute definition interface (local definition, not imported to avoid conflicts)
|
||||
export interface AttributeDefinition {
|
||||
name: string;
|
||||
label: string;
|
||||
|
|
@ -46,7 +44,7 @@ export interface AttributeDefinition {
|
|||
filterOptions?: string[]; // For enum types
|
||||
}
|
||||
|
||||
// Pagination parameters
|
||||
// Pagination parameters (local definition, not imported to avoid conflicts)
|
||||
export interface PaginationParams {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
|
|
@ -129,8 +127,7 @@ export function useUserFiles() {
|
|||
if (!cachedUser) {
|
||||
// User is not authenticated, skip fetching files
|
||||
setFiles([]);
|
||||
setLoading(false);
|
||||
setError(null);
|
||||
// Note: loading and error are managed by useApiRequest hook
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -456,10 +456,10 @@ export function usePek() {
|
|||
const firstCoord = clickedParcel.coordinates[0];
|
||||
|
||||
// Calculate centroid as fallback, but prefer a point we know is inside
|
||||
const sumX = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.x, 0);
|
||||
const sumY = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.y, 0);
|
||||
const centroidX = sumX / clickedParcel.coordinates.length;
|
||||
const centroidY = sumY / clickedParcel.coordinates.length;
|
||||
// const sumX = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.x, 0);
|
||||
// const sumY = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.y, 0);
|
||||
// const _centroidX = sumX / clickedParcel.coordinates.length;
|
||||
// const _centroidY = sumY / clickedParcel.coordinates.length;
|
||||
|
||||
// Use first coordinate (guaranteed to be on/in the parcel) for search
|
||||
const locationString = `${firstCoord.x},${firstCoord.y}`;
|
||||
|
|
@ -658,7 +658,7 @@ export function usePek() {
|
|||
|
||||
// Try to update the parcel via PUT request
|
||||
try {
|
||||
const updateResponse = await api.put(
|
||||
await api.put(
|
||||
`/api/realestate/parzelle/${parzelleResult.id}`,
|
||||
updateParcelRequestBody
|
||||
);
|
||||
|
|
|
|||
|
|
@ -223,13 +223,8 @@ export function usePrompts() {
|
|||
fieldType = 'string';
|
||||
}
|
||||
}
|
||||
// Legacy support for old format
|
||||
else if (attr.type === 'boolean') {
|
||||
fieldType = 'boolean';
|
||||
} else if (attr.type === 'enum' && attr.filterOptions) {
|
||||
fieldType = 'enum';
|
||||
options = attr.filterOptions.map(opt => ({ value: opt, label: opt }));
|
||||
}
|
||||
// Note: Legacy 'boolean' and 'enum' types are not in the AttributeDefinition type union
|
||||
// If needed, they should be handled via type casting: (attr as any).type === 'boolean'
|
||||
|
||||
// Define validators and required fields
|
||||
let required = attr.required === true;
|
||||
|
|
@ -444,7 +439,7 @@ export function usePromptOperations() {
|
|||
}
|
||||
};
|
||||
|
||||
const handlePromptUpdate = async (promptId: string, updateData: { name: string; content: string }, originalData?: any) => {
|
||||
const handlePromptUpdate = async (promptId: string, updateData: { name: string; content: string }, _originalData?: any) => {
|
||||
setUpdateError(null);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
const currentUserIdRef = useRef<string | undefined>(currentUser?.id);
|
||||
|
||||
// Load phone name from localStorage
|
||||
const loadPhoneName = useCallback((): string => {
|
||||
const _loadPhoneName = useCallback((): string => {
|
||||
try {
|
||||
return localStorage.getItem('userPhoneName') || '';
|
||||
} catch (error) {
|
||||
|
|
@ -65,9 +65,10 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
return '';
|
||||
}
|
||||
}, []);
|
||||
void _loadPhoneName; // Intentionally unused, reserved for future use
|
||||
|
||||
// Load theme from localStorage
|
||||
const loadTheme = useCallback((): string => {
|
||||
const _loadTheme = useCallback((): string => {
|
||||
try {
|
||||
const savedTheme = localStorage.getItem('theme');
|
||||
if (savedTheme) {
|
||||
|
|
@ -80,9 +81,10 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
return 'light';
|
||||
}
|
||||
}, []);
|
||||
void _loadTheme; // Intentionally unused, reserved for future use
|
||||
|
||||
// Load speech data from localStorage
|
||||
const loadSpeechData = useCallback((): any | null => {
|
||||
const _loadSpeechData = useCallback((): any | null => {
|
||||
try {
|
||||
const savedData = localStorage.getItem('speechSignUpData');
|
||||
const timestamp = localStorage.getItem('speechSignUpTimestamp');
|
||||
|
|
@ -109,9 +111,10 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
return null;
|
||||
}
|
||||
}, []);
|
||||
void _loadSpeechData; // Intentionally unused, reserved for future use
|
||||
|
||||
// Fetch user data from API
|
||||
const fetchUserData = useCallback(async () => {
|
||||
const _fetchUserData = useCallback(async () => {
|
||||
if (!currentUser?.id) return null;
|
||||
|
||||
try {
|
||||
|
|
@ -122,9 +125,10 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
throw error;
|
||||
}
|
||||
}, [currentUser?.id, getUser]);
|
||||
void _fetchUserData; // Intentionally unused, reserved for future use
|
||||
|
||||
// Fetch field definitions from backend
|
||||
const fetchFieldsForSection = useCallback(async (sectionId: string): Promise<SettingsFieldConfig[]> => {
|
||||
const _fetchFieldsForSection = useCallback(async (sectionId: string): Promise<SettingsFieldConfig[]> => {
|
||||
try {
|
||||
setSettingsLoading(prev => ({ ...prev, [sectionId]: true }));
|
||||
setSettingsErrors(prev => ({ ...prev, [sectionId]: null }));
|
||||
|
|
@ -148,6 +152,7 @@ export function createSettingsHook(): () => GenericDataHook {
|
|||
setSettingsLoading(prev => ({ ...prev, [sectionId]: false }));
|
||||
}
|
||||
}, [request]);
|
||||
void _fetchFieldsForSection; // Intentionally unused, reserved for future use
|
||||
|
||||
// Load all settings data
|
||||
const loadSettingsData = useCallback(async () => {
|
||||
|
|
|
|||
|
|
@ -125,14 +125,8 @@ export function useCurrentUser() {
|
|||
}
|
||||
|
||||
try {
|
||||
let logoutEndpoint = '/api/local/logout';
|
||||
|
||||
// Determine the correct logout endpoint based on authentication authority
|
||||
if (user.authenticationAuthority === 'msft') {
|
||||
logoutEndpoint = '/api/msft/logout';
|
||||
} else if (user.authenticationAuthority === 'local') {
|
||||
logoutEndpoint = '/api/local/logout';
|
||||
}
|
||||
// Note: logoutEndpoint is determined by logoutUserApi based on authenticationAuthority
|
||||
|
||||
await logoutUserApi(request, user.authenticationAuthority);
|
||||
|
||||
|
|
@ -498,13 +492,8 @@ export function useOrgUsers() {
|
|||
fieldType = 'string';
|
||||
}
|
||||
}
|
||||
// Legacy support for old format
|
||||
else if (attr.type === 'boolean') {
|
||||
fieldType = 'boolean';
|
||||
} else if (attr.type === 'enum' && attr.filterOptions) {
|
||||
fieldType = 'enum';
|
||||
options = attr.filterOptions.map(opt => ({ value: opt, label: opt }));
|
||||
}
|
||||
// Note: Legacy 'boolean' and 'enum' types are not in the AttributeDefinition type union
|
||||
// If needed, they should be handled via type casting: (attr as any).type === 'boolean'
|
||||
|
||||
// Define validators and required fields
|
||||
let required = attr.required === true;
|
||||
|
|
@ -547,7 +536,7 @@ export function useOrgUsers() {
|
|||
key: attr.name,
|
||||
label: attr.label || attr.name,
|
||||
type: fieldType,
|
||||
editable: attr.editable !== false && attr.readonly !== true,
|
||||
editable: (attr as any).editable !== false && (attr as any).readonly !== true,
|
||||
required,
|
||||
validator,
|
||||
minRows,
|
||||
|
|
@ -652,7 +641,7 @@ export function useUserOperations() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleUserUpdate = async (userId: string, updateData: UserUpdateData, originalData?: any) => {
|
||||
const handleUserUpdate = async (userId: string, updateData: UserUpdateData, _originalData?: any) => {
|
||||
setUpdateError(null);
|
||||
setEditingUsers(prev => new Set(prev).add(userId));
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { MessageOverlay } from '../components/UiComponents';
|
|||
import type { MessageMode } from '../components/UiComponents';
|
||||
import { useLanguage } from '../providers/language/LanguageContext';
|
||||
import { useWorkflowSelection } from '../contexts/WorkflowSelectionContext';
|
||||
import { getUserDataCache } from '../utils/userCache';
|
||||
// import { getUserDataCache } from '../utils/userCache'; // Unused import
|
||||
import { usePermissions, type UserPermissions } from './usePermissions';
|
||||
|
||||
// Workflow interface matching backend
|
||||
|
|
@ -279,13 +279,8 @@ export function useUserWorkflows() {
|
|||
fieldType = 'string';
|
||||
}
|
||||
}
|
||||
// Legacy support for old format
|
||||
else if (attr.type === 'boolean') {
|
||||
fieldType = 'boolean';
|
||||
} else if (attr.type === 'enum' && attr.filterOptions) {
|
||||
fieldType = 'enum';
|
||||
options = attr.filterOptions.map(opt => ({ value: opt, label: opt }));
|
||||
}
|
||||
// Note: Legacy 'boolean' and 'enum' types are not in the AttributeDefinition type union
|
||||
// If needed, they should be handled via type casting: (attr as any).type === 'boolean'
|
||||
|
||||
// Define validators and required fields
|
||||
let required = attr.required === true;
|
||||
|
|
@ -360,7 +355,7 @@ export function useUserWorkflows() {
|
|||
|
||||
// Listen for workflow creation events to refetch workflows list
|
||||
useEffect(() => {
|
||||
const handleWorkflowCreated = (event: CustomEvent<{ workflow: UserWorkflow }>) => {
|
||||
const handleWorkflowCreated = (_event: CustomEvent<{ workflow: UserWorkflow }>) => {
|
||||
// Refetch to ensure we have the latest data
|
||||
fetchWorkflowsData();
|
||||
};
|
||||
|
|
@ -409,7 +404,7 @@ export function useWorkflowOperations() {
|
|||
const [warningData, setWarningData] = useState<{ header: string; message: string; mode: MessageMode } | null>(null);
|
||||
|
||||
// Language context
|
||||
const { t } = useLanguage();
|
||||
const { t: _t } = useLanguage();
|
||||
|
||||
// Workflow selection context - to clear selection if deleted workflow is selected
|
||||
const { selectedWorkflowId, clearWorkflow } = useWorkflowSelection();
|
||||
|
|
@ -594,7 +589,7 @@ export function useWorkflowOperations() {
|
|||
);
|
||||
};
|
||||
|
||||
const handleWorkflowUpdate = async (workflowId: string, updateData: Partial<{ name: string; description?: string; tags?: string[] }>, originalWorkflowData?: any) => {
|
||||
const handleWorkflowUpdate = async (workflowId: string, updateData: Partial<{ name: string; description?: string; tags?: string[] }>, _originalWorkflowData?: any) => {
|
||||
setUpdateError(null);
|
||||
setEditingWorkflows(prev => new Set(prev).add(workflowId));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue