Files
tkmind_go/ui/desktop/src/projects.ts
T
Zane 77ea27f5f5 UI update with sidebar and settings tabs (#3288)
Co-authored-by: Nahiyan Khan <nahiyan@squareup.com>
Co-authored-by: Taylor Ho <taylorkmho@gmail.com>
Co-authored-by: Lily Delalande <119957291+lily-de@users.noreply.github.com>
Co-authored-by: Spence <spencrmartin@gmail.com>
Co-authored-by: spencrmartin <spencermartin@squareup.com>
Co-authored-by: Judson Stephenson <Jud@users.noreply.github.com>
Co-authored-by: Max Novich <mnovich@squareup.com>
Co-authored-by: Best Codes <106822363+The-Best-Codes@users.noreply.github.com>
Co-authored-by: caroline-a-mckenzie <cmckenzie@squareup.com>
Co-authored-by: Michael Neale <michael.neale@gmail.com>
2025-07-15 17:24:41 -07:00

226 lines
5.8 KiB
TypeScript

import { Session } from './sessions';
import { client } from './api/client.gen';
/**
* Interface for a project with all details
*/
export interface Project {
id: string;
name: string;
description: string | null;
defaultDirectory: string;
sessionIds: string[];
createdAt: string;
updatedAt: string;
}
/**
* Simplified project metadata for listings
*/
export interface ProjectMetadata {
id: string;
name: string;
description: string | null;
defaultDirectory: string;
sessionCount: number;
createdAt: string;
updatedAt: string;
}
/**
* Project with associated session objects
*/
export interface ProjectWithSessions extends Project {
sessions: Session[];
}
/**
* Request to create a new project
*/
export interface CreateProjectRequest {
name: string;
description?: string;
defaultDirectory: string;
}
/**
* Request to update an existing project
*/
export interface UpdateProjectRequest {
name?: string;
description?: string | null;
defaultDirectory?: string;
}
/**
* Ensure default directory is properly set
*/
function ensureDefaultDirectory(project: Partial<Project>): Project {
return {
id: project.id || '',
name: project.name || '',
description: project.description || null,
defaultDirectory: project.defaultDirectory || process.env.HOME || '',
sessionIds: project.sessionIds || [],
createdAt: project.createdAt || new Date().toISOString(),
updatedAt: project.updatedAt || new Date().toISOString(),
};
}
/**
* Fetches all available projects from the API
* @returns Promise with an array of ProjectMetadata objects
*/
export async function fetchProjects(): Promise<ProjectMetadata[]> {
try {
const response = await client.get<{ projects: ProjectMetadata[] }>({
url: '/projects',
});
if (response && response.data && response.data.projects) {
return response.data.projects;
} else {
throw new Error('Unexpected response format from list_projects');
}
} catch (error) {
console.error('Error fetching projects:', error);
throw error;
}
}
/**
* Creates a new project
* @param request The project creation request data
* @returns Promise with the created project
*/
export async function createProject(request: CreateProjectRequest): Promise<Project> {
const response = await client.post<{ project: Project }>({
url: '/projects',
body: request,
headers: {
'Content-Type': 'application/json',
},
});
console.log('Raw createProject response:', response);
return ensureDefaultDirectory(
(response as { project?: Project }).project ?? (response as unknown as Project)
);
}
/**
* Gets details for a specific project
* @param projectId The ID of the project to fetch
* @returns Promise with project details
*/
export async function getProject(projectId: string): Promise<Project> {
try {
const response = await client.get<{ project: Project }>({
url: `/projects/${projectId}`,
});
if (!response?.data?.project) {
throw new Error(`Unexpected response format from get_project_details for ID: ${projectId}`);
}
return ensureDefaultDirectory(response.data.project);
} catch (error) {
console.error(`Error fetching project ${projectId}:`, error);
throw error;
}
}
/**
* Updates an existing project
* @param projectId The ID of the project to update
* @param request The project update request data
* @returns Promise with the updated project
*/
export async function updateProject(
projectId: string,
request: UpdateProjectRequest
): Promise<Project> {
try {
const response = await client.put<{ project: Project }>({
url: `/projects/${projectId}`,
body: request,
headers: {
'Content-Type': 'application/json',
},
});
if (!response?.data?.project) {
throw new Error(`Unexpected response format from update_project for ID: ${projectId}`);
}
return ensureDefaultDirectory(response.data.project);
} catch (error) {
console.error(`Error updating project ${projectId}:`, error);
throw error;
}
}
/**
* Deletes a project
* @param projectId The ID of the project to delete
*/
export async function deleteProject(projectId: string): Promise<void> {
try {
await client.delete({
url: `/projects/${projectId}`,
});
} catch (error) {
console.error(`Error deleting project ${projectId}:`, error);
throw error;
}
}
/**
* Adds a session to a project
* @param projectId The ID of the project
* @param sessionId The ID of the session to add
*/
export async function addSessionToProject(projectId: string, sessionId: string): Promise<void> {
try {
await client.post({
url: `/projects/${projectId}/sessions/${sessionId}`,
});
} catch (error) {
console.error(`Error adding session ${sessionId} to project ${projectId}:`, error);
throw error;
}
}
/**
* Removes a session from a project
* @param projectId The ID of the project
* @param sessionId The ID of the session to remove
*/
export async function removeSessionFromProject(
projectId: string,
sessionId: string
): Promise<void> {
try {
await client.delete({
url: `/projects/${projectId}/sessions/${sessionId}`,
});
} catch (error) {
console.error(`Error removing session ${sessionId} from project ${projectId}:`, error);
throw error;
}
}
/**
* Generate a project ID in the format proj_yyyymmdd_hhmmss
*/
export function generateProjectId(): string {
const now = new Date();
const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `proj_${year}${month}${day}_${hours}${minutes}${seconds}`;
}