@openstack_dev/gatsby-theme-marketing-oif-core 1.0.8 → 1.0.10
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/gatsby-browser.js +2 -4
- package/gatsby-config.js +0 -2
- package/gatsby-ssr.js +33 -27
- package/package.json +7 -1
- package/src/components/Layout.js +7 -1
- package/src/components/Navbar/index.js +337 -347
- package/src/components/Navbar/index.module.scss +1 -0
- package/src/components/Navbar/placeholder.js +20 -0
- package/src/content/site-settings/index.json +1 -1
- package/src/state/ReduxWrapper.js +13 -2
- package/src/utils/createEmotionCache.js +5 -0
package/gatsby-browser.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReduxWrapperWithCacheProvider } from "./src/state/ReduxWrapper";
|
|
2
2
|
|
|
3
|
-
export const wrapRootElement =
|
|
4
|
-
|
|
5
|
-
export const onClientEntry = () => {};
|
|
3
|
+
export const wrapRootElement = ReduxWrapperWithCacheProvider;
|
package/gatsby-config.js
CHANGED
package/gatsby-ssr.js
CHANGED
|
@@ -1,50 +1,56 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as React from "react";
|
|
2
2
|
import { JSDOM } from "jsdom";
|
|
3
3
|
import { XMLHttpRequest } from "xmlhttprequest";
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import ReduxWrapper from "./src/state/ReduxWrapper";
|
|
4
|
+
import { renderToString } from "react-dom/server";
|
|
5
|
+
import { CacheProvider } from "@emotion/react";
|
|
6
|
+
import createEmotionServer from "@emotion/server/create-instance";
|
|
7
|
+
import { ReduxWrapper } from "./src/state/ReduxWrapper";
|
|
8
8
|
import { HeadComponents } from "./src/components/head-components";
|
|
9
|
+
import createEmotionCache from "./src/utils/createEmotionCache";
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
setHtmlAttributes,
|
|
13
|
-
setHeadComponents,
|
|
14
|
-
setPreBodyComponents,
|
|
15
|
-
setPostBodyComponents,
|
|
16
|
-
}, pluginOptions) => {
|
|
17
|
-
if (process.env.NODE_ENV === `production`) {
|
|
11
|
+
export const onRenderBody = ({ setHeadComponents }) => {
|
|
12
|
+
if (process.env.NODE_ENV === "production") {
|
|
18
13
|
setHeadComponents(HeadComponents);
|
|
19
14
|
}
|
|
20
15
|
};
|
|
21
16
|
|
|
22
17
|
export const replaceRenderer = ({
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
</ThemeProvider>
|
|
18
|
+
bodyComponent,
|
|
19
|
+
setHeadComponents,
|
|
20
|
+
replaceBodyHTMLString,
|
|
21
|
+
}) => {
|
|
22
|
+
const cache = createEmotionCache();
|
|
23
|
+
const { extractCriticalToChunks } = createEmotionServer(cache);
|
|
24
|
+
|
|
25
|
+
const emotionStyles = extractCriticalToChunks(
|
|
26
|
+
renderToString(<CacheProvider value={cache}>{bodyComponent}</CacheProvider>),
|
|
33
27
|
);
|
|
34
28
|
|
|
35
|
-
|
|
29
|
+
setHeadComponents(
|
|
30
|
+
emotionStyles.styles.map((style) => (
|
|
31
|
+
<style
|
|
32
|
+
data-emotion={`${style.key} ${style.ids.join(" ")}`}
|
|
33
|
+
key={style.key}
|
|
34
|
+
dangerouslySetInnerHTML={{ __html: style.css }}
|
|
35
|
+
/>
|
|
36
|
+
)),
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
// render the result from `extractCritical`
|
|
40
|
+
replaceBodyHTMLString(emotionStyles.html);
|
|
36
41
|
};
|
|
37
42
|
|
|
38
43
|
export const wrapRootElement = ReduxWrapper;
|
|
39
44
|
|
|
40
45
|
// build enabler polyfills
|
|
41
46
|
global.dom = new JSDOM("...");
|
|
42
|
-
global.window = dom.window;
|
|
43
|
-
global.document = dom.window.document;
|
|
47
|
+
global.window = global.dom.window;
|
|
48
|
+
global.document = global.dom.window.document;
|
|
44
49
|
global.navigator = global.window.navigator;
|
|
45
50
|
global.window.matchMedia = () => ({
|
|
46
51
|
matches: false,
|
|
47
52
|
addListener: () => {},
|
|
48
|
-
removeListener: () => {}
|
|
53
|
+
removeListener: () => {},
|
|
49
54
|
});
|
|
55
|
+
|
|
50
56
|
global.XMLHttpRequest = XMLHttpRequest;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openstack_dev/gatsby-theme-marketing-oif-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.10",
|
|
4
4
|
"description": "Base theme for Marketing Sites",
|
|
5
5
|
"author": "smarcet",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,12 @@
|
|
|
22
22
|
"**/*": "prettier --write --ignore-unknown"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"@emotion/cache": "^11.11.0",
|
|
26
|
+
"@emotion/react": "^11.11.4",
|
|
27
|
+
"@emotion/server": "^11.11.0",
|
|
28
|
+
"@emotion/styled": "^11.11.5",
|
|
25
29
|
"@fortawesome/fontawesome-free": "^6.5.2",
|
|
30
|
+
"@loadable/component": "^5.16.4",
|
|
26
31
|
"@mui/icons-material": "^5.15.15",
|
|
27
32
|
"@mui/material": "^5.15.15",
|
|
28
33
|
"@ncwidgets/file-relation": "^0.8.0",
|
|
@@ -108,6 +113,7 @@
|
|
|
108
113
|
"react-iframe-comm": "^1.2.2",
|
|
109
114
|
"react-immutable-proptypes": "^2.2.0",
|
|
110
115
|
"react-laag": "^2.0.5",
|
|
116
|
+
"react-loadable-visibility": "^3.0.2",
|
|
111
117
|
"react-medium-image-zoom": "^4.3.5",
|
|
112
118
|
"react-redux": "^7.2.6",
|
|
113
119
|
"react-rte": "^0.16.3",
|
package/src/components/Layout.js
CHANGED
|
@@ -2,13 +2,19 @@ import React from "react";
|
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import CssBaseline from "@mui/material/CssBaseline";
|
|
4
4
|
import { ThemeProvider } from "@mui/material/styles";
|
|
5
|
+
import loadable from "@loadable/component";
|
|
5
6
|
import Footer from "./Footer";
|
|
6
7
|
import SponsoredProjectsNav from "./SponsoredProjectsNav";
|
|
7
8
|
import SubscribeForm from "./SubscribeForm";
|
|
8
9
|
import AnnouncementBanner from "./AnnouncementBanner";
|
|
9
10
|
import Header from "./Header";
|
|
10
|
-
import Navbar from "./Navbar";
|
|
11
11
|
import theme from "../theme";
|
|
12
|
+
import NavBarPlaceholder from "./Navbar/placeholder";
|
|
13
|
+
|
|
14
|
+
const Navbar = loadable(() => import("./Navbar"), {
|
|
15
|
+
ssr: false,
|
|
16
|
+
fallback: <NavBarPlaceholder />,
|
|
17
|
+
});
|
|
12
18
|
|
|
13
19
|
function Layout({ children }) {
|
|
14
20
|
return (
|
|
@@ -15,6 +15,7 @@ import AddIcon from "@mui/icons-material/Add";
|
|
|
15
15
|
import RemoveIcon from "@mui/icons-material/Remove";
|
|
16
16
|
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
17
17
|
import Button from "@mui/material/Button";
|
|
18
|
+
import Link from "../Link";
|
|
18
19
|
|
|
19
20
|
import navbarContent from "../../content/navbar/index.json";
|
|
20
21
|
|
|
@@ -28,11 +29,6 @@ function Navbar({ isLoggedUser, member }) {
|
|
|
28
29
|
const [navbarMenu, setNavbarMenu] = React.useState(null);
|
|
29
30
|
const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
|
|
30
31
|
const [isSearchBarOpen, setIsSearchBarOpen] = React.useState(false);
|
|
31
|
-
const [domLoaded, setDomLoaded] = React.useState(false);
|
|
32
|
-
|
|
33
|
-
React.useEffect(() => {
|
|
34
|
-
setDomLoaded(true);
|
|
35
|
-
}, []);
|
|
36
32
|
|
|
37
33
|
const handleSetActiveMenu = (option) => {
|
|
38
34
|
setNavbarMenu(navbarMenu === option ? null : option);
|
|
@@ -78,399 +74,393 @@ function Navbar({ isLoggedUser, member }) {
|
|
|
78
74
|
};
|
|
79
75
|
|
|
80
76
|
return (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
if (event.key === "Enter" || event.key === " ") setIsSearchBarOpen(true);
|
|
115
|
-
}}
|
|
116
|
-
onClick={() => setIsSearchBarOpen(true)}
|
|
117
|
-
className={styles.searchComponent}
|
|
118
|
-
>
|
|
119
|
-
<SearchIcon className={styles.searchIcon} />
|
|
120
|
-
<span className={styles.headerSearchText}>Search</span>
|
|
121
|
-
</div>
|
|
122
|
-
<Box
|
|
123
|
-
className={`openstack-search-bar ${styles.openstackSearchBar}`}
|
|
124
|
-
style={{
|
|
125
|
-
visibility: isSearchBarOpen ? "visible" : "hidden",
|
|
126
|
-
opacity: isSearchBarOpen ? "1" : "0",
|
|
127
|
-
}}
|
|
128
|
-
data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
|
|
129
|
-
data-context="www-openstack"
|
|
130
|
-
/>
|
|
131
|
-
</Box>
|
|
132
|
-
</Box>
|
|
133
|
-
{/* Mobile Menu */}
|
|
134
|
-
<Box
|
|
135
|
-
className={styles.mobileMenuWrapper}
|
|
136
|
-
sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
|
|
77
|
+
<nav role="navigation">
|
|
78
|
+
<Script
|
|
79
|
+
src={`${getEnvVariable(SEARCH_WIDGET_BASE_URL)}/widget/embed.min.js`}
|
|
80
|
+
onLoad={() => console.log("Script loaded")}
|
|
81
|
+
/>
|
|
82
|
+
<AppBar
|
|
83
|
+
position="static"
|
|
84
|
+
className={styles.navbar}
|
|
85
|
+
sx={{ backgroundColor: "#fff", boxShadow: "none" }}
|
|
86
|
+
>
|
|
87
|
+
<Container maxWidth="xl">
|
|
88
|
+
<Toolbar disableGutters sx={{ flexWrap: "wrap" }}>
|
|
89
|
+
<Box className={styles.navbarHeader}>
|
|
90
|
+
<div className={styles.brandWrapper}>
|
|
91
|
+
<a
|
|
92
|
+
className={styles.navbarBrand}
|
|
93
|
+
href="/"
|
|
94
|
+
alt="Openstack logo"
|
|
95
|
+
aria-label="Go to homepage"
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
<Box
|
|
99
|
+
className={styles.searchWrapper}
|
|
100
|
+
sx={{ display: { xs: "none", md: "flex" } }}
|
|
101
|
+
>
|
|
102
|
+
<div
|
|
103
|
+
role="button"
|
|
104
|
+
tabIndex={0}
|
|
105
|
+
onKeyDown={(event) => {
|
|
106
|
+
if (event.key === "Enter" || event.key === " ") setIsSearchBarOpen(true);
|
|
107
|
+
}}
|
|
108
|
+
onClick={() => setIsSearchBarOpen(true)}
|
|
109
|
+
className={styles.searchComponent}
|
|
137
110
|
>
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
aria-label="account of current user"
|
|
142
|
-
aria-controls="menu-appbar"
|
|
143
|
-
aria-haspopup="true"
|
|
144
|
-
onClick={() => handleMobileMenuToggle()}
|
|
145
|
-
color="inherit"
|
|
146
|
-
>
|
|
147
|
-
<MenuIcon />
|
|
148
|
-
</IconButton>
|
|
149
|
-
</Box>
|
|
150
|
-
{/* Desktop Menu */}
|
|
111
|
+
<SearchIcon className={styles.searchIcon} />
|
|
112
|
+
<span className={styles.headerSearchText}>Search</span>
|
|
113
|
+
</div>
|
|
151
114
|
<Box
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
md: isSearchBarOpen ? "none" : "flex",
|
|
157
|
-
},
|
|
158
|
-
justifyContent: "flex-end",
|
|
115
|
+
className={`openstack-search-bar ${styles.openstackSearchBar}`}
|
|
116
|
+
style={{
|
|
117
|
+
visibility: isSearchBarOpen ? "visible" : "hidden",
|
|
118
|
+
opacity: isSearchBarOpen ? "1" : "0",
|
|
159
119
|
}}
|
|
120
|
+
data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
|
|
121
|
+
data-context="www-openstack"
|
|
122
|
+
/>
|
|
123
|
+
</Box>
|
|
124
|
+
</Box>
|
|
125
|
+
{/* Mobile Menu */}
|
|
126
|
+
<Box
|
|
127
|
+
className={styles.mobileMenuWrapper}
|
|
128
|
+
sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
|
|
129
|
+
>
|
|
130
|
+
<IconButton
|
|
131
|
+
className={styles.toggleIcon}
|
|
132
|
+
size="large"
|
|
133
|
+
aria-label="account of current user"
|
|
134
|
+
aria-controls="menu-appbar"
|
|
135
|
+
aria-haspopup="true"
|
|
136
|
+
onClick={() => handleMobileMenuToggle()}
|
|
137
|
+
color="inherit"
|
|
138
|
+
>
|
|
139
|
+
<MenuIcon />
|
|
140
|
+
</IconButton>
|
|
141
|
+
</Box>
|
|
142
|
+
{/* Desktop Menu */}
|
|
143
|
+
<Box
|
|
144
|
+
sx={{
|
|
145
|
+
flexGrow: 1,
|
|
146
|
+
display: {
|
|
147
|
+
xs: "none",
|
|
148
|
+
md: isSearchBarOpen ? "none" : "flex",
|
|
149
|
+
},
|
|
150
|
+
justifyContent: "flex-end",
|
|
151
|
+
}}
|
|
152
|
+
>
|
|
153
|
+
{navbarContent.items.map(
|
|
154
|
+
(item) => item.display && (
|
|
155
|
+
<Link
|
|
156
|
+
className={styles.navbarOption}
|
|
157
|
+
key={item.title}
|
|
158
|
+
sx={{ my: 2, display: "block" }}
|
|
159
|
+
href={item.link}
|
|
160
160
|
>
|
|
161
|
-
{
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
className={styles.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
{item.items?.length > 0 ? (
|
|
171
|
-
<>
|
|
172
|
-
{item.title}
|
|
173
|
-
<ArrowDropDownIcon
|
|
174
|
-
className={styles.arrowDownIcon}
|
|
161
|
+
{item.items?.length > 0 ? (
|
|
162
|
+
<>
|
|
163
|
+
{item.title}
|
|
164
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
165
|
+
<Box className={styles.dropDownMenu}>
|
|
166
|
+
{item.items.map((subItem) => (!subItem.title && !subItem.link ? (
|
|
167
|
+
<div
|
|
168
|
+
className={styles.divider}
|
|
169
|
+
key={subItem.title}
|
|
175
170
|
/>
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
</>
|
|
192
|
-
) : (
|
|
193
|
-
item.title
|
|
194
|
-
)}
|
|
195
|
-
</Button>
|
|
196
|
-
),
|
|
171
|
+
) : (
|
|
172
|
+
<Button
|
|
173
|
+
className={styles.dropdownMenuOption}
|
|
174
|
+
key={subItem.title}
|
|
175
|
+
onClick={() => handleNavigation(subItem.link)}
|
|
176
|
+
sx={{ display: "block" }}
|
|
177
|
+
disableRipple
|
|
178
|
+
>
|
|
179
|
+
{subItem.title}
|
|
180
|
+
</Button>
|
|
181
|
+
)))}
|
|
182
|
+
</Box>
|
|
183
|
+
</>
|
|
184
|
+
) : (
|
|
185
|
+
item.title
|
|
197
186
|
)}
|
|
198
|
-
</
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
187
|
+
</Link>
|
|
188
|
+
),
|
|
189
|
+
)}
|
|
190
|
+
</Box>
|
|
191
|
+
{isLoggedUser ? (
|
|
192
|
+
<Box
|
|
193
|
+
maxWidth="15%"
|
|
194
|
+
sx={{
|
|
195
|
+
display: {
|
|
196
|
+
xs: "none",
|
|
197
|
+
md: isSearchBarOpen ? "none" : "flex",
|
|
198
|
+
},
|
|
199
|
+
justifyContent: "flex-end",
|
|
200
|
+
marginLeft: "auto",
|
|
201
|
+
}}
|
|
202
|
+
>
|
|
203
|
+
<Box
|
|
204
|
+
className={`${styles.navbarOption}`}
|
|
205
|
+
sx={{ my: 2, display: "block" }}
|
|
206
|
+
>
|
|
207
|
+
My Account
|
|
208
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
209
|
+
<Box className={styles.dropDownMenu}>
|
|
211
210
|
<Button
|
|
212
|
-
className={
|
|
213
|
-
|
|
211
|
+
className={styles.dropdownMenuOption}
|
|
212
|
+
onClick={() => handleNavigation("/profile/")}
|
|
213
|
+
sx={{ display: "block" }}
|
|
214
214
|
disableRipple
|
|
215
215
|
>
|
|
216
|
-
|
|
217
|
-
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
218
|
-
<Box className={styles.dropDownMenu}>
|
|
219
|
-
<Button
|
|
220
|
-
className={styles.dropdownMenuOption}
|
|
221
|
-
onClick={() => handleNavigation("/profile/")}
|
|
222
|
-
sx={{ display: "block" }}
|
|
223
|
-
disableRipple
|
|
224
|
-
>
|
|
225
|
-
Edit Profile
|
|
226
|
-
</Button>
|
|
227
|
-
<Button
|
|
228
|
-
className={styles.dropdownMenuOption}
|
|
229
|
-
onClick={() => handleNavigation(
|
|
230
|
-
`/community/members/profile/${
|
|
231
|
-
member.id
|
|
232
|
-
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
233
|
-
)}
|
|
234
|
-
sx={{ display: "block" }}
|
|
235
|
-
disableRipple
|
|
236
|
-
>
|
|
237
|
-
View Public Profile
|
|
238
|
-
</Button>
|
|
239
|
-
<div className={styles.divider} />
|
|
240
|
-
<Button
|
|
241
|
-
className={styles.dropdownMenuOption}
|
|
242
|
-
sx={{ display: "block" }}
|
|
243
|
-
onClick={onClickLogout}
|
|
244
|
-
disableRipple
|
|
245
|
-
>
|
|
246
|
-
Log out
|
|
247
|
-
</Button>
|
|
248
|
-
</Box>
|
|
216
|
+
Edit Profile
|
|
249
217
|
</Button>
|
|
250
|
-
</Box>
|
|
251
|
-
) : (
|
|
252
|
-
<Box
|
|
253
|
-
maxWidth="15%"
|
|
254
|
-
sx={{
|
|
255
|
-
display: {
|
|
256
|
-
xs: "none",
|
|
257
|
-
md: isSearchBarOpen ? "none" : "flex",
|
|
258
|
-
},
|
|
259
|
-
justifyContent: "flex-end",
|
|
260
|
-
marginLeft: "auto",
|
|
261
|
-
}}
|
|
262
|
-
>
|
|
263
218
|
<Button
|
|
264
|
-
className={
|
|
265
|
-
|
|
219
|
+
className={styles.dropdownMenuOption}
|
|
220
|
+
onClick={() => handleNavigation(
|
|
221
|
+
`/community/members/profile/${
|
|
222
|
+
member.id
|
|
223
|
+
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
224
|
+
)}
|
|
225
|
+
sx={{ display: "block" }}
|
|
266
226
|
disableRipple
|
|
267
227
|
>
|
|
268
|
-
|
|
269
|
-
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
270
|
-
<Box className={styles.dropDownMenu}>
|
|
271
|
-
<Button
|
|
272
|
-
className={styles.dropdownMenuOption}
|
|
273
|
-
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
274
|
-
sx={{ display: "block" }}
|
|
275
|
-
disableRipple
|
|
276
|
-
>
|
|
277
|
-
Sign up for Foundation Membership
|
|
278
|
-
</Button>
|
|
279
|
-
<Button
|
|
280
|
-
className={styles.dropdownMenuOption}
|
|
281
|
-
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
282
|
-
sx={{ display: "block" }}
|
|
283
|
-
disableRipple
|
|
284
|
-
>
|
|
285
|
-
Sponsor the Foundation
|
|
286
|
-
</Button>
|
|
287
|
-
<Button
|
|
288
|
-
className={styles.dropdownMenuOption}
|
|
289
|
-
onClick={() => handleNavigation("https://openinfra.dev")}
|
|
290
|
-
sx={{ display: "block" }}
|
|
291
|
-
disableRipple
|
|
292
|
-
>
|
|
293
|
-
More about the Foundation
|
|
294
|
-
</Button>
|
|
295
|
-
</Box>
|
|
228
|
+
View Public Profile
|
|
296
229
|
</Button>
|
|
230
|
+
<div className={styles.divider} />
|
|
297
231
|
<Button
|
|
298
|
-
className={
|
|
299
|
-
|
|
300
|
-
|
|
232
|
+
className={styles.dropdownMenuOption}
|
|
233
|
+
sx={{ display: "block" }}
|
|
234
|
+
onClick={onClickLogout}
|
|
301
235
|
disableRipple
|
|
302
236
|
>
|
|
303
|
-
Log
|
|
237
|
+
Log out
|
|
304
238
|
</Button>
|
|
305
239
|
</Box>
|
|
306
|
-
|
|
307
|
-
</
|
|
240
|
+
</Box>
|
|
241
|
+
</Box>
|
|
242
|
+
) : (
|
|
308
243
|
<Box
|
|
309
|
-
|
|
244
|
+
maxWidth="15%"
|
|
310
245
|
sx={{
|
|
311
|
-
|
|
312
|
-
xs:
|
|
313
|
-
md: "
|
|
246
|
+
display: {
|
|
247
|
+
xs: "none",
|
|
248
|
+
md: isSearchBarOpen ? "none" : "flex",
|
|
314
249
|
},
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
color: "#8a959e",
|
|
250
|
+
justifyContent: "flex-end",
|
|
251
|
+
marginLeft: "auto",
|
|
318
252
|
}}
|
|
319
|
-
|
|
320
|
-
data-context="www-openstack"
|
|
321
|
-
/>
|
|
322
|
-
{isMobileMenuOpen && (
|
|
253
|
+
>
|
|
323
254
|
<Box
|
|
324
|
-
className={styles.
|
|
325
|
-
sx={{
|
|
326
|
-
display: { xs: "flex", md: "none" },
|
|
327
|
-
}}
|
|
255
|
+
className={`${styles.navbarOption} ${styles.join}`}
|
|
256
|
+
sx={{ my: 2, display: "block" }}
|
|
328
257
|
>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
258
|
+
Join
|
|
259
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
260
|
+
<Box className={styles.dropDownMenu}>
|
|
261
|
+
<Button
|
|
262
|
+
className={styles.dropdownMenuOption}
|
|
263
|
+
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
264
|
+
sx={{ display: "block" }}
|
|
265
|
+
disableRipple
|
|
266
|
+
>
|
|
267
|
+
Sign up for Foundation Membership
|
|
268
|
+
</Button>
|
|
269
|
+
<Button
|
|
270
|
+
className={styles.dropdownMenuOption}
|
|
271
|
+
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
272
|
+
sx={{ display: "block" }}
|
|
273
|
+
disableRipple
|
|
274
|
+
>
|
|
275
|
+
Sponsor the Foundation
|
|
276
|
+
</Button>
|
|
277
|
+
<Button
|
|
278
|
+
className={styles.dropdownMenuOption}
|
|
279
|
+
onClick={() => handleNavigation("https://openinfra.dev")}
|
|
280
|
+
sx={{ display: "block" }}
|
|
281
|
+
disableRipple
|
|
282
|
+
>
|
|
283
|
+
More about the Foundation
|
|
284
|
+
</Button>
|
|
285
|
+
</Box>
|
|
286
|
+
</Box>
|
|
287
|
+
<Button
|
|
288
|
+
className={`${styles.navbarOption} ${styles.login}`}
|
|
289
|
+
onClick={() => doLogin("/")}
|
|
290
|
+
sx={{ my: 2, display: "block" }}
|
|
291
|
+
disableRipple
|
|
292
|
+
>
|
|
293
|
+
Log in
|
|
294
|
+
</Button>
|
|
295
|
+
</Box>
|
|
296
|
+
)}
|
|
297
|
+
</Toolbar>
|
|
298
|
+
<Box
|
|
299
|
+
className={`${styles.openstackSearchBarMobile} openstack-search-bar ossw-mobile`}
|
|
300
|
+
sx={{
|
|
301
|
+
visibility: {
|
|
302
|
+
xs: isMobileMenuOpen ? "visible" : "hidden",
|
|
303
|
+
md: "hidden",
|
|
304
|
+
},
|
|
305
|
+
opacity: { xs: isMobileMenuOpen ? "1" : "0", md: "0" },
|
|
306
|
+
height: { xs: isMobileMenuOpen ? "auto" : 0, md: 0 },
|
|
307
|
+
color: "#8a959e",
|
|
308
|
+
}}
|
|
309
|
+
data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
|
|
310
|
+
data-context="www-openstack"
|
|
311
|
+
/>
|
|
312
|
+
{isMobileMenuOpen && (
|
|
313
|
+
<Box
|
|
314
|
+
className={styles.navbarMobileMenu}
|
|
315
|
+
sx={{
|
|
316
|
+
display: { xs: "flex", md: "none" },
|
|
317
|
+
}}
|
|
318
|
+
>
|
|
319
|
+
{navbarContent.items.map(
|
|
320
|
+
(item) => item.display && (
|
|
321
|
+
<>
|
|
322
|
+
<Button
|
|
323
|
+
disableRipple
|
|
324
|
+
className={styles.mobileOption}
|
|
325
|
+
key={`${item.title}-mobile`}
|
|
326
|
+
onClick={() => handleSetActiveMenu(item.title)}
|
|
327
|
+
>
|
|
328
|
+
{item.title}
|
|
329
|
+
{item.items?.length > 0
|
|
330
|
+
&& (item.title === navbarMenu ? (
|
|
331
|
+
<RemoveIcon aria-hidden="true" />
|
|
332
|
+
) : (
|
|
333
|
+
<AddIcon aria-hidden="true" />
|
|
334
|
+
))}
|
|
335
|
+
</Button>
|
|
336
|
+
{item.items?.length > 0 && item.title === navbarMenu && (
|
|
337
|
+
<Box className={styles.mobileDropdownMenu}>
|
|
338
|
+
{item.items.map((subItem) => (!subItem.title && !subItem.link ? (
|
|
339
|
+
<div
|
|
340
|
+
className={styles.divider}
|
|
341
|
+
key={subItem.title}
|
|
342
|
+
/>
|
|
343
|
+
) : (
|
|
332
344
|
<Button
|
|
345
|
+
className={styles.mobileDropdownOption}
|
|
346
|
+
key={`${subItem.title}-mobile`}
|
|
347
|
+
onClick={() => handleNavigation(subItem.link)}
|
|
348
|
+
sx={{ display: "block" }}
|
|
333
349
|
disableRipple
|
|
334
|
-
className={styles.mobileOption}
|
|
335
|
-
key={`${item.title}-mobile`}
|
|
336
|
-
onClick={() => handleSetActiveMenu(item.title)}
|
|
337
350
|
>
|
|
338
|
-
{
|
|
339
|
-
{item.items?.length > 0
|
|
340
|
-
&& (item.title === navbarMenu ? (
|
|
341
|
-
<RemoveIcon aria-hidden="true" />
|
|
342
|
-
) : (
|
|
343
|
-
<AddIcon aria-hidden="true" />
|
|
344
|
-
))}
|
|
351
|
+
{subItem.title}
|
|
345
352
|
</Button>
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
<Box className={styles.mobileDropdownMenu}>
|
|
349
|
-
{item.items.map((subItem) => (!subItem.title && !subItem.link ? (
|
|
350
|
-
<div className={styles.divider} />
|
|
351
|
-
) : (
|
|
352
|
-
<Button
|
|
353
|
-
className={styles.mobileDropdownOption}
|
|
354
|
-
key={subItem.title}
|
|
355
|
-
onClick={() => handleNavigation(subItem.link)}
|
|
356
|
-
sx={{ display: "block" }}
|
|
357
|
-
disableRipple
|
|
358
|
-
>
|
|
359
|
-
{subItem.title}
|
|
360
|
-
</Button>
|
|
361
|
-
)))}
|
|
362
|
-
</Box>
|
|
363
|
-
)}
|
|
364
|
-
</>
|
|
365
|
-
),
|
|
353
|
+
)))}
|
|
354
|
+
</Box>
|
|
366
355
|
)}
|
|
367
|
-
|
|
368
|
-
|
|
356
|
+
</>
|
|
357
|
+
),
|
|
358
|
+
)}
|
|
359
|
+
{isLoggedUser ? (
|
|
360
|
+
<>
|
|
361
|
+
<Button
|
|
362
|
+
className={styles.mobileOption}
|
|
363
|
+
onClick={() => handleSetActiveMenu("My Account")}
|
|
364
|
+
disableRipple
|
|
365
|
+
>
|
|
366
|
+
My Account
|
|
367
|
+
{navbarMenu === "My Account" ? (
|
|
368
|
+
<RemoveIcon aria-hidden="true" />
|
|
369
|
+
) : (
|
|
370
|
+
<AddIcon aria-hidden="true" />
|
|
371
|
+
)}
|
|
372
|
+
</Button>
|
|
373
|
+
{navbarMenu === "My Account" && (
|
|
374
|
+
<Box className={styles.mobileDropdownMenu}>
|
|
369
375
|
<Button
|
|
370
|
-
className={styles.
|
|
371
|
-
onClick={() =>
|
|
376
|
+
className={styles.mobileDropdownOption}
|
|
377
|
+
onClick={() => handleNavigation("/profile/")}
|
|
378
|
+
sx={{ display: "block" }}
|
|
372
379
|
disableRipple
|
|
373
380
|
>
|
|
374
|
-
|
|
375
|
-
{navbarMenu === "My Account" ? (
|
|
376
|
-
<RemoveIcon aria-hidden="true" />
|
|
377
|
-
) : (
|
|
378
|
-
<AddIcon aria-hidden="true" />
|
|
379
|
-
)}
|
|
381
|
+
Edit Profile
|
|
380
382
|
</Button>
|
|
381
|
-
{navbarMenu === "My Account" && (
|
|
382
|
-
<Box className={styles.mobileDropdownMenu}>
|
|
383
|
-
<Button
|
|
384
|
-
className={styles.mobileDropdownOption}
|
|
385
|
-
onClick={() => handleNavigation("/profile/")}
|
|
386
|
-
sx={{ display: "block" }}
|
|
387
|
-
disableRipple
|
|
388
|
-
>
|
|
389
|
-
Edit Profile
|
|
390
|
-
</Button>
|
|
391
|
-
<Button
|
|
392
|
-
className={styles.mobileDropdownOption}
|
|
393
|
-
onClick={() => handleNavigation(
|
|
394
|
-
`/community/members/profile/${
|
|
395
|
-
member.id
|
|
396
|
-
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
397
|
-
)}
|
|
398
|
-
sx={{ display: "block" }}
|
|
399
|
-
disableRipple
|
|
400
|
-
>
|
|
401
|
-
View Public Profile
|
|
402
|
-
</Button>
|
|
403
|
-
<div className={styles.divider} />
|
|
404
|
-
<Button
|
|
405
|
-
className={styles.mobileDropdownOption}
|
|
406
|
-
sx={{ display: "block" }}
|
|
407
|
-
onClick={onClickLogout}
|
|
408
|
-
disableRipple
|
|
409
|
-
>
|
|
410
|
-
Log out
|
|
411
|
-
</Button>
|
|
412
|
-
</Box>
|
|
413
|
-
)}
|
|
414
|
-
</>
|
|
415
|
-
) : (
|
|
416
|
-
<Box>
|
|
417
383
|
<Button
|
|
418
|
-
className={
|
|
419
|
-
|
|
384
|
+
className={styles.mobileDropdownOption}
|
|
385
|
+
onClick={() => handleNavigation(
|
|
386
|
+
`/community/members/profile/${
|
|
387
|
+
member.id
|
|
388
|
+
}/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
|
|
389
|
+
)}
|
|
390
|
+
sx={{ display: "block" }}
|
|
420
391
|
disableRipple
|
|
421
392
|
>
|
|
422
|
-
|
|
423
|
-
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
424
|
-
<Box className={styles.dropDownMenu}>
|
|
425
|
-
<Button
|
|
426
|
-
className={styles.dropdownMenuOption}
|
|
427
|
-
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
428
|
-
sx={{ display: "block" }}
|
|
429
|
-
disableRipple
|
|
430
|
-
>
|
|
431
|
-
Sign up for Foundation Membership
|
|
432
|
-
</Button>
|
|
433
|
-
<Button
|
|
434
|
-
className={styles.dropdownMenuOption}
|
|
435
|
-
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
436
|
-
sx={{ display: "block" }}
|
|
437
|
-
disableRipple
|
|
438
|
-
>
|
|
439
|
-
Sponsor the Foundation
|
|
440
|
-
</Button>
|
|
441
|
-
<Button
|
|
442
|
-
className={styles.dropdownMenuOption}
|
|
443
|
-
onClick={() => handleNavigation("https://openinfra.dev")}
|
|
444
|
-
sx={{ display: "block" }}
|
|
445
|
-
disableRipple
|
|
446
|
-
>
|
|
447
|
-
More about the Foundation
|
|
448
|
-
</Button>
|
|
449
|
-
</Box>
|
|
393
|
+
View Public Profile
|
|
450
394
|
</Button>
|
|
395
|
+
<div className={styles.divider} />
|
|
451
396
|
<Button
|
|
452
|
-
className={
|
|
453
|
-
|
|
454
|
-
|
|
397
|
+
className={styles.mobileDropdownOption}
|
|
398
|
+
sx={{ display: "block" }}
|
|
399
|
+
onClick={onClickLogout}
|
|
455
400
|
disableRipple
|
|
456
401
|
>
|
|
457
|
-
Log
|
|
402
|
+
Log out
|
|
458
403
|
</Button>
|
|
459
404
|
</Box>
|
|
460
405
|
)}
|
|
406
|
+
</>
|
|
407
|
+
) : (
|
|
408
|
+
<Box>
|
|
409
|
+
<Box
|
|
410
|
+
className={`${styles.navbarOption} ${styles.join}`}
|
|
411
|
+
sx={{ my: 2, display: "block" }}
|
|
412
|
+
>
|
|
413
|
+
Join
|
|
414
|
+
<ArrowDropDownIcon className={styles.arrowDownIcon} />
|
|
415
|
+
<Box className={styles.dropDownMenu}>
|
|
416
|
+
<Button
|
|
417
|
+
className={styles.dropdownMenuOption}
|
|
418
|
+
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
419
|
+
sx={{ display: "block" }}
|
|
420
|
+
disableRipple
|
|
421
|
+
>
|
|
422
|
+
Sign up for Foundation Membership
|
|
423
|
+
</Button>
|
|
424
|
+
<Button
|
|
425
|
+
className={styles.dropdownMenuOption}
|
|
426
|
+
onClick={() => handleNavigation("https://openinfra.dev/join")}
|
|
427
|
+
sx={{ display: "block" }}
|
|
428
|
+
disableRipple
|
|
429
|
+
>
|
|
430
|
+
Sponsor the Foundation
|
|
431
|
+
</Button>
|
|
432
|
+
<Button
|
|
433
|
+
className={styles.dropdownMenuOption}
|
|
434
|
+
onClick={() => handleNavigation("https://openinfra.dev")}
|
|
435
|
+
sx={{ display: "block" }}
|
|
436
|
+
disableRipple
|
|
437
|
+
>
|
|
438
|
+
More about the Foundation
|
|
439
|
+
</Button>
|
|
440
|
+
</Box>
|
|
441
|
+
</Box>
|
|
442
|
+
<Button
|
|
443
|
+
className={`${styles.navbarOption} ${styles.login}`}
|
|
444
|
+
onClick={() => doLogin("/")}
|
|
445
|
+
sx={{ my: 2, display: "block" }}
|
|
446
|
+
disableRipple
|
|
447
|
+
>
|
|
448
|
+
Log in
|
|
449
|
+
</Button>
|
|
461
450
|
</Box>
|
|
462
451
|
)}
|
|
463
|
-
</
|
|
464
|
-
|
|
465
|
-
</
|
|
466
|
-
|
|
467
|
-
|
|
452
|
+
</Box>
|
|
453
|
+
)}
|
|
454
|
+
</Container>
|
|
455
|
+
</AppBar>
|
|
456
|
+
</nav>
|
|
468
457
|
);
|
|
469
458
|
}
|
|
470
459
|
|
|
471
460
|
Navbar.propTypes = {
|
|
472
461
|
isLoggedUser: PropTypes.bool.isRequired,
|
|
473
|
-
member: PropTypes.object.
|
|
462
|
+
member: PropTypes.oneOfType([PropTypes.object, PropTypes.oneOf([null])])
|
|
463
|
+
.isRequired,
|
|
474
464
|
};
|
|
475
465
|
|
|
476
466
|
const mapStateToProps = ({ loggedUserState }) => ({
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import AppBar from "@mui/material/AppBar";
|
|
3
|
+
import { Container } from "@mui/material";
|
|
4
|
+
import styles from "./index.module.scss";
|
|
5
|
+
|
|
6
|
+
function NavBarPlaceholder() {
|
|
7
|
+
return (
|
|
8
|
+
<nav role="navigation">
|
|
9
|
+
<AppBar
|
|
10
|
+
position="static"
|
|
11
|
+
className={styles.navbar}
|
|
12
|
+
sx={{ backgroundColor: "#fff", boxShadow: "none" }}
|
|
13
|
+
>
|
|
14
|
+
<Container maxWidth="xl" />
|
|
15
|
+
</AppBar>
|
|
16
|
+
</nav>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default NavBarPlaceholder;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{ "staticJsonFilesBuildTime": [], "lastBuild":
|
|
1
|
+
{ "staticJsonFilesBuildTime": [], "lastBuild": 1713964554954 }
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { Provider } from "react-redux";
|
|
3
3
|
import { PersistGate } from "redux-persist/integration/react";
|
|
4
|
+
import { CacheProvider } from "@emotion/react";
|
|
4
5
|
import { store, persistor } from "./store";
|
|
6
|
+
import createEmotionCache from "../utils/createEmotionCache";
|
|
5
7
|
|
|
6
|
-
function ReduxWrapper({ element }) {
|
|
8
|
+
export function ReduxWrapper({ element }) {
|
|
7
9
|
return (
|
|
8
10
|
<Provider store={store}>
|
|
9
11
|
<PersistGate persistor={persistor}>{() => element}</PersistGate>
|
|
@@ -11,4 +13,13 @@ function ReduxWrapper({ element }) {
|
|
|
11
13
|
);
|
|
12
14
|
}
|
|
13
15
|
|
|
14
|
-
export
|
|
16
|
+
export function ReduxWrapperWithCacheProvider({ element }) {
|
|
17
|
+
const cache = createEmotionCache();
|
|
18
|
+
return (
|
|
19
|
+
<CacheProvider value={cache}>
|
|
20
|
+
<Provider store={store}>
|
|
21
|
+
<PersistGate persistor={persistor}>{() => element}</PersistGate>
|
|
22
|
+
</Provider>
|
|
23
|
+
</CacheProvider>
|
|
24
|
+
);
|
|
25
|
+
}
|