@anji-dashing/dam-solution-v2 5.8.175 → 5.8.177

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/build/AssetType/AddFieldProperties.js +53 -13
  2. package/build/AssetType/EditAssetTemplate.js +2 -2
  3. package/build/AssetType/FieldsSection.d.ts +2 -1
  4. package/build/AssetType/FieldsSection.js +10 -5
  5. package/build/CreateClient/CreateClientBtn.d.ts +2 -1
  6. package/build/CreateClient/CreateClientBtn.js +9 -2
  7. package/build/CreateClient/CreateClientForm.js +108 -47
  8. package/build/CreateClient/index.d.ts +1 -0
  9. package/build/CreateClient/index.js +7 -5
  10. package/build/MyDrive/ActionBar.js +4 -2
  11. package/build/MyDrive/BulkUploadModal.js +3 -5
  12. package/build/MyDrive/DriveContainer.js +1 -1
  13. package/build/MyDrive/FileMenuOptions.js +4 -2
  14. package/build/MyDrive/FilesGridView.js +3 -1
  15. package/build/MyDrive/FolderListView.js +1 -1
  16. package/build/MyDrive/FolderMenuOptions.js +4 -2
  17. package/build/MyDrive/FolderTree.js +25 -4
  18. package/build/MyDrive/ImagePickerBreadCrumbList.d.ts +2 -1
  19. package/build/MyDrive/ImagePickerBreadCrumbList.js +2 -2
  20. package/build/MyDrive/MyDriveMainContainer.d.ts +1 -1
  21. package/build/MyDrive/MyDriveMainContainer.js +9 -6
  22. package/build/MyDrive/fileDetails/CommentEntity.js +2 -2
  23. package/build/MyDrive/fileDetails/FileDetails.js +27 -7
  24. package/build/MyDrive/fileDetails/FileHeader.js +2 -4
  25. package/build/MyDrive/fileDetails/FileViewer.js +2 -2
  26. package/build/MyDrive/fileDetails/MetaForm.d.ts +6 -1
  27. package/build/MyDrive/fileDetails/MetaForm.js +46 -9
  28. package/build/MyDrive/fileDetails/Previewdetails.js +1 -3
  29. package/build/MyDrive/files/MapFile.d.ts +2 -1
  30. package/build/MyDrive/files/MapFile.js +10 -4
  31. package/build/MyDrive/index.d.ts +3 -1
  32. package/build/MyDrive/index.js +2 -0
  33. package/build/MyDrive/routes.d.ts +1 -1
  34. package/build/hocs/DamConfigContext.js +2 -1
  35. 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
@@ -280,6 +309,11 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
280
309
  if ((defaultName === InputTypes.DATE ||
281
310
  defaultName === InputTypes.DATE_RANGE) &&
282
311
  settings[InputSupportedTypes.ALLOW_TIME] !== undefined) {
312
+ const hasNonZeroTime = (d) => {
313
+ if (!d || typeof d.hour !== "function")
314
+ return false;
315
+ return d.hour() !== 0 || d.minute() !== 0 || d.second() !== 0;
316
+ };
283
317
  rules.push({
284
318
  validator: (_, value) => {
285
319
  const allowTime = !!get(settings, `${InputSupportedTypes.ALLOW_TIME}.allow`);
@@ -291,10 +325,13 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
291
325
  typeof value.hour === "function" &&
292
326
  typeof value.minute === "function" &&
293
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)
294
330
  if (allowTime && !hasTimeMethods) {
295
331
  return Promise.reject("Please select a date with time (hour/minute/second).");
296
332
  }
297
- if (!allowTime && hasTimeMethods) {
333
+ // When time is not allowed: strip time (handled in onValuesChange) - reject only if still has non-zero time
334
+ if (!allowTime && hasNonZeroTime(value)) {
298
335
  return Promise.reject("Time is not allowed. Please select only a date.");
299
336
  }
300
337
  }
@@ -309,10 +346,13 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
309
346
  typeof end.hour === "function" &&
310
347
  typeof end.minute === "function" &&
311
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
312
351
  if (allowTime && (!startHasTimeMethods || !endHasTimeMethods)) {
313
352
  return Promise.reject("Please select both start and end dates with time.");
314
353
  }
315
- if (!allowTime && (startHasTimeMethods || endHasTimeMethods)) {
354
+ // When time is not allowed: strip time (handled in onValuesChange) - reject only if still has non-zero time
355
+ if (!allowTime && (hasNonZeroTime(start) || hasNonZeroTime(end))) {
316
356
  return Promise.reject("Time is not allowed. Please select only dates.");
317
357
  }
318
358
  }
@@ -348,12 +388,12 @@ export default function AddFieldProperties({ field, setCurrentFieldIndex, onUpda
348
388
  InputTypes.TEAM,
349
389
  InputTypes.CHECKBOX,
350
390
  InputTypes.RADIO,
351
- ], get(currentInputType, "defaultName")) && (_jsx(OptionsField, { field: field, supportedTypes: get(currentInputType, "supportedTypes", []), currentInputType: currentInputType }))] })] }), _jsxs(Form.Item, { className: "md-lib-flex md-lib-flex-col md-lib-items-end md-lib-absolute md-lib-bottom-0 md-lib-right-0 md-lib-pr-4 md-lib-pb-4", children: [disabledReason && (_jsxs("p", { className: "md-lib-text-sm md-lib-mb-2 md-lib-mr-2", style: { color: styles === null || styles === void 0 ? void 0 : styles.secondaryTextColor }, children: ["Update disabled: ", disabledReason] })), _jsxs("div", { className: "md-lib-flex md-lib-items-center", children: [_jsx(Button, { color: "primary", variant: "text", onClick: () => {
352
- if (onCancel && index !== null) {
353
- onCancel(index);
354
- }
355
- else {
356
- setCurrentFieldIndex(null);
357
- }
358
- }, size: "large", children: "Cancel" }), _jsx(Button, { color: "primary", htmlType: "submit", className: "md-lib-ml-2 md-lib-border-primaryColor md-lib-text-primaryColor", size: "large", loading: loading, disabled: !isFormValid || loading, title: disabledReason || undefined, children: "Update" })] })] })] }) })] }));
391
+ ], get(currentInputType, "defaultName")) && (_jsx(OptionsField, { field: field, supportedTypes: get(currentInputType, "supportedTypes", []), currentInputType: currentInputType }))] })] }), _jsx(Form.Item, { className: "md-lib-flex md-lib-flex-col md-lib-items-end md-lib-absolute md-lib-bottom-0 md-lib-right-0 md-lib-pr-4 md-lib-pb-4", children: _jsxs("div", { className: "md-lib-flex md-lib-items-center", children: [_jsx(Button, { color: "primary", variant: "text", onClick: () => {
392
+ if (onCancel && index !== null) {
393
+ onCancel(index);
394
+ }
395
+ else {
396
+ setCurrentFieldIndex(null);
397
+ }
398
+ }, size: "large", children: "Cancel" }), _jsx(Button, { color: "primary", htmlType: "submit", className: "md-lib-ml-2 md-lib-border-primaryColor md-lib-text-primaryColor", size: "large", loading: loading, disabled: !isFormValid || loading, title: disabledReason || undefined, children: "Update" })] }) })] }) })] }));
359
399
  }
@@ -218,13 +218,13 @@ export default function EditAssetTemplate({ assetTemplate, inputTypes, }) {
218
218
  {
219
219
  key: "1",
220
220
  label: "Fields",
221
- children: (_jsx(AddWidgets, { name: name, inputTypes: inputTypes, transformInputTypePayload: transformInputTypePayload, currentFieldIndex: currentFieldIndex, setState: setState, fields: fields, imagePickerOutputFormat: imagePickerOutputFormat, setCurrentFieldIndex: (value) => setState((prevState) => (Object.assign(Object.assign({}, prevState), { currentFieldIndex: value }))), showOutputFormat: false })),
221
+ children: (_jsx(AddWidgets, { name: name, inputTypes: inputTypes, transformInputTypePayload: transformInputTypePayload, currentFieldIndex: currentFieldIndex, setState: setState, fields: fields, imagePickerOutputFormat: imagePickerOutputFormat, setCurrentFieldIndex: (value) => setState((prevState) => (Object.assign(Object.assign({}, prevState), { currentFieldIndex: value }))), showOutputFormat: false, assetId: id || get(assetTemplate, "_id") })),
222
222
  },
223
223
  {
224
224
  key: "2",
225
225
  label: "Image picker output format",
226
226
  disabled: fields.length === 0,
227
- children: (_jsx(AddWidgets, { name: name, inputTypes: inputTypes, transformInputTypePayload: transformInputTypePayload, currentFieldIndex: currentFieldIndex, setState: setState, fields: fields, imagePickerOutputFormat: imagePickerOutputFormat, setCurrentFieldIndex: (value) => setState((prevState) => (Object.assign(Object.assign({}, prevState), { currentFieldIndex: value }))), showOutputFormat: true })),
227
+ children: (_jsx(AddWidgets, { name: name, inputTypes: inputTypes, transformInputTypePayload: transformInputTypePayload, currentFieldIndex: currentFieldIndex, setState: setState, fields: fields, imagePickerOutputFormat: imagePickerOutputFormat, setCurrentFieldIndex: (value) => setState((prevState) => (Object.assign(Object.assign({}, prevState), { currentFieldIndex: value }))), showOutputFormat: true, assetId: id || get(assetTemplate, "_id") })),
228
228
  },
229
229
  ];
230
230
  // console.log("edit asset template", fields, imagePickerOutputFormat);
@@ -1,7 +1,7 @@
1
1
  import { SetStateAction } from "react";
2
2
  import { InputTypeEntity } from "../utilities/constants/interface";
3
3
  export declare const getWidgetIcon: (defaultName: string | undefined | null) => import("react-icons").IconType | null;
4
- export default function FieldsSection({ name, inputTypes, transformInputTypePayload, currentFieldIndex, setCurrentFieldIndex, fields, setState, showOutputFormat, imagePickerOutputFormat, }: {
4
+ export default function FieldsSection({ name, inputTypes, transformInputTypePayload, currentFieldIndex, setCurrentFieldIndex, fields, setState, showOutputFormat, imagePickerOutputFormat, assetId: assetIdProp, }: {
5
5
  name: string;
6
6
  inputTypes: InputTypeEntity[];
7
7
  transformInputTypePayload: (values: any, field: InputTypeEntity, mapId: string) => void;
@@ -11,4 +11,5 @@ export default function FieldsSection({ name, inputTypes, transformInputTypePayl
11
11
  setState: React.Dispatch<SetStateAction<any>>;
12
12
  showOutputFormat: boolean;
13
13
  imagePickerOutputFormat: InputTypeEntity[];
14
+ assetId?: string;
14
15
  }): JSX.Element;
@@ -25,7 +25,7 @@ import { IoIosRadioButtonOff } from "react-icons/io";
25
25
  import { IoCheckboxOutline } from "react-icons/io5";
26
26
  import { FaRegUser } from "react-icons/fa";
27
27
  import { showNotification } from "../common/notifications";
28
- import { DELETE_CONFIRMATION_MESSAGE, DELETE_MESSAGE_DESCRIPTION, DELETE_OK_TEXT, DELETE_SUCCESS, INPUT_SETTINGS_VALIDATION_ERROR, INPUT_SETTINGS_VALIDATION_ERROR_AT_SWITCH_INPUT, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
28
+ import { DELETE_CONFIRMATION_MESSAGE, DELETE_OK_TEXT, DELETE_SUCCESS, INPUT_SETTINGS_VALIDATION_ERROR, INPUT_SETTINGS_VALIDATION_ERROR_AT_SWITCH_INPUT, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
29
29
  import { getInputTypeValidationErrors } from "../utilities/helpers/validators";
30
30
  import { DELETE_ASSET_FIELD_URL } from "../utilities/constants/apiUrls";
31
31
  import { DeleteConfirmationModal } from "../common/CustomElements";
@@ -76,8 +76,9 @@ export const getWidgetIcon = (defaultName) => {
76
76
  return null;
77
77
  }
78
78
  };
79
- export default function FieldsSection({ name, inputTypes, transformInputTypePayload, currentFieldIndex, setCurrentFieldIndex, fields, setState, showOutputFormat, imagePickerOutputFormat, }) {
80
- const { id } = useAppParams();
79
+ export default function FieldsSection({ name, inputTypes, transformInputTypePayload, currentFieldIndex, setCurrentFieldIndex, fields, setState, showOutputFormat, imagePickerOutputFormat, assetId: assetIdProp, }) {
80
+ const { id: idFromParams } = useAppParams();
81
+ const assetId = assetIdProp !== null && assetIdProp !== void 0 ? assetIdProp : idFromParams;
81
82
  const [fieldState, setFieldState] = useState({
82
83
  showConfirmModal: false,
83
84
  selectedField: null,
@@ -166,9 +167,13 @@ export default function FieldsSection({ name, inputTypes, transformInputTypePayl
166
167
  }
167
168
  };
168
169
  const onDeleteExistedField = () => __awaiter(this, void 0, void 0, function* () {
170
+ if (!assetId) {
171
+ showNotification("Asset ID is missing. Unable to delete field.", NotificationStatus.ERROR);
172
+ return;
173
+ }
169
174
  setFieldState((prevState) => (Object.assign(Object.assign({}, prevState), { loading: true })));
170
175
  try {
171
- const response = yield api.delete(DELETE_ASSET_FIELD_URL.replace(":assetId", id).replace(":id", get(selectedField, "_id")));
176
+ const response = yield api.delete(DELETE_ASSET_FIELD_URL.replace(":assetId", assetId).replace(":id", get(selectedField, "_id")));
172
177
  const updatedFields = filter(fields, (field, index) => get(field, "_id") !== get(selectedField, "_id"));
173
178
  const updatedImagePickerOutputFormat = filter(imagePickerOutputFormat, (field, index) => get(field, "mapId") !== get(selectedField, "mapId"));
174
179
  setState((prevState) => (Object.assign(Object.assign({}, prevState), { fields: updatedFields, currentFieldIndex: null, imagePickerOutputFormat: updatedImagePickerOutputFormat })));
@@ -264,5 +269,5 @@ export default function FieldsSection({ name, inputTypes, transformInputTypePayl
264
269
  else {
265
270
  setCurrentFieldIndex(null);
266
271
  }
267
- } }) }))] }) }), showConfirmModal && (_jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmModal, okText: DELETE_OK_TEXT, onOk: onDeleteExistedField, loading: loading, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", "Delete").replace(":entity", `${get(selectedField, "name", "this field")}`), subHeading: DELETE_MESSAGE_DESCRIPTION }))] }));
272
+ } }) }))] }) }), showConfirmModal && (_jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmModal, okText: DELETE_OK_TEXT, onOk: onDeleteExistedField, loading: loading, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", "Delete").replace(":entity", `${get(selectedField, "name", "this field")}`) }))] }));
268
273
  }
@@ -1,5 +1,6 @@
1
- declare const CreateClient: ({ onSuccess, clientSubdomain, teamsApi, username, password, existingClientData, }: {
1
+ declare const CreateClient: ({ onSuccess, onRefreshSuccess, clientSubdomain, teamsApi, username, password, existingClientData, }: {
2
2
  onSuccess: (data: any) => void;
3
+ onRefreshSuccess?: (data: any) => void;
3
4
  clientSubdomain: string;
4
5
  teamsApi: string;
5
6
  username: string;
@@ -18,7 +18,7 @@ import { showNotification } from "../common/notifications";
18
18
  import { NotificationStatus } from "../utilities/constants/interface";
19
19
  import { SOMETHING_WENT_WRONG } from "../utilities/constants/messages";
20
20
  import { get } from "lodash";
21
- const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password, existingClientData, }) => {
21
+ const CreateClient = ({ onSuccess, onRefreshSuccess, clientSubdomain, teamsApi, username, password, existingClientData, }) => {
22
22
  const [showForm, setShowForm] = useState(false);
23
23
  const [refreshingKey, setRefreshingKey] = useState(false);
24
24
  const isEditMode = !!existingClientData;
@@ -32,6 +32,10 @@ const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password
32
32
  showNotification("Access key and secret key are required to refresh", NotificationStatus.ERROR);
33
33
  return;
34
34
  }
35
+ if (!(damConfig === null || damConfig === void 0 ? void 0 : damConfig.accessToken)) {
36
+ showNotification("Authentication token is not available. Please wait for the page to load or try again.", NotificationStatus.ERROR);
37
+ return;
38
+ }
35
39
  setRefreshingKey(true);
36
40
  try {
37
41
  const response = yield api.put(REFRESH_KEY_URL, {
@@ -40,7 +44,10 @@ const CreateClient = ({ onSuccess, clientSubdomain, teamsApi, username, password
40
44
  });
41
45
  setRefreshingKey(false);
42
46
  showNotification(get(response, "data.message", "Key refreshed successfully"), NotificationStatus.SUCCESS);
43
- if (onSuccess) {
47
+ if (onRefreshSuccess) {
48
+ onRefreshSuccess(response === null || response === void 0 ? void 0 : response.data);
49
+ }
50
+ else if (onSuccess) {
44
51
  onSuccess(response === null || response === void 0 ? void 0 : response.data);
45
52
  }
46
53
  }
@@ -152,66 +152,105 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
152
152
  fetchClientData();
153
153
  }, [isEditMode, existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.brandId, existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.subdomain, api, form]);
154
154
  const onFinish = (data) => __awaiter(void 0, void 0, void 0, function* () {
155
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
155
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
156
156
  try {
157
- // Use teamsApiDetails from clientData if available (from API response), otherwise use props
158
- const teamsApiDetailsFromData = get(clientData, "teamsApiDetails", {});
159
- const finalTeamsApi = teamsApiDetailsFromData.teamsApi || teamsApi;
160
- const finalUsername = teamsApiDetailsFromData.username || username;
161
- const finalPassword = teamsApiDetailsFromData.password || password;
162
- // Convert adminTeams to strings for API (API expects strings like ["547"] not numbers like [547])
163
- const adminTeamsAsStrings = Array.isArray(data.adminTeams)
164
- ? data.adminTeams.map((team) => String(team))
165
- : [];
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
157
  setLoading(true);
191
158
  let response;
192
159
  const baseUrl = getBaseUrl(appType);
193
160
  if (isEditMode && brandIdForUpdate && authToken) {
194
- // Update existing client: PUT to /brands/{brandId}
195
- const putResponse = yield axios.put(`${baseUrl}/brands/${brandIdForUpdate}`, values, {
161
+ // Edit mode: send only changed fields via PUT
162
+ const adminTeamsAsStrings = Array.isArray(data.adminTeams)
163
+ ? data.adminTeams.map((team) => String(team))
164
+ : [];
165
+ const existingAdminTeams = (get(clientData, "adminTeams", []) || []).map((t) => String(t));
166
+ const arraysEqual = (a, b) => {
167
+ const sa = [...a].sort();
168
+ const sb = [...b].sort();
169
+ return sa.length === sb.length && sa.every((v, i) => v === sb[i]);
170
+ };
171
+ const accessTypesChanged = JSON.stringify([...(data.accessTypes || [])].sort()) !==
172
+ JSON.stringify([...(get(clientData, "accessTypes", []) || [])].sort());
173
+ const payload = {};
174
+ if (data.name !== get(clientData, "name"))
175
+ payload.name = data.name;
176
+ if (accessTypesChanged)
177
+ payload.accessTypes = data.accessTypes || [];
178
+ if (!arraysEqual(adminTeamsAsStrings, existingAdminTeams))
179
+ payload.adminTeams = adminTeamsAsStrings;
180
+ if (((_a = data.showFilePreview) !== null && _a !== void 0 ? _a : false) !== get(clientData, "showFilePreview", false))
181
+ payload.showFilePreview = (_b = data.showFilePreview) !== null && _b !== void 0 ? _b : false;
182
+ if (Object.keys(payload).length === 0) {
183
+ setLoading(false);
184
+ showNotification("No changes to save", NotificationStatus.INFO);
185
+ return;
186
+ }
187
+ const putResponse = yield axios.put(`${baseUrl}/brands/${brandIdForUpdate}`, payload, {
196
188
  headers: {
197
- 'Authorization': `Bearer ${authToken}`,
198
- 'Content-Type': 'application/json',
199
- 'accept': 'application/json, text/plain, */*'
200
- }
189
+ Authorization: `Bearer ${authToken}`,
190
+ "Content-Type": "application/json",
191
+ accept: "application/json, text/plain, */*",
192
+ },
201
193
  });
202
194
  // Extract data from axios response (API returns { data: {...} } or { data: { data: {...} } })
203
195
  response = get(putResponse, "data.data", get(putResponse, "data", putResponse));
204
196
  }
205
197
  else {
206
- // Create new client: POST to /brands/sub-brand
198
+ // Create new client: POST to /brands/sub-brand (full payload required)
199
+ const teamsApiDetailsFromData = clientData ? get(clientData, "teamsApiDetails", {}) : {};
200
+ const finalTeamsApi = teamsApiDetailsFromData.teamsApi || teamsApi;
201
+ const finalUsername = teamsApiDetailsFromData.username || username;
202
+ const finalPassword = teamsApiDetailsFromData.password || password;
203
+ const adminTeamsAsStrings = Array.isArray(data.adminTeams)
204
+ ? data.adminTeams.map((team) => String(team))
205
+ : [];
206
+ const formDamLocation = data === null || data === void 0 ? void 0 : data.damLocationDetails;
207
+ const damLocationDetails = damLocationType === "external"
208
+ ? {
209
+ bucket: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.bucket,
210
+ locationType: "EXTERNAL",
211
+ rootPath: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.rootPath,
212
+ accessKeyId: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.accessKeyId,
213
+ secretAccessKey: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.secretAccessKey,
214
+ url: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.url,
215
+ region: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.region,
216
+ }
217
+ : {
218
+ locationType: "INTERNAL",
219
+ rootPath: formDamLocation === null || formDamLocation === void 0 ? void 0 : formDamLocation.rootPath,
220
+ };
221
+ const values = Object.assign(Object.assign({}, data), { adminTeams: adminTeamsAsStrings, showFilePreview: (_c = data.showFilePreview) !== null && _c !== void 0 ? _c : false, accessKey: appType == "reactJs"
222
+ ? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY
223
+ : process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_ACCESS_KEY, secretKey: appType == "reactJs"
224
+ ? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SECRET_KEY
225
+ : process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SECRET_KEY, parentSubdomain: appType == "reactJs"
226
+ ? process.env.REACT_APP_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN
227
+ : process.env.NEXT_PUBLIC_MIXDRIVE_CLIENT_PARENT_SUBDOMAIN, teamsApiDetails: {
228
+ teamsApi: finalTeamsApi,
229
+ username: finalUsername,
230
+ password: finalPassword,
231
+ }, damLocationDetails });
207
232
  response = yield api.post(CREATE_SUB_BRAND, values);
208
233
  }
209
234
  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);
211
- toggleShow();
235
+ showNotification((_d = response === null || response === void 0 ? void 0 : response.message) !== null && _d !== void 0 ? _d : (get(response, "message") || CREATE_SUCCESS), NotificationStatus.SUCCESS);
236
+ // Call onSuccess before closing drawer so parent can show its toast (e.g. d1-admin, ThemePage)
237
+ // Parent expects accessKey, secretKey, subdomain - always provide when in edit mode
212
238
  if (onSuccess) {
213
- onSuccess(response === null || response === void 0 ? void 0 : response.data);
239
+ const successData = isEditMode
240
+ ? Object.assign(Object.assign(Object.assign({}, response === null || response === void 0 ? void 0 : response.data), response), { accessKey: (_f = (_e = existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.accessKey) !== null && _e !== void 0 ? _e : get(response, "accessKey")) !== null && _f !== void 0 ? _f : get(clientData, "accessKey"), secretKey: (_h = (_g = existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.secretKey) !== null && _g !== void 0 ? _g : get(response, "secretKey")) !== null && _h !== void 0 ? _h : get(clientData, "secretKey"), subdomain: (_l = (_k = (_j = data === null || data === void 0 ? void 0 : data.subdomain) !== null && _j !== void 0 ? _j : existingClientData === null || existingClientData === void 0 ? void 0 : existingClientData.subdomain) !== null && _k !== void 0 ? _k : get(response, "subdomain")) !== null && _l !== void 0 ? _l : get(clientData, "subdomain") }) : (_m = response === null || response === void 0 ? void 0 : response.data) !== null && _m !== void 0 ? _m : response;
241
+ // Guard: parent (e.g. ThemePage.onCreateDamClient) accesses data.accessKey - never pass undefined
242
+ const safeData = successData && typeof successData === "object"
243
+ ? successData
244
+ : isEditMode && existingClientData
245
+ ? {
246
+ accessKey: existingClientData.accessKey,
247
+ secretKey: existingClientData.secretKey,
248
+ subdomain: existingClientData.subdomain,
249
+ }
250
+ : {};
251
+ onSuccess(safeData);
214
252
  }
253
+ toggleShow();
215
254
  }
216
255
  catch (error) {
217
256
  setLoading(false);
@@ -300,7 +339,7 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
300
339
  required: true,
301
340
  message: "Team Ids is required",
302
341
  },
303
- ], children: _jsx(Select, { showSearch: true, mode: "multiple", placeholder: "Team Ids", options: filteredTeams, optionFilterProp: "key" }) }), _jsxs(Form.Item, { label: "DAM Location Details", name: "damLocationDetails", children: [_jsx(Form.Item, { label: "Type", name: ["damLocationDetails", "type"], rules: [
342
+ ], children: _jsx(Select, { showSearch: true, mode: "multiple", placeholder: "Team Ids", options: filteredTeams, optionFilterProp: "key" }) }), !isEditMode && (_jsxs(Form.Item, { label: "DAM Location Details", name: "damLocationDetails", children: [_jsx(Form.Item, { label: "Type", name: ["damLocationDetails", "type"], rules: [
304
343
  {
305
344
  required: true,
306
345
  message: "Type is required",
@@ -337,11 +376,33 @@ const CreateClientForm = ({ teamsApi, username, password, toggleShow, onSuccess,
337
376
  required: damLocationType === "external",
338
377
  message: "Region is required",
339
378
  },
340
- ], children: _jsx(Input, { placeholder: "Region", disabled: damLocationType === "internal" }) })] }))] }), _jsx(Form.Item, { label: "Subdomain", name: "subdomain", rules: [
379
+ ], children: _jsx(Input, { placeholder: "Region", disabled: damLocationType === "internal" }) })] }))] })), _jsx(Form.Item, { label: "Subdomain", name: "subdomain", rules: [
341
380
  {
342
381
  required: true,
343
382
  message: "Subdomain is required",
344
383
  },
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" }) })] })) }));
384
+ ], 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, { shouldUpdate: true, style: { marginBottom: 0 }, children: () => {
385
+ var _a, _b, _c, _d, _e, _f, _g, _h;
386
+ const values = form.getFieldsValue(true);
387
+ const hasName = !!((_a = values === null || values === void 0 ? void 0 : values.name) === null || _a === void 0 ? void 0 : _a.trim());
388
+ const hasAccessTypes = Array.isArray(values === null || values === void 0 ? void 0 : values.accessTypes) && values.accessTypes.length > 0;
389
+ const hasAdminTeams = Array.isArray(values === null || values === void 0 ? void 0 : values.adminTeams) && values.adminTeams.length > 0;
390
+ const hasSubdomain = !!((_b = values === null || values === void 0 ? void 0 : values.subdomain) === null || _b === void 0 ? void 0 : _b.trim());
391
+ const baseValid = hasName && hasAccessTypes && hasAdminTeams && hasSubdomain;
392
+ let damLocationValid = true;
393
+ if (!isEditMode) {
394
+ const dl = (values === null || values === void 0 ? void 0 : values.damLocationDetails) || {};
395
+ damLocationValid = !!((dl === null || dl === void 0 ? void 0 : dl.type) && ((_c = dl === null || dl === void 0 ? void 0 : dl.rootPath) === null || _c === void 0 ? void 0 : _c.trim()));
396
+ if (damLocationValid && damLocationType === "external") {
397
+ damLocationValid = !!(((_d = dl === null || dl === void 0 ? void 0 : dl.bucket) === null || _d === void 0 ? void 0 : _d.trim()) &&
398
+ ((_e = dl === null || dl === void 0 ? void 0 : dl.accessKeyId) === null || _e === void 0 ? void 0 : _e.trim()) &&
399
+ ((_f = dl === null || dl === void 0 ? void 0 : dl.secretAccessKey) === null || _f === void 0 ? void 0 : _f.trim()) &&
400
+ ((_g = dl === null || dl === void 0 ? void 0 : dl.url) === null || _g === void 0 ? void 0 : _g.trim()) &&
401
+ ((_h = dl === null || dl === void 0 ? void 0 : dl.region) === null || _h === void 0 ? void 0 : _h.trim()));
402
+ }
403
+ }
404
+ const isFormValid = baseValid && damLocationValid;
405
+ return (_jsx(Button, { htmlType: "submit", type: "primary", block: true, loading: loading, disabled: !isFormValid, children: "Submit" }));
406
+ } })] })) }));
346
407
  };
347
408
  export default CreateClientForm;
@@ -7,6 +7,7 @@ declare function App(props: {
7
7
  username: string;
8
8
  password: string;
9
9
  onSuccess: (data: any) => void;
10
+ onRefreshSuccess?: (data: any) => void;
10
11
  teamIds: string[] | number[];
11
12
  styles: Record<string, any>;
12
13
  appType: string;
@@ -5,14 +5,16 @@ import { ThemeModes } from "../utilities/constants/interface";
5
5
  import CreateClient from "./CreateClientBtn";
6
6
  import ToastProvider from "../hocs/ToastProvider";
7
7
  function App(props) {
8
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
9
+ // Use existingClientData as fallback so login API gets token for keys/refresh APIs
8
10
  const config = {
9
- damAccessKey: props === null || props === void 0 ? void 0 : props.accessKey,
10
- secretKey: props === null || props === void 0 ? void 0 : props.secretKey,
11
- subdomain: props === null || props === void 0 ? void 0 : props.subdomain,
12
- teamIds: props === null || props === void 0 ? void 0 : props.teamIds,
11
+ damAccessKey: (_a = props === null || props === void 0 ? void 0 : props.accessKey) !== null && _a !== void 0 ? _a : (_b = props === null || props === void 0 ? void 0 : props.existingClientData) === null || _b === void 0 ? void 0 : _b.accessKey,
12
+ secretKey: (_c = props === null || props === void 0 ? void 0 : props.secretKey) !== null && _c !== void 0 ? _c : (_d = props === null || props === void 0 ? void 0 : props.existingClientData) === null || _d === void 0 ? void 0 : _d.secretKey,
13
+ subdomain: (_g = (_e = props === null || props === void 0 ? void 0 : props.subdomain) !== null && _e !== void 0 ? _e : (_f = props === null || props === void 0 ? void 0 : props.existingClientData) === null || _f === void 0 ? void 0 : _f.subdomain) !== null && _g !== void 0 ? _g : props === null || props === void 0 ? void 0 : props.clientSubdomain,
14
+ teamIds: (_h = props === null || props === void 0 ? void 0 : props.teamIds) !== null && _h !== void 0 ? _h : (((_j = props === null || props === void 0 ? void 0 : props.existingClientData) === null || _j === void 0 ? void 0 : _j.brandId) ? [props.existingClientData.brandId] : []),
13
15
  styles: props === null || props === void 0 ? void 0 : props.styles,
14
16
  appType: props === null || props === void 0 ? void 0 : props.appType,
15
17
  };
16
- return (_jsx(DamConfigProvider, { config: config, children: _jsxs(ThemeProvider, { styles: props === null || props === void 0 ? void 0 : props.styles, sessionTheme: ThemeModes.LIGHT, children: [_jsx(CreateClient, { teamsApi: props === null || props === void 0 ? void 0 : props.teamsApi, username: props === null || props === void 0 ? void 0 : props.username, password: props === null || props === void 0 ? void 0 : props.password, clientSubdomain: props === null || props === void 0 ? void 0 : props.clientSubdomain, onSuccess: props === null || props === void 0 ? void 0 : props.onSuccess, existingClientData: props === null || props === void 0 ? void 0 : props.existingClientData }), _jsx(ToastProvider, {})] }) }));
18
+ return (_jsx(DamConfigProvider, { config: config, children: _jsxs(ThemeProvider, { styles: props === null || props === void 0 ? void 0 : props.styles, sessionTheme: ThemeModes.LIGHT, children: [_jsx(CreateClient, { teamsApi: props === null || props === void 0 ? void 0 : props.teamsApi, username: props === null || props === void 0 ? void 0 : props.username, password: props === null || props === void 0 ? void 0 : props.password, clientSubdomain: props === null || props === void 0 ? void 0 : props.clientSubdomain, onSuccess: props === null || props === void 0 ? void 0 : props.onSuccess, onRefreshSuccess: props === null || props === void 0 ? void 0 : props.onRefreshSuccess, existingClientData: props === null || props === void 0 ? void 0 : props.existingClientData }), _jsx(ToastProvider, {})] }) }));
17
19
  }
18
20
  export default App;
@@ -11,7 +11,7 @@ import { DeleteConfirmationModal } from "../common/CustomElements";
11
11
  import { DeleteOutlined, RedoOutlined } from "@ant-design/icons";
12
12
  import { generateFoldersQueryKey, invalidateData, } from "../utilities/constants/queryKeys";
13
13
  import { DriveModes, NotificationStatus, } from "../utilities/constants/interface";
14
- import { ARCHIVE_OK_TEXT, DELETE_CONFIRMATION_MESSAGE, DELETE_MESSAGE_DESCRIPTION, DELETE_OK_TEXT, DELETE_SUCCESS, INVALID_URL, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
14
+ import { ARCHIVE_OK_TEXT, DELETE_CONFIRMATION_MESSAGE, DELETE_OK_TEXT, DELETE_SUCCESS, INVALID_URL, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
15
15
  import { showNotification } from "../common/notifications";
16
16
  import FileMenuOptions from "./FileMenuOptions";
17
17
  import { getFolderData } from "../react-query/hooks/folder-hooks";
@@ -185,6 +185,8 @@ const ActionsBar = ({ fileIds, folderIds, onCloseSelection, selectedFilesData =
185
185
  return (_jsxs("div", { className: "md-lib-fixed md-lib-bottom-6 md-lib-left-1/2 md-lib-transform -md-lib-translate-x-1/2 md-lib-w-80 md:md-lib-w-[720px] md-lib-max-w-3xl md-lib-bg-textColorActive md-lib-border dark:md-lib-bg-darkPrimary dark:md-lib-border-darkBorderColor md-lib-border-secondaryHoverColor md-lib-rounded-xl md-lib-shadow-md md-lib-flex md-lib-items-center md-lib-justify-between md-lib-px-4 md-lib-py-2 md-lib-z-50", children: [_jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-gap-5 md-lib-pl-2", children: [_jsx(Button, { type: "text", size: "large", icon: _jsx(FiDownloadIcon, { size: 24, className: "" }), disabled: isTrashPage, onClick: onDownloadFiles, loading: downloadFileMutation.isLoading }), _jsx(Tooltip, { title: "Move", children: _jsx(Button, { type: "text", size: "large", icon: _jsx(FiFolderPlusIcon, { size: 24, className: "" }), disabled: isTrashPage, onClick: toggleShowMoveFolder }) }), isTrashPage ? (_jsx(Tooltip, { title: "Restore", children: _jsx(Button, { type: "text", size: "large", icon: _jsx(RedoOutlined, { className: "" }), onClick: () => onRestoreFiles(), disabled: !isTrashPage }) })) : (_jsx(_Fragment, { children: isAdmin && (_jsx(Tooltip, { title: "Delete", children: _jsx(Button, { type: "text", size: "large", icon: _jsx(FiTrash2Icon, { size: 24, className: "" }), onClick: () => toggleConfirmPopup("delete"), disabled: isTrashPage }) })) })), _jsx(FileMenuOptions, { file: selectedFile || null, fileIds: fileIds, folderIds: folderIds, folder: selectedFolder || null, onCloseSelection: onCloseSelection, readOnly: isTrashPage })] }), _jsx("div", { className: "md-lib-flex md-lib-items-center", children: _jsxs(Tag, { className: "md-lib-bg-[#DEE4ED] dark:md-lib-bg-darkPrimaryHoverColor !md-lib-rounded-lg !md-lib-px-4 h-[38px] md-lib-text-sm md-lib-items-center md-lib-font-medium md-lib-flex md-lib-gap-2 md-lib-text-textColor dark:md-lib-text-darkTextColor", closable: true, closeIcon: _jsx(FiXIcon, { onClick: onCloseSelection, className: "md-lib-cursor-pointer" }), children: [get(fileIds, "length", 0) + get(folderIds, "length", 0), " Selected"] }) }), showMoveFolder && (_jsx(MoveToAnotherFolder, { open: showMoveFolder, handleCancel: () => {
186
186
  toggleShowMoveFolder();
187
187
  onCloseSelection();
188
- }, folderIds: folderIds, fileIds: fileIds, entity: null })), _jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmPopup, icon: actionType === "archive" ? (_jsx(IoArchiveOutlineIcon, {})) : (_jsx(DeleteOutlined, {})), okText: actionType === "archive" ? ARCHIVE_OK_TEXT : DELETE_OK_TEXT, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(" :entity", ""), subHeading: actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION, onOk: actionType === "archive" ? () => { } : onDeleteFile, loading: deleteFileMutation.isLoading })] }));
188
+ }, folderIds: folderIds, fileIds: fileIds, entity: null })), _jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmPopup, icon: actionType === "archive" ? (_jsx(IoArchiveOutlineIcon, {})) : (_jsx(DeleteOutlined, {})), okText: actionType === "archive" ? ARCHIVE_OK_TEXT : DELETE_OK_TEXT, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(" :entity", ""),
189
+ // subHeading={actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION}
190
+ onOk: actionType === "archive" ? () => { } : onDeleteFile, loading: deleteFileMutation.isLoading })] }));
189
191
  };
190
192
  export default ActionsBar;
@@ -43,7 +43,6 @@ const BulkUploadModal = ({ toggleUpload, userEmail, folderId, thumbnailsOnly, })
43
43
  const [form] = Form.useForm();
44
44
  const emailValue = Form.useWatch("email", form);
45
45
  const zipFileUrlValue = Form.useWatch("zip_file_url", form);
46
- const emailsValue = Form.useWatch("emails", form);
47
46
  const isSubmitDisabled = useMemo(() => {
48
47
  if (loading)
49
48
  return true;
@@ -51,9 +50,9 @@ const BulkUploadModal = ({ toggleUpload, userEmail, folderId, thumbnailsOnly, })
51
50
  const hasAssetFile = assetsSourceType === "zip"
52
51
  ? assetFile && !assetFileError
53
52
  : !!(zipFileUrlValue === null || zipFileUrlValue === void 0 ? void 0 : zipFileUrlValue.trim());
54
- const hasEmails = Array.isArray(emailsValue) &&
55
- emailsValue.length > 0 &&
56
- emailsValue.every((e) => get(validateEmail(e), "valid"));
53
+ const hasEmails = Array.isArray(emailValue) &&
54
+ emailValue.length > 0 &&
55
+ emailValue.every((e) => get(validateEmail(e), "valid"));
57
56
  return !hasAssetFile || !hasEmails;
58
57
  }
59
58
  const hasAssetType = !!assetTypeId;
@@ -74,7 +73,6 @@ const BulkUploadModal = ({ toggleUpload, userEmail, folderId, thumbnailsOnly, })
74
73
  assetsSourceType,
75
74
  emailValue,
76
75
  zipFileUrlValue,
77
- emailsValue,
78
76
  ]);
79
77
  useEffect(() => {
80
78
  onFetchAssetTemplates();
@@ -316,7 +316,7 @@ function DriveContainer({ parentFolderId, setSelectedFile, setParentFolderId, pi
316
316
  if (setGlobalSearch)
317
317
  setGlobalSearch("");
318
318
  };
319
- return (_jsx(RefetchFoldersProvider, { value: refetch, children: _jsxs("div", { className: "md-lib-h-[inherit]", children: [type !== DriveModes.FILE && (_jsx(_Fragment, { children: _jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-px-4 md-lib-h-20 md-lib-justify-between md-lib-border-b md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-mb-4", children: [imagePicker ? (_jsx(ImagePickerBreadCrumbList, { folder: parentFolder, parentFolderId: parentFolderId, setParentFolderId: setParentFolderId, pickerFolderId: pickerFolderId })) : (_jsx(_Fragment, { children: _jsx(BreadCrumbList, { folder: parentFolder, parentFolderId: parentFolderId, setParentFolderId: setParentFolderId, pickerFolderId: pickerFolderId, globalSearch: globalSearch, setSelectedKeys: setSelectedKeys }) })), isAdmin && _jsx(AddDrive, { parentFolderId: parentFolderId }), get(imagePicker, "allowNewFiles") && (_jsx(Upload, { beforeUpload: (file) => {
319
+ return (_jsx(RefetchFoldersProvider, { value: refetch, children: _jsxs("div", { className: "md-lib-h-[inherit]", children: [type !== DriveModes.FILE && (_jsx(_Fragment, { children: _jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-px-4 md-lib-h-20 md-lib-justify-between md-lib-border-b md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-mb-4", children: [imagePicker ? (_jsx(ImagePickerBreadCrumbList, { folder: parentFolder, parentFolderId: parentFolderId, setParentFolderId: setParentFolderId, pickerFolderId: pickerFolderId, imagePickerModal: true })) : (_jsx(_Fragment, { children: _jsx(BreadCrumbList, { folder: parentFolder, parentFolderId: parentFolderId, setParentFolderId: setParentFolderId, pickerFolderId: pickerFolderId, globalSearch: globalSearch, setSelectedKeys: setSelectedKeys }) })), isAdmin && _jsx(AddDrive, { parentFolderId: parentFolderId }), get(imagePicker, "allowNewFiles") && (_jsx(Upload, { beforeUpload: (file) => {
320
320
  onSelectNewFile(file);
321
321
  }, showUploadList: false, accept: "image/*", children: _jsx(CustomButton, { loading: loadingType === "NEW_FILE_UPLOAD", label: "Select File", icon: _jsx(BsUploadIcon, {}) }) }))] }) })), _jsxs("div", { className: `md-lib-px-4 md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-flex ${!includes([DriveModes.FOLDERS, DriveModes.FILE], type)
322
322
  ? "md-lib-justify-between"
@@ -22,7 +22,7 @@ import { DownloadOutlined, } from "@ant-design/icons";
22
22
  import AddFolder from "./AddFolder";
23
23
  import { useMutation, useQueryClient } from "react-query";
24
24
  import { archiveFiles, deleteFiles, downloadFiles, duplicateFiles, restoreFiles, unarchiveFiles, useFile, } from "../react-query/services/file-services";
25
- import { ADDED_TO_FAV_MSG, ARCHIVE_OK_TEXT, ARCHIVE_SUCCESS, CREATE_SUCCESS, DELETE_CONFIRMATION_MESSAGE, DELETE_MESSAGE_DESCRIPTION, DELETE_OK_TEXT, DELETE_SUCCESS, INVALID_URL, REMOVED_FROM_FAV_MSG, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
25
+ import { ADDED_TO_FAV_MSG, ARCHIVE_OK_TEXT, ARCHIVE_SUCCESS, CREATE_SUCCESS, DELETE_CONFIRMATION_MESSAGE, DELETE_OK_TEXT, DELETE_SUCCESS, INVALID_URL, REMOVED_FROM_FAV_MSG, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
26
26
  import { getSelectedFiles, } from "../react-query/hooks/folder-hooks";
27
27
  import { generateFoldersQueryKey, invalidateData, QueryKeys, } from "../utilities/constants/queryKeys";
28
28
  import { useRefetchFolders } from "../utilities/FoldersContext";
@@ -445,6 +445,8 @@ function FileMenuOptions({ file, folderIds = [], fileIds = [], folder, onCloseSe
445
445
  ? "md-lib-cursor-not-allowed md-lib-text-disabledBtnColor dark:md-lib-text-darkBorderColor"
446
446
  : "md-lib-cursor-pointer", onClick: (e) => e.stopPropagation() }) }), displayUpdateName && (!!file || !!folder) && (_jsx(AddFolder, { file: file, open: displayUpdateName, handleCancel: toggleDisplayUpdateName, folder: folder, onCloseSelection: onCloseSelection, fileModal: fileModal })), _jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmPopup, icon: actionType === "archive" ? (_jsx(IoArchiveOutlineIcon, {})) : (_jsx(DeleteOutlined, {})), okText: actionType === "archive" ? ARCHIVE_OK_TEXT : DELETE_OK_TEXT, description: isMultiSelection
447
447
  ? DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(" :entity", "")
448
- : DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(":entity", get(file, "name", "this file")), onOk: actionType === "archive" ? onArchiveFile : onDeleteFile, subHeading: actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION, loading: deleteFileMutation.isLoading || archiveFileMutation.isLoading }), showPreviewModal && (_jsx(FileDetails, { open: showPreviewModal, handleClose: toggleShowPreviewModal, file: file || undefined, files: getSelectedFiles(queryClient, folderId ? folderId : rootFolderId, generateFoldersQueryKey(type), file ? [get(file, "_id")] : fileIds), fileIds: file ? [get(file, "_id")] : fileIds, onCloseSelection: onCloseSelection })), showMoveFolder && (effectiveFile || file) && (_jsx(MoveToAnotherFolder, { open: showMoveFolder, handleCancel: toggleShowMoveFolder, fileIds: effectiveFile ? [get(effectiveFile, "_id")] : [get(file, "_id")], folderIds: [], entity: effectiveFile || file, onCloseSelection: onCloseSelection })), showShareModal && (_jsx(InviteTeamModal, { open: showShareModal, onClose: toggleShareModal, onFetchInvitations: () => { }, shareModal: true, fileIds: file ? [get(file, "_id")] : fileIds, folderIds: folderIds, inviteType: DriveModes.FILE, file: file })), showFileAccess && (file || folder) && (_jsx(ManageFile, { open: showFileAccess, onClose: toggleFileAccess, file: file ? file : folder })), showLogsModal && (_jsx(FileDownloadHistory, { file: file ? file : folder, open: showLogsModal, onClose: toggleLogsModal }))] }));
448
+ : DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(":entity", get(file, "name", "this file")), onOk: actionType === "archive" ? onArchiveFile : onDeleteFile,
449
+ // subHeading={actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION}
450
+ loading: deleteFileMutation.isLoading || archiveFileMutation.isLoading }), showPreviewModal && (_jsx(FileDetails, { open: showPreviewModal, handleClose: toggleShowPreviewModal, file: file || undefined, files: getSelectedFiles(queryClient, folderId ? folderId : rootFolderId, generateFoldersQueryKey(type), file ? [get(file, "_id")] : fileIds), fileIds: file ? [get(file, "_id")] : fileIds, onCloseSelection: onCloseSelection })), showMoveFolder && (effectiveFile || file) && (_jsx(MoveToAnotherFolder, { open: showMoveFolder, handleCancel: toggleShowMoveFolder, fileIds: effectiveFile ? [get(effectiveFile, "_id")] : [get(file, "_id")], folderIds: [], entity: effectiveFile || file, onCloseSelection: onCloseSelection })), showShareModal && (_jsx(InviteTeamModal, { open: showShareModal, onClose: toggleShareModal, onFetchInvitations: () => { }, shareModal: true, fileIds: file ? [get(file, "_id")] : fileIds, folderIds: folderIds, inviteType: DriveModes.FILE, file: file })), showFileAccess && (file || folder) && (_jsx(ManageFile, { open: showFileAccess, onClose: toggleFileAccess, file: file ? file : folder })), showLogsModal && (_jsx(FileDownloadHistory, { file: file ? file : folder, open: showLogsModal, onClose: toggleLogsModal }))] }));
449
451
  }
450
452
  export default FileMenuOptions;
@@ -19,7 +19,9 @@ const FilesGridView = ({ files, handleClick, selectedFileIds, isImagePicker, sel
19
19
  type !== DriveModes.FOLDERS &&
20
20
  get(file, "fileUploadStatus") !== ThumbnailStatus.PENDING && (_jsx(FileMenuOptions, { file: file }))] }), _jsx("div", { className: "md-lib-mt-2 md-lib-h-28 md-lib-mx-2.5 md-lib-bg-white dark:md-lib-bg-darkPrimaryHoverColor md-lib-rounded-md md-lib-flex md-lib-justify-center", children: get(file, "fileUploadStatus") === ThumbnailStatus.PENDING ? (
21
21
  // <IconInprogress className="mt-10 text-[40px] text-imagesColor" />
22
- _jsx(Image, { src: UPLOAD_FILE_IN_PROGRESS_WHITE_IMAGE, width: 100, height: 100 })) : (_jsx("img", { src: get(file, "thumbnailUrl", ""), width: 100, height: 100, alt: get(file, "name", "N/A") })) }), _jsx("div", { children: _jsx("p", { className: "md-lib-text-xs md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-px-5 md-lib-pt-2.5 md-lib-truncate md-lib-max-w-40", title: get(file, "name", "N/A"), children: get(file, "assetName", "N/A") }) })] }, get(file, "_id")));
22
+ _jsx(Image, { src: UPLOAD_FILE_IN_PROGRESS_WHITE_IMAGE, width: 100, height: 100 })) : (_jsx("img", { src: get(file, "thumbnailUrl", ""),
23
+ // width={100}
24
+ height: 100, alt: get(file, "name", "N/A"), className: "mb-lib-w-auto" })) }), _jsx("div", { children: _jsx("p", { className: "md-lib-text-xs md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-px-5 md-lib-pt-2.5 md-lib-truncate md-lib-max-w-40", title: get(file, "name", "N/A"), children: get(file, "assetName", "N/A") }) })] }, get(file, "_id")));
23
25
  }) }));
24
26
  };
25
27
  export default FilesGridView;
@@ -152,7 +152,7 @@ const FolderListView = ({ folders, foldersFetching, hasNextPage, fetchNextPage,
152
152
  }
153
153
  return groupBy(sortedFolders, (folder) => formatGroupDate(get(folder, "updatedAt")));
154
154
  }, [sortedFolders, sortByKey]);
155
- return (_jsxs("div", { className: "md-lib-space-y-6 md-lib-relative ", children: [_jsxs("div", { className: "md-lib-flex md-lib-justify-between md-lib-items-center md-lib-px-2 md-lib-min-w-fit md-lib-gap-2 mb-lib-sticky md-lib-top-0 md-lib-bg-white dark:md-lib-bg-darkPrimary", children: [!isImagePicker && type !== DriveModes.FOLDERS && (_jsx("div", { className: "md-lib-w-6", children: ((searchKey && searchValue) || (metadataKey && metadataValue)) && (_jsx("div", { className: "md-lib-p-1 md-lib-border md-lib-rounded md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-cursor-pointer", children: _jsx(Tooltip, { title: "Clear filter", children: _jsx(ClearFilterIcon, { fill: get(theme, "variables.primaryColor"), onClick: () => {
155
+ return (_jsxs("div", { className: "md-lib-space-y-6 md-lib-relative ", children: [_jsxs("div", { className: "md-lib-flex md-lib-justify-between md-lib-items-center md-lib-px-2 md-lib-min-w-fit md-lib-gap-2 mb-lib-sticky md-lib-top-0 md-lib-bg-white dark:md-lib-bg-darkPrimary", style: { position: "sticky", top: '0' }, children: [!isImagePicker && type !== DriveModes.FOLDERS && (_jsx("div", { className: "md-lib-w-6", children: ((searchKey && searchValue) || (metadataKey && metadataValue)) && (_jsx("div", { className: "md-lib-p-1 md-lib-border md-lib-rounded md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-cursor-pointer", children: _jsx(Tooltip, { title: "Clear filter", children: _jsx(ClearFilterIcon, { fill: get(theme, "variables.primaryColor"), onClick: () => {
156
156
  onSearch({
157
157
  searchKey: "",
158
158
  searchValue: "",
@@ -6,7 +6,7 @@ import { IoArchiveOutline, IoDuplicateOutline } from "react-icons/io5";
6
6
  import { useMemo, useState } from "react";
7
7
  import { DriveModes, NotificationStatus, } from "../utilities/constants/interface";
8
8
  import { DeleteConfirmationModal } from "../common/CustomElements";
9
- import { ADDED_TO_FAV_MSG, ARCHIVE_OK_TEXT, ARCHIVE_SUCCESS, DELETE_CONFIRMATION_MESSAGE, DELETE_MESSAGE_DESCRIPTION, DELETE_OK_TEXT, DELETE_SUCCESS, DUPLICATE_SUCCESS, INVALID_URL, REMOVED_FROM_FAV_MSG, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
9
+ import { ADDED_TO_FAV_MSG, ARCHIVE_OK_TEXT, ARCHIVE_SUCCESS, DELETE_CONFIRMATION_MESSAGE, DELETE_OK_TEXT, DELETE_SUCCESS, DUPLICATE_SUCCESS, INVALID_URL, REMOVED_FROM_FAV_MSG, RESTORE_SUCCESS, SOMETHING_WENT_WRONG, } from "../utilities/constants/messages";
10
10
  import { filter, get, includes } from "lodash";
11
11
  import { useMutation, useQueryClient } from "react-query";
12
12
  import { addToFavFolders, archiveFolders, deleteFolders, duplicateFolder, removeFromFavFolders, restoreFolders, unarchiveFolders, } from "../react-query/services/folder-services";
@@ -345,6 +345,8 @@ function FolderMenuOptions({ folder }) {
345
345
  const currentMenuItems = useMemo(() => {
346
346
  return filterActions(items, get(AllowedFolderActions, type));
347
347
  }, [type, items]);
348
- return (_jsxs(_Fragment, { children: [_jsx(Dropdown, { menu: { items: currentMenuItems }, trigger: ["click"], children: _jsx(BsThreeDotsVerticalIcon, { size: 20, className: "md-lib-cursor-pointer", onClick: (e) => e.stopPropagation() }) }), _jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmPopup, icon: actionType === "archive" ? (_jsx(IoArchiveOutlineIcon, {})) : (_jsx(DeleteOutlined, {})), okText: actionType === "archive" ? ARCHIVE_OK_TEXT : DELETE_OK_TEXT, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(":entity", get(folder, "name", "this folder")), subHeading: actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION, onOk: actionType === "archive" ? onArchiveFolder : onDeleteFolder, loading: deleteFolderMutation.isLoading || archiveFolderMutation.isLoading }), _jsx(AddFolder, { open: showUpdateModal, handleCancel: toggleUpdateModal, folder: folder }), showMoveFolder && (_jsx(MoveToAnotherFolder, { open: showMoveFolder, handleCancel: toggleShowMoveFolder, folderIds: [get(folder, "_id")], entity: folder })), showShareModal && (_jsx(InviteTeamModal, { open: showShareModal, onClose: toggleShareModal, onFetchInvitations: () => { }, shareModal: true, fileIds: [], folderIds: [get(folder, "_id")], inviteType: DriveModes.FOLDERS, file: folder })), showFileAccess && folder && (_jsx(ManageFile, { open: showFileAccess, onClose: toggleFileAccess, file: folder })), showLogs && (_jsx(FileDownloadHistory, { file: folder, open: showLogs, onClose: toggleLogsModal }))] }));
348
+ return (_jsxs(_Fragment, { children: [_jsx(Dropdown, { menu: { items: currentMenuItems }, trigger: ["click"], children: _jsx(BsThreeDotsVerticalIcon, { size: 20, className: "md-lib-cursor-pointer", onClick: (e) => e.stopPropagation() }) }), _jsx(DeleteConfirmationModal, { showDeleteModal: showConfirmModal, toggleDeleteModal: toggleConfirmPopup, icon: actionType === "archive" ? (_jsx(IoArchiveOutlineIcon, {})) : (_jsx(DeleteOutlined, {})), okText: actionType === "archive" ? ARCHIVE_OK_TEXT : DELETE_OK_TEXT, description: DELETE_CONFIRMATION_MESSAGE.replace(":action", actionType).replace(":entity", get(folder, "name", "this folder")),
349
+ // subHeading={actionType === "archive" ? "" : DELETE_MESSAGE_DESCRIPTION}
350
+ onOk: actionType === "archive" ? onArchiveFolder : onDeleteFolder, loading: deleteFolderMutation.isLoading || archiveFolderMutation.isLoading }), _jsx(AddFolder, { open: showUpdateModal, handleCancel: toggleUpdateModal, folder: folder }), showMoveFolder && (_jsx(MoveToAnotherFolder, { open: showMoveFolder, handleCancel: toggleShowMoveFolder, folderIds: [get(folder, "_id")], entity: folder })), showShareModal && (_jsx(InviteTeamModal, { open: showShareModal, onClose: toggleShareModal, onFetchInvitations: () => { }, shareModal: true, fileIds: [], folderIds: [get(folder, "_id")], inviteType: DriveModes.FOLDERS, file: folder })), showFileAccess && folder && (_jsx(ManageFile, { open: showFileAccess, onClose: toggleFileAccess, file: folder })), showLogs && (_jsx(FileDownloadHistory, { file: folder, open: showLogs, onClose: toggleLogsModal }))] }));
349
351
  }
350
352
  export default FolderMenuOptions;
@@ -232,13 +232,34 @@ function FolderTree({ currentRootId, expandedKeys, selectedKeys, handleExpand, s
232
232
  prevCurrentRootIdRef.current = currentRootId;
233
233
  }
234
234
  else {
235
- if (currentRootId === rootFolderId || folders.length === 0) {
235
+ // When folders is empty and we have a subfolder ID (e.g. from URL refresh),
236
+ // fetch root first so the full tree is visible, then expand to the selected folder
237
+ if (folders.length === 0 && currentRootId !== rootFolderId) {
238
+ // Don't set prevCurrentRootIdRef yet - we need to re-run when folders is populated
239
+ fetchFolders(rootFolderId);
240
+ }
241
+ else if (currentRootId === rootFolderId || folders.length === 0) {
236
242
  prevCurrentRootIdRef.current = currentRootId;
237
243
  fetchFolders(currentRootId);
238
244
  }
239
245
  else {
240
- console.log('## Folder not in tree but tree has content - keeping existing tree structure');
241
- prevCurrentRootIdRef.current = currentRootId;
246
+ // Folder not in tree - it may be a nested subfolder (e.g. "Books Sub folder" under "Book")
247
+ // Fetch children for top-level folders until the target appears in the tree
248
+ console.log('## Folder not in tree - fetching children to find nested subfolder:', currentRootId);
249
+ (() => __awaiter(this, void 0, void 0, function* () {
250
+ setState((s) => (Object.assign(Object.assign({}, s), { loading: true })));
251
+ for (const folder of folders) {
252
+ const fid = get(folder, "_id");
253
+ if (!fid)
254
+ continue;
255
+ const hasChildrenLoaded = isArray(folder.children) && folder.children.length > 0;
256
+ if (!hasChildrenLoaded) {
257
+ yield fetchFolderChildren(fid);
258
+ // Effect will re-run when folders update; if target is now in tree, we'll expand
259
+ }
260
+ }
261
+ setState((s) => (Object.assign(Object.assign({}, s), { loading: false })));
262
+ }))();
242
263
  }
243
264
  }
244
265
  }
@@ -247,7 +268,7 @@ function FolderTree({ currentRootId, expandedKeys, selectedKeys, handleExpand, s
247
268
  console.log('## FolderTree useEffect - globalSearch changed, refetching root folder');
248
269
  fetchFolders(currentRootId);
249
270
  }
250
- }, [currentRootId, globalSearch]);
271
+ }, [currentRootId, globalSearch, folders]);
251
272
  // ✅ Handle sort dropdown
252
273
  const handleSortChange = (value) => {
253
274
  setState((prevState) => {
@@ -1,8 +1,9 @@
1
1
  import { FolderEntity } from "../utilities/constants/interface";
2
- declare function ImagePickerBreadCrumbList({ folder, parentFolderId, setParentFolderId, pickerFolderId, }: {
2
+ declare function ImagePickerBreadCrumbList({ folder, parentFolderId, setParentFolderId, pickerFolderId, imagePickerModal }: {
3
3
  folder: FolderEntity;
4
4
  parentFolderId?: string;
5
5
  setParentFolderId?: (id: string) => void;
6
6
  pickerFolderId?: string;
7
+ imagePickerModal?: boolean;
7
8
  }): JSX.Element;
8
9
  export default ImagePickerBreadCrumbList;
@@ -5,7 +5,7 @@ import { useMemo } from "react";
5
5
  import { FaChevronRight } from "react-icons/fa";
6
6
  import { useDamConfig } from "../hocs/DamConfigContext";
7
7
  const FaChevronRightIcon = FaChevronRight;
8
- function ImagePickerBreadCrumbList({ folder, parentFolderId, setParentFolderId, pickerFolderId, }) {
8
+ function ImagePickerBreadCrumbList({ folder, parentFolderId, setParentFolderId, pickerFolderId, imagePickerModal }) {
9
9
  const damConfig = useDamConfig();
10
10
  const { rootFolderId } = damConfig;
11
11
  const tree = useMemo(() => {
@@ -29,7 +29,7 @@ function ImagePickerBreadCrumbList({ folder, parentFolderId, setParentFolderId,
29
29
  setParentFolderId(treeId);
30
30
  }
31
31
  };
32
- return (_jsx(Breadcrumb.Item, { onClick: handleClick, className: "md-lib-h-auto md-lib-cursor-pointer", children: _jsx(Tooltip, { title: name, children: _jsx("p", { className: "md-lib-max-w-28 md-lib-truncate md-lib-font-semibold md-lib-text-[22px]", children: name }) }) }, treeId));
32
+ return (_jsx(Breadcrumb.Item, { onClick: handleClick, className: "md-lib-h-auto md-lib-cursor-pointer", children: _jsx(Tooltip, { title: name, children: _jsx("p", { className: `${!imagePickerModal && "md-lib-max-w-28"} md-lib-truncate md-lib-font-semibold md-lib-text-[22px]`, children: name }) }) }, treeId));
33
33
  }) }));
34
34
  }
35
35
  export default ImagePickerBreadCrumbList;
@@ -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
  }
@@ -17,7 +17,7 @@ import CustomButton from "../../common/Button";
17
17
  import { MoreOutlined } from "@ant-design/icons";
18
18
  import { useMemo, useState } from "react";
19
19
  import { DeleteConfirmationModal } from "../../common/CustomElements";
20
- import { DELETE_CONFIRMATION_MESSAGE, DELETE_MESSAGE_DESCRIPTION, DELETE_OK_TEXT, DELETE_SUCCESS, SOMETHING_WENT_WRONG, UPDATE_SUCCESS, } from "../../utilities/constants/messages";
20
+ import { DELETE_CONFIRMATION_MESSAGE, DELETE_OK_TEXT, DELETE_SUCCESS, SOMETHING_WENT_WRONG, UPDATE_SUCCESS, } from "../../utilities/constants/messages";
21
21
  import { FETCH_COMMENT_URL } from "../../utilities/constants/apiUrls";
22
22
  import { showNotification } from "../../common/notifications";
23
23
  import Editor from "./Editor";
@@ -97,6 +97,6 @@ function CommentEntity({ comment, refreshData, parentId, file, }) {
97
97
  likes: includes(likesArray, userId)
98
98
  ? filter(likesArray, (id) => id !== userId)
99
99
  : [...likesArray, userId],
100
- }, "like") })] })] }, get(commentData, "_id"))), showConfimation && (_jsx(DeleteConfirmationModal, { showDeleteModal: showConfimation, toggleDeleteModal: toggleConfirmation, okText: DELETE_OK_TEXT, onOk: onDeleteComment, loading: loadingType === "delete", description: DELETE_CONFIRMATION_MESSAGE.replace(":action", "Delete").replace(" :entity", ""), subHeading: DELETE_MESSAGE_DESCRIPTION })), showReplies && (_jsxs("div", { className: "md-lib-mt-3 md-lib-ml-12 md-lib-flex md-lib-flex-col md-lib-gap-3 md-lib-animate-fade-in md-lib-transition-all md-lib-duration-300 md-lib-ease-in-out", children: [_jsx("p", { className: "md-lib-text-sm md-lib-text-secondaryTextColor dark:md-lib-text-darkSecondaryTextColor md-lib-font-semibold", children: "Replies" }), _jsx(Comments, { parentId: get(comment, "_id"), file: file })] }))] }));
100
+ }, "like") })] })] }, get(commentData, "_id"))), showConfimation && (_jsx(DeleteConfirmationModal, { showDeleteModal: showConfimation, toggleDeleteModal: toggleConfirmation, okText: DELETE_OK_TEXT, onOk: onDeleteComment, loading: loadingType === "delete", description: DELETE_CONFIRMATION_MESSAGE.replace(":action", "Delete").replace(" :entity", "") })), showReplies && (_jsxs("div", { className: "md-lib-mt-3 md-lib-ml-12 md-lib-flex md-lib-flex-col md-lib-gap-3 md-lib-animate-fade-in md-lib-transition-all md-lib-duration-300 md-lib-ease-in-out", children: [_jsx("p", { className: "md-lib-text-sm md-lib-text-secondaryTextColor dark:md-lib-text-darkSecondaryTextColor md-lib-font-semibold", children: "Replies" }), _jsx(Comments, { parentId: get(comment, "_id"), file: file })] }))] }));
101
101
  }
102
102
  export default CommentEntity;
@@ -31,6 +31,7 @@ const FileDetails = ({ open, handleClose, file, files, fileIds, onCloseSelection
31
31
  console.log("## FileDetails - files:", files, "file:", file, "initialFile:", initialFile, "fileIds:", fileIds, "initialFileId:", initialFileId);
32
32
  const { id } = useAppParams();
33
33
  const damConfig = useDamConfig();
34
+ const headerHeight = get(damConfig, "headerHeight", 0) || 0;
34
35
  const api = useMemo(() => createApiClient(damConfig), [damConfig]);
35
36
  const [state, setState] = useState({
36
37
  visible: false,
@@ -108,18 +109,37 @@ const FileDetails = ({ open, handleClose, file, files, fileIds, onCloseSelection
108
109
  setState((prevState) => (Object.assign(Object.assign({}, prevState), { visible: false })));
109
110
  }
110
111
  }, [open]);
112
+ // Lock body scroll when preview modal is open so drive page files don't scroll behind it
113
+ // Add body class so host app can lower header z-index and let preview modal appear above it
114
+ useEffect(() => {
115
+ if (open && visible) {
116
+ const prevBodyOverflow = document.body.style.overflow;
117
+ const prevHtmlOverflow = document.documentElement.style.overflow;
118
+ document.body.style.overflow = "hidden";
119
+ document.documentElement.style.overflow = "hidden";
120
+ document.body.classList.add("dam-preview-open");
121
+ return () => {
122
+ document.body.style.overflow = prevBodyOverflow;
123
+ document.documentElement.style.overflow = prevHtmlOverflow;
124
+ document.body.classList.remove("dam-preview-open");
125
+ };
126
+ }
127
+ }, [open, visible]);
111
128
  if (!open && !visible)
112
129
  return null;
113
- const modalContent = (_jsxs("div", { className: `md-lib-fixed md-lib-inset-0 md-lib-z-[1000] md-lib-w-screen md-lib-h-screen md-lib-bg-white dark:md-lib-bg-darkPrimary md-lib-text-black dark:md-lib-text-white md-lib-overflow-auto md-lib-transform md-lib-transition-all md-lib-duration-300 md-lib-ease-in-out ${open && visible
130
+ const modalStyle = headerHeight > 0
131
+ ? { top: headerHeight, left: 0, right: 0, bottom: 0, height: `calc(100vh - ${headerHeight}px)` }
132
+ : undefined;
133
+ const modalContent = (_jsxs("div", { className: `md-lib-fixed md-lib-z-[1000] md-lib-w-screen md-lib-bg-white dark:md-lib-bg-darkPrimary md-lib-text-black dark:md-lib-text-white md-lib-flex md-lib-flex-col md-lib-transform md-lib-transition-all md-lib-duration-300 md-lib-ease-in-out ${headerHeight === 0 ? "md-lib-inset-0 md-lib-h-screen" : ""} ${open && visible
114
134
  ? "md-lib-opacity-100 md-lib-translate-y-0"
115
- : "md-lib-opacity-0 md-lib-translate-y-4"}`, onTransitionEnd: () => {
135
+ : "md-lib-opacity-0 md-lib-translate-y-4"}`, style: modalStyle, onTransitionEnd: () => {
116
136
  if (!open)
117
137
  setState((prevState) => (Object.assign(Object.assign({}, prevState), { visible: false })));
118
- }, children: [_jsx(FileDetailsHeader, { handleClose: handleClose, file: currentFile, onCloseSelection: onCloseSelection }), isFetching ? (_jsx(Loader, {})) : (_jsx(FileViewer, { file: currentFile, hasPrev: (!!files && currentIndex > 0) ||
119
- (!!fileIds && fileIds.length > 1 && currentIndex > 0) ||
120
- !!get(currentFile, "prevFileId"), hasNext: (!!files && currentIndex < get(files, "length", 0) - 1) ||
121
- (!!fileIds && fileIds.length > 1 && currentIndex < fileIds.length - 1) ||
122
- !!get(currentFile, "nextFileId"), onPrev: handlePrevious, onNext: handleNext, handleClose: handleClose }))] }));
138
+ }, children: [_jsx("div", { className: "md-lib-shrink-0", children: _jsx(FileDetailsHeader, { handleClose: handleClose, file: currentFile, onCloseSelection: onCloseSelection }) }), _jsx("div", { className: "md-lib-flex-1 md-lib-min-h-0 md-lib-overflow-auto", children: isFetching ? (_jsx(Loader, {})) : (_jsx(FileViewer, { file: currentFile, hasPrev: (!!files && currentIndex > 0) ||
139
+ (!!fileIds && fileIds.length > 1 && currentIndex > 0) ||
140
+ !!get(currentFile, "prevFileId"), hasNext: (!!files && currentIndex < get(files, "length", 0) - 1) ||
141
+ (!!fileIds && fileIds.length > 1 && currentIndex < fileIds.length - 1) ||
142
+ !!get(currentFile, "nextFileId"), onPrev: handlePrevious, onNext: handleNext, handleClose: handleClose })) })] }));
123
143
  return ReactDOM.createPortal(modalContent, document.body);
124
144
  };
125
145
  export default FileDetails;
@@ -2,20 +2,18 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from "antd";
3
3
  import { IoIosClose } from "react-icons/io";
4
4
  import { BsDownload } from "react-icons/bs";
5
- import { DriveModes, NotificationStatus, } from "../../utilities/constants/interface";
5
+ import { NotificationStatus, } from "../../utilities/constants/interface";
6
6
  import { get } from "lodash";
7
7
  import { showNotification } from "../../common/notifications";
8
8
  import { INVALID_URL } from "../../utilities/constants/messages";
9
9
  import FileMenuOptions from "../FileMenuOptions";
10
10
  import { useDamConfig } from "../../hocs/DamConfigContext";
11
- import useAppParams from "../../utilities/useAppParams";
12
11
  const IoIosCloseIcon = IoIosClose;
13
12
  const BsDownloadIcon = BsDownload;
14
13
  const FileDetailsHeader = ({ handleClose, file, onCloseSelection, }) => {
15
14
  const damConfig = useDamConfig();
16
15
  const { isAdmin } = damConfig;
17
- const { id, type } = useAppParams();
18
- return (_jsxs("div", { className: "md-lib-bg-white dark:md-lib-bg-darkPrimaryHoverColor md-lib-py-3 md-lib-px-5 md-lib-border-b md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-flex md-lib-justify-between md-lib-items-center", children: [_jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-gap-5", children: [!id && type !== DriveModes.FILE && (_jsx(IoIosCloseIcon, { className: "md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-cursor-pointer", size: 24, onClick: handleClose })), !!file && (_jsx("h4", { className: "md-lib-font-semibold md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-text-base md-lib-truncate md-lib-max-w-[calc(100vw-180px)]", title: get(file, "name", "N/A"), children: get(file, "name", "N/A") }))] }), !!file && (_jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-gap-4", children: [_jsx(FileMenuOptions, { file: file, fileIds: get(file, "_id") ? [get(file, "_id")] : [], onCloseSelection: onCloseSelection, fileModal: true }), _jsx(Button, { size: "large", className: "md-lib-bg-secondaryColor dark:md-lib-bg-darkSecondaryColor hover:md-lib-bg-secondaryHoverColor dark:hover:md-lib-bg-darkSecondaryColor md-lib-border-none", onClick: () => {
16
+ return (_jsxs("div", { className: "md-lib-bg-white dark:md-lib-bg-darkPrimaryHoverColor md-lib-py-3 md-lib-px-5 md-lib-border-b md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-flex md-lib-justify-between md-lib-items-center", children: [_jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-gap-5", children: [_jsx(IoIosCloseIcon, { className: "md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-cursor-pointer", size: 24, onClick: () => handleClose === null || handleClose === void 0 ? void 0 : handleClose(), "aria-label": "Close" }), !!file && (_jsx("h4", { className: "md-lib-font-semibold md-lib-text-textColor dark:md-lib-text-darkTextColor md-lib-text-base md-lib-truncate md-lib-max-w-[calc(100vw-180px)]", title: get(file, "name", "N/A"), children: get(file, "name", "N/A") }))] }), !!file && (_jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-gap-4", children: [_jsx(FileMenuOptions, { file: file, fileIds: get(file, "_id") ? [get(file, "_id")] : [], onCloseSelection: onCloseSelection, fileModal: true }), _jsx(Button, { size: "large", className: "md-lib-bg-secondaryColor dark:md-lib-bg-darkSecondaryColor hover:md-lib-bg-secondaryHoverColor dark:hover:md-lib-bg-darkSecondaryColor md-lib-border-none", onClick: () => {
19
17
  const url = get(file, "downloadUrl") || get(file, "s3Url") || get(file, "thumbnailUrl");
20
18
  if (!url) {
21
19
  showNotification(INVALID_URL, NotificationStatus.ERROR);
@@ -11,7 +11,7 @@ const FileViewer = ({ file, onNext, onPrev, hasNext, hasPrev, handleClose, }) =>
11
11
  const damConfig = useDamConfig();
12
12
  const brand = damConfig === null || damConfig === void 0 ? void 0 : damConfig.brand;
13
13
  const showFilePreview = get(brand, "showFilePreview", false);
14
- const [metadataOpen, setMetadataOpen] = useState(showFilePreview);
15
- return (_jsx(Layout, { className: "md-lib-h-full", children: _jsxs(Content, { className: "md-lib-flex md-lib-h-full md-lib-w-full", children: [_jsx("div", { className: `md-lib-flex md-lib-items-center md-lib-justify-center md-lib-relative md-lib-bg-textColorActive dark:md-lib-bg-darkSecondaryColor md-lib-min-h-full ${metadataOpen ? "md-lib-flex-1" : "md-lib-flex-1 md-lib-w-full"}`, children: _jsx(PreviewDetails, { file: file, hasNext: hasNext, hasPrev: hasPrev, onNext: onNext, onPrev: onPrev, showFilePreview: showFilePreview }) }), showFilePreview && (_jsxs(_Fragment, { children: [_jsx(Button, { type: "text", className: "md-lib-shrink-0 md-lib-flex md-lib-items-center md-lib-justify-center md-lib-w-10 md-lib-h-10 md-lib-rounded-none md-lib-bg-black/50 hover:md-lib-bg-black/70 dark:md-lib-bg-white/20 dark:hover:md-lib-bg-white/30 md-lib-text-white md-lib-border-0 md-lib-self-start md-lib-mt-4", onClick: () => setMetadataOpen((prev) => !prev), "aria-label": metadataOpen ? "Hide Metadata" : "Show Metadata", children: metadataOpen ? (_jsx(RightOutlined, { className: "md-lib-text-lg" })) : (_jsx(LeftOutlined, { className: "md-lib-text-lg" })) }), metadataOpen && (_jsx("div", { className: "md-lib-w-[400px] md-lib-min-w-[320px] md-lib-shrink-0 md-lib-border-l md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-bg-backgroundColor dark:md-lib-bg-darkPrimary md-lib-overflow-y-auto", children: _jsx(MapFile, { fromUpload: false, filesList: file ? [file] : [], handleCancel: handleClose ? () => handleClose() : undefined }) }))] }))] }) }));
14
+ const [metadataOpen, setMetadataOpen] = useState(true);
15
+ return (_jsx(Layout, { className: "md-lib-h-full", children: _jsxs(Content, { className: "md-lib-flex md-lib-h-full md-lib-w-full", children: [_jsx("div", { className: `md-lib-flex md-lib-items-center md-lib-justify-center md-lib-relative md-lib-bg-textColorActive dark:md-lib-bg-darkSecondaryColor md-lib-min-h-full ${metadataOpen ? "md-lib-flex-1" : "md-lib-flex-1 md-lib-w-full"}`, children: _jsx(PreviewDetails, { file: file, hasNext: hasNext, hasPrev: hasPrev, onNext: onNext, onPrev: onPrev, showFilePreview: showFilePreview }) }), _jsxs(_Fragment, { children: [_jsx(Button, { type: "text", className: "md-lib-shrink-0 md-lib-flex md-lib-items-center md-lib-justify-center md-lib-w-10 md-lib-h-10 md-lib-rounded-none md-lib-bg-black/50 hover:md-lib-bg-black/70 dark:md-lib-bg-white/20 dark:hover:md-lib-bg-white/30 md-lib-text-white md-lib-border-0 md-lib-self-start md-lib-mt-4", onClick: () => setMetadataOpen((prev) => !prev), "aria-label": metadataOpen ? "Hide Metadata" : "Show Metadata", children: metadataOpen ? (_jsx(RightOutlined, { className: "md-lib-text-lg" })) : (_jsx(LeftOutlined, { className: "md-lib-text-lg" })) }), metadataOpen && (_jsx("div", { className: "md-lib-w-[400px] md-lib-min-w-[320px] md-lib-shrink-0 md-lib-border-l md-lib-border-borderColor dark:md-lib-border-darkBorderColor md-lib-bg-backgroundColor dark:md-lib-bg-darkPrimary md-lib-overflow-y-auto", children: _jsx(MapFile, { fromUpload: false, filesList: file ? [file] : [], handleCancel: handleClose ? () => handleClose() : undefined, canEdit: showFilePreview }) }))] })] }) }));
16
16
  };
17
17
  export default FileViewer;
@@ -1,9 +1,14 @@
1
+ import React from "react";
1
2
  import type { FormInstance } from "antd";
2
3
  import { BrandUserEntity, MetaDataFieldEntity } from "../../utilities/constants/interface";
3
4
  export declare const buildInitialValues: (formData: Record<string, any>, metaFields: MetaDataFieldEntity[], isEditMode: boolean) => {
4
5
  [x: string]: any;
5
6
  };
6
- export declare const getFormItem: (item: MetaDataFieldEntity, fromDefaultValue: boolean, userOptions?: BrandUserEntity[]) => JSX.Element | null;
7
+ export declare const getFormItem: (item: MetaDataFieldEntity, fromDefaultValue: boolean, userOptions?: BrandUserEntity[], teamOptions?: {
8
+ label: React.ReactNode;
9
+ value: string;
10
+ key?: string;
11
+ }[]) => JSX.Element | null;
7
12
  declare const MetaForm: ({ metaFields, metaData, form, isEditMode, }: {
8
13
  metaFields: MetaDataFieldEntity[];
9
14
  metaData: {
@@ -1,6 +1,6 @@
1
- import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo } from "react";
3
- import { Form, Input, InputNumber, DatePicker, Select, Checkbox, Radio, } from "antd";
3
+ import { Form, Input, InputNumber, DatePicker, Select, Checkbox, Radio, Typography, } from "antd";
4
4
  import { find, first, get, includes, isArray, isNumber, map, mapValues, nth, } from "lodash";
5
5
  import dayjs from "dayjs";
6
6
  import { InputSupportedTypes, InputTypes, } from "../../utilities/constants/interface";
@@ -42,7 +42,7 @@ export const buildInitialValues = (formData, metaFields, isEditMode) => {
42
42
  }
43
43
  });
44
44
  };
45
- export const getFormItem = (item, fromDefaultValue, userOptions) => {
45
+ export const getFormItem = (item, fromDefaultValue, userOptions, teamOptions) => {
46
46
  const name = get(item, "_id");
47
47
  const label = get(item, "name");
48
48
  const placeholder = get(item, "placeholder", "");
@@ -112,10 +112,12 @@ export const getFormItem = (item, fromDefaultValue, userOptions) => {
112
112
  // VALUE_RANGE
113
113
  if (defaultName === InputTypes.NUMBERS &&
114
114
  get(settings, "VALUE_RANGE.allow")) {
115
- const min = get(settings, "VALUE_RANGE.minValue");
116
- const max = get(settings, "VALUE_RANGE.maxValue");
117
- const hasMin = isNumber(min);
118
- const hasMax = isNumber(max);
115
+ const minRaw = get(settings, "VALUE_RANGE.minValue");
116
+ const maxRaw = get(settings, "VALUE_RANGE.maxValue");
117
+ const min = minRaw != null && minRaw !== "" ? Number(minRaw) : undefined;
118
+ const max = maxRaw != null && maxRaw !== "" ? Number(maxRaw) : undefined;
119
+ const hasMin = isNumber(min) && !Number.isNaN(min);
120
+ const hasMax = isNumber(max) && !Number.isNaN(max);
119
121
  let message = "";
120
122
  if (hasMin && hasMax) {
121
123
  message = `Must be between ${min} and ${max}.`;
@@ -126,7 +128,24 @@ export const getFormItem = (item, fromDefaultValue, userOptions) => {
126
128
  else if (!hasMin && hasMax) {
127
129
  message = `Maximum value is ${max}.`;
128
130
  }
129
- rules.push(Object.assign(Object.assign(Object.assign({ type: "number" }, (hasMin ? { min } : {})), (hasMax ? { max } : {})), { message }));
131
+ rules.push({
132
+ validator: (_, value) => {
133
+ if (value === undefined || value === null || value === "") {
134
+ return Promise.resolve();
135
+ }
136
+ const num = Number(value);
137
+ if (Number.isNaN(num)) {
138
+ return Promise.reject(new Error("Must be a valid number."));
139
+ }
140
+ if (hasMin && num < min) {
141
+ return Promise.reject(new Error(message || `Minimum value is ${min}.`));
142
+ }
143
+ if (hasMax && num > max) {
144
+ return Promise.reject(new Error(message || `Maximum value is ${max}.`));
145
+ }
146
+ return Promise.resolve();
147
+ },
148
+ });
130
149
  }
131
150
  switch (defaultName) {
132
151
  case InputTypes.TEXT:
@@ -163,6 +182,11 @@ export const getFormItem = (item, fromDefaultValue, userOptions) => {
163
182
  return false;
164
183
  }, placeholder: placeholder, options: userOptions, optionFilterProp: "children" }) }, name));
165
184
  case InputTypes.TEAM:
185
+ return (_jsx(Form.Item, { name: itemName, label: label, rules: rules, children: _jsx(Select, { mode: get(settings, InputSupportedTypes.ALLOW_MULTIPLE)
186
+ ? "multiple"
187
+ : undefined, allowClear: !!get(settings, InputSupportedTypes.ALLOW_CLEAR), showSearch: !!get(settings, InputSupportedTypes.SEARCHABLE), filterOption: (input, option) => ((option === null || option === void 0 ? void 0 : option.key) || String((option === null || option === void 0 ? void 0 : option.value) || ""))
188
+ .toLowerCase()
189
+ .indexOf(input.toLowerCase()) >= 0, placeholder: placeholder, options: teamOptions || [], optionFilterProp: "key" }) }, name));
166
190
  case InputTypes.SELECT:
167
191
  return (_jsx(Form.Item, { name: itemName, label: label, rules: rules, children: _jsx(Select, { mode: get(settings, InputSupportedTypes.ALLOW_MULTIPLE)
168
192
  ? "multiple"
@@ -185,6 +209,19 @@ const MetaForm = ({ metaFields, metaData, form, isEditMode, }) => {
185
209
  const brandId = get(brand, "_id");
186
210
  const queryClient = useQueryClient();
187
211
  const brandUsers = getCurrentBrandUsers(queryClient, brandId);
212
+ const teamOptions = useMemo(() => {
213
+ const externalTeams = (teams || []).filter((team) => get(team, "id") != null || get(team, "_id") != null);
214
+ return map(externalTeams, (team) => {
215
+ const teamId = get(team, "id") || get(team, "_id");
216
+ const teamName = get(team, "name", "");
217
+ const teamType = get(team, "type", "");
218
+ return {
219
+ label: (_jsxs(Typography.Text, { style: { display: "flex" }, children: [teamId, " ", teamName, " ", _jsx("span", { style: { marginLeft: "auto" }, children: teamType })] })),
220
+ value: teamId,
221
+ key: `${teamId} - ${teamName} - ${teamType}`,
222
+ };
223
+ });
224
+ }, [teams]);
188
225
  useEffect(() => {
189
226
  const formData = {
190
227
  metadata: buildInitialValues(metaData, metaFields, isEditMode),
@@ -194,6 +231,6 @@ const MetaForm = ({ metaFields, metaData, form, isEditMode, }) => {
194
231
  const userOptions = useMemo(() => {
195
232
  return map(brandUsers, (user) => getUserAvatar(user));
196
233
  }, [brandUsers, brandId]);
197
- return (_jsx(_Fragment, { children: metaFields.map((item) => getFormItem(item, false, userOptions)) }));
234
+ return (_jsx(_Fragment, { children: metaFields.map((item) => getFormItem(item, false, userOptions, teamOptions)) }));
198
235
  };
199
236
  export default MetaForm;
@@ -5,12 +5,10 @@ import { get, startsWith } from "lodash";
5
5
  import ImageViewer from "./ImageViewer";
6
6
  import { useMemo } from "react";
7
7
  import VideoPlayer from "./VideoPlayer";
8
- import useAppParams from "../../utilities/useAppParams";
9
8
  // const PDFViewer = lazy(() => import("./PdfViewer"));
10
9
  const GoArrowLeftIcon = GoArrowLeft;
11
10
  const GoArrowRightIcon = GoArrowRight;
12
11
  const PreviewDetails = ({ file, hasPrev, hasNext, onPrev, onNext, showFilePreview, }) => {
13
- const { id } = useAppParams();
14
12
  const mimetype = get(file, "mimetype", "");
15
13
  const fileComponent = useMemo(() => {
16
14
  if (startsWith(mimetype, "image/")) {
@@ -48,6 +46,6 @@ const PreviewDetails = ({ file, hasPrev, hasNext, onPrev, onNext, showFilePrevie
48
46
  );
49
47
  }
50
48
  }, [mimetype, file]);
51
- return (_jsxs(_Fragment, { children: [fileComponent, !id && (_jsxs(_Fragment, { children: [_jsx(Button, { icon: _jsx(GoArrowLeftIcon, { size: 24 }), className: "md-lib-h-11 md-lib-bg-white !md-lib-w-12 md-lib-rounded-lg md-lib-text-textColor dark:md-lib-text-darkTextColor dark:md-lib-bg-darkPrimary md-lib-absolute md-lib-left-6 md-lib-top-1/2 -md-lib-translate-y-1/2", onClick: onPrev, disabled: !hasPrev }), _jsx(Button, { icon: _jsx(GoArrowRightIcon, { size: 24 }), className: "md-lib-h-11 md-lib-bg-white !md-lib-w-12 md-lib-rounded-lg md-lib-text-textColor dark:md-lib-text-darkTextColor dark:md-lib-bg-darkPrimary md-lib-absolute md-lib-right-6 md-lib-top-1/2 -md-lib-translate-y-1/2", onClick: onNext, disabled: !hasNext })] }))] }));
49
+ return (_jsxs(_Fragment, { children: [fileComponent, _jsx(Button, { icon: _jsx(GoArrowLeftIcon, { size: 24 }), className: "md-lib-h-11 md-lib-bg-white !md-lib-w-12 md-lib-rounded-lg md-lib-text-textColor dark:md-lib-text-darkTextColor dark:md-lib-bg-darkPrimary md-lib-absolute md-lib-left-6 md-lib-top-1/2 -md-lib-translate-y-1/2", onClick: onPrev, disabled: !hasPrev }), _jsx(Button, { icon: _jsx(GoArrowRightIcon, { size: 24 }), className: "md-lib-h-11 md-lib-bg-white !md-lib-w-12 md-lib-rounded-lg md-lib-text-textColor dark:md-lib-text-darkTextColor dark:md-lib-bg-darkPrimary md-lib-absolute md-lib-right-6 md-lib-top-1/2 -md-lib-translate-y-1/2", onClick: onNext, disabled: !hasNext })] }));
52
50
  };
53
51
  export default PreviewDetails;
@@ -1,9 +1,10 @@
1
1
  import { FileEntity, ResponseFile } from "../../utilities/constants/interface";
2
- declare function MapFile({ open, handleCancel, filesList, fromUpload, parentFolderId, }: {
2
+ declare function MapFile({ open, handleCancel, filesList, fromUpload, parentFolderId, canEdit, }: {
3
3
  open?: boolean;
4
4
  handleCancel?: (shouldDelete?: boolean) => void;
5
5
  filesList: ResponseFile[] | FileEntity[];
6
6
  fromUpload?: boolean;
7
7
  parentFolderId?: string;
8
+ canEdit?: boolean;
8
9
  }): JSX.Element;
9
10
  export default MapFile;
@@ -27,7 +27,7 @@ import { DATE_FORMAT, DATE_WITH_TIME_FORMAT } from "../../hocs/appConstants";
27
27
  import dayjs from "dayjs";
28
28
  import useAppNavigate from "../../utilities/useAppNavigate";
29
29
  import { addQueryParams } from "../../hocs/helpers";
30
- function MapFile({ open, handleCancel, filesList, fromUpload, parentFolderId, }) {
30
+ function MapFile({ open, handleCancel, filesList, fromUpload, parentFolderId, canEdit = true, }) {
31
31
  const { folderId, type } = useAppParams();
32
32
  const damConfig = useDamConfig();
33
33
  const externalTeams = (damConfig === null || damConfig === void 0 ? void 0 : damConfig.teams) || [];
@@ -231,9 +231,15 @@ function MapFile({ open, handleCancel, filesList, fromUpload, parentFolderId, })
231
231
  },
232
232
  });
233
233
  };
234
- const getMetadataForm = (_jsxs(Form, { layout: "vertical", form: form, scrollToFirstError: true, onFinish: fromUpload ? handleSubmit : handleUpdate, className: "md-lib-m-2", children: [_jsx(AssetSelectionFormItem, { handleAssetTemplateChange: handleAssetTemplateChange, assetOptions: assetOptions, assetsLoading: assetsLoading }), selectedAssetTemplate && (_jsxs(_Fragment, { children: [_jsx(Form.Item, { name: "teamIds", label: "Teams", children: _jsx(Select, { options: teamOptions, placeholder: "Select teams", mode: "multiple", onChange: (val) => onChangeTeams(val), style: { width: "100%" }, showSearch: true, optionFilterProp: "key" }) }), _jsx(Form.Item, { name: "expiryDate", label: "Expiry Date", children: _jsx(DatePicker, { placeholder: "Expiry Date", style: { width: "100%" } }) }), _jsx(Metadata, { asset: selectedAssetTemplate, form: form, file: (filesList === null || filesList === void 0 ? void 0 : filesList[0]) || null })] })), _jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-justify-end md-lib-gap-3", children: [_jsx(Button, { onClick: handleCancelWithConfirmation, children: "Cancel" }), _jsx(Button, { disabled: !selectedAssetTemplate, type: "primary",
235
- // onClick={handleSubmit}
236
- loading: loading || updateFileMutation.isLoading, htmlType: "submit", children: "Save" })] })] }));
234
+ const preventEnterSubmit = (e) => {
235
+ if (e.key === "Enter" && e.target instanceof HTMLElement) {
236
+ const tagName = e.target.tagName.toLowerCase();
237
+ if (tagName !== "textarea") {
238
+ e.preventDefault();
239
+ }
240
+ }
241
+ };
242
+ const getMetadataForm = (_jsxs(Form, { layout: "vertical", form: form, scrollToFirstError: true, onFinish: fromUpload ? handleSubmit : handleUpdate, onKeyDown: preventEnterSubmit, className: "md-lib-m-2", disabled: !canEdit, children: [_jsx(AssetSelectionFormItem, { handleAssetTemplateChange: handleAssetTemplateChange, assetOptions: assetOptions, assetsLoading: assetsLoading }), selectedAssetTemplate && (_jsxs(_Fragment, { children: [_jsx(Form.Item, { name: "teamIds", label: "Teams", children: _jsx(Select, { options: teamOptions, placeholder: "Select teams", mode: "multiple", onChange: (val) => onChangeTeams(val), style: { width: "100%" }, showSearch: true, optionFilterProp: "key" }) }), _jsx(Form.Item, { name: "expiryDate", label: "Expiry Date", children: _jsx(DatePicker, { placeholder: "Expiry Date", style: { width: "100%" } }) }), _jsx(Metadata, { asset: selectedAssetTemplate, form: form, file: (filesList === null || filesList === void 0 ? void 0 : filesList[0]) || null })] })), _jsxs("div", { className: "md-lib-flex md-lib-items-center md-lib-justify-end md-lib-gap-3", children: [_jsx(Button, { onClick: handleCancelWithConfirmation, children: canEdit ? "Cancel" : "Close" }), canEdit && (_jsx(Button, { disabled: !selectedAssetTemplate, type: "primary", loading: loading || updateFileMutation.isLoading, htmlType: "submit", children: "Save" }))] })] }));
237
243
  return (_jsx(_Fragment, { children: fromUpload ? (_jsx(Drawer, { title: "Metadata", open: open, onClose: handleCancelWithConfirmation, maskClosable: false, children: getMetadataForm })) : (_jsxs("div", { className: "md-lib-p-2 md-lib-overflow-y-scroll md-lib-max-h-[calc(100vh-65px)]", children: [_jsx("p", { className: "md-lib-text-lg md-lib-font-semibold", children: "Metadata" }), getMetadataForm] })) }));
238
244
  }
239
245
  export default MapFile;
@@ -11,6 +11,8 @@ 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
+ /** Height of host app header (e.g. navbar) in px. When set, preview modal positions below it instead of covering. */
16
+ headerHeight?: number;
15
17
  }): JSX.Element;
16
18
  export default App;
@@ -23,6 +23,7 @@ function App(props) {
23
23
  parentId: props === null || props === void 0 ? void 0 : props.parentId,
24
24
  showSubfolders: props === null || props === void 0 ? void 0 : props.showSubfolders,
25
25
  routerVersion: props === null || props === void 0 ? void 0 : props.routerVersion,
26
+ headerHeight: props === null || props === void 0 ? void 0 : props.headerHeight,
26
27
  }), [
27
28
  props === null || props === void 0 ? void 0 : props.accessKey,
28
29
  props === null || props === void 0 ? void 0 : props.secretKey,
@@ -35,6 +36,7 @@ function App(props) {
35
36
  props === null || props === void 0 ? void 0 : props.id,
36
37
  props === null || props === void 0 ? void 0 : props.parentId,
37
38
  props === null || props === void 0 ? void 0 : props.showSubfolders,
39
+ props === null || props === void 0 ? void 0 : props.headerHeight,
38
40
  ]);
39
41
  const [folders, setFolders] = useState([]);
40
42
  if (typeof window !== "undefined" && !window.process) {
@@ -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 {};
@@ -19,7 +19,7 @@ import { SUBSCRIPTION_EXPIRED_ERROR_MESSAGE } from "./appConstants";
19
19
  const DamConfigContext = createContext(null);
20
20
  export const DamConfigProvider = ({ children, config }) => {
21
21
  // console.log(config);
22
- const { damAccessKey, secretKey, subdomain, teamIds, appType, initialRootFolderId } = config;
22
+ const { damAccessKey, secretKey, subdomain, teamIds, appType, initialRootFolderId, headerHeight } = config;
23
23
  const [accessToken, setAccessToken] = useState(null);
24
24
  const [user, setDamUser] = useState(null);
25
25
  const [brand, setBrand] = useState(null);
@@ -148,6 +148,7 @@ export const DamConfigProvider = ({ children, config }) => {
148
148
  rootFolderId,
149
149
  teams,
150
150
  isAdmin,
151
+ headerHeight: headerHeight !== null && headerHeight !== void 0 ? headerHeight : 0,
151
152
  }, children: loading ? (_jsx(Loader, {})) : (_jsx(_Fragment, { children: showPaymentErr ? (_jsx("div", { className: "flex items-center justify-center h-[calc(100vh-200px)]", children: _jsx("p", { className: "text-sm font-medium text-textColor dark:text-darkTextColor", children: SUBSCRIPTION_EXPIRED_ERROR_MESSAGE }) })) : (children) })) }));
152
153
  };
153
154
  export const useDamConfig = () => useContext(DamConfigContext);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anji-dashing/dam-solution-v2",
3
- "version": "5.8.175",
3
+ "version": "5.8.177",
4
4
  "dependencies": {
5
5
  "@ant-design/icons": "^5.0.1",
6
6
  "@emoji-mart/data": "^1.2.1",