diff --git a/README.md b/README.md index 2201f2c9..9c402887 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@
AOSSIE - + OrgExplorer
diff --git a/index.html b/index.html index 4b2eedf7..c42f7e1e 100644 --- a/index.html +++ b/index.html @@ -23,8 +23,12 @@ - - + + + + + + diff --git a/public/org-explorer-icon.png b/public/org-explorer-icon.png new file mode 100644 index 00000000..fa11b9d8 --- /dev/null +++ b/public/org-explorer-icon.png @@ -0,0 +1,2 @@ +data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAABCAQAAAC1HAwAAAAA+0lEQVQY02NgAAIAAAyuSrbxYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8iDWOO/AAAAABJRU5ErkJggg== + \ No newline at end of file diff --git a/public/org-explorer-icon.svg b/public/org-explorer-icon.svg new file mode 100644 index 00000000..0ab05eb4 --- /dev/null +++ b/public/org-explorer-icon.svg @@ -0,0 +1,7 @@ + + + + + Org + Explorer + \ No newline at end of file diff --git a/public/org-explorer-logo.svg b/public/org-explorer-logo.svg new file mode 100644 index 00000000..9266f532 --- /dev/null +++ b/public/org-explorer-logo.svg @@ -0,0 +1,6 @@ + + + + + OrgExplorer + diff --git a/src/context/AppContext.jsx b/src/context/AppContext.jsx index 66f7de0d..cecfbf7c 100644 --- a/src/context/AppContext.jsx +++ b/src/context/AppContext.jsx @@ -41,6 +41,7 @@ export function AppProvider({ children }) { const [advanceAnalyticsComplete, setAdvanceAnalyticsComplete] = useState(false) const [isComplete, setIsComplete] = useState(false) const [auditComplete, setAuditComplete] = useState(false) + const [auditFailures, setAuditFailures] = useState([]) const [lastOrgNames, setLastOrgNames] = useState([]) // True until the cached analysis has been read, so routes that need a model // wait for the restore instead of bouncing to the picker on first paint. @@ -220,23 +221,35 @@ export function AppProvider({ children }) { const repos = selectAnalysisRepos(allRepos) const map = {} + let hasFailures = false + const failedKeys = [] for (let i = 0; i < repos.length; i += 5) { const batch = repos.slice(i, i + 5) - await Promise.allSettled(batch.map(async repo => { + const results = await Promise.allSettled(batch.map(async repo => { map[`${repo.orgLogin}/${repo.name}`] = await fetchIssues(repo.orgLogin, repo.name, pat) })) + results.forEach((r, idx) => { + if (r.status === 'rejected') { + hasFailures = true + failedKeys.push(`${batch[idx].orgLogin}/${batch[idx].name}`) + } + }) + } + if (failedKeys.length) { + setAuditFailures(prev => [...new Set([...prev, ...failedKeys])]) } - return map + return { map, hasFailures } }, [pat, selectAnalysisRepos]) // Governance audit : used directly when repos are already complete const runAudit = useCallback(async () => { if (!model || govLoading) return setGovLoading(true) - const map = await auditRepos(model.allRepos) + setAuditFailures([]) + const { map, hasFailures } = await auditRepos(model.allRepos) setIssuesData(map) setGovLoading(false) - setAuditComplete(!!pat) + setAuditComplete(!hasFailures && !!pat) }, [model, pat, govLoading, auditRepos]) // Entry point for Governance / Analytics "Run Complete Analysis" @@ -259,10 +272,11 @@ export function AppProvider({ children }) { if (!currentModel) return setGovLoading(true) - const map = await auditRepos(currentModel.allRepos) + setAuditFailures([]) + const { map, hasFailures } = await auditRepos(currentModel.allRepos) setIssuesData(map) setGovLoading(false) - setAuditComplete(!!pat) + setAuditComplete(!hasFailures && !!pat) }, [isComplete, model, runFullExplore, auditRepos, pat, govLoading]) // Advanced analytics — parallel batches of 5 (Section 3.2.5) @@ -321,7 +335,11 @@ export function AppProvider({ children }) { setAdvanceAnalyticsLoading(true) const [issuesMap, pullsMap] = await Promise.all([ - auditRepos(currentModel.allRepos), + (async () => { + const { map, hasFailures } = await auditRepos(currentModel.allRepos) + if (hasFailures) setAuditFailures(prev => prev) + return map + })(), (async () => { const repos = selectAnalysisRepos(currentModel.totalRepos) const map = {} @@ -383,7 +401,7 @@ export function AppProvider({ children }) { rateLimit, loading, loadMsg, govLoading, error, totalRepo, runAdvanceAnalytics, refreshRateLimit, advanceAnalyticsLoading, advanceAnalyticsComplete, runFullAnalytics, - isComplete, auditComplete, lastOrgNames, hydrating, + isComplete, auditComplete, auditFailures, lastOrgNames, hydrating, explore, runFullExplore, runAudit, runGovernanceAnalysis, setError, staleRepoStats }}> {children}