mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2025-07-24 17:31:52 +00:00
Rollback visibility rules cleanup (#4426)
* Revert "[ACS-9369] Updated rule-migration-guide.md to include missed rule (#4420)" This reverts commitb3e2af7f0f
. * Revert "[ACS-9369] Resolved issues where visibility rules with a single element array would log errors (#4416)" This reverts commit4e33f1126d
. * Revert "[ACS-8694] Cleanup of visibility rules for extensions in ACA (#4140)" This reverts commitf1c4dcf45d
.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -15,9 +15,7 @@
|
||||
"id": "app.toolbar.rules.separator",
|
||||
"type": "separator",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"app.selection.folder"
|
||||
]
|
||||
"visible": "app.selection.folder"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -26,9 +24,7 @@
|
||||
"description": "ACA_FOLDER_RULES.MENU.CREATE_RULES_DESC",
|
||||
"icon": "add",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"rules.canCreateFolderRule"
|
||||
]
|
||||
"visible": "rules.canCreateFolderRule"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -37,9 +33,7 @@
|
||||
"description": "ACA_FOLDER_RULES.MENU.LINK_RULES_DESC",
|
||||
"icon": "link",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"rules.canLinkFolderRule"
|
||||
]
|
||||
"visible": "rules.canLinkFolderRule"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -51,9 +45,7 @@
|
||||
"id": "app.toolbar.rules.separator",
|
||||
"type": "separator",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"app.selection.folder"
|
||||
]
|
||||
"visible": "app.selection.folder"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -62,9 +54,7 @@
|
||||
"description": "ACA_FOLDER_RULES.MENU.CREATE_RULES_DESC",
|
||||
"icon": "add",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"rules.canCreateFolderRule"
|
||||
]
|
||||
"visible": "rules.canCreateFolderRule"
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -73,9 +63,7 @@
|
||||
"description": "ACA_FOLDER_RULES.MENU.LINK_RULES_DESC",
|
||||
"icon": "link",
|
||||
"rules": {
|
||||
"visible": [
|
||||
"rules.canLinkFolderRule"
|
||||
]
|
||||
"visible": "rules.canLinkFolderRule"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -77,7 +77,7 @@ export class AcaFolderRulesModule {
|
||||
translation.addTranslationFolder('folder-rules', 'assets/folder-rules');
|
||||
|
||||
extensions.setEvaluators({
|
||||
'rules.isFolderRulesEnabled': rules.isFolderRulesEnabled
|
||||
'rules.canManageFolderRules': rules.canManageFolderRules
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,9 @@
|
||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { isFolderRulesEnabled } from './folder-rules.rules';
|
||||
import { AcaRuleContext } from '@alfresco/aca-shared/rules';
|
||||
import { canManageFolderRules, isFolderRulesEnabled } from './folder-rules.rules';
|
||||
import { NodeEntry } from '@alfresco/js-api';
|
||||
|
||||
describe('Folder Rules Visibility Rules', () => {
|
||||
describe('isFolderRulesEnabled', () => {
|
||||
@@ -48,4 +50,44 @@ describe('Folder Rules Visibility Rules', () => {
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('canManageFolderRules', () => {
|
||||
let context: AcaRuleContext;
|
||||
|
||||
beforeEach(() => {
|
||||
context = {
|
||||
appConfig: {
|
||||
get: () => true
|
||||
},
|
||||
selection: {
|
||||
folder: {} as any
|
||||
},
|
||||
navigation: {
|
||||
url: '/personal-files'
|
||||
},
|
||||
permissions: {
|
||||
check: () => true
|
||||
}
|
||||
} as any;
|
||||
});
|
||||
|
||||
it('should allow creating a rule for the selected folder', () => {
|
||||
const result = canManageFolderRules(context);
|
||||
expect(result).toEqual(true);
|
||||
});
|
||||
|
||||
it('should not allow creating a rule if no folder selected', () => {
|
||||
context.selection.folder = null;
|
||||
|
||||
const result = canManageFolderRules(context);
|
||||
expect(result).toEqual(false);
|
||||
});
|
||||
|
||||
it('should not allow creating a rule if the selected node is a smart folder', () => {
|
||||
context.selection.first = { entry: { aspectNames: ['smf:customConfigSmartFolder'], isFolder: true } } as NodeEntry;
|
||||
const result = canManageFolderRules(context);
|
||||
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -22,6 +22,10 @@
|
||||
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { AcaRuleContext } from '@alfresco/aca-shared/rules';
|
||||
import { AcaRuleContext, canEditFolder, hasFolderSelected, isNotFavorites, isSmartFolder } from '@alfresco/aca-shared/rules';
|
||||
|
||||
export const isFolderRulesEnabled = (context: AcaRuleContext) => context.appConfig.get<boolean>('plugins.folderRules', false);
|
||||
export const isFolderRulesAllowed = (context: AcaRuleContext) =>
|
||||
isFolderRulesEnabled(context) && canEditFolder(context) && hasFolderSelected(context) && isNotFavorites(context) && !isSmartFolder(context);
|
||||
|
||||
export const canManageFolderRules = (context: AcaRuleContext): boolean => isFolderRulesAllowed(context);
|
||||
|
@@ -29,9 +29,7 @@
|
||||
"click": "aos.openWith.office"
|
||||
},
|
||||
"rules": {
|
||||
"visible": [
|
||||
"aos.canOpenWithOffice"
|
||||
]
|
||||
"visible": "aos.canOpenWithOffice"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -47,9 +45,7 @@
|
||||
"click": "aos.openWith.office"
|
||||
},
|
||||
"rules": {
|
||||
"visible": [
|
||||
"aos.canOpenWithOffice"
|
||||
]
|
||||
"visible": "aos.canOpenWithOffice"
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -67,9 +63,7 @@
|
||||
"click": "aos.openWith.office"
|
||||
},
|
||||
"rules": {
|
||||
"visible": [
|
||||
"aos.canOpenWithOffice"
|
||||
]
|
||||
"visible": "aos.canOpenWithOffice"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@@ -163,42 +163,74 @@ export class ContentServiceExtensionModule {
|
||||
});
|
||||
|
||||
extensions.setEvaluators({
|
||||
canCopyNode: rules.canCopyNode,
|
||||
canToggleJoinLibrary: rules.canToggleJoinLibrary,
|
||||
canEditFolder: rules.canEditFolder,
|
||||
isTrashcanItemSelected: rules.isTrashcanItemSelected,
|
||||
canViewFile: rules.canViewFile,
|
||||
canLeaveLibrary: rules.canLeaveLibrary,
|
||||
canToggleSharedLink: rules.canToggleSharedLink,
|
||||
canToggleFileLock: rules.canToggleFileLock,
|
||||
canShowInfoDrawer: rules.canShowInfoDrawer,
|
||||
canManageFileVersions: rules.canManageFileVersions,
|
||||
canManagePermissions: rules.canManagePermissions,
|
||||
canToggleEditOffline: rules.canToggleEditOffline,
|
||||
canToggleFavorite: rules.canToggleFavorite,
|
||||
isLibraryManager: rules.isLibraryManager,
|
||||
canEditAspects: rules.canEditAspects,
|
||||
isSmartFolder: rules.isSmartFolder,
|
||||
isMultiSelection: rules.isMultiselection,
|
||||
canShowExpand: rules.canShowExpand,
|
||||
canInfoPreview: rules.canInfoPreview,
|
||||
|
||||
'app.selection.canDelete': rules.canDeleteSelection,
|
||||
'app.selection.file.canUnlock': rules.canUnlockFile,
|
||||
'app.selection.file.canLock': rules.canLockFile,
|
||||
'app.selection.canDownload': rules.canDownloadSelection,
|
||||
'app.selection.notEmpty': rules.hasSelection,
|
||||
'app.selection.canUnshare': rules.canUnshareNodes,
|
||||
'app.selection.canAddFavorite': rules.canAddFavorite,
|
||||
'app.selection.canRemoveFavorite': rules.canRemoveFavorite,
|
||||
'app.selection.first.canUpdate': rules.canUpdateSelectedNode,
|
||||
'app.selection.file': rules.hasFileSelected,
|
||||
'app.selection.file.canShare': rules.canShareFile,
|
||||
'app.selection.file.isShared': rules.isShared,
|
||||
'app.selection.file.isLocked': rules.hasLockedFiles,
|
||||
'app.selection.file.isLockOwner': rules.isUserWriteLockOwner,
|
||||
'app.selection.file.canUploadVersion': rules.canUploadVersion,
|
||||
'app.selection.library': rules.hasLibrarySelected,
|
||||
'app.selection.isPrivateLibrary': rules.isPrivateLibrary,
|
||||
'app.selection.hasLibraryRole': rules.hasLibraryRole,
|
||||
'app.selection.hasNoLibraryRole': rules.hasNoLibraryRole,
|
||||
'app.selection.folder': rules.hasFolderSelected,
|
||||
'app.selection.folder.canUpdate': rules.canUpdateSelectedFolder,
|
||||
'app.selection.displayedKnowledgeRetrievalButton': rules.canDisplayKnowledgeRetrievalButton,
|
||||
|
||||
'app.navigation.folder.canCreate': rules.canCreateFolder,
|
||||
'app.navigation.folder.canUpload': rules.canUpload,
|
||||
'app.navigation.isTrashcan': rules.isTrashcan,
|
||||
'app.navigation.isNotTrashcan': rules.isNotTrashcan,
|
||||
'app.navigation.isLibraries': rules.isLibraries,
|
||||
'app.navigation.isLibraryFiles': rules.isLibraryFiles,
|
||||
'app.navigation.isPersonalFiles': rules.isPersonalFiles,
|
||||
'app.navigation.isNotLibraries': rules.isNotLibraries,
|
||||
'app.navigation.isSharedFiles': rules.isSharedFiles,
|
||||
'app.navigation.isNotSharedFiles': rules.isNotSharedFiles,
|
||||
'app.navigation.isFavorites': rules.isFavorites,
|
||||
'app.navigation.isNotFavorites': rules.isNotFavorites,
|
||||
'app.navigation.isRecentFiles': rules.isRecentFiles,
|
||||
'app.navigation.isNotRecentFiles': rules.isNotRecentFiles,
|
||||
'app.navigation.isSearchResults': rules.isSearchResults,
|
||||
'app.navigation.isNotSearchResults': rules.isNotSearchResults,
|
||||
'app.navigation.isPreview': rules.isPreview,
|
||||
'app.navigation.isDetails': rules.isDetails,
|
||||
'app.navigation.isSharedPreview': rules.isSharedPreview,
|
||||
'app.navigation.isFavoritesPreview': rules.isFavoritesPreview,
|
||||
'app.navigation.isSharedFileViewer': rules.isSharedFileViewer,
|
||||
'app.navigation.isNotDetails': rules.isNotDetails,
|
||||
|
||||
'repository.isQuickShareEnabled': rules.hasQuickShareEnabled,
|
||||
'user.isAdmin': rules.isAdmin,
|
||||
'app.canShowLogout': rules.canShowLogout,
|
||||
'app.isContentServiceEnabled': rules.isContentServiceEnabled,
|
||||
'app.isUploadSupported': rules.isUploadSupported,
|
||||
'app.canCreateLibrary': rules.canCreateLibrary,
|
||||
'app.areTagsEnabled': rules.areTagsEnabled,
|
||||
'app.areCategoriesEnabled': rules.areCategoriesEnabled
|
||||
});
|
||||
|
@@ -23,10 +23,9 @@
|
||||
*/
|
||||
|
||||
import * as app from './app.rules';
|
||||
import { getFileExtension } from './app.rules';
|
||||
import { TestRuleContext } from './test-rule-context';
|
||||
import { NodeEntry, RepositoryInfo, StatusInfo } from '@alfresco/js-api';
|
||||
import { ProfileState } from '@alfresco/adf-extensions';
|
||||
import { getFileExtension } from './app.rules';
|
||||
import { AppConfigService } from '@alfresco/adf-core';
|
||||
|
||||
describe('app.evaluators', () => {
|
||||
@@ -106,6 +105,20 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canShowExpand', () => {
|
||||
it('should return false when isLibraries returns true', () => {
|
||||
context.navigation.url = '/libraries';
|
||||
|
||||
expect(app.canShowExpand(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false when isDetails returns true', () => {
|
||||
context.navigation.url = '/details';
|
||||
|
||||
expect(app.canShowExpand(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasLockedFiles', () => {
|
||||
it('should return [false] if selection not present', () => {
|
||||
context = {} as any;
|
||||
@@ -442,6 +455,34 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canManagePermissions', () => {
|
||||
it('should return false if user cannot update the selected node', () => {
|
||||
context.permissions.check = spyOn(context.permissions, 'check').and.returnValue(false);
|
||||
|
||||
expect(app.canManagePermissions(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the context is trashcan', () => {
|
||||
context.navigation = { url: '/trashcan' };
|
||||
|
||||
expect(app.canManagePermissions(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if many nodes are selected', () => {
|
||||
context.selection.count = 2;
|
||||
expect(app.canManagePermissions(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if the selected node is a smart folder', () => {
|
||||
context.selection.first = { entry: { aspectNames: ['smf:customConfigSmartFolder'], isFolder: true } } as NodeEntry;
|
||||
expect(app.canManagePermissions(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if user can update the selected node and it is not a trashcan nor smart folder nor multiselect', () => {
|
||||
expect(app.canManagePermissions(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('areTagsEnabled', () => {
|
||||
it('should call context.appConfig.get with correct parameters', () => {
|
||||
context.appConfig = { get: jasmine.createSpy() } as any;
|
||||
@@ -650,6 +691,34 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canCopyNode', () => {
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.selection.isEmpty = true;
|
||||
expect(app.canCopyNode(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when selection exists and user is in trashcan', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canCopyNode(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when selection exists and user is in library', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.navigation.url = '/test/libraries';
|
||||
expect(app.canCopyNode(context)).toBeFalse();
|
||||
|
||||
context.navigation.url = '/search-libraries/test';
|
||||
expect(app.canCopyNode(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when selection exists and user is outside library and trashcan', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.navigation.url = '/personal-files';
|
||||
expect(app.canCopyNode(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canAddFavorite', () => {
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.selection.isEmpty = true;
|
||||
@@ -897,6 +966,35 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canUnshareNodes', () => {
|
||||
it('should return false when selection is empty', () => {
|
||||
context.selection.isEmpty = true;
|
||||
expect(app.canUnshareNodes(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when permission check fails', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.nodes = [{} as any];
|
||||
context.permissions = { check: () => false };
|
||||
expect(app.canUnshareNodes(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when permission requirements are met', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.nodes = [{} as any];
|
||||
context.permissions = { check: () => true };
|
||||
expect(app.canUnshareNodes(context)).toBeTrue();
|
||||
});
|
||||
|
||||
it('should verify if user have delete permission on selected node', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.nodes = [{ allowableOperationsOnTarget: ['delete'] } as any];
|
||||
spyOn(context.permissions, 'check');
|
||||
app.canUnshareNodes(context);
|
||||
expect(context.permissions.check).toHaveBeenCalledWith(context.selection.nodes, ['delete'], { target: 'allowableOperationsOnTarget' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasSelection', () => {
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.selection.isEmpty = true;
|
||||
@@ -954,6 +1052,70 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canCreateLibrary', () => {
|
||||
it('should return false when content service is disabled', () => {
|
||||
context.appConfig = { get: () => false } as any;
|
||||
expect(app.canCreateLibrary(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is outside libraries', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/favorite/test';
|
||||
expect(app.canCreateLibrary(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when content service is enabled and user is in libraries', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/test/libraries';
|
||||
expect(app.canCreateLibrary(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canUpload', () => {
|
||||
it('should return false when content service is disabled', () => {
|
||||
context.appConfig = { get: () => false } as any;
|
||||
expect(app.canUpload(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is outside personal files or libraries', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/favorite/test';
|
||||
expect(app.canUpload(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when current folder does not exist', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.navigation.currentFolder = null;
|
||||
expect(app.canUpload(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when permission check fails', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.navigation.currentFolder = {} as any;
|
||||
context.permissions = { check: () => false };
|
||||
expect(app.canUpload(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when permission requirements are met', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.navigation.currentFolder = {} as any;
|
||||
context.permissions = { check: () => true };
|
||||
expect(app.canUpload(context)).toBeTrue();
|
||||
});
|
||||
|
||||
it('should verify if user has create permission on current folder', () => {
|
||||
context.appConfig = { get: () => true } as any;
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.navigation.currentFolder = { allowableOperations: ['create'] } as any;
|
||||
spyOn(context.permissions, 'check');
|
||||
app.canCreateFolder(context);
|
||||
expect(context.permissions.check).toHaveBeenCalledWith(context.navigation.currentFolder, ['create']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasFileSelected', () => {
|
||||
it('should return false when no file is selected', () => {
|
||||
context.selection.file = null;
|
||||
@@ -1014,6 +1176,18 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasNoLibraryRole', () => {
|
||||
it('should return false when library has a role', () => {
|
||||
context.selection.library = { entry: { role: 'test' } } as any;
|
||||
expect(app.hasNoLibraryRole(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when library has no role', () => {
|
||||
context.selection.library = { entry: { role: '' } } as any;
|
||||
expect(app.hasNoLibraryRole(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isMultiselection', () => {
|
||||
it('should return false when there is no or single selection', () => {
|
||||
context.selection.isEmpty = true;
|
||||
@@ -1148,35 +1322,58 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canToggleFileLock', () => {
|
||||
beforeEach(() => {
|
||||
context.profile = {} as ProfileState;
|
||||
describe('isTrashcanItemSelected', () => {
|
||||
it('should return false when user is not in trashcan', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
expect(app.isTrashcanItemSelected(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when permission requirements are not met, regardless of file lock', () => {
|
||||
context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as NodeEntry;
|
||||
context.permissions = { check: () => false };
|
||||
expect(app.canToggleFileLock(context)).toBeFalse();
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.navigation.url = '/trashcan/test';
|
||||
context.selection.isEmpty = true;
|
||||
expect(app.isTrashcanItemSelected(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when file has no lock and permission requirements are met', () => {
|
||||
context.selection.file = { entry: { properties: {} } } as NodeEntry;
|
||||
context.permissions = { check: () => true };
|
||||
expect(app.canToggleFileLock(context)).toBeTrue();
|
||||
it('should return true when user is in trashcan and node is selected', () => {
|
||||
context.navigation.url = '/trashcan/test';
|
||||
context.selection.isEmpty = false;
|
||||
expect(app.isTrashcanItemSelected(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canViewFile', () => {
|
||||
it('should return false when user is in trashcan', () => {
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canViewFile(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when file is locked and permission requirements are met', () => {
|
||||
context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as NodeEntry;
|
||||
context.profile.id = 'test1';
|
||||
context.permissions = { check: () => true };
|
||||
expect(app.canToggleFileLock(context)).toBeTrue();
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.file = null;
|
||||
expect(app.canViewFile(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when file is locked and user is the owner of the lock', () => {
|
||||
context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test1' } } } } as NodeEntry;
|
||||
context.profile.id = 'test1';
|
||||
context.permissions = { check: () => false };
|
||||
expect(app.canToggleFileLock(context)).toBeTrue();
|
||||
it('should return true when user is not in trashcan and file is selected', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.file = {} as any;
|
||||
expect(app.canViewFile(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canLeaveLibrary', () => {
|
||||
it('should return false when no library is selected', () => {
|
||||
context.selection.library = null;
|
||||
expect(app.canLeaveLibrary(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user does not have library role', () => {
|
||||
context.selection.library = { entry: { role: null } } as any;
|
||||
expect(app.canLeaveLibrary(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when user has a library role', () => {
|
||||
context.selection.library = { entry: { role: 'test' } } as any;
|
||||
expect(app.canLeaveLibrary(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1209,6 +1406,136 @@ describe('app.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('canShowInfoDrawer', () => {
|
||||
it('should return false when nothing is selected', () => {
|
||||
context.selection.isEmpty = true;
|
||||
expect(app.canShowInfoDrawer(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is in libraries or trashcan or details', () => {
|
||||
context.selection.isEmpty = false;
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canShowInfoDrawer(context)).toBeFalse();
|
||||
|
||||
context.navigation.url = '/test/libraries';
|
||||
expect(app.canShowInfoDrawer(context)).toBeFalse();
|
||||
|
||||
context.navigation.url = '/test/details';
|
||||
expect(app.canShowInfoDrawer(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when selection exists and user is not in trashcan, libraries or details', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.isEmpty = false;
|
||||
expect(app.canShowInfoDrawer(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canManageFileVersions', () => {
|
||||
it('should return false when no file is selected', () => {
|
||||
context.selection.file = null;
|
||||
expect(app.canManageFileVersions(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is in trashcan', () => {
|
||||
context.selection.file = {} as any;
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canManageFileVersions(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when locked file is selected', () => {
|
||||
context.selection.file = {} as any;
|
||||
context.selection.nodes = [{ entry: { isFile: true, isLocked: true } } as any];
|
||||
context.navigation.url = '/personal-files/test';
|
||||
expect(app.canManageFileVersions(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when non-locked file is selected', () => {
|
||||
context.selection.file = {} as any;
|
||||
context.selection.nodes = [{ entry: { isFile: true, isLocked: false } } as any];
|
||||
context.navigation.url = '/personal-files/test';
|
||||
expect(app.canManageFileVersions(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canToggleEditOffline', () => {
|
||||
beforeEach(() => {
|
||||
context.profile = {} as any;
|
||||
});
|
||||
|
||||
it('should return false when no file is selected', () => {
|
||||
context.selection.file = null;
|
||||
expect(app.canToggleEditOffline(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is in trashcan', () => {
|
||||
context.selection.file = {} as any;
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canToggleEditOffline(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user cannot lock or unlock files', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test' } } } } as any;
|
||||
context.profile.id = 'test1';
|
||||
context.permissions = { check: () => false };
|
||||
expect(app.canToggleEditOffline(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when user can lock file', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.file = {} as any;
|
||||
context.permissions = { check: () => true };
|
||||
expect(app.canToggleEditOffline(context)).toBeTrue();
|
||||
});
|
||||
|
||||
it('should return true when user can unlock file', () => {
|
||||
context.navigation.url = '/personal-files/test';
|
||||
context.selection.file = { entry: { properties: { 'cm:lockType': 'WRITE_LOCK', 'cm:lockOwner': { id: 'test1' } } } } as any;
|
||||
context.profile.id = 'test1';
|
||||
expect(app.canToggleEditOffline(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('canInfoPreview', () => {
|
||||
it('should return false when user is not is search results page', () => {
|
||||
context.navigation.url = '/trashcan/test';
|
||||
expect(app.canInfoPreview(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when multiple nodes are selected', () => {
|
||||
context.navigation.url = '/search/test';
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.count = 5;
|
||||
expect(app.canInfoPreview(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when folder is selected', () => {
|
||||
context.navigation.url = '/search/test';
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.count = 1;
|
||||
context.selection.folder = {} as any;
|
||||
expect(app.canInfoPreview(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return false when user is in preview', () => {
|
||||
context.navigation.url = '/preview/test';
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.count = 1;
|
||||
context.selection.folder = null;
|
||||
expect(app.canInfoPreview(context)).toBeFalse();
|
||||
});
|
||||
|
||||
it('should return true when user is in search results page and single file is selected', () => {
|
||||
context.navigation.url = '/search/test';
|
||||
context.selection.isEmpty = false;
|
||||
context.selection.count = 1;
|
||||
context.selection.folder = null;
|
||||
context.selection.file = {} as any;
|
||||
expect(app.canInfoPreview(context)).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSmartFolder', () => {
|
||||
it('should return false when there is no selection', () => {
|
||||
context.selection.isEmpty = true;
|
||||
|
@@ -94,15 +94,35 @@ export const isContentServiceEnabled = (context: AcaRuleContext): boolean => {
|
||||
return flag === true || flag === 'true';
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if upload action is supported for the given context
|
||||
* JSON ref: `app.isUploadSupported`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const isUploadSupported = (context: AcaRuleContext): boolean =>
|
||||
[isContentServiceEnabled(context), navigation.isPersonalFiles(context) || navigation.isLibraryContent(context), canUpload(context)].every(Boolean);
|
||||
/**
|
||||
* Checks if user can copy selected node.
|
||||
* JSON ref: `app.canCopyNode`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canCopyNode = (context: RuleContext): boolean =>
|
||||
[hasSelection(context), navigation.isNotTrashcan(context), navigation.isNotLibraries(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can mark selected nodes as **Favorite**.
|
||||
* JSON ref: `app.selection.canAddFavorite`
|
||||
*/
|
||||
export function canAddFavorite(context: RuleContext): boolean {
|
||||
if (navigation.isFavorites(context) || navigation.isLibraries(context) || navigation.isTrashcan(context)) {
|
||||
return false;
|
||||
if (hasSelection(context)) {
|
||||
if (navigation.isFavorites(context) || navigation.isLibraries(context) || navigation.isTrashcan(context)) {
|
||||
return false;
|
||||
}
|
||||
return context.selection.nodes.some((node) => !node.entry.isFavorite);
|
||||
}
|
||||
return context.selection.nodes.some((node) => !node.entry.isFavorite);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,10 +130,13 @@ export function canAddFavorite(context: RuleContext): boolean {
|
||||
* JSON ref: `app.selection.canRemoveFavorite`
|
||||
*/
|
||||
export function canRemoveFavorite(context: RuleContext): boolean {
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
if (hasSelection(context) && !navigation.isTrashcan(context)) {
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
return context.selection.nodes.every((node) => node.entry.isFavorite);
|
||||
}
|
||||
return context.selection.nodes.every((node) => node.entry.isFavorite);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,14 +144,15 @@ export function canRemoveFavorite(context: RuleContext): boolean {
|
||||
* JSON ref: `app.selection.file.canShare`
|
||||
*/
|
||||
export const canShareFile = (context: RuleContext): boolean =>
|
||||
[context.selection.file, !navigation.isTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean);
|
||||
[context.selection.file, navigation.isNotTrashcan(context), repository.hasQuickShareEnabled(context), !isShared(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can perform "Join" or "Cancel Join Request" on a library.
|
||||
* JSON ref: `canToggleJoinLibrary`
|
||||
*/
|
||||
export const canToggleJoinLibrary = (context: RuleContext): boolean =>
|
||||
!isPrivateLibrary(context) || [isPrivateLibrary(context), isAdmin(context)].every(Boolean);
|
||||
[hasLibrarySelected(context), !isPrivateLibrary(context), hasNoLibraryRole(context)].every(Boolean) ||
|
||||
[hasLibrarySelected(context), isPrivateLibrary(context), hasNoLibraryRole(context), isAdmin(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can edit the selected folder.
|
||||
@@ -136,7 +160,7 @@ export const canToggleJoinLibrary = (context: RuleContext): boolean =>
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canEditFolder = (context: RuleContext): boolean => [canUpdateSelectedFolder(context), !navigation.isTrashcan(context)].every(Boolean);
|
||||
export const canEditFolder = (context: RuleContext): boolean => [canUpdateSelectedFolder(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if the selected file is already shared.
|
||||
@@ -147,7 +171,7 @@ export function isShared(context: RuleContext): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!navigation.isTrashcan(context) && hasSelection(context) && context.selection.file) {
|
||||
if (navigation.isNotTrashcan(context) && hasSelection(context) && context.selection.file) {
|
||||
return !!context.selection.file.entry?.properties?.['qshare:sharedId'];
|
||||
}
|
||||
|
||||
@@ -159,27 +183,43 @@ export function isShared(context: RuleContext): boolean {
|
||||
* JSON ref: `app.selection.canDelete`
|
||||
*/
|
||||
export function canDeleteSelection(context: RuleContext): boolean {
|
||||
if (hasLockedFiles(context)) {
|
||||
return false;
|
||||
}
|
||||
if (navigation.isNotTrashcan(context) && navigation.isNotLibraries(context) && hasSelection(context)) {
|
||||
if (hasLockedFiles(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// temp workaround for Favorites api
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
// temp workaround for Favorites api
|
||||
if (navigation.isFavorites(context)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (navigation.isPreview(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete']);
|
||||
}
|
||||
|
||||
// workaround for Shared Files
|
||||
if (navigation.isSharedFiles(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
});
|
||||
}
|
||||
|
||||
if (navigation.isPreview(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete']);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// workaround for Shared Files
|
||||
if (navigation.isSharedFiles(context)) {
|
||||
/**
|
||||
* Checks if user can un-share selected nodes.
|
||||
* JSON ref: `app.selection.canUnshare`
|
||||
*/
|
||||
export function canUnshareNodes(context: RuleContext): boolean {
|
||||
if (hasSelection(context)) {
|
||||
return context.permissions.check(context.selection.nodes, ['delete'], {
|
||||
target: 'allowableOperationsOnTarget'
|
||||
});
|
||||
}
|
||||
|
||||
return context.permissions.check(context.selection.nodes, ['delete']);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,7 +233,7 @@ export const hasSelection = (context: RuleContext): boolean => !context.selectio
|
||||
* JSON ref: `app.navigation.folder.canCreate`
|
||||
*/
|
||||
export function canCreateFolder(context: AcaRuleContext): boolean {
|
||||
if (navigation.isPersonalFiles(context) || navigation.isLibraryContent(context)) {
|
||||
if (isContentServiceEnabled(context) && (navigation.isPersonalFiles(context) || navigation.isLibraryContent(context))) {
|
||||
const { currentFolder } = context.navigation;
|
||||
|
||||
if (currentFolder) {
|
||||
@@ -203,12 +243,32 @@ export function canCreateFolder(context: AcaRuleContext): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can create a Library
|
||||
* JSON ref: `app.canCreateLibrary`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canCreateLibrary = (context: AcaRuleContext): boolean =>
|
||||
[isContentServiceEnabled(context), navigation.isLibraries(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can upload content to current folder.
|
||||
* JSON ref: `app.navigation.folder.canUpload`
|
||||
*/
|
||||
export function canUpload(context: AcaRuleContext): boolean {
|
||||
return canCreateFolder(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user can download selected nodes (either files or folders).
|
||||
* JSON ref: `app.selection.canDownload`
|
||||
*/
|
||||
export function canDownloadSelection(context: RuleContext): boolean {
|
||||
return context.selection.nodes.every((node: any) => node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId));
|
||||
if (hasSelection(context) && navigation.isNotTrashcan(context)) {
|
||||
return context.selection.nodes.every((node: any) => node.entry && (node.entry.isFile || node.entry.isFolder || !!node.entry.nodeId));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,6 +300,12 @@ export function hasLibraryRole(context: RuleContext): boolean {
|
||||
return library ? !!library.entry?.role : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the selected library has no **role** property defined.
|
||||
* JSON ref: `app.selection.hasNoLibraryRole`
|
||||
*/
|
||||
export const hasNoLibraryRole = (context: RuleContext): boolean => !hasLibraryRole(context);
|
||||
|
||||
/**
|
||||
* Checks if user has selected a file.
|
||||
* JSON ref: `app.selection.file`
|
||||
@@ -350,18 +416,61 @@ export function canUploadVersion(context: RuleContext): boolean {
|
||||
|
||||
return [
|
||||
hasFileSelected(context),
|
||||
!navigation.isTrashcan(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
isWriteLocked(context) ? isUserWriteLockOwner(context) : canUpdateSelectedNode(context)
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if user has trashcan item selected.
|
||||
* JSON ref: `isTrashcanItemSelected`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const isTrashcanItemSelected = (context: RuleContext): boolean => [navigation.isTrashcan(context), hasSelection(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can view the file.
|
||||
* JSON ref: `canViewFile`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canViewFile = (context: RuleContext): boolean => [hasFileSelected(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can **Leave** selected library.
|
||||
* JSON ref: `canLeaveLibrary`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canLeaveLibrary = (context: RuleContext): boolean => [hasLibrarySelected(context), hasLibraryRole(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can toggle shared link mode.
|
||||
* JSON ref: `canToggleSharedLink`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canToggleSharedLink = (context: RuleContext): boolean => [canShareFile(context), isShared(context)].some(Boolean);
|
||||
export const canToggleSharedLink = (context: RuleContext): boolean =>
|
||||
[hasFileSelected(context), [canShareFile(context), isShared(context)].some(Boolean)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can show **Info Drawer** for the selected node.
|
||||
* JSON ref: `canShowInfoDrawer`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canShowInfoDrawer = (context: RuleContext): boolean =>
|
||||
[hasSelection(context), navigation.isNotLibraries(context), navigation.isNotTrashcan(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can manage file versions for the selected node.
|
||||
* JSON ref: `canManageFileVersions`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canManageFileVersions = (context: RuleContext): boolean =>
|
||||
[hasFileSelected(context), navigation.isNotTrashcan(context), !hasLockedFiles(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can edit aspects for the selected node.
|
||||
@@ -374,11 +483,29 @@ export const canEditAspects = (context: RuleContext): boolean =>
|
||||
!isMultiselection(context),
|
||||
canUpdateSelectedNode(context),
|
||||
!isWriteLocked(context),
|
||||
!navigation.isTrashcan(context),
|
||||
navigation.isNotTrashcan(context),
|
||||
repository.isMajorVersionAvailable(context, '7')
|
||||
].every(Boolean);
|
||||
|
||||
export const canToggleFileLock = (context: RuleContext): boolean => [canLockFile(context) || canUnlockFile(context)].some(Boolean);
|
||||
export const canShowExpand = (context: RuleContext): boolean => [!navigation.isLibraries(context), !navigation.isDetails(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can manage permissions for the selected node.
|
||||
* JSON ref: `canManagePermissions`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canManagePermissions = (context: RuleContext): boolean =>
|
||||
[canUpdateSelectedNode(context), navigation.isNotTrashcan(context), !isSmartFolder(context), !isMultiselection(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* Checks if user can toggle **Edit Offline** mode for selected node.
|
||||
* JSON ref: `canToggleEditOffline`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canToggleEditOffline = (context: RuleContext): boolean =>
|
||||
[hasFileSelected(context), navigation.isNotTrashcan(context), canLockFile(context) || canUnlockFile(context)].every(Boolean);
|
||||
|
||||
/**
|
||||
* @deprecated Uses workarounds for for recent files and search api issues.
|
||||
@@ -407,7 +534,23 @@ export const canShowLogout = (context: AcaRuleContext): boolean => !context.with
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const isLibraryManager = (context: RuleContext): boolean => context.selection.library?.entry.role === 'SiteManager' || isAdmin(context);
|
||||
export const isLibraryManager = (context: RuleContext): boolean =>
|
||||
hasLibrarySelected(context) && (context.selection.library?.entry.role === 'SiteManager' || isAdmin(context));
|
||||
|
||||
/**
|
||||
* Checks if the preview button for search results can be showed
|
||||
* JSON ref: `canInfoPreview`
|
||||
*
|
||||
* @param context Rule execution context
|
||||
*/
|
||||
export const canInfoPreview = (context: RuleContext): boolean => {
|
||||
const isSearchResult = navigation.isSearchResults(context);
|
||||
const isNotMultiselect = !isMultiselection(context);
|
||||
const isFileSelected = !hasFolderSelected(context);
|
||||
const isPreview = !navigation.isPreview(context);
|
||||
|
||||
return isSearchResult && isNotMultiselect && isFileSelected && isPreview;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the file can be opened with MS Office
|
||||
@@ -493,4 +636,4 @@ export const canDisplayKnowledgeRetrievalButton = (context: AcaRuleContext): boo
|
||||
navigation.isSharedFiles(context) ||
|
||||
navigation.isRecentFiles(context) ||
|
||||
navigation.isFavorites(context) ||
|
||||
((navigation.isSearchResults(context) || navigation.isLibraryContent(context)) && !navigation.isLibraries(context)));
|
||||
((navigation.isSearchResults(context) || navigation.isLibraryContent(context)) && navigation.isNotLibraries(context)));
|
||||
|
@@ -59,6 +59,28 @@ describe('navigation.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotFavorites', () => {
|
||||
it('should return [true] if url is not `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/some/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotFavorites(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url starts with `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotFavorites(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedFiles', () => {
|
||||
it('should return [true] if path starts with `/shared`', () => {
|
||||
const context: any = {
|
||||
@@ -81,6 +103,28 @@ describe('navigation.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotSharedFiles', () => {
|
||||
it('should return [true] if path does not contain `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/some/path/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotSharedFiles(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if path contains `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/path/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotSharedFiles(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isTrashcan', () => {
|
||||
it('should return [true] if url starts with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
@@ -103,6 +147,28 @@ describe('navigation.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotTrashcan', () => {
|
||||
it('should return [true] if url does not start with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotTrashcan(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does start with `/trashcan`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/trashcan'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotTrashcan(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isPersonalFiles', () => {
|
||||
it('should return [true] if url starts with `/personal-files`', () => {
|
||||
const context: any = {
|
||||
@@ -147,6 +213,18 @@ describe('navigation.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotLibraries', () => {
|
||||
it('should return [true] if url does not end with `/libraries`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/libraries/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotLibraries(context)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isDetails', () => {
|
||||
it('should return true if url includes with `/details`', () => {
|
||||
const context: any = {
|
||||
@@ -169,6 +247,28 @@ describe('navigation.evaluators', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNotDetails', () => {
|
||||
it('should return true if url does not include `/details`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotDetails(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if url includes `/details`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: 'personal-files/details/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isNotDetails(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isRecentFiles', () => {
|
||||
it('should return [true] if url starts with `/recent-files`', () => {
|
||||
const context: any = {
|
||||
@@ -212,4 +312,90 @@ describe('navigation.evaluators', () => {
|
||||
expect(app.isSearchResults(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedPreview', () => {
|
||||
it('should return [true] if url starts with `/shared` and contains `viewer:view', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/(viewer:view)'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedPreview(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/shared`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/shared/(viewer:view)'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedPreview(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if url starts with `/shared` and does not includes `viewer:view`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/shared/something'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedPreview(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFavoritesPreview', () => {
|
||||
it('should return [true] if url starts with `/favorites` and includes `viewer:view`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/(viewer:view)'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavoritesPreview(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/favorites`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/favorites/(viewer:view)'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavoritesPreview(context)).toBe(false);
|
||||
});
|
||||
|
||||
it('should return [false] if url starts with `/favorites` and does not include `viewer:view`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/favorites/other'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isFavoritesPreview(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isSharedFileViewer', () => {
|
||||
it('should return [true] if url starts with `/preview/s/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/preview/s/path'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFileViewer(context)).toBe(true);
|
||||
});
|
||||
|
||||
it('should return [false] if url does not start with `/preview/s/`', () => {
|
||||
const context: any = {
|
||||
navigation: {
|
||||
url: '/path/preview/s/'
|
||||
}
|
||||
};
|
||||
|
||||
expect(app.isSharedFileViewer(context)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -42,6 +42,12 @@ export function isFavorites(context: RuleContext): boolean {
|
||||
return url?.startsWith('/favorites') && !isPreview(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Favorites**.
|
||||
* JSON ref: `app.navigation.isNotFavorites`
|
||||
*/
|
||||
export const isNotFavorites = (context: RuleContext): boolean => !isFavorites(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Shared Files** route is activated.
|
||||
* JSON ref: `app.navigation.isSharedFiles`
|
||||
@@ -51,6 +57,12 @@ export function isSharedFiles(context: RuleContext): boolean {
|
||||
return url?.startsWith('/shared') && !isPreview(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Shared Files**.
|
||||
* JSON ref: `app.navigation.isNotSharedFiles`
|
||||
*/
|
||||
export const isNotSharedFiles = (context: RuleContext): boolean => !isSharedFiles(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Trashcan** route is activated.
|
||||
* JSON ref: `app.navigation.isTrashcan`
|
||||
@@ -60,6 +72,12 @@ export function isTrashcan(context: RuleContext): boolean {
|
||||
return url?.startsWith('/trashcan');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Trashcan**.
|
||||
* JSON ref: `app.navigation.isNotTrashcan`
|
||||
*/
|
||||
export const isNotTrashcan = (context: RuleContext): boolean => !isTrashcan(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Personal Files** route is activated.
|
||||
* JSON ref: `app.navigation.isPersonalFiles`
|
||||
@@ -69,6 +87,15 @@ export function isPersonalFiles(context: RuleContext): boolean {
|
||||
return url?.startsWith('/personal-files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Library Files** route is activated.
|
||||
* JSON ref: `app.navigation.isLibraryFiles`
|
||||
*/
|
||||
export function isLibraryFiles(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url?.startsWith('/libraries');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Library Files** or **Library Search Result** route is activated.
|
||||
* JSON ref: `app.navigation.isLibraryFiles`
|
||||
@@ -88,6 +115,18 @@ export function isDetails(context: RuleContext): boolean {
|
||||
return url?.includes('/details');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Details**.
|
||||
* JSON ref: `app.navigation.isNotDetails`
|
||||
*/
|
||||
export const isNotDetails = (context: RuleContext): boolean => !isDetails(context);
|
||||
|
||||
/**
|
||||
* Checks if the activated route is neither **Libraries** nor **Library Search Results**.
|
||||
* JSON ref: `app.navigation.isNotLibraries`
|
||||
*/
|
||||
export const isNotLibraries = (context: RuleContext): boolean => !isLibraries(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Recent Files** route is activated.
|
||||
* JSON ref: `app.navigation.isRecentFiles`
|
||||
@@ -97,6 +136,12 @@ export function isRecentFiles(context: RuleContext): boolean {
|
||||
return url?.startsWith('/recent-files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Recent Files**.
|
||||
* JSON ref: `app.navigation.isNotRecentFiles`
|
||||
*/
|
||||
export const isNotRecentFiles = (context: RuleContext): boolean => !isRecentFiles(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Search Results** route is activated.
|
||||
* JSON ref: `app.navigation.isSearchResults`
|
||||
@@ -108,3 +153,36 @@ export function isSearchResults(
|
||||
const { url } = context.navigation;
|
||||
return url?.startsWith('/search');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the activated route is not **Search Results**.
|
||||
* JSON ref: `app.navigation.isNotSearchResults`
|
||||
*/
|
||||
export const isNotSearchResults = (context: RuleContext): boolean => !isSearchResults(context);
|
||||
|
||||
/**
|
||||
* Checks if a **Shared Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isSharedPreview`
|
||||
*/
|
||||
export function isSharedPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url?.startsWith('/shared/preview/') || (url?.startsWith('/shared') && url?.includes('viewer:view'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Favorites Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isFavoritesPreview`
|
||||
*/
|
||||
export function isFavoritesPreview(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url?.startsWith('/favorites/preview/') || (url?.startsWith('/favorites') && url?.includes('viewer:view'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a **Shared File Preview** route is activated.
|
||||
* JSON ref: `app.navigation.isFavoritesPreview`
|
||||
*/
|
||||
export function isSharedFileViewer(context: RuleContext): boolean {
|
||||
const { url } = context.navigation;
|
||||
return url?.startsWith('/preview/s/');
|
||||
}
|
||||
|
@@ -1087,16 +1087,6 @@ describe('AppExtensionService', () => {
|
||||
expect(service.evaluateRule('rule1')).toBeTrue();
|
||||
});
|
||||
|
||||
it('should evaluate list of rules', () => {
|
||||
extensions.setEvaluators({
|
||||
rule1: () => true,
|
||||
rule2: () => true,
|
||||
rule3: () => true
|
||||
});
|
||||
|
||||
expect(service.evaluateRule(['rule1', 'rule2', 'rule3'])).toBeTrue();
|
||||
});
|
||||
|
||||
it('should not evaluate missing rule and return [false] by default', () => {
|
||||
expect(service.evaluateRule('missing')).toBeFalse();
|
||||
});
|
||||
|
@@ -532,18 +532,11 @@ export class AppExtensionService implements RuleContext {
|
||||
}
|
||||
|
||||
// todo: move to ADF/RuleService
|
||||
evaluateRule(ruleId: string | string[], ...args: any[]): boolean {
|
||||
let evaluatorList: RuleEvaluator[] = [];
|
||||
if (Array.isArray(ruleId)) {
|
||||
evaluatorList = ruleId.filter((rule) => !!this.getEvaluator(rule)).map((rule) => this.getEvaluator(rule));
|
||||
} else {
|
||||
const evaluator = this.getEvaluator(ruleId);
|
||||
if (evaluator) {
|
||||
evaluatorList.push(evaluator);
|
||||
}
|
||||
}
|
||||
if (evaluatorList?.length > 0) {
|
||||
return evaluatorList.every((evaluator) => evaluator(this, ...args));
|
||||
evaluateRule(ruleId: string, ...args: any[]): boolean {
|
||||
const evaluator = this.getEvaluator(ruleId);
|
||||
|
||||
if (evaluator) {
|
||||
return evaluator(this, ...args);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
Reference in New Issue
Block a user