diff --git a/README.md b/README.md
index 2201f2c9..9c402887 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
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 @@
+
+
+
\ 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 @@
+
+
+
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}