diff --git a/.changeset/rare-dancers-own.md b/.changeset/rare-dancers-own.md new file mode 100644 index 000000000000..358963661bef --- /dev/null +++ b/.changeset/rare-dancers-own.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Adds the missing `ignoreThreads` param fixing the issue not allowing ignoring threads when overriding retention policy diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx index a32df8a44580..2bdf5ff395f6 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.tsx @@ -152,6 +152,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => retentionMaxAge, retentionExcludePinned, retentionFilesOnly, + retentionIgnoreThreads, ...formData }) => { const data = getDirtyFields(formData, dirtyFields); @@ -172,6 +173,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => retentionMaxAge, retentionExcludePinned, retentionFilesOnly, + retentionIgnoreThreads, }), }); @@ -218,6 +220,7 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => const retentionMaxAgeField = useUniqueId(); const retentionExcludePinnedField = useUniqueId(); const retentionFilesOnlyField = useUniqueId(); + const retentionIgnoreThreads = useUniqueId(); return ( <> @@ -538,6 +541,18 @@ const EditRoomInfo = ({ room, onClickClose, onClickBack }: EditRoomInfoProps) => /> + + + {t('RetentionPolicy_DoNotPruneThreads')} + ( + + )} + /> + + {canViewEncrypted && ( diff --git a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts index 1cb76cadd335..fa25dab96f0d 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts +++ b/apps/meteor/client/views/room/contextualBar/Info/EditRoomInfo/useEditRoomInitialValues.ts @@ -34,6 +34,7 @@ export const useEditRoomInitialValues = (room: IRoomWithRetentionPolicy) => { retentionMaxAge: retention?.maxAge ?? retentionPolicy.maxAge, retentionExcludePinned: retention?.excludePinned ?? retentionPolicy.excludePinned, retentionFilesOnly: retention?.filesOnly ?? retentionPolicy.filesOnly, + retentionIgnoreThreads: retention?.ignoreThreads ?? retentionPolicy.ignoreThreads, }), }), [ diff --git a/apps/meteor/client/views/room/hooks/useRetentionPolicy.ts b/apps/meteor/client/views/room/hooks/useRetentionPolicy.ts index ce16df8bc329..1b048630ce74 100644 --- a/apps/meteor/client/views/room/hooks/useRetentionPolicy.ts +++ b/apps/meteor/client/views/room/hooks/useRetentionPolicy.ts @@ -8,6 +8,7 @@ type RetentionPolicySettings = { enabled: boolean; filesOnly: boolean; doNotPrunePinned: boolean; + ignoreThreads: boolean; appliesToChannels: boolean; maxAgeChannels: number; appliesToGroups: boolean; @@ -55,6 +56,14 @@ const extractExcludePinned = (room: IRoom, { doNotPrunePinned }: RetentionPolicy return doNotPrunePinned; }; +const extractIgnoreThreads = (room: IRoom, { ignoreThreads }: RetentionPolicySettings): boolean => { + if (hasRetentionPolicy(room) && room.retention.overrideGlobal) { + return room.retention.ignoreThreads; + } + + return ignoreThreads; +}; + const getMaxAge = (room: IRoom, { maxAgeChannels, maxAgeGroups, maxAgeDMs }: RetentionPolicySettings): number => { if (hasRetentionPolicy(room) && room.retention.overrideGlobal) { return room.retention.maxAge; @@ -81,6 +90,7 @@ export const useRetentionPolicy = ( isActive: boolean; filesOnly: boolean; excludePinned: boolean; + ignoreThreads: boolean; maxAge: number; } | undefined => { @@ -88,6 +98,7 @@ export const useRetentionPolicy = ( enabled: useSetting('RetentionPolicy_Enabled') as boolean, filesOnly: useSetting('RetentionPolicy_FilesOnly') as boolean, doNotPrunePinned: useSetting('RetentionPolicy_DoNotPrunePinned') as boolean, + ignoreThreads: useSetting('RetentionPolicy_DoNotPruneThreads') as boolean, appliesToChannels: useSetting('RetentionPolicy_AppliesToChannels') as boolean, maxAgeChannels: useSetting('RetentionPolicy_MaxAge_Channels') as number, appliesToGroups: useSetting('RetentionPolicy_AppliesToGroups') as boolean, @@ -105,6 +116,7 @@ export const useRetentionPolicy = ( isActive: isActive(room, settings), filesOnly: extractFilesOnly(room, settings), excludePinned: extractExcludePinned(room, settings), + ignoreThreads: extractIgnoreThreads(room, settings), maxAge: getMaxAge(room, settings), }; }; diff --git a/apps/meteor/server/models/raw/Rooms.ts b/apps/meteor/server/models/raw/Rooms.ts index 64bde1c32924..78efa845ba34 100644 --- a/apps/meteor/server/models/raw/Rooms.ts +++ b/apps/meteor/server/models/raw/Rooms.ts @@ -1838,13 +1838,12 @@ export class RoomsRaw extends BaseRaw implements IRoomsModel { return this.updateOne(query, update); } - // 5 saveRetentionIgnoreThreadsById(_id: IRoom['_id'], value: boolean): Promise { const query: Filter = { _id }; const update: UpdateFilter = { - [value === true ? '$set' : '$unset']: { - 'retention.ignoreThreads': true, + $set: { + 'retention.ignoreThreads': value === true, }, }; diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts index 041b37da9919..038409eceec9 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-flextab-room.ts @@ -56,10 +56,18 @@ export class HomeFlextabRoom { } get checkboxPruneMessages(): Locator { - return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Automatically prune old messages' }) }); + return this.page + .getByRole('dialog') + .locator('label', { has: this.page.getByRole('checkbox', { name: 'Automatically prune old messages' }) }); } get checkboxOverrideGlobalRetention(): Locator { - return this.page.locator('label', { has: this.page.getByRole('checkbox', { name: 'Override global retention policy' }) }); + return this.page + .getByRole('dialog') + .locator('label', { has: this.page.getByRole('checkbox', { name: 'Override global retention policy' }) }); + } + + get checkboxIgnoreThreads(): Locator { + return this.page.getByRole('dialog').locator('label', { has: this.page.getByRole('checkbox', { name: 'Do not prune Threads' }) }); } } diff --git a/apps/meteor/tests/e2e/retention-policy.spec.ts b/apps/meteor/tests/e2e/retention-policy.spec.ts index d17276a160af..c5db60384d92 100644 --- a/apps/meteor/tests/e2e/retention-policy.spec.ts +++ b/apps/meteor/tests/e2e/retention-policy.spec.ts @@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker'; import { createAuxContext } from './fixtures/createAuxContext'; import { Users } from './fixtures/userStates'; import { HomeChannel } from './page-objects'; -import { createTargetPrivateChannel, createTargetTeam, setSettingValueById } from './utils'; +import { createTargetTeam, createTargetPrivateChannel, getSettingValueById, setSettingValueById } from './utils'; import { test, expect } from './utils/test'; test.use({ storageState: Users.admin.state }); @@ -155,7 +155,10 @@ test.describe.serial('retention-policy', () => { }); test.describe('retention policy override', () => { + let ignoreThreadsSetting: boolean; + test.beforeAll(async ({ api }) => { + ignoreThreadsSetting = (await getSettingValueById(api, 'RetentionPolicy_DoNotPruneThreads')) as boolean; expect((await setSettingValueById(api, 'RetentionPolicy_MaxAge_Channels', 15)).status()).toBe(200); }); @@ -186,6 +189,31 @@ test.describe.serial('retention-policy', () => { await expect(poHomeChannel.tabs.room.getMaxAgeLabel('15')).toBeVisible(); await expect(poHomeChannel.tabs.room.inputRetentionMaxAge).toHaveValue('365'); }); + + test('should ignore threads be checked accordingly with the global default value', async () => { + await poHomeChannel.sidenav.openChat(targetChannel); + await poHomeChannel.tabs.btnRoomInfo.click(); + await poHomeChannel.tabs.room.btnEdit.click(); + await poHomeChannel.tabs.room.pruneAccordion.click(); + + await expect(poHomeChannel.tabs.room.checkboxIgnoreThreads).toBeChecked({ checked: ignoreThreadsSetting }); + }); + + test('should override ignore threads default value', async () => { + await poHomeChannel.sidenav.openChat(targetChannel); + await poHomeChannel.tabs.btnRoomInfo.click(); + await poHomeChannel.tabs.room.btnEdit.click(); + await poHomeChannel.tabs.room.pruneAccordion.click(); + await poHomeChannel.tabs.room.checkboxIgnoreThreads.click(); + await poHomeChannel.tabs.room.btnSave.click(); + await poHomeChannel.dismissToast(); + + await poHomeChannel.tabs.btnRoomInfo.click(); + await poHomeChannel.tabs.room.btnEdit.click(); + await poHomeChannel.tabs.room.pruneAccordion.click(); + + await expect(poHomeChannel.tabs.room.checkboxIgnoreThreads).toBeChecked({ checked: !ignoreThreadsSetting }); + }); }); }); });