redux-connected-devtools 1.0.2 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. package/dist/components/DevInspector/DevInspector.js +12 -0
  2. package/{src/components/DevInspector/DevInspector.style.tsx → dist/components/DevInspector/DevInspector.style.js} +1 -3
  3. package/dist/components/DevList/DevList.js +24 -0
  4. package/{src/components/DevList/DevList.style.tsx → dist/components/DevList/DevList.style.js} +2 -4
  5. package/dist/components/DevMenu/DevMenu.js +25 -0
  6. package/{src/components/DevMenu/DevMenu.style.tsx → dist/components/DevMenu/DevMenu.style.js} +15 -19
  7. package/dist/components/DevPanel/DevPanel.js +38 -0
  8. package/dist/components/DevPanel/DevPanel.style.js +22 -0
  9. package/dist/components/DevtoolsApp/DevtoolsApp.js +17 -0
  10. package/dist/components/DevtoolsApp/DevtoolsApp.style.js +11 -0
  11. package/dist/components/Icon/AllIcons.js +18 -0
  12. package/dist/components/Icon/Icon.js +9 -0
  13. package/dist/components/Icon/Icon.style.js +10 -0
  14. package/{src/components/JourneyRow/JourneyRow.tsx → dist/components/JourneyRow/JourneyRow.js} +9 -32
  15. package/{src/components/JourneyRow/JourneyRow.style.tsx → dist/components/JourneyRow/JourneyRow.style.js} +7 -12
  16. package/dist/components/JsonViewer/JsonViewer.js +7 -0
  17. package/{src/components/JsonViewer/JsonViewer.style.tsx → dist/components/JsonViewer/JsonViewer.style.js} +1 -2
  18. package/dist/components/Lifecycle/Lifecycle.js +15 -0
  19. package/{src/components/Lifecycle/Lifecycle.style.tsx → dist/components/Lifecycle/Lifecycle.style.js} +1 -2
  20. package/dist/components/RequestDetails/RequestDetails.js +10 -0
  21. package/dist/components/RequestDetails/RequestDetails.style.js +16 -0
  22. package/dist/components/RequestJourney/RequestJourney.js +14 -0
  23. package/dist/components/RequestJourney/RequestJourney.style.js +26 -0
  24. package/dist/components/RequestRow/RequestRow.js +9 -0
  25. package/{src/components/RequestRow/RequestRow.style.tsx → dist/components/RequestRow/RequestRow.style.js} +6 -10
  26. package/dist/components/Size/Size.js +10 -0
  27. package/dist/components/Size/Size.style.js +5 -0
  28. package/{src/components/Time/Time.tsx → dist/components/Time/Time.js} +3 -17
  29. package/{src/components/Time/Time.style.tsx → dist/components/Time/Time.style.js} +4 -7
  30. package/dist/containers/DevMenuContainer.js +11 -0
  31. package/dist/containers/DevPanelContainer.js +6 -0
  32. package/dist/containers/DevtoolsAppContainer.js +24 -0
  33. package/{src/containers/EndpointConfigsContainer.tsx → dist/containers/EndpointConfigsContainer.js} +2 -5
  34. package/{src/containers/EndpointStatusContainer.tsx → dist/containers/EndpointStatusContainer.js} +2 -5
  35. package/{src/containers/GlobalSettingsContainer.tsx → dist/containers/GlobalSettingsContainer.js} +2 -5
  36. package/{src/containers/GlobalStatsContainer.tsx → dist/containers/GlobalStatsContainer.js} +2 -5
  37. package/{src/containers/LifecycleApiErrorContainer.tsx → dist/containers/LifecycleApiErrorContainer.js} +2 -4
  38. package/dist/containers/LifecycleFailedContainer.js +9 -0
  39. package/{src/containers/LifecycleGeneralErrorContainer.tsx → dist/containers/LifecycleGeneralErrorContainer.js} +2 -4
  40. package/{src/containers/LifecycleInQueueContainer.tsx → dist/containers/LifecycleInQueueContainer.js} +2 -4
  41. package/{src/containers/LifecyclePendingApiContainer.tsx → dist/containers/LifecyclePendingApiContainer.js} +2 -4
  42. package/{src/containers/LifecyclePostActionContainer.tsx → dist/containers/LifecyclePostActionContainer.js} +2 -4
  43. package/{src/containers/LifecycleReceivedContainer.tsx → dist/containers/LifecycleReceivedContainer.js} +2 -4
  44. package/{src/data/devComponents.tsx → dist/data/devComponents.js} +3 -4
  45. package/{src/data/devRoutes.ts → dist/data/devRoutes.js} +23 -28
  46. package/dist/dts/components/DevInspector/DevInspector.d.ts +7 -0
  47. package/dist/dts/components/DevInspector/DevInspector.style.d.ts +1 -0
  48. package/dist/dts/components/DevList/DevList.d.ts +9 -0
  49. package/dist/dts/components/DevList/DevList.style.d.ts +2 -0
  50. package/dist/dts/components/DevMenu/DevMenu.d.ts +12 -0
  51. package/dist/dts/components/DevMenu/DevMenu.style.d.ts +7 -0
  52. package/dist/dts/components/DevPanel/DevPanel.d.ts +6 -0
  53. package/dist/dts/components/DevPanel/DevPanel.style.d.ts +3 -0
  54. package/dist/dts/components/DevtoolsApp/DevtoolsApp.d.ts +10 -0
  55. package/dist/dts/components/DevtoolsApp/DevtoolsApp.style.d.ts +1 -0
  56. package/dist/dts/components/Icon/AllIcons.d.ts +8 -0
  57. package/dist/dts/components/Icon/Icon.d.ts +10 -0
  58. package/dist/dts/components/Icon/Icon.style.d.ts +3 -0
  59. package/dist/dts/components/JourneyRow/JourneyRow.d.ts +7 -0
  60. package/dist/dts/components/JourneyRow/JourneyRow.style.d.ts +5 -0
  61. package/dist/dts/components/JsonViewer/JsonViewer.d.ts +7 -0
  62. package/dist/dts/components/JsonViewer/JsonViewer.style.d.ts +3 -0
  63. package/dist/dts/components/Lifecycle/Lifecycle.d.ts +7 -0
  64. package/dist/dts/components/Lifecycle/Lifecycle.style.d.ts +1 -0
  65. package/dist/dts/components/RequestDetails/RequestDetails.d.ts +7 -0
  66. package/dist/dts/components/RequestDetails/RequestDetails.style.d.ts +4 -0
  67. package/dist/dts/components/RequestJourney/RequestJourney.d.ts +7 -0
  68. package/dist/dts/components/RequestJourney/RequestJourney.style.d.ts +1 -0
  69. package/dist/dts/components/RequestRow/RequestRow.d.ts +11 -0
  70. package/dist/dts/components/RequestRow/RequestRow.style.d.ts +6 -0
  71. package/dist/dts/components/Size/Size.d.ts +6 -0
  72. package/dist/dts/components/Size/Size.style.d.ts +1 -0
  73. package/dist/dts/components/Time/Time.d.ts +6 -0
  74. package/dist/dts/components/Time/Time.style.d.ts +3 -0
  75. package/dist/dts/containers/DevMenuContainer.d.ts +8 -0
  76. package/dist/dts/containers/DevPanelContainer.d.ts +6 -0
  77. package/dist/dts/containers/DevtoolsAppContainer.d.ts +7 -0
  78. package/dist/dts/containers/EndpointConfigsContainer.d.ts +3 -0
  79. package/dist/dts/containers/EndpointStatusContainer.d.ts +3 -0
  80. package/dist/dts/containers/GlobalSettingsContainer.d.ts +3 -0
  81. package/dist/dts/containers/GlobalStatsContainer.d.ts +3 -0
  82. package/dist/dts/containers/LifecycleApiErrorContainer.d.ts +3 -0
  83. package/dist/dts/containers/LifecycleFailedContainer.d.ts +3 -0
  84. package/dist/dts/containers/LifecycleGeneralErrorContainer.d.ts +3 -0
  85. package/dist/dts/containers/LifecycleInQueueContainer.d.ts +3 -0
  86. package/dist/dts/containers/LifecyclePendingApiContainer.d.ts +3 -0
  87. package/dist/dts/containers/LifecyclePostActionContainer.d.ts +3 -0
  88. package/dist/dts/containers/LifecycleReceivedContainer.d.ts +3 -0
  89. package/dist/dts/data/devComponents.d.ts +4 -0
  90. package/dist/dts/data/devRoutes.d.ts +8 -0
  91. package/dist/dts/hooks/useStoreSize.d.ts +7 -0
  92. package/dist/dts/index.d.ts +1 -0
  93. package/dist/dts/store/selectors.d.ts +2235 -0
  94. package/dist/dts/types.d.ts +0 -0
  95. package/dist/dts/utils/date.d.ts +4 -0
  96. package/dist/dts/utils/download.d.ts +1 -0
  97. package/dist/hooks/useStoreSize.js +16 -0
  98. package/dist/index.d.ts +1 -0
  99. package/dist/index.js +1 -0
  100. package/dist/redux-connected-devtools.es.js +992 -0
  101. package/dist/redux-connected-devtools.es.js.map +1 -0
  102. package/dist/redux-connected-devtools.umd.js +247 -0
  103. package/dist/redux-connected-devtools.umd.js.map +1 -0
  104. package/dist/store/selectors.js +143 -0
  105. package/dist/types.js +1 -0
  106. package/dist/utils/date.js +8 -0
  107. package/dist/utils/download.js +17 -0
  108. package/package.json +29 -13
  109. package/.env +0 -2
  110. package/.prettierrc.js +0 -10
  111. package/.vscode/settings.json +0 -12
  112. package/.vscode/tasks.json +0 -33
  113. package/index.html +0 -58
  114. package/jest.config.js +0 -8
  115. package/public/devtools.html +0 -8
  116. package/public/icon.png +0 -0
  117. package/public/manifest.json +0 -29
  118. package/public/options.html +0 -12
  119. package/public/panel.html +0 -39
  120. package/public/popup.html +0 -12
  121. package/src/__tests__/sum.ts +0 -9
  122. package/src/background.ts +0 -49
  123. package/src/components/DevInspector/DevInspector.scss +0 -2
  124. package/src/components/DevInspector/DevInspector.tsx +0 -34
  125. package/src/components/DevList/DevList.scss +0 -2
  126. package/src/components/DevList/DevList.tsx +0 -62
  127. package/src/components/DevMenu/DevMenu.scss +0 -2
  128. package/src/components/DevMenu/DevMenu.tsx +0 -76
  129. package/src/components/DevPanel/DevPanel.scss +0 -2
  130. package/src/components/DevPanel/DevPanel.style.tsx +0 -16
  131. package/src/components/DevPanel/DevPanel.tsx +0 -51
  132. package/src/components/JourneyRow/JourneyRow.scss +0 -2
  133. package/src/components/JsonViewer/JsonViewer.scss +0 -2
  134. package/src/components/JsonViewer/JsonViewer.tsx +0 -24
  135. package/src/components/Lifecycle/Lifecycle.scss +0 -2
  136. package/src/components/Lifecycle/Lifecycle.tsx +0 -31
  137. package/src/components/LogsViewer/LogsViewer.scss +0 -2
  138. package/src/components/LogsViewer/LogsViewer.style.tsx +0 -5
  139. package/src/components/LogsViewer/LogsViewer.tsx +0 -14
  140. package/src/components/RequestDetails/RequestDetails.scss +0 -2
  141. package/src/components/RequestDetails/RequestDetails.style.tsx +0 -20
  142. package/src/components/RequestDetails/RequestDetails.tsx +0 -60
  143. package/src/components/RequestJourney/RequestJourney.scss +0 -2
  144. package/src/components/RequestJourney/RequestJourney.style.tsx +0 -6
  145. package/src/components/RequestJourney/RequestJourney.tsx +0 -33
  146. package/src/components/RequestRow/RequestRow.scss +0 -2
  147. package/src/components/RequestRow/RequestRow.tsx +0 -37
  148. package/src/components/Time/Time.scss +0 -2
  149. package/src/containers/DevMenuContainer.tsx +0 -28
  150. package/src/containers/DevPanelContainer.tsx +0 -10
  151. package/src/content_script.ts +0 -19
  152. package/src/devtools.tsx +0 -29
  153. package/src/index.ts +0 -1
  154. package/src/injected_script.ts +0 -9
  155. package/src/options.tsx +0 -77
  156. package/src/panel.tsx +0 -30
  157. package/src/popup.tsx +0 -63
  158. package/src/store/initialState.ts +0 -42
  159. package/src/store/selectors.ts +0 -205
  160. package/src/sum.ts +0 -3
  161. package/src/types.ts +0 -1
  162. package/src/utils/date.ts +0 -3
  163. package/tsconfig.json +0 -24
  164. package/vite.config.ts +0 -45
  165. package/webpack/webpack.common.js +0 -46
  166. package/webpack/webpack.dev.js +0 -7
  167. package/webpack/webpack.prod.js +0 -6
@@ -0,0 +1,992 @@
1
+ import React, { useState, useMemo, useRef, useEffect } from "react";
2
+ import styled from "styled-components";
3
+ import { useSelector, Provider } from "react-redux";
4
+ import classnames from "classnames";
5
+ import { createSelector } from "reselect";
6
+ import { connectedSelectors, LifecycleStatus, clearCompletedRequests, clearFailedRequests } from "redux-connected";
7
+ import bytes from "bytes";
8
+ import { FixedSizeList } from "react-window";
9
+ import { debounce } from "shared-base";
10
+ const Download = (props) => {
11
+ const { size = 24 } = props;
12
+ return /* @__PURE__ */ React.createElement("svg", {
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ viewBox: "0 0 24 24",
15
+ width: `${size}px`,
16
+ height: `${size}px`,
17
+ fill: "currentColor"
18
+ }, /* @__PURE__ */ React.createElement("path", {
19
+ d: "M0 0h24v24H0z",
20
+ fill: "none"
21
+ }), /* @__PURE__ */ React.createElement("path", {
22
+ d: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z"
23
+ }));
24
+ };
25
+ const Close = (props) => {
26
+ const { size = 24 } = props;
27
+ return /* @__PURE__ */ React.createElement("svg", {
28
+ xmlns: "http://www.w3.org/2000/svg",
29
+ viewBox: "0 0 24 24",
30
+ width: `${size}px`,
31
+ height: `${size}px`,
32
+ fill: "currentColor"
33
+ }, /* @__PURE__ */ React.createElement("path", {
34
+ d: "M0 0h24v24H0z",
35
+ fill: "none"
36
+ }), /* @__PURE__ */ React.createElement("path", {
37
+ d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"
38
+ }));
39
+ };
40
+ const ClearAll = (props) => {
41
+ const { size = 24 } = props;
42
+ return /* @__PURE__ */ React.createElement("svg", {
43
+ xmlns: "http://www.w3.org/2000/svg",
44
+ viewBox: "0 0 24 24",
45
+ width: `${size}px`,
46
+ height: `${size}px`,
47
+ fill: "currentColor"
48
+ }, /* @__PURE__ */ React.createElement("path", {
49
+ d: "M0 0h24v24H0z",
50
+ fill: "none"
51
+ }), /* @__PURE__ */ React.createElement("path", {
52
+ d: "M5 13h14v-2H5v2zm-2 4h14v-2H3v2zM7 7v2h14V7H7z"
53
+ }));
54
+ };
55
+ const allIcons = {
56
+ close: Close,
57
+ clearAll: ClearAll,
58
+ download: Download
59
+ };
60
+ const Container$d = styled.div`
61
+ margin: 0 3px;
62
+ color: ${(props) => {
63
+ var _a;
64
+ return (_a = props.color) != null ? _a : "inherit";
65
+ }};
66
+ cursor: pointer;
67
+
68
+ &:hover {
69
+ color: gold;
70
+ }
71
+ `;
72
+ function Icon(props) {
73
+ const { name, size = 20, color } = props;
74
+ const Cmp = allIcons[name];
75
+ return /* @__PURE__ */ React.createElement(Container$d, {
76
+ className: "Icon-container",
77
+ "data-testid": "Icon-container",
78
+ color,
79
+ onClick: props.onClick
80
+ }, /* @__PURE__ */ React.createElement(Cmp, {
81
+ size
82
+ }));
83
+ }
84
+ const Container$c = styled.div`
85
+ flex: 1;
86
+ background-color: #223;
87
+ z-index: 3;
88
+ color: #eee;
89
+ display: flex;
90
+ flex-direction: column;
91
+ min-width: 880px;
92
+ min-height: 880px;
93
+ `;
94
+ const Container$b = styled.div`
95
+ width: 190px;
96
+ ${(props) => props.theme.borderRight("1px solid rgba(255, 255, 255, 0.2)")}
97
+ box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.5);
98
+ `;
99
+ const MenuGroup = styled.div`
100
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
101
+ `;
102
+ const MenuGroupTitle = styled.div`
103
+ font-size: 13px;
104
+ padding: 5px 10px;
105
+ color: rgba(255, 255, 255, 0.5);
106
+ border-bottom: 1px solid rgba(255, 255, 255, 0.2);
107
+ background-color: rgba(0, 0, 0, 0.1);
108
+ `;
109
+ const MenuItem = styled.div`
110
+ display: flex;
111
+ flex-direction: row;
112
+ align-items: center;
113
+ padding: 6px 10px;
114
+ font-size: 14px;
115
+ color: rgba(255, 255, 255, 0.89);
116
+ background-color: transparent;
117
+
118
+ &.selected {
119
+ color: gold;
120
+ background-color: rgba(255, 255, 255, 0.05);
121
+ }
122
+
123
+ &:hover {
124
+ background-color: rgba(255, 255, 255, 0.1);
125
+ cursor: pointer;
126
+ }
127
+ `;
128
+ const Title = styled.div`
129
+ flex: 1;
130
+ `;
131
+ const Badge = styled.div`
132
+ background-color: rgba(0, 0, 80, 0.3);
133
+ padding: 0 4px;
134
+ font-size: 12px;
135
+ border-radius: 7px;
136
+ border: 1px solid #334;
137
+ color: cyan;
138
+ `;
139
+ const BadgeTotal = styled(Badge)`
140
+ color: #555;
141
+ `;
142
+ function DevMenu(props) {
143
+ const { groups, items, selectedId, badges, badgesTotal } = props;
144
+ function renderItem(item) {
145
+ const { title, id } = item;
146
+ const selected = id === selectedId;
147
+ const badge = badges[id];
148
+ const badgeTotal = badgesTotal[id];
149
+ return /* @__PURE__ */ React.createElement(MenuItem, {
150
+ key: item.id,
151
+ className: classnames({ selected }),
152
+ onClick: () => props.onClick(item)
153
+ }, /* @__PURE__ */ React.createElement(Title, null, title), badgeTotal > 0 && badgeTotal !== badge && /* @__PURE__ */ React.createElement(BadgeTotal, null, badgeTotal), badge > 0 && /* @__PURE__ */ React.createElement(Badge, null, badge));
154
+ }
155
+ function renderItems(groupItems) {
156
+ return groupItems.map((item) => renderItem(item));
157
+ }
158
+ function renderGroup(group) {
159
+ const groupItems = items.filter((item) => item.group === group);
160
+ return /* @__PURE__ */ React.createElement(MenuGroup, {
161
+ key: group
162
+ }, /* @__PURE__ */ React.createElement(MenuGroupTitle, null, group), renderItems(groupItems));
163
+ }
164
+ function renderGroups() {
165
+ return groups.map((group) => renderGroup(group));
166
+ }
167
+ return /* @__PURE__ */ React.createElement(Container$b, {
168
+ className: "DevMenu-container",
169
+ "data-testid": "DevMenu-container"
170
+ }, renderGroups());
171
+ }
172
+ const devRoutes = [
173
+ {
174
+ id: "lifecycleReceived",
175
+ title: "1. Received",
176
+ group: "lifecycle",
177
+ componentId: "LifecycleReceived"
178
+ },
179
+ {
180
+ id: "lifecycleInQueue",
181
+ title: "2. In queue",
182
+ group: "lifecycle",
183
+ componentId: "LifecycleInQueue"
184
+ },
185
+ {
186
+ id: "lifecyclePendingApi",
187
+ title: "3. Pending API",
188
+ group: "lifecycle",
189
+ componentId: "LifecyclePendingApi"
190
+ },
191
+ {
192
+ id: "lifecyclePostAction",
193
+ title: "4. Post action",
194
+ group: "lifecycle",
195
+ componentId: "LifecyclePostAction"
196
+ },
197
+ {
198
+ id: "lifecycleGeneralError",
199
+ title: "e1. General errors",
200
+ group: "errors",
201
+ componentId: "LifecycleGeneralError"
202
+ },
203
+ {
204
+ id: "lifecycleApiError",
205
+ title: "e2. API errors",
206
+ group: "errors",
207
+ componentId: "LifecycleApiError"
208
+ },
209
+ {
210
+ id: "lifecycleFailed",
211
+ title: "e3. Failed requests (after retries)",
212
+ group: "errors",
213
+ componentId: "LifecycleFailed"
214
+ },
215
+ {
216
+ id: "endpointStatus",
217
+ title: "Endpoint status",
218
+ group: "settings & stats",
219
+ componentId: "EndpointStatus"
220
+ },
221
+ {
222
+ id: "settingsGlobal",
223
+ title: "Global settings",
224
+ group: "settings & stats",
225
+ componentId: "GlobalSettings"
226
+ },
227
+ {
228
+ id: "settingsEndpoints",
229
+ title: "Endpoints configs",
230
+ group: "settings & stats",
231
+ componentId: "EndpointConfigs"
232
+ },
233
+ {
234
+ id: "statsGlobal",
235
+ title: "Global stats",
236
+ group: "settings & stats",
237
+ componentId: "GlobalStats"
238
+ }
239
+ ];
240
+ const getGroups = () => {
241
+ const output = [];
242
+ devRoutes.forEach((group) => {
243
+ if (!output.includes(group.group)) {
244
+ output.push(group.group);
245
+ }
246
+ });
247
+ return output;
248
+ };
249
+ const devGroups = getGroups();
250
+ const $requests = createSelector(
251
+ connectedSelectors.$requests,
252
+ (requests) => {
253
+ return requests.map((request) => {
254
+ var _a;
255
+ const { items } = request;
256
+ const lastPoint = (_a = items[items.length - 1]) != null ? _a : {};
257
+ const journeyWithDelta = items.map((point, index) => {
258
+ var _a2;
259
+ const nextPoint = (_a2 = items[index + 1]) != null ? _a2 : point;
260
+ const delta = nextPoint.timestamp - point.timestamp;
261
+ return {
262
+ ...point,
263
+ delta
264
+ };
265
+ });
266
+ return {
267
+ ...request,
268
+ items: journeyWithDelta,
269
+ lastPointTimestamp: lastPoint.timestamp,
270
+ lastPointStatus: lastPoint.status
271
+ };
272
+ }).sort((a, b) => {
273
+ if (a.lastPointTimestamp === b.lastPointTimestamp) {
274
+ return 0;
275
+ }
276
+ return a.lastPointTimestamp > b.lastPointTimestamp ? -1 : 1;
277
+ });
278
+ }
279
+ );
280
+ const $requestsReceived = createSelector($requests, (requests) => {
281
+ return requests.filter((request) => {
282
+ const { items } = request;
283
+ const lastPoint = items[items.length - 1];
284
+ return lastPoint && lastPoint.status === LifecycleStatus.RECEIVED;
285
+ });
286
+ });
287
+ const $requestsReceivedPast = createSelector($requests, (requests) => {
288
+ return requests.filter((request) => {
289
+ const { items } = request;
290
+ return items.find((point) => point.status === LifecycleStatus.RECEIVED);
291
+ });
292
+ });
293
+ const $requestsInQueue = createSelector($requests, (requests) => {
294
+ return requests.filter((request) => {
295
+ const { items } = request;
296
+ const lastPoint = items[items.length - 1];
297
+ return lastPoint && lastPoint.status === LifecycleStatus.IN_QUEUE;
298
+ });
299
+ });
300
+ const $requestsInQueuePast = createSelector($requests, (requests) => {
301
+ return requests.filter((request) => {
302
+ const { items } = request;
303
+ return items.find((point) => point.status === LifecycleStatus.IN_QUEUE);
304
+ });
305
+ });
306
+ const $requestsPendingApi = createSelector($requests, (requests) => {
307
+ return requests.filter((request) => {
308
+ const { items } = request;
309
+ const lastPoint = items[items.length - 1];
310
+ return lastPoint && lastPoint.status === LifecycleStatus.PENDING_API_RESPONSE;
311
+ });
312
+ });
313
+ const $requestsPendingApiPast = createSelector($requests, (requests) => {
314
+ return requests.filter((request) => {
315
+ const { items } = request;
316
+ return items.find(
317
+ (point) => point.status === LifecycleStatus.PENDING_API_RESPONSE
318
+ );
319
+ });
320
+ });
321
+ const $requestsPostAction = createSelector($requests, (requests) => {
322
+ return requests.filter((request) => {
323
+ const { items } = request;
324
+ const lastPoint = items[items.length - 1];
325
+ return lastPoint && lastPoint.status === LifecycleStatus.POST_ACTION;
326
+ });
327
+ });
328
+ const $requestsPostActionPast = createSelector($requests, (requests) => {
329
+ return requests.filter((request) => {
330
+ const { items } = request;
331
+ return items.find(
332
+ (point) => point.status === LifecycleStatus.POST_ACTION
333
+ );
334
+ });
335
+ });
336
+ const $requestsGeneralError = createSelector($requests, (requests) => {
337
+ return requests.filter((request) => {
338
+ const { items } = request;
339
+ const lastPoint = items[items.length - 1];
340
+ return lastPoint && lastPoint.status === LifecycleStatus.GENERAL_ERROR;
341
+ });
342
+ });
343
+ const $requestsGeneralErrorPast = createSelector(
344
+ $requests,
345
+ (requests) => {
346
+ return requests.filter((request) => {
347
+ const { items } = request;
348
+ return items.find(
349
+ (point) => point.status === LifecycleStatus.GENERAL_ERROR
350
+ );
351
+ });
352
+ }
353
+ );
354
+ const $requestsApiError = createSelector($requests, (requests) => {
355
+ return requests.filter((request) => {
356
+ const { items } = request;
357
+ const lastPoint = items[items.length - 1];
358
+ return lastPoint && lastPoint.status === LifecycleStatus.API_ERROR;
359
+ });
360
+ });
361
+ const $requestsFailed = createSelector($requests, (requests) => {
362
+ return requests.filter((request) => {
363
+ const { items } = request;
364
+ return items.find((point) => point.status === LifecycleStatus.FAILED);
365
+ });
366
+ });
367
+ const $requestsApiErrorPast = createSelector($requests, (requests) => {
368
+ return requests.filter((request) => {
369
+ const { items } = request;
370
+ return items.find(
371
+ (point) => point.status === LifecycleStatus.API_ERROR
372
+ );
373
+ });
374
+ });
375
+ const $menuBadges = createSelector(
376
+ $requestsReceived,
377
+ $requestsInQueue,
378
+ $requestsGeneralError,
379
+ $requestsPendingApi,
380
+ $requestsApiError,
381
+ $requestsFailed,
382
+ $requestsPostAction,
383
+ (requestsReceived, requestsInQueue, requestsGeneralError, requestsPendingApi, requestsApiError, requestsFailed, requestsPostAction) => {
384
+ return {
385
+ lifecycleReceived: requestsReceived.length,
386
+ lifecycleInQueue: requestsInQueue.length,
387
+ lifecycleGeneralError: requestsGeneralError.length,
388
+ lifecyclePendingApi: requestsPendingApi.length,
389
+ lifecycleApiError: requestsApiError.length,
390
+ lifecycleFailed: requestsFailed.length,
391
+ lifecyclePostAction: requestsPostAction.length
392
+ };
393
+ }
394
+ );
395
+ const $menuBadgesTotal = createSelector(
396
+ $requestsReceivedPast,
397
+ $requestsInQueuePast,
398
+ $requestsGeneralErrorPast,
399
+ $requestsPendingApiPast,
400
+ $requestsApiErrorPast,
401
+ $requestsFailed,
402
+ $requestsPostActionPast,
403
+ (requestsReceived, requestsInQueue, requestsGeneralError, requestsPendingApi, requestsApiError, requestsFailed, requestsPostAction) => {
404
+ return {
405
+ lifecycleReceived: requestsReceived.length,
406
+ lifecycleInQueue: requestsInQueue.length,
407
+ lifecycleGeneralError: requestsGeneralError.length,
408
+ lifecyclePendingApi: requestsPendingApi.length,
409
+ lifecycleApiError: requestsApiError.length,
410
+ lifecycleFailed: requestsFailed.length,
411
+ lifecyclePostAction: requestsPostAction.length
412
+ };
413
+ }
414
+ );
415
+ function DevMenuContainer(props) {
416
+ const badges = useSelector($menuBadges);
417
+ const badgesTotal = useSelector($menuBadgesTotal);
418
+ return /* @__PURE__ */ React.createElement(DevMenu, {
419
+ groups: devGroups,
420
+ items: devRoutes,
421
+ badges,
422
+ badgesTotal,
423
+ selectedId: props.selectedId,
424
+ onClick: props.onClick
425
+ });
426
+ }
427
+ const Container$a = styled.div`
428
+ flex: 1;
429
+ color: #eee;
430
+ background-color: #232332;
431
+ display: flex;
432
+ flex-direction: row;
433
+ `;
434
+ const Content = styled.div`
435
+ flex: 1;
436
+ background-color: rgba(0, 0, 0, 0.15);
437
+ display: flex;
438
+ flex-direction: column;
439
+ `;
440
+ const Actions = styled.div`
441
+ position: absolute;
442
+ bottom: 5px;
443
+ ${(props) => props.theme.left("10px")}
444
+ display: flex;
445
+ flex-direction: row;
446
+ align-items: center;
447
+ `;
448
+ const Container$9 = styled.div`
449
+ flex: 1;
450
+ display: flex;
451
+ flex-direction: column;
452
+ `;
453
+ const Container$8 = styled.div`
454
+ flex: 1;
455
+ border-top: 1px solid #333;
456
+ max-height: 380px;
457
+ overflow-y: scroll;
458
+
459
+ &::-webkit-scrollbar {
460
+ width: 8px;
461
+ }
462
+
463
+ /* Track */
464
+ &::-webkit-scrollbar-track {
465
+ background: #333;
466
+ }
467
+
468
+ /* Handle */
469
+ &::-webkit-scrollbar-thumb {
470
+ background: #555;
471
+ }
472
+
473
+ /* Handle on hover */
474
+ &::-webkit-scrollbar-thumb:hover {
475
+ background: #666;
476
+ }
477
+ `;
478
+ const timestamp = () => new Date().getTime();
479
+ let startOfTime = timestamp();
480
+ const resetStartOfTime = () => {
481
+ startOfTime = timestamp();
482
+ };
483
+ const getMinutes = () => {
484
+ return new Date().getMinutes();
485
+ };
486
+ const Container$7 = styled.div`
487
+ display: flex;
488
+ flex-direction: row;
489
+ align-items: flex-start;
490
+ font-family: monospace;
491
+ color: #99a;
492
+ `;
493
+ const Full = styled.div`
494
+ font-size: 24px;
495
+ `;
496
+ const Fraction = styled.div`
497
+ font-size: 12px;
498
+ `;
499
+ function Time(props) {
500
+ const { value } = props;
501
+ const relativeValue = (value - startOfTime) / 1e3;
502
+ const full = Math.floor(relativeValue);
503
+ const fraction = (relativeValue - full).toFixed(3).split(".").pop();
504
+ return /* @__PURE__ */ React.createElement(Container$7, {
505
+ className: "Time-container",
506
+ "data-testid": "Time-container"
507
+ }, /* @__PURE__ */ React.createElement(Full, null, full), /* @__PURE__ */ React.createElement(Fraction, null, fraction));
508
+ }
509
+ const Container$6 = styled.div`
510
+ flex: 1;
511
+ display: flex;
512
+ flex-direction: row;
513
+ align-items: center;
514
+ padding: 10px 20px;
515
+
516
+ &:nth-child(2n-1) {
517
+ background-color: rgba(0, 0, 0, 0.2);
518
+ }
519
+
520
+ &:hover {
521
+ background-color: rgba(0, 0, 0, 0.3);
522
+ cursor: pointer;
523
+ }
524
+ `;
525
+ const Status = styled.div`
526
+ color: #aaa;
527
+ `;
528
+ const DataIcon = styled.div`
529
+ background-color: #000;
530
+ padding: 3px 7px;
531
+ font-size: 13px;
532
+ font-weight: bold;
533
+ color: purple;
534
+ border-radius: 5px;
535
+ ${(props) => props.theme.marginLeft("10px")}
536
+ `;
537
+ const Delta = styled.div`
538
+ font-size: 13px;
539
+ width: 60px;
540
+ font-weight: bold;
541
+ color: olive;
542
+ ${(props) => props.theme.marginRight("10px")}
543
+ text-align: center;
544
+ font-family: monospace;
545
+ `;
546
+ const Flex = styled.div`
547
+ flex: 1;
548
+ `;
549
+ const statusMap = {
550
+ [LifecycleStatus.RECEIVED]: "Received",
551
+ [LifecycleStatus.POST_ACTION_OPTIMISTIC]: "Post action (optimistic)",
552
+ [LifecycleStatus.IN_QUEUE]: "In queue",
553
+ [LifecycleStatus.GENERAL_ERROR]: "General error",
554
+ [LifecycleStatus.PENDING_API_RESPONSE]: "Pending API",
555
+ [LifecycleStatus.API_ERROR]: "API error",
556
+ [LifecycleStatus.POST_ACTION]: "Post action",
557
+ [LifecycleStatus.FAILED]: "Failed"
558
+ };
559
+ function JourneyRow(props) {
560
+ const { point } = props;
561
+ const { status, timestamp: timestamp2, data, delta = "" } = point;
562
+ function printPoint() {
563
+ console.log(data);
564
+ }
565
+ function renderDataIcon() {
566
+ if (!data) {
567
+ return null;
568
+ }
569
+ return /* @__PURE__ */ React.createElement(DataIcon, null, "D");
570
+ }
571
+ function renderDelta() {
572
+ if (!delta) {
573
+ return null;
574
+ }
575
+ return /* @__PURE__ */ React.createElement(Delta, null, "+", delta.toLocaleString());
576
+ }
577
+ return /* @__PURE__ */ React.createElement(Container$6, {
578
+ className: "JourneyRow-container",
579
+ "data-testid": "JourneyRow-container",
580
+ onClick: printPoint
581
+ }, /* @__PURE__ */ React.createElement(Status, null, statusMap[status]), renderDataIcon(), /* @__PURE__ */ React.createElement(Flex, null), renderDelta(), /* @__PURE__ */ React.createElement(Time, {
582
+ value: timestamp2
583
+ }));
584
+ }
585
+ function RequestJourney(props) {
586
+ const { item } = props;
587
+ function renderItem(point, index) {
588
+ return /* @__PURE__ */ React.createElement(JourneyRow, {
589
+ key: index,
590
+ point
591
+ });
592
+ }
593
+ function renderItems() {
594
+ return item.items.map(
595
+ (point, index) => renderItem(point, index)
596
+ );
597
+ }
598
+ return /* @__PURE__ */ React.createElement(Container$8, {
599
+ className: "RequestJourney-container",
600
+ "data-testid": "RequestJourney-container"
601
+ }, renderItems());
602
+ }
603
+ const Container$5 = styled.div`
604
+ flex: 1;
605
+ padding: 20px;
606
+ `;
607
+ const Table = styled.table``;
608
+ const Tr = styled.tr``;
609
+ const Td = styled.td`
610
+ color: goldenrod;
611
+
612
+ &:first-child {
613
+ color: #778;
614
+ text-align: right;
615
+ ${(props) => props.theme.paddingRight("10px")}
616
+ }
617
+ `;
618
+ const Container$4 = styled.div`
619
+ flex: 1;
620
+ max-height: 850px;
621
+ overflow: auto;
622
+ padding: 0 25px;
623
+ max-width: ${(props) => props.width ? props.width + "px" : "680px"};
624
+ color: #ccc;
625
+ line-height: 26px;
626
+
627
+ &::-webkit-scrollbar {
628
+ width: 8px;
629
+ height: 7px;
630
+ }
631
+
632
+ /* Track */
633
+ &::-webkit-scrollbar-track {
634
+ background: #333;
635
+ }
636
+
637
+ /* Handle */
638
+ &::-webkit-scrollbar-thumb {
639
+ background: #555;
640
+ }
641
+
642
+ /* Handle on hover */
643
+ &::-webkit-scrollbar-thumb:hover {
644
+ background: #666;
645
+ }
646
+ `;
647
+ function JsonViewer(props) {
648
+ const { json, width } = props;
649
+ return /* @__PURE__ */ React.createElement(Container$4, {
650
+ className: "JsonViewer-container",
651
+ "data-testid": "JsonViewer-container",
652
+ width
653
+ }, /* @__PURE__ */ React.createElement("pre", null, JSON.stringify(json, null, 4)));
654
+ }
655
+ function RequestDetails(props) {
656
+ const { item } = props;
657
+ return /* @__PURE__ */ React.createElement(Container$5, {
658
+ className: "RequestDetails-container",
659
+ "data-testid": "RequestDetails-container"
660
+ }, /* @__PURE__ */ React.createElement(Table, null, /* @__PURE__ */ React.createElement("tbody", null, /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "sequence"), /* @__PURE__ */ React.createElement(Td, null, item.sequence)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "id"), /* @__PURE__ */ React.createElement(Td, null, item.shortId)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "apiVerb"), /* @__PURE__ */ React.createElement(Td, null, item.argsApiVerb)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "connection"), /* @__PURE__ */ React.createElement(Td, null, item.argsConnectionType)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "duration"), /* @__PURE__ */ React.createElement(Td, null, item.apiDuration)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "nodeName"), /* @__PURE__ */ React.createElement(Td, null, item.argsNodeName)), /* @__PURE__ */ React.createElement(Tr, null, /* @__PURE__ */ React.createElement(Td, null, "responseSize"), /* @__PURE__ */ React.createElement(Td, null, item.apiResponseSize && bytes(item.apiResponseSize))))), /* @__PURE__ */ React.createElement(JsonViewer, {
661
+ width: 290,
662
+ json: item.originalAction
663
+ }));
664
+ }
665
+ function DevInspector(props) {
666
+ const { item } = props;
667
+ if (!item) {
668
+ return /* @__PURE__ */ React.createElement(Container$9, {
669
+ className: "DevInspector-container",
670
+ "data-testid": "DevInspector-container"
671
+ });
672
+ }
673
+ return /* @__PURE__ */ React.createElement(Container$9, {
674
+ className: "DevInspector-container",
675
+ "data-testid": "DevInspector-container"
676
+ }, /* @__PURE__ */ React.createElement(RequestDetails, {
677
+ item
678
+ }), /* @__PURE__ */ React.createElement(RequestJourney, {
679
+ item
680
+ }));
681
+ }
682
+ const Container$3 = styled.div`
683
+ flex: 1;
684
+
685
+ .list {
686
+ &::-webkit-scrollbar {
687
+ width: 8px;
688
+ }
689
+
690
+ /* Track */
691
+ &::-webkit-scrollbar-track {
692
+ background: #333;
693
+ }
694
+
695
+ /* Handle */
696
+ &::-webkit-scrollbar-thumb {
697
+ background: #555;
698
+ }
699
+
700
+ /* Handle on hover */
701
+ &::-webkit-scrollbar-thumb:hover {
702
+ background: #666;
703
+ }
704
+ }
705
+ `;
706
+ const Empty = styled.div`
707
+ color: #456;
708
+ margin: 30px;
709
+ font-size: 17px;
710
+ text-align: center;
711
+ text-shadow: 1px 3px 3px rgba(0, 0, 0, 0.2);
712
+ `;
713
+ function DevList(props) {
714
+ const { row: Cmp, items, selectedRow } = props;
715
+ const Item = (rowInfo) => {
716
+ const { index, style } = rowInfo;
717
+ const item = items[index];
718
+ const className = classnames({ selected: item.id === (selectedRow == null ? void 0 : selectedRow.id) });
719
+ return /* @__PURE__ */ React.createElement(Cmp, {
720
+ onClick: props.onClick,
721
+ className,
722
+ index,
723
+ style,
724
+ item
725
+ });
726
+ };
727
+ function renderEmpty() {
728
+ return /* @__PURE__ */ React.createElement(Empty, null, "Empty list");
729
+ }
730
+ function renderList() {
731
+ if (items.length === 0) {
732
+ return renderEmpty();
733
+ }
734
+ return /* @__PURE__ */ React.createElement(FixedSizeList, {
735
+ height: 850,
736
+ itemCount: items.length,
737
+ itemSize: 68,
738
+ width: 350,
739
+ className: "list"
740
+ }, Item);
741
+ }
742
+ return /* @__PURE__ */ React.createElement(Container$3, {
743
+ className: "DevList-container",
744
+ "data-testid": "DevList-container"
745
+ }, renderList());
746
+ }
747
+ const Container$2 = styled.div`
748
+ flex: 1;
749
+ display: flex;
750
+ flex-direction: row;
751
+ align-items: center;
752
+ padding: 10px;
753
+ max-width: 90%;
754
+ background-color: ${(props) => props.index % 2 === 1 ? "rgba(0, 0, 0, 0.2)" : "transparent"};
755
+
756
+ &:hover {
757
+ background-color: rgba(0, 0, 0, 0.7);
758
+ cursor: pointer;
759
+ }
760
+ `;
761
+ const Col = styled.div`
762
+ &:first-child {
763
+ flex: 1;
764
+ }
765
+ `;
766
+ const Id = styled.div`
767
+ color: goldenrod;
768
+ font-size: 16px;
769
+ `;
770
+ const Type = styled.div`
771
+ color: brown;
772
+ `;
773
+ function RequestRow(props) {
774
+ var _a;
775
+ const { index, style, item, className } = props;
776
+ const { sequence, createdTS } = item;
777
+ return /* @__PURE__ */ React.createElement(Container$2, {
778
+ className: `DevListRow-container ${className}`,
779
+ "data-testid": "DevListRow-container",
780
+ style,
781
+ index,
782
+ onClick: () => props.onClick(item)
783
+ }, /* @__PURE__ */ React.createElement(Col, null, /* @__PURE__ */ React.createElement(Id, null, sequence), /* @__PURE__ */ React.createElement(Type, null, (_a = item.originalAction) == null ? void 0 : _a.type)), /* @__PURE__ */ React.createElement(Col, null, /* @__PURE__ */ React.createElement(Time, {
784
+ value: createdTS
785
+ })));
786
+ }
787
+ const Container$1 = styled.div`
788
+ flex: 1;
789
+ display: flex;
790
+ `;
791
+ function Lifecycle(props) {
792
+ const { requests } = props;
793
+ const [item, setItem] = useState();
794
+ function onClick(newItem) {
795
+ setItem(newItem);
796
+ }
797
+ return /* @__PURE__ */ React.createElement(Container$1, {
798
+ className: "Lifecycle-container",
799
+ "data-testid": "Lifecycle-container"
800
+ }, /* @__PURE__ */ React.createElement(DevList, {
801
+ items: requests,
802
+ row: RequestRow,
803
+ onClick,
804
+ selectedRow: item
805
+ }), /* @__PURE__ */ React.createElement(DevInspector, {
806
+ item
807
+ }));
808
+ }
809
+ function LifecycleReceivedContainer() {
810
+ const requests = useSelector($requestsReceivedPast);
811
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
812
+ requests
813
+ });
814
+ }
815
+ function GlobalStatsContainer() {
816
+ const json = useSelector(connectedSelectors.$apiGlobalStatsRaw);
817
+ return /* @__PURE__ */ React.createElement(JsonViewer, {
818
+ json
819
+ });
820
+ }
821
+ function EndpointConfigsContainer() {
822
+ const json = useSelector(connectedSelectors.$endpointsConfigRaw);
823
+ return /* @__PURE__ */ React.createElement(JsonViewer, {
824
+ json
825
+ });
826
+ }
827
+ function GlobalSettingsContainer() {
828
+ const json = useSelector(connectedSelectors.$apiGlobalSettingsRaw);
829
+ return /* @__PURE__ */ React.createElement(JsonViewer, {
830
+ json
831
+ });
832
+ }
833
+ function EndpointStatusContainer() {
834
+ const json = useSelector(connectedSelectors.$endpointsStateRaw);
835
+ return /* @__PURE__ */ React.createElement(JsonViewer, {
836
+ json
837
+ });
838
+ }
839
+ function LifecycleInQueueContainer() {
840
+ const requests = useSelector($requestsInQueuePast);
841
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
842
+ requests
843
+ });
844
+ }
845
+ function LifecycleGeneralErrorContainer() {
846
+ const requests = useSelector($requestsGeneralErrorPast);
847
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
848
+ requests
849
+ });
850
+ }
851
+ function LifecyclePendingApiContainer() {
852
+ const requests = useSelector($requestsPendingApiPast);
853
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
854
+ requests
855
+ });
856
+ }
857
+ function LifecycleApiErrorContainer() {
858
+ const requests = useSelector($requestsApiErrorPast);
859
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
860
+ requests
861
+ });
862
+ }
863
+ function LifecyclePostActionContainer() {
864
+ const requests = useSelector($requestsPostActionPast);
865
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
866
+ requests
867
+ });
868
+ }
869
+ function LifecycleFailedContainer() {
870
+ const requests = useSelector($requestsFailed);
871
+ return /* @__PURE__ */ React.createElement(Lifecycle, {
872
+ requests
873
+ });
874
+ }
875
+ const devComponents = {
876
+ LifecycleReceived: LifecycleReceivedContainer,
877
+ LifecycleInQueue: LifecycleInQueueContainer,
878
+ LifecycleGeneralError: LifecycleGeneralErrorContainer,
879
+ LifecyclePendingApi: LifecyclePendingApiContainer,
880
+ LifecycleApiError: LifecycleApiErrorContainer,
881
+ LifecycleFailed: LifecycleFailedContainer,
882
+ LifecyclePostAction: LifecyclePostActionContainer,
883
+ GlobalSettings: GlobalSettingsContainer,
884
+ GlobalStats: GlobalStatsContainer,
885
+ EndpointConfigs: EndpointConfigsContainer,
886
+ EndpointStatus: EndpointStatusContainer
887
+ };
888
+ function DevPanel(props) {
889
+ const [route, setRoute] = useState(devRoutes[0]);
890
+ function renderRoute() {
891
+ const Cmp = devComponents[route.componentId];
892
+ return /* @__PURE__ */ React.createElement(Cmp, {
893
+ key: route.id
894
+ });
895
+ }
896
+ return /* @__PURE__ */ React.createElement(Container$a, {
897
+ className: "DevPanel-container",
898
+ "data-testid": "DevPanel-container"
899
+ }, /* @__PURE__ */ React.createElement(DevMenuContainer, {
900
+ selectedId: route.id,
901
+ onClick: (item) => setRoute(item)
902
+ }), /* @__PURE__ */ React.createElement(Actions, null, props.children), /* @__PURE__ */ React.createElement(Content, null, renderRoute()));
903
+ }
904
+ function DevPanelContainer(props) {
905
+ return /* @__PURE__ */ React.createElement(DevPanel, null, props.children);
906
+ }
907
+ const Container = styled.div`
908
+ color: olive;
909
+ margin: 0 5px;
910
+ `;
911
+ function Size(props) {
912
+ const { size = 0 } = props;
913
+ const sizeText = useMemo(() => bytes(size), [size]);
914
+ return /* @__PURE__ */ React.createElement(Container, {
915
+ className: "Size-container",
916
+ "data-testid": "Size-container"
917
+ }, !size ? "-" : sizeText);
918
+ }
919
+ function DevtoolsApp(props) {
920
+ const { connectedStore, storeSizeInBytes, isDarkMode } = props;
921
+ const ref = useRef(null);
922
+ const className = classnames("DevtoolsApp-container", {
923
+ darkMode: isDarkMode
924
+ });
925
+ return /* @__PURE__ */ React.createElement(Container$c, {
926
+ ref,
927
+ className,
928
+ "data-testid": "DevtoolsApp-container"
929
+ }, /* @__PURE__ */ React.createElement(Provider, {
930
+ store: connectedStore
931
+ }, /* @__PURE__ */ React.createElement(DevPanelContainer, null, /* @__PURE__ */ React.createElement(Size, {
932
+ size: storeSizeInBytes
933
+ }), /* @__PURE__ */ React.createElement(Icon, {
934
+ name: "clearAll",
935
+ onClick: () => props.clearRequests()
936
+ }), /* @__PURE__ */ React.createElement(Icon, {
937
+ name: "download",
938
+ onClick: props.downloadState
939
+ }))));
940
+ }
941
+ const download = (filename, json) => {
942
+ const data = JSON.stringify(json, null, 4);
943
+ const blob = new Blob([data], { type: "text/csv" });
944
+ if (window.navigator.msSaveOrOpenBlob) {
945
+ window.navigator.msSaveBlob(blob, filename);
946
+ } else {
947
+ const elem = window.document.createElement("a");
948
+ elem.href = window.URL.createObjectURL(blob);
949
+ elem.download = filename;
950
+ document.body.appendChild(elem);
951
+ elem.click();
952
+ document.body.removeChild(elem);
953
+ }
954
+ };
955
+ const useStoreSize = (store) => {
956
+ const [storeSize, setStoreSize] = useState();
957
+ const calculateSize = debounce(() => {
958
+ const state = store.getState();
959
+ const size = JSON.stringify(state).length;
960
+ setStoreSize(size);
961
+ }, 500);
962
+ useEffect(() => {
963
+ store.subscribe(() => {
964
+ calculateSize();
965
+ });
966
+ }, [store]);
967
+ return storeSize;
968
+ };
969
+ function DevtoolsAppContainer(props) {
970
+ const { connectedStore, isDarkMode } = props;
971
+ const storeSizeInBytes = useStoreSize(connectedStore);
972
+ function clearRequests() {
973
+ connectedStore.dispatch(clearCompletedRequests());
974
+ connectedStore.dispatch(clearFailedRequests());
975
+ resetStartOfTime();
976
+ }
977
+ function downloadState() {
978
+ const state = connectedStore.getState();
979
+ const minutes = getMinutes();
980
+ const filename = `state_${minutes}.json`;
981
+ download(filename, state);
982
+ }
983
+ return /* @__PURE__ */ React.createElement(DevtoolsApp, {
984
+ connectedStore,
985
+ clearRequests,
986
+ downloadState,
987
+ storeSizeInBytes,
988
+ isDarkMode
989
+ });
990
+ }
991
+ export { DevtoolsAppContainer as DevtoolsApp };
992
+ //# sourceMappingURL=redux-connected-devtools.es.js.map