@bindu-dashing/dam-solution-v2 5.8.190 → 5.8.194
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/build/AssetType/AddFieldProperties.js +38 -5
- package/build/CreateClient/CreateClientBtn.js +30 -8
- package/build/CreateClient/CreateClientForm.js +115 -39
- package/build/MyDrive/FolderTree.js +8 -2
- package/build/MyDrive/MyDriveMainContainer.d.ts +1 -1
- package/build/MyDrive/MyDriveMainContainer.js +9 -6
- package/build/MyDrive/index.d.ts +1 -1
- package/build/MyDrive/routes.d.ts +1 -1
- package/build/RefreshKey/RefreshKeyBtn.js +25 -8
- package/package.json +1 -1
|
@@ -214,13 +214,42 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
|
|
|
214
214
|
setDisabledReason(null);
|
|
215
215
|
}, 100);
|
|
216
216
|
}, [field, form]);
|
|
217
|
+
// Strip time from dayjs (set to midnight) - used when "Allow time" is toggled OFF
|
|
218
|
+
const stripTimeFromDayjs = (d) => {
|
|
219
|
+
if (!d || typeof d.hour !== "function")
|
|
220
|
+
return d;
|
|
221
|
+
return d.hour(0).minute(0).second(0).millisecond(0);
|
|
222
|
+
};
|
|
217
223
|
// Update defaultValueInput whenever form values change
|
|
218
|
-
const handleFormValuesChange = () => {
|
|
224
|
+
const handleFormValuesChange = (changedValues, allValues) => {
|
|
219
225
|
var _a;
|
|
220
|
-
const formValues = form.getFieldsValue(true);
|
|
226
|
+
const formValues = allValues !== null && allValues !== void 0 ? allValues : form.getFieldsValue(true);
|
|
221
227
|
const defaultName = currentInputType === null || currentInputType === void 0 ? void 0 : currentInputType.defaultName;
|
|
228
|
+
// When "Allow time" is toggled OFF for DATE/DATE_RANGE, strip time from defaultValue
|
|
229
|
+
const settings = get(formValues, "inputTypeSettings", {});
|
|
230
|
+
const allowTime = !!get(settings, `${InputSupportedTypes.ALLOW_TIME}.allow`);
|
|
231
|
+
const allowTimeChanged = changedValues && get(changedValues, "inputTypeSettings");
|
|
232
|
+
if (allowTimeChanged &&
|
|
233
|
+
!allowTime &&
|
|
234
|
+
(defaultName === InputTypes.DATE || defaultName === InputTypes.DATE_RANGE)) {
|
|
235
|
+
const currentDefault = get(formValues, "defaultValue");
|
|
236
|
+
if (currentDefault) {
|
|
237
|
+
let normalized = null;
|
|
238
|
+
if (defaultName === InputTypes.DATE_RANGE && isArray(currentDefault)) {
|
|
239
|
+
normalized = [
|
|
240
|
+
stripTimeFromDayjs(first(currentDefault)),
|
|
241
|
+
stripTimeFromDayjs(nth(currentDefault, 1)),
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
else if (defaultName === InputTypes.DATE) {
|
|
245
|
+
normalized = stripTimeFromDayjs(currentDefault);
|
|
246
|
+
}
|
|
247
|
+
if (normalized !== null) {
|
|
248
|
+
form.setFieldValue("defaultValue", normalized);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
222
252
|
const options = ((_a = formValues.options) === null || _a === void 0 ? void 0 : _a.filter((opt) => (opt === null || opt === void 0 ? void 0 : opt.label) && (opt === null || opt === void 0 ? void 0 : opt.value))) || [];
|
|
223
|
-
const settings = formValues.inputTypeSettings || {};
|
|
224
253
|
const isOptionsBasedField = includes([InputTypes.SELECT, InputTypes.CHECKBOX, InputTypes.RADIO], defaultName);
|
|
225
254
|
if (isOptionsBasedField && options.length === 0) {
|
|
226
255
|
// Don't show Default Value field if no options exist
|
|
@@ -296,10 +325,12 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
|
|
|
296
325
|
typeof value.hour === "function" &&
|
|
297
326
|
typeof value.minute === "function" &&
|
|
298
327
|
typeof value.second === "function";
|
|
328
|
+
// When time is allowed: accept any moment with time methods (including 00:00:00 - midnight is valid)
|
|
329
|
+
// Only reject if value lacks time methods (e.g. date-only format)
|
|
299
330
|
if (allowTime && !hasTimeMethods) {
|
|
300
331
|
return Promise.reject("Please select a date with time (hour/minute/second).");
|
|
301
332
|
}
|
|
302
|
-
// When time is not allowed: reject only if
|
|
333
|
+
// When time is not allowed: strip time (handled in onValuesChange) - reject only if still has non-zero time
|
|
303
334
|
if (!allowTime && hasNonZeroTime(value)) {
|
|
304
335
|
return Promise.reject("Time is not allowed. Please select only a date.");
|
|
305
336
|
}
|
|
@@ -315,10 +346,12 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
|
|
|
315
346
|
typeof end.hour === "function" &&
|
|
316
347
|
typeof end.minute === "function" &&
|
|
317
348
|
typeof end.second === "function";
|
|
349
|
+
// When time is allowed: accept any moment with time methods (including 00:00:00 - midnight is valid)
|
|
350
|
+
// Only reject if start or end lacks time methods
|
|
318
351
|
if (allowTime && (!startHasTimeMethods || !endHasTimeMethods)) {
|
|
319
352
|
return Promise.reject("Please select both start and end dates with time.");
|
|
320
353
|
}
|
|
321
|
-
// When time is not allowed: reject only if
|
|
354
|
+
// When time is not allowed: strip time (handled in onValuesChange) - reject only if still has non-zero time
|
|
322
355
|
if (!allowTime && (hasNonZeroTime(start) || hasNonZeroTime(end))) {
|
|
323
356
|
return Promise.reject("Time is not allowed. Please select only dates.");
|
|
324
357
|
}
|
|
@@ -9,11 +9,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
11
11
|
import { Button, Space } from "antd";
|
|
12
|
-
import { useState
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import axios from "axios";
|
|
13
14
|
import CreateClientForm from "./CreateClientForm";
|
|
14
15
|
import { useDamConfig } from "../hocs/DamConfigContext";
|
|
15
|
-
import {
|
|
16
|
-
import { REFRESH_KEY_URL } from "../utilities/constants/apiUrls";
|
|
16
|
+
import { getBaseUrl } from "../hocs/helpers";
|
|
17
|
+
import { REFRESH_KEY_URL, USER_LOGIN } from "../utilities/constants/apiUrls";
|
|
17
18
|
import { showNotification } from "../common/notifications";
|
|
18
19
|
import { NotificationStatus } from "../utilities/constants/interface";
|
|
19
20
|
import { SOMETHING_WENT_WRONG } from "../utilities/constants/messages";
|
|
@@ -23,7 +24,7 @@ const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password
|
|
|
23
24
|
const [refreshingKey, setRefreshingKey] = useState(false);
|
|
24
25
|
const isEditMode = !!existingClientData;
|
|
25
26
|
const damConfig = useDamConfig();
|
|
26
|
-
const
|
|
27
|
+
const { appType, teamIds } = damConfig;
|
|
27
28
|
const toggleShow = () => {
|
|
28
29
|
setShowForm(!showForm);
|
|
29
30
|
};
|
|
@@ -32,11 +33,32 @@ const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password
|
|
|
32
33
|
showNotification("Access key and secret key are required to refresh", NotificationStatus.ERROR);
|
|
33
34
|
return;
|
|
34
35
|
}
|
|
36
|
+
const accessKey = existingClientData.accessKey;
|
|
37
|
+
const secretKey = existingClientData.secretKey;
|
|
38
|
+
const subdomain = existingClientData.subdomain || clientSubdomain || (damConfig === null || damConfig === void 0 ? void 0 : damConfig.subdomain) || "";
|
|
39
|
+
if (!subdomain) {
|
|
40
|
+
showNotification("Subdomain is required to refresh key", NotificationStatus.ERROR);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
35
43
|
setRefreshingKey(true);
|
|
36
44
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
// Step 1: Login with keys to get DAM token (same as Edit Client flow)
|
|
46
|
+
const loginResponse = yield axios.post(getBaseUrl(appType) + USER_LOGIN, {
|
|
47
|
+
accessKey,
|
|
48
|
+
secretKey,
|
|
49
|
+
subdomain,
|
|
50
|
+
teams: teamIds && teamIds.length > 0 ? teamIds : [""],
|
|
51
|
+
});
|
|
52
|
+
const token = get(loginResponse, "data.data.access_token");
|
|
53
|
+
if (!token) {
|
|
54
|
+
throw new Error("Failed to get token from login");
|
|
55
|
+
}
|
|
56
|
+
// Step 2: Call refresh API with the DAM token (include subdomain header)
|
|
57
|
+
const response = yield axios.put(getBaseUrl(appType) + REFRESH_KEY_URL, { accessKey, secretKey }, {
|
|
58
|
+
headers: {
|
|
59
|
+
Authorization: `Bearer ${token}`,
|
|
60
|
+
subdomain: subdomain,
|
|
61
|
+
},
|
|
40
62
|
});
|
|
41
63
|
setRefreshingKey(false);
|
|
42
64
|
showNotification(get(response, "data.message", "Key refreshed successfully"), NotificationStatus.SUCCESS);
|
|
@@ -45,7 +67,7 @@ const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password
|
|
|
45
67
|
}
|
|
46
68
|
}
|
|
47
69
|
catch (error) {
|
|
48
|
-
showNotification(get(error, "message", SOMETHING_WENT_WRONG), NotificationStatus.ERROR);
|
|
70
|
+
showNotification(get(error, "response.data.message", get(error, "message", SOMETHING_WENT_WRONG)), NotificationStatus.ERROR);
|
|
49
71
|
setRefreshingKey(false);
|
|
50
72
|
}
|
|
51
73
|
});
|
|
@@ -19,7 +19,7 @@ import { getBaseUrl } from "../hocs/helpers";
|
|
|
19
19
|
import { CREATE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
|
|
20
20
|
import { NotificationStatus } from "../utilities/constants/interface";
|
|
21
21
|
import { showNotification } from "../common/notifications";
|
|
22
|
-
import { get } from "lodash";
|
|
22
|
+
import { get, isEqual } from "lodash";
|
|
23
23
|
const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess, clientSubdomain, existingClientData, }) => {
|
|
24
24
|
const damConfig = useDamConfig();
|
|
25
25
|
const { appType } = damConfig;
|
|
@@ -34,6 +34,51 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
|
|
|
34
34
|
const api = useMemo(() => createApiClient(damConfig), [damConfig]);
|
|
35
35
|
const [form] = Form.useForm();
|
|
36
36
|
const isEditMode = !!existingClientData;
|
|
37
|
+
// Watch form values to enable/disable Submit button
|
|
38
|
+
const formValues = Form.useWatch([], form);
|
|
39
|
+
const isFormValid = useMemo(() => {
|
|
40
|
+
var _a;
|
|
41
|
+
if (!formValues)
|
|
42
|
+
return false;
|
|
43
|
+
// In edit mode, disabled fields (subdomain, damLocationDetails) may be excluded from form values - use clientData as fallback
|
|
44
|
+
const damLocationDetails = formValues.damLocationDetails || get(clientData, "damLocationDetails", {}) || {};
|
|
45
|
+
const name = formValues.name;
|
|
46
|
+
const accessTypes = formValues.accessTypes;
|
|
47
|
+
const adminTeams = formValues.adminTeams;
|
|
48
|
+
const subdomain = (_a = formValues.subdomain) !== null && _a !== void 0 ? _a : (isEditMode ? (get(clientData, "subdomain") || (existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.subdomain)) : undefined);
|
|
49
|
+
const type = damLocationDetails.type;
|
|
50
|
+
const rootPath = damLocationDetails.rootPath;
|
|
51
|
+
if (!(name === null || name === void 0 ? void 0 : name.trim()))
|
|
52
|
+
return false;
|
|
53
|
+
if (!(accessTypes === null || accessTypes === void 0 ? void 0 : accessTypes.length))
|
|
54
|
+
return false;
|
|
55
|
+
if (!(adminTeams === null || adminTeams === void 0 ? void 0 : adminTeams.length))
|
|
56
|
+
return false;
|
|
57
|
+
if (!(subdomain === null || subdomain === void 0 ? void 0 : subdomain.trim()))
|
|
58
|
+
return false;
|
|
59
|
+
if (!type)
|
|
60
|
+
return false;
|
|
61
|
+
if (!(rootPath === null || rootPath === void 0 ? void 0 : rootPath.trim()))
|
|
62
|
+
return false;
|
|
63
|
+
if (damLocationType === "external") {
|
|
64
|
+
const bucket = damLocationDetails.bucket;
|
|
65
|
+
const accessKeyId = damLocationDetails.accessKeyId;
|
|
66
|
+
const secretAccessKey = damLocationDetails.secretAccessKey;
|
|
67
|
+
const url = damLocationDetails.url;
|
|
68
|
+
const region = damLocationDetails.region;
|
|
69
|
+
if (!(bucket === null || bucket === void 0 ? void 0 : bucket.trim()))
|
|
70
|
+
return false;
|
|
71
|
+
if (!(accessKeyId === null || accessKeyId === void 0 ? void 0 : accessKeyId.trim()))
|
|
72
|
+
return false;
|
|
73
|
+
if (!(secretAccessKey === null || secretAccessKey === void 0 ? void 0 : secretAccessKey.trim()))
|
|
74
|
+
return false;
|
|
75
|
+
if (!(url === null || url === void 0 ? void 0 : url.trim()))
|
|
76
|
+
return false;
|
|
77
|
+
if (!(region === null || region === void 0 ? void 0 : region.trim()))
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
return true;
|
|
81
|
+
}, [formValues, damLocationType, isEditMode, clientData, existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.subdomain]);
|
|
37
82
|
const onChangeDamLocationType = (e) => {
|
|
38
83
|
setDamLocationType(e);
|
|
39
84
|
form.setFieldValue("dam_location_details", { type: e });
|
|
@@ -152,7 +197,7 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
|
|
|
152
197
|
fetchClientData();
|
|
153
198
|
}, [isEditMode, existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.brandId, existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.subdomain, api, form]);
|
|
154
199
|
const onFinish = (data) => __awaiter(void 0, void 0, void 0, function* () {
|
|
155
|
-
var _a, _b, _c, _d
|
|
200
|
+
var _a, _b, _c, _d;
|
|
156
201
|
try {
|
|
157
202
|
// Use teamsApiDetails from clientData if available (from API response), otherwise use props
|
|
158
203
|
const teamsApiDetailsFromData = get(clientData, "teamsApiDetails", {});
|
|
@@ -163,54 +208,85 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
|
|
|
163
208
|
const adminTeamsAsStrings = Array.isArray(data.adminTeams)
|
|
164
209
|
? data.adminTeams.map((team) => String(team))
|
|
165
210
|
: [];
|
|
166
|
-
const values = Object.assign(Object.assign({}, data), { adminTeams: adminTeamsAsStrings, showFilePreview: (_a = data.showFilePreview) !== null && _a !== void 0 ? _a : false, accessKey: appType == "reactJs"
|
|
167
|
-
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY
|
|
168
|
-
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY, secretKey: appType == "reactJs"
|
|
169
|
-
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SECRET_KEY
|
|
170
|
-
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SECRET_KEY, parentSubdomain: appType == "reactJs"
|
|
171
|
-
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN
|
|
172
|
-
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN, teamsApiDetails: {
|
|
173
|
-
teamsApi: finalTeamsApi,
|
|
174
|
-
username: finalUsername,
|
|
175
|
-
password: finalPassword,
|
|
176
|
-
}, damLocationDetails: damLocationType === "external"
|
|
177
|
-
? {
|
|
178
|
-
bucket: (_b = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _b === void 0 ? void 0 : _b.bucket,
|
|
179
|
-
locationType: "EXTERNAL",
|
|
180
|
-
rootPath: (_c = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _c === void 0 ? void 0 : _c.rootPath,
|
|
181
|
-
accessKeyId: (_d = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _d === void 0 ? void 0 : _d.accessKeyId,
|
|
182
|
-
secretAccessKey: (_e = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _e === void 0 ? void 0 : _e.secretAccessKey,
|
|
183
|
-
url: (_f = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _f === void 0 ? void 0 : _f.url,
|
|
184
|
-
region: (_g = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _g === void 0 ? void 0 : _g.region,
|
|
185
|
-
}
|
|
186
|
-
: {
|
|
187
|
-
locationType: "INTERNAL",
|
|
188
|
-
rootPath: (_h = data === null || data === void 0 ? void 0 : data.damLocationDetails) === null || _h === void 0 ? void 0 : _h.rootPath,
|
|
189
|
-
} });
|
|
190
211
|
setLoading(true);
|
|
191
212
|
let response;
|
|
192
213
|
const baseUrl = getBaseUrl(appType);
|
|
193
214
|
if (isEditMode && brandIdForUpdate && authToken) {
|
|
194
|
-
//
|
|
195
|
-
const
|
|
215
|
+
// Edit mode: send only changed fields (partial update)
|
|
216
|
+
const originalAdminTeams = get(clientData, "adminTeams", []);
|
|
217
|
+
const originalAdminTeamsStr = Array.isArray(originalAdminTeams)
|
|
218
|
+
? originalAdminTeams.map((t) => String(t)).sort()
|
|
219
|
+
: [];
|
|
220
|
+
const newAdminTeamsStr = [...adminTeamsAsStrings].sort();
|
|
221
|
+
const payload = {};
|
|
222
|
+
if (data.name !== undefined && data.name !== get(clientData, "name")) {
|
|
223
|
+
payload.name = data.name;
|
|
224
|
+
}
|
|
225
|
+
if (!isEqual(newAdminTeamsStr, originalAdminTeamsStr)) {
|
|
226
|
+
payload.adminTeams = adminTeamsAsStrings;
|
|
227
|
+
}
|
|
228
|
+
if (!isEqual(data.accessTypes || [], get(clientData, "accessTypes", []))) {
|
|
229
|
+
payload.accessTypes = data.accessTypes;
|
|
230
|
+
}
|
|
231
|
+
if (((_a = data.showFilePreview) !== null && _a !== void 0 ? _a : false) !== get(clientData, "showFilePreview", false)) {
|
|
232
|
+
payload.showFilePreview = (_b = data.showFilePreview) !== null && _b !== void 0 ? _b : false;
|
|
233
|
+
}
|
|
234
|
+
if (Object.keys(payload).length === 0) {
|
|
235
|
+
setLoading(false);
|
|
236
|
+
showNotification("No changes to save", NotificationStatus.INFO);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const putResponse = yield axios.patch(`${baseUrl}/brands/${brandIdForUpdate}`, payload, {
|
|
196
240
|
headers: {
|
|
197
241
|
'Authorization': `Bearer ${authToken}`,
|
|
198
242
|
'Content-Type': 'application/json',
|
|
199
243
|
'accept': 'application/json, text/plain, */*'
|
|
200
244
|
}
|
|
201
245
|
});
|
|
202
|
-
// Extract data from axios response (API returns { data: {...} } or { data: { data: {...} } })
|
|
203
246
|
response = get(putResponse, "data.data", get(putResponse, "data", putResponse));
|
|
204
247
|
}
|
|
205
248
|
else {
|
|
249
|
+
// Create mode: send full payload
|
|
250
|
+
const damLocationDetailsFromForm = data === null || data === void 0 ? void 0 : data.damLocationDetails;
|
|
251
|
+
const subdomainValue = data.subdomain;
|
|
252
|
+
const values = Object.assign(Object.assign({}, data), { subdomain: subdomainValue, adminTeams: adminTeamsAsStrings, showFilePreview: (_c = data.showFilePreview) !== null && _c !== void 0 ? _c : false, accessKey: appType == "reactJs"
|
|
253
|
+
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY
|
|
254
|
+
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY, secretKey: appType == "reactJs"
|
|
255
|
+
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SECRET_KEY
|
|
256
|
+
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SECRET_KEY, parentSubdomain: appType == "reactJs"
|
|
257
|
+
? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN
|
|
258
|
+
: process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN, teamsApiDetails: {
|
|
259
|
+
teamsApi: finalTeamsApi,
|
|
260
|
+
username: finalUsername,
|
|
261
|
+
password: finalPassword,
|
|
262
|
+
}, damLocationDetails: damLocationType === "external"
|
|
263
|
+
? {
|
|
264
|
+
bucket: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.bucket,
|
|
265
|
+
locationType: "EXTERNAL",
|
|
266
|
+
rootPath: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.rootPath,
|
|
267
|
+
accessKeyId: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.accessKeyId,
|
|
268
|
+
secretAccessKey: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.secretAccessKey,
|
|
269
|
+
url: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.url,
|
|
270
|
+
region: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.region,
|
|
271
|
+
}
|
|
272
|
+
: {
|
|
273
|
+
locationType: "INTERNAL",
|
|
274
|
+
rootPath: damLocationDetailsFromForm === null || damLocationDetailsFromForm === void 0 ? void 0 : damLocationDetailsFromForm.rootPath,
|
|
275
|
+
} });
|
|
206
276
|
// Create new client: POST to /brands/sub-brand
|
|
207
277
|
response = yield api.post(CREATE_SUB_BRAND, values);
|
|
208
278
|
}
|
|
209
279
|
setLoading(false);
|
|
210
|
-
showNotification((
|
|
280
|
+
showNotification((_d = response === null || response === void 0 ? void 0 : response.message) !== null && _d !== void 0 ? _d : (get(response, "message") || CREATE_SUCCESS), NotificationStatus.SUCCESS);
|
|
211
281
|
toggleShow();
|
|
212
282
|
if (onSuccess) {
|
|
213
|
-
|
|
283
|
+
// Pass full brand object: API may return { data: {...} } or {...} directly
|
|
284
|
+
// For PATCH (edit), response may be partial - merge with clientData and existingClientData
|
|
285
|
+
// so parent gets accessKey, secretKey, subdomain (credentials may not be in API response)
|
|
286
|
+
const apiBrand = get(response, "data", response);
|
|
287
|
+
const brandData = isEditMode
|
|
288
|
+
? Object.assign(Object.assign(Object.assign({}, (clientData || {})), (existingClientData || {})), apiBrand) : apiBrand;
|
|
289
|
+
onSuccess(brandData);
|
|
214
290
|
}
|
|
215
291
|
}
|
|
216
292
|
catch (error) {
|
|
@@ -307,41 +383,41 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
|
|
|
307
383
|
},
|
|
308
384
|
], children: _jsx(Select, { options: DAM_LOCATION_TYPES, onChange: (e) => {
|
|
309
385
|
onChangeDamLocationType(e);
|
|
310
|
-
}, placeholder: "Type" }) }), _jsx(Form.Item, { label: "Root Path", name: ["damLocationDetails", "rootPath"], rules: [
|
|
386
|
+
}, placeholder: "Type", disabled: isEditMode }) }), _jsx(Form.Item, { label: "Root Path", name: ["damLocationDetails", "rootPath"], rules: [
|
|
311
387
|
{
|
|
312
388
|
required: true,
|
|
313
389
|
message: "Root path is required",
|
|
314
390
|
},
|
|
315
|
-
], children: _jsx(Input, { placeholder: "Root path" }) }), shouldShowExternalFields && (_jsxs(_Fragment, { children: [_jsx(Form.Item, { label: "Bucket", name: ["damLocationDetails", "bucket"], rules: [
|
|
391
|
+
], children: _jsx(Input, { placeholder: "Root path", disabled: isEditMode }) }), shouldShowExternalFields && (_jsxs(_Fragment, { children: [_jsx(Form.Item, { label: "Bucket", name: ["damLocationDetails", "bucket"], rules: [
|
|
316
392
|
{
|
|
317
393
|
required: damLocationType === "external",
|
|
318
394
|
message: "Bucket is required",
|
|
319
395
|
},
|
|
320
|
-
], children: _jsx(Input, { placeholder: "Bucket", disabled: damLocationType === "internal" }) }), _jsx(Form.Item, { label: "Access Key", name: ["damLocationDetails", "accessKeyId"], rules: [
|
|
396
|
+
], children: _jsx(Input, { placeholder: "Bucket", disabled: damLocationType === "internal" || isEditMode }) }), _jsx(Form.Item, { label: "Access Key", name: ["damLocationDetails", "accessKeyId"], rules: [
|
|
321
397
|
{
|
|
322
398
|
required: damLocationType === "external",
|
|
323
399
|
message: "Access key is required",
|
|
324
400
|
},
|
|
325
|
-
], children: _jsx(Input, { placeholder: "Access Key", disabled: damLocationType === "internal" }) }), _jsx(Form.Item, { label: "Secret Access Key", name: ["damLocationDetails", "secretAccessKey"], rules: [
|
|
401
|
+
], children: _jsx(Input, { placeholder: "Access Key", disabled: damLocationType === "internal" || isEditMode }) }), _jsx(Form.Item, { label: "Secret Access Key", name: ["damLocationDetails", "secretAccessKey"], rules: [
|
|
326
402
|
{
|
|
327
403
|
required: damLocationType === "external",
|
|
328
404
|
message: "Secret Access Key is required",
|
|
329
405
|
},
|
|
330
|
-
], children: _jsx(Input, { placeholder: "Secret Key", disabled: damLocationType === "internal" }) }), _jsx(Form.Item, { label: "Url", name: ["damLocationDetails", "url"], rules: [
|
|
406
|
+
], children: _jsx(Input, { placeholder: "Secret Key", disabled: damLocationType === "internal" || isEditMode }) }), _jsx(Form.Item, { label: "Url", name: ["damLocationDetails", "url"], rules: [
|
|
331
407
|
{
|
|
332
408
|
required: damLocationType === "external",
|
|
333
409
|
message: "Url is required",
|
|
334
410
|
},
|
|
335
|
-
], children: _jsx(Input, { placeholder: "Url", disabled: damLocationType === "internal" }) }), _jsx(Form.Item, { label: "Region", name: ["damLocationDetails", "region"], rules: [
|
|
411
|
+
], children: _jsx(Input, { placeholder: "Url", disabled: damLocationType === "internal" || isEditMode }) }), _jsx(Form.Item, { label: "Region", name: ["damLocationDetails", "region"], rules: [
|
|
336
412
|
{
|
|
337
413
|
required: damLocationType === "external",
|
|
338
414
|
message: "Region is required",
|
|
339
415
|
},
|
|
340
|
-
], children: _jsx(Input, { placeholder: "Region", disabled: damLocationType === "internal" }) })] }))] }), _jsx(Form.Item, { label: "Subdomain", name: "subdomain", rules: [
|
|
416
|
+
], children: _jsx(Input, { placeholder: "Region", disabled: damLocationType === "internal" || isEditMode }) })] }))] }), _jsx(Form.Item, { label: "Subdomain", name: "subdomain", rules: [
|
|
341
417
|
{
|
|
342
418
|
required: true,
|
|
343
419
|
message: "Subdomain is required",
|
|
344
420
|
},
|
|
345
|
-
], children: _jsx(Input, { placeholder: "Subdomain" }) }), _jsx(Form.Item, { name: "showFilePreview", valuePropName: "checked", initialValue: false, children: _jsx(Checkbox, { children: "Show File Preview Editor" }) }), _jsx(Form.Item, { children: _jsx(Button, { htmlType: "submit", type: "primary", block: true, loading: loading, children: "Submit" }) })] })) }));
|
|
421
|
+
], children: _jsx(Input, { placeholder: "Subdomain", disabled: isEditMode }) }), _jsx(Form.Item, { name: "showFilePreview", valuePropName: "checked", initialValue: false, children: _jsx(Checkbox, { children: "Show File Preview Editor" }) }), _jsx(Form.Item, { children: _jsx(Button, { htmlType: "submit", type: "primary", block: true, loading: loading, disabled: !isFormValid || loading, children: "Submit" }) })] })) }));
|
|
346
422
|
};
|
|
347
423
|
export default CreateClientForm;
|
|
@@ -233,7 +233,13 @@ function FolderTree({ currentRootId, expandedKeys, selectedKeys, handleExpand, s
|
|
|
233
233
|
prevCurrentRootIdRef.current = currentRootId;
|
|
234
234
|
}
|
|
235
235
|
else {
|
|
236
|
-
|
|
236
|
+
// When folders is empty and we have a subfolder ID (e.g. from URL refresh),
|
|
237
|
+
// fetch root first so the full tree is visible, then expand to the selected folder
|
|
238
|
+
if (folders.length === 0 && currentRootId !== rootFolderId) {
|
|
239
|
+
// Don't set prevCurrentRootIdRef yet - we need to re-run when folders is populated
|
|
240
|
+
fetchFolders(rootFolderId);
|
|
241
|
+
}
|
|
242
|
+
else if (currentRootId === rootFolderId || folders.length === 0) {
|
|
237
243
|
prevCurrentRootIdRef.current = currentRootId;
|
|
238
244
|
fetchFolders(currentRootId);
|
|
239
245
|
}
|
|
@@ -248,7 +254,7 @@ function FolderTree({ currentRootId, expandedKeys, selectedKeys, handleExpand, s
|
|
|
248
254
|
console.log('## FolderTree useEffect - globalSearch changed, refetching root folder');
|
|
249
255
|
fetchFolders(currentRootId);
|
|
250
256
|
}
|
|
251
|
-
}, [currentRootId, globalSearch]);
|
|
257
|
+
}, [currentRootId, globalSearch, folders]);
|
|
252
258
|
// ✅ Handle sort dropdown
|
|
253
259
|
const handleSortChange = (value) => {
|
|
254
260
|
setState((prevState) => {
|
|
@@ -2,5 +2,5 @@ import { type FolderTypes } from "../utilities/FoldersContext";
|
|
|
2
2
|
export default function MyDriveMainContainer({ folders, setFolders, onFolderChange, }: {
|
|
3
3
|
folders: FolderTypes[];
|
|
4
4
|
setFolders: React.Dispatch<React.SetStateAction<FolderTypes[]>>;
|
|
5
|
-
onFolderChange?: (folderId: string) => void;
|
|
5
|
+
onFolderChange?: (folderId: string | undefined) => void;
|
|
6
6
|
}): JSX.Element;
|
|
@@ -20,13 +20,13 @@ export default function MyDriveMainContainer({ folders, setFolders, onFolderChan
|
|
|
20
20
|
// Priority: URL params > Props from ParamsProvider > rootFolderId from config
|
|
21
21
|
if (params === null || params === void 0 ? void 0 : params.folderId) {
|
|
22
22
|
console.log('## Setting selectedKeys from params.folderId:', params.folderId);
|
|
23
|
-
setSelectedKeys(params.folderId);
|
|
23
|
+
setSelectedKeys(Array.isArray(params.folderId) ? params.folderId : [params.folderId]);
|
|
24
24
|
initializedFromParamsRef.current = true;
|
|
25
25
|
}
|
|
26
|
-
else if (!(params === null || params === void 0 ? void 0 : params.folderId) && rootFolderId && !selectedKeys && !initializedFromParamsRef.current) {
|
|
26
|
+
else if (!(params === null || params === void 0 ? void 0 : params.folderId) && rootFolderId && !(selectedKeys === null || selectedKeys === void 0 ? void 0 : selectedKeys.length) && !initializedFromParamsRef.current) {
|
|
27
27
|
// Only set to rootFolderId if no params AND selectedKeys is empty AND we haven't initialized from params
|
|
28
28
|
console.log('## No params.folderId and no selectedKeys, using rootFolderId:', rootFolderId);
|
|
29
|
-
setSelectedKeys(rootFolderId);
|
|
29
|
+
setSelectedKeys([rootFolderId]);
|
|
30
30
|
}
|
|
31
31
|
}, [params === null || params === void 0 ? void 0 : params.folderId, params === null || params === void 0 ? void 0 : params.id, params === null || params === void 0 ? void 0 : params.parentId]);
|
|
32
32
|
// Priority: selectedKeys > params > rootFolderId
|
|
@@ -51,13 +51,16 @@ export default function MyDriveMainContainer({ folders, setFolders, onFolderChan
|
|
|
51
51
|
setExpandedKeys(map(keys, (k) => k.toString()));
|
|
52
52
|
};
|
|
53
53
|
// Wrapper function to handle both string and string[] for setSelectedKeys
|
|
54
|
+
// Also updates URL via onFolderChange so folder persists on refresh
|
|
54
55
|
const handleSetSelectedKeys = (keys) => {
|
|
55
56
|
const next = typeof keys === "string" ? [keys] : keys;
|
|
56
57
|
setSelectedKeys(next);
|
|
57
58
|
const singleFolderId = Array.isArray(next) && next.length === 1 ? next[0] : null;
|
|
58
|
-
if (
|
|
59
|
-
|
|
59
|
+
if (onFolderChange) {
|
|
60
|
+
// Update URL: subfolder id for subfolders, undefined for root/My Drive (so URL stays /digital-asset-management)
|
|
61
|
+
const urlFolderId = singleFolderId && singleFolderId !== rootFolderId ? singleFolderId : undefined;
|
|
62
|
+
onFolderChange(urlFolderId);
|
|
60
63
|
}
|
|
61
64
|
};
|
|
62
|
-
return (_jsxs(FoldersProvider, { value: { setFolders, folders, globalSearch }, children: [_jsx(FolderTree, { currentRootId: currentRootId, handleExpand: handleExpand, setSelectedKeys:
|
|
65
|
+
return (_jsxs(FoldersProvider, { value: { setFolders, folders, globalSearch }, children: [_jsx(FolderTree, { currentRootId: currentRootId, handleExpand: handleExpand, setSelectedKeys: handleSetSelectedKeys, expandedKeys: expandedKeys, selectedKeys: selectedKeys, folders: folders, setExpandedKeys: setExpandedKeys, setFolders: setFolders, setGlobalSearch: setGlobalSearch, globalSearch: globalSearch }), _jsx("div", { className: "md-lib-h-[inherit] md-lib-overflow-x-auto", children: _jsx(DriveContainer, { parentFolderId: selectedFolderId, globalSearch: globalSearch, setGlobalSearch: setGlobalSearch, setSelectedKeys: handleSetSelectedKeys }) })] }));
|
|
63
66
|
}
|
package/build/MyDrive/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ declare function App(props: {
|
|
|
11
11
|
parentId?: string;
|
|
12
12
|
showSubfolders?: boolean;
|
|
13
13
|
userEmail?: string;
|
|
14
|
-
onFolderChange?: (folderId: string) => void;
|
|
14
|
+
onFolderChange?: (folderId: string | undefined) => void;
|
|
15
15
|
/** Height of host app header (e.g. navbar) in px. When set, preview modal positions below it instead of covering. */
|
|
16
16
|
headerHeight?: number;
|
|
17
17
|
}): JSX.Element;
|
|
@@ -4,7 +4,7 @@ type AppRoutesProps = {
|
|
|
4
4
|
folders: FolderTypes[];
|
|
5
5
|
setFolders: React.Dispatch<React.SetStateAction<FolderTypes[]>>;
|
|
6
6
|
routerVersion: 4 | 5 | 6;
|
|
7
|
-
onFolderChange?: (folderId: string) => void;
|
|
7
|
+
onFolderChange?: (folderId: string | undefined) => void;
|
|
8
8
|
};
|
|
9
9
|
export default function AppRoutes({ folders, setFolders, routerVersion, onFolderChange, }: AppRoutesProps): JSX.Element;
|
|
10
10
|
export {};
|
|
@@ -9,32 +9,49 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
11
|
import { Button } from "antd";
|
|
12
|
-
import {
|
|
12
|
+
import { useState } from "react";
|
|
13
|
+
import axios from "axios";
|
|
13
14
|
import { showNotification } from "../common/notifications";
|
|
14
15
|
import { NotificationStatus } from "../utilities/constants/interface";
|
|
15
16
|
import { SOMETHING_WENT_WRONG } from "../utilities/constants/messages";
|
|
16
17
|
import { get } from "lodash";
|
|
17
|
-
import { REFRESH_KEY_URL } from "../utilities/constants/apiUrls";
|
|
18
|
+
import { REFRESH_KEY_URL, USER_LOGIN } from "../utilities/constants/apiUrls";
|
|
18
19
|
import { useDamConfig } from "../hocs/DamConfigContext";
|
|
19
|
-
import {
|
|
20
|
+
import { getBaseUrl } from "../hocs/helpers";
|
|
20
21
|
export default function RefreshKeyBtn() {
|
|
21
22
|
const [loading, setLoading] = useState(false);
|
|
22
23
|
const damConfig = useDamConfig();
|
|
23
|
-
const { damAccessKey, secretKey } = damConfig;
|
|
24
|
-
const api = useMemo(() => createApiClient(damConfig), [damConfig]);
|
|
24
|
+
const { damAccessKey, secretKey, subdomain, teamIds, appType } = damConfig;
|
|
25
25
|
const onRefreshKey = () => __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
if (!damAccessKey || !secretKey || !subdomain) {
|
|
27
|
+
showNotification("Access key, secret key, and subdomain are required to refresh", NotificationStatus.ERROR);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
26
30
|
setLoading(true);
|
|
27
31
|
try {
|
|
28
|
-
|
|
32
|
+
// Step 1: Login with keys to get DAM token (same as Edit Client flow)
|
|
33
|
+
const loginResponse = yield axios.post(getBaseUrl(appType) + USER_LOGIN, {
|
|
29
34
|
accessKey: damAccessKey,
|
|
30
35
|
secretKey,
|
|
36
|
+
subdomain,
|
|
37
|
+
teams: teamIds && teamIds.length > 0 ? teamIds : [""],
|
|
38
|
+
});
|
|
39
|
+
const token = get(loginResponse, "data.data.access_token");
|
|
40
|
+
if (!token) {
|
|
41
|
+
throw new Error("Failed to get token from login");
|
|
42
|
+
}
|
|
43
|
+
// Step 2: Call refresh API with the DAM token (include subdomain header)
|
|
44
|
+
const response = yield axios.put(getBaseUrl(appType) + REFRESH_KEY_URL, { accessKey: damAccessKey, secretKey }, {
|
|
45
|
+
headers: {
|
|
46
|
+
Authorization: `Bearer ${token}`,
|
|
47
|
+
subdomain: subdomain,
|
|
48
|
+
},
|
|
31
49
|
});
|
|
32
|
-
// console.log(response);
|
|
33
50
|
setLoading(false);
|
|
34
51
|
showNotification(get(response, "data.message", "Key refreshed successfully"), NotificationStatus.SUCCESS);
|
|
35
52
|
}
|
|
36
53
|
catch (error) {
|
|
37
|
-
showNotification(get(error, "message", SOMETHING_WENT_WRONG), NotificationStatus.ERROR);
|
|
54
|
+
showNotification(get(error, "response.data.message", get(error, "message", SOMETHING_WENT_WRONG)), NotificationStatus.ERROR);
|
|
38
55
|
setLoading(false);
|
|
39
56
|
}
|
|
40
57
|
});
|