import { FiltersMap, Tags } from '@wix/bex-core'; import { cairoAssignTagsToEntities, cairoUndoClicked } from '@wix/bex-core/bi'; import { TagsBulkAssignPopoverState, TagsBulkAssignPopoverStateParams, } from './TagsBulkAssignPopoverState'; export interface BulkUpdateTagsParams { entityIds: string[]; assignTags: Tags; unassignTags: Tags; } export interface TagsBulkAssignSyncStateParams extends Pick< TagsBulkAssignPopoverStateParams, 'bulkUpdateTags' | 'collectionState' | 'getTags' | 'bulkUpdateTagsShowUndoToast' > { container: TagsBulkAssignPopoverState['container']; optimisticActions: TagsBulkAssignPopoverState['optimisticActions']; tagsBIReporter: TagsBulkAssignPopoverState['tagsBIReporter']; } export const MAX_SELECTED_ENTITIES_FOR_BULK_ASSIGN_SYNC = 100; export class TagsBulkAssignSyncState { readonly collectionState; readonly optimisticActions; readonly container; readonly tagsBIReporter; readonly bulkUpdateTags; readonly getTags; readonly showUndoToast: boolean; constructor(params: TagsBulkAssignSyncStateParams) { const { collectionState, optimisticActions, container, tagsBIReporter, getTags, bulkUpdateTags, bulkUpdateTagsShowUndoToast: showUndoToast = true, } = params; this.collectionState = collectionState; this.optimisticActions = optimisticActions; this.container = container; this.tagsBIReporter = tagsBIReporter; this.getTags = getTags; this.bulkUpdateTags = bulkUpdateTags; this.showUndoToast = showUndoToast; } get canUseBulkSync() { const { allSelectedItemsFetched, selectedCountOrTotal } = this.collectionState.bulkSelect; return ( allSelectedItemsFetched && selectedCountOrTotal <= MAX_SELECTED_ENTITIES_FOR_BULK_ASSIGN_SYNC ); } async applyChanges({ newAssignedTagIds, newUnassignedTagIds, searchValue, }: { newAssignedTagIds: string[]; newUnassignedTagIds: string[]; searchValue: string; }) { this._reportApplyBi({ newAssignedTagIds, newUnassignedTagIds, searchValue, }); const items = this._calcOptimisticItems({ newAssignedTagIds, newUnassignedTagIds, }); const entityIds = this.collectionState.bulkSelect.selectedIds; this.optimisticActions.updateMany(items, { keepPosition: true, submit: async () => { return this.bulkUpdateTags({ entityIds, assignTags: { privateTags: { tagIds: newAssignedTagIds } }, unassignTags: { privateTags: { tagIds: newUnassignedTagIds } }, }); }, successToast: { biName: 'cairo-update-bulk-assign-tags-success', message: this.container.translate( 'cairo.tags.applyChanges.toast.success', ), }, showUndoToast: this.showUndoToast, errorToast: () => ({ biName: 'cairo-update-bulk-assign-tags-error', message: this.container.translate( 'cairo.tags.collectionPage.toast.update.error', ), }), onUndo: this._reportUndoBi, }); } private _calculateUpdatedTagIds({ item, getTags, newAssignedTagIds, newUnassignedTagIds, }: { item: T; getTags?: (item: T) => Tags; newAssignedTagIds: string[]; newUnassignedTagIds: string[]; }) { const tags: Tags = (item as any).tags ?? getTags?.(item); const currentTagIds = tags?.privateTags?.tagIds || []; const updatedTagIds = Array.from( new Set( [...currentTagIds, ...newAssignedTagIds].filter( (tagId) => !newUnassignedTagIds.includes(tagId), ), ), ); return updatedTagIds; } private _calcOptimisticItems({ newAssignedTagIds, newUnassignedTagIds, }: { newAssignedTagIds: string[]; newUnassignedTagIds: string[]; }) { return this.collectionState.result.items.map((item: T) => { const selectedIds = this.collectionState.bulkSelect.selectedIds; const itemKey = this.collectionState.itemKey(item); if (!selectedIds.includes(itemKey)) { return item; } const updatedTagIds = this._calculateUpdatedTagIds({ newAssignedTagIds, newUnassignedTagIds, item, getTags: this.getTags, }); return { ...item, tags: { privateTags: { tagIds: updatedTagIds } } }; }); } private _reportApplyBi({ newAssignedTagIds, newUnassignedTagIds, searchValue, }: { newAssignedTagIds: string[]; newUnassignedTagIds: string[]; searchValue: string; }) { let actionName = 'Both'; if (newAssignedTagIds.length === 0) { actionName = 'Remove'; } else if (newUnassignedTagIds.length === 0) { actionName = 'Assign'; } const { selectedIds: selectedItemsIds } = this.collectionState.bulkSelect; this.tagsBIReporter.reportBi( cairoAssignTagsToEntities({ actionName, isFromSearch: searchValue !== '', itemIds: JSON.stringify(selectedItemsIds), numItems: selectedItemsIds.length, assignedTags: JSON.stringify(newAssignedTagIds), unAssignedTags: JSON.stringify(newUnassignedTagIds), origin: 'Assign Tags Modal', }), ); } private _reportUndoBi = () => { this.tagsBIReporter.reportBi( cairoUndoClicked({ actionName: 'Save', changedAttributes: 'Tags Assignment', }), ); }; }