@bindu-dashing/dam-solution-v2 5.8.193 → 5.8.195

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.
@@ -314,11 +314,6 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
314
314
  return false;
315
315
  return d.hour() !== 0 || d.minute() !== 0 || d.second() !== 0;
316
316
  };
317
- const hasOnlyDateNoTime = (d) => {
318
- if (!d || typeof d.hour !== "function")
319
- return false;
320
- return d.hour() === 0 && d.minute() === 0 && d.second() === 0;
321
- };
322
317
  rules.push({
323
318
  validator: (_, value) => {
324
319
  const allowTime = !!get(settings, `${InputSupportedTypes.ALLOW_TIME}.allow`);
@@ -330,10 +325,8 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
330
325
  typeof value.hour === "function" &&
331
326
  typeof value.minute === "function" &&
332
327
  typeof value.second === "function";
333
- // When time is allowed: reject if user selected date-only (must re-select with time)
334
- if (allowTime && hasTimeMethods && hasOnlyDateNoTime(value)) {
335
- return Promise.reject("Please select a date with time (hour/minute/second).");
336
- }
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)
337
330
  if (allowTime && !hasTimeMethods) {
338
331
  return Promise.reject("Please select a date with time (hour/minute/second).");
339
332
  }
@@ -353,12 +346,8 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
353
346
  typeof end.hour === "function" &&
354
347
  typeof end.minute === "function" &&
355
348
  typeof end.second === "function";
356
- // When time is allowed: reject if either date is date-only (must re-select with time)
357
- if (allowTime && (startHasTimeMethods || endHasTimeMethods)) {
358
- if (hasOnlyDateNoTime(start) || hasOnlyDateNoTime(end)) {
359
- return Promise.reject("Please select both start and end dates with time.");
360
- }
361
- }
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
362
351
  if (allowTime && (!startHasTimeMethods || !endHasTimeMethods)) {
363
352
  return Promise.reject("Please select both start and end dates with time.");
364
353
  }
@@ -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.put(`${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) => {
@@ -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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bindu-dashing/dam-solution-v2",
3
- "version": "5.8.193",
3
+ "version": "5.8.195",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.0.1",
6
6
  "@emoji-mart/data": "^1.2.1",