Sonarcloud issues fixes (#3499)

* Sonarcloud issues fixes

* Code smell fixes

* Refactoring to remove new code duplications

* Sonarcloud code smell fixes part I

* Sonarcloud code smell fixes part II

* Missing code smell fix

* Add new ESLint rules to cover fixed SonarCloud issues

* Add missing command

* Add missing is existing check
This commit is contained in:
MichalKinas
2023-11-03 11:43:06 +01:00
committed by GitHub
parent 968febffb0
commit 69c00fc403
72 changed files with 327 additions and 530 deletions

View File

@@ -83,10 +83,10 @@ export class LocationLinkComponent implements OnInit {
ngOnInit() {
if (this.context) {
const node: NodeEntry = this.context.row.node;
if (node && node.entry && node.entry.path) {
if (node?.entry && node?.entry?.path) {
const path = node.entry.path;
if (path && path.name && path.elements) {
if (path?.name && path?.elements) {
if (this.showLocation) {
this.displayText = of(path.name.substring(1).replace(/\//g, ' › '));
} else {
@@ -144,7 +144,9 @@ export class LocationLinkComponent implements OnInit {
let result: string = null;
const elements = path.elements.map((e) => Object.assign({}, e));
const elements = path.elements.map((e) => {
return { ...e };
});
const personalFiles = this.translationService.instant('APP.BROWSE.PERSONAL.TITLE');
const fileLibraries = this.translationService.instant('APP.BROWSE.LIBRARIES.TITLE');

View File

@@ -62,7 +62,7 @@ export class ToggleSharedComponent implements OnInit, OnDestroy {
this.selectionState = selectionState;
this.isShared =
(this.selectionState.first && this.selectionState.first.entry && (this.selectionState.first.entry as any).sharedByUser) ||
(this.selectionState?.first?.entry && (this.selectionState.first.entry as any).sharedByUser) ||
!!this.selectionState?.first?.entry?.properties?.['qshare:sharedId'];
this.selectionLabel = this.isShared ? 'APP.ACTIONS.SHARE_EDIT' : 'APP.ACTIONS.SHARE';

View File

@@ -52,7 +52,7 @@ export class ContextMenuItemComponent {
}
private hasClickAction(actionRef: ContentActionRef): boolean {
return !!(actionRef && actionRef.actions && actionRef.actions.click);
return !!actionRef?.actions?.click;
}
trackByActionId(_: number, obj: ContentActionRef): string {

View File

@@ -36,8 +36,6 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
@Output()
clickOutside: EventEmitter<null> = new EventEmitter();
constructor() {}
ngOnInit() {
this.subscriptions = this.subscriptions.concat([
fromEvent(document.body, 'click')
@@ -54,11 +52,9 @@ export class OutsideEventDirective implements OnInit, OnDestroy {
private findAncestor(el: Element): boolean {
const className = 'aca-context-menu';
if (el.classList.contains(className)) {
return true;
while (el && !el.classList.contains(className)) {
el = el.parentElement;
}
// eslint-disable-next-line curly
while ((el = el.parentElement) && !el.classList.contains(className));
return !!el;
}
}

View File

@@ -68,11 +68,6 @@ export class ContextMenuService {
}
private createInjector(contextmenuOverlayRef: ContextMenuOverlayRef): Injector {
const injectionTokens = new WeakMap();
injectionTokens.set(ContextMenuOverlayRef, contextmenuOverlayRef);
injectionTokens.set(CONTEXT_MENU_DIRECTION, this.direction);
return Injector.create({
parent: this.injector,
providers: [

View File

@@ -95,7 +95,7 @@ export class FavoriteLibrariesComponent extends PageComponent implements OnInit
}
navigateTo(node: SiteEntry) {
if (node && node.entry && node.entry.guid) {
if (node?.entry?.guid) {
this.store.dispatch(new NavigateLibraryAction(node.entry.guid, 'favorite/libraries'));
}
}

View File

@@ -83,7 +83,7 @@ export class FavoritesComponent extends PageComponent implements OnInit {
const { isFolder, id } = favorite;
// TODO: rework as it will fail on non-English setups
const isSitePath = (path: PathInfo): boolean => path && path.elements && path.elements.some(({ name }: PathElement) => name === 'Sites');
const isSitePath = (path: PathInfo): boolean => path?.elements?.some(({ name }: PathElement) => name === 'Sites');
if (isFolder) {
this.contentApi
@@ -97,7 +97,7 @@ export class FavoritesComponent extends PageComponent implements OnInit {
}
onNodeDoubleClick(node: NodeEntry) {
if (node && node.entry) {
if (node?.entry) {
if (node.entry.isFolder) {
this.navigate(node.entry);
}

View File

@@ -102,7 +102,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
(node) => {
this.isValidPath = true;
if (node.entry && node.entry.isFolder) {
if (node?.entry?.isFolder) {
this.updateCurrentNode(node.entry);
} else {
this.router.navigate(['/personal-files', node.entry.parentId], {
@@ -190,7 +190,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
navigateTo(node: NodeEntry) {
if (node && node.entry) {
if (node?.entry) {
this.selectedNode = node;
const { isFolder } = node.entry;
@@ -220,7 +220,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
this.documentList.resetNewFolderPagination();
// todo: review this approach once 5.2.3 is out
if (this.nodePath && this.nodePath.length > 2) {
if (this.nodePath && this.nodePath?.length > 2) {
if (this.nodePath[1].name === 'Sites' && this.nodePath[2].id === route.id) {
return this.navigate(this.nodePath[3].id);
}
@@ -232,31 +232,31 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
const node: NodeEntry = event.file.data;
// check root and child nodes
if (node && node.entry && node.entry.parentId === this.getParentNodeId()) {
if (node?.entry?.parentId === this.getParentNodeId()) {
this.reload(this.selectedNode);
return;
}
// check the child nodes to show dropped folder
if (event && event.file.options.parentId === this.getParentNodeId()) {
this.displayFolderParent(event.file.options.path, 0);
this.displayFolderParent(0, event.file.options.path);
return;
}
if (event && event.file.options.parentId) {
if (event?.file.options.parentId) {
if (this.nodePath) {
const correspondingNodePath = this.nodePath.find((pathItem) => pathItem.id === event.file.options.parentId);
// check if the current folder has the 'trigger-upload-folder' as one of its parents
if (correspondingNodePath) {
const correspondingIndex = this.nodePath.length - this.nodePath.indexOf(correspondingNodePath);
this.displayFolderParent(event.file.options.path, correspondingIndex);
this.displayFolderParent(correspondingIndex, event.file.options.path);
}
}
}
}
displayFolderParent(filePath = '', index: number) {
displayFolderParent(index: number, filePath = '') {
const parentName = filePath.split('/')[index];
const currentFoldersDisplayed = (this.documentList.data.getRows() as ShareDataRow[]) || [];
@@ -269,7 +269,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
onContentCopied(nodes: NodeEntry[]) {
const newNode = nodes.find((node) => node && node.entry && node.entry.parentId === this.getParentNodeId());
const newNode = nodes.find((node) => node?.entry?.parentId === this.getParentNodeId());
if (newNode) {
this.reload(this.selectedNode);
}
@@ -279,10 +279,12 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
private async updateCurrentNode(node: Node) {
this.nodePath = null;
if (node && node.path && node.path.elements) {
if (node?.path?.elements) {
const elements = node.path.elements;
this.nodePath = elements.map((pathElement) => Object.assign({}, pathElement));
this.nodePath = elements.map((pathElement) => {
return { ...pathElement };
});
if (elements.length > 1) {
if (elements[1].name === 'User Homes') {
@@ -329,14 +331,14 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
isSiteContainer(node: Node): boolean {
if (node && node.aspectNames && node.aspectNames.length > 0) {
if (node?.aspectNames?.length > 0) {
return node.aspectNames.indexOf('st:siteContainer') >= 0;
}
return false;
}
isRootNode(nodeId: string): boolean {
if (this.node && this.node.path && this.node.path.elements && this.node.path.elements.length > 0) {
if (this.node?.path?.elements?.length > 0) {
return this.node.path.elements[0].id === nodeId;
}
return false;
@@ -359,7 +361,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
const objectFromMap = {};
activeFilters.forEach((filter: FilterSearch) => {
let paramValue;
if (filter.value && filter.value.from && filter.value.to) {
if (filter?.value?.from && filter?.value?.to) {
paramValue = `${filter.value.from}||${filter.value.to}`;
} else {
paramValue = filter.value;

View File

@@ -60,8 +60,8 @@ import { Actions, ofType } from '@ngrx/effects';
export class InstantErrorStateMatcher implements ErrorStateMatcher {
isErrorState(control: UntypedFormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
const isSubmitted = form?.submitted;
return !!(control?.invalid && (control?.dirty || control?.touched || isSubmitted));
}
}

View File

@@ -81,7 +81,7 @@ export class LibrariesComponent extends PageComponent implements OnInit {
}
navigateTo(node: SiteEntry) {
if (node && node.entry && node.entry.guid) {
if (node?.entry?.guid) {
this.store.dispatch(new NavigateLibraryAction(node.entry.guid));
}
}

View File

@@ -63,10 +63,6 @@ import { TranslateModule } from '@ngx-translate/core';
export class RecentFilesComponent extends PageComponent implements OnInit {
columns: DocumentListPresetRef[] = [];
constructor() {
super();
}
ngOnInit() {
super.ngOnInit();
@@ -79,7 +75,7 @@ export class RecentFilesComponent extends PageComponent implements OnInit {
}
onNodeDoubleClick(node: NodeEntry) {
if (node && node.entry) {
if (node?.entry) {
this.showPreview(node, { location: this.router.url });
}
}

View File

@@ -42,39 +42,39 @@ describe('SearchInputControlComponent', () => {
fixture.detectChanges();
});
it('should emit submit event on searchSubmit', async () => {
it('should emit submit event on searchSubmit', () => {
const keyboardEvent = { target: { value: 'a' } };
let eventArgs = null;
component.submit.subscribe((args) => (eventArgs = args));
await component.searchSubmit(keyboardEvent);
component.searchSubmit(keyboardEvent);
expect(eventArgs).toBe(keyboardEvent);
});
it('should emit searchChange event on inputChange', async () => {
it('should emit searchChange event on inputChange', () => {
const searchTerm = 'b';
let eventArgs = null;
component.searchChange.subscribe((args) => (eventArgs = args));
await component.inputChange(searchTerm);
component.inputChange(searchTerm);
expect(eventArgs).toBe(searchTerm);
});
it('should emit searchChange event on clear', async () => {
it('should emit searchChange event on clear', () => {
let eventArgs = null;
component.searchChange.subscribe((args) => (eventArgs = args));
await component.clear();
component.clear();
expect(eventArgs).toBe('');
});
it('should clear searchTerm', async () => {
it('should clear searchTerm', () => {
component.searchTerm = 'c';
fixture.detectChanges();
await component.clear();
component.clear();
expect(component.searchTerm).toBe('');
});

View File

@@ -53,13 +53,13 @@ describe('SearchLibrariesQueryBuilderService', () => {
expect(builder.userQuery).toEqual('something');
});
it('should build query and raise an event on update', async () => {
it('should build query and raise an event on update', () => {
spyOn(builder, 'buildQuery').and.returnValue(query);
let eventArgs = null;
builder.updated.subscribe((args) => (eventArgs = args));
await builder.update();
builder.update();
expect(eventArgs).toBe(query);
});

View File

@@ -80,12 +80,12 @@ export class SearchLibrariesQueryBuilderService {
buildQuery(): LibrarySearchQuery {
const query = this.userQuery;
if (query && query.length > 1) {
if (query?.length > 1) {
return {
term: query,
opts: {
skipCount: this.paging && this.paging.skipCount,
maxItems: this.paging && this.paging.maxItems
skipCount: this.paging?.skipCount,
maxItems: this.paging?.maxItems
}
};
}

View File

@@ -158,7 +158,7 @@ export class SearchLibrariesResultsComponent extends PageComponent implements On
}
getNumberOfResults() {
if (this.data && this.data.list && this.data.list.pagination) {
if (this.data?.list?.pagination) {
return this.data.list.pagination.totalItems;
}
return 0;
@@ -173,7 +173,7 @@ export class SearchLibrariesResultsComponent extends PageComponent implements On
}
navigateTo(node: SiteEntry) {
if (node && node.entry && node.entry.guid) {
if (node?.entry?.guid) {
this.store.dispatch(new NavigateLibraryAction(node.entry.guid));
}
}

View File

@@ -74,7 +74,7 @@ export class SearchResultsRowComponent implements OnInit, OnDestroy {
if (entry.id === node.id) {
entry.name = node.name;
entry.properties = Object.assign({}, node.properties);
entry.properties = { ...node.properties };
this.updateValues();
}

View File

@@ -95,11 +95,7 @@ describe('SearchComponent', () => {
});
it('should raise an error if search fails', fakeAsync(() => {
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(
Promise.reject({
message: `{ "error": { "statusCode": 500 } } `
})
);
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(Promise.reject(new Error('{ "error": { "statusCode": 500 } }')));
spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub();
@@ -118,11 +114,7 @@ describe('SearchComponent', () => {
return key;
});
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(
Promise.reject({
message: `{ "error": { "statusCode": 401 } } `
})
);
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(Promise.reject(new Error('{ "error": { "statusCode": 401 } }')));
spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub();
@@ -141,11 +133,7 @@ describe('SearchComponent', () => {
return key;
});
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(
Promise.reject({
message: `{ "error": { "statusCode": 401 } } `
})
);
spyOn(queryBuilder['searchApi'], 'search').and.returnValue(Promise.reject(new Error('{ "error": { "statusCode": 401 } }')));
spyOn(queryBuilder, 'buildQuery').and.returnValue(searchRequest);
spyOn(store, 'dispatch').and.stub();
@@ -191,7 +179,7 @@ describe('SearchComponent', () => {
});
it('should format user input as cm:name if configuration not provided', () => {
const query = component.formatSearchQuery('hello', undefined);
const query = component.formatSearchQuery('hello');
expect(query).toBe(`(cm:name:"hello*")`);
});

View File

@@ -266,7 +266,7 @@ export class SearchResultsComponent extends PageComponent implements OnInit {
}
onNodeDoubleClick(node: NodeEntry) {
if (node && node.entry) {
if (node?.entry) {
if (node.entry.isFolder) {
this.store.dispatch(new NavigateToFolder(node));
return;

View File

@@ -95,7 +95,7 @@ describe('SharedLinkViewComponent', () => {
}));
it('should not update store on error', fakeAsync(() => {
spyGetSharedLink.and.returnValue(Promise.reject('error'));
spyGetSharedLink.and.returnValue(Promise.reject(new Error('error')));
fixture.detectChanges();
tick();

View File

@@ -75,7 +75,6 @@ describe('ActionDirective', () => {
it('should add active route class name', () => {
fixture.detectChanges();
router.navigateByUrl('/dummy');
// fixture.detectChanges();
expect(document.body.querySelector('#test-element').className.includes('active-link-class')).toBe(true);
});

View File

@@ -67,7 +67,7 @@ export class ActiveLinkDirective implements OnInit, AfterContentInit {
}
private render(routerUrl: string, actionUrl: string) {
if (routerUrl && routerUrl.substring(1).startsWith(actionUrl)) {
if (routerUrl?.substring(1).startsWith(actionUrl)) {
this.isLinkActive = true;
this.renderer.addClass(this.element.nativeElement, this.acaActiveLink);
} else {
@@ -82,6 +82,6 @@ export class ActiveLinkDirective implements OnInit, AfterContentInit {
}
private resolveUrl(item): string {
return (item.action && item.action.click && item.action.click.payload) || item.action.route;
return item.action?.click?.payload || item.action?.route;
}
}

View File

@@ -58,7 +58,7 @@ export class ExpansionPanelDirective implements OnInit, OnDestroy {
constructor(private store: Store<any>, private router: Router, private expansionPanel: MatExpansionPanel) {}
hasActiveLinks() {
if (this.acaExpansionPanel && this.acaExpansionPanel.children) {
if (this.acaExpansionPanel?.children) {
return this.acaExpansionPanel.children.some((child) => this.router.url.startsWith(child.url || child.action.payload));
}
return false;

View File

@@ -57,7 +57,7 @@ export class MenuPanelDirective implements OnInit, OnDestroy {
constructor(private store: Store<any>, private router: Router) {}
hasActiveLinks() {
if (this.acaMenuPanel && this.acaMenuPanel.children) {
if (this.acaMenuPanel?.children) {
return this.acaMenuPanel.children.some((child) => this.router.url.startsWith(child.url || child.action.payload));
}
return false;

View File

@@ -57,7 +57,7 @@ export class UserMenuComponent implements OnInit {
ngOnInit() {
this.getUserInfo();
if (this.data && this.data.items) {
if (this.data?.items) {
this.data.items.sort((a, b) => a.order - b.order);
}
}

View File

@@ -69,7 +69,7 @@ describe('ToggleEditOfflineComponent', () => {
fixture.detectChanges();
expect(component.selection).toEqual(selection.file as any);
expect(component.selection).toEqual(selection.file);
});
it('should download content when node is locked', async () => {