six-degrees 0.4.10 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +1 -0
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/prerender-manifest.json +9 -9
- package/.next/standalone/.next/routes-manifest.json +6 -0
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +13 -13
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +12 -12
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/admin-delete/route.js +1 -1
- package/.next/standalone/.next/server/app/api/admin-delete/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/admin-update/route.js +1 -1
- package/.next/standalone/.next/server/app/api/admin-update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bridges/route.js +1 -1
- package/.next/standalone/.next/server/app/api/bridges/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/bulk-import/route.js +1 -1
- package/.next/standalone/.next/server/app/api/bulk-import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/legacy/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/route.js +1 -1
- package/.next/standalone/.next/server/app/api/company-scores/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/connections/route.js +1 -1
- package/.next/standalone/.next/server/app/api/connections/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/export/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/restart/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js +1 -1
- package/.next/standalone/.next/server/app/api/delete-cluster/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/ingest/route.js +1 -1
- package/.next/standalone/.next/server/app/api/ingest/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/network/route.js +1 -1
- package/.next/standalone/.next/server/app/api/network/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/outreach/route.js +1 -1
- package/.next/standalone/.next/server/app/api/outreach/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/queue/route.js +1 -1
- package/.next/standalone/.next/server/app/api/queue/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/scraper/route.js +3 -2
- package/.next/standalone/.next/server/app/api/scraper/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/route.js +1 -1
- package/.next/standalone/.next/server/app/api/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-preview/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/settings/sector-suggestions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/setup-profile/route.js +1 -1
- package/.next/standalone/.next/server/app/api/setup-profile/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/crm/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/social/crm/route/build-manifest.json +12 -0
- package/.next/standalone/.next/server/app/api/social/crm/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/social/crm/route.js +10 -0
- package/.next/standalone/.next/server/app/api/social/crm/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/social/crm/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/social/crm/route_client-reference-manifest.js +3 -0
- package/.next/standalone/.next/server/app/api/social/messages/route.js +4 -3
- package/.next/standalone/.next/server/app/api/social/messages/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/social/route.js +4 -3
- package/.next/standalone/.next/server/app/api/social/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/unlock/route.js +1 -1
- package/.next/standalone/.next/server/app/api/unlock/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/update-images/route.js +1 -1
- package/.next/standalone/.next/server/app/api/update-images/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/users/route.js +1 -1
- package/.next/standalone/.next/server/app/api/users/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/avatars/[file]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/import/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/import.html +1 -1
- package/.next/standalone/.next/server/app/import.rsc +15 -15
- package/.next/standalone/.next/server/app/import.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/import.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/import.segments/import/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/launch/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/launch/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/launch.html +2 -2
- package/.next/standalone/.next/server/app/launch.rsc +15 -15
- package/.next/standalone/.next/server/app/launch.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/launch.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/launch.segments/launch/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/paths/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/paths.html +1 -1
- package/.next/standalone/.next/server/app/paths.rsc +15 -15
- package/.next/standalone/.next/server/app/paths.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/paths.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/paths.segments/paths/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/profile/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/profile/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/profile.html +1 -1
- package/.next/standalone/.next/server/app/profile.rsc +15 -15
- package/.next/standalone/.next/server/app/profile.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/profile.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/profile.segments/profile/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/queue/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/queue/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/queue.html +1 -1
- package/.next/standalone/.next/server/app/queue.rsc +15 -15
- package/.next/standalone/.next/server/app/queue.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/queue.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/queue.segments/queue/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/scores/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/scores/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/scores.html +1 -1
- package/.next/standalone/.next/server/app/scores.rsc +15 -15
- package/.next/standalone/.next/server/app/scores.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/scores.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/scores.segments/scores/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings.html +1 -1
- package/.next/standalone/.next/server/app/settings.rsc +15 -15
- package/.next/standalone/.next/server/app/settings.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/setup/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/setup/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/setup.html +1 -1
- package/.next/standalone/.next/server/app/setup.rsc +15 -15
- package/.next/standalone/.next/server/app/setup.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/setup.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/setup.segments/setup/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/social/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/social/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/social.html +1 -1
- package/.next/standalone/.next/server/app/social.rsc +15 -15
- package/.next/standalone/.next/server/app/social.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/social.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/social.segments/social/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app-paths-manifest.json +1 -0
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__0bat8nx._.js → [root-of-the-server]__05_3-22._.js} +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0t3v1a1._.js +1 -1
- package/.next/standalone/.next/server/chunks/{[root-of-the-server]__06mi9k2._.js → [root-of-the-server]__13dx4sd._.js} +7 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__15wc9e-._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1kbl21f._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1tir0vc._.js +8 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20rwfdw._.js +8 -0
- package/.next/standalone/.next/server/chunks/_072jl0y._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0ea9qwy._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1_fynia._.js +7 -7
- package/.next/standalone/.next/server/chunks/_1itd1o_._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1iwkh8t._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1oqfuh8._.js +3 -0
- package/.next/standalone/.next/server/chunks/_1xh07bp._.js +1 -1
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_social_crm_route_actions_0d1aflv.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_0851sk0._.js +8 -0
- package/.next/standalone/.next/server/chunks/lib_1q7p2ro._.js +8 -0
- package/.next/standalone/.next/server/chunks/lib_1r6l86l._.js +8 -0
- package/.next/standalone/.next/server/chunks/lib_db-client_15le7cw.js +8 -8
- package/.next/standalone/.next/server/chunks/lib_linkedin-export_12imqxg.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_04s8mzr.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_053z7as.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0b_-2te.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0dhbxdm.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0dxlk31.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0f8b-qc.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0pzie7_.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0r76fq_.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_0ut7pjp.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_15zyqaz.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_18zpjtq.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1a8xkiz.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1e_55xo.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1oxfd1_.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_rpc_1s0lod0.js +3 -0
- package/.next/standalone/.next/server/chunks/lib_scoring_1-e4ur0.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_01kacen._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_03l7vge._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/{_1ap1tu_._.js → _0gtv9jb._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_0jdkqgi._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0xi-fbs._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0xmwmfv._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1-b9hj7._.js +9 -0
- package/.next/standalone/.next/server/chunks/ssr/_112ewem._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_16ab63q._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1fxm0-s._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_1ra1d3r._.js +9 -0
- package/.next/standalone/.next/server/chunks/ssr/app_141w189._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_page_1fazqbf.js +22 -10
- package/.next/standalone/.next/server/chunks/ssr/app_paths_page_1ol90m7.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_profile_page_0u3-l5y.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_queue_page_0c6znd6.js +6 -5
- package/.next/standalone/.next/server/chunks/ssr/app_settings_page_1f8mjj_.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_setup_page_1-282zx.js +19 -3
- package/.next/standalone/.next/server/chunks/ssr/app_social_page_0h7zxda.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_0i8v-s3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/lib_13rapwj._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/lib_galaxy-lab_108_lu-.js +3 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/03bziijw5srol.js +1 -0
- package/.next/standalone/.next/static/chunks/0bgq8wmopl_ig.js +7 -0
- package/.next/standalone/.next/static/chunks/0ezus6p2eb-vg.js +1 -0
- package/.next/standalone/.next/static/chunks/0g_fy2034bp0x.js +34 -0
- package/.next/standalone/.next/static/chunks/0q5dru4q6gxl5.js +22 -0
- package/.next/standalone/.next/static/chunks/0w-byiwb2zax8.js +2 -0
- package/.next/standalone/.next/static/chunks/1g7jcovdejc9-.js +1 -0
- package/.next/standalone/.next/static/chunks/1i51yylxdzht1.js +1 -0
- package/.next/{static/chunks/1xptlvtcz6654.css → standalone/.next/static/chunks/1x_ysly42-teq.css} +1 -1
- package/.next/standalone/.next/static/chunks/1zf8swaasjf1e.js +43 -0
- package/.next/standalone/.next/static/chunks/2rqtpccruavf2.js +1 -0
- package/.next/standalone/.next/static/chunks/2wgz9ietkqqe6.js +1 -0
- package/.next/standalone/.next/static/chunks/30x3oq_st7a5r.js +1 -0
- package/.next/standalone/.next/static/chunks/355ryio1b7sm1.js +1 -0
- package/.next/standalone/.next/static/chunks/3ap5hgma7n0o7.js +1 -0
- package/.next/standalone/.next/static/chunks/3fci6qi39-1n5.js +1 -0
- package/.next/standalone/.next/static/chunks/{24tvdun1cb3g1.js → 3sowbvbaj1s6n.js} +1 -1
- package/.next/standalone/CHANGELOG.md +235 -0
- package/.next/standalone/app/api/data/export/route.js +2 -1
- package/.next/standalone/app/api/ingest/route.js +40 -1
- package/.next/standalone/app/api/scraper/route.js +12 -2
- package/.next/standalone/app/api/settings/sector-preview/route.js +2 -1
- package/.next/standalone/app/api/social/crm/route.js +37 -0
- package/.next/standalone/app/api/social/messages/route.js +44 -8
- package/.next/standalone/app/api/social/route.js +80 -22
- package/.next/standalone/app/components/AppTabs.js +59 -0
- package/.next/standalone/app/components/ChainView.js +303 -89
- package/.next/standalone/app/components/CirclePanel.js +162 -0
- package/.next/standalone/app/components/CompanyScores.js +2 -2
- package/.next/standalone/app/components/FieldStep.js +4 -4
- package/.next/standalone/app/components/FilterPanel.js +121 -183
- package/.next/standalone/app/components/ForceGraph.js +41 -3
- package/.next/standalone/app/components/GalaxyLab.js +26 -31
- package/.next/standalone/app/components/LegacyScoresCard.js +2 -2
- package/.next/standalone/app/components/MapControls.js +154 -0
- package/.next/standalone/app/components/NoteDetail.js +118 -0
- package/.next/standalone/app/components/PathsAnalyzer.js +147 -110
- package/.next/standalone/app/components/PeopleMap.js +308 -0
- package/.next/standalone/app/components/ScanRadar.js +129 -0
- package/.next/standalone/app/components/ScanStatusBar.js +72 -27
- package/.next/standalone/app/components/SeparationView.js +626 -118
- package/.next/standalone/app/components/Sidebar.js +28 -2
- package/.next/standalone/app/components/settings/DataSection.js +12 -3
- package/.next/standalone/app/components/settings/NetworkHealthSection.js +1 -1
- package/.next/standalone/app/components/settings/SectorSection.js +2 -2
- package/.next/standalone/app/components/settings/TierSection.js +1 -1
- package/.next/standalone/app/components/settings/TitleSection.js +149 -0
- package/.next/standalone/app/components/views.js +15 -14
- package/.next/standalone/app/globals.css +11 -0
- package/.next/standalone/app/page.js +89 -156
- package/.next/standalone/app/paths/page.js +39 -27
- package/.next/standalone/app/profile/page.js +33 -5
- package/.next/standalone/app/queue/page.js +56 -34
- package/.next/standalone/app/scores/page.js +16 -66
- package/.next/standalone/app/settings/page.js +27 -13
- package/.next/standalone/app/setup/page.js +298 -205
- package/.next/standalone/app/social/Crm.js +683 -0
- package/.next/standalone/app/social/SocialHub.js +374 -0
- package/.next/standalone/app/social/Thread.js +90 -0
- package/.next/standalone/app/social/page.js +10 -351
- package/.next/standalone/lib/chain-layout.js +105 -35
- package/.next/standalone/lib/data-export.js +10 -4
- package/.next/standalone/lib/data-folder.js +9 -0
- package/.next/standalone/lib/data-import.js +13 -3
- package/.next/standalone/lib/degrees.js +0 -6
- package/.next/standalone/lib/dot-rings.js +25 -0
- package/.next/standalone/lib/galaxy-lab.js +65 -6
- package/.next/standalone/lib/ingest.js +2 -0
- package/.next/standalone/lib/island.js +40 -0
- package/.next/standalone/lib/linkedin-export.js +267 -46
- package/.next/standalone/lib/linkedin-limits.js +6 -2
- package/.next/standalone/lib/map-heat.js +20 -0
- package/.next/standalone/lib/network-health.js +1 -1
- package/.next/standalone/lib/notifications.js +121 -0
- package/.next/standalone/lib/people-map.js +82 -0
- package/.next/standalone/lib/rarity.js +45 -3
- package/.next/standalone/lib/reach.js +7 -6
- package/.next/standalone/lib/rpc.js +15 -4
- package/.next/standalone/lib/scan-pace.js +46 -0
- package/.next/standalone/lib/scoring.js +39 -8
- package/.next/standalone/lib/scraper-client.js +19 -6
- package/.next/standalone/lib/sector-focus.js +4 -4
- package/.next/standalone/lib/separation.js +137 -10
- package/.next/standalone/lib/settings-effects.js +20 -11
- package/.next/standalone/lib/settings.js +3 -0
- package/.next/standalone/lib/social-crm.js +415 -0
- package/.next/standalone/lib/social-store.js +13 -6
- package/.next/standalone/lib/tier-grid.js +99 -0
- package/.next/standalone/lib/title-ranking.js +83 -0
- package/.next/standalone/package-lock.json +2 -2
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/scripts/scrape.py +177 -35
- package/.next/static/chunks/03bziijw5srol.js +1 -0
- package/.next/static/chunks/0bgq8wmopl_ig.js +7 -0
- package/.next/static/chunks/0ezus6p2eb-vg.js +1 -0
- package/.next/static/chunks/0g_fy2034bp0x.js +34 -0
- package/.next/static/chunks/0q5dru4q6gxl5.js +22 -0
- package/.next/static/chunks/0w-byiwb2zax8.js +2 -0
- package/.next/static/chunks/1g7jcovdejc9-.js +1 -0
- package/.next/static/chunks/1i51yylxdzht1.js +1 -0
- package/.next/{standalone/.next/static/chunks/1xptlvtcz6654.css → static/chunks/1x_ysly42-teq.css} +1 -1
- package/.next/static/chunks/1zf8swaasjf1e.js +43 -0
- package/.next/static/chunks/2rqtpccruavf2.js +1 -0
- package/.next/static/chunks/2wgz9ietkqqe6.js +1 -0
- package/.next/static/chunks/30x3oq_st7a5r.js +1 -0
- package/.next/static/chunks/355ryio1b7sm1.js +1 -0
- package/.next/static/chunks/3ap5hgma7n0o7.js +1 -0
- package/.next/static/chunks/3fci6qi39-1n5.js +1 -0
- package/.next/static/chunks/{24tvdun1cb3g1.js → 3sowbvbaj1s6n.js} +1 -1
- package/CHANGELOG.md +235 -0
- package/lib/chain-layout.js +105 -35
- package/lib/data-export.js +10 -4
- package/lib/data-folder.js +9 -0
- package/lib/data-import.js +13 -3
- package/lib/degrees.js +0 -6
- package/lib/dot-rings.js +25 -0
- package/lib/galaxy-lab.js +65 -6
- package/lib/ingest.js +2 -0
- package/lib/island.js +40 -0
- package/lib/linkedin-export.js +267 -46
- package/lib/linkedin-limits.js +6 -2
- package/lib/map-heat.js +20 -0
- package/lib/network-health.js +1 -1
- package/lib/notifications.js +121 -0
- package/lib/people-map.js +82 -0
- package/lib/rarity.js +45 -3
- package/lib/reach.js +7 -6
- package/lib/rpc.js +15 -4
- package/lib/scan-pace.js +46 -0
- package/lib/scoring.js +39 -8
- package/lib/scraper-client.js +19 -6
- package/lib/sector-focus.js +4 -4
- package/lib/separation.js +137 -10
- package/lib/settings-effects.js +20 -11
- package/lib/settings.js +3 -0
- package/lib/social-crm.js +415 -0
- package/lib/social-store.js +13 -6
- package/lib/tier-grid.js +99 -0
- package/lib/title-ranking.js +83 -0
- package/package.json +1 -1
- package/scripts/scrape.py +177 -35
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08f5awg._.js +0 -8
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__17hjtzl._.js +0 -8
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__20tmem7._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_18cr1gi._.js +0 -8
- package/.next/standalone/.next/server/chunks/lib_rpc_03i8xef.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_08fc3rp.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_08r2t_q.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0btpv1t.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0c9d9ti.js +0 -8
- package/.next/standalone/.next/server/chunks/lib_rpc_0cm2ev3.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0iovswz.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0is8flp.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0v8ajtd.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_0xgmvvt.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_144mzbf.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1bggi0n.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1dkcu9f.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_rpc_1o0jb6w.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0c_y09g._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0ezj4e0._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0j4-lc3._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0l8cxmo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_0xkur4p._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_14iv_zy._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_15x6q32._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1errbuf._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_212xw8q._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_components_19c2d9c._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/app_scores_page_09wepvv.js +0 -3
- package/.next/standalone/.next/static/chunks/07dyt47mp4s9-.js +0 -1
- package/.next/standalone/.next/static/chunks/0a5iadnmt9u9k.js +0 -1
- package/.next/standalone/.next/static/chunks/160wjb73ddwqd.js +0 -6
- package/.next/standalone/.next/static/chunks/1c_n0973t07l0.js +0 -2
- package/.next/standalone/.next/static/chunks/1e1n0kkz-psdb.js +0 -1
- package/.next/standalone/.next/static/chunks/206rm6j42gl_a.js +0 -1
- package/.next/standalone/.next/static/chunks/236f0jtp68j_h.js +0 -1
- package/.next/standalone/.next/static/chunks/2coxzjm_k6ilr.js +0 -1
- package/.next/standalone/.next/static/chunks/2kfhc58df2xyo.js +0 -1
- package/.next/standalone/.next/static/chunks/2pw6_osz1n_te.js +0 -1
- package/.next/standalone/.next/static/chunks/39hr8d-b2ibtw.js +0 -31
- package/.next/standalone/.next/static/chunks/3zw8bv7-mc4n6.js +0 -33
- package/.next/standalone/app/components/OrbitGraph.js +0 -737
- package/.next/standalone/app/social/Conversations.js +0 -246
- package/.next/static/chunks/07dyt47mp4s9-.js +0 -1
- package/.next/static/chunks/0a5iadnmt9u9k.js +0 -1
- package/.next/static/chunks/160wjb73ddwqd.js +0 -6
- package/.next/static/chunks/1c_n0973t07l0.js +0 -2
- package/.next/static/chunks/1e1n0kkz-psdb.js +0 -1
- package/.next/static/chunks/206rm6j42gl_a.js +0 -1
- package/.next/static/chunks/236f0jtp68j_h.js +0 -1
- package/.next/static/chunks/2coxzjm_k6ilr.js +0 -1
- package/.next/static/chunks/2kfhc58df2xyo.js +0 -1
- package/.next/static/chunks/2pw6_osz1n_te.js +0 -1
- package/.next/static/chunks/39hr8d-b2ibtw.js +0 -31
- package/.next/static/chunks/3zw8bv7-mc4n6.js +0 -33
- /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_ssgManifest.js +0 -0
- /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_buildManifest.js +0 -0
- /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_clientMiddlewareManifest.js +0 -0
- /package/.next/static/{7zWJnSkfSoRhRsqY6ZKtD → I-cj79yE2IZ8taX2dZGp3}/_ssgManifest.js +0 -0
|
@@ -14,9 +14,11 @@ import { reachIndex, reachState, circleState, readyToScan, circleScanCost } from
|
|
|
14
14
|
import { exclusiveReach, bridgeOverlap } from '../../lib/brokerage';
|
|
15
15
|
import { profileInsights } from '../../lib/insights';
|
|
16
16
|
import Avatar from './Avatar';
|
|
17
|
+
import NoteDetail from './NoteDetail';
|
|
18
|
+
import CirclePanel from './CirclePanel';
|
|
17
19
|
import { localPhoto } from '../../lib/photos';
|
|
18
20
|
|
|
19
|
-
export default function Sidebar({ selected, stats, tierColors, connections, degree2 = [], mode, collapsed, filter, pending = [], onToggle, onSelect, onSwitchMode, onFocusNode, onMarkSent, onUndoPending, scanNotes, csvSource = null, onOpenCircle, onShowInSeparation }) {
|
|
21
|
+
export default function Sidebar({ selected, stats, tierColors, connections, degree2 = [], mode, collapsed, filter, pending = [], onToggle, onSelect, onSwitchMode, onFocusNode, onMarkSent, onUndoPending, scanNotes, csvSource = null, onOpenCircle, onShowInSeparation, note = null, onCloseNote, circle = null }) {
|
|
20
22
|
const isDegreesMode = mode === 'degrees';
|
|
21
23
|
// 'sample' or 'csv' while the sample or a CSV import is open in this window,
|
|
22
24
|
// null for your own network. Only your own can be scanned: the scanner looks
|
|
@@ -53,6 +55,18 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
|
|
|
53
55
|
const requests = useRequests();
|
|
54
56
|
const isRequested = useCallback((row) => hasRequest(row, requests), [requests]);
|
|
55
57
|
|
|
58
|
+
// A notification someone clicked takes the panel over until they go back (app/components/NoteDetail.js).
|
|
59
|
+
if (note) {
|
|
60
|
+
return (
|
|
61
|
+
<SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
|
|
62
|
+
<NoteDetail note={note} connections={connections} degree2={degree2} onBack={onCloseNote}
|
|
63
|
+
onSelect={(p) => { onCloseNote?.(); onSelect?.(p); }}
|
|
64
|
+
onOpenCircle={onOpenCircle ? (id) => { onCloseNote?.(); onOpenCircle(id); } : undefined}
|
|
65
|
+
onShowInSeparation={onShowInSeparation ? (preset) => { onCloseNote?.(); onShowInSeparation(preset); } : undefined} />
|
|
66
|
+
</SidebarWrapper>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
56
70
|
if (selected) {
|
|
57
71
|
const isBridge = selected.degree === 1 && bridgeMap[selected.id];
|
|
58
72
|
const bridgeConnections = bridgeMap[selected.id] || [];
|
|
@@ -494,6 +508,16 @@ export default function Sidebar({ selected, stats, tierColors, connections, degr
|
|
|
494
508
|
);
|
|
495
509
|
}
|
|
496
510
|
|
|
511
|
+
// A circle open in Bridge Chains: the panel is about whoever's circle you're in.
|
|
512
|
+
if (isDegreesMode && circle) {
|
|
513
|
+
return (
|
|
514
|
+
<SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
|
|
515
|
+
<CirclePanel key={circle.id} person={circle} connections={connections} degree2={degree2} scanNotes={scanNotes}
|
|
516
|
+
tierColors={tierColors} onSelect={onSelect} onToggle={onToggle} canScan={canScan} />
|
|
517
|
+
</SidebarWrapper>
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
|
|
497
521
|
if (isDegreesMode) {
|
|
498
522
|
return (
|
|
499
523
|
<SidebarWrapper collapsed={collapsed} onToggle={onToggle}>
|
|
@@ -1202,7 +1226,9 @@ function ScanLog({ title, log, small = false }) {
|
|
|
1202
1226
|
padding: '10px', borderRadius: 8, background: 'rgba(155,89,182,0.1)', border: '1px solid rgba(155,89,182,0.3)',
|
|
1203
1227
|
}}>
|
|
1204
1228
|
<div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 4 }}>
|
|
1205
|
-
|
|
1229
|
+
{/* Its own keyframes: the 'pulse' this named was never defined anywhere, so the dot sat still. */}
|
|
1230
|
+
<style>{'@keyframes scanlogPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .35; transform: scale(.7); } } @media (prefers-reduced-motion: reduce) { .scanlog-dot { animation: none !important; } }'}</style>
|
|
1231
|
+
<div className="scanlog-dot" style={{ width: small ? 6 : 8, height: small ? 6 : 8, borderRadius: '50%', background: '#9B59B6', animation: 'scanlogPulse 1s ease-in-out infinite' }} />
|
|
1206
1232
|
<span style={{ fontSize: 11, fontWeight: 600, color: '#9B59B6' }}>{title}</span>
|
|
1207
1233
|
</div>
|
|
1208
1234
|
<div style={{ fontFamily: 'monospace', fontSize: small ? 9 : 10, color: '#888', maxHeight: small ? 80 : 100, overflow: 'auto' }}>
|
|
@@ -79,6 +79,7 @@ export default function DataSection() {
|
|
|
79
79
|
const [exportNote, setExportNote] = useState(null);
|
|
80
80
|
const [importNote, setImportNote] = useState(null);
|
|
81
81
|
const [photos, setPhotos] = useState(true);
|
|
82
|
+
const [social, setSocial] = useState(true);
|
|
82
83
|
const [file, setFile] = useState(null);
|
|
83
84
|
const [confirmed, setConfirmed] = useState(false);
|
|
84
85
|
const [restarting, setRestarting] = useState(false);
|
|
@@ -137,7 +138,7 @@ export default function DataSection() {
|
|
|
137
138
|
const res = await fetch('/api/data/export', {
|
|
138
139
|
method: 'POST',
|
|
139
140
|
headers: { 'Content-Type': 'application/json' },
|
|
140
|
-
body: JSON.stringify({ photos }),
|
|
141
|
+
body: JSON.stringify({ photos, social }),
|
|
141
142
|
});
|
|
142
143
|
if (!res.ok) await answer(res, 'The copy could not be made.');
|
|
143
144
|
const blob = await res.blob();
|
|
@@ -324,6 +325,13 @@ export default function DataSection() {
|
|
|
324
325
|
They can’t be downloaded again without a new scan.
|
|
325
326
|
</span>
|
|
326
327
|
</label>
|
|
328
|
+
<label style={check}>
|
|
329
|
+
<input type="checkbox" checked={social} onChange={(e) => setSocial(e.target.checked)} style={{ marginTop: 3 }} />
|
|
330
|
+
<span>
|
|
331
|
+
Include the Social tab: its findings, your CRM notes, stages and follow-ups, and any messages you keep
|
|
332
|
+
there.
|
|
333
|
+
</span>
|
|
334
|
+
</label>
|
|
327
335
|
<div style={row}>
|
|
328
336
|
<Btn primary onClick={exportNow} disabled={!!busy || restarting || info.people === 0}>
|
|
329
337
|
{busy === 'export' ? 'Saving…' : 'Save a copy of my network'}
|
|
@@ -334,8 +342,9 @@ export default function DataSection() {
|
|
|
334
342
|
<Body style={small}>
|
|
335
343
|
The copy holds the names, headlines and photos of the people in your network. Keep it private: don’t
|
|
336
344
|
post it or share it, and delete it once it has been imported. A network opened from a LinkedIn CSV lives
|
|
337
|
-
only in its browser tab, so it isn’t in the copy; import the CSV again on the new computer.
|
|
338
|
-
tab
|
|
345
|
+
only in its browser tab, so it isn’t in the copy; import the CSV again on the new computer. With the
|
|
346
|
+
Social tab included, the copy also holds your CRM notes and any messages you keep, so it’s as private
|
|
347
|
+
as your inbox.
|
|
339
348
|
</Body>
|
|
340
349
|
|
|
341
350
|
<h3 style={subhead}>Bring in a network from another computer</h3>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
// Network health
|
|
3
|
+
// Network health, in Profile → Insights (lib/network-health.js; it was on the Scores tab): how much of your
|
|
4
4
|
// 2nd degree you reach two or more ways, the effective size of your own
|
|
5
5
|
// network from the ties scans have kept, and your top five connections by who
|
|
6
6
|
// only they reach. Only your own numbers, never a percentile against others.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
// Scores → Your
|
|
3
|
+
// Settings → Scores → Your field (app/settings; it was a Scores tab of its own from 9/28 to 10/2). Up to three sectors you work in: one of the twelve
|
|
4
4
|
// broad industries, or a narrower sector from the app's directory (Dental,
|
|
5
5
|
// Real Estate, Software & SaaS…). Companies in them count for more when your
|
|
6
6
|
// scanned network is scored, like setting their scores by hand on Paths →
|
|
@@ -78,7 +78,7 @@ export default function SectorSection({ onSaved } = {}) {
|
|
|
78
78
|
return () => { off = true; clearTimeout(timer.current); };
|
|
79
79
|
}, []);
|
|
80
80
|
|
|
81
|
-
// Links to /
|
|
81
|
+
// Links to /settings#sector (the profile's card, the old /scores#sector) arrive
|
|
82
82
|
// before this section has loaded, so the browser's own jump to it finds
|
|
83
83
|
// nothing. Jump once it's here, then keep it in place while what loads above
|
|
84
84
|
// it (Updates) pushes it down: the browser only holds steady what's already
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
// Scores → Tiers (app/
|
|
3
|
+
// Settings → Scores → Tiers (app/settings; it was a Scores tab of its own from 9/28 to 10/2). How the S to D rings are drawn: on your network's curve
|
|
4
4
|
// (your top 3% are S, and so on down), or on the fixed scale, the same lines
|
|
5
5
|
// for everyone. The curve only lifts, so a network full of companies the
|
|
6
6
|
// curated list knows keeps its tiers. The model is lib/scoring.js (CURVE,
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// Settings → Scores → Titles (Blake, 2026-10-02): how much each kind of title
|
|
4
|
+
// counts, your way. Value founders, investors, or a role you're looking for
|
|
5
|
+
// (outbound, hiring: "find more in that role"), and everyone with it rises.
|
|
6
|
+
// Saving rescores everyone and says how many changed tier, as Tiers does.
|
|
7
|
+
// The setting and its presets are lib/title-ranking.js; scoring applies it
|
|
8
|
+
// (lib/scoring.js rankedPoints).
|
|
9
|
+
|
|
10
|
+
import { useEffect, useRef, useState } from 'react';
|
|
11
|
+
import { Section, Body, Status, Btn, LINE } from '../ui';
|
|
12
|
+
import { LEVELS } from '../../../lib/scoring';
|
|
13
|
+
import { RANKED_LEVELS, NO_RANKING, RANKING_PRESETS, MAX_ROLES, rankingFingerprint } from '../../../lib/title-ranking';
|
|
14
|
+
import { saveSettings } from '../../../lib/settings-client';
|
|
15
|
+
|
|
16
|
+
const POINTS = [10, 9.5, 9, 8.5, 8, 7.5, 7, 6.5, 6, 5.5, 5, 4.5, 4, 3, 2, 1, 0];
|
|
17
|
+
const plural = (n, one, many) => `${n.toLocaleString()} ${n === 1 ? one : many}`;
|
|
18
|
+
const select = {
|
|
19
|
+
padding: '5px 8px', borderRadius: 6, fontSize: 12.5, cursor: 'pointer',
|
|
20
|
+
border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default function TitleSection({ onSaved } = {}) {
|
|
24
|
+
const [saved, setSaved] = useState(null);
|
|
25
|
+
const [draft, setDraft] = useState(null);
|
|
26
|
+
const [role, setRole] = useState('');
|
|
27
|
+
const [rolePoints, setRolePoints] = useState(10);
|
|
28
|
+
const [saving, setSaving] = useState(false);
|
|
29
|
+
const [result, setResult] = useState(null);
|
|
30
|
+
const [loadError, setLoadError] = useState(null);
|
|
31
|
+
const roleBox = useRef(null);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
let off = false;
|
|
35
|
+
fetch('/api/settings')
|
|
36
|
+
.then((r) => r.json().then((d) => (r.ok ? d : Promise.reject(new Error(d.error || 'Could not load your title ranking.')))))
|
|
37
|
+
.then((d) => { if (!off) { const r = d.settings?.titleRanking || NO_RANKING; setSaved(r); setDraft(r); } })
|
|
38
|
+
.catch((e) => { if (!off) setLoadError(e.message); });
|
|
39
|
+
return () => { off = true; };
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
if (!draft) return loadError ? <Status tone="bad">{loadError}</Status> : null;
|
|
43
|
+
|
|
44
|
+
const pointsOf = (key) => draft.points?.[key] ?? LEVELS[key].points;
|
|
45
|
+
const setPoints = (key, v) => {
|
|
46
|
+
const points = { ...draft.points };
|
|
47
|
+
if (v === LEVELS[key].points) delete points[key]; else points[key] = v;
|
|
48
|
+
setDraft({ ...draft, points });
|
|
49
|
+
setResult(null);
|
|
50
|
+
};
|
|
51
|
+
const addRole = () => {
|
|
52
|
+
const text = role.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
53
|
+
if (text.length < 2) return;
|
|
54
|
+
const roles = [...draft.roles.filter((r) => r.text !== text), { text, points: rolePoints }];
|
|
55
|
+
setDraft({ ...draft, roles: roles.slice(-MAX_ROLES) });
|
|
56
|
+
setRole('');
|
|
57
|
+
setResult(null);
|
|
58
|
+
};
|
|
59
|
+
const dropRole = (text) => { setDraft({ ...draft, roles: draft.roles.filter((r) => r.text !== text) }); setResult(null); };
|
|
60
|
+
const preset = RANKING_PRESETS.find((p) => p.ranking && rankingFingerprint(p.ranking) === rankingFingerprint(draft))?.key ?? null;
|
|
61
|
+
const pick = (p) => {
|
|
62
|
+
setResult(null);
|
|
63
|
+
if (p.ranking) setDraft({ points: { ...p.ranking.points }, roles: [...p.ranking.roles] });
|
|
64
|
+
else roleBox.current?.focus();
|
|
65
|
+
};
|
|
66
|
+
const dirty = rankingFingerprint(draft) !== rankingFingerprint(saved);
|
|
67
|
+
|
|
68
|
+
async function save() {
|
|
69
|
+
setSaving(true);
|
|
70
|
+
setResult(null);
|
|
71
|
+
const { settings, effects, error } = await saveSettings({ titleRanking: draft });
|
|
72
|
+
if (settings) { setSaved(settings.titleRanking); setDraft(settings.titleRanking); }
|
|
73
|
+
if (error) setResult({ tone: 'bad', text: error });
|
|
74
|
+
else {
|
|
75
|
+
const e = effects?.titleRanking;
|
|
76
|
+
setResult({ tone: 'ok', text: e ? `Saved. ${plural(e.moved, 'person', 'people')} changed tier.` : 'Saved.' });
|
|
77
|
+
onSaved?.();
|
|
78
|
+
}
|
|
79
|
+
setSaving(false);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<Section id="titles" title="Titles" intro="How much each kind of title counts towards someone's power, out of 10. Change it if you value some people more than the app does: founders, investors, or a role you're looking for.">
|
|
84
|
+
{/* Starting points */}
|
|
85
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 6 }}>
|
|
86
|
+
{RANKING_PRESETS.map((p) => (
|
|
87
|
+
<button key={p.key} type="button" onClick={() => pick(p)} aria-pressed={preset === p.key} title={p.note} style={{
|
|
88
|
+
padding: '6px 12px', borderRadius: 16, fontSize: 12.5, fontWeight: 650, cursor: 'pointer',
|
|
89
|
+
border: preset === p.key ? '1px solid rgba(155,89,182,0.7)' : LINE,
|
|
90
|
+
background: preset === p.key ? 'rgba(155,89,182,0.16)' : 'rgba(255,255,255,0.03)', color: preset === p.key ? '#fff' : '#bbb',
|
|
91
|
+
}}>{p.label}</button>
|
|
92
|
+
))}
|
|
93
|
+
</div>
|
|
94
|
+
<Body style={{ marginBottom: 14 }}>
|
|
95
|
+
{RANKING_PRESETS.find((p) => p.key === preset)?.note || 'Your own ranking. Higher points rank higher; the company someone works at still weighs it.'}
|
|
96
|
+
</Body>
|
|
97
|
+
|
|
98
|
+
{/* The ladder */}
|
|
99
|
+
<div style={{ display: 'grid', gridTemplateColumns: '1fr auto auto', gap: '6px 12px', alignItems: 'center', maxWidth: 520 }}>
|
|
100
|
+
{RANKED_LEVELS.map((key) => {
|
|
101
|
+
const mine = draft.points?.[key] != null;
|
|
102
|
+
return [
|
|
103
|
+
<div key={`${key}-l`} style={{ fontSize: 13, color: mine ? '#fff' : '#ccc', fontWeight: mine ? 700 : 500 }}>{LEVELS[key].label}</div>,
|
|
104
|
+
<select key={`${key}-s`} aria-label={`Points for ${LEVELS[key].label}`} value={pointsOf(key)} onChange={(e) => setPoints(key, Number(e.target.value))}
|
|
105
|
+
style={{ ...select, borderColor: mine ? 'rgba(155,89,182,0.7)' : undefined }}>
|
|
106
|
+
{POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
|
|
107
|
+
</select>,
|
|
108
|
+
<div key={`${key}-d`} style={{ fontSize: 11, color: '#667', minWidth: 70 }}>
|
|
109
|
+
{mine ? <button type="button" onClick={() => setPoints(key, LEVELS[key].points)} style={{ background: 'none', border: 'none', color: '#9b9bd0', cursor: 'pointer', fontSize: 11, padding: 0 }}>back to {LEVELS[key].points}</button> : 'as it comes'}
|
|
110
|
+
</div>,
|
|
111
|
+
];
|
|
112
|
+
})}
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
{/* Roles you're looking for */}
|
|
116
|
+
<div style={{ marginTop: 18, fontSize: 13.5, fontWeight: 700, color: '#eee' }}>Roles you’re looking for</div>
|
|
117
|
+
<Body style={{ margin: '4px 0 10px' }}>
|
|
118
|
+
Anyone whose title has these words counts what you give them, whatever their level: for outbound to one role, or hiring for it. “Account executive” at 10 puts every account executive you can reach near the top.
|
|
119
|
+
</Body>
|
|
120
|
+
<form onSubmit={(e) => { e.preventDefault(); addRole(); }} style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
121
|
+
<input ref={roleBox} value={role} onChange={(e) => setRole(e.target.value)} placeholder="e.g. head of growth, recruiter, founder"
|
|
122
|
+
maxLength={60} style={{ flex: '1 1 220px', padding: '7px 10px', borderRadius: 6, fontSize: 13, border: LINE, background: 'rgba(0,0,0,0.3)', color: '#fff' }} />
|
|
123
|
+
<select aria-label="Points for this role" value={rolePoints} onChange={(e) => setRolePoints(Number(e.target.value))} style={select}>
|
|
124
|
+
{POINTS.map((p) => <option key={p} value={p}>{p}</option>)}
|
|
125
|
+
</select>
|
|
126
|
+
<Btn type="submit" disabled={role.trim().length < 2 || draft.roles.length >= MAX_ROLES}>Add</Btn>
|
|
127
|
+
</form>
|
|
128
|
+
{draft.roles.length > 0 && (
|
|
129
|
+
<div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 10 }}>
|
|
130
|
+
{draft.roles.map((r) => (
|
|
131
|
+
<span key={r.text} style={{
|
|
132
|
+
display: 'inline-flex', alignItems: 'center', gap: 6, padding: '4px 6px 4px 11px', borderRadius: 14, fontSize: 12.5,
|
|
133
|
+
border: '1px solid rgba(155,89,182,0.5)', background: 'rgba(155,89,182,0.12)', color: '#eee',
|
|
134
|
+
}}>
|
|
135
|
+
{r.text} <b style={{ color: '#d2b4ff' }}>{r.points}</b>
|
|
136
|
+
<button type="button" onClick={() => dropRole(r.text)} aria-label={`Remove ${r.text}`} style={{ background: 'none', border: 'none', color: '#aaa', cursor: 'pointer', fontSize: 13 }}>✕</button>
|
|
137
|
+
</span>
|
|
138
|
+
))}
|
|
139
|
+
</div>
|
|
140
|
+
)}
|
|
141
|
+
|
|
142
|
+
<div style={{ display: 'flex', gap: 10, alignItems: 'center', marginTop: 16 }}>
|
|
143
|
+
<Btn primary onClick={save} disabled={!dirty || saving}>{saving ? 'Rescoring…' : 'Save and rescore'}</Btn>
|
|
144
|
+
{dirty && <span style={{ fontSize: 12, color: '#999' }}>Not saved yet. Saving rescores everyone.</span>}
|
|
145
|
+
</div>
|
|
146
|
+
{result && <Status tone={result.tone}>{result.text}</Status>}
|
|
147
|
+
</Section>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
// the component and adding a row.
|
|
12
12
|
|
|
13
13
|
import ForceGraph from './ForceGraph';
|
|
14
|
-
import OrbitGraph from './OrbitGraph';
|
|
15
14
|
import ChainView from './ChainView';
|
|
16
15
|
import GridView from './GridView';
|
|
17
16
|
import ListView from './ListView';
|
|
@@ -19,30 +18,32 @@ import RingsView from './RingsView';
|
|
|
19
18
|
import SeparationView from './SeparationView';
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
|
-
* `modes` — which top-level
|
|
21
|
+
* `modes` — which top-level tab the view belongs in ('network', 'degrees', 'separation').
|
|
23
22
|
* `allDegree2` — give it every 2nd-degree row rather than the mode-filtered
|
|
24
|
-
* set.
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* set. No view wants it now (Orbit did, before it became a Galaxy layout);
|
|
24
|
+
* declared here rather than hidden in a branch, because an exception you
|
|
25
|
+
* cannot see is one you break later.
|
|
27
26
|
*/
|
|
28
27
|
export const VIEWS = {
|
|
29
28
|
galaxy: { component: ForceGraph, modes: ['network'], label: 'Galaxy', icon: '🌌', desc: 'Force-directed layout' },
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
29
|
+
// Orbit is a layout of the Galaxy now, in its Physics (Blake, 2026-10-02: "add that
|
|
30
|
+
// as a visual option instead so the person can interact with it"): lib/galaxy-lab.js ORBIT.
|
|
31
|
+
// Separation is a tab of its own (Blake, 2026-10-02), not a view inside Degrees.
|
|
32
|
+
separation: { component: SeparationView, modes: ['separation'], label: 'Separation', icon: '🏆', desc: 'Every 2nd degree, ranked · every way in' },
|
|
33
|
+
chain: { component: ChainView, modes: ['degrees'], label: 'Bridge Chains', icon: '🔗', desc: 'Your bridges, and the chains that lead on from them' },
|
|
34
|
+
// Pyramid and List left Network Circle (Blake, 2026-10-02: "the list and pyramid gone"): the
|
|
35
|
+
// Galaxy and its physics are what that tab is for. They stay in Degrees.
|
|
36
|
+
rings: { component: RingsView, modes: ['degrees'], label: 'Pyramid', icon: '🔺', desc: 'Tier hierarchy' },
|
|
37
|
+
list: { component: ListView, modes: ['degrees'], label: 'List', icon: '☰', desc: 'Ranked power list' },
|
|
35
38
|
grid: { component: GridView, modes: ['network', 'degrees'], label: 'Grid', icon: '▦', desc: 'Cards' },
|
|
36
39
|
};
|
|
37
40
|
|
|
38
41
|
/**
|
|
39
42
|
* The order they appear in the menu. Bridge Chains is the first Degrees view, so
|
|
40
43
|
* it is also where resolveView lands when the chosen view isn't a Degrees one
|
|
41
|
-
* (Galaxy, say, carried over from Network Circle); then Separation
|
|
42
|
-
* Orbit is a Degrees view only: in Network Circle it was slow and said nothing
|
|
43
|
-
* the Galaxy doesn't (OrbitGraph still has that branch until Orbit is redrawn).
|
|
44
|
+
* (Galaxy, say, carried over from Network Circle); then Separation.
|
|
44
45
|
*/
|
|
45
|
-
const ORDER = ['galaxy', 'chain', 'separation', '
|
|
46
|
+
const ORDER = ['galaxy', 'chain', 'separation', 'rings', 'list'];
|
|
46
47
|
|
|
47
48
|
export function viewsForMode(mode) {
|
|
48
49
|
return ORDER
|
|
@@ -46,3 +46,14 @@ html:has([data-field-question]) {
|
|
|
46
46
|
/* The notch's running dot (app/components/ScanStatusBar.js). */
|
|
47
47
|
@keyframes notch-pulse { 50% { opacity: 0.35; } }
|
|
48
48
|
@media (prefers-reduced-motion: no-preference) { .notch-pulse { animation: notch-pulse 1.6s ease-in-out infinite; } }
|
|
49
|
+
|
|
50
|
+
/* The Social tab's CRM (app/social/Crm.js): the list and the person side by
|
|
51
|
+
side, stacked on a phone. In Pipeline the board takes the whole width and
|
|
52
|
+
the person sits under it. */
|
|
53
|
+
.crm-grid { display: grid; grid-template-columns: minmax(280px, 400px) minmax(0, 1fr); gap: 10px; align-items: start; }
|
|
54
|
+
.crm-grid > .crm-wide { grid-column: 1 / -1; }
|
|
55
|
+
.crm-board { display: grid; grid-template-columns: repeat(6, minmax(150px, 1fr)); gap: 10px; padding: 10px; overflow-x: auto; }
|
|
56
|
+
@media (max-width: 760px) {
|
|
57
|
+
.crm-grid { grid-template-columns: minmax(0, 1fr); }
|
|
58
|
+
.crm-board { grid-template-columns: minmax(0, 1fr); }
|
|
59
|
+
}
|