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

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 (113) hide show
  1. package/dist/explorer.css +1 -1
  2. package/dist/explorer.js +1 -1
  3. package/dist/openwith.js +1 -1
  4. package/dist/picker.js +1 -1
  5. package/dist/preview.js +1 -1
  6. package/dist/sharing.js +1 -1
  7. package/dist/sidebar.js +1 -1
  8. package/dist/uploader.js +1 -1
  9. package/es/api/Metadata.js +98 -13
  10. package/es/api/Metadata.js.flow +110 -12
  11. package/es/api/Metadata.js.map +1 -1
  12. package/es/elements/common/messages.js +16 -0
  13. package/es/elements/common/messages.js.flow +25 -0
  14. package/es/elements/common/messages.js.map +1 -1
  15. package/es/elements/content-explorer/Content.js +5 -2
  16. package/es/elements/content-explorer/Content.js.map +1 -1
  17. package/es/elements/content-explorer/ContentExplorer.js +31 -6
  18. package/es/elements/content-explorer/ContentExplorer.js.map +1 -1
  19. package/es/elements/content-explorer/MetadataQueryAPIHelper.js +164 -10
  20. package/es/elements/content-explorer/MetadataQueryAPIHelper.js.map +1 -1
  21. package/es/elements/content-explorer/MetadataQueryBuilder.js +115 -0
  22. package/es/elements/content-explorer/MetadataQueryBuilder.js.map +1 -0
  23. package/es/elements/content-explorer/MetadataSidePanel.js +40 -14
  24. package/es/elements/content-explorer/MetadataSidePanel.js.map +1 -1
  25. package/es/elements/content-explorer/MetadataViewContainer.js +133 -36
  26. package/es/elements/content-explorer/MetadataViewContainer.js.map +1 -1
  27. package/es/elements/content-explorer/stories/MetadataView.stories.js +3 -25
  28. package/es/elements/content-explorer/stories/MetadataView.stories.js.map +1 -1
  29. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +65 -29
  30. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
  31. package/es/elements/content-explorer/utils.js +140 -12
  32. package/es/elements/content-explorer/utils.js.map +1 -1
  33. package/es/src/elements/common/__mocks__/mockMetadata.d.ts +8 -24
  34. package/es/src/elements/content-explorer/Content.d.ts +4 -3
  35. package/es/src/elements/content-explorer/ContentExplorer.d.ts +19 -6
  36. package/es/src/elements/content-explorer/MetadataQueryAPIHelper.d.ts +22 -3
  37. package/es/src/elements/content-explorer/MetadataQueryBuilder.d.ts +27 -0
  38. package/es/src/elements/content-explorer/MetadataSidePanel.d.ts +6 -3
  39. package/es/src/elements/content-explorer/MetadataViewContainer.d.ts +10 -4
  40. package/es/src/elements/content-explorer/__tests__/MetadataQueryBuilder.test.d.ts +1 -0
  41. package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +1 -0
  42. package/es/src/elements/content-explorer/utils.d.ts +9 -3
  43. package/i18n/bn-IN.js +4 -0
  44. package/i18n/bn-IN.properties +12 -0
  45. package/i18n/da-DK.js +4 -0
  46. package/i18n/da-DK.properties +12 -0
  47. package/i18n/de-DE.js +5 -1
  48. package/i18n/de-DE.properties +12 -0
  49. package/i18n/en-AU.js +4 -0
  50. package/i18n/en-AU.properties +12 -0
  51. package/i18n/en-CA.js +4 -0
  52. package/i18n/en-CA.properties +12 -0
  53. package/i18n/en-GB.js +4 -0
  54. package/i18n/en-GB.properties +12 -0
  55. package/i18n/en-US.js +4 -0
  56. package/i18n/en-US.properties +8 -0
  57. package/i18n/en-x-pseudo.js +4 -0
  58. package/i18n/es-419.js +5 -1
  59. package/i18n/es-419.properties +12 -0
  60. package/i18n/es-ES.js +5 -1
  61. package/i18n/es-ES.properties +12 -0
  62. package/i18n/fi-FI.js +4 -0
  63. package/i18n/fi-FI.properties +12 -0
  64. package/i18n/fr-CA.js +4 -0
  65. package/i18n/fr-CA.properties +12 -0
  66. package/i18n/fr-FR.js +4 -0
  67. package/i18n/fr-FR.properties +12 -0
  68. package/i18n/hi-IN.js +4 -0
  69. package/i18n/hi-IN.properties +12 -0
  70. package/i18n/it-IT.js +4 -0
  71. package/i18n/it-IT.properties +12 -0
  72. package/i18n/ja-JP.js +6 -2
  73. package/i18n/ja-JP.properties +14 -2
  74. package/i18n/ko-KR.js +4 -0
  75. package/i18n/ko-KR.properties +12 -0
  76. package/i18n/nb-NO.js +4 -0
  77. package/i18n/nb-NO.properties +12 -0
  78. package/i18n/nl-NL.js +4 -0
  79. package/i18n/nl-NL.properties +12 -0
  80. package/i18n/pl-PL.js +4 -0
  81. package/i18n/pl-PL.properties +12 -0
  82. package/i18n/pt-BR.js +4 -0
  83. package/i18n/pt-BR.properties +12 -0
  84. package/i18n/ru-RU.js +5 -1
  85. package/i18n/ru-RU.properties +12 -0
  86. package/i18n/sv-SE.js +4 -0
  87. package/i18n/sv-SE.properties +12 -0
  88. package/i18n/tr-TR.js +5 -1
  89. package/i18n/tr-TR.properties +12 -0
  90. package/i18n/zh-CN.js +4 -0
  91. package/i18n/zh-CN.properties +12 -0
  92. package/i18n/zh-TW.js +4 -0
  93. package/i18n/zh-TW.properties +12 -0
  94. package/package.json +3 -3
  95. package/src/api/Metadata.js +110 -12
  96. package/src/api/__tests__/Metadata.test.js +120 -0
  97. package/src/elements/common/__mocks__/mockMetadata.ts +7 -11
  98. package/src/elements/common/messages.js +25 -0
  99. package/src/elements/content-explorer/Content.tsx +9 -2
  100. package/src/elements/content-explorer/ContentExplorer.tsx +71 -17
  101. package/src/elements/content-explorer/MetadataQueryAPIHelper.ts +199 -8
  102. package/src/elements/content-explorer/MetadataQueryBuilder.ts +159 -0
  103. package/src/elements/content-explorer/MetadataSidePanel.tsx +55 -14
  104. package/src/elements/content-explorer/MetadataViewContainer.tsx +164 -29
  105. package/src/elements/content-explorer/__tests__/Content.test.tsx +1 -0
  106. package/src/elements/content-explorer/__tests__/ContentExplorer.test.tsx +38 -7
  107. package/src/elements/content-explorer/__tests__/MetadataQueryAPIHelper.test.ts +428 -12
  108. package/src/elements/content-explorer/__tests__/MetadataQueryBuilder.test.ts +419 -0
  109. package/src/elements/content-explorer/__tests__/MetadataSidePanel.test.tsx +145 -3
  110. package/src/elements/content-explorer/__tests__/MetadataViewContainer.test.tsx +413 -9
  111. package/src/elements/content-explorer/stories/MetadataView.stories.tsx +3 -21
  112. package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +56 -21
  113. package/src/elements/content-explorer/utils.ts +150 -13
@@ -582,12 +582,18 @@ be.messageCenter.previewError = Не удается показать это из
582
582
  be.messageCenter.product = Продукт
583
583
  # Title for the message center modal
584
584
  be.messageCenter.title = Новые возможности
585
+ # Text shown in error notification banner
586
+ be.metadataUpdateErrorNotification = Unable to save changes. Please try again.
587
+ # Text shown in success notification banner
588
+ be.metadataUpdateSuccessNotification = {numSelected, plural, =1 {1 document updated} other {# documents updated} }
585
589
  # Text for modified date with modified prefix.
586
590
  be.modifiedDate = Изменено: {date}
587
591
  # Text for modified date with user with modified prefix.
588
592
  be.modifiedDateBy = Изменено {date} пользователем {name}
589
593
  # Label for a button that displays more options
590
594
  be.moreOptions = Дополнительные параметры
595
+ # Display text for field when there are multiple items selected and have different value
596
+ be.multipleValues = Multiple Values
591
597
  # Name ascending option shown in the share access drop down select.
592
598
  be.nameASC = Имя: А → Я
593
599
  # Name descending option shown in the share access drop down select.
@@ -834,6 +840,8 @@ be.skillUnknownError = Произошла ошибка при запуске э
834
840
  be.sort = Сортировать
835
841
  # Label for status skill card in the preview sidebar
836
842
  be.statusSkill = Статус
843
+ # Generic success label.
844
+ be.success = Success
837
845
  # Shown instead of todays date.
838
846
  be.today = сегодня
839
847
  # Label for keywords/topics skill section in the preview sidebar
@@ -966,6 +974,10 @@ boxui.categorySelector.label.more = Дополнительно
966
974
  boxui.checkboxTooltip.iconInfoText = Информация
967
975
  # Button to add classification on an item
968
976
  boxui.classification.add = Добавить
977
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
978
+ boxui.classification.appliedByBoxAi = ИИ Box
979
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
980
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
981
  # Header for classification section in sidebar
970
982
  boxui.classification.classification = Классификация
971
983
  # Classification label color name as dark blue
package/i18n/sv-SE.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "Vi har tyvärr problem med att visa den här bilden.",
292
292
  "be.messageCenter.product": "Produkt",
293
293
  "be.messageCenter.title": "Nyheter",
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": "Ändrad {date}",
295
297
  "be.modifiedDateBy": "Ändrad {date} av {name}",
296
298
  "be.moreOptions": "Fler alternativ",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "Namn: A → Ö",
298
301
  "be.nameDESC": "Namn: Ö → A",
299
302
  "be.nameDate": "{date} av {name}",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "Något gick fel när funktionen kördes eller när dess data hämtades.",
418
421
  "be.sort": "Sortera",
419
422
  "be.statusSkill": "Status",
423
+ "be.success": "Success",
420
424
  "be.today": "idag",
421
425
  "be.topicsSkill": "Ämnen",
422
426
  "be.transcriptEdit": "Klicka på det avsnitt du vill redigera.",
@@ -582,12 +582,18 @@ be.messageCenter.previewError = Vi har tyvärr problem med att visa den här bil
582
582
  be.messageCenter.product = Produkt
583
583
  # Title for the message center modal
584
584
  be.messageCenter.title = Nyheter
585
+ # Text shown in error notification banner
586
+ be.metadataUpdateErrorNotification = Unable to save changes. Please try again.
587
+ # Text shown in success notification banner
588
+ be.metadataUpdateSuccessNotification = {numSelected, plural, =1 {1 document updated} other {# documents updated} }
585
589
  # Text for modified date with modified prefix.
586
590
  be.modifiedDate = Ändrad {date}
587
591
  # Text for modified date with user with modified prefix.
588
592
  be.modifiedDateBy = Ändrad {date} av {name}
589
593
  # Label for a button that displays more options
590
594
  be.moreOptions = Fler alternativ
595
+ # Display text for field when there are multiple items selected and have different value
596
+ be.multipleValues = Multiple Values
591
597
  # Name ascending option shown in the share access drop down select.
592
598
  be.nameASC = Namn: A → Ö
593
599
  # Name descending option shown in the share access drop down select.
@@ -834,6 +840,8 @@ be.skillUnknownError = Något gick fel när funktionen kördes eller när dess d
834
840
  be.sort = Sortera
835
841
  # Label for status skill card in the preview sidebar
836
842
  be.statusSkill = Status
843
+ # Generic success label.
844
+ be.success = Success
837
845
  # Shown instead of todays date.
838
846
  be.today = idag
839
847
  # Label for keywords/topics skill section in the preview sidebar
@@ -966,6 +974,10 @@ boxui.categorySelector.label.more = Mer
966
974
  boxui.checkboxTooltip.iconInfoText = Info
967
975
  # Button to add classification on an item
968
976
  boxui.classification.add = Lägg till
977
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
978
+ boxui.classification.appliedByBoxAi = Box AI
979
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
980
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
981
  # Header for classification section in sidebar
970
982
  boxui.classification.classification = Klassificering
971
983
  # Classification label color name as dark blue
package/i18n/tr-TR.js CHANGED
@@ -291,9 +291,12 @@ export default {
291
291
  "be.messageCenter.previewError": "Üzgünüz, bu görüntüyü göstermekte sorun yaşıyoruz.",
292
292
  "be.messageCenter.product": "Ürün",
293
293
  "be.messageCenter.title": "Yenilikler",
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} tarihinde değiştirildi",
295
297
  "be.modifiedDateBy": "{name} tarafından {date} tarihinde değiştirildi",
296
298
  "be.moreOptions": "Daha Fazla Seçenek",
299
+ "be.multipleValues": "Multiple Values",
297
300
  "be.nameASC": "Ad: A → Z",
298
301
  "be.nameDESC": "Ad: Z → A",
299
302
  "be.nameDate": "{name} tarafından {date} tarihinde",
@@ -417,6 +420,7 @@ export default {
417
420
  "be.skillUnknownError": "Bu Skill özelliği kullanılırken veya ilgili veriler getirilirken bir hata oluştu.",
418
421
  "be.sort": "Sırala",
419
422
  "be.statusSkill": "Durum",
423
+ "be.success": "Success",
420
424
  "be.today": "bugün",
421
425
  "be.topicsSkill": "Konular",
422
426
  "be.transcriptEdit": "Düzenlemek için bir bölüme tıklayın.",
@@ -483,7 +487,7 @@ export default {
483
487
  "boxui.categorySelector.label.more": "Daha fazla",
484
488
  "boxui.checkboxTooltip.iconInfoText": "Bilgi",
485
489
  "boxui.classification.add": "Ekle",
486
- "boxui.classification.appliedByBoxAi": "Box AI",
490
+ "boxui.classification.appliedByBoxAi": "Box IA",
487
491
  "boxui.classification.appliedByBoxAiOnDate": "Box AI on {modifiedAt}",
488
492
  "boxui.classification.classification": "Sınıflandırma",
489
493
  "boxui.classification.classificationDarkBlue": "Koyu Mavi",
@@ -582,12 +582,18 @@ be.messageCenter.previewError = Üzgünüz, bu görüntüyü göstermekte sorun
582
582
  be.messageCenter.product = Ürün
583
583
  # Title for the message center modal
584
584
  be.messageCenter.title = Yenilikler
585
+ # Text shown in error notification banner
586
+ be.metadataUpdateErrorNotification = Unable to save changes. Please try again.
587
+ # Text shown in success notification banner
588
+ be.metadataUpdateSuccessNotification = {numSelected, plural, =1 {1 document updated} other {# documents updated} }
585
589
  # Text for modified date with modified prefix.
586
590
  be.modifiedDate = {date} tarihinde değiştirildi
587
591
  # Text for modified date with user with modified prefix.
588
592
  be.modifiedDateBy = {name} tarafından {date} tarihinde değiştirildi
589
593
  # Label for a button that displays more options
590
594
  be.moreOptions = Daha Fazla Seçenek
595
+ # Display text for field when there are multiple items selected and have different value
596
+ be.multipleValues = Multiple Values
591
597
  # Name ascending option shown in the share access drop down select.
592
598
  be.nameASC = Ad: A → Z
593
599
  # Name descending option shown in the share access drop down select.
@@ -834,6 +840,8 @@ be.skillUnknownError = Bu Skill özelliği kullanılırken veya ilgili veriler g
834
840
  be.sort = Sırala
835
841
  # Label for status skill card in the preview sidebar
836
842
  be.statusSkill = Durum
843
+ # Generic success label.
844
+ be.success = Success
837
845
  # Shown instead of todays date.
838
846
  be.today = bugün
839
847
  # Label for keywords/topics skill section in the preview sidebar
@@ -966,6 +974,10 @@ boxui.categorySelector.label.more = Daha fazla
966
974
  boxui.checkboxTooltip.iconInfoText = Bilgi
967
975
  # Button to add classification on an item
968
976
  boxui.classification.add = Ekle
977
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
978
+ boxui.classification.appliedByBoxAi = Box IA
979
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
980
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
981
  # Header for classification section in sidebar
970
982
  boxui.classification.classification = Sınıflandırma
971
983
  # Classification label color name as dark blue
package/i18n/zh-CN.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": "单击任何部分开始编辑。",
@@ -582,12 +582,18 @@ be.messageCenter.previewError = 抱歉,无法显示此图像。
582
582
  be.messageCenter.product = 产品
583
583
  # Title for the message center modal
584
584
  be.messageCenter.title = 新增功能
585
+ # Text shown in error notification banner
586
+ be.metadataUpdateErrorNotification = Unable to save changes. Please try again.
587
+ # Text shown in success notification banner
588
+ be.metadataUpdateSuccessNotification = {numSelected, plural, =1 {1 document updated} other {# documents updated} }
585
589
  # Text for modified date with modified prefix.
586
590
  be.modifiedDate = 修改日期:{date}
587
591
  # Text for modified date with user with modified prefix.
588
592
  be.modifiedDateBy = {name} 于 {date} 修改
589
593
  # Label for a button that displays more options
590
594
  be.moreOptions = 更多选项
595
+ # Display text for field when there are multiple items selected and have different value
596
+ be.multipleValues = Multiple Values
591
597
  # Name ascending option shown in the share access drop down select.
592
598
  be.nameASC = 名称:A → Z
593
599
  # Name descending option shown in the share access drop down select.
@@ -834,6 +840,8 @@ be.skillUnknownError = 运行此技能或获取其数据时出错。
834
840
  be.sort = 排序
835
841
  # Label for status skill card in the preview sidebar
836
842
  be.statusSkill = 状态
843
+ # Generic success label.
844
+ be.success = Success
837
845
  # Shown instead of todays date.
838
846
  be.today = 今天
839
847
  # Label for keywords/topics skill section in the preview sidebar
@@ -966,6 +974,10 @@ boxui.categorySelector.label.more = 更多
966
974
  boxui.checkboxTooltip.iconInfoText = 信息
967
975
  # Button to add classification on an item
968
976
  boxui.classification.add = 添加
977
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
978
+ boxui.classification.appliedByBoxAi = Box AI
979
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
980
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
981
  # Header for classification section in sidebar
970
982
  boxui.classification.classification = 分类
971
983
  # Classification label color name as dark blue
package/i18n/zh-TW.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": "按一下任一區段以編輯。",
@@ -582,12 +582,18 @@ be.messageCenter.previewError = 很抱歉,顯示此影像時發生問題。
582
582
  be.messageCenter.product = 產品
583
583
  # Title for the message center modal
584
584
  be.messageCenter.title = 新增內容
585
+ # Text shown in error notification banner
586
+ be.metadataUpdateErrorNotification = Unable to save changes. Please try again.
587
+ # Text shown in success notification banner
588
+ be.metadataUpdateSuccessNotification = {numSelected, plural, =1 {1 document updated} other {# documents updated} }
585
589
  # Text for modified date with modified prefix.
586
590
  be.modifiedDate = 於 {date} 修改
587
591
  # Text for modified date with user with modified prefix.
588
592
  be.modifiedDateBy = {name} 於 {date} 修改
589
593
  # Label for a button that displays more options
590
594
  be.moreOptions = 更多選項
595
+ # Display text for field when there are multiple items selected and have different value
596
+ be.multipleValues = Multiple Values
591
597
  # Name ascending option shown in the share access drop down select.
592
598
  be.nameASC = 名稱:A → Z
593
599
  # Name descending option shown in the share access drop down select.
@@ -834,6 +840,8 @@ be.skillUnknownError = 執行這個技能或擷取其資料時發生錯誤。
834
840
  be.sort = 排序
835
841
  # Label for status skill card in the preview sidebar
836
842
  be.statusSkill = 狀態
843
+ # Generic success label.
844
+ be.success = Success
837
845
  # Shown instead of todays date.
838
846
  be.today = 今天
839
847
  # Label for keywords/topics skill section in the preview sidebar
@@ -966,6 +974,10 @@ boxui.categorySelector.label.more = 更多
966
974
  boxui.checkboxTooltip.iconInfoText = 資訊
967
975
  # Button to add classification on an item
968
976
  boxui.classification.add = 新增
977
+ # Title of the card that shows the reason why the AI classification was applied when no date is available.
978
+ boxui.classification.appliedByBoxAi = Box AI
979
+ # Title of the card that shows the reason why the AI classification was applied on a specific date.
980
+ boxui.classification.appliedByBoxAiOnDate = Box AI on {modifiedAt}
969
981
  # Header for classification section in sidebar
970
982
  boxui.classification.classification = 分類
971
983
  # Classification label color name as dark blue
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "box-ui-elements",
3
- "version": "24.0.0-beta.4",
3
+ "version": "24.0.0-beta.6",
4
4
  "description": "Box UI Elements",
5
5
  "author": "Box (https://www.box.com/)",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -140,7 +140,7 @@
140
140
  "@box/languages": "^1.0.0",
141
141
  "@box/metadata-editor": "^0.122.12",
142
142
  "@box/metadata-filter": "^1.19.2",
143
- "@box/metadata-view": "^0.41.2",
143
+ "@box/metadata-view": "^0.48.1",
144
144
  "@box/react-virtualized": "^9.22.3-rc-box.10",
145
145
  "@box/types": "^0.2.1",
146
146
  "@cfaester/enzyme-adapter-react-18": "^0.8.0",
@@ -307,7 +307,7 @@
307
307
  "@box/item-icon": "^0.17.15",
308
308
  "@box/metadata-editor": "^0.122.12",
309
309
  "@box/metadata-filter": "^1.19.2",
310
- "@box/metadata-view": "^0.41.2",
310
+ "@box/metadata-view": "^0.48.1",
311
311
  "@box/react-virtualized": "^9.22.3-rc-box.10",
312
312
  "@box/types": "^0.2.1",
313
313
  "@hapi/address": "^2.1.4",
@@ -16,7 +16,7 @@ import partition from 'lodash/partition';
16
16
  import uniq from 'lodash/uniq';
17
17
  import uniqueId from 'lodash/uniqueId';
18
18
  import { getBadItemError, getBadPermissionsError, isUserCorrectableError } from '../utils/error';
19
- import { getTypedFileId } from '../utils/file';
19
+ import { getTypedFileId, getTypedFolderId } from '../utils/file';
20
20
  import { handleOnAbort, formatMetadataFieldValue } from './utils';
21
21
  import File from './File';
22
22
  import {
@@ -90,6 +90,16 @@ class Metadata extends File {
90
90
  return `${this.getMetadataCacheKey(id)}_classification`;
91
91
  }
92
92
 
93
+ /**
94
+ * Creates a key for the metadata template schema cache
95
+ *
96
+ * @param {string} templateKey - template key
97
+ * @return {string} key
98
+ */
99
+ getMetadataTemplateSchemaCacheKey(templateKey: string): string {
100
+ return `${CACHE_PREFIX_METADATA}template_schema_${templateKey}`;
101
+ }
102
+
93
103
  /**
94
104
  * API URL for metadata
95
105
  *
@@ -105,6 +115,21 @@ class Metadata extends File {
105
115
  return baseUrl;
106
116
  }
107
117
 
118
+ /**
119
+ * API URL for metadata
120
+ *
121
+ * @param {string} id - a Box folder id
122
+ * @param {string} field - metadata field
123
+ * @return {string} base url for files
124
+ */
125
+ getMetadataUrlForFolder(id: string, scope?: string, template?: string): string {
126
+ const baseUrl = `${this.getBaseApiUrl()}/folders/${id}/metadata`;
127
+ if (scope && template) {
128
+ return `${baseUrl}/${scope}/${template}`;
129
+ }
130
+ return baseUrl;
131
+ }
132
+
108
133
  /**
109
134
  * API URL for metadata templates for a scope
110
135
  *
@@ -337,9 +362,23 @@ class Metadata extends File {
337
362
  * @param {string} templateKey - template key
338
363
  * @return {Promise} Promise object of metadata template
339
364
  */
340
- getSchemaByTemplateKey(templateKey: string): Promise<MetadataTemplateSchemaResponse> {
365
+ async getSchemaByTemplateKey(templateKey: string): Promise<MetadataTemplateSchemaResponse> {
366
+ const cache: APICache = this.getCache();
367
+ const key = this.getMetadataTemplateSchemaCacheKey(templateKey);
368
+
369
+ // Return cached value if it exists
370
+ if (cache.has(key)) {
371
+ return cache.get(key);
372
+ }
373
+
374
+ // Fetch from API if not cached
341
375
  const url = this.getMetadataTemplateSchemaUrl(templateKey);
342
- return this.xhr.get({ url });
376
+ const response = await this.xhr.get({ url });
377
+
378
+ // Cache the response
379
+ cache.set(key, response);
380
+
381
+ return response;
343
382
  }
344
383
 
345
384
  /**
@@ -786,27 +825,33 @@ class Metadata extends File {
786
825
  }
787
826
 
788
827
  /**
789
- * API for patching metadata on file
828
+ * API for patching metadata on item (file/folder)
790
829
  *
791
- * @param {BoxItem} file - File object for which we are changing the description
830
+ * @param {BoxItem} item - File/Folder object for which we are changing the description
792
831
  * @param {Object} template - Metadata template
793
832
  * @param {Array} operations - Array of JSON patch operations
794
833
  * @param {Function} successCallback - Success callback
795
834
  * @param {Function} errorCallback - Error callback
835
+ * @param {boolean} suppressCallbacks - Boolean to decide whether suppress callbacks or not
796
836
  * @return {Promise}
797
837
  */
798
838
  async updateMetadata(
799
- file: BoxItem,
839
+ item: BoxItem,
800
840
  template: MetadataTemplate,
801
841
  operations: JSONPatchOperations,
802
842
  successCallback: Function,
803
843
  errorCallback: ElementsErrorCallback,
844
+ suppressCallbacks?: boolean,
804
845
  ): Promise<void> {
805
846
  this.errorCode = ERROR_CODE_UPDATE_METADATA;
806
- this.successCallback = successCallback;
807
- this.errorCallback = errorCallback;
847
+ if (!suppressCallbacks) {
848
+ // Only set callbacks when we intend to invoke them for this call
849
+ // so that callers performing bulk operations can suppress per-item callbacks
850
+ this.successCallback = successCallback;
851
+ this.errorCallback = errorCallback;
852
+ }
808
853
 
809
- const { id, permissions } = file;
854
+ const { id, permissions, type } = item;
810
855
  if (!id || !permissions) {
811
856
  this.errorHandler(getBadItemError());
812
857
  return;
@@ -821,11 +866,14 @@ class Metadata extends File {
821
866
 
822
867
  try {
823
868
  const metadata = await this.xhr.put({
824
- url: this.getMetadataUrl(id, template.scope, template.templateKey),
869
+ url:
870
+ type === 'file'
871
+ ? this.getMetadataUrl(id, template.scope, template.templateKey)
872
+ : this.getMetadataUrlForFolder(id, template.scope, template.templateKey),
825
873
  headers: {
826
874
  [HEADER_CONTENT_TYPE]: 'application/json-patch+json',
827
875
  },
828
- id: getTypedFileId(id),
876
+ id: type === 'file' ? getTypedFileId(id) : getTypedFolderId(id),
829
877
  data: operations,
830
878
  });
831
879
  if (!this.isDestroyed()) {
@@ -840,13 +888,63 @@ class Metadata extends File {
840
888
  editor,
841
889
  );
842
890
  }
843
- this.successHandler(editor);
891
+ if (!suppressCallbacks) {
892
+ this.successHandler(editor);
893
+ }
844
894
  }
845
895
  } catch (e) {
896
+ if (suppressCallbacks) {
897
+ // Let the caller decide how to handle errors (e.g., aggregate for bulk operations)
898
+ throw e;
899
+ }
846
900
  this.errorHandler(e);
847
901
  }
848
902
  }
849
903
 
904
+ /**
905
+ * API for bulk patching metadata on items (file/folder)
906
+ *
907
+ * @param {BoxItem[]} items - File/Folder object for which we are changing the description
908
+ * @param {Object} template - Metadata template
909
+ * @param {Array} operations - Array of JSON patch operations for each item
910
+ * @param {Function} successCallback - Success callback
911
+ * @param {Function} errorCallback - Error callback
912
+ * @return {Promise}
913
+ */
914
+ async bulkUpdateMetadata(
915
+ items: BoxItem[],
916
+ template: MetadataTemplate,
917
+ operations: JSONPatchOperations[],
918
+ successCallback: Function,
919
+ errorCallback: ElementsErrorCallback,
920
+ ): Promise<void> {
921
+ this.errorCode = ERROR_CODE_UPDATE_METADATA;
922
+ this.successCallback = successCallback;
923
+ this.errorCallback = errorCallback;
924
+
925
+ try {
926
+ const updatePromises = items.map(async (item, index) => {
927
+ try {
928
+ // Suppress per-item callbacks; aggregate outcome at the bulk level only
929
+ await this.updateMetadata(item, template, operations[index], successCallback, errorCallback, true);
930
+ } catch (e) {
931
+ // Re-throw to be caught by Promise.all and handled once below
932
+ throw new Error(`Failed to update metadata: ${e.message || e}`);
933
+ }
934
+ });
935
+
936
+ await Promise.all(updatePromises);
937
+
938
+ if (!this.isDestroyed()) {
939
+ this.successHandler();
940
+ }
941
+ } catch (e) {
942
+ if (!this.isDestroyed()) {
943
+ this.errorHandler(e);
944
+ }
945
+ }
946
+ }
947
+
850
948
  /**
851
949
  * API for patching metadata on file
852
950
  *
@@ -1700,6 +1700,7 @@ describe('api/Metadata', () => {
1700
1700
  permissions: {
1701
1701
  can_upload: true,
1702
1702
  },
1703
+ type: 'file',
1703
1704
  };
1704
1705
  const ops = [{ op: 'add' }, { op: 'test' }];
1705
1706
  const cache = new Cache();
@@ -1767,6 +1768,7 @@ describe('api/Metadata', () => {
1767
1768
  permissions: {
1768
1769
  can_upload: true,
1769
1770
  },
1771
+ type: 'file',
1770
1772
  };
1771
1773
  const ops = [{ op: 'add' }, { op: 'test' }];
1772
1774
  const cache = new Cache();
@@ -1833,6 +1835,7 @@ describe('api/Metadata', () => {
1833
1835
  permissions: {
1834
1836
  can_upload: true,
1835
1837
  },
1838
+ type: 'file',
1836
1839
  };
1837
1840
  const ops = [{ op: 'add' }, { op: 'test' }];
1838
1841
  const cache = new Cache();
@@ -1894,6 +1897,123 @@ describe('api/Metadata', () => {
1894
1897
  });
1895
1898
  });
1896
1899
 
1900
+ describe('bulkUpdateMetadata()', () => {
1901
+ test('should call updateMetadata for each item and call successHandler when all succeed', async () => {
1902
+ const success = jest.fn();
1903
+ const error = jest.fn();
1904
+ const items = [
1905
+ { id: '1', name: 'file1', permissions: { can_upload: true }, type: 'file' },
1906
+ { id: '2', name: 'file2', permissions: { can_upload: true }, type: 'file' },
1907
+ ];
1908
+ const template = { scope: 'scope', templateKey: 'templateKey' };
1909
+ const ops = [[{ op: 'replace', path: '/foo', value: 'a' }], [{ op: 'replace', path: '/foo', value: 'b' }]];
1910
+
1911
+ metadata.updateMetadata = jest.fn().mockResolvedValue(undefined);
1912
+ metadata.isDestroyed = jest.fn().mockReturnValue(false);
1913
+ metadata.successHandler = jest.fn();
1914
+ metadata.errorHandler = jest.fn();
1915
+
1916
+ await metadata.bulkUpdateMetadata(items, template, ops, success, error);
1917
+
1918
+ expect(metadata.errorCode).toBe(ERROR_CODE_UPDATE_METADATA);
1919
+ expect(metadata.successCallback).toBe(success);
1920
+ expect(metadata.errorCallback).toBe(error);
1921
+ expect(metadata.updateMetadata).toHaveBeenCalledTimes(2);
1922
+ expect(metadata.updateMetadata).toHaveBeenNthCalledWith(
1923
+ 1,
1924
+ items[0],
1925
+ template,
1926
+ ops[0],
1927
+ success,
1928
+ error,
1929
+ true,
1930
+ );
1931
+ expect(metadata.updateMetadata).toHaveBeenNthCalledWith(
1932
+ 2,
1933
+ items[1],
1934
+ template,
1935
+ ops[1],
1936
+ success,
1937
+ error,
1938
+ true,
1939
+ );
1940
+ expect(metadata.isDestroyed).toHaveBeenCalledTimes(1);
1941
+ expect(metadata.successHandler).toHaveBeenCalledTimes(1);
1942
+ expect(metadata.errorHandler).not.toHaveBeenCalled();
1943
+ });
1944
+
1945
+ test('should call errorHandler with aggregated error when any update fails', async () => {
1946
+ const success = jest.fn();
1947
+ const error = jest.fn();
1948
+ const items = [
1949
+ { id: '1', name: 'file1', permissions: { can_upload: true }, type: 'file' },
1950
+ { id: '2', name: 'file2', permissions: { can_upload: true }, type: 'file' },
1951
+ ];
1952
+ const template = { scope: 'scope', templateKey: 'templateKey' };
1953
+ const ops = [[], []];
1954
+
1955
+ metadata.updateMetadata = jest
1956
+ .fn()
1957
+ .mockResolvedValueOnce(undefined)
1958
+ .mockRejectedValueOnce(new Error('mock error'));
1959
+ metadata.isDestroyed = jest.fn().mockReturnValue(false);
1960
+ metadata.successHandler = jest.fn();
1961
+ metadata.errorHandler = jest.fn();
1962
+
1963
+ await metadata.bulkUpdateMetadata(items, template, ops, success, error);
1964
+
1965
+ expect(metadata.updateMetadata).toHaveBeenCalledTimes(2);
1966
+ expect(metadata.errorHandler).toHaveBeenCalledTimes(1);
1967
+ const errArg = metadata.errorHandler.mock.calls[0][0];
1968
+ expect(errArg).toBeInstanceOf(Error);
1969
+ expect(errArg.message).toContain('Failed to update metadata');
1970
+ expect(errArg.message).toContain('mock error');
1971
+ expect(metadata.successHandler).not.toHaveBeenCalled();
1972
+ });
1973
+
1974
+ test('should not call successHandler when destroyed after successful updates', async () => {
1975
+ const success = jest.fn();
1976
+ const error = jest.fn();
1977
+ const items = [
1978
+ { id: '1', name: 'file1', permissions: { can_upload: true }, type: 'file' },
1979
+ { id: '2', name: 'file2', permissions: { can_upload: true }, type: 'file' },
1980
+ ];
1981
+ const template = { scope: 'scope', templateKey: 'templateKey' };
1982
+ const ops = [[], []];
1983
+
1984
+ metadata.updateMetadata = jest.fn().mockResolvedValue(undefined);
1985
+ metadata.isDestroyed = jest.fn().mockReturnValue(true);
1986
+ metadata.successHandler = jest.fn();
1987
+ metadata.errorHandler = jest.fn();
1988
+
1989
+ await metadata.bulkUpdateMetadata(items, template, ops, success, error);
1990
+
1991
+ expect(metadata.successHandler).not.toHaveBeenCalled();
1992
+ expect(metadata.errorHandler).not.toHaveBeenCalled();
1993
+ });
1994
+
1995
+ test('should not call errorHandler when destroyed after failure', async () => {
1996
+ const success = jest.fn();
1997
+ const error = jest.fn();
1998
+ const items = [
1999
+ { id: '1', name: 'file1', permissions: { can_upload: true }, type: 'file' },
2000
+ { id: '2', name: 'file2', permissions: { can_upload: true }, type: 'file' },
2001
+ ];
2002
+ const template = { scope: 'scope', templateKey: 'templateKey' };
2003
+ const ops = [[], []];
2004
+
2005
+ metadata.updateMetadata = jest.fn().mockRejectedValue(new Error('mock error'));
2006
+ metadata.isDestroyed = jest.fn().mockReturnValue(true);
2007
+ metadata.successHandler = jest.fn();
2008
+ metadata.errorHandler = jest.fn();
2009
+
2010
+ await metadata.bulkUpdateMetadata(items, template, ops, success, error);
2011
+
2012
+ expect(metadata.successHandler).not.toHaveBeenCalled();
2013
+ expect(metadata.errorHandler).not.toHaveBeenCalled();
2014
+ });
2015
+ });
2016
+
1897
2017
  describe('updateMetadataRedesign()', () => {
1898
2018
  test('should call error callback with a bad item error when no id', () => {
1899
2019
  jest.spyOn(ErrorUtil, 'getBadItemError').mockReturnValueOnce('error');