@openstack_dev/gatsby-theme-marketing-oif-core 1.0.12 → 1.0.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openstack_dev/gatsby-theme-marketing-oif-core",
3
- "version": "1.0.12",
3
+ "version": "1.0.13",
4
4
  "description": "Base theme for Marketing Sites",
5
5
  "author": "smarcet",
6
6
  "keywords": [
@@ -0,0 +1,145 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { navigate } from "gatsby";
4
+ import Box from "@mui/material/Box";
5
+ import Button from "@mui/material/Button";
6
+ import AddIcon from "@mui/icons-material/Add";
7
+ import RemoveIcon from "@mui/icons-material/Remove";
8
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
9
+
10
+ import styles from "../index.module.scss";
11
+
12
+ function AuthUserSubNavBar({
13
+ member,
14
+ isMobile,
15
+ navbarMenu,
16
+ setActiveMenu,
17
+ isSearchBarOpen,
18
+ handleNavigation,
19
+ }) {
20
+ const onClickLogout = () => {
21
+ navigate("/auth/logout", {
22
+ state: {
23
+ backUrl: window.location.pathname,
24
+ },
25
+ });
26
+ };
27
+
28
+ return isMobile ? (
29
+ <>
30
+ <Button
31
+ className={styles.mobileOption}
32
+ onClick={() => setActiveMenu("My Account")}
33
+ disableRipple
34
+ >
35
+ My Account
36
+ {navbarMenu === "My Account" ? (
37
+ <RemoveIcon aria-hidden="true" />
38
+ ) : (
39
+ <AddIcon aria-hidden="true" />
40
+ )}
41
+ </Button>
42
+ {navbarMenu === "My Account" && (
43
+ <Box className={styles.mobileDropdownMenu}>
44
+ <Button
45
+ className={styles.mobileDropdownOption}
46
+ onClick={() => handleNavigation("/profile/")}
47
+ sx={{ display: "block" }}
48
+ disableRipple
49
+ >
50
+ Edit Profile
51
+ </Button>
52
+ <Button
53
+ className={styles.mobileDropdownOption}
54
+ onClick={() => handleNavigation(
55
+ `/community/members/profile/${
56
+ member.id
57
+ }/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
58
+ )}
59
+ sx={{ display: "block" }}
60
+ disableRipple
61
+ >
62
+ View Public Profile
63
+ </Button>
64
+ <div className={styles.divider} />
65
+ <Button
66
+ className={styles.mobileDropdownOption}
67
+ sx={{ display: "block" }}
68
+ onClick={onClickLogout}
69
+ disableRipple
70
+ >
71
+ Log out
72
+ </Button>
73
+ </Box>
74
+ )}
75
+ </>
76
+ ) : (
77
+ <Box
78
+ maxWidth="15%"
79
+ sx={{
80
+ display: {
81
+ xs: "none",
82
+ md: isSearchBarOpen ? "none" : "flex",
83
+ },
84
+ justifyContent: "flex-end",
85
+ marginLeft: "auto",
86
+ }}
87
+ >
88
+ <Box
89
+ className={`${styles.navbarOption}`}
90
+ sx={{ my: 2, display: "block" }}
91
+ >
92
+ My Account
93
+ <ArrowDropDownIcon className={styles.arrowDownIcon} />
94
+ <Box className={styles.dropDownMenu}>
95
+ <Button
96
+ className={styles.dropdownMenuOption}
97
+ onClick={() => handleNavigation("/profile/")}
98
+ sx={{ display: "block" }}
99
+ disableRipple
100
+ >
101
+ Edit Profile
102
+ </Button>
103
+ <Button
104
+ className={styles.dropdownMenuOption}
105
+ onClick={() => handleNavigation(
106
+ `/community/members/profile/${
107
+ member.id
108
+ }/${`${member.first_name.toLowerCase()}-${member.last_name.toLowerCase()}`}`,
109
+ )}
110
+ sx={{ display: "block" }}
111
+ disableRipple
112
+ >
113
+ View Public Profile
114
+ </Button>
115
+ <div className={styles.divider} />
116
+ <Button
117
+ className={styles.dropdownMenuOption}
118
+ sx={{ display: "block" }}
119
+ onClick={onClickLogout}
120
+ disableRipple
121
+ >
122
+ Log out
123
+ </Button>
124
+ </Box>
125
+ </Box>
126
+ </Box>
127
+ );
128
+ }
129
+
130
+ AuthUserSubNavBar.propTypes = {
131
+ member: PropTypes.oneOfType([PropTypes.object, PropTypes.oneOf([null])]),
132
+ isMobile: PropTypes.bool.isRequired,
133
+ navbarMenu: PropTypes.string.isRequired,
134
+ setActiveMenu: PropTypes.func,
135
+ isSearchBarOpen: PropTypes.bool,
136
+ handleNavigation: PropTypes.func.isRequired,
137
+ };
138
+
139
+ AuthUserSubNavBar.defaultProps = {
140
+ member: null,
141
+ isSearchBarOpen: false,
142
+ setActiveMenu: (option) => console.log(option),
143
+ };
144
+
145
+ export default AuthUserSubNavBar;
@@ -0,0 +1,29 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import { doLogin } from "openstack-uicore-foundation/lib/security/methods";
4
+ import Button from "@mui/material/Button";
5
+
6
+ import styles from "../index.module.scss";
7
+
8
+ function LoginButton({ backUrl }) {
9
+ return (
10
+ <Button
11
+ className={`${styles.navbarOption} ${styles.login}`}
12
+ onClick={() => doLogin(backUrl)}
13
+ sx={{ my: 2, display: "block" }}
14
+ disableRipple
15
+ >
16
+ Log in
17
+ </Button>
18
+ );
19
+ }
20
+
21
+ LoginButton.propTypes = {
22
+ backUrl: PropTypes.string,
23
+ };
24
+
25
+ LoginButton.defaultProps = {
26
+ backUrl: "/",
27
+ };
28
+
29
+ export default LoginButton;
@@ -0,0 +1,34 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Box from "@mui/material/Box";
4
+ import IconButton from "@mui/material/IconButton";
5
+ import MenuIcon from "@mui/icons-material/Menu";
6
+
7
+ import styles from "./index.module.scss";
8
+
9
+ function MobileMenu({ handleMobileMenuToggle }) {
10
+ return (
11
+ <Box
12
+ className={styles.mobileMenuWrapper}
13
+ sx={{ flexGrow: 1, display: { xs: "flex", md: "none" } }}
14
+ >
15
+ <IconButton
16
+ className={styles.toggleIcon}
17
+ size="large"
18
+ aria-label="account of current user"
19
+ aria-controls="menu-appbar"
20
+ aria-haspopup="true"
21
+ onClick={() => handleMobileMenuToggle()}
22
+ color="inherit"
23
+ >
24
+ <MenuIcon />
25
+ </IconButton>
26
+ </Box>
27
+ );
28
+ }
29
+
30
+ MobileMenu.propTypes = {
31
+ handleMobileMenuToggle: PropTypes.func.isRequired,
32
+ };
33
+
34
+ export default MobileMenu;
@@ -0,0 +1,9 @@
1
+ .mobileMenuWrapper {
2
+ .toggleIcon {
3
+ color: #5a5a5a;
4
+ margin-left: auto;
5
+ &:hover {
6
+ background-color: transparent;
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,47 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Box from "@mui/material/Box";
4
+ import Button from "@mui/material/Button";
5
+
6
+ import styles from "../index.module.scss";
7
+
8
+ function NavBarDropDown({ isMobile, items, handleNavigation }) {
9
+ return (
10
+ <Box className={isMobile ? styles.mobileDropdownMenu : styles.dropDownMenu}>
11
+ {items.map((subItem) => (!subItem.title && !subItem.link ? (
12
+ <div className={styles.divider} key={subItem.title} />
13
+ ) : (
14
+ <Button
15
+ className={
16
+ isMobile ? styles.mobileDropdownOption : styles.dropdownMenuOption
17
+ }
18
+ key={isMobile ? `${subItem.title}-mobile` : subItem.title}
19
+ onClick={(ev) => handleNavigation(ev, subItem.link)}
20
+ sx={{ display: "block" }}
21
+ disableRipple
22
+ >
23
+ {subItem.title}
24
+ </Button>
25
+ )))}
26
+ </Box>
27
+ );
28
+ }
29
+
30
+ NavBarDropDown.propTypes = {
31
+ isMobile: PropTypes.bool,
32
+ items: PropTypes.arrayOf(
33
+ PropTypes.shape({
34
+ link: PropTypes.string,
35
+ title: PropTypes.string,
36
+ display: PropTypes.bool,
37
+ requiresAuth: PropTypes.bool,
38
+ }),
39
+ ).isRequired,
40
+ handleNavigation: PropTypes.func.isRequired,
41
+ };
42
+
43
+ NavBarDropDown.defaultProps = {
44
+ isMobile: false,
45
+ };
46
+
47
+ export default NavBarDropDown;
@@ -0,0 +1,28 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Box from "@mui/material/Box";
4
+
5
+ import styles from "./index.module.scss";
6
+ import SearchBar from "../SearchBar";
7
+
8
+ function NavBarHeader({ setIsSearchBarOpen }) {
9
+ return (
10
+ <Box className={styles.navbarHeader}>
11
+ <div className={styles.brandWrapper}>
12
+ <a
13
+ className={styles.navbarBrand}
14
+ href="/"
15
+ alt="Openstack logo"
16
+ aria-label="Go to homepage"
17
+ />
18
+ </div>
19
+ <SearchBar onSearchBarOpen={(value) => setIsSearchBarOpen(value)} />
20
+ </Box>
21
+ );
22
+ }
23
+
24
+ NavBarHeader.propTypes = {
25
+ setIsSearchBarOpen: PropTypes.func.isRequired,
26
+ };
27
+
28
+ export default NavBarHeader;
@@ -0,0 +1,55 @@
1
+ .navbarHeader {
2
+ .brandWrapper {
3
+ margin: 10px 0;
4
+ padding-right: 20px;
5
+ float: left;
6
+ border-right: 1px solid #eee;
7
+ min-width: 135px;
8
+ a.navbarBrand {
9
+ background: url("../../../images/openstack-logo-full.svg") left no-repeat;
10
+ height: 35px;
11
+ width: 135px;
12
+ color: #777;
13
+ padding: 15px 15px;
14
+ font-size: 18px;
15
+ line-height: 20px;
16
+ display: block;
17
+ }
18
+ }
19
+ .navbarToggle {
20
+ appearance: button;
21
+ cursor: pointer;
22
+ position: relative;
23
+ float: right;
24
+ padding: 9px 10px;
25
+ margin-top: 8px;
26
+ margin-bottom: 8px;
27
+ background: transparent;
28
+ border: none;
29
+ .iconBar {
30
+ background-color: #5a5a5a;
31
+ height: 3px;
32
+ border-radius: 3px;
33
+ display: block;
34
+ width: 22px;
35
+ margin-top: 4px;
36
+ }
37
+ @media (min-width: 768px) {
38
+ display: none;
39
+ }
40
+ }
41
+ @media (min-width: 768px) and (max-width: 1310px) {
42
+ .brandWrapper {
43
+ width: 75px;
44
+ min-width: 75px;
45
+ margin-top: 0;
46
+ a.navbarBrand {
47
+ background: url("../../../images/openstack-logo-vert.svg") left
48
+ no-repeat;
49
+ margin-left: 0px !important;
50
+ height: 54px;
51
+ width: 59px;
52
+ }
53
+ }
54
+ }
55
+ }
@@ -0,0 +1,92 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Button from "@mui/material/Button";
4
+ import AddIcon from "@mui/icons-material/Add";
5
+ import RemoveIcon from "@mui/icons-material/Remove";
6
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
7
+ import NavBarDropDown from "../NavBarDropDown";
8
+ import Link from "../../Link";
9
+
10
+ import styles from "../index.module.scss";
11
+
12
+ function NavBarItem({
13
+ isMobile,
14
+ item,
15
+ navbarMenu,
16
+ setActiveMenu,
17
+ handleNavigation,
18
+ }) {
19
+ return isMobile ? (
20
+ <>
21
+ <Button
22
+ disableRipple
23
+ className={styles.mobileOption}
24
+ key={`${item.title}-mobile`}
25
+ onClick={() => setActiveMenu(item.title)}
26
+ >
27
+ {item.title}
28
+ {item.items?.length > 0
29
+ && (item.title === navbarMenu ? (
30
+ <RemoveIcon aria-hidden="true" />
31
+ ) : (
32
+ <AddIcon aria-hidden="true" />
33
+ ))}
34
+ </Button>
35
+ {item.items?.length > 0 && item.title === navbarMenu && (
36
+ <NavBarDropDown
37
+ items={item.items}
38
+ handleNavigation={handleNavigation}
39
+ isMobile
40
+ />
41
+ )}
42
+ </>
43
+ ) : (
44
+ <Link
45
+ className={styles.navbarOption}
46
+ key={item.title}
47
+ sx={{ my: 2, display: "block" }}
48
+ href={item.link}
49
+ >
50
+ {item.items?.length > 0 ? (
51
+ <>
52
+ {item.title}
53
+ <ArrowDropDownIcon className={styles.arrowDownIcon} />
54
+ <NavBarDropDown
55
+ items={item.items}
56
+ handleNavigation={handleNavigation}
57
+ />
58
+ </>
59
+ ) : (
60
+ item.title
61
+ )}
62
+ </Link>
63
+ );
64
+ }
65
+
66
+ NavBarItem.propTypes = {
67
+ isMobile: PropTypes.bool,
68
+ item: PropTypes.shape({
69
+ title: PropTypes.string,
70
+ link: PropTypes.string,
71
+ display: PropTypes.bool,
72
+ requiresAuth: PropTypes.bool,
73
+ items: PropTypes.arrayOf(
74
+ PropTypes.shape({
75
+ link: PropTypes.string,
76
+ title: PropTypes.string,
77
+ display: PropTypes.bool,
78
+ requiresAuth: PropTypes.bool,
79
+ }),
80
+ ),
81
+ }),
82
+ navbarMenu: PropTypes.string.isRequired,
83
+ setActiveMenu: PropTypes.func,
84
+ handleNavigation: PropTypes.func.isRequired,
85
+ };
86
+
87
+ NavBarItem.defaultProps = {
88
+ isMobile: false,
89
+ setActiveMenu: (option) => console.log(option),
90
+ };
91
+
92
+ export default NavBarItem;
@@ -0,0 +1,83 @@
1
+ import * as React from "react";
2
+ import PropTypes from "prop-types";
3
+ import Box from "@mui/material/Box";
4
+ import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
5
+ import LoginButton from "../LoginButton";
6
+ import NavBarDropDown from "../NavBarDropDown";
7
+
8
+ import styles from "../index.module.scss";
9
+
10
+ function PublicUserSubNavBar({ isSearchBarOpen, isDesktop, handleNavigation }) {
11
+ const publicNavbarMenu = [
12
+ {
13
+ link: "https://openinfra.dev/join",
14
+ title: "Sign up for Foundation Membership",
15
+ display: true,
16
+ requiresAuth: false,
17
+ },
18
+ {
19
+ link: "https://openinfra.dev/join",
20
+ title: "Sponsor the Foundation",
21
+ display: true,
22
+ requiresAuth: false,
23
+ },
24
+ {
25
+ link: "https://openinfra.dev",
26
+ title: "More about the Foundation",
27
+ display: true,
28
+ requiresAuth: false,
29
+ },
30
+ ];
31
+
32
+ const getBackURL = () => {
33
+ let backUrl = "/";
34
+ if (window && typeof window !== "undefined") {
35
+ backUrl = window.location.pathname;
36
+ }
37
+ return backUrl;
38
+ };
39
+
40
+ return (
41
+ <Box
42
+ maxWidth={isDesktop ? "15%" : "100px"}
43
+ sx={
44
+ isDesktop
45
+ ? {
46
+ display: {
47
+ xs: "none",
48
+ md: isSearchBarOpen ? "none" : "flex",
49
+ },
50
+ justifyContent: "flex-end",
51
+ marginLeft: "auto",
52
+ }
53
+ : {}
54
+ }
55
+ >
56
+ <Box
57
+ className={`${styles.navbarOption} ${styles.join}`}
58
+ sx={{ my: 2, display: "block" }}
59
+ >
60
+ Join
61
+ <ArrowDropDownIcon className={styles.arrowDownIcon} />
62
+ <NavBarDropDown
63
+ items={publicNavbarMenu}
64
+ handleNavigation={handleNavigation}
65
+ />
66
+ </Box>
67
+ <LoginButton backUrl={getBackURL()} />
68
+ </Box>
69
+ );
70
+ }
71
+
72
+ PublicUserSubNavBar.propTypes = {
73
+ isSearchBarOpen: PropTypes.bool,
74
+ isDesktop: PropTypes.bool,
75
+ handleNavigation: PropTypes.func.isRequired,
76
+ };
77
+
78
+ PublicUserSubNavBar.defaultProps = {
79
+ isSearchBarOpen: false,
80
+ isDesktop: false,
81
+ };
82
+
83
+ export default PublicUserSubNavBar;
@@ -0,0 +1,108 @@
1
+ import * as React from "react";
2
+ import { Script } from "gatsby";
3
+ import PropTypes from "prop-types";
4
+ import Box from "@mui/material/Box";
5
+ import SearchIcon from "@mui/icons-material/Search";
6
+
7
+ import {
8
+ SEARCH_WIDGET_BASE_URL,
9
+ getEnvVariable,
10
+ } from "../../../utils/envVariables";
11
+
12
+ import styles from "./index.module.scss";
13
+
14
+ function SearchBar({ isMobile, isMobileMenuOpen, onSearchBarOpen }) {
15
+ const [isSearchBarOpen, setIsSearchBarOpen] = React.useState(false);
16
+
17
+ const handleSearchBarOpenClose = (value) => {
18
+ onSearchBarOpen(value);
19
+ setIsSearchBarOpen(value);
20
+ };
21
+
22
+ const handleCloseSearchBar = (event) => {
23
+ if (event?.target.matches(".ossw-search-bar-close")) {
24
+ handleSearchBarOpenClose(false);
25
+ }
26
+ };
27
+
28
+ React.useEffect(() => {
29
+ document.addEventListener("click", handleCloseSearchBar);
30
+ return () => {
31
+ document.removeEventListener("click", handleCloseSearchBar);
32
+ };
33
+ }, []);
34
+
35
+ React.useEffect(() => {
36
+ if (isSearchBarOpen) {
37
+ const inputElement = document.getElementById("search-bar-input");
38
+ if (inputElement) {
39
+ inputElement.focus();
40
+ }
41
+ }
42
+ }, [isSearchBarOpen]);
43
+
44
+ return (
45
+ <>
46
+ <Script
47
+ src={`${getEnvVariable(SEARCH_WIDGET_BASE_URL)}/widget/embed.min.js`}
48
+ />
49
+ {isMobile ? (
50
+ <Box
51
+ className={`${styles.openstackSearchBarMobile} openstack-search-bar ossw-mobile`}
52
+ sx={{
53
+ visibility: {
54
+ xs: isMobileMenuOpen ? "visible" : "hidden",
55
+ md: "hidden",
56
+ },
57
+ opacity: { xs: isMobileMenuOpen ? "1" : "0", md: "0" },
58
+ height: { xs: isMobileMenuOpen ? "auto" : 0, md: 0 },
59
+ color: "#8a959e",
60
+ }}
61
+ data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
62
+ data-context="www-openstack"
63
+ />
64
+ ) : (
65
+ <Box
66
+ className={styles.searchWrapper}
67
+ sx={{ display: { xs: "none", md: "flex" } }}
68
+ >
69
+ <div
70
+ role="button"
71
+ tabIndex={0}
72
+ onKeyDown={(event) => {
73
+ if (event.key === "Enter" || event.key === " ") handleSearchBarOpenClose(true);
74
+ }}
75
+ onClick={() => handleSearchBarOpenClose(true)}
76
+ className={styles.searchComponent}
77
+ >
78
+ <SearchIcon className={styles.searchIcon} />
79
+ <span className={styles.headerSearchText}>Search</span>
80
+ </div>
81
+ <Box
82
+ className={`openstack-search-bar ${styles.openstackSearchBar}`}
83
+ style={{
84
+ visibility: isSearchBarOpen ? "visible" : "hidden",
85
+ opacity: isSearchBarOpen ? "1" : "0",
86
+ }}
87
+ data-baseurl={getEnvVariable(SEARCH_WIDGET_BASE_URL)}
88
+ data-context="www-openstack"
89
+ />
90
+ </Box>
91
+ )}
92
+ </>
93
+ );
94
+ }
95
+
96
+ SearchBar.propTypes = {
97
+ isMobile: PropTypes.bool,
98
+ isMobileMenuOpen: PropTypes.bool,
99
+ onSearchBarOpen: PropTypes.func,
100
+ };
101
+
102
+ SearchBar.defaultProps = {
103
+ isMobile: false,
104
+ isMobileMenuOpen: false,
105
+ onSearchBarOpen: () => null,
106
+ };
107
+
108
+ export default SearchBar;
@@ -0,0 +1,43 @@
1
+ .searchWrapper {
2
+ padding: 20px 0px 15px 20px;
3
+ float: left;
4
+ text-transform: uppercase;
5
+ color: #8a959e;
6
+ font-size: 12px;
7
+ font-weight: 400;
8
+ line-height: 17.15px;
9
+ .searchComponent {
10
+ cursor: pointer;
11
+ z-index: 5;
12
+ position: relative;
13
+ .searchIcon {
14
+ width: 12px;
15
+ height: 12px;
16
+ line-height: 12px;
17
+ margin-right: 5px;
18
+ }
19
+ }
20
+ .openstackSearchBar {
21
+ width: 100%;
22
+ position: absolute;
23
+ top: 0;
24
+ z-index: 100;
25
+ height: 70px;
26
+ padding-top: 10px;
27
+ padding-right: 12%;
28
+ background-color: #fff;
29
+ opacity: 0;
30
+ transition: opacity 0.3s ease;
31
+ }
32
+ @media (max-width: 768px) {
33
+ display: none;
34
+ }
35
+ @media (max-width: 1160px) {
36
+ .headerSearchText {
37
+ display: none;
38
+ }
39
+ }
40
+ @media (min-width: 768px) and (max-width: 1310px) {
41
+ padding: 25px 0px 15px 20px;
42
+ }
43
+ }