From 60f96bc2018c78daec072088696bc72b559553c9 Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Tue, 26 Sep 2023 16:40:09 +0530 Subject: [PATCH] chore: handle moving & removing tags with subtags into/out of vaults (#2528) --- .../src/Domain/Item/ItemManagerInterface.ts | 1 + .../services/src/Domain/Vault/VaultService.ts | 40 ++++++++++++++++--- .../snjs/lib/Services/Items/ItemManager.ts | 12 ++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/services/src/Domain/Item/ItemManagerInterface.ts b/packages/services/src/Domain/Item/ItemManagerInterface.ts index aa2ef6bf3..2715cd993 100644 --- a/packages/services/src/Domain/Item/ItemManagerInterface.ts +++ b/packages/services/src/Domain/Item/ItemManagerInterface.ts @@ -116,6 +116,7 @@ export interface ItemManagerInterface extends AbstractService { getNoteCount(): number getDisplayableTags(): SNTag[] getTagChildren(itemToLookupUuidFor: SNTag): SNTag[] + getDeepTagChildren(itemToLookupUuidFor: SNTag): SNTag[] getTagParent(itemToLookupUuidFor: SNTag): SNTag | undefined getDisplayableTagParent(itemToLookupUuidFor: SNTag): SNTag | undefined isValidTagParent(parentTagToLookUpUuidFor: SNTag, childToLookUpUuidFor: SNTag): boolean diff --git a/packages/services/src/Domain/Vault/VaultService.ts b/packages/services/src/Domain/Vault/VaultService.ts index f662fb921..a3480494a 100644 --- a/packages/services/src/Domain/Vault/VaultService.ts +++ b/packages/services/src/Domain/Vault/VaultService.ts @@ -8,11 +8,13 @@ import { IconType, KeySystemIdentifier, KeySystemRootKeyStorageMode, + SNTag, SharedVaultListingInterface, VaultListingInterface, VaultListingMutator, isFile, isNote, + isTag, } from '@standardnotes/models' import { VaultServiceInterface } from './VaultServiceInterface' import { ChangeVaultKeyOptionsDTO } from './UseCase/ChangeVaultKeyOptionsDTO' @@ -161,20 +163,39 @@ export class VaultService }) if (areAnyLinkedItemsInOtherVaults) { + const reason = + 'This item is linked to other items that are not in the same vault. Please move those items to this vault first.' this.alerts .alertV2({ title: 'Cannot move item to vault', - text: 'This item is linked to other items that are not in the same vault. Please move those items to this vault first.', + text: reason, }) .catch(console.error) - - return Result.fail( - 'This item is linked to other items that are not in the same vault. Please move those items to this vault first.', - ) + return Result.fail(reason) } } - await this._moveItemsToVault.execute({ vault, items: [item] }) + let moveableSubtags: SNTag[] = [] + if (isTag(item)) { + const deepSubtags = this.items.getDeepTagChildren(item) + const anySubtagIsInOtherVault = deepSubtags.some((subtag) => { + return subtag.key_system_identifier && subtag.key_system_identifier !== vault.systemIdentifier + }) + if (anySubtagIsInOtherVault) { + const reason = + 'One or more subtags are in other vaults. Please remove those subtags from the vaults or move them to this vault first.' + this.alerts + .alertV2({ + title: 'Cannot move item to vault', + text: reason, + }) + .catch(console.error) + return Result.fail(reason) + } + moveableSubtags = deepSubtags + } + + await this._moveItemsToVault.execute({ vault, items: [item, ...moveableSubtags] }) return Result.ok(this.items.findSureItem(item.uuid)) } @@ -189,6 +210,13 @@ export class VaultService throw new Error('Attempting to remove item from locked vault') } + if (isTag(item)) { + const deepSubtags = this.items.getDeepTagChildren(item) + for (const subtag of deepSubtags) { + await this._removeItemFromVault.execute({ item: subtag }) + } + } + await this._removeItemFromVault.execute({ item }) return this.items.findSureItem(item.uuid) } diff --git a/packages/snjs/lib/Services/Items/ItemManager.ts b/packages/snjs/lib/Services/Items/ItemManager.ts index cb38606e4..22684c013 100644 --- a/packages/snjs/lib/Services/Items/ItemManager.ts +++ b/packages/snjs/lib/Services/Items/ItemManager.ts @@ -702,6 +702,18 @@ export class ItemManager extends Services.AbstractService implements Services.It return tags.filter((tag) => tag.parentId === itemToLookupUuidFor.uuid) } + public getDeepTagChildren(itemToLookupUuidFor: Models.SNTag): Models.SNTag[] { + const allChildren: Models.SNTag[] = [] + + const children = this.getTagChildren(itemToLookupUuidFor) + for (const child of children) { + allChildren.push(child) + allChildren.push(...this.getDeepTagChildren(child)) + } + + return allChildren + } + public isTagAncestor(tagToLookUpUuidFor: Models.SNTag, childToLookUpUuidFor: Models.SNTag): boolean { const tag = this.findItem(childToLookUpUuidFor.uuid) if (!tag) {