1- import React , { useState , useEffect } from "react"
2- import { SubscribersOnlyModal } from "/src/components/SubscribersOnlyModal.tsx"
3-
4- const gruntworkGithubOrg = "https://github.com/gruntwork-io/"
1+ /**
2+ * This file is the mechanism for adding stateful logic to a docusaurus
3+ * application since the <Root> component is rendered at the very top of the
4+ * React tree and never unmounts.
5+ * We swizzle(customize) the Root component by creating this file: Root.js
6+ * https://docusaurus.io/docs/swizzling#wrapper-your-site-with-root
7+ */
58
6- const gruntworkCisRepoName = "terraform-aws-cis-service-catalog"
9+ import React , { useState , useEffect } from "react"
10+ import { getRepos } from "/utils"
11+ import {
12+ SubscribersOnlyModal ,
13+ repoNamePattern ,
14+ gruntworkGithubOrg ,
15+ } from "/src/components/SubscribersOnlyModal.tsx"
716
817const publicGruntworkRepoNames = [
918 "bash-commons" ,
@@ -53,29 +62,46 @@ const publicGruntworkRepoNames = [
5362 "website-comments" ,
5463]
5564
65+ const { awsCISRepos, enterpriseRepos } = getRepos ( )
66+
5667/**
57- * Checks if a link references a known public Gruntwork repo
68+ * Checks if a given list of repo names includes a repo name extracted from a given url that matches the repoNamePattern
5869 *
59- * @param string url
70+ * @param {string[] } repoNames
71+ * @param {string } url
6072 * @return {boolean }
6173 */
62- const isPublicGruntworkRepo = ( url ) => {
74+ const listIncludesRepo = ( repoNames , url ) => {
6375 if ( ! url ) {
6476 return false
6577 }
66- // Match a link prefixed by the gruntworkGithubOrg and capture the next path reference
67- const pattern = new RegExp ( `^${ gruntworkGithubOrg } (.*?)(\/|$)` )
68- // e.g for a given link https://github.com/gruntwork-io/docs/intro -> `docs`
69- const repoName = url . match ( pattern ) [ 1 ]
78+
79+ const repoMatchArray = url . match ( repoNamePattern )
80+ if ( ! repoMatchArray ) {
81+ return false
82+ }
83+
84+ const repoName = repoMatchArray [ 1 ] // e.g for a given link https://github.com/gruntwork-io/docs/intro -> `docs`
7085
7186 // returns boolean
72- return publicGruntworkRepoNames . includes ( repoName )
87+ return repoNames . includes ( repoName )
88+ }
89+
90+ /**
91+ * Checks if a link references a known public Gruntwork repo
92+ *
93+ * @param {string } url
94+ * @return {boolean }
95+ */
96+ const isPublicGruntworkRepo = ( url ) => {
97+ // returns boolean
98+ return listIncludesRepo ( publicGruntworkRepoNames , url )
7399}
74100
75101/**
76102 * Checks if a link references a private Gruntwork repo
77103 *
78- * @param string url
104+ * @param { string } url
79105 * @return {boolean }
80106 */
81107const isPrivateGruntworkRepo = ( url ) => {
@@ -85,33 +111,49 @@ const isPrivateGruntworkRepo = (url) => {
85111}
86112
87113/**
88- * Checks if a link references the Gruntwork CIS service catalog repo
114+ * Checks if a link references a Gruntwork CIS repo
89115 *
90- * @param string url
116+ * @param { string } url
91117 * @return {boolean }
92118 */
93-
94119const isGruntworkCisRepo = ( url ) => {
95- return url && url . startsWith ( `${ gruntworkGithubOrg } ${ gruntworkCisRepoName } ` )
120+ // awsCISRepos is an array of strings, e.g. `gruntwork-io/cis-docs`
121+ const cisRepoNames = awsCISRepos . map ( ( repo ) => repo . split ( "/" ) [ 1 ] )
122+ return listIncludesRepo ( cisRepoNames , url )
123+ }
124+
125+ /**
126+ * Checks if a link references a Gruntwork Enterprise repo
127+ *
128+ * @param {string } url
129+ * @return {boolean }
130+ */
131+ const isGruntworkEnterpriseRepo = ( url ) => {
132+ // enterpriseRepos is an array of strings, e.g. `gruntwork-io/enterprise-docs`
133+ const enterpriseRepoNames = enterpriseRepos . map ( ( repo ) => repo . split ( "/" ) [ 1 ] )
134+ return listIncludesRepo ( enterpriseRepoNames , url )
96135}
97136
98137export const DONT_SHOW_PRIVATE_GITHUB_WARNING_KEY = "dontWarnGitHubLinks"
99138export const DONT_SHOW_CIS_GITHUB_WARNING_KEY = "dontWarnCISLinks"
139+ export const DONT_SHOW_ENTERPRISE_GITHUB_WARNING_KEY = "dontWarnEnterpriseLinks"
100140
101141function Root ( { children } ) {
102- const [ displaySubscriberNotice , setDisplaySubscriberNotice ] = useState ( false )
103142 const [ subscriberNoticeLink , setSubscriberNoticeLink ] = useState ( "" )
104-
105- const [ displayCisNotice , setDisplayCisNotice ] = useState ( false )
106143 const [ cisNoticeLink , setCisNoticeLink ] = useState ( "" )
144+ const [ enterpriseNoticeLink , setEnterpriseNoticeLink ] = useState ( "" )
107145
108- useEffect ( ( ) => {
146+ useEffect ( function showModalForPrivateGithubLinks ( ) {
109147 const listener = ( event ) => {
110148 // Sometimes our links wrap components, such as Cards. In these cases, the event
111149 // target is often a child element of the <a> we're attempting to extract the
112150 // href data from, and so we search for the closest parent <a>. In the event that
113151 // an <a> is clicked directly, that <a> itself will be returned.
114- const targetLink = event . target . closest ( "a" )
152+ const targetLink = event ?. target ?. closest ( "a" )
153+
154+ if ( ! targetLink || ! targetLink . href ) {
155+ return
156+ }
115157
116158 // Allow clicks on the external GitHub link FROM the modal notices to work normally
117159 if ( targetLink . dataset . modalExempt ) {
@@ -124,13 +166,25 @@ function Root({ children }) {
124166 )
125167
126168 if ( dontWarn ) {
127- setDisplayCisNotice ( false )
128169 return
129170 }
130171
131- event . preventDefault ( )
172+ event . preventDefault ( ) // This prevents the link from opening & ensures the modal is displayed
132173 setCisNoticeLink ( targetLink . href )
133- setDisplayCisNotice ( true )
174+ return
175+ }
176+
177+ if ( isGruntworkEnterpriseRepo ( targetLink . href ) ) {
178+ const dontWarn = window . localStorage . getItem (
179+ DONT_SHOW_ENTERPRISE_GITHUB_WARNING_KEY
180+ )
181+
182+ if ( dontWarn ) {
183+ return
184+ }
185+
186+ event . preventDefault ( ) // This prevents the link from opening & ensures the modal is displayed
187+ setEnterpriseNoticeLink ( targetLink . href )
134188 return
135189 }
136190
@@ -144,9 +198,8 @@ function Root({ children }) {
144198 return
145199 }
146200
147- event . preventDefault ( )
201+ event . preventDefault ( ) // This prevents the link from opening & ensures the modal is displayed
148202 setSubscriberNoticeLink ( targetLink . href )
149- setDisplaySubscriberNotice ( true )
150203 return
151204 }
152205 }
@@ -160,29 +213,24 @@ function Root({ children }) {
160213 return (
161214 < >
162215 < SubscribersOnlyModal
163- showModal = { displaySubscriberNotice }
216+ showModal = { ! ! subscriberNoticeLink }
164217 externalLink = { subscriberNoticeLink }
165218 localStorageKey = { DONT_SHOW_PRIVATE_GITHUB_WARNING_KEY }
166- handleCancelRequest = { ( ) => {
167- setDisplaySubscriberNotice ( false )
168- setSubscriberNoticeLink ( "" )
169- } }
170- handleAcceptRequest = { ( ) => {
171- setDisplaySubscriberNotice ( false )
172- } }
219+ clearLink = { ( ) => setSubscriberNoticeLink ( "" ) }
173220 />
174221 < SubscribersOnlyModal
175- showModal = { displayCisNotice }
222+ showModal = { ! ! cisNoticeLink }
176223 externalLink = { cisNoticeLink }
177224 localStorageKey = { DONT_SHOW_CIS_GITHUB_WARNING_KEY }
178225 subscriberType = "CIS"
179- handleCancelRequest = { ( ) => {
180- setDisplayCisNotice ( false )
181- setCisNoticeLink ( "" )
182- } }
183- handleAcceptRequest = { ( ) => {
184- setDisplayCisNotice ( false )
185- } }
226+ clearLink = { ( ) => setCisNoticeLink ( "" ) }
227+ />
228+ < SubscribersOnlyModal
229+ showModal = { ! ! enterpriseNoticeLink }
230+ externalLink = { enterpriseNoticeLink }
231+ localStorageKey = { DONT_SHOW_ENTERPRISE_GITHUB_WARNING_KEY }
232+ subscriberType = "Enterprise"
233+ clearLink = { ( ) => setEnterpriseNoticeLink ( "" ) }
186234 />
187235 { children }
188236 </ >
0 commit comments