box-ui-elements 24.0.0-beta.4 → 24.0.0-beta.5

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 (98) hide show
  1. package/dist/explorer.js +1 -1
  2. package/dist/openwith.js +1 -1
  3. package/dist/picker.js +1 -1
  4. package/dist/preview.js +1 -1
  5. package/dist/sharing.js +1 -1
  6. package/dist/sidebar.js +1 -1
  7. package/dist/uploader.js +1 -1
  8. package/es/api/Metadata.js +98 -13
  9. package/es/api/Metadata.js.flow +110 -12
  10. package/es/api/Metadata.js.map +1 -1
  11. package/es/elements/common/messages.js +16 -0
  12. package/es/elements/common/messages.js.flow +25 -0
  13. package/es/elements/common/messages.js.map +1 -1
  14. package/es/elements/content-explorer/Content.js +2 -1
  15. package/es/elements/content-explorer/Content.js.map +1 -1
  16. package/es/elements/content-explorer/ContentExplorer.js +19 -5
  17. package/es/elements/content-explorer/ContentExplorer.js.map +1 -1
  18. package/es/elements/content-explorer/MetadataQueryAPIHelper.js +61 -4
  19. package/es/elements/content-explorer/MetadataQueryAPIHelper.js.map +1 -1
  20. package/es/elements/content-explorer/MetadataSidePanel.js +40 -14
  21. package/es/elements/content-explorer/MetadataSidePanel.js.map +1 -1
  22. package/es/elements/content-explorer/MetadataViewContainer.js +55 -4
  23. package/es/elements/content-explorer/MetadataViewContainer.js.map +1 -1
  24. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +61 -13
  25. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
  26. package/es/elements/content-explorer/utils.js +140 -12
  27. package/es/elements/content-explorer/utils.js.map +1 -1
  28. package/es/src/elements/content-explorer/ContentExplorer.d.ts +11 -3
  29. package/es/src/elements/content-explorer/MetadataQueryAPIHelper.d.ts +11 -1
  30. package/es/src/elements/content-explorer/MetadataSidePanel.d.ts +6 -3
  31. package/es/src/elements/content-explorer/MetadataViewContainer.d.ts +3 -1
  32. package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +1 -0
  33. package/es/src/elements/content-explorer/utils.d.ts +9 -3
  34. package/i18n/bn-IN.js +4 -0
  35. package/i18n/bn-IN.properties +4 -0
  36. package/i18n/da-DK.js +4 -0
  37. package/i18n/da-DK.properties +4 -0
  38. package/i18n/de-DE.js +5 -1
  39. package/i18n/de-DE.properties +4 -0
  40. package/i18n/en-AU.js +4 -0
  41. package/i18n/en-AU.properties +4 -0
  42. package/i18n/en-CA.js +4 -0
  43. package/i18n/en-CA.properties +4 -0
  44. package/i18n/en-GB.js +4 -0
  45. package/i18n/en-GB.properties +4 -0
  46. package/i18n/en-US.js +4 -0
  47. package/i18n/en-US.properties +8 -0
  48. package/i18n/en-x-pseudo.js +4 -0
  49. package/i18n/es-419.js +5 -1
  50. package/i18n/es-419.properties +4 -0
  51. package/i18n/es-ES.js +5 -1
  52. package/i18n/es-ES.properties +4 -0
  53. package/i18n/fi-FI.js +4 -0
  54. package/i18n/fi-FI.properties +4 -0
  55. package/i18n/fr-CA.js +4 -0
  56. package/i18n/fr-CA.properties +4 -0
  57. package/i18n/fr-FR.js +4 -0
  58. package/i18n/fr-FR.properties +4 -0
  59. package/i18n/hi-IN.js +4 -0
  60. package/i18n/hi-IN.properties +4 -0
  61. package/i18n/it-IT.js +4 -0
  62. package/i18n/it-IT.properties +4 -0
  63. package/i18n/ja-JP.js +6 -2
  64. package/i18n/ja-JP.properties +6 -2
  65. package/i18n/ko-KR.js +4 -0
  66. package/i18n/ko-KR.properties +4 -0
  67. package/i18n/nb-NO.js +4 -0
  68. package/i18n/nb-NO.properties +4 -0
  69. package/i18n/nl-NL.js +4 -0
  70. package/i18n/nl-NL.properties +4 -0
  71. package/i18n/pl-PL.js +4 -0
  72. package/i18n/pl-PL.properties +4 -0
  73. package/i18n/pt-BR.js +4 -0
  74. package/i18n/pt-BR.properties +4 -0
  75. package/i18n/ru-RU.js +5 -1
  76. package/i18n/ru-RU.properties +4 -0
  77. package/i18n/sv-SE.js +4 -0
  78. package/i18n/sv-SE.properties +4 -0
  79. package/i18n/tr-TR.js +5 -1
  80. package/i18n/tr-TR.properties +4 -0
  81. package/i18n/zh-CN.js +4 -0
  82. package/i18n/zh-CN.properties +4 -0
  83. package/i18n/zh-TW.js +4 -0
  84. package/i18n/zh-TW.properties +4 -0
  85. package/package.json +1 -1
  86. package/src/api/Metadata.js +110 -12
  87. package/src/api/__tests__/Metadata.test.js +120 -0
  88. package/src/elements/common/messages.js +25 -0
  89. package/src/elements/content-explorer/Content.tsx +1 -0
  90. package/src/elements/content-explorer/ContentExplorer.tsx +220 -181
  91. package/src/elements/content-explorer/MetadataQueryAPIHelper.ts +89 -4
  92. package/src/elements/content-explorer/MetadataSidePanel.tsx +55 -14
  93. package/src/elements/content-explorer/MetadataViewContainer.tsx +61 -1
  94. package/src/elements/content-explorer/__tests__/ContentExplorer.test.tsx +36 -2
  95. package/src/elements/content-explorer/__tests__/MetadataQueryAPIHelper.test.ts +8 -5
  96. package/src/elements/content-explorer/__tests__/MetadataSidePanel.test.tsx +145 -3
  97. package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +54 -8
  98. package/src/elements/content-explorer/utils.ts +150 -13
@@ -6,18 +6,22 @@ import find from 'lodash/find';
6
6
  import getProp from 'lodash/get';
7
7
  import includes from 'lodash/includes';
8
8
  import isArray from 'lodash/isArray';
9
- import isNil from 'lodash/isNil';
9
+ import { areFieldValuesEqual, isEmptyValue, isMultiValuesField } from './utils';
10
10
  import { JSON_PATCH_OP_ADD, JSON_PATCH_OP_REMOVE, JSON_PATCH_OP_REPLACE, JSON_PATCH_OP_TEST, METADATA_FIELD_TYPE_ENUM, METADATA_FIELD_TYPE_MULTISELECT } from '../../common/constants';
11
- import { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION } from '../../constants';
11
+ import { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION, FIELD_PERMISSIONS } from '../../constants';
12
12
  const SELECT_TYPES = [METADATA_FIELD_TYPE_ENUM, METADATA_FIELD_TYPE_MULTISELECT];
13
13
  export default class MetadataQueryAPIHelper {
14
14
  constructor(api) {
15
15
  _defineProperty(this, "createJSONPatchOperations", (field, oldValue, newValue) => {
16
+ // check if two values are the same, return empty operations if so
17
+ if (areFieldValuesEqual(oldValue, newValue)) {
18
+ return [];
19
+ }
16
20
  let operation = JSON_PATCH_OP_REPLACE;
17
- if (isNil(oldValue) && newValue) {
21
+ if (isEmptyValue(oldValue) && !isEmptyValue(newValue)) {
18
22
  operation = JSON_PATCH_OP_ADD;
19
23
  }
20
- if (oldValue && isNil(newValue)) {
24
+ if (!isEmptyValue(oldValue) && isEmptyValue(newValue)) {
21
25
  operation = JSON_PATCH_OP_REMOVE;
22
26
  }
23
27
  const testOp = {
@@ -113,6 +117,43 @@ export default class MetadataQueryAPIHelper {
113
117
  this.templateKey = Object.keys(instance)[0];
114
118
  return this.api.getMetadataAPI(true).getSchemaByTemplateKey(this.templateKey);
115
119
  });
120
+ /**
121
+ * Generate operations for all fields update in the metadata sidepanel
122
+ *
123
+ * @private
124
+ * @return {JSONPatchOperations}
125
+ */
126
+ _defineProperty(this, "generateOperations", (item, templateOldFields, templateNewFields) => {
127
+ const {
128
+ scope,
129
+ templateKey
130
+ } = this.metadataTemplate;
131
+ const itemFields = item.metadata[scope][templateKey];
132
+ const operations = templateNewFields.flatMap(newField => {
133
+ let newFieldValue = newField.value;
134
+ const {
135
+ key,
136
+ type
137
+ } = newField;
138
+ // when retrieve value from float type field, it gives a string instead
139
+ if (type === 'float' && newFieldValue !== '') {
140
+ newFieldValue = Number(newFieldValue);
141
+ }
142
+ const oldField = templateOldFields.find(f => f.key === key);
143
+ const oldFieldValue = oldField.value;
144
+
145
+ /*
146
+ Generate operations array based on all the fields' orignal value and the incoming updated value.
147
+ Edge Case:
148
+ If there are multiple items shared different value for enum or multi-select field, the form will
149
+ return 'Multiple values' as the value. In this case, it needs to generate operation based on the
150
+ actual item's field value.
151
+ */
152
+ const shouldUseItemFieldValue = isMultiValuesField(type, oldFieldValue) && !isMultiValuesField(type, newFieldValue);
153
+ return this.createJSONPatchOperations(key, shouldUseItemFieldValue ? itemFields[key] : oldFieldValue, newFieldValue);
154
+ });
155
+ return operations;
156
+ });
116
157
  _defineProperty(this, "queryMetadata", () => {
117
158
  return new Promise((resolve, reject) => {
118
159
  this.api.getMetadataQueryAPI().queryMetadata(this.metadataQuery, resolve, reject, {
@@ -130,6 +171,17 @@ export default class MetadataQueryAPIHelper {
130
171
  const operations = this.createJSONPatchOperations(field, oldValue, newValue);
131
172
  return this.api.getMetadataAPI(true).updateMetadata(file, this.metadataTemplate, operations, successCallback, errorCallback);
132
173
  });
174
+ _defineProperty(this, "updateMetadataWithOperations", (item, operations, successCallback, errorCallback) => {
175
+ return this.api.getMetadataAPI(true).updateMetadata(item, this.metadataTemplate, operations, successCallback, errorCallback);
176
+ });
177
+ _defineProperty(this, "bulkUpdateMetadata", (items, templateOldFields, templateNewFields, successCallback, errorCallback) => {
178
+ const operations = [];
179
+ items.forEach(item => {
180
+ const operation = this.generateOperations(item, templateOldFields, templateNewFields);
181
+ operations.push(operation);
182
+ });
183
+ return this.api.getMetadataAPI(true).bulkUpdateMetadata(items, this.metadataTemplate, operations, successCallback, errorCallback);
184
+ });
133
185
  /**
134
186
  * Verify that the metadata query has required fields and update it if necessary
135
187
  * For a file item, default fields included in the response are "type", "id", "etag"
@@ -148,6 +200,11 @@ export default class MetadataQueryAPIHelper {
148
200
  if (!clonedFields.includes(FIELD_EXTENSION)) {
149
201
  clonedFields.push(FIELD_EXTENSION);
150
202
  }
203
+
204
+ // This field is necessary to check if the user has permission to update metadata
205
+ if (!clonedFields.includes(FIELD_PERMISSIONS)) {
206
+ clonedFields.push(FIELD_PERMISSIONS);
207
+ }
151
208
  clonedQuery.fields = clonedFields;
152
209
  return clonedQuery;
153
210
  });
@@ -1 +1 @@
1
- {"version":3,"file":"MetadataQueryAPIHelper.js","names":["cloneDeep","find","getProp","includes","isArray","isNil","JSON_PATCH_OP_ADD","JSON_PATCH_OP_REMOVE","JSON_PATCH_OP_REPLACE","JSON_PATCH_OP_TEST","METADATA_FIELD_TYPE_ENUM","METADATA_FIELD_TYPE_MULTISELECT","FIELD_NAME","FIELD_METADATA","FIELD_EXTENSION","SELECT_TYPES","MetadataQueryAPIHelper","constructor","api","_defineProperty","field","oldValue","newValue","operation","testOp","op","path","value","patchOp","fields","from","metadataQuery","filter","map","split","pop","metadata","templateFields","metadataTemplate","instance","templateScope","templateKey","queryFields","getMetadataQueryFields","queryField","templateField","type","displayName","key","options","enterprise","id","$id","templateSchemaResponse","entries","items","next_marker","nextMarker","metadataQueryResponseData","data","length","Promise","resolve","Object","keys","getMetadataAPI","getSchemaByTemplateKey","reject","getMetadataQueryAPI","queryMetadata","forceFetch","successCallback","errorCallback","verifyQueryFields","then","getTemplateSchemaInfo","getDataWithTypes","collection","catch","file","operations","createJSONPatchOperations","updateMetadata","clonedQuery","clonedFields","push"],"sources":["../../../src/elements/content-explorer/MetadataQueryAPIHelper.ts"],"sourcesContent":["import cloneDeep from 'lodash/cloneDeep';\nimport find from 'lodash/find';\nimport getProp from 'lodash/get';\nimport includes from 'lodash/includes';\nimport isArray from 'lodash/isArray';\nimport isNil from 'lodash/isNil';\nimport API from '../../api';\n\nimport {\n JSON_PATCH_OP_ADD,\n JSON_PATCH_OP_REMOVE,\n JSON_PATCH_OP_REPLACE,\n JSON_PATCH_OP_TEST,\n METADATA_FIELD_TYPE_ENUM,\n METADATA_FIELD_TYPE_MULTISELECT,\n} from '../../common/constants';\nimport { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION } from '../../constants';\n\nimport type { MetadataQuery as MetadataQueryType, MetadataQueryResponseData } from '../../common/types/metadataQueries';\nimport type {\n MetadataTemplateSchemaResponse,\n MetadataTemplate,\n MetadataFieldValue,\n MetadataType,\n MetadataQueryInstanceTypeField,\n} from '../../common/types/metadata';\nimport type { ElementsXhrError, JSONPatchOperations } from '../../common/types/api';\nimport type { Collection, BoxItem } from '../../common/types/core';\n\ntype SuccessCallback = (metadataQueryCollection: Collection, metadataTemplate: MetadataTemplate) => void;\ntype ErrorCallback = (e: ElementsXhrError) => void;\n\nconst SELECT_TYPES: Array<typeof METADATA_FIELD_TYPE_ENUM | typeof METADATA_FIELD_TYPE_MULTISELECT> = [\n METADATA_FIELD_TYPE_ENUM,\n METADATA_FIELD_TYPE_MULTISELECT,\n];\n\nexport default class MetadataQueryAPIHelper {\n api: API;\n\n metadataQueryResponseData: MetadataQueryResponseData;\n\n metadataTemplate: MetadataTemplate;\n\n templateKey: string;\n\n templateScope: string;\n\n metadataQuery: MetadataQueryType;\n\n constructor(api: API) {\n this.api = api;\n }\n\n createJSONPatchOperations = (\n field: string,\n oldValue: MetadataFieldValue | null,\n newValue: MetadataFieldValue | null,\n ): JSONPatchOperations => {\n let operation = JSON_PATCH_OP_REPLACE;\n\n if (isNil(oldValue) && newValue) {\n operation = JSON_PATCH_OP_ADD;\n }\n\n if (oldValue && isNil(newValue)) {\n operation = JSON_PATCH_OP_REMOVE;\n }\n\n const testOp = {\n op: JSON_PATCH_OP_TEST,\n path: `/${field}`,\n value: oldValue,\n };\n const patchOp = {\n op: operation,\n path: `/${field}`,\n value: newValue,\n };\n\n if (operation === JSON_PATCH_OP_REMOVE) {\n delete patchOp.value;\n }\n\n return operation === JSON_PATCH_OP_ADD ? [patchOp] : [testOp, patchOp];\n };\n\n getMetadataQueryFields = (): string[] => {\n /*\n Example metadata query:\n const query = {\n from: 'enterprise_12345.myAwesomeTemplateKey',\n fields: [\n 'name', // base representation field for an item (name, size, etag etc.)\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_1', // metadata instance field\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_2', // metadata instance field\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_3' // metadata instance field\n ],\n ancestor_folder_id: 0,\n };\n\n This function will return ['field_1', 'field_2', 'field_3']\n */\n const { fields = [], from } = this.metadataQuery;\n return fields.filter(field => field.includes(from)).map(field => field.split('.').pop());\n };\n\n flattenMetadata = (metadata?: MetadataType): MetadataType => {\n const templateFields = getProp(this.metadataTemplate, 'fields', []);\n const instance = getProp(metadata, `${this.templateScope}.${this.templateKey}`);\n\n if (!instance) {\n return {};\n }\n\n const queryFields = this.getMetadataQueryFields();\n\n const fields = queryFields.map((queryField: string) => {\n const templateField = find(templateFields, ['key', queryField]);\n const type = getProp(templateField, 'type'); // get data type\n const displayName = getProp(templateField, 'displayName', queryField); // get displayName, defaults to key\n\n const field: MetadataQueryInstanceTypeField = {\n key: `${FIELD_METADATA}.${this.templateScope}.${this.templateKey}.${queryField}`,\n value: instance[queryField],\n type,\n displayName,\n };\n\n if (includes(SELECT_TYPES, type)) {\n // get \"options\" for enums or multiselects\n field.options = getProp(templateField, 'options');\n }\n\n return field;\n });\n\n return {\n enterprise: {\n fields,\n id: instance.$id,\n },\n };\n };\n\n getDataWithTypes = (templateSchemaResponse?: MetadataTemplateSchemaResponse): Collection => {\n this.metadataTemplate = getProp(templateSchemaResponse, 'data');\n\n const { entries: items, next_marker: nextMarker }: MetadataQueryResponseData = this.metadataQueryResponseData;\n\n return {\n items,\n nextMarker,\n };\n };\n\n getTemplateSchemaInfo = (data: MetadataQueryResponseData): Promise<MetadataTemplateSchemaResponse | void> => {\n const { entries } = data;\n this.metadataQueryResponseData = data;\n if (!entries || entries.length === 0) {\n // Don't make metadata API call to get template info\n return Promise.resolve();\n }\n\n const metadata = getProp(entries, '[0].metadata');\n this.templateScope = Object.keys(metadata)[0];\n const instance = metadata[this.templateScope];\n this.templateKey = Object.keys(instance)[0];\n\n return this.api.getMetadataAPI(true).getSchemaByTemplateKey(this.templateKey);\n };\n\n queryMetadata = (): Promise<MetadataQueryResponseData> => {\n return new Promise((resolve, reject) => {\n this.api.getMetadataQueryAPI().queryMetadata(this.metadataQuery, resolve, reject, { forceFetch: true });\n });\n };\n\n fetchMetadataQueryResults = (\n metadataQuery: MetadataQueryType,\n successCallback: SuccessCallback,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n this.metadataQuery = this.verifyQueryFields(metadataQuery);\n return this.queryMetadata()\n .then(this.getTemplateSchemaInfo)\n .then(this.getDataWithTypes)\n .then((collection: Collection) => {\n return successCallback(collection, this.metadataTemplate);\n })\n .catch(errorCallback);\n };\n\n updateMetadata = (\n file: BoxItem,\n field: string,\n oldValue: MetadataFieldValue | null,\n newValue: MetadataFieldValue | null,\n successCallback: () => void,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n const operations = this.createJSONPatchOperations(field, oldValue, newValue);\n return this.api\n .getMetadataAPI(true)\n .updateMetadata(file, this.metadataTemplate, operations, successCallback, errorCallback);\n };\n\n /**\n * Verify that the metadata query has required fields and update it if necessary\n * For a file item, default fields included in the response are \"type\", \"id\", \"etag\"\n *\n * @param {MetadataQueryType} metadataQuery metadata query object\n * @return {MetadataQueryType} updated metadata query object with required fields\n */\n verifyQueryFields = (metadataQuery: MetadataQueryType): MetadataQueryType => {\n const clonedQuery = cloneDeep(metadataQuery);\n const clonedFields = isArray(clonedQuery.fields) ? clonedQuery.fields : [];\n\n // Make sure the query fields array has \"name\" field which is necessary to display info.\n if (!clonedFields.includes(FIELD_NAME)) {\n clonedFields.push(FIELD_NAME);\n }\n\n if (!clonedFields.includes(FIELD_EXTENSION)) {\n clonedFields.push(FIELD_EXTENSION);\n }\n\n clonedQuery.fields = clonedFields;\n\n return clonedQuery;\n };\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MetadataQueryAPIHelper.js","names":["cloneDeep","find","getProp","includes","isArray","areFieldValuesEqual","isEmptyValue","isMultiValuesField","JSON_PATCH_OP_ADD","JSON_PATCH_OP_REMOVE","JSON_PATCH_OP_REPLACE","JSON_PATCH_OP_TEST","METADATA_FIELD_TYPE_ENUM","METADATA_FIELD_TYPE_MULTISELECT","FIELD_NAME","FIELD_METADATA","FIELD_EXTENSION","FIELD_PERMISSIONS","SELECT_TYPES","MetadataQueryAPIHelper","constructor","api","_defineProperty","field","oldValue","newValue","operation","testOp","op","path","value","patchOp","fields","from","metadataQuery","filter","map","split","pop","metadata","templateFields","metadataTemplate","instance","templateScope","templateKey","queryFields","getMetadataQueryFields","queryField","templateField","type","displayName","key","options","enterprise","id","$id","templateSchemaResponse","entries","items","next_marker","nextMarker","metadataQueryResponseData","data","length","Promise","resolve","Object","keys","getMetadataAPI","getSchemaByTemplateKey","item","templateOldFields","templateNewFields","scope","itemFields","operations","flatMap","newField","newFieldValue","Number","oldField","f","oldFieldValue","shouldUseItemFieldValue","createJSONPatchOperations","reject","getMetadataQueryAPI","queryMetadata","forceFetch","successCallback","errorCallback","verifyQueryFields","then","getTemplateSchemaInfo","getDataWithTypes","collection","catch","file","updateMetadata","forEach","generateOperations","push","bulkUpdateMetadata","clonedQuery","clonedFields"],"sources":["../../../src/elements/content-explorer/MetadataQueryAPIHelper.ts"],"sourcesContent":["import cloneDeep from 'lodash/cloneDeep';\nimport find from 'lodash/find';\nimport getProp from 'lodash/get';\nimport includes from 'lodash/includes';\nimport isArray from 'lodash/isArray';\nimport type { MetadataTemplateField } from '@box/metadata-editor';\nimport type { MetadataFieldType } from '@box/metadata-view';\nimport API from '../../api';\nimport { areFieldValuesEqual, isEmptyValue, isMultiValuesField } from './utils';\n\nimport {\n JSON_PATCH_OP_ADD,\n JSON_PATCH_OP_REMOVE,\n JSON_PATCH_OP_REPLACE,\n JSON_PATCH_OP_TEST,\n METADATA_FIELD_TYPE_ENUM,\n METADATA_FIELD_TYPE_MULTISELECT,\n} from '../../common/constants';\nimport { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION, FIELD_PERMISSIONS } from '../../constants';\n\nimport type { MetadataQuery as MetadataQueryType, MetadataQueryResponseData } from '../../common/types/metadataQueries';\nimport type {\n MetadataTemplateSchemaResponse,\n MetadataTemplate,\n MetadataFieldValue,\n MetadataType,\n MetadataQueryInstanceTypeField,\n} from '../../common/types/metadata';\nimport type { ElementsXhrError, JSONPatchOperations } from '../../common/types/api';\nimport type { Collection, BoxItem } from '../../common/types/core';\n\ntype SuccessCallback = (metadataQueryCollection: Collection, metadataTemplate: MetadataTemplate) => void;\ntype ErrorCallback = (e: ElementsXhrError) => void;\n\nconst SELECT_TYPES: Array<typeof METADATA_FIELD_TYPE_ENUM | typeof METADATA_FIELD_TYPE_MULTISELECT> = [\n METADATA_FIELD_TYPE_ENUM,\n METADATA_FIELD_TYPE_MULTISELECT,\n];\n\nexport default class MetadataQueryAPIHelper {\n api: API;\n\n metadataQueryResponseData: MetadataQueryResponseData;\n\n metadataTemplate: MetadataTemplate;\n\n templateKey: string;\n\n templateScope: string;\n\n metadataQuery: MetadataQueryType;\n\n constructor(api: API) {\n this.api = api;\n }\n\n createJSONPatchOperations = (\n field: string,\n oldValue: MetadataFieldValue | null,\n newValue: MetadataFieldValue | null,\n ): JSONPatchOperations => {\n // check if two values are the same, return empty operations if so\n if (areFieldValuesEqual(oldValue, newValue)) {\n return [];\n }\n\n let operation = JSON_PATCH_OP_REPLACE;\n\n if (isEmptyValue(oldValue) && !isEmptyValue(newValue)) {\n operation = JSON_PATCH_OP_ADD;\n }\n\n if (!isEmptyValue(oldValue) && isEmptyValue(newValue)) {\n operation = JSON_PATCH_OP_REMOVE;\n }\n\n const testOp = {\n op: JSON_PATCH_OP_TEST,\n path: `/${field}`,\n value: oldValue,\n };\n const patchOp = {\n op: operation,\n path: `/${field}`,\n value: newValue,\n };\n\n if (operation === JSON_PATCH_OP_REMOVE) {\n delete patchOp.value;\n }\n\n return operation === JSON_PATCH_OP_ADD ? [patchOp] : [testOp, patchOp];\n };\n\n getMetadataQueryFields = (): string[] => {\n /*\n Example metadata query:\n const query = {\n from: 'enterprise_12345.myAwesomeTemplateKey',\n fields: [\n 'name', // base representation field for an item (name, size, etag etc.)\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_1', // metadata instance field\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_2', // metadata instance field\n 'metadata.enterprise_12345.myAwesomeTemplateKey.field_3' // metadata instance field\n ],\n ancestor_folder_id: 0,\n };\n\n This function will return ['field_1', 'field_2', 'field_3']\n */\n const { fields = [], from } = this.metadataQuery;\n return fields.filter(field => field.includes(from)).map(field => field.split('.').pop());\n };\n\n flattenMetadata = (metadata?: MetadataType): MetadataType => {\n const templateFields = getProp(this.metadataTemplate, 'fields', []);\n const instance = getProp(metadata, `${this.templateScope}.${this.templateKey}`);\n\n if (!instance) {\n return {};\n }\n\n const queryFields = this.getMetadataQueryFields();\n\n const fields = queryFields.map((queryField: string) => {\n const templateField = find(templateFields, ['key', queryField]);\n const type = getProp(templateField, 'type'); // get data type\n const displayName = getProp(templateField, 'displayName', queryField); // get displayName, defaults to key\n\n const field: MetadataQueryInstanceTypeField = {\n key: `${FIELD_METADATA}.${this.templateScope}.${this.templateKey}.${queryField}`,\n value: instance[queryField],\n type,\n displayName,\n };\n\n if (includes(SELECT_TYPES, type)) {\n // get \"options\" for enums or multiselects\n field.options = getProp(templateField, 'options');\n }\n\n return field;\n });\n\n return {\n enterprise: {\n fields,\n id: instance.$id,\n },\n };\n };\n\n getDataWithTypes = (templateSchemaResponse?: MetadataTemplateSchemaResponse): Collection => {\n this.metadataTemplate = getProp(templateSchemaResponse, 'data');\n\n const { entries: items, next_marker: nextMarker }: MetadataQueryResponseData = this.metadataQueryResponseData;\n\n return {\n items,\n nextMarker,\n };\n };\n\n getTemplateSchemaInfo = (data: MetadataQueryResponseData): Promise<MetadataTemplateSchemaResponse | void> => {\n const { entries } = data;\n this.metadataQueryResponseData = data;\n if (!entries || entries.length === 0) {\n // Don't make metadata API call to get template info\n return Promise.resolve();\n }\n\n const metadata = getProp(entries, '[0].metadata');\n this.templateScope = Object.keys(metadata)[0];\n const instance = metadata[this.templateScope];\n this.templateKey = Object.keys(instance)[0];\n\n return this.api.getMetadataAPI(true).getSchemaByTemplateKey(this.templateKey);\n };\n\n /**\n * Generate operations for all fields update in the metadata sidepanel\n *\n * @private\n * @return {JSONPatchOperations}\n */\n generateOperations = (\n item: BoxItem,\n templateOldFields: MetadataTemplateField[],\n templateNewFields: MetadataTemplateField[],\n ): JSONPatchOperations => {\n const { scope, templateKey } = this.metadataTemplate;\n const itemFields = item.metadata[scope][templateKey];\n const operations = templateNewFields.flatMap(newField => {\n let newFieldValue = newField.value;\n const { key, type } = newField;\n // when retrieve value from float type field, it gives a string instead\n if (type === 'float' && newFieldValue !== '') {\n newFieldValue = Number(newFieldValue);\n }\n const oldField = templateOldFields.find(f => f.key === key);\n const oldFieldValue = oldField.value;\n\n /*\n Generate operations array based on all the fields' orignal value and the incoming updated value.\n\n Edge Case:\n If there are multiple items shared different value for enum or multi-select field, the form will\n return 'Multiple values' as the value. In this case, it needs to generate operation based on the\n actual item's field value.\n */\n const shouldUseItemFieldValue =\n isMultiValuesField(type as MetadataFieldType, oldFieldValue) &&\n !isMultiValuesField(type as MetadataFieldType, newFieldValue);\n\n return this.createJSONPatchOperations(\n key,\n shouldUseItemFieldValue ? itemFields[key] : oldFieldValue,\n newFieldValue,\n );\n });\n\n return operations;\n };\n\n queryMetadata = (): Promise<MetadataQueryResponseData> => {\n return new Promise((resolve, reject) => {\n this.api.getMetadataQueryAPI().queryMetadata(this.metadataQuery, resolve, reject, { forceFetch: true });\n });\n };\n\n fetchMetadataQueryResults = (\n metadataQuery: MetadataQueryType,\n successCallback: SuccessCallback,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n this.metadataQuery = this.verifyQueryFields(metadataQuery);\n return this.queryMetadata()\n .then(this.getTemplateSchemaInfo)\n .then(this.getDataWithTypes)\n .then((collection: Collection) => {\n return successCallback(collection, this.metadataTemplate);\n })\n .catch(errorCallback);\n };\n\n updateMetadata = (\n file: BoxItem,\n field: string,\n oldValue: MetadataFieldValue | null,\n newValue: MetadataFieldValue | null,\n successCallback: () => void,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n const operations = this.createJSONPatchOperations(field, oldValue, newValue);\n return this.api\n .getMetadataAPI(true)\n .updateMetadata(file, this.metadataTemplate, operations, successCallback, errorCallback);\n };\n\n updateMetadataWithOperations = (\n item: BoxItem,\n operations: JSONPatchOperations,\n successCallback: () => void,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n return this.api\n .getMetadataAPI(true)\n .updateMetadata(item, this.metadataTemplate, operations, successCallback, errorCallback);\n };\n\n bulkUpdateMetadata = (\n items: BoxItem[],\n templateOldFields: MetadataTemplateField[],\n templateNewFields: MetadataTemplateField[],\n successCallback: () => void,\n errorCallback: ErrorCallback,\n ): Promise<void> => {\n const operations: JSONPatchOperations = [];\n items.forEach(item => {\n const operation = this.generateOperations(item, templateOldFields, templateNewFields);\n operations.push(operation);\n });\n return this.api\n .getMetadataAPI(true)\n .bulkUpdateMetadata(items, this.metadataTemplate, operations, successCallback, errorCallback);\n };\n\n /**\n * Verify that the metadata query has required fields and update it if necessary\n * For a file item, default fields included in the response are \"type\", \"id\", \"etag\"\n *\n * @param {MetadataQueryType} metadataQuery metadata query object\n * @return {MetadataQueryType} updated metadata query object with required fields\n */\n verifyQueryFields = (metadataQuery: MetadataQueryType): MetadataQueryType => {\n const clonedQuery = cloneDeep(metadataQuery);\n const clonedFields = isArray(clonedQuery.fields) ? clonedQuery.fields : [];\n\n // Make sure the query fields array has \"name\" field which is necessary to display info.\n if (!clonedFields.includes(FIELD_NAME)) {\n clonedFields.push(FIELD_NAME);\n }\n\n if (!clonedFields.includes(FIELD_EXTENSION)) {\n clonedFields.push(FIELD_EXTENSION);\n }\n\n // This field is necessary to check if the user has permission to update metadata\n if (!clonedFields.includes(FIELD_PERMISSIONS)) {\n clonedFields.push(FIELD_PERMISSIONS);\n }\n\n clonedQuery.fields = clonedFields;\n\n return clonedQuery;\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,18 +1,23 @@
1
1
  import React, { useState } from 'react';
2
2
  import { useIntl } from 'react-intl';
3
- import { IconButton, SidePanel, Text } from '@box/blueprint-web';
3
+ import { IconButton, SidePanel, Text, useNotification } from '@box/blueprint-web';
4
4
  import { XMark } from '@box/blueprint-web-assets/icons/Fill/index';
5
5
  import { FileDefault } from '@box/blueprint-web-assets/icons/Line/index';
6
6
  import { AutofillContextProvider, MetadataInstance, MetadataInstanceForm } from '@box/metadata-editor';
7
- import { getTemplateInstance, useSelectedItemText } from './utils';
7
+ import { useTemplateInstance, useSelectedItemText } from './utils';
8
8
  import messages from '../common/messages';
9
9
  import './MetadataSidePanel.scss';
10
10
  const MetadataSidePanel = ({
11
11
  currentCollection,
12
+ metadataTemplate,
12
13
  onClose,
13
- selectedItemIds,
14
- metadataTemplate
14
+ onUpdate,
15
+ refreshCollection,
16
+ selectedItemIds
15
17
  }) => {
18
+ const {
19
+ addNotification
20
+ } = useNotification();
16
21
  const {
17
22
  formatMessage
18
23
  } = useIntl();
@@ -20,26 +25,47 @@ const MetadataSidePanel = ({
20
25
  const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState(false);
21
26
  const selectedItemText = useSelectedItemText(currentCollection, selectedItemIds);
22
27
  const selectedItems = selectedItemIds === 'all' ? currentCollection.items : currentCollection.items.filter(item => selectedItemIds.has(item.id));
23
- const templateInstance = getTemplateInstance(metadataTemplate, selectedItems);
28
+ const templateInstance = useTemplateInstance(metadataTemplate, selectedItems, isEditing);
24
29
  const handleMetadataInstanceEdit = () => {
25
30
  setIsEditing(true);
26
31
  };
27
32
  const handleMetadataInstanceFormCancel = () => {
28
33
  setIsEditing(false);
29
34
  };
30
-
31
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
32
- const handleMetadataInstanceFormChange = values => {
33
- // TODO: Implement on form change
34
- };
35
35
  const handleMetadataInstanceFormDiscardUnsavedChanges = () => {
36
36
  setIsUnsavedChangesModalOpen(false);
37
37
  setIsEditing(false);
38
38
  };
39
-
40
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
39
+ const handleUpdateMetadataSuccess = () => {
40
+ addNotification({
41
+ closeButtonAriaLabel: formatMessage(messages.close),
42
+ sensitivity: 'foreground',
43
+ styledText: formatMessage(messages.metadataUpdateSuccessNotification, {
44
+ numSelected: selectedItems.length
45
+ }),
46
+ typeIconAriaLabel: formatMessage(messages.success),
47
+ variant: 'success'
48
+ });
49
+ setIsEditing(false);
50
+ refreshCollection();
51
+ };
52
+ const handleUpdateMetadataError = () => {
53
+ addNotification({
54
+ closeButtonAriaLabel: formatMessage(messages.close),
55
+ sensitivity: 'foreground',
56
+ styledText: formatMessage(messages.metadataUpdateErrorNotification),
57
+ typeIconAriaLabel: formatMessage(messages.error),
58
+ variant: 'error'
59
+ });
60
+ };
41
61
  const handleMetadataInstanceFormSubmit = async (values, operations) => {
42
- // TODO: Implement onSave callback
62
+ const {
63
+ fields: templateNewFields
64
+ } = values.metadata;
65
+ const {
66
+ fields: templateOldFields
67
+ } = templateInstance;
68
+ await onUpdate(selectedItems, operations, templateOldFields, templateNewFields, handleUpdateMetadataSuccess, handleUpdateMetadataError);
43
69
  };
44
70
  return /*#__PURE__*/React.createElement(SidePanel, {
45
71
  variant: "persistent"
@@ -73,7 +99,7 @@ const MetadataSidePanel = ({
73
99
  isUnsavedChangesModalOpen: isUnsavedChangesModalOpen,
74
100
  selectedTemplateInstance: templateInstance,
75
101
  onCancel: handleMetadataInstanceFormCancel,
76
- onChange: handleMetadataInstanceFormChange,
102
+ onChange: null,
77
103
  onDelete: null,
78
104
  onDiscardUnsavedChanges: handleMetadataInstanceFormDiscardUnsavedChanges,
79
105
  onSubmit: handleMetadataInstanceFormSubmit,
@@ -1 +1 @@
1
- {"version":3,"file":"MetadataSidePanel.js","names":["React","useState","useIntl","IconButton","SidePanel","Text","XMark","FileDefault","AutofillContextProvider","MetadataInstance","MetadataInstanceForm","getTemplateInstance","useSelectedItemText","messages","MetadataSidePanel","currentCollection","onClose","selectedItemIds","metadataTemplate","formatMessage","isEditing","setIsEditing","isUnsavedChangesModalOpen","setIsUnsavedChangesModalOpen","selectedItemText","selectedItems","items","filter","item","has","id","templateInstance","handleMetadataInstanceEdit","handleMetadataInstanceFormCancel","handleMetadataInstanceFormChange","values","handleMetadataInstanceFormDiscardUnsavedChanges","handleMetadataInstanceFormSubmit","operations","createElement","variant","Header","as","sidebarMetadataTitle","className","color","close","icon","onClick","size","ScrollableContainer","fetchSuggestions","isAiSuggestionsFeatureEnabled","areAiSuggestionsAvailable","isBetaLanguageEnabled","isDeleteButtonDisabled","isDeleteConfirmationModalCheckboxEnabled","isLargeFile","isMultilevelTaxonomyFieldEnabled","selectedTemplateInstance","onCancel","onChange","onDelete","onDiscardUnsavedChanges","onSubmit","taxonomyOptionsFetcher","onEdit","taxonomyNodeFetcher"],"sources":["../../../src/elements/content-explorer/MetadataSidePanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { IconButton, SidePanel, Text } from '@box/blueprint-web';\nimport { XMark } from '@box/blueprint-web-assets/icons/Fill/index';\nimport { FileDefault } from '@box/blueprint-web-assets/icons/Line/index';\nimport {\n AutofillContextProvider,\n FormValues,\n JSONPatchOperations,\n MetadataInstance,\n MetadataInstanceForm,\n} from '@box/metadata-editor';\n\nimport type { Selection } from 'react-aria-components';\nimport type { Collection } from '../../common/types/core';\nimport type { MetadataTemplate } from '../../common/types/metadata';\nimport { getTemplateInstance, useSelectedItemText } from './utils';\n\nimport messages from '../common/messages';\n\nimport './MetadataSidePanel.scss';\n\nexport interface MetadataSidePanelProps {\n currentCollection: Collection;\n onClose: () => void;\n metadataTemplate: MetadataTemplate;\n selectedItemIds: Selection;\n}\n\nconst MetadataSidePanel = ({\n currentCollection,\n onClose,\n selectedItemIds,\n metadataTemplate,\n}: MetadataSidePanelProps) => {\n const { formatMessage } = useIntl();\n const [isEditing, setIsEditing] = useState<boolean>(false);\n const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState<boolean>(false);\n\n const selectedItemText = useSelectedItemText(currentCollection, selectedItemIds);\n const selectedItems =\n selectedItemIds === 'all'\n ? currentCollection.items\n : currentCollection.items.filter(item => selectedItemIds.has(item.id));\n const templateInstance = getTemplateInstance(metadataTemplate, selectedItems);\n\n const handleMetadataInstanceEdit = () => {\n setIsEditing(true);\n };\n\n const handleMetadataInstanceFormCancel = () => {\n setIsEditing(false);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const handleMetadataInstanceFormChange = (values: FormValues) => {\n // TODO: Implement on form change\n };\n\n const handleMetadataInstanceFormDiscardUnsavedChanges = () => {\n setIsUnsavedChangesModalOpen(false);\n setIsEditing(false);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const handleMetadataInstanceFormSubmit = async (values: FormValues, operations: JSONPatchOperations) => {\n // TODO: Implement onSave callback\n };\n\n return (\n <SidePanel variant=\"persistent\">\n <SidePanel.Header>\n <div>\n <Text as=\"span\" variant=\"titleLarge\">\n {formatMessage(messages.sidebarMetadataTitle)}\n </Text>\n <div className=\"bce-MetadataSidePanel-subtitle\">\n <FileDefault />\n <Text as=\"span\" color=\"textOnLightSecondary\" variant=\"subtitle\">\n {selectedItemText}\n </Text>\n </div>\n </div>\n <IconButton aria-label={formatMessage(messages.close)} icon={XMark} onClick={onClose} size=\"large\" />\n </SidePanel.Header>\n <SidePanel.ScrollableContainer>\n <div className=\"bce-MetadataSidePanel-content\">\n <AutofillContextProvider fetchSuggestions={null} isAiSuggestionsFeatureEnabled={false}>\n {isEditing ? (\n <MetadataInstanceForm\n areAiSuggestionsAvailable={false}\n isAiSuggestionsFeatureEnabled={false}\n isBetaLanguageEnabled={false}\n isDeleteButtonDisabled={true}\n isDeleteConfirmationModalCheckboxEnabled={false}\n isLargeFile={false}\n isMultilevelTaxonomyFieldEnabled={false}\n isUnsavedChangesModalOpen={isUnsavedChangesModalOpen}\n selectedTemplateInstance={templateInstance}\n onCancel={handleMetadataInstanceFormCancel}\n onChange={handleMetadataInstanceFormChange}\n onDelete={null}\n onDiscardUnsavedChanges={handleMetadataInstanceFormDiscardUnsavedChanges}\n onSubmit={handleMetadataInstanceFormSubmit}\n setIsUnsavedChangesModalOpen={setIsUnsavedChangesModalOpen}\n taxonomyOptionsFetcher={null}\n />\n ) : (\n <MetadataInstance\n areAiSuggestionsAvailable={false}\n isAiSuggestionsFeatureEnabled={false}\n isBetaLanguageEnabled={false}\n onEdit={handleMetadataInstanceEdit}\n templateInstance={templateInstance}\n taxonomyNodeFetcher={null}\n />\n )}\n </AutofillContextProvider>\n </div>\n </SidePanel.ScrollableContainer>\n </SidePanel>\n );\n};\n\nexport default MetadataSidePanel;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MetadataSidePanel.js","names":["React","useState","useIntl","IconButton","SidePanel","Text","useNotification","XMark","FileDefault","AutofillContextProvider","MetadataInstance","MetadataInstanceForm","useTemplateInstance","useSelectedItemText","messages","MetadataSidePanel","currentCollection","metadataTemplate","onClose","onUpdate","refreshCollection","selectedItemIds","addNotification","formatMessage","isEditing","setIsEditing","isUnsavedChangesModalOpen","setIsUnsavedChangesModalOpen","selectedItemText","selectedItems","items","filter","item","has","id","templateInstance","handleMetadataInstanceEdit","handleMetadataInstanceFormCancel","handleMetadataInstanceFormDiscardUnsavedChanges","handleUpdateMetadataSuccess","closeButtonAriaLabel","close","sensitivity","styledText","metadataUpdateSuccessNotification","numSelected","length","typeIconAriaLabel","success","variant","handleUpdateMetadataError","metadataUpdateErrorNotification","error","handleMetadataInstanceFormSubmit","values","operations","fields","templateNewFields","metadata","templateOldFields","createElement","Header","as","sidebarMetadataTitle","className","color","icon","onClick","size","ScrollableContainer","fetchSuggestions","isAiSuggestionsFeatureEnabled","areAiSuggestionsAvailable","isBetaLanguageEnabled","isDeleteButtonDisabled","isDeleteConfirmationModalCheckboxEnabled","isLargeFile","isMultilevelTaxonomyFieldEnabled","selectedTemplateInstance","onCancel","onChange","onDelete","onDiscardUnsavedChanges","onSubmit","taxonomyOptionsFetcher","onEdit","taxonomyNodeFetcher"],"sources":["../../../src/elements/content-explorer/MetadataSidePanel.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport { IconButton, SidePanel, Text, useNotification } from '@box/blueprint-web';\nimport { XMark } from '@box/blueprint-web-assets/icons/Fill/index';\nimport { FileDefault } from '@box/blueprint-web-assets/icons/Line/index';\nimport {\n AutofillContextProvider,\n FormValues,\n JSONPatchOperations,\n MetadataInstance,\n MetadataInstanceForm,\n type MetadataTemplateField,\n} from '@box/metadata-editor';\n\nimport type { Selection } from 'react-aria-components';\nimport type { BoxItem, Collection } from '../../common/types/core';\nimport type { MetadataTemplate } from '../../common/types/metadata';\nimport { useTemplateInstance, useSelectedItemText } from './utils';\n\nimport messages from '../common/messages';\n\nimport './MetadataSidePanel.scss';\n\nexport interface MetadataSidePanelProps {\n currentCollection: Collection;\n metadataTemplate: MetadataTemplate;\n onClose: () => void;\n onUpdate: (\n items: BoxItem[],\n operations: JSONPatchOperations,\n templateOldFields: MetadataTemplateField[],\n templateNewFields: MetadataTemplateField[],\n successCallback: () => void,\n errorCallback: ErrorCallback,\n ) => Promise<void>;\n refreshCollection: () => void;\n selectedItemIds: Selection;\n}\n\nconst MetadataSidePanel = ({\n currentCollection,\n metadataTemplate,\n onClose,\n onUpdate,\n refreshCollection,\n selectedItemIds,\n}: MetadataSidePanelProps) => {\n const { addNotification } = useNotification();\n const { formatMessage } = useIntl();\n const [isEditing, setIsEditing] = useState<boolean>(false);\n const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState<boolean>(false);\n\n const selectedItemText = useSelectedItemText(currentCollection, selectedItemIds);\n const selectedItems =\n selectedItemIds === 'all'\n ? currentCollection.items\n : currentCollection.items.filter(item => selectedItemIds.has(item.id));\n const templateInstance = useTemplateInstance(metadataTemplate, selectedItems, isEditing);\n\n const handleMetadataInstanceEdit = () => {\n setIsEditing(true);\n };\n\n const handleMetadataInstanceFormCancel = () => {\n setIsEditing(false);\n };\n\n const handleMetadataInstanceFormDiscardUnsavedChanges = () => {\n setIsUnsavedChangesModalOpen(false);\n setIsEditing(false);\n };\n\n const handleUpdateMetadataSuccess = () => {\n addNotification({\n closeButtonAriaLabel: formatMessage(messages.close),\n sensitivity: 'foreground',\n styledText: formatMessage(messages.metadataUpdateSuccessNotification, {\n numSelected: selectedItems.length,\n }),\n typeIconAriaLabel: formatMessage(messages.success),\n variant: 'success',\n });\n setIsEditing(false);\n refreshCollection();\n };\n\n const handleUpdateMetadataError = () => {\n addNotification({\n closeButtonAriaLabel: formatMessage(messages.close),\n sensitivity: 'foreground',\n styledText: formatMessage(messages.metadataUpdateErrorNotification),\n typeIconAriaLabel: formatMessage(messages.error),\n variant: 'error',\n });\n };\n\n const handleMetadataInstanceFormSubmit = async (values: FormValues, operations: JSONPatchOperations) => {\n const { fields: templateNewFields } = values.metadata;\n const { fields: templateOldFields } = templateInstance;\n\n await onUpdate(\n selectedItems,\n operations,\n templateOldFields,\n templateNewFields,\n handleUpdateMetadataSuccess,\n handleUpdateMetadataError,\n );\n };\n\n return (\n <SidePanel variant=\"persistent\">\n <SidePanel.Header>\n <div>\n <Text as=\"span\" variant=\"titleLarge\">\n {formatMessage(messages.sidebarMetadataTitle)}\n </Text>\n <div className=\"bce-MetadataSidePanel-subtitle\">\n <FileDefault />\n <Text as=\"span\" color=\"textOnLightSecondary\" variant=\"subtitle\">\n {selectedItemText}\n </Text>\n </div>\n </div>\n <IconButton aria-label={formatMessage(messages.close)} icon={XMark} onClick={onClose} size=\"large\" />\n </SidePanel.Header>\n <SidePanel.ScrollableContainer>\n <div className=\"bce-MetadataSidePanel-content\">\n <AutofillContextProvider fetchSuggestions={null} isAiSuggestionsFeatureEnabled={false}>\n {isEditing ? (\n <MetadataInstanceForm\n areAiSuggestionsAvailable={false}\n isAiSuggestionsFeatureEnabled={false}\n isBetaLanguageEnabled={false}\n isDeleteButtonDisabled={true}\n isDeleteConfirmationModalCheckboxEnabled={false}\n isLargeFile={false}\n isMultilevelTaxonomyFieldEnabled={false}\n isUnsavedChangesModalOpen={isUnsavedChangesModalOpen}\n selectedTemplateInstance={templateInstance}\n onCancel={handleMetadataInstanceFormCancel}\n onChange={null}\n onDelete={null}\n onDiscardUnsavedChanges={handleMetadataInstanceFormDiscardUnsavedChanges}\n onSubmit={handleMetadataInstanceFormSubmit}\n setIsUnsavedChangesModalOpen={setIsUnsavedChangesModalOpen}\n taxonomyOptionsFetcher={null}\n />\n ) : (\n <MetadataInstance\n areAiSuggestionsAvailable={false}\n isAiSuggestionsFeatureEnabled={false}\n isBetaLanguageEnabled={false}\n onEdit={handleMetadataInstanceEdit}\n templateInstance={templateInstance}\n taxonomyNodeFetcher={null}\n />\n )}\n </AutofillContextProvider>\n </div>\n </SidePanel.ScrollableContainer>\n </SidePanel>\n );\n};\n\nexport default MetadataSidePanel;\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,5 @@
1
- const _excluded = ["actionBarProps", "columns", "currentCollection", "metadataTemplate"];
1
+ const _excluded = ["actionBarProps", "columns", "currentCollection", "metadataTemplate", "onSortChange"],
2
+ _excluded2 = ["tableProps"];
2
3
  function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
3
4
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
5
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -13,6 +14,20 @@ import { MetadataView } from '@box/metadata-view';
13
14
  // Public-friendly version of MetadataFormFieldValue from @box/metadata-filter
14
15
  // (string[] for enum type, range/float objects stay the same)
15
16
 
17
+ /**
18
+ * Helper function to trim metadataFieldNamePrefix from column names
19
+ * For example: 'metadata.enterprise_1515946.mdViewTemplate1.industry' -> 'industry'
20
+ */
21
+ function trimMetadataFieldPrefix(column) {
22
+ // Check if the column starts with 'metadata.' and contains at least 2 dots
23
+ if (column.startsWith('metadata.') && column.split('.').length >= 3) {
24
+ // Split by dots and take everything after the first 3 parts
25
+ // metadata.enterprise_1515946.mdViewTemplate1.industry -> industry
26
+ const parts = column.split('.');
27
+ return parts.slice(3).join('.');
28
+ }
29
+ return column;
30
+ }
16
31
  function transformInitialFilterValuesToInternal(publicValues) {
17
32
  if (!publicValues) return undefined;
18
33
  return Object.entries(publicValues).reduce((acc, [key, {
@@ -45,7 +60,8 @@ const MetadataViewContainer = _ref => {
45
60
  actionBarProps,
46
61
  columns,
47
62
  currentCollection,
48
- metadataTemplate
63
+ metadataTemplate,
64
+ onSortChange: onSortChangeInternal
49
65
  } = _ref,
50
66
  rest = _objectWithoutProperties(_ref, _excluded);
51
67
  const {
@@ -86,11 +102,46 @@ const MetadataViewContainer = _ref => {
86
102
  filterGroups
87
103
  });
88
104
  }, [actionBarProps, initialFilterValues, onFilterSubmit, filterGroups]);
105
+
106
+ // Extract the original tableProps.onSortChange from rest
107
+ const {
108
+ tableProps
109
+ } = rest,
110
+ otherRest = _objectWithoutProperties(rest, _excluded2);
111
+ const onSortChangeExternal = tableProps?.onSortChange;
112
+
113
+ // Create a wrapper function that calls both. The wrapper function should follow the signature of onSortChange from RAC
114
+ const handleSortChange = React.useCallback(({
115
+ column,
116
+ direction
117
+ }) => {
118
+ // Call the internal onSortChange first
119
+ // API accepts asc/desc "https://developer.box.com/reference/post-metadata-queries-execute-read/"
120
+ if (onSortChangeInternal) {
121
+ const trimmedColumn = trimMetadataFieldPrefix(String(column));
122
+ onSortChangeInternal(trimmedColumn, direction === 'ascending' ? 'ASC' : 'DESC');
123
+ }
124
+
125
+ // Then call the original customer-provided onSortChange if it exists
126
+ // Accepts "ascending" / "descending" (https://react-spectrum.adobe.com/react-aria/Table.html)
127
+ if (onSortChangeExternal) {
128
+ onSortChangeExternal({
129
+ column,
130
+ direction
131
+ });
132
+ }
133
+ }, [onSortChangeInternal, onSortChangeExternal]);
134
+
135
+ // Create new tableProps with our wrapper function
136
+ const newTableProps = _objectSpread(_objectSpread({}, tableProps), {}, {
137
+ onSortChange: handleSortChange
138
+ });
89
139
  return /*#__PURE__*/React.createElement(MetadataView, _extends({
90
140
  actionBarProps: transformedActionBarProps,
91
141
  columns: columns,
92
- items: items
93
- }, rest));
142
+ items: items,
143
+ tableProps: newTableProps
144
+ }, otherRest));
94
145
  };
95
146
  export default MetadataViewContainer;
96
147
  //# sourceMappingURL=MetadataViewContainer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MetadataViewContainer.js","names":["React","MetadataView","transformInitialFilterValuesToInternal","publicValues","undefined","Object","entries","reduce","acc","key","value","Array","isArray","enum","transformInternalFieldsToPublic","fields","MetadataViewContainer","_ref","actionBarProps","columns","currentCollection","metadataTemplate","rest","_objectWithoutProperties","_excluded","items","initialFilterValues","initialFilterValuesProp","onFilterSubmit","onFilterSubmitProp","filterGroups","useMemo","toggleable","filters","map","field","id","name","displayName","fieldType","type","options","shouldRenderChip","useCallback","transformed","transformedActionBarProps","_objectSpread","createElement","_extends"],"sources":["../../../src/elements/content-explorer/MetadataViewContainer.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { EnumType, FloatType, MetadataFormFieldValue, RangeType } from '@box/metadata-filter';\nimport { MetadataView, type MetadataViewProps } from '@box/metadata-view';\n\nimport type { Collection } from '../../common/types/core';\nimport type { MetadataTemplate } from '../../common/types/metadata';\n\n// Public-friendly version of MetadataFormFieldValue from @box/metadata-filter\n// (string[] for enum type, range/float objects stay the same)\ntype EnumToStringArray<T> = T extends EnumType ? string[] : T;\ntype ExternalMetadataFormFieldValue = EnumToStringArray<MetadataFormFieldValue>;\n\ntype ExternalFilterValues = Record<\n string,\n {\n value: ExternalMetadataFormFieldValue;\n }\n>;\n\ntype ActionBarProps = Omit<\n MetadataViewProps['actionBarProps'],\n 'initialFilterValues' | 'onFilterSubmit' | 'filterGroups'\n> & {\n initialFilterValues?: ExternalFilterValues;\n onFilterSubmit?: (filterValues: ExternalFilterValues) => void;\n};\n\nfunction transformInitialFilterValuesToInternal(\n publicValues?: ExternalFilterValues,\n): Record<string, { value: MetadataFormFieldValue }> | undefined {\n if (!publicValues) return undefined;\n\n return Object.entries(publicValues).reduce<Record<string, { value: MetadataFormFieldValue }>>(\n (acc, [key, { value }]) => {\n acc[key] = Array.isArray(value) ? { value: { enum: value } } : { value };\n return acc;\n },\n {},\n );\n}\n\nfunction transformInternalFieldsToPublic(\n fields: Record<string, { value: MetadataFormFieldValue }>,\n): ExternalFilterValues {\n return Object.entries(fields).reduce<ExternalFilterValues>((acc, [key, { value }]) => {\n acc[key] =\n 'enum' in value && Array.isArray(value.enum)\n ? { value: value.enum }\n : { value: value as RangeType | FloatType };\n return acc;\n }, {});\n}\n\nexport interface MetadataViewContainerProps extends Omit<MetadataViewProps, 'items' | 'actionBarProps'> {\n actionBarProps?: ActionBarProps;\n currentCollection: Collection;\n metadataTemplate: MetadataTemplate;\n}\n\nconst MetadataViewContainer = ({\n actionBarProps,\n columns,\n currentCollection,\n metadataTemplate,\n ...rest\n}: MetadataViewContainerProps) => {\n const { items = [] } = currentCollection;\n const { initialFilterValues: initialFilterValuesProp, onFilterSubmit: onFilterSubmitProp } = actionBarProps ?? {};\n\n const filterGroups = React.useMemo(\n () => [\n {\n toggleable: true,\n filters:\n metadataTemplate?.fields?.map(field => {\n return {\n id: `${field.key}-filter`,\n name: field.displayName,\n fieldType: field.type,\n options: field.options?.map(({ key }) => key) || [],\n shouldRenderChip: true,\n };\n }) || [],\n },\n ],\n [metadataTemplate],\n );\n\n // Transform initial filter values to internal field format\n const initialFilterValues = React.useMemo(\n () => transformInitialFilterValuesToInternal(initialFilterValuesProp),\n [initialFilterValuesProp],\n );\n\n // Transform field values to public-friendly format\n const onFilterSubmit = React.useCallback(\n (fields: Record<string, { value: MetadataFormFieldValue }>) => {\n if (!onFilterSubmitProp) return;\n const transformed = transformInternalFieldsToPublic(fields);\n onFilterSubmitProp(transformed);\n },\n [onFilterSubmitProp],\n );\n\n const transformedActionBarProps = React.useMemo(() => {\n return {\n ...actionBarProps,\n initialFilterValues,\n onFilterSubmit,\n filterGroups,\n };\n }, [actionBarProps, initialFilterValues, onFilterSubmit, filterGroups]);\n\n return <MetadataView actionBarProps={transformedActionBarProps} columns={columns} items={items} {...rest} />;\n};\n\nexport default MetadataViewContainer;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MetadataViewContainer.js","names":["React","MetadataView","trimMetadataFieldPrefix","column","startsWith","split","length","parts","slice","join","transformInitialFilterValuesToInternal","publicValues","undefined","Object","entries","reduce","acc","key","value","Array","isArray","enum","transformInternalFieldsToPublic","fields","MetadataViewContainer","_ref","actionBarProps","columns","currentCollection","metadataTemplate","onSortChange","onSortChangeInternal","rest","_objectWithoutProperties","_excluded","items","initialFilterValues","initialFilterValuesProp","onFilterSubmit","onFilterSubmitProp","filterGroups","useMemo","toggleable","filters","map","field","id","name","displayName","fieldType","type","options","shouldRenderChip","useCallback","transformed","transformedActionBarProps","_objectSpread","tableProps","otherRest","_excluded2","onSortChangeExternal","handleSortChange","direction","trimmedColumn","String","newTableProps","createElement","_extends"],"sources":["../../../src/elements/content-explorer/MetadataViewContainer.tsx"],"sourcesContent":["import * as React from 'react';\nimport type { EnumType, FloatType, MetadataFormFieldValue, RangeType } from '@box/metadata-filter';\nimport { MetadataView, type MetadataViewProps } from '@box/metadata-view';\nimport { type Key } from '@react-types/shared';\n\nimport { SortDescriptor } from 'react-aria-components';\nimport type { Collection } from '../../common/types/core';\nimport type { MetadataTemplate } from '../../common/types/metadata';\n\n// Public-friendly version of MetadataFormFieldValue from @box/metadata-filter\n// (string[] for enum type, range/float objects stay the same)\ntype EnumToStringArray<T> = T extends EnumType ? string[] : T;\ntype ExternalMetadataFormFieldValue = EnumToStringArray<MetadataFormFieldValue>;\n\ntype ExternalFilterValues = Record<\n string,\n {\n value: ExternalMetadataFormFieldValue;\n }\n>;\n\ntype ActionBarProps = Omit<\n MetadataViewProps['actionBarProps'],\n 'initialFilterValues' | 'onFilterSubmit' | 'filterGroups'\n> & {\n initialFilterValues?: ExternalFilterValues;\n onFilterSubmit?: (filterValues: ExternalFilterValues) => void;\n};\n\n/**\n * Helper function to trim metadataFieldNamePrefix from column names\n * For example: 'metadata.enterprise_1515946.mdViewTemplate1.industry' -> 'industry'\n */\nfunction trimMetadataFieldPrefix(column: string): string {\n // Check if the column starts with 'metadata.' and contains at least 2 dots\n if (column.startsWith('metadata.') && column.split('.').length >= 3) {\n // Split by dots and take everything after the first 3 parts\n // metadata.enterprise_1515946.mdViewTemplate1.industry -> industry\n const parts = column.split('.');\n return parts.slice(3).join('.');\n }\n return column;\n}\n\nfunction transformInitialFilterValuesToInternal(\n publicValues?: ExternalFilterValues,\n): Record<string, { value: MetadataFormFieldValue }> | undefined {\n if (!publicValues) return undefined;\n\n return Object.entries(publicValues).reduce<Record<string, { value: MetadataFormFieldValue }>>(\n (acc, [key, { value }]) => {\n acc[key] = Array.isArray(value) ? { value: { enum: value } } : { value };\n return acc;\n },\n {},\n );\n}\n\nfunction transformInternalFieldsToPublic(\n fields: Record<string, { value: MetadataFormFieldValue }>,\n): ExternalFilterValues {\n return Object.entries(fields).reduce<ExternalFilterValues>((acc, [key, { value }]) => {\n acc[key] =\n 'enum' in value && Array.isArray(value.enum)\n ? { value: value.enum }\n : { value: value as RangeType | FloatType };\n return acc;\n }, {});\n}\n\nexport interface MetadataViewContainerProps extends Omit<MetadataViewProps, 'items' | 'actionBarProps'> {\n actionBarProps?: ActionBarProps;\n currentCollection: Collection;\n metadataTemplate: MetadataTemplate;\n /* Internally controlled onSortChange prop for the MetadataView component. */\n onSortChange?: (sortBy: Key, sortDirection: string) => void;\n}\n\nconst MetadataViewContainer = ({\n actionBarProps,\n columns,\n currentCollection,\n metadataTemplate,\n onSortChange: onSortChangeInternal,\n ...rest\n}: MetadataViewContainerProps) => {\n const { items = [] } = currentCollection;\n const { initialFilterValues: initialFilterValuesProp, onFilterSubmit: onFilterSubmitProp } = actionBarProps ?? {};\n\n const filterGroups = React.useMemo(\n () => [\n {\n toggleable: true,\n filters:\n metadataTemplate?.fields?.map(field => {\n return {\n id: `${field.key}-filter`,\n name: field.displayName,\n fieldType: field.type,\n options: field.options?.map(({ key }) => key) || [],\n shouldRenderChip: true,\n };\n }) || [],\n },\n ],\n [metadataTemplate],\n );\n\n // Transform initial filter values to internal field format\n const initialFilterValues = React.useMemo(\n () => transformInitialFilterValuesToInternal(initialFilterValuesProp),\n [initialFilterValuesProp],\n );\n\n // Transform field values to public-friendly format\n const onFilterSubmit = React.useCallback(\n (fields: Record<string, { value: MetadataFormFieldValue }>) => {\n if (!onFilterSubmitProp) return;\n const transformed = transformInternalFieldsToPublic(fields);\n onFilterSubmitProp(transformed);\n },\n [onFilterSubmitProp],\n );\n\n const transformedActionBarProps = React.useMemo(() => {\n return {\n ...actionBarProps,\n initialFilterValues,\n onFilterSubmit,\n filterGroups,\n };\n }, [actionBarProps, initialFilterValues, onFilterSubmit, filterGroups]);\n\n // Extract the original tableProps.onSortChange from rest\n const { tableProps, ...otherRest } = rest;\n const onSortChangeExternal = tableProps?.onSortChange;\n\n // Create a wrapper function that calls both. The wrapper function should follow the signature of onSortChange from RAC\n const handleSortChange = React.useCallback(\n ({ column, direction }: SortDescriptor) => {\n // Call the internal onSortChange first\n // API accepts asc/desc \"https://developer.box.com/reference/post-metadata-queries-execute-read/\"\n if (onSortChangeInternal) {\n const trimmedColumn = trimMetadataFieldPrefix(String(column));\n onSortChangeInternal(trimmedColumn, direction === 'ascending' ? 'ASC' : 'DESC');\n }\n\n // Then call the original customer-provided onSortChange if it exists\n // Accepts \"ascending\" / \"descending\" (https://react-spectrum.adobe.com/react-aria/Table.html)\n if (onSortChangeExternal) {\n onSortChangeExternal({\n column,\n direction,\n });\n }\n },\n [onSortChangeInternal, onSortChangeExternal],\n );\n\n // Create new tableProps with our wrapper function\n const newTableProps = {\n ...tableProps,\n onSortChange: handleSortChange,\n };\n\n return (\n <MetadataView\n actionBarProps={transformedActionBarProps}\n columns={columns}\n items={items}\n tableProps={newTableProps}\n {...otherRest}\n />\n );\n};\n\nexport default MetadataViewContainer;\n"],"mappings":"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","ignoreList":[]}
@@ -8,6 +8,7 @@ import { Download, SignMeOthers } from '@box/blueprint-web-assets/icons/Fill/ind
8
8
  import { Sign } from '@box/blueprint-web-assets/icons/Line';
9
9
  import { expect, fn, userEvent, waitFor, within, screen } from 'storybook/test';
10
10
  import noop from 'lodash/noop';
11
+ import orderBy from 'lodash/orderBy';
11
12
  import ContentExplorer from '../../ContentExplorer';
12
13
  import { DEFAULT_HOSTNAME_API } from '../../../../constants';
13
14
  import { mockMetadata, mockSchema } from '../../../common/__mocks__/mockMetadata';
@@ -131,25 +132,20 @@ const metadataViewV2WithBulkItemActions = _objectSpread(_objectSpread({}, metada
131
132
  export const metadataViewV2 = {
132
133
  args: metadataViewV2ElementProps
133
134
  };
134
-
135
- // @TODO Assert that rows are actually sorted in a different order, once handleSortChange is implemented
136
135
  export const metadataViewV2SortsFromHeader = {
137
136
  args: metadataViewV2ElementProps,
138
137
  play: async ({
139
138
  canvas
140
139
  }) => {
141
- await waitFor(() => {
142
- expect(canvas.getByRole('row', {
143
- name: /Industry/i
144
- })).toBeInTheDocument();
145
- });
146
- const firstRow = canvas.getByRole('row', {
147
- name: /Industry/i
148
- });
149
- const industryHeader = within(firstRow).getByRole('columnheader', {
140
+ const industryHeader = await canvas.findByRole('columnheader', {
150
141
  name: 'Industry'
151
142
  });
152
- userEvent.click(industryHeader);
143
+ expect(industryHeader).toBeInTheDocument();
144
+ const firstRow = await canvas.findByRole('row', {
145
+ name: /Child 2/i
146
+ });
147
+ expect(firstRow).toBeInTheDocument();
148
+ await userEvent.click(industryHeader);
153
149
  }
154
150
  };
155
151
  export const metadataViewV2WithCustomActions = {
@@ -263,6 +259,43 @@ export const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu = {
263
259
  expect(downloadAction).toBeInTheDocument();
264
260
  }
265
261
  };
262
+ export const sidePanelOpenWithMultipleItemsSelected = {
263
+ args: _objectSpread(_objectSpread({}, metadataViewV2ElementProps), {}, {
264
+ metadataViewProps: {
265
+ columns,
266
+ tableProps: {
267
+ isSelectAllEnabled: true
268
+ }
269
+ }
270
+ }),
271
+ play: async ({
272
+ canvas
273
+ }) => {
274
+ await waitFor(() => {
275
+ expect(canvas.getByRole('row', {
276
+ name: /Child 2/i
277
+ })).toBeInTheDocument();
278
+ });
279
+
280
+ // Select the first row by clicking its checkbox
281
+ const firstItem = canvas.getByRole('row', {
282
+ name: /Child 2/i
283
+ });
284
+ const checkbox = within(firstItem).getByRole('checkbox');
285
+ await userEvent.click(checkbox);
286
+
287
+ // Select the second row by clicking its checkbox
288
+ const secondItem = canvas.getAllByRole('row', {
289
+ name: /Child 1/i
290
+ })[0];
291
+ const secondCheckbox = within(secondItem).getByRole('checkbox');
292
+ await userEvent.click(secondCheckbox);
293
+ const metadataButton = canvas.getByRole('button', {
294
+ name: 'Metadata'
295
+ });
296
+ await userEvent.click(metadataButton);
297
+ }
298
+ };
266
299
  const meta = {
267
300
  title: 'Elements/ContentExplorer/tests/MetadataView/visual',
268
301
  component: ContentExplorer,
@@ -273,7 +306,22 @@ const meta = {
273
306
  },
274
307
  parameters: {
275
308
  msw: {
276
- handlers: [http.post(`${DEFAULT_HOSTNAME_API}/2.0/metadata_queries/execute_read`, () => {
309
+ handlers: [
310
+ // Note that the Metadata API backend normally handles the sorting. The mocks below simulate the sorting for specific cases, but may not 100% accurately reflect the backend behavior.
311
+ http.post(`${DEFAULT_HOSTNAME_API}/2.0/metadata_queries/execute_read`, async ({
312
+ request
313
+ }) => {
314
+ const body = await request.clone().json();
315
+ const orderByDirection = body.order_by[0].direction;
316
+ const orderByFieldKey = body.order_by[0].field_key;
317
+
318
+ // Hardcoded case for sorting by industry
319
+ if (orderByFieldKey === `industry` && orderByDirection === 'ASC') {
320
+ const sortedMetadata = orderBy(mockMetadata.entries, 'metadata.enterprise_0.templateName.industry', 'asc');
321
+ return HttpResponse.json(_objectSpread(_objectSpread({}, mockMetadata), {}, {
322
+ entries: sortedMetadata
323
+ }));
324
+ }
277
325
  return HttpResponse.json(mockMetadata);
278
326
  }), http.get(`${DEFAULT_HOSTNAME_API}/2.0/metadata_templates/enterprise/templateName/schema`, () => {
279
327
  return HttpResponse.json(mockSchema);