1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135export interface Tag { id: string; content: string; } export interface Blocker { id: string; created_at: string; messages: string[]; url: string; content: string; categories: string[]; tags: Tag[]; // 'status' is not directly on the blocker object in the sample but might be useful if present later } // Keeping DatasetConfig for backward compatibility or potential future list usage // Keeping DatasetConfig for backward compatibility or potential future list usage // export interface DatasetConfig { // name: string; // url: string; // } // export const fetchDatasetList = async (): Promise<DatasetConfig[]> => { // // Current requirement is to let user enter URL. // // We'll return an empty list or predefined ones if needed later. // return []; // }; export const STORAGE_KEY = 'equalify_ignored_ids'; export const getIgnoredIds = (): string[] => { const stored = localStorage.getItem(STORAGE_KEY); return stored ? JSON.parse(stored) : []; }; export const toggleIgnoreId = (id: string) => { const current = getIgnoredIds(); const index = current.indexOf(id); let newIds; if (index >= 0) { newIds = current.filter(i => i !== id); } else { newIds = [...current, id]; } localStorage.setItem(STORAGE_KEY, JSON.stringify(newIds)); return newIds; }; export const bulkIgnoreIds = (ids: string[], shouldIgnore: boolean) => { const current = new Set(getIgnoredIds()); ids.forEach(id => { if (shouldIgnore) current.add(id); else current.delete(id); }); const newIds = Array.from(current); localStorage.setItem(STORAGE_KEY, JSON.stringify(newIds)); return newIds; }; interface Pagination { totalPages: number; pageSize: number; page: number; totalCount: number; } interface ApiResponse { audit_name: string; audit_id: string; pagination: Pagination; blockers: Blocker[]; // availableCategories, statusCounts, etc. can be added if needed } export interface Dataset { id: string; url: string; name: string; blockers: Blocker[]; timestamp: number; } export const loadDataset = async (url: string): Promise<Dataset> => { try { // Basic URL validation let fetchUrl = url; try { const parsedUrl = new URL(url); const pageSize = parsedUrl.searchParams.get('pageSize'); if (!pageSize || parseInt(pageSize) < 100) { // Enforce larger page size if not set or too small, though the user's URL usually rules // For now, trust the user's URL but warn if needed } if (pageSize && parseInt(pageSize) > 100) { console.warn(`Large pageSize (${pageSize}) detected. The API may return empty results. Consider reducing it to 100.`); } } catch (e) { console.error("Invalid URL provided:", url); throw new Error("The provided URL is not valid."); } const response = await fetch(fetchUrl); if (!response.ok) { throw new Error(`Failed to fetch data: ${response.statusText} (${response.status})`); } const data: ApiResponse = await response.json(); // If blockers is empty but totalCount is > 0, it's likely the pageSize bug if ((!data.blockers || data.blockers.length === 0) && data.pagination && data.pagination.totalCount > 0) { console.warn("API returned 0 blockers despite a positive totalCount. This often happens with pageSize > 100."); throw new Error("The API returned no data for this page size. Please try reducing the pageSize in the URL (e.g., to 100)."); } // Generate a unique ID for local tracking to allow multiple views/pages of the same audit const localId = typeof crypto !== 'undefined' && crypto.randomUUID ? crypto.randomUUID() : `ds_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`; return { id: localId, url: url, name: data.audit_name || "Untitled Audit", blockers: data.blockers || [], timestamp: Date.now() }; } catch (error) { console.error("Error loading dataset:", error); throw error; } };