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
@@ -1 +1 @@
1
- {"version":3,"file":"MetadataView-visual.stories.js","names":["http","HttpResponse","Download","SignMeOthers","Sign","expect","fn","userEvent","waitFor","within","screen","noop","ContentExplorer","DEFAULT_HOSTNAME_API","mockMetadata","mockSchema","mockRootFolder","scope","templateScope","templateKey","metadataScopeAndKey","metadataFieldNamePrefix","metadataQuery","from","ancestor_folder_id","order_by","field_key","fields","key","direction","map","field","fieldsToShow","canEdit","displayName","columns","textValue","id","type","allowsSorting","minWidth","maxWidth","defaultView","metadataView","args","metadataViewV2ElementProps","metadataViewProps","features","contentExplorer","metadataViewV2","metadataViewV2WithInlineCustomActionsElementProps","_objectSpread","tableProps","isSelectAllEnabled","itemActionMenuProps","actions","label","onClick","icon","subMenuTrigger","subMenuActions","metadataViewV2WithBulkItemActions","bulkItemActions","metadataViewV2SortsFromHeader","play","canvas","getByRole","name","toBeInTheDocument","firstRow","industryHeader","click","metadataViewV2WithCustomActions","ellipsesButton","initialFilterActionBarProps","initialFilterValues","value","metadataViewV2WithInitialFilterValues","actionBarProps","toHaveTextContent","contactRoleChip","fileTypeChip","sidePanelOpenWithSingleItemSelected","checkbox","metadataButton","metadataViewV2WithBulkItemActionMenuShowsItemActionMenu","findByRole","ellipsisButton","downloadAction","meta","title","component","global","FEATURE_FLAGS","rootFolderId","FOLDER_ID","token","TOKEN","parameters","msw","handlers","post","json","get"],"sources":["../../../../../src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx"],"sourcesContent":["import type { Meta, StoryObj } from '@storybook/react';\nimport { http, HttpResponse } from 'msw';\nimport { Download, SignMeOthers } from '@box/blueprint-web-assets/icons/Fill/index';\nimport { Sign } from '@box/blueprint-web-assets/icons/Line';\nimport { expect, fn, userEvent, waitFor, within, screen } from 'storybook/test';\nimport noop from 'lodash/noop';\n\nimport ContentExplorer from '../../ContentExplorer';\nimport { DEFAULT_HOSTNAME_API } from '../../../../constants';\nimport { mockMetadata, mockSchema } from '../../../common/__mocks__/mockMetadata';\nimport { mockRootFolder } from '../../../common/__mocks__/mockRootFolder';\n\n// The intent behind relying on mockMetadata is to allow a developer to paste in their own metadata template schema for use with live API calls.\nconst { scope: templateScope, templateKey } = mockSchema;\n\nconst metadataScopeAndKey = `${templateScope}.${templateKey}`;\nconst metadataFieldNamePrefix = `metadata.${metadataScopeAndKey}`;\n\n// This is the body of the metadata query API call.\n// https://developer.box.com/guides/metadata/queries/syntax/\nconst metadataQuery = {\n from: metadataScopeAndKey,\n ancestor_folder_id: '0',\n order_by: [\n {\n field_key: `${metadataFieldNamePrefix}.${mockSchema.fields[0].key}`, // Default to sorting by the first field in the schema\n direction: 'asc',\n },\n ],\n fields: [\n // Default to returning all fields in the metadata template schema, and name as a standalone (non-metadata) field\n ...mockSchema.fields.map(field => `${metadataFieldNamePrefix}.${field.key}`),\n 'name',\n ],\n};\n\n// Used for metadata view v1\nconst fieldsToShow = [\n { key: `${metadataFieldNamePrefix}.name`, canEdit: false, displayName: 'Alias' },\n { key: `${metadataFieldNamePrefix}.industry`, canEdit: true },\n { key: `${metadataFieldNamePrefix}.last_contacted_at`, canEdit: true },\n { key: `${metadataFieldNamePrefix}.role`, canEdit: true },\n];\n\n// Used for metadata view v2\nconst columns = [\n {\n // Always include the name column\n textValue: 'Name',\n id: 'name',\n type: 'string',\n allowsSorting: true,\n minWidth: 150,\n maxWidth: 150,\n },\n ...mockSchema.fields.map(field => ({\n textValue: field.displayName,\n id: `${metadataFieldNamePrefix}.${field.key}`,\n type: field.type,\n allowsSorting: true,\n minWidth: 150,\n maxWidth: 150,\n })),\n];\n\n// Switches ContentExplorer to use Metadata View over standard, folder-based view.\nconst defaultView = 'metadata';\n\nexport const metadataView: Story = {\n args: {\n metadataQuery,\n fieldsToShow,\n defaultView,\n },\n};\n\nconst metadataViewV2ElementProps = {\n metadataViewProps: {\n columns,\n },\n metadataQuery,\n fieldsToShow,\n defaultView,\n features: {\n contentExplorer: {\n metadataViewV2: true,\n },\n },\n};\n\nconst metadataViewV2WithInlineCustomActionsElementProps = {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n itemActionMenuProps: {\n actions: [\n {\n label: 'Download',\n onClick: noop,\n icon: Download,\n },\n ],\n subMenuTrigger: {\n label: 'Sign',\n icon: Sign,\n },\n subMenuActions: [\n {\n label: 'Request Signature',\n onClick: noop,\n icon: SignMeOthers,\n },\n ],\n },\n },\n};\n\nconst metadataViewV2WithBulkItemActions = {\n ...metadataViewV2ElementProps,\n bulkItemActions: [\n {\n label: 'Download',\n onClick: fn(),\n },\n ],\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n },\n};\n\nexport const metadataViewV2: Story = {\n args: metadataViewV2ElementProps,\n};\n\n// @TODO Assert that rows are actually sorted in a different order, once handleSortChange is implemented\nexport const metadataViewV2SortsFromHeader: Story = {\n args: metadataViewV2ElementProps,\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Industry/i })).toBeInTheDocument();\n });\n\n const firstRow = canvas.getByRole('row', { name: /Industry/i });\n const industryHeader = within(firstRow).getByRole('columnheader', { name: 'Industry' });\n userEvent.click(industryHeader);\n },\n};\n\nexport const metadataViewV2WithCustomActions: Story = {\n args: metadataViewV2WithInlineCustomActionsElementProps,\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();\n });\n const firstRow = canvas.getByRole('row', { name: /Child 2/i });\n const ellipsesButton = within(firstRow).getByRole('button', { name: 'Action menu' });\n userEvent.click(ellipsesButton);\n },\n};\n\nconst initialFilterActionBarProps = {\n initialFilterValues: {\n 'industry-filter': { value: ['Legal'] },\n 'mimetype-filter': { value: ['boxnoteType', 'documentType', 'threedType'] },\n 'role-filter': { value: ['Developer', 'Business Owner', 'Marketing'] },\n },\n};\n\nexport const metadataViewV2WithInitialFilterValues: Story = {\n args: {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n actionBarProps: initialFilterActionBarProps,\n },\n },\n play: async ({ canvas }) => {\n // Wait for chips to update with initial values\n await waitFor(() => {\n expect(canvas.getByRole('button', { name: /Industry/i })).toHaveTextContent(/\\(1\\)/);\n });\n // Other chips should reflect initialized values\n const contactRoleChip = canvas.getByRole('button', { name: /Contact Role/i });\n expect(contactRoleChip).toHaveTextContent(/\\(3\\)/);\n\n const fileTypeChip = canvas.getByRole('button', { name: /Box Note/i });\n expect(fileTypeChip).toHaveTextContent(/\\+2/);\n },\n};\n\nexport const sidePanelOpenWithSingleItemSelected: Story = {\n args: {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n },\n },\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();\n });\n\n // Select the first row by clicking its checkbox\n const firstRow = canvas.getByRole('row', { name: /Child 2/i });\n const checkbox = within(firstRow).getByRole('checkbox');\n await userEvent.click(checkbox);\n\n const metadataButton = canvas.getByRole('button', { name: 'Metadata' });\n await userEvent.click(metadataButton);\n },\n};\n\nexport const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu: Story = {\n args: metadataViewV2WithBulkItemActions,\n play: async ({ canvas }) => {\n const firstRow = await canvas.findByRole('row', { name: /Child 2/i });\n expect(firstRow).toBeInTheDocument();\n\n const checkbox = within(firstRow).getByRole('checkbox');\n await userEvent.click(checkbox);\n\n const ellipsisButton = canvas.getByRole('button', { name: 'Bulk actions' });\n expect(ellipsisButton).toBeInTheDocument();\n await userEvent.click(ellipsisButton);\n\n const downloadAction = screen.getByRole('menuitem', { name: 'Download' });\n expect(downloadAction).toBeInTheDocument();\n },\n};\n\nconst meta: Meta<typeof ContentExplorer> = {\n title: 'Elements/ContentExplorer/tests/MetadataView/visual',\n component: ContentExplorer,\n args: {\n features: global.FEATURE_FLAGS,\n rootFolderId: global.FOLDER_ID,\n token: global.TOKEN,\n },\n parameters: {\n msw: {\n handlers: [\n http.post(`${DEFAULT_HOSTNAME_API}/2.0/metadata_queries/execute_read`, () => {\n return HttpResponse.json(mockMetadata);\n }),\n http.get(`${DEFAULT_HOSTNAME_API}/2.0/metadata_templates/enterprise/templateName/schema`, () => {\n return HttpResponse.json(mockSchema);\n }),\n http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/:id`, () => {\n return HttpResponse.json(mockRootFolder);\n }),\n ],\n },\n },\n};\n\ntype Story = StoryObj<typeof meta>;\n\nexport default meta;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"MetadataView-visual.stories.js","names":["http","HttpResponse","Download","SignMeOthers","Sign","expect","fn","userEvent","waitFor","within","screen","noop","orderBy","ContentExplorer","DEFAULT_HOSTNAME_API","mockMetadata","mockSchema","mockRootFolder","scope","templateScope","templateKey","metadataScopeAndKey","metadataFieldNamePrefix","metadataQuery","from","ancestor_folder_id","order_by","field_key","fields","key","direction","map","field","fieldsToShow","canEdit","displayName","columns","textValue","id","type","allowsSorting","minWidth","maxWidth","defaultView","metadataView","args","metadataViewV2ElementProps","metadataViewProps","features","contentExplorer","metadataViewV2","metadataViewV2WithInlineCustomActionsElementProps","_objectSpread","tableProps","isSelectAllEnabled","itemActionMenuProps","actions","label","onClick","icon","subMenuTrigger","subMenuActions","metadataViewV2WithBulkItemActions","bulkItemActions","metadataViewV2SortsFromHeader","play","canvas","industryHeader","findByRole","name","toBeInTheDocument","firstRow","click","metadataViewV2WithCustomActions","getByRole","ellipsesButton","initialFilterActionBarProps","initialFilterValues","value","metadataViewV2WithInitialFilterValues","actionBarProps","toHaveTextContent","contactRoleChip","fileTypeChip","sidePanelOpenWithSingleItemSelected","checkbox","metadataButton","metadataViewV2WithBulkItemActionMenuShowsItemActionMenu","ellipsisButton","downloadAction","sidePanelOpenWithMultipleItemsSelected","firstItem","secondItem","getAllByRole","secondCheckbox","meta","title","component","global","FEATURE_FLAGS","rootFolderId","FOLDER_ID","token","TOKEN","parameters","msw","handlers","post","request","body","clone","json","orderByDirection","orderByFieldKey","sortedMetadata","entries","get"],"sources":["../../../../../src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx"],"sourcesContent":["import type { Meta, StoryObj } from '@storybook/react';\nimport { http, HttpResponse } from 'msw';\nimport { Download, SignMeOthers } from '@box/blueprint-web-assets/icons/Fill/index';\nimport { Sign } from '@box/blueprint-web-assets/icons/Line';\nimport { expect, fn, userEvent, waitFor, within, screen } from 'storybook/test';\n\nimport noop from 'lodash/noop';\nimport orderBy from 'lodash/orderBy';\n\nimport ContentExplorer from '../../ContentExplorer';\nimport { DEFAULT_HOSTNAME_API } from '../../../../constants';\nimport { mockMetadata, mockSchema } from '../../../common/__mocks__/mockMetadata';\nimport { mockRootFolder } from '../../../common/__mocks__/mockRootFolder';\n\n// The intent behind relying on mockMetadata is to allow a developer to paste in their own metadata template schema for use with live API calls.\nconst { scope: templateScope, templateKey } = mockSchema;\n\nconst metadataScopeAndKey = `${templateScope}.${templateKey}`;\nconst metadataFieldNamePrefix = `metadata.${metadataScopeAndKey}`;\n\n// This is the body of the metadata query API call.\n// https://developer.box.com/guides/metadata/queries/syntax/\nconst metadataQuery = {\n from: metadataScopeAndKey,\n ancestor_folder_id: '0',\n order_by: [\n {\n field_key: `${metadataFieldNamePrefix}.${mockSchema.fields[0].key}`, // Default to sorting by the first field in the schema\n direction: 'asc',\n },\n ],\n fields: [\n // Default to returning all fields in the metadata template schema, and name as a standalone (non-metadata) field\n ...mockSchema.fields.map(field => `${metadataFieldNamePrefix}.${field.key}`),\n 'name',\n ],\n};\n\n// Used for metadata view v1\nconst fieldsToShow = [\n { key: `${metadataFieldNamePrefix}.name`, canEdit: false, displayName: 'Alias' },\n { key: `${metadataFieldNamePrefix}.industry`, canEdit: true },\n { key: `${metadataFieldNamePrefix}.last_contacted_at`, canEdit: true },\n { key: `${metadataFieldNamePrefix}.role`, canEdit: true },\n];\n\n// Used for metadata view v2\nconst columns = [\n {\n // Always include the name column\n textValue: 'Name',\n id: 'name',\n type: 'string',\n allowsSorting: true,\n minWidth: 150,\n maxWidth: 150,\n },\n ...mockSchema.fields.map(field => ({\n textValue: field.displayName,\n id: `${metadataFieldNamePrefix}.${field.key}`,\n type: field.type,\n allowsSorting: true,\n minWidth: 150,\n maxWidth: 150,\n })),\n];\n\n// Switches ContentExplorer to use Metadata View over standard, folder-based view.\nconst defaultView = 'metadata';\n\nexport const metadataView: Story = {\n args: {\n metadataQuery,\n fieldsToShow,\n defaultView,\n },\n};\n\nconst metadataViewV2ElementProps = {\n metadataViewProps: {\n columns,\n },\n metadataQuery,\n fieldsToShow,\n defaultView,\n features: {\n contentExplorer: {\n metadataViewV2: true,\n },\n },\n};\n\nconst metadataViewV2WithInlineCustomActionsElementProps = {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n itemActionMenuProps: {\n actions: [\n {\n label: 'Download',\n onClick: noop,\n icon: Download,\n },\n ],\n subMenuTrigger: {\n label: 'Sign',\n icon: Sign,\n },\n subMenuActions: [\n {\n label: 'Request Signature',\n onClick: noop,\n icon: SignMeOthers,\n },\n ],\n },\n },\n};\n\nconst metadataViewV2WithBulkItemActions = {\n ...metadataViewV2ElementProps,\n bulkItemActions: [\n {\n label: 'Download',\n onClick: fn(),\n },\n ],\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n },\n};\n\nexport const metadataViewV2: Story = {\n args: metadataViewV2ElementProps,\n};\n\nexport const metadataViewV2SortsFromHeader: Story = {\n args: metadataViewV2ElementProps,\n play: async ({ canvas }) => {\n const industryHeader = await canvas.findByRole('columnheader', { name: 'Industry' });\n expect(industryHeader).toBeInTheDocument();\n\n const firstRow = await canvas.findByRole('row', { name: /Child 2/i });\n expect(firstRow).toBeInTheDocument();\n\n await userEvent.click(industryHeader);\n },\n};\n\nexport const metadataViewV2WithCustomActions: Story = {\n args: metadataViewV2WithInlineCustomActionsElementProps,\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();\n });\n const firstRow = canvas.getByRole('row', { name: /Child 2/i });\n const ellipsesButton = within(firstRow).getByRole('button', { name: 'Action menu' });\n userEvent.click(ellipsesButton);\n },\n};\n\nconst initialFilterActionBarProps = {\n initialFilterValues: {\n 'industry-filter': { value: ['Legal'] },\n 'mimetype-filter': { value: ['boxnoteType', 'documentType', 'threedType'] },\n 'role-filter': { value: ['Developer', 'Business Owner', 'Marketing'] },\n },\n};\n\nexport const metadataViewV2WithInitialFilterValues: Story = {\n args: {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n actionBarProps: initialFilterActionBarProps,\n },\n },\n play: async ({ canvas }) => {\n // Wait for chips to update with initial values\n await waitFor(() => {\n expect(canvas.getByRole('button', { name: /Industry/i })).toHaveTextContent(/\\(1\\)/);\n });\n // Other chips should reflect initialized values\n const contactRoleChip = canvas.getByRole('button', { name: /Contact Role/i });\n expect(contactRoleChip).toHaveTextContent(/\\(3\\)/);\n\n const fileTypeChip = canvas.getByRole('button', { name: /Box Note/i });\n expect(fileTypeChip).toHaveTextContent(/\\+2/);\n },\n};\n\nexport const sidePanelOpenWithSingleItemSelected: Story = {\n args: {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n },\n },\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();\n });\n\n // Select the first row by clicking its checkbox\n const firstRow = canvas.getByRole('row', { name: /Child 2/i });\n const checkbox = within(firstRow).getByRole('checkbox');\n await userEvent.click(checkbox);\n\n const metadataButton = canvas.getByRole('button', { name: 'Metadata' });\n await userEvent.click(metadataButton);\n },\n};\n\nexport const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu: Story = {\n args: metadataViewV2WithBulkItemActions,\n play: async ({ canvas }) => {\n const firstRow = await canvas.findByRole('row', { name: /Child 2/i });\n expect(firstRow).toBeInTheDocument();\n\n const checkbox = within(firstRow).getByRole('checkbox');\n await userEvent.click(checkbox);\n\n const ellipsisButton = canvas.getByRole('button', { name: 'Bulk actions' });\n expect(ellipsisButton).toBeInTheDocument();\n await userEvent.click(ellipsisButton);\n\n const downloadAction = screen.getByRole('menuitem', { name: 'Download' });\n expect(downloadAction).toBeInTheDocument();\n },\n};\n\nexport const sidePanelOpenWithMultipleItemsSelected: Story = {\n args: {\n ...metadataViewV2ElementProps,\n metadataViewProps: {\n columns,\n tableProps: {\n isSelectAllEnabled: true,\n },\n },\n },\n\n play: async ({ canvas }) => {\n await waitFor(() => {\n expect(canvas.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();\n });\n\n // Select the first row by clicking its checkbox\n const firstItem = canvas.getByRole('row', { name: /Child 2/i });\n const checkbox = within(firstItem).getByRole('checkbox');\n await userEvent.click(checkbox);\n\n // Select the second row by clicking its checkbox\n const secondItem = canvas.getAllByRole('row', { name: /Child 1/i })[0];\n const secondCheckbox = within(secondItem).getByRole('checkbox');\n await userEvent.click(secondCheckbox);\n\n const metadataButton = canvas.getByRole('button', { name: 'Metadata' });\n await userEvent.click(metadataButton);\n },\n};\n\nconst meta: Meta<typeof ContentExplorer> = {\n title: 'Elements/ContentExplorer/tests/MetadataView/visual',\n component: ContentExplorer,\n args: {\n features: global.FEATURE_FLAGS,\n rootFolderId: global.FOLDER_ID,\n token: global.TOKEN,\n },\n parameters: {\n msw: {\n handlers: [\n // 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.\n http.post(`${DEFAULT_HOSTNAME_API}/2.0/metadata_queries/execute_read`, async ({ request }) => {\n const body = await request.clone().json();\n const orderByDirection = body.order_by[0].direction;\n const orderByFieldKey = body.order_by[0].field_key;\n\n // Hardcoded case for sorting by industry\n if (orderByFieldKey === `industry` && orderByDirection === 'ASC') {\n const sortedMetadata = orderBy(\n mockMetadata.entries,\n 'metadata.enterprise_0.templateName.industry',\n 'asc',\n );\n return HttpResponse.json({ ...mockMetadata, entries: sortedMetadata });\n }\n return HttpResponse.json(mockMetadata);\n }),\n http.get(`${DEFAULT_HOSTNAME_API}/2.0/metadata_templates/enterprise/templateName/schema`, () => {\n return HttpResponse.json(mockSchema);\n }),\n http.get(`${DEFAULT_HOSTNAME_API}/2.0/folders/:id`, () => {\n return HttpResponse.json(mockRootFolder);\n }),\n ],\n },\n },\n};\n\ntype Story = StoryObj<typeof meta>;\n\nexport default meta;\n"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,18 @@
1
- import { useMemo } from 'react';
1
+ 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; }
2
+ 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; }
3
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
+ import React, { useMemo } from 'react';
2
7
  import { useIntl } from 'react-intl';
8
+ import isNil from 'lodash/isNil';
9
+ import xor from 'lodash/xor';
10
+ import { MULTI_VALUE_DEFAULT_OPTION, MULTI_VALUE_DEFAULT_VALUE } from '@box/metadata-editor';
3
11
  import messages from '../common/messages';
4
12
 
13
+ // Specific type for metadata field value in the item
14
+ // Note: Item doesn't have field value in metadata object if that field is not set, so the value will be undefined in this case
15
+
5
16
  // Get selected item text
6
17
  export function useSelectedItemText(currentCollection, selectedItemIds) {
7
18
  const {
@@ -25,8 +36,78 @@ export function useSelectedItemText(currentCollection, selectedItemIds) {
25
36
  }, [currentCollection.items, formatMessage, selectedItemIds]);
26
37
  }
27
38
 
39
+ // Check if the field value is empty.
40
+ // Note: 0 doesn't represent empty here because of float type field
41
+ export function isEmptyValue(value) {
42
+ if (isNil(value)) {
43
+ return true;
44
+ }
45
+
46
+ // date, string, enum
47
+ if (value === '') {
48
+ return true;
49
+ }
50
+
51
+ // multiSelect
52
+ if (Array.isArray(value) && value.length === 0) {
53
+ return true;
54
+ }
55
+
56
+ // float
57
+ if (Number.isNaN(value)) {
58
+ return true;
59
+ }
60
+ return false;
61
+ }
62
+
63
+ // Check if the field values are equal based on the field types
64
+ export function areFieldValuesEqual(value1, value2) {
65
+ if (isEmptyValue(value1) && isEmptyValue(value2)) {
66
+ return true;
67
+ }
68
+
69
+ // Handle multiSelect arrays comparison
70
+ if (Array.isArray(value1) && Array.isArray(value2)) {
71
+ return xor(value1, value2).length === 0;
72
+ }
73
+ return value1 === value2;
74
+ }
75
+
76
+ // Return default form value by field type
77
+ function getDefaultValueByFieldType(fieldType) {
78
+ if (fieldType === 'date' || fieldType === 'enum' || fieldType === 'float' || fieldType === 'string') {
79
+ return '';
80
+ }
81
+ if (fieldType === 'multiSelect') {
82
+ return [];
83
+ }
84
+ return undefined;
85
+ }
86
+
87
+ // Set the field value in Metadata Form based on the field type
88
+ function getFieldValue(fieldType, fieldValue) {
89
+ if (isNil(fieldValue)) {
90
+ return getDefaultValueByFieldType(fieldType);
91
+ }
92
+ return fieldValue;
93
+ }
94
+
95
+ // Check if the field value in Metadata Form is multi-values such as "Multiple values"
96
+ export function isMultiValuesField(fieldType, fieldValue) {
97
+ if (fieldType === 'multiSelect') {
98
+ return Array.isArray(fieldValue) && fieldValue.length === 1 && fieldValue[0] === MULTI_VALUE_DEFAULT_VALUE;
99
+ }
100
+ if (fieldType === 'enum') {
101
+ return fieldValue === MULTI_VALUE_DEFAULT_VALUE;
102
+ }
103
+ return false;
104
+ }
105
+
28
106
  // Get template instance based on metadata template and selected items
29
- export function getTemplateInstance(metadataTemplate, selectedItems) {
107
+ export function useTemplateInstance(metadataTemplate, selectedItems, isEditing) {
108
+ const {
109
+ formatMessage
110
+ } = useIntl();
30
111
  const {
31
112
  displayName,
32
113
  fields,
@@ -43,16 +124,63 @@ export function getTemplateInstance(metadataTemplate, selectedItems) {
43
124
  key,
44
125
  options,
45
126
  type: fieldType
46
- }) => ({
47
- displayName: fieldDisplayName,
48
- hidden: fieldHidden,
49
- id: fieldId,
50
- key,
51
- options,
52
- type: fieldType,
53
- // TODO: Add support for multiple selected items
54
- value: selectedItems[0].metadata[scope][templateKey][key]
55
- }));
127
+ }) => {
128
+ const defaultItemField = {
129
+ displayName: fieldDisplayName,
130
+ hidden: fieldHidden,
131
+ id: fieldId,
132
+ key,
133
+ options,
134
+ type: fieldType,
135
+ value: getFieldValue(fieldType, undefined)
136
+ };
137
+ const firstSelectedItem = selectedItems[0];
138
+ const firstSelectedItemFieldValue = firstSelectedItem.metadata[scope][templateKey][key];
139
+
140
+ // Case 1: Single selected item
141
+ if (selectedItems.length <= 1) {
142
+ return _objectSpread(_objectSpread({}, defaultItemField), {}, {
143
+ value: firstSelectedItemFieldValue
144
+ });
145
+ }
146
+
147
+ // Case 2.1: Multiple selected items, but all have the same initial value
148
+ const allItemsHaveSameInitialValue = selectedItems.every(selectedItem => areFieldValuesEqual(selectedItem.metadata[scope][templateKey][key], firstSelectedItemFieldValue));
149
+ if (allItemsHaveSameInitialValue) {
150
+ return _objectSpread(_objectSpread({}, defaultItemField), {}, {
151
+ value: getFieldValue(fieldType, firstSelectedItemFieldValue)
152
+ });
153
+ }
154
+
155
+ // Case 2.2: Multiple selected items, but some have different initial values
156
+ // Case 2.2.1: Edit Mode
157
+ if (isEditing) {
158
+ let fieldValue = getFieldValue(fieldType, undefined);
159
+ // Add MultiValue Option if the field is multiSelect or enum
160
+ if (fieldType === 'multiSelect' || fieldType === 'enum') {
161
+ fieldValue = fieldType === 'enum' ? MULTI_VALUE_DEFAULT_VALUE : [MULTI_VALUE_DEFAULT_VALUE];
162
+ const multiValueOption = options?.find(option => option.key === MULTI_VALUE_DEFAULT_VALUE);
163
+ if (!multiValueOption) {
164
+ options?.push(MULTI_VALUE_DEFAULT_OPTION);
165
+ }
166
+ }
167
+ return _objectSpread(_objectSpread({}, defaultItemField), {}, {
168
+ value: fieldValue
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Case: 2.2.2 View Mode
174
+ *
175
+ * We want to show "Multiple values" label for multiple dates across files selection.
176
+ * We use fragment here to bypass check in shared feature.
177
+ * This feature tries to parse string as date if the string is passed as value.
178
+ */
179
+ const multipleValuesText = formatMessage(messages.multipleValues);
180
+ return _objectSpread(_objectSpread({}, defaultItemField), {}, {
181
+ value: /*#__PURE__*/React.createElement(React.Fragment, null, multipleValuesText)
182
+ });
183
+ });
56
184
  return {
57
185
  canEdit: true,
58
186
  displayName,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","names":["useMemo","useIntl","messages","useSelectedItemText","currentCollection","selectedItemIds","formatMessage","selectedCount","items","length","size","selectedKey","id","values","next","value","selectedItem","find","item","name","numFilesSelected","numSelected","getTemplateInstance","metadataTemplate","selectedItems","displayName","fields","hidden","scope","templateKey","type","selectedItemsFields","map","fieldDisplayName","fieldHidden","fieldId","key","options","fieldType","metadata","canEdit"],"sources":["../../../src/elements/content-explorer/utils.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { useIntl } from 'react-intl';\n\nimport type { MetadataTemplate } from '@box/metadata-editor';\nimport type { Selection } from 'react-aria-components';\nimport type { BoxItem, Collection } from '../../common/types/core';\n\nimport messages from '../common/messages';\n\n// Get selected item text\nexport function useSelectedItemText(currentCollection: Collection, selectedItemIds: Selection): string {\n const { formatMessage } = useIntl();\n\n return useMemo(() => {\n const selectedCount = selectedItemIds === 'all' ? currentCollection.items.length : selectedItemIds.size;\n if (selectedCount === 0) return '';\n\n // Case 1: Single selected item - show item name\n if (selectedCount === 1) {\n const selectedKey =\n selectedItemIds === 'all' ? currentCollection.items[0].id : selectedItemIds.values().next().value;\n const selectedItem = currentCollection.items.find(item => item.id === selectedKey);\n return selectedItem?.name ?? '';\n }\n\n // Case 2: Multiple selected items - show count\n return formatMessage(messages.numFilesSelected, { numSelected: selectedCount });\n }, [currentCollection.items, formatMessage, selectedItemIds]);\n}\n\n// Get template instance based on metadata template and selected items\nexport function getTemplateInstance(metadataTemplate: MetadataTemplate, selectedItems: BoxItem[]) {\n const { displayName, fields, hidden, id, scope, templateKey, type } = metadataTemplate;\n\n const selectedItemsFields = fields.map(\n ({ displayName: fieldDisplayName, hidden: fieldHidden, id: fieldId, key, options, type: fieldType }) => ({\n displayName: fieldDisplayName,\n hidden: fieldHidden,\n id: fieldId,\n key,\n options,\n type: fieldType,\n // TODO: Add support for multiple selected items\n value: selectedItems[0].metadata[scope][templateKey][key],\n }),\n );\n\n return {\n canEdit: true,\n displayName,\n hidden,\n id,\n fields: selectedItemsFields,\n scope,\n templateKey,\n type,\n };\n}\n"],"mappings":"AAAA,SAASA,OAAO,QAAQ,OAAO;AAC/B,SAASC,OAAO,QAAQ,YAAY;AAMpC,OAAOC,QAAQ,MAAM,oBAAoB;;AAEzC;AACA,OAAO,SAASC,mBAAmBA,CAACC,iBAA6B,EAAEC,eAA0B,EAAU;EACnG,MAAM;IAAEC;EAAc,CAAC,GAAGL,OAAO,CAAC,CAAC;EAEnC,OAAOD,OAAO,CAAC,MAAM;IACjB,MAAMO,aAAa,GAAGF,eAAe,KAAK,KAAK,GAAGD,iBAAiB,CAACI,KAAK,CAACC,MAAM,GAAGJ,eAAe,CAACK,IAAI;IACvG,IAAIH,aAAa,KAAK,CAAC,EAAE,OAAO,EAAE;;IAElC;IACA,IAAIA,aAAa,KAAK,CAAC,EAAE;MACrB,MAAMI,WAAW,GACbN,eAAe,KAAK,KAAK,GAAGD,iBAAiB,CAACI,KAAK,CAAC,CAAC,CAAC,CAACI,EAAE,GAAGP,eAAe,CAACQ,MAAM,CAAC,CAAC,CAACC,IAAI,CAAC,CAAC,CAACC,KAAK;MACrG,MAAMC,YAAY,GAAGZ,iBAAiB,CAACI,KAAK,CAACS,IAAI,CAACC,IAAI,IAAIA,IAAI,CAACN,EAAE,KAAKD,WAAW,CAAC;MAClF,OAAOK,YAAY,EAAEG,IAAI,IAAI,EAAE;IACnC;;IAEA;IACA,OAAOb,aAAa,CAACJ,QAAQ,CAACkB,gBAAgB,EAAE;MAAEC,WAAW,EAAEd;IAAc,CAAC,CAAC;EACnF,CAAC,EAAE,CAACH,iBAAiB,CAACI,KAAK,EAAEF,aAAa,EAAED,eAAe,CAAC,CAAC;AACjE;;AAEA;AACA,OAAO,SAASiB,mBAAmBA,CAACC,gBAAkC,EAAEC,aAAwB,EAAE;EAC9F,MAAM;IAAEC,WAAW;IAAEC,MAAM;IAAEC,MAAM;IAAEf,EAAE;IAAEgB,KAAK;IAAEC,WAAW;IAAEC;EAAK,CAAC,GAAGP,gBAAgB;EAEtF,MAAMQ,mBAAmB,GAAGL,MAAM,CAACM,GAAG,CAClC,CAAC;IAAEP,WAAW,EAAEQ,gBAAgB;IAAEN,MAAM,EAAEO,WAAW;IAAEtB,EAAE,EAAEuB,OAAO;IAAEC,GAAG;IAAEC,OAAO;IAAEP,IAAI,EAAEQ;EAAU,CAAC,MAAM;IACrGb,WAAW,EAAEQ,gBAAgB;IAC7BN,MAAM,EAAEO,WAAW;IACnBtB,EAAE,EAAEuB,OAAO;IACXC,GAAG;IACHC,OAAO;IACPP,IAAI,EAAEQ,SAAS;IACf;IACAvB,KAAK,EAAES,aAAa,CAAC,CAAC,CAAC,CAACe,QAAQ,CAACX,KAAK,CAAC,CAACC,WAAW,CAAC,CAACO,GAAG;EAC5D,CAAC,CACL,CAAC;EAED,OAAO;IACHI,OAAO,EAAE,IAAI;IACbf,WAAW;IACXE,MAAM;IACNf,EAAE;IACFc,MAAM,EAAEK,mBAAmB;IAC3BH,KAAK;IACLC,WAAW;IACXC;EACJ,CAAC;AACL","ignoreList":[]}
1
+ {"version":3,"file":"utils.js","names":["React","useMemo","useIntl","isNil","xor","MULTI_VALUE_DEFAULT_OPTION","MULTI_VALUE_DEFAULT_VALUE","messages","useSelectedItemText","currentCollection","selectedItemIds","formatMessage","selectedCount","items","length","size","selectedKey","id","values","next","value","selectedItem","find","item","name","numFilesSelected","numSelected","isEmptyValue","Array","isArray","Number","isNaN","areFieldValuesEqual","value1","value2","getDefaultValueByFieldType","fieldType","undefined","getFieldValue","fieldValue","isMultiValuesField","useTemplateInstance","metadataTemplate","selectedItems","isEditing","displayName","fields","hidden","scope","templateKey","type","selectedItemsFields","map","fieldDisplayName","fieldHidden","fieldId","key","options","defaultItemField","firstSelectedItem","firstSelectedItemFieldValue","metadata","_objectSpread","allItemsHaveSameInitialValue","every","multiValueOption","option","push","multipleValuesText","multipleValues","createElement","Fragment","canEdit"],"sources":["../../../src/elements/content-explorer/utils.ts"],"sourcesContent":["import React, { useMemo } from 'react';\nimport { useIntl } from 'react-intl';\nimport isNil from 'lodash/isNil';\nimport xor from 'lodash/xor';\n\nimport {\n MULTI_VALUE_DEFAULT_OPTION,\n MULTI_VALUE_DEFAULT_VALUE,\n type MetadataTemplate,\n type MetadataFormFieldValue,\n} from '@box/metadata-editor';\nimport type { MetadataFieldType } from '@box/metadata-view';\nimport type { Selection } from 'react-aria-components';\nimport type { BoxItem, Collection } from '../../common/types/core';\n\nimport messages from '../common/messages';\n\n// Specific type for metadata field value in the item\n// Note: Item doesn't have field value in metadata object if that field is not set, so the value will be undefined in this case\ntype ItemMetadataFieldValue = string | number | Array<string> | null | undefined;\n\n// Get selected item text\nexport function useSelectedItemText(currentCollection: Collection, selectedItemIds: Selection): string {\n const { formatMessage } = useIntl();\n\n return useMemo(() => {\n const selectedCount = selectedItemIds === 'all' ? currentCollection.items.length : selectedItemIds.size;\n if (selectedCount === 0) return '';\n\n // Case 1: Single selected item - show item name\n if (selectedCount === 1) {\n const selectedKey =\n selectedItemIds === 'all' ? currentCollection.items[0].id : selectedItemIds.values().next().value;\n const selectedItem = currentCollection.items.find(item => item.id === selectedKey);\n return selectedItem?.name ?? '';\n }\n\n // Case 2: Multiple selected items - show count\n return formatMessage(messages.numFilesSelected, { numSelected: selectedCount });\n }, [currentCollection.items, formatMessage, selectedItemIds]);\n}\n\n// Check if the field value is empty.\n// Note: 0 doesn't represent empty here because of float type field\nexport function isEmptyValue(value: ItemMetadataFieldValue) {\n if (isNil(value)) {\n return true;\n }\n\n // date, string, enum\n if (value === '') {\n return true;\n }\n\n // multiSelect\n if (Array.isArray(value) && value.length === 0) {\n return true;\n }\n\n // float\n if (Number.isNaN(value)) {\n return true;\n }\n\n return false;\n}\n\n// Check if the field values are equal based on the field types\nexport function areFieldValuesEqual(value1: ItemMetadataFieldValue, value2: ItemMetadataFieldValue) {\n if (isEmptyValue(value1) && isEmptyValue(value2)) {\n return true;\n }\n\n // Handle multiSelect arrays comparison\n if (Array.isArray(value1) && Array.isArray(value2)) {\n return xor(value1, value2).length === 0;\n }\n\n return value1 === value2;\n}\n\n// Return default form value by field type\nfunction getDefaultValueByFieldType(fieldType: MetadataFieldType) {\n if (fieldType === 'date' || fieldType === 'enum' || fieldType === 'float' || fieldType === 'string') {\n return '';\n }\n if (fieldType === 'multiSelect') {\n return [];\n }\n return undefined;\n}\n\n// Set the field value in Metadata Form based on the field type\nfunction getFieldValue(fieldType: MetadataFieldType, fieldValue: ItemMetadataFieldValue) {\n if (isNil(fieldValue)) {\n return getDefaultValueByFieldType(fieldType);\n }\n return fieldValue;\n}\n\n// Check if the field value in Metadata Form is multi-values such as \"Multiple values\"\nexport function isMultiValuesField(fieldType: MetadataFieldType, fieldValue: MetadataFormFieldValue) {\n if (fieldType === 'multiSelect') {\n return Array.isArray(fieldValue) && fieldValue.length === 1 && fieldValue[0] === MULTI_VALUE_DEFAULT_VALUE;\n }\n if (fieldType === 'enum') {\n return fieldValue === MULTI_VALUE_DEFAULT_VALUE;\n }\n return false;\n}\n\n// Get template instance based on metadata template and selected items\nexport function useTemplateInstance(metadataTemplate: MetadataTemplate, selectedItems: BoxItem[], isEditing: boolean) {\n const { formatMessage } = useIntl();\n const { displayName, fields, hidden, id, scope, templateKey, type } = metadataTemplate;\n\n const selectedItemsFields = fields.map(\n ({ displayName: fieldDisplayName, hidden: fieldHidden, id: fieldId, key, options, type: fieldType }) => {\n const defaultItemField = {\n displayName: fieldDisplayName,\n hidden: fieldHidden,\n id: fieldId,\n key,\n options,\n type: fieldType,\n value: getFieldValue(fieldType as MetadataFieldType, undefined),\n };\n\n const firstSelectedItem = selectedItems[0];\n const firstSelectedItemFieldValue = firstSelectedItem.metadata[scope][templateKey][key];\n\n // Case 1: Single selected item\n if (selectedItems.length <= 1) {\n return {\n ...defaultItemField,\n value: firstSelectedItemFieldValue,\n };\n }\n\n // Case 2.1: Multiple selected items, but all have the same initial value\n const allItemsHaveSameInitialValue = selectedItems.every(selectedItem =>\n areFieldValuesEqual(selectedItem.metadata[scope][templateKey][key], firstSelectedItemFieldValue),\n );\n\n if (allItemsHaveSameInitialValue) {\n return {\n ...defaultItemField,\n value: getFieldValue(fieldType as MetadataFieldType, firstSelectedItemFieldValue),\n };\n }\n\n // Case 2.2: Multiple selected items, but some have different initial values\n // Case 2.2.1: Edit Mode\n if (isEditing) {\n let fieldValue = getFieldValue(fieldType as MetadataFieldType, undefined);\n // Add MultiValue Option if the field is multiSelect or enum\n if (fieldType === 'multiSelect' || fieldType === 'enum') {\n fieldValue = fieldType === 'enum' ? MULTI_VALUE_DEFAULT_VALUE : [MULTI_VALUE_DEFAULT_VALUE];\n const multiValueOption = options?.find(option => option.key === MULTI_VALUE_DEFAULT_VALUE);\n if (!multiValueOption) {\n options?.push(MULTI_VALUE_DEFAULT_OPTION);\n }\n }\n return {\n ...defaultItemField,\n value: fieldValue,\n };\n }\n\n /**\n * Case: 2.2.2 View Mode\n *\n * We want to show \"Multiple values\" label for multiple dates across files selection.\n * We use fragment here to bypass check in shared feature.\n * This feature tries to parse string as date if the string is passed as value.\n */\n const multipleValuesText = formatMessage(messages.multipleValues);\n return {\n ...defaultItemField,\n value: React.createElement(React.Fragment, null, multipleValuesText),\n };\n },\n );\n\n return {\n canEdit: true,\n displayName,\n hidden,\n id,\n fields: selectedItemsFields,\n scope,\n templateKey,\n type,\n };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -2,7 +2,8 @@
2
2
  import 'regenerator-runtime/runtime';
3
3
  import React, { Component } from 'react';
4
4
  import { AxiosRequestConfig, AxiosResponse } from 'axios';
5
- import type { Selection } from 'react-aria-components';
5
+ import type { Key, Selection } from 'react-aria-components';
6
+ import type { MetadataTemplateField } from '@box/metadata-editor';
6
7
  import API from '../../api';
7
8
  import MetadataQueryAPIHelper from '../../features/metadata-based-view/MetadataQueryAPIHelper';
8
9
  import LocalStore from '../../utils/LocalStore';
@@ -68,7 +69,7 @@ export interface ContentExplorerProps {
68
69
  rootFolderId?: string;
69
70
  sharedLink?: string;
70
71
  sharedLinkPassword?: string;
71
- sortBy?: SortBy;
72
+ sortBy?: SortBy | Key;
72
73
  sortDirection?: SortDirection;
73
74
  staticHost?: string;
74
75
  staticPath?: string;
@@ -203,6 +204,13 @@ declare class ContentExplorer extends Component<ContentExplorerProps, State> {
203
204
  * @return {void}
204
205
  */
205
206
  showMetadataQueryResults(): void;
207
+ /**
208
+ * Update selected items' metadata instances based on original and new field values in the metadata instance form
209
+ *
210
+ * @private
211
+ * @return {void}
212
+ */
213
+ updateMetadataV2: (items: BoxItem[], operations: JSONPatchOperations, templateOldFields: MetadataTemplateField[], templateNewFields: MetadataTemplateField[], successCallback: () => void, errorCallback: ErrorCallback) => Promise<void>;
206
214
  /**
207
215
  * Resets the collection so that the loading bar starts showing
208
216
  *
@@ -333,7 +341,7 @@ declare class ContentExplorer extends Component<ContentExplorerProps, State> {
333
341
  * @param {string} sortDirection - sort direction
334
342
  * @return {void}
335
343
  */
336
- sort: (sortBy: SortBy, sortDirection: SortDirection) => void;
344
+ sort: (sortBy: SortBy | Key, sortDirection: SortDirection) => void;
337
345
  /**
338
346
  * Sets state with currentCollection updated to have `items.selected` properties
339
347
  * set according to the given selected param. Also updates the selected item in the
@@ -1,8 +1,9 @@
1
+ import type { MetadataTemplateField } from '@box/metadata-editor';
1
2
  import API from '../../api';
2
3
  import type { MetadataQuery as MetadataQueryType, MetadataQueryResponseData } from '../../common/types/metadataQueries';
3
4
  import type { MetadataTemplateSchemaResponse, MetadataTemplate, MetadataFieldValue } from '../../common/types/metadata';
4
5
  import type { ElementsXhrError } from '../../common/types/api';
5
- import type { Collection } from '../../common/types/core';
6
+ import type { Collection, BoxItem } from '../../common/types/core';
6
7
  type SuccessCallback = (metadataQueryCollection: Collection, metadataTemplate: MetadataTemplate) => void;
7
8
  type ErrorCallback = (e: ElementsXhrError) => void;
8
9
  export default class MetadataQueryAPIHelper {
@@ -18,9 +19,18 @@ export default class MetadataQueryAPIHelper {
18
19
  flattenMetadata: (metadata?: MetadataType) => MetadataType;
19
20
  getDataWithTypes: (templateSchemaResponse?: MetadataTemplateSchemaResponse) => Collection;
20
21
  getTemplateSchemaInfo: (data: MetadataQueryResponseData) => Promise<MetadataTemplateSchemaResponse | void>;
22
+ /**
23
+ * Generate operations for all fields update in the metadata sidepanel
24
+ *
25
+ * @private
26
+ * @return {JSONPatchOperations}
27
+ */
28
+ generateOperations: (item: BoxItem, templateOldFields: MetadataTemplateField[], templateNewFields: MetadataTemplateField[]) => JSONPatchOperations;
21
29
  queryMetadata: () => Promise<MetadataQueryResponseData>;
22
30
  fetchMetadataQueryResults: (metadataQuery: MetadataQueryType, successCallback: SuccessCallback, errorCallback: ErrorCallback) => Promise<void>;
23
31
  updateMetadata: (file: BoxItem, field: string, oldValue: MetadataFieldValue | null, newValue: MetadataFieldValue | null, successCallback: () => void, errorCallback: ErrorCallback) => Promise<void>;
32
+ updateMetadataWithOperations: (item: BoxItem, operations: JSONPatchOperations, successCallback: () => void, errorCallback: ErrorCallback) => Promise<void>;
33
+ bulkUpdateMetadata: (items: BoxItem[], templateOldFields: MetadataTemplateField[], templateNewFields: MetadataTemplateField[], successCallback: () => void, errorCallback: ErrorCallback) => Promise<void>;
24
34
  /**
25
35
  * Verify that the metadata query has required fields and update it if necessary
26
36
  * For a file item, default fields included in the response are "type", "id", "etag"
@@ -1,13 +1,16 @@
1
1
  import React from 'react';
2
+ import { JSONPatchOperations, type MetadataTemplateField } from '@box/metadata-editor';
2
3
  import type { Selection } from 'react-aria-components';
3
- import type { Collection } from '../../common/types/core';
4
+ import type { BoxItem, Collection } from '../../common/types/core';
4
5
  import type { MetadataTemplate } from '../../common/types/metadata';
5
6
  import './MetadataSidePanel.scss';
6
7
  export interface MetadataSidePanelProps {
7
8
  currentCollection: Collection;
8
- onClose: () => void;
9
9
  metadataTemplate: MetadataTemplate;
10
+ onClose: () => void;
11
+ onUpdate: (items: BoxItem[], operations: JSONPatchOperations, templateOldFields: MetadataTemplateField[], templateNewFields: MetadataTemplateField[], successCallback: () => void, errorCallback: ErrorCallback) => Promise<void>;
12
+ refreshCollection: () => void;
10
13
  selectedItemIds: Selection;
11
14
  }
12
- declare const MetadataSidePanel: ({ currentCollection, onClose, selectedItemIds, metadataTemplate, }: MetadataSidePanelProps) => React.JSX.Element;
15
+ declare const MetadataSidePanel: ({ currentCollection, metadataTemplate, onClose, onUpdate, refreshCollection, selectedItemIds, }: MetadataSidePanelProps) => React.JSX.Element;
13
16
  export default MetadataSidePanel;
@@ -1,6 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import type { EnumType, MetadataFormFieldValue } from '@box/metadata-filter';
3
3
  import { type MetadataViewProps } from '@box/metadata-view';
4
+ import { type Key } from '@react-types/shared';
4
5
  import type { Collection } from '../../common/types/core';
5
6
  import type { MetadataTemplate } from '../../common/types/metadata';
6
7
  type EnumToStringArray<T> = T extends EnumType ? string[] : T;
@@ -16,6 +17,7 @@ export interface MetadataViewContainerProps extends Omit<MetadataViewProps, 'ite
16
17
  actionBarProps?: ActionBarProps;
17
18
  currentCollection: Collection;
18
19
  metadataTemplate: MetadataTemplate;
20
+ onSortChange?: (sortBy: Key, sortDirection: string) => void;
19
21
  }
20
- declare const MetadataViewContainer: ({ actionBarProps, columns, currentCollection, metadataTemplate, ...rest }: MetadataViewContainerProps) => React.JSX.Element;
22
+ declare const MetadataViewContainer: ({ actionBarProps, columns, currentCollection, metadataTemplate, onSortChange: onSortChangeInternal, ...rest }: MetadataViewContainerProps) => React.JSX.Element;
21
23
  export default MetadataViewContainer;
@@ -7,6 +7,7 @@ export declare const metadataViewV2WithCustomActions: Story;
7
7
  export declare const metadataViewV2WithInitialFilterValues: Story;
8
8
  export declare const sidePanelOpenWithSingleItemSelected: Story;
9
9
  export declare const metadataViewV2WithBulkItemActionMenuShowsItemActionMenu: Story;
10
+ export declare const sidePanelOpenWithMultipleItemsSelected: Story;
10
11
  declare const meta: Meta<typeof ContentExplorer>;
11
12
  type Story = StoryObj<typeof meta>;
12
13
  export default meta;
@@ -1,22 +1,28 @@
1
- import type { MetadataTemplate } from '@box/metadata-editor';
1
+ import { type MetadataTemplate, type MetadataFormFieldValue } from '@box/metadata-editor';
2
+ import type { MetadataFieldType } from '@box/metadata-view';
2
3
  import type { Selection } from 'react-aria-components';
3
4
  import type { BoxItem, Collection } from '../../common/types/core';
5
+ type ItemMetadataFieldValue = string | number | Array<string> | null | undefined;
4
6
  export declare function useSelectedItemText(currentCollection: Collection, selectedItemIds: Selection): string;
5
- export declare function getTemplateInstance(metadataTemplate: MetadataTemplate, selectedItems: BoxItem[]): {
7
+ export declare function isEmptyValue(value: ItemMetadataFieldValue): boolean;
8
+ export declare function areFieldValuesEqual(value1: ItemMetadataFieldValue, value2: ItemMetadataFieldValue): boolean;
9
+ export declare function isMultiValuesField(fieldType: MetadataFieldType, fieldValue: MetadataFormFieldValue): boolean;
10
+ export declare function useTemplateInstance(metadataTemplate: MetadataTemplate, selectedItems: BoxItem[], isEditing: boolean): {
6
11
  canEdit: boolean;
7
12
  displayName: string;
8
13
  hidden: boolean;
9
14
  id: string;
10
15
  fields: {
16
+ value: any;
11
17
  displayName: string;
12
18
  hidden: boolean;
13
19
  id: string;
14
20
  key: string;
15
21
  options: import("@box/metadata-editor").MetadataTemplateFieldOption[];
16
22
  type: import("@box/metadata-editor").MetadataTemplateFieldType;
17
- value: any;
18
23
  }[];
19
24
  scope: string;
20
25
  templateKey: string;
21
26
  type: string;
22
27
  };
28
+ export {};
package/i18n/bn-IN.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "দুঃখিত, এই ইমেজটি দেখাতে আমরা সমস্যার সম্মুখীন হচ্ছি।",
292
292
  "be.messageCenter.product": "পণ্য",
293
293
  "be.messageCenter.title": "নতুন কী",
294
+ "be.metadataUpdateErrorNotification": "Unable to save changes. Please try again.",
295
+ "be.metadataUpdateSuccessNotification": " {numSelected, plural, =1 {1 document updated} other {# documents updated} } ",
294
296
  "be.modifiedDate": "সংশোধিত {date}",
295
297
  "be.modifiedDateBy": "{name}-এর দ্বারা {date}-এ সংশোধিত",
296
298
  "be.moreOptions": "আরও বিকল্প",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "নাম: A → Z",
298
301
  "be.nameDESC": "নাম: Z → A",
299
302
  "be.nameDate": "{name}-এর দ্বারা {date}",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "এই দক্ষতাটি চালনা করার সময় বা এর ডেটা প্রাপ্তির সময় কিছু ত্রুটি ঘটেছে।",
418
421
  "be.sort": "বাছাই করুন",
419
422
  "be.statusSkill": "স্থিতি",
423
+ "be.success": "Success",
420
424
  "be.today": "আজ",
421
425
  "be.topicsSkill": "টপিকগুলি",
422
426
  "be.transcriptEdit": "সম্পাদনা করতে যে কোনও নির্বাচন ক্লিক করুন।",
@@ -966,6 +966,10 @@ boxui.categorySelector.label.more = আরও
966
966
  boxui.checkboxTooltip.iconInfoText = তথ্য
967
967
  # Button to add classification on an item
968
968
  boxui.classification.add = যোগ করুন
969
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
970
+ boxui.classification.appliedByBoxAi = Box AI
971
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
972
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
973
  # Header for classification section in sidebar
970
974
  boxui.classification.classification = শ্রেণিবিভাজন
971
975
  # Classification label color name as dark blue
package/i18n/da-DK.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "Vi har desværre problemer med at vise dette billede.",
292
292
  "be.messageCenter.product": "Produkt",
293
293
  "be.messageCenter.title": "Nyheder",
294
+ "be.metadataUpdateErrorNotification": "Unable to save changes. Please try again.",
295
+ "be.metadataUpdateSuccessNotification": " {numSelected, plural, =1 {1 document updated} other {# documents updated} } ",
294
296
  "be.modifiedDate": "Ændret {date}",
295
297
  "be.modifiedDateBy": "Ændret {date} af {name}",
296
298
  "be.moreOptions": "Flere muligheder",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "Navn: A → Å",
298
301
  "be.nameDESC": "Navn: Å → A",
299
302
  "be.nameDate": "{date} af {name}",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "Der opstod et problem under kørsel af denne færdighed eller i forbindelse med hentning af tilhørende data.",
418
421
  "be.sort": "Sortér",
419
422
  "be.statusSkill": "Status",
423
+ "be.success": "Success",
420
424
  "be.today": "i dag",
421
425
  "be.topicsSkill": "Emner",
422
426
  "be.transcriptEdit": "Klik på et afsnit for at redigere.",
@@ -966,6 +966,10 @@ boxui.categorySelector.label.more = Mere
966
966
  boxui.checkboxTooltip.iconInfoText = Oplysninger
967
967
  # Button to add classification on an item
968
968
  boxui.classification.add = Tilføj
969
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
970
+ boxui.classification.appliedByBoxAi = Box AI
971
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
972
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
973
  # Header for classification section in sidebar
970
974
  boxui.classification.classification = Klassificering
971
975
  # Classification label color name as dark blue
package/i18n/de-DE.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "Leider kann dieses Bild derzeit nicht angezeigt werden.",
292
292
  "be.messageCenter.product": "Produkt",
293
293
  "be.messageCenter.title": "Neuerungen",
294
+ "be.metadataUpdateErrorNotification": "Unable to save changes. Please try again.",
295
+ "be.metadataUpdateSuccessNotification": " {numSelected, plural, =1 {1 document updated} other {# documents updated} } ",
294
296
  "be.modifiedDate": "Geändert am {date}",
295
297
  "be.modifiedDateBy": "Geändert am {date} von {name}",
296
298
  "be.moreOptions": "Weitere Optionen",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "Name: A → Z",
298
301
  "be.nameDESC": "Name: Z → A",
299
302
  "be.nameDate": "Am {date} von {name}",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "Beim Ausführen dieses Skills oder Abrufen seiner Daten ist ein Fehler aufgetreten.",
418
421
  "be.sort": "Sortieren",
419
422
  "be.statusSkill": "Status",
423
+ "be.success": "Success",
420
424
  "be.today": "heute",
421
425
  "be.topicsSkill": "Themen",
422
426
  "be.transcriptEdit": "Klicken Sie auf einen beliebigen Abschnitt, um ihn zu bearbeiten.",
@@ -483,7 +487,7 @@ export default {
483
487
  "boxui.categorySelector.label.more": "Mehr",
484
488
  "boxui.checkboxTooltip.iconInfoText": "Informationen",
485
489
  "boxui.classification.add": "Hinzufügen",
486
- "boxui.classification.appliedByBoxAi": "Box AI",
490
+ "boxui.classification.appliedByBoxAi": "Box-KI",
487
491
  "boxui.classification.appliedByBoxAiOnDate": "Box AI on {modifiedAt}",
488
492
  "boxui.classification.classification": "Klassifizierung",
489
493
  "boxui.classification.classificationDarkBlue": "Dunkelblau",
@@ -966,6 +966,10 @@ boxui.categorySelector.label.more = Mehr
966
966
  boxui.checkboxTooltip.iconInfoText = Informationen
967
967
  # Button to add classification on an item
968
968
  boxui.classification.add = Hinzufügen
969
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
970
+ boxui.classification.appliedByBoxAi = Box-KI
971
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
972
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
973
  # Header for classification section in sidebar
970
974
  boxui.classification.classification = Klassifizierung
971
975
  # Classification label color name as dark blue
package/i18n/en-AU.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "Sorry, we're having trouble showing this image.",
292
292
  "be.messageCenter.product": "Product",
293
293
  "be.messageCenter.title": "What's New",
294
+ "be.metadataUpdateErrorNotification": "Unable to save changes. Please try again.",
295
+ "be.metadataUpdateSuccessNotification": " {numSelected, plural, =1 {1 document updated} other {# documents updated} } ",
294
296
  "be.modifiedDate": "Modified {date}",
295
297
  "be.modifiedDateBy": "Modified {date} by {name}",
296
298
  "be.moreOptions": "More Options",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "Name: A → Z",
298
301
  "be.nameDESC": "Name: Z → A",
299
302
  "be.nameDate": "{date} by {name}",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "Something went wrong while running this skill or fetching its data.",
418
421
  "be.sort": "Sort",
419
422
  "be.statusSkill": "Status",
423
+ "be.success": "Success",
420
424
  "be.today": "today",
421
425
  "be.topicsSkill": "Topics",
422
426
  "be.transcriptEdit": "Click any section to edit.",
@@ -966,6 +966,10 @@ boxui.categorySelector.label.more = More
966
966
  boxui.checkboxTooltip.iconInfoText = Info
967
967
  # Button to add classification on an item
968
968
  boxui.classification.add = Add
969
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
970
+ boxui.classification.appliedByBoxAi = Box AI
971
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
972
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
973
  # Header for classification section in sidebar
970
974
  boxui.classification.classification = Classification
971
975
  # Classification label color name as dark blue