@quillsql/admin 1.4.0 → 1.6.0

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.
Files changed (149) hide show
  1. package/dist/cjs/Admin.d.ts +23 -73
  2. package/dist/cjs/Admin.d.ts.map +1 -1
  3. package/dist/cjs/Admin.js +221 -970
  4. package/dist/cjs/AdminProvider.d.ts +1 -12
  5. package/dist/cjs/AdminProvider.d.ts.map +1 -1
  6. package/dist/cjs/AdminProvider.js +24 -18
  7. package/dist/cjs/api/ConnectionClient.d.ts +11 -0
  8. package/dist/cjs/api/ConnectionClient.d.ts.map +1 -1
  9. package/dist/cjs/api/ConnectionClient.js +84 -10
  10. package/dist/cjs/components/DropDownMenu.js +1 -1
  11. package/dist/cjs/components/DropDownMenuWithLabel.d.ts.map +1 -1
  12. package/dist/cjs/components/DropDownMenuWithLabel.js +16 -54
  13. package/dist/cjs/components/OrgSelect.d.ts.map +1 -1
  14. package/dist/cjs/components/OrgSelect.js +10 -20
  15. package/dist/cjs/components/QuillSelect.d.ts +3 -0
  16. package/dist/cjs/components/QuillSelect.d.ts.map +1 -0
  17. package/dist/cjs/components/QuillSelect.js +137 -0
  18. package/dist/cjs/components/SegmentedControl.d.ts +7 -0
  19. package/dist/cjs/components/SegmentedControl.d.ts.map +1 -0
  20. package/dist/cjs/components/SegmentedControl.js +54 -0
  21. package/dist/cjs/components/UiComponents.d.ts +18 -29
  22. package/dist/cjs/components/UiComponents.d.ts.map +1 -1
  23. package/dist/cjs/components/UiComponents.js +40 -83
  24. package/dist/cjs/forms/client_onboard/ConnectSchema.d.ts +2 -1
  25. package/dist/cjs/forms/client_onboard/ConnectSchema.d.ts.map +1 -1
  26. package/dist/cjs/forms/client_onboard/ConnectSchema.js +143 -68
  27. package/dist/cjs/forms/client_onboard/CreateSqlViews.d.ts.map +1 -1
  28. package/dist/cjs/forms/client_onboard/CreateSqlViews.js +40 -11
  29. package/dist/cjs/forms/sql_views/CreateEditSqlView.d.ts +7 -4
  30. package/dist/cjs/forms/sql_views/CreateEditSqlView.d.ts.map +1 -1
  31. package/dist/cjs/forms/sql_views/CreateEditSqlView.js +36 -20
  32. package/dist/cjs/hooks/useOnClickOutside.d.ts +3 -0
  33. package/dist/cjs/hooks/useOnClickOutside.d.ts.map +1 -0
  34. package/dist/cjs/hooks/useOnClickOutside.js +20 -0
  35. package/dist/cjs/modals/EditFiltersModal.d.ts +17 -0
  36. package/dist/cjs/modals/EditFiltersModal.d.ts.map +1 -0
  37. package/dist/cjs/modals/EditFiltersModal.js +345 -0
  38. package/dist/cjs/modals/NewDashboardModal.d.ts +1 -3
  39. package/dist/cjs/modals/NewDashboardModal.d.ts.map +1 -1
  40. package/dist/cjs/modals/NewDashboardModal.js +63 -46
  41. package/dist/cjs/modals/PromoteDashModal.d.ts.map +1 -1
  42. package/dist/cjs/modals/PromoteDashModal.js +10 -3
  43. package/dist/cjs/modals/ReorderDashboardModal.d.ts.map +1 -1
  44. package/dist/cjs/modals/ReorderDashboardModal.js +202 -90
  45. package/dist/cjs/modals/index.d.ts +0 -1
  46. package/dist/cjs/modals/index.d.ts.map +1 -1
  47. package/dist/cjs/modals/index.js +1 -3
  48. package/dist/cjs/primitives/ButtonPrimitive.d.ts +3 -1
  49. package/dist/cjs/primitives/ButtonPrimitive.d.ts.map +1 -1
  50. package/dist/cjs/primitives/ButtonPrimitive.js +5 -3
  51. package/dist/cjs/primitives/ModalPrimitive.d.ts.map +1 -1
  52. package/dist/cjs/primitives/ModalPrimitive.js +1 -2
  53. package/dist/cjs/primitives/TogglePrimitive.js +5 -5
  54. package/dist/cjs/public_components/CreateEnvironment.d.ts.map +1 -1
  55. package/dist/cjs/public_components/CreateEnvironment.js +1 -1
  56. package/dist/cjs/public_components/DashboardBuilder.d.ts.map +1 -1
  57. package/dist/cjs/public_components/DashboardBuilder.js +127 -30
  58. package/dist/cjs/public_components/DashboardManager.d.ts.map +1 -1
  59. package/dist/cjs/public_components/DashboardManager.js +161 -193
  60. package/dist/cjs/public_components/SQLViewManager.d.ts.map +1 -1
  61. package/dist/cjs/public_components/SQLViewManager.js +92 -24
  62. package/dist/cjs/utils/constants.d.ts +4 -4
  63. package/dist/cjs/utils/constants.js +2 -2
  64. package/dist/cjs/utils/schema.d.ts +6 -0
  65. package/dist/cjs/utils/schema.d.ts.map +1 -1
  66. package/dist/cjs/utils/table.d.ts +1 -0
  67. package/dist/cjs/utils/table.d.ts.map +1 -1
  68. package/dist/cjs/utils/table.js +13 -0
  69. package/dist/cjs/utils/textProcessing.d.ts +2 -0
  70. package/dist/cjs/utils/textProcessing.d.ts.map +1 -0
  71. package/dist/cjs/utils/textProcessing.js +9 -0
  72. package/dist/esm/Admin.d.ts +23 -73
  73. package/dist/esm/Admin.d.ts.map +1 -1
  74. package/dist/esm/Admin.js +225 -964
  75. package/dist/esm/AdminProvider.d.ts +1 -12
  76. package/dist/esm/AdminProvider.d.ts.map +1 -1
  77. package/dist/esm/AdminProvider.js +25 -19
  78. package/dist/esm/api/ConnectionClient.d.ts +11 -0
  79. package/dist/esm/api/ConnectionClient.d.ts.map +1 -1
  80. package/dist/esm/api/ConnectionClient.js +82 -9
  81. package/dist/esm/components/DropDownMenu.js +1 -1
  82. package/dist/esm/components/DropDownMenuWithLabel.d.ts.map +1 -1
  83. package/dist/esm/components/DropDownMenuWithLabel.js +16 -54
  84. package/dist/esm/components/OrgSelect.d.ts.map +1 -1
  85. package/dist/esm/components/OrgSelect.js +6 -19
  86. package/dist/esm/components/QuillSelect.d.ts +3 -0
  87. package/dist/esm/components/QuillSelect.d.ts.map +1 -0
  88. package/dist/esm/components/QuillSelect.js +130 -0
  89. package/dist/esm/components/SegmentedControl.d.ts +7 -0
  90. package/dist/esm/components/SegmentedControl.d.ts.map +1 -0
  91. package/dist/esm/components/SegmentedControl.js +50 -0
  92. package/dist/esm/components/UiComponents.d.ts +18 -29
  93. package/dist/esm/components/UiComponents.d.ts.map +1 -1
  94. package/dist/esm/components/UiComponents.js +37 -82
  95. package/dist/esm/forms/client_onboard/ConnectSchema.d.ts +2 -1
  96. package/dist/esm/forms/client_onboard/ConnectSchema.d.ts.map +1 -1
  97. package/dist/esm/forms/client_onboard/ConnectSchema.js +145 -70
  98. package/dist/esm/forms/client_onboard/CreateSqlViews.d.ts.map +1 -1
  99. package/dist/esm/forms/client_onboard/CreateSqlViews.js +41 -12
  100. package/dist/esm/forms/sql_views/CreateEditSqlView.d.ts +7 -4
  101. package/dist/esm/forms/sql_views/CreateEditSqlView.d.ts.map +1 -1
  102. package/dist/esm/forms/sql_views/CreateEditSqlView.js +38 -22
  103. package/dist/esm/hooks/useOnClickOutside.d.ts +3 -0
  104. package/dist/esm/hooks/useOnClickOutside.d.ts.map +1 -0
  105. package/dist/esm/hooks/useOnClickOutside.js +18 -0
  106. package/dist/esm/modals/EditFiltersModal.d.ts +17 -0
  107. package/dist/esm/modals/EditFiltersModal.d.ts.map +1 -0
  108. package/dist/esm/modals/EditFiltersModal.js +338 -0
  109. package/dist/esm/modals/NewDashboardModal.d.ts +1 -3
  110. package/dist/esm/modals/NewDashboardModal.d.ts.map +1 -1
  111. package/dist/esm/modals/NewDashboardModal.js +63 -46
  112. package/dist/esm/modals/PromoteDashModal.d.ts.map +1 -1
  113. package/dist/esm/modals/PromoteDashModal.js +10 -3
  114. package/dist/esm/modals/ReorderDashboardModal.d.ts.map +1 -1
  115. package/dist/esm/modals/ReorderDashboardModal.js +201 -89
  116. package/dist/esm/modals/index.d.ts +0 -1
  117. package/dist/esm/modals/index.d.ts.map +1 -1
  118. package/dist/esm/modals/index.js +0 -1
  119. package/dist/esm/primitives/ButtonPrimitive.d.ts +3 -1
  120. package/dist/esm/primitives/ButtonPrimitive.d.ts.map +1 -1
  121. package/dist/esm/primitives/ButtonPrimitive.js +5 -3
  122. package/dist/esm/primitives/ModalPrimitive.d.ts.map +1 -1
  123. package/dist/esm/primitives/ModalPrimitive.js +1 -2
  124. package/dist/esm/primitives/TogglePrimitive.js +5 -5
  125. package/dist/esm/public_components/CreateEnvironment.d.ts.map +1 -1
  126. package/dist/esm/public_components/CreateEnvironment.js +1 -1
  127. package/dist/esm/public_components/DashboardBuilder.d.ts.map +1 -1
  128. package/dist/esm/public_components/DashboardBuilder.js +128 -31
  129. package/dist/esm/public_components/DashboardManager.d.ts.map +1 -1
  130. package/dist/esm/public_components/DashboardManager.js +163 -195
  131. package/dist/esm/public_components/SQLViewManager.d.ts.map +1 -1
  132. package/dist/esm/public_components/SQLViewManager.js +92 -24
  133. package/dist/esm/utils/constants.d.ts +4 -4
  134. package/dist/esm/utils/constants.js +2 -2
  135. package/dist/esm/utils/schema.d.ts +6 -0
  136. package/dist/esm/utils/schema.d.ts.map +1 -1
  137. package/dist/esm/utils/table.d.ts +1 -0
  138. package/dist/esm/utils/table.d.ts.map +1 -1
  139. package/dist/esm/utils/table.js +11 -1
  140. package/dist/esm/utils/textProcessing.d.ts +2 -0
  141. package/dist/esm/utils/textProcessing.d.ts.map +1 -0
  142. package/dist/esm/utils/textProcessing.js +5 -0
  143. package/package.json +1 -1
  144. package/dist/cjs/modals/EditDashboardsModal.d.ts +0 -20
  145. package/dist/cjs/modals/EditDashboardsModal.d.ts.map +0 -1
  146. package/dist/cjs/modals/EditDashboardsModal.js +0 -94
  147. package/dist/esm/modals/EditDashboardsModal.d.ts +0 -20
  148. package/dist/esm/modals/EditDashboardsModal.d.ts.map +0 -1
  149. package/dist/esm/modals/EditDashboardsModal.js +0 -91
@@ -3,10 +3,11 @@ import { useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { useAdmin } from '../AdminProvider';
4
4
  import { convertPostgresColumn } from '../Admin';
5
5
  import { EnvSelectPopover, OrgSelect } from '../components';
6
- import { SQLEditor } from '@quillsql/react';
6
+ import { ReportBuilder, SQLEditor } from '@quillsql/react';
7
7
  import { QUILL_SERVER } from '../utils/constants';
8
8
  import Banner from '../components/Banner';
9
9
  import DatabaseMismatchCard from '../components/DatabaseMismatchCard';
10
+ const modeToggleOptions = ['SQL Editor', 'Report Builder'];
10
11
  export default function DashboardBuilder({ navigateToDashboardManager, containerStyle, sqlEditor = true, }) {
11
12
  const parentRef = useRef(null);
12
13
  const { state, dispatch } = useAdmin();
@@ -27,6 +28,7 @@ export default function DashboardBuilder({ navigateToDashboardManager, container
27
28
  const [fields, setFields] = useState([]);
28
29
  const [errorMessage, setErrorMessage] = useState('');
29
30
  const [sqlResponseLoading, setSqlResponseLoading] = useState(false);
31
+ const [toggleMode, setToggleMode] = useState('SQL Editor');
30
32
  useEffect(() => {
31
33
  if (state.activeQuery) {
32
34
  setIsEditActive(true);
@@ -152,7 +154,7 @@ export default function DashboardBuilder({ navigateToDashboardManager, container
152
154
  borderLeftWidth: 0,
153
155
  borderRightWidth: 0,
154
156
  borderStyle: 'solid',
155
- borderColor: state.theme.borderColor,
157
+ borderColor: state.theme?.borderColor,
156
158
  paddingBottom: 20,
157
159
  // boxShadow: "0px 1px 4px 0px rgba(0, 0, 0, 0.07)",
158
160
  // paddingRight: '50px',
@@ -164,18 +166,57 @@ export default function DashboardBuilder({ navigateToDashboardManager, container
164
166
  alignItems: 'flex-end',
165
167
  justifyContent: 'space-between',
166
168
  width: '100%',
167
- }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx("h1", { style: {
168
- fontSize: '14px',
169
- paddingTop: '0px',
170
- marginTop: '0px',
171
- marginBottom: '4px',
172
- fontWeight: '600',
173
- color: state.theme.secondaryTextColor,
174
- fontFamily: state.theme.fontFamily,
175
- userSelect: 'none',
176
- }, children: "Environment" }), _jsx(EnvSelectPopover, { setEnvironment: (env) => {
177
- dispatch({ type: 'SET_ENVIRONMENT', payload: env });
178
- }, environment: state.environment, clients: state.clients, client: state.client, setClient: (client) => dispatch({ type: 'SET_CLIENT', payload: client }), theme: state.theme, showPromote: false })] }), !state.databaseTypeMismatch.show && (_jsx(OrgSelect, { environment: state.environment, setEnvironment: (env) => {
169
+ }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'row', gap: 12 }, children: [_jsxs("div", { style: { display: 'flex', flexDirection: 'column' }, children: [_jsx("h1", { style: {
170
+ fontSize: '14px',
171
+ paddingTop: '0px',
172
+ marginTop: '0px',
173
+ marginBottom: '4px',
174
+ fontWeight: '600',
175
+ color: state.theme.secondaryTextColor,
176
+ fontFamily: state.theme.fontFamily,
177
+ userSelect: 'none',
178
+ }, children: "Environment" }), _jsx(EnvSelectPopover, { setEnvironment: (env) => {
179
+ dispatch({ type: 'SET_ENVIRONMENT', payload: env });
180
+ }, environment: state.environment, clients: state.clients, client: state.client, setClient: (client) => dispatch({ type: 'SET_CLIENT', payload: client }), theme: state.theme, showPromote: false })] }), _jsx("div", { style: { display: 'flex', marginTop: 'auto', height: 38 }, children: _jsx("div", { style: {
181
+ display: 'flex',
182
+ flexDirection: 'row',
183
+ alignItems: 'center',
184
+ borderRadius: '0.25rem',
185
+ borderStyle: 'none',
186
+ outlineStyle: 'none',
187
+ background: '#F9FAFB',
188
+ paddingLeft: 3,
189
+ paddingRight: 3,
190
+ paddingTop: 4,
191
+ paddingBottom: 4,
192
+ }, children: modeToggleOptions.map((label) => (_jsx("button", { onClick: () => setToggleMode(label), style: {
193
+ borderRadius: '0.25rem',
194
+ borderWidth: '1px',
195
+ fontSize: '14px',
196
+ outlineStyle: 'none',
197
+ transitionProperty: 'background-color, border-color, color, fill, stroke, opacity, box-shadow, transform',
198
+ transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)',
199
+ transitionDuration: '300ms',
200
+ margin: '0px',
201
+ paddingTop: '0.375rem',
202
+ paddingBottom: '0.375rem',
203
+ paddingLeft: '0.75rem',
204
+ paddingRight: '0.75rem',
205
+ ...(label === toggleMode
206
+ ? {
207
+ fontWeight: 600,
208
+ backgroundColor: '#ffffff',
209
+ boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
210
+ color: '#212121',
211
+ borderColor: '#e7e7e7',
212
+ }
213
+ : {
214
+ borderColor: 'transparent',
215
+ fontWeight: 500,
216
+ backgroundColor: 'transparent',
217
+ color: '#606572',
218
+ }),
219
+ }, children: label }, label))) }) })] }), !state.databaseTypeMismatch.show && (_jsx(OrgSelect, { environment: state.environment, setEnvironment: (env) => {
179
220
  dispatch({ type: 'SET_ENVIRONMENT', payload: env });
180
221
  }, organizations: state.organizations, organizationId: state.organizationId, setOrganizationId: (orgId) => {
181
222
  dispatch({ type: 'SET_ORGANIZATION_ID', payload: orgId });
@@ -185,22 +226,78 @@ export default function DashboardBuilder({ navigateToDashboardManager, container
185
226
  return;
186
227
  dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
187
228
  dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
188
- } })), state.databaseTypeMismatch.show && (_jsx(DatabaseMismatchCard, { environemntName: state.client.name, environemntDatabaseType: state.client.databaseType, backendDatabaseType: state.databaseTypeMismatch.backendDatabaseType })), sqlEditor && !state.databaseTypeMismatch.show && (_jsx(SQLEditor, { chartBuilderEnabled: true, showAccessControlOptions: true, showDateFieldOptions: true, showTableFormatOptions: true, defaultQuery: query, isEditMode: !!state.activeQuery, addToDashboardButtonLabel: state.activeQuery ? 'Save changes' : 'Add to dashboard', chartBuilderTitle: state.activeQuery ? 'Save changes' : 'Add to dashboard', dashboardItem: state.activeQuery ? state.activeEditItem : undefined, onAddToDashboardComplete: () => {
189
- dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
190
- dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
191
- if (state.navigateToDashboardManager) {
192
- dispatch({
193
- type: 'SET_ACTIVE_COMPONENT',
194
- payload: 'Dashboards',
229
+ } })), state.databaseTypeMismatch.show && (_jsx(DatabaseMismatchCard, { environemntName: state.client.name, environemntDatabaseType: state.client.databaseType, backendDatabaseType: state.databaseTypeMismatch.backendDatabaseType })), _jsx("div", { style: {
230
+ // Toggle the height of the container so they both stay in the DOM
231
+ // and don't refetch when switching back and forth.
232
+ height: toggleMode === 'Report Builder' ? '100%' : 0,
233
+ overflow: 'hidden',
234
+ }, children: _jsx(ReportBuilder, { isAdminEnabled: true,
235
+ // initialTableName={state.tables.length > 0 && state.tables[0]!.name}
236
+ onSubmitCreateReport: (report) => {
237
+ const dashboard = state.dashboards.find((dash) => {
238
+ return dash.name === report.dashboardName;
239
+ });
240
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
241
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
242
+ if (state.navigateToDashboardManager) {
243
+ dispatch({
244
+ type: 'SET_ACTIVE_COMPONENT',
245
+ payload: 'Dashboards',
246
+ });
247
+ dispatch({
248
+ type: 'SET_SELECTED_DASHBOARD',
249
+ payload: dashboard,
250
+ });
251
+ state.navigateToDashboardManager();
252
+ }
253
+ }, onSubmitEditReport: (report) => {
254
+ const dashboard = state.dashboards.find((dash) => {
255
+ return dash.name === report.dashboardName;
195
256
  });
196
- state.navigateToDashboardManager();
197
- }
198
- }, containerStyle: {
199
- height: 'calc(100% - 96px)',
200
- width: '100%',
201
- // paddingRight: 25,
202
- // paddingTop: 25,
203
- }, organizationName: state.organizations.find((org) => {
204
- return (org.id && String(org.id) === String(state.organizationId));
205
- })?.name }))] }) }));
257
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
258
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
259
+ if (state.navigateToDashboardManager) {
260
+ dispatch({
261
+ type: 'SET_ACTIVE_COMPONENT',
262
+ payload: 'Dashboards',
263
+ });
264
+ dispatch({
265
+ type: 'SET_SELECTED_DASHBOARD',
266
+ payload: dashboard,
267
+ });
268
+ state.navigateToDashboardManager();
269
+ }
270
+ }, organizationName: state.organizations.find((org) => {
271
+ return (org.id && String(org.id) === String(state.organizationId));
272
+ })?.name, containerStyle: {
273
+ height: '100%',
274
+ width: '100%',
275
+ } }) }), sqlEditor && !state.databaseTypeMismatch.show && (_jsx("div", { style: {
276
+ height: toggleMode === 'SQL Editor' ? '100%' : 0,
277
+ overflow: 'hidden',
278
+ }, children: _jsx(SQLEditor, { isChartBuilderEnabled: true, showAccessControlOptions: true, showDateFieldOptions: true, showTableFormatOptions: true, defaultQuery: query, addToDashboardButtonLabel: state.activeQuery ? 'Save changes' : 'Add to dashboard', chartBuilderTitle: state.activeQuery ? 'Save changes' : 'Add to dashboard', report: state.activeQuery ? state.activeEditItem : undefined, onAddToDashboardComplete: (report) => {
279
+ const dashboard = state.dashboards.find((dash) => {
280
+ return dash.name === report.dashboardName;
281
+ });
282
+ dispatch({ type: 'SET_ACTIVE_QUERY', payload: '' });
283
+ dispatch({ type: 'SET_ACTIVE_EDIT_ITEM', payload: null });
284
+ if (state.navigateToDashboardManager) {
285
+ dispatch({
286
+ type: 'SET_ACTIVE_COMPONENT',
287
+ payload: 'Dashboards',
288
+ });
289
+ dispatch({
290
+ type: 'SET_SELECTED_DASHBOARD',
291
+ payload: dashboard,
292
+ });
293
+ state.navigateToDashboardManager();
294
+ }
295
+ }, containerStyle: {
296
+ height: '100%',
297
+ width: '100%',
298
+ // paddingRight: 25,
299
+ // paddingTop: 25,
300
+ }, organizationName: state.organizations.find((org) => {
301
+ return (org.id && String(org.id) === String(state.organizationId));
302
+ })?.name }) }))] }) }));
206
303
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardManager.d.ts","sourceRoot":"","sources":["../../../src/public_components/DashboardManager.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA+B,MAAM,OAAO,CAAC;AAgCnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,0BAA0B,EAC1B,cAAc,GACf,EAAE;IACD,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC,2CAkkBA"}
1
+ {"version":3,"file":"DashboardManager.d.ts","sourceRoot":"","sources":["../../../src/public_components/DashboardManager.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA+B,MAAM,OAAO,CAAC;AA0BnE,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,EACvC,0BAA0B,EAC1B,cAAc,GACf,EAAE;IACD,0BAA0B,CAAC,EAAE,MAAM,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,aAAa,CAAC;CAChC,2CAofA"}