datajunction-ui 0.0.2-0.dev1 → 0.0.2-3.dev1
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 +4 -4
- package/src/app/components/NotificationBell.tsx +11 -5
- package/src/app/components/UserMenu.tsx +3 -11
- package/src/app/components/__tests__/NotificationBell.test.tsx +17 -6
- package/src/app/components/__tests__/UserMenu.test.tsx +10 -3
- package/src/app/index.tsx +92 -85
- package/src/app/pages/AddEditNodePage/OwnersField.jsx +2 -3
- package/src/app/pages/NamespacePage/index.jsx +2 -4
- package/src/app/pages/NodePage/ClientCodePopover.jsx +27 -5
- package/src/app/pages/NodePage/NodeDependenciesTab.jsx +47 -45
- package/src/app/pages/NodePage/NodeInfoTab.jsx +73 -15
- package/src/app/pages/NodePage/__tests__/NodeDependenciesTab.test.jsx +13 -7
- package/src/app/pages/NodePage/__tests__/NodePage.test.jsx +23 -13
- package/src/app/pages/NodePage/index.jsx +14 -19
- package/src/app/pages/SettingsPage/__tests__/index.test.jsx +4 -1
- package/src/app/pages/SettingsPage/index.jsx +6 -6
- package/src/app/providers/UserProvider.tsx +78 -0
- package/src/app/services/DJService.js +43 -0
- package/src/app/services/__tests__/DJService.test.jsx +76 -0
- package/src/styles/nav-bar.css +5 -5
- package/webpack.config.js +3 -1
- package/cleanup-deps.sh +0 -70
- package/runit.sh +0 -30
- package/runit2.sh +0 -30
- package/src/app/icons/WrenchIcon.jsx +0 -36
- package/src/app/pages/AddEditNodePage/ColumnMetadata.jsx +0 -61
- package/src/app/pages/AddEditNodePage/ColumnsMetadataInput.jsx +0 -72
- package/src/app/pages/AddEditNodePage/ExperimentationExtension.jsx +0 -338
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
2
|
-
import { useFormikContext } from 'formik';
|
|
3
|
-
import { ColumnsSelect } from 'datajunction-ui/src/app/pages/AddEditNodePage/ColumnsSelect';
|
|
4
|
-
|
|
5
|
-
const AllocationJoinHeader = () => {
|
|
6
|
-
return (
|
|
7
|
-
<div
|
|
8
|
-
style={{
|
|
9
|
-
display: 'flex',
|
|
10
|
-
alignItems: 'center',
|
|
11
|
-
justifyContent: 'space-between',
|
|
12
|
-
cursor: 'pointer',
|
|
13
|
-
fontSize: '16px',
|
|
14
|
-
fontWeight: 'bold',
|
|
15
|
-
padding: '10px',
|
|
16
|
-
borderRadius: '6px',
|
|
17
|
-
transition: 'background 0.2s',
|
|
18
|
-
}}
|
|
19
|
-
>
|
|
20
|
-
🔥 Fields to enable automatic allocation joins for use in ABlaze
|
|
21
|
-
</div>
|
|
22
|
-
);
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const AllocationUnitTypeHeader = ({ unit }) => {
|
|
26
|
-
return (
|
|
27
|
-
<span
|
|
28
|
-
style={{
|
|
29
|
-
backgroundColor: '#fff7ea',
|
|
30
|
-
color: '#333',
|
|
31
|
-
fontWeight: '600',
|
|
32
|
-
width: '100%',
|
|
33
|
-
borderRadius: '8px 8px 0 0',
|
|
34
|
-
padding: '15px',
|
|
35
|
-
display: 'inline-block',
|
|
36
|
-
marginBottom: '10px',
|
|
37
|
-
borderBottom: '1px solid #ffe2b2',
|
|
38
|
-
textTransform: 'capitalize',
|
|
39
|
-
}}
|
|
40
|
-
>
|
|
41
|
-
Allocation Unit Type: {unit.replace('_', ' ')}
|
|
42
|
-
</span>
|
|
43
|
-
);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
const AddAllocationJoin = ({ onClick }) => {
|
|
47
|
-
return (
|
|
48
|
-
<button
|
|
49
|
-
onClick={onClick}
|
|
50
|
-
style={{
|
|
51
|
-
marginTop: '10px',
|
|
52
|
-
cursor: 'pointer',
|
|
53
|
-
textTransform: 'none',
|
|
54
|
-
background: '#ffe4b2',
|
|
55
|
-
padding: '15px',
|
|
56
|
-
fontWeight: '400',
|
|
57
|
-
fontSize: '16px',
|
|
58
|
-
display: 'none',
|
|
59
|
-
}}
|
|
60
|
-
>
|
|
61
|
-
➕ Add another allocation join type
|
|
62
|
-
</button>
|
|
63
|
-
);
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export const ExperimentationExtension = ({
|
|
67
|
-
node,
|
|
68
|
-
action,
|
|
69
|
-
registerSubmitHandler,
|
|
70
|
-
}) => {
|
|
71
|
-
const AllocationUnitType = Object.freeze({
|
|
72
|
-
ACCOUNT_ID: {
|
|
73
|
-
name: 'account_id',
|
|
74
|
-
node: 'common.dimensions.xp.allocation_day',
|
|
75
|
-
},
|
|
76
|
-
VISITOR_DEVICE_ID: { name: 'visitor_device_id', node: null },
|
|
77
|
-
PARTNER_VISITOR_DEVICE_ID: {
|
|
78
|
-
name: 'partner_visitor_device_id',
|
|
79
|
-
node: null,
|
|
80
|
-
},
|
|
81
|
-
PARTNER_ACCOUNT_ID: { name: 'partner_account_id', node: null },
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
const ALLOCATION_LINK_FIELD = 'allocation_links';
|
|
85
|
-
|
|
86
|
-
const { values, setFieldValue } = useFormikContext();
|
|
87
|
-
|
|
88
|
-
const [allocationConfigFields, setAllocationConfigFields] = useState({});
|
|
89
|
-
|
|
90
|
-
// Extracts any Allocation dimension node links
|
|
91
|
-
const getAllocationLinks = node => {
|
|
92
|
-
return Object.values(AllocationUnitType)
|
|
93
|
-
.map(alloc => ({
|
|
94
|
-
...alloc,
|
|
95
|
-
link:
|
|
96
|
-
node?.dimension_links?.find(
|
|
97
|
-
link => link.dimension.name === alloc.node,
|
|
98
|
-
) || null,
|
|
99
|
-
}))
|
|
100
|
-
.filter(alloc => alloc.link !== null);
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const linkAllocations = async (
|
|
104
|
-
nodeName,
|
|
105
|
-
allocationNode,
|
|
106
|
-
allocationUnit,
|
|
107
|
-
eventTimestamp,
|
|
108
|
-
) => {
|
|
109
|
-
const response = await fetch(
|
|
110
|
-
`${process.env.REACT_APP_DJ_URL}/nodes/${nodeName}/link/${allocationNode}`,
|
|
111
|
-
{
|
|
112
|
-
method: 'POST',
|
|
113
|
-
headers: {
|
|
114
|
-
'Content-Type': 'application/json',
|
|
115
|
-
},
|
|
116
|
-
body: JSON.stringify({
|
|
117
|
-
event_timestamp_column: eventTimestamp,
|
|
118
|
-
account_id_column: allocationUnit,
|
|
119
|
-
}),
|
|
120
|
-
credentials: 'include',
|
|
121
|
-
},
|
|
122
|
-
);
|
|
123
|
-
return { status: response.status, json: await response.json() };
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
const unlinkAllocations = async (nodeName, allocationNode) => {
|
|
127
|
-
const response = await fetch(
|
|
128
|
-
`${process.env.REACT_APP_DJ_URL}/nodes/${nodeName}/link`,
|
|
129
|
-
{
|
|
130
|
-
method: 'DELETE',
|
|
131
|
-
headers: {
|
|
132
|
-
'Content-Type': 'application/json',
|
|
133
|
-
},
|
|
134
|
-
body: JSON.stringify({ dimension_node: allocationNode }),
|
|
135
|
-
credentials: 'include',
|
|
136
|
-
},
|
|
137
|
-
);
|
|
138
|
-
return { status: response.status, json: await response.json() };
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
const handleSubmit = async (values, { setSubmitting, setStatus }) => {
|
|
142
|
-
for (const [unit, fields] of Object.entries(
|
|
143
|
-
values[ALLOCATION_LINK_FIELD],
|
|
144
|
-
)) {
|
|
145
|
-
const shouldDelete = Object.values(fields).every(
|
|
146
|
-
value => value === null || value === '',
|
|
147
|
-
);
|
|
148
|
-
const linkResponse = shouldDelete
|
|
149
|
-
? await unlinkAllocations(
|
|
150
|
-
values.name,
|
|
151
|
-
AllocationUnitType[unit.toUpperCase()].node,
|
|
152
|
-
)
|
|
153
|
-
: await linkAllocations(
|
|
154
|
-
values.name,
|
|
155
|
-
AllocationUnitType[unit.toUpperCase()].node,
|
|
156
|
-
fields.allocation_unit,
|
|
157
|
-
fields.event_timestamp,
|
|
158
|
-
);
|
|
159
|
-
if (
|
|
160
|
-
linkResponse.status === 200 ||
|
|
161
|
-
linkResponse.status === 201 ||
|
|
162
|
-
linkResponse.status === 204
|
|
163
|
-
) {
|
|
164
|
-
const verbiage = shouldDelete ? 'removed the link' : 'linked it';
|
|
165
|
-
setStatus({
|
|
166
|
-
success: (
|
|
167
|
-
<>
|
|
168
|
-
Successfully {action.name}ed {values.type} node{' '}
|
|
169
|
-
<a href={`/nodes/${values.name}`}>{values.name}</a> and {verbiage}{' '}
|
|
170
|
-
with{' '}
|
|
171
|
-
<a href={`/nodes/${AllocationUnitType[unit.toUpperCase()].node}`}>
|
|
172
|
-
Allocations
|
|
173
|
-
</a>
|
|
174
|
-
!
|
|
175
|
-
</>
|
|
176
|
-
),
|
|
177
|
-
});
|
|
178
|
-
} else {
|
|
179
|
-
if (linkResponse.status === 404) {
|
|
180
|
-
setStatus({
|
|
181
|
-
failure: `The DJ API is not set up to support linking to ${
|
|
182
|
-
AllocationUnitType[unit.toUpperCase()].node
|
|
183
|
-
}.`,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
// Register this function so the main form can call it on submit
|
|
191
|
-
useEffect(() => {
|
|
192
|
-
if (registerSubmitHandler) {
|
|
193
|
-
if (action.name === 'edit') {
|
|
194
|
-
registerSubmitHandler(handleSubmit, { prepend: false });
|
|
195
|
-
} else {
|
|
196
|
-
registerSubmitHandler(handleSubmit, { prepend: false });
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
}, []);
|
|
200
|
-
|
|
201
|
-
const getAllocationUnitColumn = link => {
|
|
202
|
-
return Object.entries(link.link.foreign_keys)
|
|
203
|
-
.find(([_, value]) => value === `${link.node}.${link.name}`)?.[0]
|
|
204
|
-
?.replace(node.name + '.', '');
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const getEventTimestampColumn = link => {
|
|
208
|
-
return Object.entries(link.link.foreign_keys)
|
|
209
|
-
.find(([_, value]) => value === null)?.[0]
|
|
210
|
-
?.replace(node.name + '.', '');
|
|
211
|
-
};
|
|
212
|
-
|
|
213
|
-
const createColumnsSelect = (
|
|
214
|
-
fieldName,
|
|
215
|
-
label,
|
|
216
|
-
placeholder,
|
|
217
|
-
defaultValue = null,
|
|
218
|
-
) => (
|
|
219
|
-
<ColumnsSelect
|
|
220
|
-
defaultValue={defaultValue}
|
|
221
|
-
fieldName={fieldName}
|
|
222
|
-
label={label}
|
|
223
|
-
labelStyle={{
|
|
224
|
-
textTransform: 'revert',
|
|
225
|
-
fontFamily: 'inherit',
|
|
226
|
-
fontWeight: 'inherit',
|
|
227
|
-
}}
|
|
228
|
-
placeholder={placeholder}
|
|
229
|
-
isClearable={true}
|
|
230
|
-
/>
|
|
231
|
-
);
|
|
232
|
-
|
|
233
|
-
useEffect(() => {
|
|
234
|
-
const allocationLinks = getAllocationLinks(node);
|
|
235
|
-
if (
|
|
236
|
-
action.name === 'add' ||
|
|
237
|
-
(node &&
|
|
238
|
-
!Array.isArray(node) &&
|
|
239
|
-
node.length !== 0 &&
|
|
240
|
-
allocationLinks.length === 0)
|
|
241
|
-
) {
|
|
242
|
-
setAllocationConfigFields(prevFields => ({
|
|
243
|
-
...prevFields,
|
|
244
|
-
[AllocationUnitType.ACCOUNT_ID.name]: {
|
|
245
|
-
allocationUnit: createColumnsSelect(
|
|
246
|
-
`${ALLOCATION_LINK_FIELD}.${AllocationUnitType.ACCOUNT_ID.name}.allocation_unit`,
|
|
247
|
-
`Column that maps to ${AllocationUnitType.ACCOUNT_ID.name.replace(
|
|
248
|
-
'_',
|
|
249
|
-
' ',
|
|
250
|
-
)}`,
|
|
251
|
-
'Choose Account ID Column',
|
|
252
|
-
),
|
|
253
|
-
eventTimestamp: createColumnsSelect(
|
|
254
|
-
`${ALLOCATION_LINK_FIELD}.${AllocationUnitType.ACCOUNT_ID.name}.event_timestamp`,
|
|
255
|
-
'Event Timestamp Column',
|
|
256
|
-
'Choose Event Timestamp Column',
|
|
257
|
-
),
|
|
258
|
-
},
|
|
259
|
-
}));
|
|
260
|
-
} else {
|
|
261
|
-
for (const link of allocationLinks) {
|
|
262
|
-
const allocationUnit = getAllocationUnitColumn(link);
|
|
263
|
-
const eventTimestamp = getEventTimestampColumn(link);
|
|
264
|
-
|
|
265
|
-
setFieldValue(
|
|
266
|
-
`${ALLOCATION_LINK_FIELD}.${link.name}.allocation_unit`,
|
|
267
|
-
allocationUnit || '',
|
|
268
|
-
false,
|
|
269
|
-
);
|
|
270
|
-
setFieldValue(
|
|
271
|
-
`${ALLOCATION_LINK_FIELD}.${link.name}.event_timestamp`,
|
|
272
|
-
eventTimestamp || '',
|
|
273
|
-
false,
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
setAllocationConfigFields(prevFields => ({
|
|
277
|
-
...prevFields,
|
|
278
|
-
[link.name]: {
|
|
279
|
-
allocationUnit: createColumnsSelect(
|
|
280
|
-
`${ALLOCATION_LINK_FIELD}.${link.name}.allocation_unit`,
|
|
281
|
-
`Column that maps to ${link.name.replace('_', ' ')}`,
|
|
282
|
-
'Choose Account ID Column',
|
|
283
|
-
allocationUnit,
|
|
284
|
-
),
|
|
285
|
-
eventTimestamp: createColumnsSelect(
|
|
286
|
-
`${ALLOCATION_LINK_FIELD}.${link.name}.event_timestamp`,
|
|
287
|
-
'Event Timestamp Column',
|
|
288
|
-
'Choose Event Timestamp Column',
|
|
289
|
-
eventTimestamp,
|
|
290
|
-
),
|
|
291
|
-
},
|
|
292
|
-
}));
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
}, [node]);
|
|
296
|
-
|
|
297
|
-
if (
|
|
298
|
-
node?.type !== 'transform' &&
|
|
299
|
-
window.location.pathname.split('/')[2] !== 'transform'
|
|
300
|
-
) {
|
|
301
|
-
return <></>;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return (
|
|
305
|
-
<>
|
|
306
|
-
{
|
|
307
|
-
<div
|
|
308
|
-
style={{
|
|
309
|
-
borderRadius: '8px',
|
|
310
|
-
padding: '10px 10px 20px 10px',
|
|
311
|
-
margin: '32px 0',
|
|
312
|
-
background: '#f9f9f9',
|
|
313
|
-
width: 'max-content',
|
|
314
|
-
}}
|
|
315
|
-
>
|
|
316
|
-
<AllocationJoinHeader />
|
|
317
|
-
{Object.keys(allocationConfigFields).map(unit => (
|
|
318
|
-
<>
|
|
319
|
-
<div
|
|
320
|
-
style={{
|
|
321
|
-
backgroundColor: '#ffffff',
|
|
322
|
-
borderRadius: '8px',
|
|
323
|
-
margin: '15px 25px',
|
|
324
|
-
paddingBottom: '10px',
|
|
325
|
-
border: '1px solid #ffe2b2',
|
|
326
|
-
}}
|
|
327
|
-
>
|
|
328
|
-
<AllocationUnitTypeHeader unit={unit} />
|
|
329
|
-
{Object.values(allocationConfigFields[unit])}
|
|
330
|
-
</div>
|
|
331
|
-
<AddAllocationJoin />
|
|
332
|
-
</>
|
|
333
|
-
))}
|
|
334
|
-
</div>
|
|
335
|
-
}
|
|
336
|
-
</>
|
|
337
|
-
);
|
|
338
|
-
};
|