@punch-in/strapi-admin 1.2.1 → 1.2.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/admin/src/app.js
CHANGED
|
@@ -55,6 +55,65 @@ import history from './utils/history';
|
|
|
55
55
|
|
|
56
56
|
import plugins from './plugins';
|
|
57
57
|
|
|
58
|
+
// Retry on 504 (Gateway Timeout): the tenant Lambda backends occasionally hit
|
|
59
|
+
// a concurrent cold-start race (multiple containers contending for the same
|
|
60
|
+
// SQLite file - SQLITE_BUSY) where the Lambda crashes before doing any work
|
|
61
|
+
// at all, surfaced to the browser as a 504. That's almost always transient -
|
|
62
|
+
// a follow-up request a few seconds later succeeds once one container wins.
|
|
63
|
+
//
|
|
64
|
+
// Also retries on a *rejected* fetch, not just a resolved 504: API Gateway's
|
|
65
|
+
// own gateway-generated error responses (this same 504, plus throttles etc.)
|
|
66
|
+
// never reach Strapi, so its CORS middleware never adds the usual headers -
|
|
67
|
+
// the browser then discards the cross-origin response as a CORS failure and
|
|
68
|
+
// fetch() rejects instead of resolving with the status code, invisible to
|
|
69
|
+
// the `response.status === 504` check below. (The per-tenant CloudFormation
|
|
70
|
+
// template's GatewayResponseDefault4xx/5xx now add a CORS header to those
|
|
71
|
+
// gateway-generated responses too, so this should mostly stop happening -
|
|
72
|
+
// this is a second, independent safety net for whatever slips through, e.g.
|
|
73
|
+
// a genuinely dropped connection that never got any response to add headers
|
|
74
|
+
// to in the first place.)
|
|
75
|
+
//
|
|
76
|
+
// Installed once, globally, here at the app's entry point (before anything
|
|
77
|
+
// else runs) rather than inside strapi-helper-plugin's request() - that
|
|
78
|
+
// package only ships a prebuilt dist bundle with no source to patch, and
|
|
79
|
+
// request() calls window.fetch directly, so wrapping fetch here covers every
|
|
80
|
+
// request() call (and any other direct fetch caller) with zero changes to
|
|
81
|
+
// strapi-helper-plugin or any of its hundreds of call sites.
|
|
82
|
+
//
|
|
83
|
+
// Note: this retries every method, including POST/PUT/DELETE. A 504 (or a
|
|
84
|
+
// rejected fetch) here has only ever been observed as "the Lambda crashed
|
|
85
|
+
// before it did anything" (see above), not "the write succeeded but the
|
|
86
|
+
// response was lost" - but that's this app's specific failure mode, not a
|
|
87
|
+
// general guarantee, so it's worth knowing if this ever gets reused
|
|
88
|
+
// somewhere with different backend behavior.
|
|
89
|
+
const RETRY_DELAYS_MS = [2000, 4000, 8000];
|
|
90
|
+
const nativeFetch = window.fetch.bind(window);
|
|
91
|
+
|
|
92
|
+
const attemptFetch = (...args) =>
|
|
93
|
+
nativeFetch(...args).then(
|
|
94
|
+
response => ({ response }),
|
|
95
|
+
error => ({ error })
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
window.fetch = async (...args) => {
|
|
99
|
+
let { response, error } = await attemptFetch(...args);
|
|
100
|
+
|
|
101
|
+
for (
|
|
102
|
+
let i = 0;
|
|
103
|
+
(error || response.status === 504) && i < RETRY_DELAYS_MS.length;
|
|
104
|
+
i += 1
|
|
105
|
+
) {
|
|
106
|
+
await new Promise(resolve => setTimeout(resolve, RETRY_DELAYS_MS[i]));
|
|
107
|
+
({ response, error } = await attemptFetch(...args));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (error) {
|
|
111
|
+
throw error;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return response;
|
|
115
|
+
};
|
|
116
|
+
|
|
58
117
|
const strapi = Strapi();
|
|
59
118
|
|
|
60
119
|
const pluginsReducers = {};
|
|
@@ -11,7 +11,10 @@ const NavTopRightWrapper = styled.div`
|
|
|
11
11
|
justify-content: space-between;
|
|
12
12
|
align-items: center;
|
|
13
13
|
box-shadow: 0 6px 18px #002f5f52;
|
|
14
|
-
z-index:
|
|
14
|
+
/* Must outrank .adminPageRightWrapper (z-index: 5, see containers/Admin/Wrapper.js) and
|
|
15
|
+
the LeftMenu sidebar (z-index: 10) - otherwise the Logout dropdown menu that pops out
|
|
16
|
+
of this bar renders underneath the main content area and is invisible/unclickable. */
|
|
17
|
+
z-index: 15;
|
|
15
18
|
`;
|
|
16
19
|
|
|
17
20
|
export default NavTopRightWrapper;
|
|
@@ -64,9 +64,25 @@ const Wrapper = styled.div`
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
.dropDownContent {
|
|
67
|
-
z-index
|
|
68
|
-
|
|
67
|
+
/* Was 8 - lower than LeftMenu's sidebar (z-index 10) and even this
|
|
68
|
+
component's own toggle button (z-index 9 above), so the open dropdown
|
|
69
|
+
could render underneath either. The earlier fix (3bc5191a) raised the
|
|
70
|
+
outer NavTopRightWrapper to 15 to outrank the sidebar but missed this
|
|
71
|
+
nested value. */
|
|
72
|
+
z-index: 1000;
|
|
73
|
+
/* Popper.js (v1, via reactstrap 8's react-popper) computes a broken
|
|
74
|
+
translate3d offset for this toggle - even after disabling its flip
|
|
75
|
+
modifier and trying positionFixed, it still placed the menu at
|
|
76
|
+
negative Y (off-screen above the viewport) or off to the right past
|
|
77
|
+
the viewport edge. Forcing static positioning here overrides Popper's
|
|
78
|
+
inline transform/position outright: the menu just hangs directly
|
|
79
|
+
below its toggle button, which is all this fixed, always-in-the-
|
|
80
|
+
same-spot navbar dropdown ever needs. */
|
|
81
|
+
position: absolute !important;
|
|
82
|
+
transform: none !important;
|
|
83
|
+
top: 100% !important;
|
|
69
84
|
left: auto !important;
|
|
85
|
+
right: 0 !important;
|
|
70
86
|
min-width: 190px;
|
|
71
87
|
margin: 0 !important;
|
|
72
88
|
padding: 0;
|
|
@@ -38,12 +38,21 @@ const Logout = ({ history: { push } }) => {
|
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<Wrapper>
|
|
41
|
-
<ButtonDropdown isOpen={isOpen} toggle={toggle}>
|
|
41
|
+
<ButtonDropdown isOpen={isOpen} toggle={toggle} direction="down">
|
|
42
42
|
<DropdownToggle>
|
|
43
43
|
{displayName}
|
|
44
44
|
<FontAwesomeIcon icon="caret-down" />
|
|
45
45
|
</DropdownToggle>
|
|
46
|
-
|
|
46
|
+
{/* flip={false}: this toggle lives in a position:fixed, top:0 navbar with
|
|
47
|
+
no room above it. Popper's flip modifier was misjudging available space
|
|
48
|
+
in that context and auto-flipping the menu to open upward, pushing it to
|
|
49
|
+
negative Y coordinates - technically "visible" (not display:none, correct
|
|
50
|
+
z-index) but rendered entirely off-screen above the viewport. Popper's
|
|
51
|
+
translate3d offset stayed wrong (and got worse under positionFixed) even
|
|
52
|
+
after this, so components.js also forces static CSS positioning below,
|
|
53
|
+
overriding Popper's transform outright rather than fighting its popper.js
|
|
54
|
+
v1 coordinate math in this nested-fixed-position navbar. */}
|
|
55
|
+
<DropdownMenu className="dropDownContent" flip={false}>
|
|
47
56
|
<DropdownItem onClick={handleGoToMe} className="item">
|
|
48
57
|
<FormattedMessage id="app.components.Logout.profile" />
|
|
49
58
|
</DropdownItem>
|
package/package.json
CHANGED