@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.
@@ -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 user selected a non-zero time
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 user selected a non-zero time
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, useMemo } from "react";
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 { createApiClient } from "../hocs/configureAxios";
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 api = useMemo(() => createApiClient(damConfig), [damConfig]);
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
- const response = yield api.put(REFRESH_KEY_URL, {
38
- accessKey: existingClientData.accessKey,
39
- secretKey: existingClientData.secretKey,
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, _e, _f, _g, _h, _j;
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
- // Update existing client: PUT to /brands/{brandId}
195
- const putResponse = yield axios.put(`${baseUrl}/brands/${brandIdForUpdate}`, values, {
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((_j = response === null || response === void 0 ? void 0 : response.message) !== null && _j !== void 0 ? _j : (get(response, "message") || CREATE_SUCCESS), NotificationStatus.SUCCESS);
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
- onSuccess(response === null || response === void 0 ? void 0 : response.data);
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
- if (currentRootId === rootFolderId || folders.length === 0) {
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 (singleFolderId && onFolderChange) {
59
- onFolderChange(singleFolderId);
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: setSelectedKeys, 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 }) })] }));
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
  }
@@ -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 { useMemo, useState } from "react";
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 { createApiClient } from "../hocs/configureAxios";
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
- const response = yield api.put(REFRESH_KEY_URL, {
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
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bindu-dashing/dam-solution-v2",
3
- "version": "5.8.190",
3
+ "version": "5.8.194",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.0.1",
6
6
  "@emoji-mart/data": "^1.2.1",