| 33 | 33 | | return roadmapIn(section).map((item) => ({ label: item.title, path: `soon/${item.key}`, soon: true, about: item.summary })); |
| 34 | 34 | | } |
| 35 | 35 | | |
| 36 | | − | export const SECTIONS: Section[] = [ |
| 37 | | − | { |
| 38 | | − | key: "Code", |
| 39 | | − | tabs: [ |
| 40 | | − | { label: "Files", path: "code", also: ["tree", "blob"] }, |
| 41 | | − | { label: "Commits", path: "commits", also: ["commit"] }, |
| 42 | | − | { label: "Branches", path: "branches" }, |
| 43 | | − | { label: "Tags", path: "tags" }, |
| 44 | | − | { label: "Releases", path: "releases" }, |
| 45 | | − | { label: "Compare", path: "compare" }, |
| 46 | | − | // No Docs tab: code is not docs. Docs is a workspace mode, filtered by project there. |
| 47 | | − | ], |
| 48 | | − | }, |
| 49 | | − | { |
| 50 | | − | key: "Issues", |
| 51 | | − | tabs: [ |
| 52 | | − | { label: "Issues", path: "issues" }, |
| 53 | | − | { label: "Milestones", path: "milestones" }, |
| 54 | | − | ...soon("Issues"), |
| 55 | | − | ], |
| 56 | | − | }, |
| 57 | | − | { |
| 58 | | − | key: "Deployments", |
| 59 | | − | tabs: [{ label: "Deployments", path: "deployments" }, ...soon("Deployments")], |
| 60 | | − | }, |
| 61 | | − | { |
| 62 | | − | key: "Observability", |
| 63 | | − | tabs: [ |
| 64 | | − | { label: "Overview", path: "observability", exact: true, members: true }, |
| 65 | | − | { label: "Requests", path: "observability/requests", members: true }, |
| 66 | | − | { label: "Logs", path: "observability/logs", members: true }, |
| 67 | | − | { label: "Traces", path: "observability/traces", members: true }, |
| 68 | | − | { label: "Errors", path: "observability/errors", members: true }, |
| 69 | | − | { label: "Metrics", path: "observability/metrics", members: true }, |
| 70 | | − | { label: "Settings", path: "observability/settings", members: true, needs: "manage_integrations" }, |
| 71 | | − | ...soon("Observability"), |
| 72 | | − | ], |
| 73 | | − | }, |
| 74 | | − | { |
| 75 | | − | key: "Security", |
| 76 | | − | tabs: [ |
| 77 | | − | { label: "Overview", path: "security", members: true, needs: "security_alerts", exact: true }, |
| 78 | | − | { label: "Secret scanning", path: "security/secret-scanning", members: true, needs: "security_alerts" }, |
| 79 | | − | { label: "Code scanning", path: "security/code-scanning", members: true, needs: "security_alerts", also: ["security/pulls"] }, |
| 80 | | − | { label: "Vulnerabilities", path: "security/vulnerabilities", members: true, needs: "security_alerts" }, |
| 81 | | − | { label: "Dependency graph", path: "security/dependency-graph", members: true, needs: "security_alerts" }, |
| 82 | | − | { label: "Dependency updates", path: "security/dependency-updates", members: true, needs: "security_alerts" }, |
| 83 | | − | { label: "Advisories", path: "security/advisories", members: true, needs: "security_alerts", also: ["security/reports"] }, |
| 84 | | − | { label: "Settings", path: "security/settings", members: true, needs: "security_alerts" }, |
| 85 | | − | ...soon("Security"), |
| 86 | | − | ], |
| 87 | | − | }, |
| 88 | | − | { |
| 89 | | − | key: "Insights", |
| 90 | | − | tabs: [ |
| 91 | | − | { label: "Contributors", path: "contributors" }, |
| 92 | | − | { label: "Activity", path: "activity" }, |
| 93 | | − | { label: "Stargazers", path: "stargazers" }, |
| 94 | | − | ...soon("Insights"), |
| 95 | | − | ], |
| 96 | | − | }, |
| 97 | | − | ]; |
| 36 | + | /** |
| 37 | + | * The project's pages, built on first use rather than when the module |
| 38 | + | * loads: the soon tabs read the roadmap, and a bundle that splits the two |
| 39 | + | * into chunks that import each other could otherwise read it before it is |
| 40 | + | * there (a page that throws as it loads, so nothing on it works). |
| 41 | + | */ |
| 42 | + | let built: Section[] | null = null; |
| 43 | + | export function sections(): Section[] { |
| 44 | + | return (built ??= [ |
| 45 | + | { |
| 46 | + | key: "Code", |
| 47 | + | tabs: [ |
| 48 | + | { label: "Files", path: "code", also: ["tree", "blob"] }, |
| 49 | + | { label: "Commits", path: "commits", also: ["commit"] }, |
| 50 | + | { label: "Branches", path: "branches" }, |
| 51 | + | { label: "Tags", path: "tags" }, |
| 52 | + | { label: "Releases", path: "releases" }, |
| 53 | + | { label: "Compare", path: "compare" }, |
| 54 | + | // No Docs tab: code is not docs. Docs is a workspace mode, filtered by project there. |
| 55 | + | ], |
| 56 | + | }, |
| 57 | + | { |
| 58 | + | key: "Issues", |
| 59 | + | tabs: [ |
| 60 | + | { label: "Issues", path: "issues" }, |
| 61 | + | { label: "Milestones", path: "milestones" }, |
| 62 | + | ...soon("Issues"), |
| 63 | + | ], |
| 64 | + | }, |
| 65 | + | { |
| 66 | + | key: "Deployments", |
| 67 | + | tabs: [{ label: "Deployments", path: "deployments" }, ...soon("Deployments")], |
| 68 | + | }, |
| 69 | + | { |
| 70 | + | key: "Observability", |
| 71 | + | tabs: [ |
| 72 | + | { label: "Overview", path: "observability", exact: true, members: true }, |
| 73 | + | { label: "Requests", path: "observability/requests", members: true }, |
| 74 | + | { label: "Logs", path: "observability/logs", members: true }, |
| 75 | + | { label: "Traces", path: "observability/traces", members: true }, |
| 76 | + | { label: "Errors", path: "observability/errors", members: true }, |
| 77 | + | { label: "Metrics", path: "observability/metrics", members: true }, |
| 78 | + | { label: "Settings", path: "observability/settings", members: true, needs: "manage_integrations" }, |
| 79 | + | ...soon("Observability"), |
| 80 | + | ], |
| 81 | + | }, |
| 82 | + | { |
| 83 | + | key: "Security", |
| 84 | + | tabs: [ |
| 85 | + | { label: "Overview", path: "security", members: true, needs: "security_alerts", exact: true }, |
| 86 | + | { label: "Secret scanning", path: "security/secret-scanning", members: true, needs: "security_alerts" }, |
| 87 | + | { label: "Code scanning", path: "security/code-scanning", members: true, needs: "security_alerts", also: ["security/pulls"] }, |
| 88 | + | { label: "Vulnerabilities", path: "security/vulnerabilities", members: true, needs: "security_alerts" }, |
| 89 | + | { label: "Dependency graph", path: "security/dependency-graph", members: true, needs: "security_alerts" }, |
| 90 | + | { label: "Dependency updates", path: "security/dependency-updates", members: true, needs: "security_alerts" }, |
| 91 | + | { label: "Advisories", path: "security/advisories", members: true, needs: "security_alerts", also: ["security/reports"] }, |
| 92 | + | { label: "Settings", path: "security/settings", members: true, needs: "security_alerts" }, |
| 93 | + | ...soon("Security"), |
| 94 | + | ], |
| 95 | + | }, |
| 96 | + | { |
| 97 | + | key: "Insights", |
| 98 | + | tabs: [ |
| 99 | + | { label: "Contributors", path: "contributors" }, |
| 100 | + | { label: "Activity", path: "activity" }, |
| 101 | + | { label: "Stargazers", path: "stargazers" }, |
| 102 | + | ...soon("Insights"), |
| 103 | + | ], |
| 104 | + | }, |
| 105 | + | ]); |
| 106 | + | } |
| 98 | 107 | | |
| 99 | 108 | | /** Pull requests, the work on them, the merge queue and sessions share a page's tabs too. */ |
| 100 | 109 | | export const PULLS: Section = { |
| ⋯ |
| 116 | 125 | | * belongs to a page with more than one view. |
| 117 | 126 | | */ |
| 118 | 127 | | export function tabsFor(rest: string, member: boolean, can?: Partial<Abilities>, features?: { issues?: boolean }): Tab[] | null { |
| 119 | | − | for (const section of [...SECTIONS, PULLS]) { |
| 128 | + | for (const section of [...sections(), PULLS]) { |
| 120 | 129 | | // Issues turned off (a fork's default): no Issues tabs, though what was opened stays readable. |
| 121 | 130 | | if (section.key === "Issues" && features?.issues === false) continue; |
| 122 | 131 | | const visible = section.tabs.filter( |
| ⋯ |
| 129 | 138 | | |
| 130 | 139 | | /** The first page of a section, for its sidebar link: a built one if any. */ |
| 131 | 140 | | export function entryOf(key: Section["key"]): Tab | undefined { |
| 132 | | − | return SECTIONS.find((section) => section.key === key)?.tabs[0]; |
| 141 | + | return sections().find((section) => section.key === key)?.tabs[0]; |
| 133 | 142 | | } |