diff --git a/src/CONST/index.ts b/src/CONST/index.ts index db994296906b..f8e984a12a3d 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -2248,6 +2248,7 @@ const CONST = { SET_AUTO_REIMBURSEMENT: 'POLICYCHANGELOG_SET_AUTOREIMBURSEMENT', SET_AUTO_JOIN: 'POLICYCHANGELOG_SET_AUTO_JOIN', SET_CATEGORY_NAME: 'POLICYCHANGELOG_SET_CATEGORY_NAME', + SET_CATEGORY_VISIBILITY: 'POLICYCHANGELOG_SET_CATEGORY_VISIBILITY', SHARED_BUDGET_NOTIFICATION: 'POLICYCHANGELOG_SHARED_BUDGET_NOTIFICATION', UPDATE_ACH_ACCOUNT: 'POLICYCHANGELOG_UPDATE_ACH_ACCOUNT', UPDATE_APPROVER_RULE: 'POLICYCHANGELOG_UPDATE_APPROVER_RULE', @@ -5280,6 +5281,15 @@ const CONST = { IS_RECRUITING_ENABLED: 'isRecruitingEnabled', IS_MCP_ENABLED: 'isMCPEnabled', }, + CATEGORY_VISIBILITY: { + // Change log lists with this many entries or more show a count instead, with the full list at the top of the thread + MAX_LISTED_ITEMS: 10, + REASON: { + SET_BY_ADMIN: 'setByAdmin', + CATEGORIES_DELETED: 'categoriesDeleted', + CATEGORIES_DISABLED: 'categoriesDisabled', + }, + }, DEFAULT_CATEGORIES: { ADVERTISING: 'Advertising', BENEFITS: 'Benefits', diff --git a/src/languages/de.ts b/src/languages/de.ts index 8c5bd5bc988a..0a6af8fe0f75 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -9996,6 +9996,25 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc return `hat die Positionenbelege der Kategorie „${categoryName}“ auf ${newValue} geändert (zuvor ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `hat die Kategorie „${oldName}“ in „${newName}“ umbenannt`, + setCategoryVisibility: (members: string, categories: string) => `hat ${members} so eingestellt, dass sie nur ${categories} sehen`, + changedCategoryVisibility: (members: string, categories: string) => `hat ${members} so geändert, dass sie nur noch ${categories} sehen`, + clearedCategoryVisibility: (members: string) => `${members} können jetzt alle Kategorien sehen`, + quotedCategoryName: (categoryName: string) => `„${categoryName}“`, + oneCategory: (categoryName: string) => `die Kategorie ${categoryName}`, + someCategories: (categoryList: string) => `die ${categoryList} Kategorien`, + everyone: 'alle', + categoryCount: ({count}: {count: number}) => ({ + one: '1 Kategorie', + other: `${count} Kategorien`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 Mitglied', + other: `${count} Mitglieder`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Kategorien: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Mitglieder: ${memberList}`, + categoryVisibilityReasonDeleted: ', da ihre einzige Kategorie gelöscht wurde. Aktualisieren Sie bei Bedarf ihre Kategoriesichtbarkeit.', + categoryVisibilityReasonDisabled: ', da ihre einzige Kategorie deaktiviert war. Aktualisieren Sie bei Bedarf deren Kategoriesichtbarkeit.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `hat den Beschreibungshinweis „${oldValue}“ aus der Kategorie „${categoryName}“ entfernt`; diff --git a/src/languages/el.ts b/src/languages/el.ts index c448d7d2bf63..3debe17bedd2 100644 --- a/src/languages/el.ts +++ b/src/languages/el.ts @@ -10152,6 +10152,25 @@ ${reportName}`, return `άλλαξε τις αναλυτικές αποδείξεις της κατηγορίας «${categoryName}» σε ${newValue} (προηγουμένως ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `μετονόμασε την κατηγορία «${oldName}» σε «${newName}»`, + setCategoryVisibility: (members: string, categories: string) => `όρισε ώστε ${members} να βλέπουν μόνο ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `άλλαξε ώστε ${members} να βλέπουν μόνο ${categories}`, + clearedCategoryVisibility: (members: string) => `άλλαξε τα δικαιώματα των ${members} ώστε να βλέπουν όλες τις κατηγορίες`, + quotedCategoryName: (categoryName: string) => `«${categoryName}»`, + oneCategory: (categoryName: string) => `την κατηγορία ${categoryName}`, + someCategories: (categoryList: string) => `τις κατηγορίες ${categoryList}`, + everyone: 'όλοι', + categoryCount: ({count}: {count: number}) => ({ + one: '1 κατηγορία', + other: `${count} κατηγορίες`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 μέλος', + other: `${count} μέλη`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Κατηγορίες: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Μέλη: ${memberList}`, + categoryVisibilityReasonDeleted: ', επειδή η μοναδική τους κατηγορία διαγράφηκε. Ενημερώστε, αν χρειάζεται, την ορατότητα της κατηγορίας τους.', + categoryVisibilityReasonDisabled: ', καθώς η μοναδική τους κατηγορία ήταν απενεργοποιημένη. Ενημερώστε την ορατότητα της κατηγορίας τους, αν χρειάζεται.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `αφαίρεσε την υπόδειξη περιγραφής «${oldValue}» από την κατηγορία «${categoryName}»`; diff --git a/src/languages/en.ts b/src/languages/en.ts index 31ed384ef13d..46259f8772ca 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -10220,6 +10220,25 @@ const translations = { return `changed the "${categoryName}" category Itemized receipts to ${newValue} (previously ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `renamed the category "${oldName}" to "${newName}"`, + setCategoryVisibility: (members: string, categories: string) => `set ${members} to only see ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `changed ${members} to only see ${categories}`, + clearedCategoryVisibility: (members: string) => `changed ${members} to see all categories`, + quotedCategoryName: (categoryName: string) => `"${categoryName}"`, + oneCategory: (categoryName: string) => `the ${categoryName} category`, + someCategories: (categoryList: string) => `the ${categoryList} categories`, + everyone: 'everyone', + categoryCount: ({count}: {count: number}) => ({ + one: '1 category', + other: `${count} categories`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 member', + other: `${count} members`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Categories: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Members: ${memberList}`, + categoryVisibilityReasonDeleted: ', since their only category was deleted. Update their category visibility if needed.', + categoryVisibilityReasonDisabled: ', since their only category was disabled. Update their category visibility if needed.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `removed the description hint "${oldValue}" from the category "${categoryName}"`; diff --git a/src/languages/es.ts b/src/languages/es.ts index c4f9b9f80374..3b15ccb4a3ed 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -9818,6 +9818,25 @@ ${reportName}`, return `cambió los Recibos detallados de la categoría "${categoryName}" a ${newValue} (previamente ${oldValue})`; }, setCategoryName: (oldName, newName) => `renombró la categoría "${oldName}" a "${newName}"`, + setCategoryVisibility: (members, categories) => `configuró a ${members} para que solo vean ${categories}`, + changedCategoryVisibility: (members, categories) => `cambió a ${members} para que solo vean ${categories}`, + clearedCategoryVisibility: (members) => `cambió a ${members} para que vean todas las categorías`, + quotedCategoryName: (categoryName) => `"${categoryName}"`, + oneCategory: (categoryName) => `la categoría ${categoryName}`, + someCategories: (categoryList) => `las categorías ${categoryList}`, + everyone: 'todos', + categoryCount: ({count}: {count: number}) => ({ + one: '1 categoría', + other: `${count} categorías`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 miembro', + other: `${count} miembros`, + }), + categoryVisibilityCategoriesList: (categoryList) => `Categorías: ${categoryList}`, + categoryVisibilityMembersList: (memberList) => `Miembros: ${memberList}`, + categoryVisibilityReasonDeleted: ', ya que su única categoría se eliminó. Actualiza la visibilidad de su categoría si es necesario.', + categoryVisibilityReasonDisabled: ', ya que su única categoría estaba deshabilitada. Actualiza la visibilidad de su categoría si es necesario.', updateCategories: (count) => `actualizó ${count} categorías`, updateTagListName: (oldName, newName) => `cambió el nombre de la lista de etiquetas a "${newName}" (previamente "${oldName}")`, updateTagList: (tagListName) => `actualizó las etiquetas de la lista "${tagListName}"`, diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 611d20088216..fab900b41bd6 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -10024,6 +10024,25 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e return `a modifié les reçus détaillés de la catégorie « ${categoryName} » en ${newValue} (auparavant ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `a renommé la catégorie « ${oldName} » en « ${newName} »`, + setCategoryVisibility: (members: string, categories: string) => `a configuré ${members} pour ne voir que ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `a modifié ${members} pour qu’ils ne voient que ${categories}`, + clearedCategoryVisibility: (members: string) => `a modifié ${members} pour voir toutes les catégories`, + quotedCategoryName: (categoryName: string) => `« ${categoryName} »`, + oneCategory: (categoryName: string) => `la catégorie ${categoryName}`, + someCategories: (categoryList: string) => `les catégories ${categoryList}`, + everyone: 'tout le monde', + categoryCount: ({count}: {count: number}) => ({ + one: '1 catégorie', + other: `${count} catégories`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 membre', + other: `${count} membres`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Catégories : ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Membres : ${memberList}`, + categoryVisibilityReasonDeleted: ', car leur seule catégorie a été supprimée. Mettez à jour la visibilité de leur catégorie si nécessaire.', + categoryVisibilityReasonDisabled: ', car leur seule catégorie a été désactivée. Mettez à jour la visibilité de leurs catégories si nécessaire.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `a supprimé l’indication de description « ${oldValue} » de la catégorie « ${categoryName} »`; diff --git a/src/languages/it.ts b/src/languages/it.ts index 3ee7445f89c5..52ef891c274a 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -9941,6 +9941,25 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`, return `ha modificato le ricevute con voce di dettaglio della categoria "${categoryName}" in ${newValue} (in precedenza ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `ha rinominato la categoria "${oldName}" in "${newName}"`, + setCategoryVisibility: (members: string, categories: string) => `ha impostato ${members} per vedere solo ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `ha modificato ${members} in modo che possano vedere solo ${categories}`, + clearedCategoryVisibility: (members: string) => `ha modificato ${members} per vedere tutte le categorie`, + quotedCategoryName: (categoryName: string) => `"${categoryName}"`, + oneCategory: (categoryName: string) => `la categoria ${categoryName}`, + someCategories: (categoryList: string) => `le categorie ${categoryList}`, + everyone: 'tutti', + categoryCount: ({count}: {count: number}) => ({ + one: '1 categoria', + other: `${count} categorie`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 membro', + other: `${count} membri`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Categorie: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Membri: ${memberList}`, + categoryVisibilityReasonDeleted: ', perché la loro unica categoria è stata eliminata. Aggiorna la visibilità della loro categoria se necessario.', + categoryVisibilityReasonDisabled: ', perché la loro unica categoria è stata disattivata. Aggiorna la visibilità della loro categoria se necessario.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `ha rimosso il suggerimento di descrizione "${oldValue}" dalla categoria "${categoryName}"`; diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 37f26ac96239..2c7b0dd32148 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -9796,6 +9796,25 @@ ${reportName}`, return `「${categoryName}」カテゴリの明細付きレシートを${newValue}に変更しました(以前は${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `カテゴリ名を「${oldName}」から「${newName}」に変更しました`, + setCategoryVisibility: (members: string, categories: string) => `${members}が${categories}のみを表示できるように設定しました`, + changedCategoryVisibility: (members: string, categories: string) => `${members} が ${categories} のみを表示するように変更しました`, + clearedCategoryVisibility: (members: string) => `${members} がすべてのカテゴリを表示できるように変更しました`, + quotedCategoryName: (categoryName: string) => `「${categoryName}」`, + oneCategory: (categoryName: string) => `${categoryName} カテゴリ`, + someCategories: (categoryList: string) => `カテゴリ${categoryList}`, + everyone: '全員', + categoryCount: ({count}: {count: number}) => ({ + one: '1 件のカテゴリ', + other: `${count} 個のカテゴリ`, + }), + memberCount: ({count}: {count: number}) => ({ + one: 'メンバー 1 人', + other: `${count} 名のメンバー`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `カテゴリ:${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `メンバー:${memberList}`, + categoryVisibilityReasonDeleted: '。唯一のカテゴリが削除されたためです。必要に応じてカテゴリの表示設定を更新してください。', + categoryVisibilityReasonDisabled: '、そのユーザーの唯一のカテゴリが無効になっているためです。必要に応じてカテゴリの表示設定を更新してください。', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `カテゴリ「${categoryName}」から説明のヒント「${oldValue}」を削除しました`; diff --git a/src/languages/nl.ts b/src/languages/nl.ts index bb7c4acb402f..c6975806b39c 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -9917,6 +9917,25 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`, return `heeft de categorie „${categoryName}” Itemized receipts gewijzigd naar ${newValue} (voorheen ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `heeft de categorie "${oldName}" hernoemd naar "${newName}"`, + setCategoryVisibility: (members: string, categories: string) => `heeft ${members} zo ingesteld dat ze alleen ${categories} zien`, + changedCategoryVisibility: (members: string, categories: string) => `heeft ${members} gewijzigd zodat ze alleen ${categories} zien`, + clearedCategoryVisibility: (members: string) => `heeft ${members} gewijzigd zodat ze alle categorieën kunnen zien`, + quotedCategoryName: (categoryName: string) => `"${categoryName}"`, + oneCategory: (categoryName: string) => `de categorie ${categoryName}`, + someCategories: (categoryList: string) => `de ${categoryList} categorieën`, + everyone: 'iedereen', + categoryCount: ({count}: {count: number}) => ({ + one: '1 categorie', + other: `${count} categorieën`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 lid', + other: `${count} leden`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Categorieën: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Leden: ${memberList}`, + categoryVisibilityReasonDeleted: ', omdat hun enige categorie is verwijderd. Werk hun categoriezichtbaarheid bij indien nodig.', + categoryVisibilityReasonDisabled: ', omdat hun enige categorie was uitgeschakeld. Werk indien nodig hun categoriezichtbaarheid bij.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `heeft de beschrijvingshint "${oldValue}" verwijderd uit de categorie "${categoryName}"`; diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 73cb67e00b3e..5970935577aa 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -9937,6 +9937,29 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`, return `zmienił(a) pozycjonowanie paragonów dla kategorii „${categoryName}” na ${newValue} (wcześniej ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `zmieniono nazwę kategorii „${oldName}” na „${newName}”`, + setCategoryVisibility: (members: string, categories: string) => `ustawiono, aby ${members} widzieli tylko ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `zmienił(a) ustawienia, aby ${members} widzieli tylko ${categories}`, + clearedCategoryVisibility: (members: string) => `zmieniono uprawnienia ${members}, aby widzieli wszystkie kategorie`, + quotedCategoryName: (categoryName: string) => `„${categoryName}”`, + oneCategory: (categoryName: string) => `kategorię ${categoryName}`, + someCategories: (categoryList: string) => `${categoryList} kategorie`, + everyone: 'wszyscy', + categoryCount: ({count}: {count: number}) => ({ + one: '1 kategorię', + few: `${count} kategorie`, + many: `${count} kategorii`, + other: `${count} kategorii`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 członek', + few: `${count} członków`, + many: `${count} członków`, + other: `${count} członków`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Kategorie: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Członkowie: ${memberList}`, + categoryVisibilityReasonDeleted: ', ponieważ ich jedyna kategoria została usunięta. Zaktualizuj w razie potrzeby widoczność ich kategorii.', + categoryVisibilityReasonDisabled: ', ponieważ ich jedyna kategoria została wyłączona. Zaktualizuj widoczność ich kategorii, jeśli to konieczne.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `usunięto podpowiedź opisu „${oldValue}” z kategorii „${categoryName}”`; diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index dceae4285aa5..e10c056ab5b7 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -9926,6 +9926,25 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`, return `alterou a categoria "${categoryName}" Itens detalhados de recibos para ${newValue} (antes ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `renomeou a categoria "${oldName}" para "${newName}"`, + setCategoryVisibility: (members: string, categories: string) => `configurou ${members} para ver apenas ${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `alterou ${members} para verem apenas ${categories}`, + clearedCategoryVisibility: (members: string) => `alterou ${members} para ver todas as categorias`, + quotedCategoryName: (categoryName: string) => `"${categoryName}"`, + oneCategory: (categoryName: string) => `a categoria ${categoryName}`, + someCategories: (categoryList: string) => `as categorias ${categoryList}`, + everyone: 'todos', + categoryCount: ({count}: {count: number}) => ({ + one: '1 categoria', + other: `${count} categorias`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 membro', + other: `${count} membros`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `Categorias: ${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `Membros: ${memberList}`, + categoryVisibilityReasonDeleted: ', já que a única categoria deles foi excluída. Atualize a visibilidade da categoria deles, se necessário.', + categoryVisibilityReasonDisabled: ', já que a única categoria deles foi desativada. Atualize a visibilidade da categoria, se necessário.', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `removeu a dica de descrição "${oldValue}" da categoria "${categoryName}"`; diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 975f7708b68e..5096e619ed1b 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -9550,6 +9550,25 @@ ${reportName}`, return `将“${categoryName}”类别的分项收据更改为 ${newValue}(之前为 ${oldValue})`; }, setCategoryName: (oldName: string, newName: string) => `已将类别“${oldName}”重命名为“${newName}”`, + setCategoryVisibility: (members: string, categories: string) => `已将${members}设置为仅可查看${categories}`, + changedCategoryVisibility: (members: string, categories: string) => `已更改${members}为仅能看到${categories}`, + clearedCategoryVisibility: (members: string) => `已更改${members}为可查看所有类别`, + quotedCategoryName: (categoryName: string) => `“${categoryName}”`, + oneCategory: (categoryName: string) => `${categoryName} 类别`, + someCategories: (categoryList: string) => `类别${categoryList}`, + everyone: '所有人', + categoryCount: ({count}: {count: number}) => ({ + one: '1 个类别', + other: `${count} 个类别`, + }), + memberCount: ({count}: {count: number}) => ({ + one: '1 名成员', + other: `${count} 名成员`, + }), + categoryVisibilityCategoriesList: (categoryList: string) => `类别:${categoryList}`, + categoryVisibilityMembersList: (memberList: string) => `成员:${memberList}`, + categoryVisibilityReasonDeleted: ',因为他们唯一的类别已被删除。如有需要,请更新其类别可见性。', + categoryVisibilityReasonDisabled: ',因为他们唯一的类别已被禁用。如有需要,请更新其类别可见性。', updatedDescriptionHint: (categoryName: string, newValue?: string, oldValue?: string) => { if (!newValue) { return `已从类别“${categoryName}”中移除描述提示“${oldValue}”`; diff --git a/src/libs/ReportActionsUtils.ts b/src/libs/ReportActionsUtils.ts index 0776e4748952..89a2e18b51b1 100644 --- a/src/libs/ReportActionsUtils.ts +++ b/src/libs/ReportActionsUtils.ts @@ -4,7 +4,7 @@ import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList'; import usePrevious from '@hooks/usePrevious'; // eslint-disable-next-line @dword-design/import-alias/prefer-alias -import {doesReportContainRequestsFromMultipleUsers, getReportOrDraftReport} from '@libs/ReportUtils'; +import {doesReportContainRequestsFromMultipleUsers, getDisplayNameForParticipant, getReportOrDraftReport} from '@libs/ReportUtils'; import CONST from '@src/CONST'; import IntlStore from '@src/languages/IntlStore'; @@ -66,7 +66,7 @@ import getBase62ReportID from './getBase62ReportID'; import {isReportMessageAttachment} from './isReportMessageAttachment'; import {toLocaleOrdinal} from './LocaleDigitUtils'; import {formatPhoneNumber} from './LocalePhoneNumber'; -import {formatMessageElementList} from './Localize'; +import {formatList, formatMessageElementList} from './Localize'; import Log from './Log'; import getReportURLForCurrentContext from './Navigation/helpers/getReportURLForCurrentContext'; import {getIsOffline, subscribe as subscribeNetworkState} from './NetworkState'; @@ -265,6 +265,7 @@ const SYSTEM_POLICY_CHANGE_LOG_ACTION_TYPES = new Set([ CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.RENAME_CARD_FEED, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_AUTO_JOIN, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_NAME, + CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SHARED_BUDGET_NOTIFICATION, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.TEAM_DOWNGRADE, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UNASSIGN_COMPANY_CARD, @@ -2472,7 +2473,8 @@ function isCategoryModificationAction(actionName: string): boolean { actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_CATEGORY || actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.DELETE_CATEGORY || actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY || - actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_NAME + actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_NAME || + actionName === CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY ); } @@ -3829,7 +3831,83 @@ function getWorkspaceFrequencyUpdateMessage(translate: LocalizedTranslate, actio return translate('workspaceActions.updatedWorkspaceFrequencyAction', oldFrequencyTranslation, newFrequencyTranslation); } -function getWorkspaceCategoryUpdateMessage(translate: LocalizedTranslate, action: ReportAction, policy?: OnyxEntry): string { +/** + * Builds the message for a category visibility change, e.g. "set Bob Sterling to only see the "Meals" and "Fuel" categories". + * Lists that are too long to read inline show a count, and when shouldShowFullList is true (the action is shown at the top of its thread), + * those lists are returned in full instead. + * Pass personalDetails from a subscription so member names update when their details load or change. + */ +function getCategoryVisibilityUpdateMessage( + translate: LocalizedTranslate, + action: ReportAction, + shouldShowFullList: boolean, + personalDetails?: OnyxEntry, +): string | undefined { + const {categoryNames, accountIDs, hadRestriction, reason} = getOriginalMessage(action) ?? {}; + if (!Array.isArray(categoryNames) || !Array.isArray(accountIDs)) { + return undefined; + } + + const maxListedItems = CONST.POLICY.CATEGORY_VISIBILITY.MAX_LISTED_ITEMS; + const getQuotedCategoryNames = () => categoryNames.map((name) => translate('workspaceActions.quotedCategoryName', getDecodedCategoryName(name))); + const getMemberNames = () => { + const hiddenTranslation = translate('common.hidden'); + return accountIDs.map((accountID) => getDisplayNameForParticipant({accountID, personalDetailsData: personalDetails, formatPhoneNumber, hiddenTranslation})); + }; + + if (shouldShowFullList) { + const fullLists: string[] = []; + if (categoryNames.length >= maxListedItems) { + fullLists.push(translate('workspaceActions.categoryVisibilityCategoriesList', formatList(getQuotedCategoryNames()))); + } + if (accountIDs.length >= maxListedItems) { + fullLists.push(translate('workspaceActions.categoryVisibilityMembersList', formatList(getMemberNames()))); + } + if (fullLists.length > 0) { + return fullLists.join('\n'); + } + } + + let members: string; + if (accountIDs.length === 0) { + members = translate('workspaceActions.everyone'); + } else if (accountIDs.length >= maxListedItems) { + members = translate('workspaceActions.memberCount', {count: accountIDs.length}); + } else { + members = formatList(getMemberNames()); + } + + let message: string; + if (categoryNames.length === 0) { + message = translate('workspaceActions.clearedCategoryVisibility', members); + } else { + let categories: string; + if (categoryNames.length >= maxListedItems) { + categories = translate('workspaceActions.categoryCount', {count: categoryNames.length}); + } else if (categoryNames.length === 1) { + categories = translate('workspaceActions.oneCategory', getQuotedCategoryNames().at(0) ?? ''); + } else { + categories = translate('workspaceActions.someCategories', formatList(getQuotedCategoryNames())); + } + message = hadRestriction ? translate('workspaceActions.changedCategoryVisibility', members, categories) : translate('workspaceActions.setCategoryVisibility', members, categories); + } + + if (reason === CONST.POLICY.CATEGORY_VISIBILITY.REASON.CATEGORIES_DELETED) { + return `${message}${translate('workspaceActions.categoryVisibilityReasonDeleted')}`; + } + if (reason === CONST.POLICY.CATEGORY_VISIBILITY.REASON.CATEGORIES_DISABLED) { + return `${message}${translate('workspaceActions.categoryVisibilityReasonDisabled')}`; + } + return message; +} + +function getWorkspaceCategoryUpdateMessage( + translate: LocalizedTranslate, + action: ReportAction, + policy?: OnyxEntry, + shouldShowFullList = false, + personalDetails?: OnyxEntry, +): string { const {categoryName, oldValue, newName, oldName, updatedField, newValue, currency} = getOriginalMessage(action as ReportAction) ?? {}; @@ -3927,6 +4005,13 @@ function getWorkspaceCategoryUpdateMessage(translate: LocalizedTranslate, action return translate('workspaceActions.setCategoryName', getDecodedCategoryName(oldName), getDecodedCategoryName(newName)); } + if (isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY)) { + const categoryVisibilityMessage = getCategoryVisibilityUpdateMessage(translate, action, shouldShowFullList, personalDetails); + if (categoryVisibilityMessage) { + return categoryVisibilityMessage; + } + } + return getReportActionText(action); } diff --git a/src/pages/inbox/report/ReportActionItem.tsx b/src/pages/inbox/report/ReportActionItem.tsx index 9a2ee6759a18..edd943268e5f 100644 --- a/src/pages/inbox/report/ReportActionItem.tsx +++ b/src/pages/inbox/report/ReportActionItem.tsx @@ -694,6 +694,7 @@ function ReportActionItem({ isOnSearch={isOnSearch} setIsPaymentMethodPopoverActive={setIsPaymentMethodPopoverActive} isLatestConciergeFeedbackAction={isLatestConciergeFeedbackAction} + isThreadReportParentAction={isThreadReportParentAction} /> {Permissions.canUseLinkPreviews() && !isHidden && (action.linkMetadata?.length ?? 0) > 0 && ( diff --git a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx index 73ae231973c4..8a7302027519 100644 --- a/src/pages/inbox/report/actionContents/ActionContentRouter.tsx +++ b/src/pages/inbox/report/actionContents/ActionContentRouter.tsx @@ -144,6 +144,9 @@ type ActionContentRouterProps = { setIsPaymentMethodPopoverActive: (value: boolean) => void; isTrackIntentUser?: boolean; paymentExpectedDate?: string; + + /** Whether the action is shown at the top of its thread */ + isThreadReportParentAction?: boolean; }; function ActionContentRouter({ @@ -167,6 +170,7 @@ function ActionContentRouter({ isTrackIntentUser, isLatestConciergeFeedbackAction, paymentExpectedDate, + isThreadReportParentAction = false, }: ActionContentRouterProps): React.JSX.Element | null { const {translate, formatTravelDate} = useLocalize(); const styles = useThemeStyles(); @@ -380,6 +384,7 @@ function ActionContentRouter({ ); } diff --git a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx index b9a4ea49a3d0..59954ffe039f 100644 --- a/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx +++ b/src/pages/inbox/report/actionContents/PolicyChangeLogContent.tsx @@ -5,6 +5,7 @@ import {useCurrencyListActions} from '@hooks/useCurrencyList'; import type {CurrencyListActionsContextType} from '@hooks/useCurrencyList'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; +import {usePersonalDetailsByIDs} from '@hooks/usePersonalDetails'; import {getAddAgentRuleMessage, getDeleteAgentRuleMessage, getUpdateAgentRuleMessage} from '@libs/AgentRuleChangeLogUtils'; import {getCleanedTagName} from '@libs/PolicyUtils'; @@ -34,6 +35,7 @@ import { getInvoiceCompanyNameUpdateMessage, getInvoiceCompanyWebsiteUpdateMessage, getMccGroupCategoryMessage, + getOriginalMessage, getOverLimitForwardsToUpdateMessage, getPolicyChangeLogAddEmployeeMessage, getPolicyChangeLogDefaultBillableMessage, @@ -99,6 +101,7 @@ import { getWorkspaceTagUpdateMessage, getWorkspaceTaxUpdateMessage, getWorkspaceUpdateFieldMessage, + isActionOfType, } from '@libs/ReportActionsUtils'; import {getPolicyChangeLogCopyMessage, getUpdateEmployeeDisplayNameMessage, getWorkspaceNameUpdatedMessage} from '@libs/ReportUtils'; import {getAddExpensifyCardRuleMessage, getRemoveExpensifyCardRuleMessage, getUpdateExpensifyCardRuleMessage} from '@libs/SpendRuleChangeLogUtils'; @@ -121,10 +124,13 @@ type ResolverFn = ( policy: OnyxEntry, convertToDisplayString: CurrencyListActionsContextType['convertToDisplayString'], dateFnsLocale: LocaleContextProps['dateFnsLocale'], + isThreadReportParentAction: boolean, + personalDetails: OnyxEntry, ) => PolicyChangeLogMessageResult; // Reusable resolvers for action types that share the same handler -const categoryResolver: ResolverFn = (translate, action, policy) => getWorkspaceCategoryUpdateMessage(translate, action, policy); +const categoryResolver: ResolverFn = (translate, action, policy, convertToDisplayString, dateFnsLocale, isThreadReportParentAction, personalDetails) => + getWorkspaceCategoryUpdateMessage(translate, action, policy, isThreadReportParentAction, personalDetails); const taxResolver: ResolverFn = (translate, action) => getWorkspaceTaxUpdateMessage(translate, action); const tagModificationResolver: ResolverFn = (translate, action) => getCleanedTagName(getWorkspaceTagUpdateMessage(translate, action)); const copySettingsResolver: ResolverFn = (translate, action) => ({ @@ -262,6 +268,7 @@ const POLICY_CHANGE_LOG_RESOLVERS: Record = { [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.DELETE_CATEGORY]: categoryResolver, [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_CATEGORY]: categoryResolver, [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_NAME]: categoryResolver, + [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY]: categoryResolver, [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.ADD_BUDGET]: (translate, action, policy) => getAddedBudgetMessage(translate, action, policy), [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_BUDGET]: (translate, action, policy) => getUpdatedBudgetMessage(translate, action, policy), [CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.DELETE_BUDGET]: (translate, action, policy) => getDeletedBudgetMessage(translate, action, policy), @@ -317,19 +324,24 @@ function isHandledPolicyChangeLogAction(action: OnyxTypes.ReportAction): boolean type PolicyChangeLogContentProps = { action: OnyxTypes.ReportAction; policyID: string | undefined; + + /** Whether the action is shown at the top of its thread */ + isThreadReportParentAction?: boolean; }; -function PolicyChangeLogContent({action, policyID}: PolicyChangeLogContentProps) { +function PolicyChangeLogContent({action, policyID, isThreadReportParentAction = false}: PolicyChangeLogContentProps) { const {translate, dateFnsLocale} = useLocalize(); const {convertToDisplayString} = useCurrencyListActions(); const [policy] = useOnyx(`${ONYXKEYS.COLLECTION.POLICY}${policyID}`); + const categoryVisibilityAccountIDs = isActionOfType(action, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY) ? getOriginalMessage(action)?.accountIDs : undefined; + const [personalDetails] = usePersonalDetailsByIDs(categoryVisibilityAccountIDs); const resolver = POLICY_CHANGE_LOG_RESOLVERS[action.actionName]; if (!resolver) { return null; } - const message = resolver(translate, action, policy, convertToDisplayString, dateFnsLocale); + const message = resolver(translate, action, policy, convertToDisplayString, dateFnsLocale, isThreadReportParentAction, personalDetails); if (typeof message === 'object') { return ( diff --git a/src/types/onyx/OriginalMessage.ts b/src/types/onyx/OriginalMessage.ts index 898076ca27e4..f8d8c883a587 100644 --- a/src/types/onyx/OriginalMessage.ts +++ b/src/types/onyx/OriginalMessage.ts @@ -500,6 +500,19 @@ type OriginalMessagePolicyChangeLog = { connectionName?: AllConnectionName; categoryName?: string; + + /** Categories the members can see after a category visibility change, empty when they can see all categories */ + categoryNames?: string[]; + + /** Account IDs of the members whose category visibility changed, empty when it applies to everyone */ + accountIDs?: number[]; + + /** Whether the members already had a category visibility restriction before the change */ + hadRestriction?: boolean; + + /** Why the category visibility changed */ + reason?: ValueOf; + taxName?: string; updatedField?: string; oldMaxExpenseAmountNoReceipt?: number; diff --git a/tests/unit/ReportActionsUtilsTest.ts b/tests/unit/ReportActionsUtilsTest.ts index 896083114db8..18573aab8176 100644 --- a/tests/unit/ReportActionsUtilsTest.ts +++ b/tests/unit/ReportActionsUtilsTest.ts @@ -8571,6 +8571,197 @@ describe('ReportActionsUtils', () => { const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); expect(actual).toBe('changed the "Advertising" category description to not required (previously required)'); }); + + describe('category visibility', () => { + const BOB_ACCOUNT_ID = 1; + const CATHY_ACCOUNT_ID = 2; + const MANY_CATEGORY_NAMES = Array.from({length: 14}, (_, index) => `Category ${index + 1}`); + const MANY_ACCOUNT_IDS = Array.from({length: 12}, (_, index) => 100 + index); + + function buildSetCategoryVisibilityAction(originalMessage: ReportAction['originalMessage']) { + const action: ReportAction = { + reportActionID: '1', + actionName: CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY, + created: '', + originalMessage, + }; + return action; + } + + beforeEach(async () => { + const personalDetails: PersonalDetailsList = { + [BOB_ACCOUNT_ID]: {accountID: BOB_ACCOUNT_ID, displayName: 'Bob Sterling', login: 'bob@example.com'}, + [CATHY_ACCOUNT_ID]: {accountID: CATHY_ACCOUNT_ID, displayName: 'Cathy Parker', login: 'cathy@example.com'}, + }; + for (const accountID of MANY_ACCOUNT_IDS) { + personalDetails[accountID] = {accountID, displayName: `Member ${accountID}`, login: `member${accountID}@example.com`}; + } + await Onyx.set(ONYXKEYS.PERSONAL_DETAILS_LIST, personalDetails); + await waitForBatchedUpdates(); + }); + + it('says the admin set a member to see only the listed categories when they had no restriction', () => { + // Given an admin restricting Bob, who had no restriction, to two categories + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Meals', 'Fuel'], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: false, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + + // Then it uses "set" and quotes each category, so admins can tell which categories Bob now sees + expect(actual).toBe('set Bob Sterling to only see the "Meals" and "Fuel" categories'); + }); + + it('says the admin changed a member who was already restricted', () => { + // Given Bob, who was already restricted, being changed to a single category + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Meals'], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: true, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + + // Then it uses "changed" and the singular category wording + expect(actual).toBe('changed Bob Sterling to only see the "Meals" category'); + }); + + it('says a member can see all categories when the restriction is cleared', () => { + // Given Bob's restriction being cleared, which Auth sends as an empty category list + const action = buildSetCategoryVisibilityAction({ + categoryNames: [], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: true, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + + // Then it says Bob can see all categories + expect(actual).toBe('changed Bob Sterling to see all categories'); + }); + + it('says everyone when the change applies to every member', () => { + // Given a restriction applied to every member, which Auth sends as an empty member list + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Meals', 'Fuel'], + accountIDs: [], + hadRestriction: false, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + + // Then it names everyone instead of listing members + expect(actual).toBe('set everyone to only see the "Meals" and "Fuel" categories'); + }); + + it('shows a count for long category lists, and the full list at the top of the thread', () => { + // Given Cathy being changed to 14 categories + const action = buildSetCategoryVisibilityAction({ + categoryNames: MANY_CATEGORY_NAMES, + accountIDs: [CATHY_ACCOUNT_ID], + hadRestriction: true, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built for #admins and for the top of the thread + const adminsMessage = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + const threadMessage = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action, undefined, true); + + // Then #admins shows a count so the entry stays short, and the thread names every category + expect(adminsMessage).toBe('changed Cathy Parker to only see 14 categories'); + expect(threadMessage).toBe( + `Categories: ${MANY_CATEGORY_NAMES.slice(0, -1) + .map((name) => `"${name}"`) + .join(', ')}, and "Category 14"`, + ); + }); + + it('shows a count for long member lists, and the full list at the top of the thread', () => { + // Given 12 members being restricted to one category + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Fees'], + accountIDs: MANY_ACCOUNT_IDS, + hadRestriction: false, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built for #admins and for the top of the thread + const adminsMessage = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + const threadMessage = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action, undefined, true); + + // Then #admins shows a count, and the thread names every member + expect(adminsMessage).toBe('set 12 members to only see the "Fees" category'); + expect(threadMessage).toBe( + `Members: ${MANY_ACCOUNT_IDS.slice(0, -1) + .map((accountID) => `Member ${accountID}`) + .join(', ')}, and Member 111`, + ); + }); + + it('keeps the short message at the top of the thread when no list is long', () => { + // Given a change with short lists + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Meals', 'Fuel'], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: false, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + + // When the message is built for the top of the thread + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action, undefined, true); + + // Then it is the same as in #admins, since there is no hidden list to show + expect(actual).toBe('set Bob Sterling to only see the "Meals" and "Fuel" categories'); + }); + + it('uses the personal details passed in, so the row shows names from the component subscription', () => { + // Given Bob's details as the component's subscription returns them, with a newer name than the cache + const action = buildSetCategoryVisibilityAction({ + categoryNames: ['Meals'], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: false, + reason: CONST.POLICY.CATEGORY_VISIBILITY.REASON.SET_BY_ADMIN, + }); + const subscribedPersonalDetails: PersonalDetailsList = { + [BOB_ACCOUNT_ID]: {accountID: BOB_ACCOUNT_ID, displayName: 'Robert Sterling', login: 'bob@example.com'}, + }; + + // When the message is built with those details + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action, undefined, false, subscribedPersonalDetails); + + // Then it uses the subscribed name, so a name change shows without waiting for an unrelated render + expect(actual).toBe('set Robert Sterling to only see the "Meals" category'); + }); + + it.each([ + [CONST.POLICY.CATEGORY_VISIBILITY.REASON.CATEGORIES_DELETED, 'deleted'], + [CONST.POLICY.CATEGORY_VISIBILITY.REASON.CATEGORIES_DISABLED, 'disabled'], + ])('explains why the restriction was cleared when the reason is %s', (reason, verb) => { + // Given Bob's only category being removed, which clears his restriction automatically + const action = buildSetCategoryVisibilityAction({ + categoryNames: [], + accountIDs: [BOB_ACCOUNT_ID], + hadRestriction: true, + reason, + }); + + // When the message is built + const actual = ReportActionsUtils.getWorkspaceCategoryUpdateMessage(translateLocal, action); + + // Then it tells the admin why, so they know to review Bob's category visibility + expect(actual).toBe(`changed Bob Sterling to see all categories, since their only category was ${verb}. Update their category visibility if needed.`); + }); + }); }); describe('getLatestConciergeFeedbackActionID', () => { diff --git a/tests/unit/SystemMessageDisplayStateTest.ts b/tests/unit/SystemMessageDisplayStateTest.ts index 8f6e351974c6..18b0e3c3fbcf 100644 --- a/tests/unit/SystemMessageDisplayStateTest.ts +++ b/tests/unit/SystemMessageDisplayStateTest.ts @@ -78,6 +78,7 @@ describe('system message presentation', () => { CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.INVITE_TO_ROOM, CONST.REPORT.ACTIONS.TYPE.ROOM_CHANGE_LOG.LEAVE_ROOM, CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.UPDATE_NAME, + CONST.REPORT.ACTIONS.TYPE.POLICY_CHANGE_LOG.SET_CATEGORY_VISIBILITY, CONST.REPORT.ACTIONS.TYPE.REIMBURSED, CONST.REPORT.ACTIONS.TYPE.MOVED_TRANSACTION, CONST.REPORT.ACTIONS.TYPE.MOVED,