@openstack_dev/gatsby-theme-marketing-oif-core 1.0.35-beta.1 → 1.0.35-beta.3

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 CHANGED
@@ -1,3 +1,6 @@
1
- import { ReduxWrapperWithCacheProvider } from "./src/state/ReduxWrapper";
1
+ import React from "react";
2
+ import ReduxWrapper from "./src/state/ReduxWrapper";
2
3
 
3
- export const wrapRootElement = ReduxWrapperWithCacheProvider;
4
+ export const wrapRootElement = ({ element }) => (
5
+ <ReduxWrapper element={element} />
6
+ );
package/gatsby-ssr.js CHANGED
@@ -1,6 +1,7 @@
1
+ import React from "react";
1
2
  import { JSDOM } from "jsdom";
2
3
  import { XMLHttpRequest } from "xmlhttprequest";
3
- import { ReduxWrapper } from "./src/state/ReduxWrapper";
4
+ import ReduxWrapper from "./src/state/ReduxWrapper";
4
5
  import { HeadComponents } from "./src/components/head-components";
5
6
 
6
7
  export const onRenderBody = ({ setHeadComponents }) => {
@@ -9,7 +10,9 @@ export const onRenderBody = ({ setHeadComponents }) => {
9
10
  }
10
11
  };
11
12
 
12
- export const wrapRootElement = ReduxWrapper;
13
+ export const wrapRootElement = ({ element }) => (
14
+ <ReduxWrapper element={element} />
15
+ );
13
16
 
14
17
  // build enabler polyfills
15
18
  global.dom = new JSDOM("...");
@@ -19,7 +22,7 @@ global.navigator = global.window.navigator;
19
22
  global.window.matchMedia = () => ({
20
23
  matches: false,
21
24
  addListener: () => {},
22
- removeListener: () => {},
25
+ removeListener: () => {}
23
26
  });
24
27
 
25
28
  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.35-beta.1",
3
+ "version": "1.0.35-beta.3",
4
4
  "description": "Base theme for Marketing Sites",
5
5
  "author": "smarcet",
6
6
  "keywords": [
@@ -1,4 +1,4 @@
1
- import { useEffect } from "react";
1
+ import { useEffect, useRef } from "react";
2
2
  import { useSelector } from "react-redux";
3
3
  import { doLoginBasicLogin } from "openstack-uicore-foundation/lib/security/methods";
4
4
  import { getBackURL } from "../utils/url";
@@ -7,42 +7,45 @@ export default function AuthBootstrap() {
7
7
  const isLoggedUser = useSelector(
8
8
  (state) => state.loggedUserState.isLoggedUser
9
9
  );
10
+ const ranRef = useRef(false);
10
11
 
11
- const checkLoginStatus = async () => {
12
- try {
13
- const response = await fetch("/oidc/session/whoami", {
14
- method: "GET",
15
- credentials: "same-origin"
16
- });
12
+ useEffect(() => {
13
+ // already ran
14
+ if (ranRef.current || isLoggedUser) return;
15
+ ranRef.current = true;
16
+
17
+ const controller = new AbortController();
18
+
19
+ const run = async () => {
20
+ try {
21
+ const response = await fetch("/oidc/session/whoami", {
22
+ method: "GET",
23
+ credentials: "same-origin",
24
+ signal: controller.signal
25
+ });
26
+
27
+ if (!response.ok) return;
17
28
 
18
- if (response.ok) {
19
29
  const data = await response.json();
20
- if (
21
- data.email &&
22
- typeof data.email === "string" &&
23
- /\S+@\S+\.\S+/.test(data.email)
24
- ) {
25
- doLoginBasicLogin(getBackURL(), data.email);
26
- } else {
27
- console.warn(
28
- "Invalid or missing email in login response:",
29
- data.email
30
- );
30
+ const email = data?.email;
31
+
32
+ if (typeof email === "string" && /\S+@\S+\.\S+/.test(email)) {
33
+ doLoginBasicLogin(getBackURL(), email);
31
34
  }
32
- }
33
- } catch (error) {
34
- console.error(
35
- "Failed to check login status. Possible network error or invalid response.",
36
- {
37
- error,
38
- attemptedUrl: "/oidc/session/whoami"
35
+ } catch (err) {
36
+ if (err?.name !== "AbortError") {
37
+ console.error("AuthBootstrap whoami failed", err);
39
38
  }
40
- );
39
+ }
40
+ };
41
+
42
+ if (typeof window !== "undefined" && "requestIdleCallback" in window) {
43
+ window.requestIdleCallback(run, { timeout: 1000 });
44
+ } else {
45
+ setTimeout(run, 0);
41
46
  }
42
- };
43
47
 
44
- useEffect(() => {
45
- if (!isLoggedUser) checkLoginStatus();
48
+ return () => controller.abort();
46
49
  }, [isLoggedUser]);
47
50
 
48
51
  return null;
@@ -1,28 +1,33 @@
1
- import * as React from "react";
1
+ import React from "react";
2
2
  import { Provider } from "react-redux";
3
3
  import { PersistGate } from "redux-persist/integration/react";
4
4
  import { CacheProvider } from "@emotion/react";
5
+
5
6
  import { store, persistor } from "./store";
6
7
  import createEmotionCache from "../utils/createEmotionCache";
7
8
  import AuthBootstrap from "../components/AuthBootstrap";
8
9
 
9
- export function ReduxWrapper({ element }) {
10
- return (
11
- <Provider store={store}>
12
- <PersistGate persistor={persistor}>{() => element}</PersistGate>
13
- </Provider>
14
- );
15
- }
10
+ const isBrowser = typeof window !== "undefined";
11
+
12
+ const ReduxWrapper = ({ element }) => {
13
+ const cache = createEmotionCache(); // sin hooks: SSR safe
16
14
 
17
- export function ReduxWrapperWithCacheProvider({ element }) {
18
- const cacheRef = React.useRef(null);
19
- if (!cacheRef.current) cacheRef.current = createEmotionCache();
20
15
  return (
21
- <CacheProvider value={cacheRef.current}>
16
+ <CacheProvider value={cache}>
22
17
  <Provider store={store}>
23
- <AuthBootstrap />
24
- <PersistGate persistor={persistor}>{() => element}</PersistGate>
18
+ {isBrowser && persistor ? (
19
+ <PersistGate persistor={persistor} loading={element}>
20
+ <>
21
+ <AuthBootstrap />
22
+ {element}
23
+ </>
24
+ </PersistGate>
25
+ ) : (
26
+ // SSR
27
+ element
28
+ )}
25
29
  </Provider>
26
30
  </CacheProvider>
27
31
  );
28
- }
32
+ };
33
+ export default ReduxWrapper;
@@ -1,10 +1,20 @@
1
1
  import { applyMiddleware, compose, createStore } from "redux";
2
2
  import { persistCombineReducers, persistStore } from "redux-persist";
3
- import storage from "redux-persist/lib/storage";
4
3
  import thunk from "redux-thunk";
5
-
6
4
  import * as reducers from "../reducers";
7
5
 
6
+ const isBrowser = typeof window !== "undefined";
7
+
8
+ const createNoopStorage = () => ({
9
+ getItem: () => Promise.resolve(null),
10
+ setItem: () => Promise.resolve(),
11
+ removeItem: () => Promise.resolve()
12
+ });
13
+
14
+ const storage = isBrowser
15
+ ? require("redux-persist/lib/storage").default
16
+ : createNoopStorage();
17
+
8
18
  // Get from process.env because window is not set yet
9
19
  const clientId = process.env.GATSBY_OAUTH2_CLIENT_ID;
10
20
 
@@ -14,16 +24,17 @@ const config = {
14
24
  blacklist: [
15
25
  // this will be not saved to persistent storage see
16
26
  // https://github.com/rt2zz/redux-persist#blacklist--whitelist
17
- ],
27
+ ]
18
28
  };
19
29
 
20
30
  const states = {
21
- loggedUserState: reducers.loggedUserReducer,
31
+ loggedUserState: reducers.loggedUserReducer
22
32
  };
23
33
 
24
- const composeEnhancers = typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
25
- ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
26
- : compose;
34
+ const composeEnhancers =
35
+ typeof window === "object" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
36
+ ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
37
+ : compose;
27
38
 
28
39
  const enhancer = composeEnhancers(applyMiddleware(thunk));
29
40
 
@@ -33,7 +44,9 @@ export const { store, persistor } = (() => {
33
44
 
34
45
  const store = createStore(persistedReducers, enhancer);
35
46
  const onRehydrateComplete = () => {};
36
- const persistor = persistStore(store, null, onRehydrateComplete);
47
+ const persistor = isBrowser
48
+ ? persistStore(store, null, onRehydrateComplete)
49
+ : null;
37
50
 
38
51
  return { store, persistor };
39
52
  })();