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