feat: separate prettier from eslint

This commit is contained in:
Rainer Killinger
2023-01-11 13:25:18 +01:00
committed by Thea Schöbl
parent 939fb6ef0f
commit a88d000ccd
381 changed files with 17952 additions and 38411 deletions

View File

@@ -1,32 +1,22 @@
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
/* eslint-disable @typescript-eslint/no-non-null-assertion, @typescript-eslint/ban-ts-comment */
import {
APP_BASE_HREF,
CommonModule,
Location,
LocationStrategy,
PathLocationStrategy,
} from '@angular/common';
import {APP_BASE_HREF, CommonModule, Location, LocationStrategy, PathLocationStrategy} from '@angular/common';
import {ComponentFixture, TestBed} from '@angular/core/testing';
import {FormsModule} from '@angular/forms';
import {
ChildrenOutletContexts,
RouterModule,
UrlSerializer,
} from '@angular/router';
import {ChildrenOutletContexts, RouterModule, UrlSerializer} from '@angular/router';
import {IonicModule} from '@ionic/angular';
import {TranslateModule} from '@ngx-translate/core';
import {SCFacet, SCThingType} from '@openstapps/core';
@@ -71,38 +61,29 @@ describe('ContextMenuComponent', async () => {
}).compileComponents();
fixture = TestBed.createComponent(ContextMenuContainerComponent);
instance = fixture.debugElement.query(
By.directive(ContextMenuComponent),
).componentInstance;
instance = fixture.debugElement.query(By.directive(ContextMenuComponent)).componentInstance;
});
it('should show items in sort context', () => {
instance.sortOption = getSortContextType();
fixture.detectChanges();
const sort: HTMLElement =
fixture.debugElement.nativeElement.querySelector('.context-sort');
const sort: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-sort');
const sortItem = sort.querySelector('.sort-item');
expect(sortItem!.querySelector('ion-label')?.textContent).toContain(
'relevance',
);
expect(sortItem!.querySelector('ion-label')?.textContent).toContain('relevance');
});
it('should show items in filter context', () => {
instance.filterOption = getFilterContextType();
fixture.detectChanges();
const filter: HTMLElement =
fixture.debugElement.nativeElement.querySelector('.context-filter');
const filter: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-filter');
const filterItem = filter.querySelector('.filter-group');
expect(filterItem!.querySelector('ion-list-header')!.textContent).toContain(
'Type',
);
expect(filterItem!.querySelector('ion-list-header')!.textContent).toContain('Type');
});
it('should set sort context value and reverse on click', () => {
instance.sortOption = getSortContextType();
fixture.detectChanges();
const sort: HTMLElement =
fixture.debugElement.nativeElement.querySelector('.context-sort');
const sort: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-sort');
// @ts-expect-error not relevant for this case
const sortItem: HTMLElement = sort.querySelectorAll('.sort-item')[1];
sortItem!.click();
@@ -121,8 +102,7 @@ describe('ContextMenuComponent', async () => {
instance.filterOption = getFilterContextType();
fixture.detectChanges();
// get filter context div
const filter: HTMLElement =
fixture.debugElement.nativeElement.querySelector('.context-filter');
const filter: HTMLElement = fixture.debugElement.nativeElement.querySelector('.context-filter');
// get all filter groups that represent a facet
const filterGroups = filter.querySelectorAll('.filter-group');
@@ -162,11 +142,7 @@ describe('ContextMenuComponent', async () => {
for (let i = 0; i < filterItems.length; i++) {
if (
filterItems
.item(i)
.textContent!.toString()
.toLowerCase()
.indexOf(bucket.key.toLowerCase()) > 0
filterItems.item(i).textContent!.toString().toLowerCase().indexOf(bucket.key.toLowerCase()) > 0
) {
filterItem = filterItems.item(i);
break;
@@ -189,8 +165,7 @@ describe('ContextMenuComponent', async () => {
fixture.detectChanges();
// click reset button
const resetButton: HTMLElement =
fixture.debugElement.nativeElement.querySelector('.resetFilterButton');
const resetButton: HTMLElement = fixture.debugElement.nativeElement.querySelector('.resetFilterButton');
resetButton.click();
expect(instance.filterOption.options[0].buckets[0].checked).toEqual(false);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018-2021 StApps
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -14,12 +14,7 @@
*/
import {Component, Input, OnDestroy} from '@angular/core';
import {LangChangeEvent, TranslateService} from '@ngx-translate/core';
import {
SCLanguage,
SCThingTranslator,
SCThingType,
SCTranslations,
} from '@openstapps/core';
import {SCLanguage, SCThingTranslator, SCThingType, SCTranslations} from '@openstapps/core';
import {Subscription} from 'rxjs';
import {ContextMenuService} from './context-menu.service';
import {FilterContext, SortContext, SortContextOption} from './context-type';
@@ -83,8 +78,7 @@ export class ContextMenuComponent implements OnDestroy {
private translateService: TranslateService,
private readonly contextMenuService: ContextMenuService,
) {
this.language = this.translateService
.currentLang as keyof SCTranslations<SCLanguage>;
this.language = this.translateService.currentLang as keyof SCTranslations<SCLanguage>;
this.translator = new SCThingTranslator(this.language);
this.subscriptions.push(
@@ -111,10 +105,7 @@ export class ContextMenuComponent implements OnDestroy {
/**
* Returns translated property name
*/
getTranslatedPropertyName(
property: string,
onlyForType?: SCThingType,
): string {
getTranslatedPropertyName(property: string, onlyForType?: SCThingType): string {
return (
this.translator.translatedPropertyNames(
onlyForType ?? SCThingType.AcademicEvent,
@@ -126,11 +117,7 @@ export class ContextMenuComponent implements OnDestroy {
/**
* Returns translated property value
*/
getTranslatedPropertyValue(
onlyForType: SCThingType,
field: string,
key?: string,
): string | undefined {
getTranslatedPropertyValue(onlyForType: SCThingType, field: string, key?: string): string | undefined {
return this.translator.translatedPropertyValue(onlyForType, field, key);
}

View File

@@ -1,25 +1,19 @@
<!--
~ Copyright (C) 2022 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
~
~ This program is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
~ more details.
~ This program is distributed in the hope that it will be useful, but WITHOUT
~ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
~ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
~ more details.
~
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
~ You should have received a copy of the GNU General Public License along with
~ this program. If not, see <https://www.gnu.org/licenses/>.
-->
<ion-menu
type="overlay"
menuId="context"
contentId="{{ contentId }}"
maxEdgeStart="0"
side="end"
>
<ion-menu type="overlay" menuId="context" contentId="{{ contentId }}" maxEdgeStart="0" side="end">
<ion-toolbar color="primary" mode="ios">
<ion-label class="ion-padding-horizontal">
<h1 class="ion-padding-horizontal">
@@ -33,9 +27,7 @@
<ion-radio-group class="context-sort" *ngIf="sortOption" [value]="0">
<ion-list-header>
<ion-icon name="sort"></ion-icon>
<ion-title>{{
'menu.context.sort.title' | translate | titlecase
}}</ion-title>
<ion-title>{{ 'menu.context.sort.title' | translate | titlecase }}</ion-title>
</ion-list-header>
<ion-item
class="sort-item"
@@ -45,14 +37,8 @@
<ion-label
>{{ 'menu.context.sort.' + value.value | translate | titlecase }}
<span *ngIf="sortOption.value === value.value && value.reversible">
<ion-icon
*ngIf="sortOption.reversed"
name="arrow_downward"
></ion-icon>
<ion-icon
*ngIf="!sortOption.reversed"
name="arrow_upward"
></ion-icon>
<ion-icon *ngIf="sortOption.reversed" name="arrow_downward"></ion-icon>
<ion-icon *ngIf="!sortOption.reversed" name="arrow_upward"></ion-icon>
</span>
</ion-label>
<ion-radio slot="end" [value]="i"> </ion-radio>
@@ -63,15 +49,8 @@
<div class="context-filter" *ngIf="filterOption">
<ion-list-header>
<ion-icon name="filter_list"></ion-icon>
<ion-title>{{
'menu.context.filter.title' | translate | titlecase
}}</ion-title>
<ion-button
class="resetFilterButton"
fill="clear"
color="dark"
(click)="resetFilter(filterOption)"
>
<ion-title>{{ 'menu.context.filter.title' | translate | titlecase }}</ion-title>
<ion-button class="resetFilterButton" fill="clear" color="dark" (click)="resetFilter(filterOption)">
<ion-icon name="delete"></ion-icon>
</ion-button>
</ion-list-header>
@@ -95,9 +74,7 @@
}}
{{
facet.onlyOnType
? ' | ' +
(getTranslatedPropertyValue(facet.onlyOnType, 'type')
| titlecase)
? ' | ' + (getTranslatedPropertyValue(facet.onlyOnType, 'type') | titlecase)
: ''
}}
</ion-label>
@@ -114,13 +91,8 @@
({{ bucket.count }})
{{
facet.field === 'type'
? (getTranslatedPropertyValue($any(bucket.key), 'type')
| titlecase)
: (getTranslatedPropertyValue(
facet.onlyOnType,
facet.field,
bucket.key
) | titlecase)
? (getTranslatedPropertyValue($any(bucket.key), 'type') | titlecase)
: (getTranslatedPropertyValue(facet.onlyOnType, facet.field, bucket.key) | titlecase)
}}
</ion-label>
<ion-checkbox
@@ -136,10 +108,7 @@
</ion-item>
<ion-button
fill="clear"
*ngIf="
!facet.compact &&
facet.buckets.length > compactFilterOptionCount
"
*ngIf="!facet.compact && facet.buckets.length > compactFilterOptionCount"
(click)="facet.compact = true"
>
{{ 'menu.context.filter.showAll' | translate }}
@@ -149,10 +118,7 @@
</ion-list>
<ion-button
fill="clear"
*ngIf="
!filterOption.compact &&
filterOption.options.length > compactFilterOptionCount
"
*ngIf="!filterOption.compact && filterOption.options.length > compactFilterOptionCount"
(click)="filterOption.compact = true"
>
{{ 'menu.context.filter.showAll' | translate }}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 StApps
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -13,19 +13,9 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Injectable} from '@angular/core';
import {
SCFacet,
SCSearchFilter,
SCSearchSort,
SCThingType,
} from '@openstapps/core';
import {SCFacet, SCSearchFilter, SCSearchSort, SCThingType} from '@openstapps/core';
import {Subject} from 'rxjs';
import {
FilterBucket,
FilterContext,
FilterFacet,
SortContext,
} from './context-type';
import {FilterBucket, FilterContext, FilterFacet, SortContext} from './context-type';
/**
* ContextMenuService provides bidirectional communication of context menu options and search queries
@@ -87,9 +77,7 @@ export class ContextMenuService {
*
* @param filterContext FilterContext to build SCSearchFilter from
*/
buildFilterQuery = (
filterContext: FilterContext,
): SCSearchFilter | undefined => {
buildFilterQuery = (filterContext: FilterContext): SCSearchFilter | undefined => {
const filters: SCSearchFilter[] = [];
if (typeof this.forcedType !== 'undefined') {
@@ -217,10 +205,7 @@ export class ContextMenuService {
* Updates context filter with new facets.
* It preserves the checked status of existing filter options
*/
updateContextFilterOptions = (
contextFilter: FilterContext,
facets: SCFacet[],
) => {
updateContextFilterOptions = (contextFilter: FilterContext, facets: SCFacet[]) => {
const newFilterOptions: FilterFacet[] = [];
// iterate new facets
@@ -236,21 +221,15 @@ export class ContextMenuService {
// search existing filterOption
const filterOption = contextFilter.options.find(
(contextFacet: FilterFacet) =>
contextFacet.field === facet.field &&
contextFacet.onlyOnType === facet.onlyOnType,
contextFacet.field === facet.field && contextFacet.onlyOnType === facet.onlyOnType,
);
for (const bucket of facet.buckets) {
// search existing bucket to preserve checked status
const existingFilterBucket = filterOption
? filterOption.buckets.find(
(contextBucket: FilterBucket) =>
contextBucket.key === bucket.key,
)
? filterOption.buckets.find((contextBucket: FilterBucket) => contextBucket.key === bucket.key)
: undefined;
const filterBucket: FilterBucket = {
checked: existingFilterBucket
? existingFilterBucket.checked
: false,
checked: existingFilterBucket ? existingFilterBucket.checked : false,
count: bucket.count,
key: bucket.key,
};

View File

@@ -1,5 +1,5 @@
<!--
~ Copyright (C) 2022 StApps
~ Copyright (C) 2023 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
@@ -14,13 +14,7 @@
-->
<ion-split-pane contentId="main" when="lg">
<ion-menu
menuId="main"
contentId="main"
type="overlay"
side="start"
swipe-gesture="false"
>
<ion-menu menuId="main" contentId="main" type="overlay" side="start" swipe-gesture="false">
<ion-header>
<ion-toolbar color="primary" mode="ios">
<ion-buttons slot="start"></ion-buttons>
@@ -43,11 +37,7 @@
{{ category.translations[language].title | titlecase }}
</ion-label>
</ion-item>
<ion-item
*ngFor="let item of category.items"
[rootLink]="item.route"
[redirectedFrom]="item.route"
>
<ion-item *ngFor="let item of category.items" [rootLink]="item.route" [redirectedFrom]="item.route">
<ion-icon slot="end" [name]="item.icon"></ion-icon>
<ion-label>
{{ item.translations[language].title | titlecase }}

View File

@@ -24,13 +24,7 @@ import {RouterModule} from '@angular/router';
@NgModule({
declarations: [RootLinkDirective, NavigationComponent, TabsComponent],
imports: [
CommonModule,
IonicModule,
IonIconModule,
TranslateModule,
RouterModule,
],
imports: [CommonModule, IonicModule, IonIconModule, TranslateModule, RouterModule],
exports: [TabsComponent, RootLinkDirective, NavigationComponent],
})
export class NavigationModule {}

View File

@@ -77,4 +77,3 @@ ion-router-outlet {
--fill: 1;
}
}

View File

@@ -1,3 +1,18 @@
/*
* Copyright (C) 2022 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {Injectable} from '@angular/core';
import {SCAppConfigurationMenuCategory} from '@openstapps/core';
import {ConfigProvider} from '../../config/config.provider';
@@ -7,17 +22,12 @@ import {NGXLogger} from 'ngx-logger';
providedIn: 'root',
})
export class NavigationService {
constructor(
private configProvider: ConfigProvider,
private logger: NGXLogger,
) {}
constructor(private configProvider: ConfigProvider, private logger: NGXLogger) {}
async getMenu() {
let menu: SCAppConfigurationMenuCategory[] = [];
try {
menu = this.configProvider.getValue(
'menus',
) as SCAppConfigurationMenuCategory[];
menu = this.configProvider.getValue('menus') as SCAppConfigurationMenuCategory[];
} catch (error) {
this.logger.error(`error from loading menu entries: ${error}`);
}

View File

@@ -13,14 +13,7 @@
* this program. If not, see <https://www.gnu.org/licenses/>.
*/
import {
Directive,
ElementRef,
Input,
OnDestroy,
OnInit,
Renderer2,
} from '@angular/core';
import {Directive, ElementRef, Input, OnDestroy, OnInit, Renderer2} from '@angular/core';
import {AnimationController, NavController} from '@ionic/angular';
import {Router, RouterEvent} from '@angular/router';
import {tabsTransition} from './tabs-transition';
@@ -61,10 +54,7 @@ export class RootLinkDirective implements OnInit, OnDestroy {
// @ts-expect-error access private member
(this.navController.direction === 'root' || this.needsInit)
) {
if (
event.url === this.rootLink ||
(this.redirectedFrom && event.url === this.redirectedFrom)
) {
if (event.url === this.rootLink || (this.redirectedFrom && event.url === this.redirectedFrom)) {
this.setActive();
} else {
this.setInactive();
@@ -74,15 +64,11 @@ export class RootLinkDirective implements OnInit, OnDestroy {
}),
);
this.dispose = this.renderer.listen(
this.element.nativeElement,
'click',
() => {
this.setActive();
this.navController.setDirection('root', true, 'back', animation);
void this.router.navigate([this.rootLink]);
},
);
this.dispose = this.renderer.listen(this.element.nativeElement, 'click', () => {
this.setActive();
this.navController.setDirection('root', true, 'back', animation);
void this.router.navigate([this.rootLink]);
});
}
setActive() {

View File

@@ -20,9 +20,7 @@ import type {AnimationOptions} from '@ionic/angular/providers/nav-controller';
/**
*
*/
export function tabsTransition(
animationController: AnimationController,
): AnimationBuilder {
export function tabsTransition(animationController: AnimationController): AnimationBuilder {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (_baseElement: HTMLElement, options: AnimationOptions | any) => {
const duration = options.duration || 350;
@@ -50,9 +48,7 @@ export function tabsTransition(
.easing('linear')
.duration(contentExitDuration)
.fromTo('opacity', '1', '0')
.addElement(
options.leavingEl.querySelectorAll(':scope > *:not(ion-header)'),
);
.addElement(options.leavingEl.querySelectorAll(':scope > *:not(ion-header)'));
const contentEnter = animationController
.create()
.delay(contentExitDuration)
@@ -60,17 +56,9 @@ export function tabsTransition(
.easing('cubic-bezier(0.16, 1, 0.3, 1)')
.fromTo('transform', 'scale(1.025)', 'scale(1)')
.fromTo('opacity', '0', '1')
.addElement(
options.enteringEl.querySelectorAll(':scope > *:not(ion-header)'),
);
.addElement(options.enteringEl.querySelectorAll(':scope > *:not(ion-header)'));
rootTransition.addAnimation([
enterTransition,
contentExit,
contentEnter,
exitTransition,
exitZIndex,
]);
rootTransition.addAnimation([enterTransition, contentExit, contentEnter, exitTransition, exitZIndex]);
return rootTransition;
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 StApps
* Copyright (C) 2023 StApps
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, version 3.
@@ -57,8 +57,7 @@ export class TabsComponent {
private readonly logger: NGXLogger,
private readonly router: Router,
) {
this.language = this.translateService
.currentLang as keyof SCTranslations<SCLanguage>;
this.language = this.translateService.currentLang as keyof SCTranslations<SCLanguage>;
this.translator = new SCThingTranslator(this.language);
void this.loadMenuEntries();
this.router.events.subscribe((event: unknown) => {
@@ -79,9 +78,7 @@ export class TabsComponent {
*/
async loadMenuEntries() {
try {
const menus = (await this.configProvider.getValue(
'menus',
)) as SCAppConfigurationMenuCategory[];
const menus = (await this.configProvider.getValue('menus')) as SCAppConfigurationMenuCategory[];
const menu = menus.slice(0, 5);
if (menu) {
@@ -101,9 +98,7 @@ export class TabsComponent {
this.selectedTab = (this.menu[0] as any)?.title ?? '';
return;
}
const candidate = this.menu
.slice(0, 5)
.find(category => url.includes(category.route));
const candidate = this.menu.slice(0, 5).find(category => url.includes(category.route));
this.selectedTab = candidate?.title ?? '';
}
}

View File

@@ -47,13 +47,8 @@ describe('Tabs', () => {
ready: platformReadySpy,
is: platformIsSpy,
});
translateServiceSpy = jasmine.createSpyObj('TranslateService', [
'setDefaultLang',
'use',
]);
thingTranslateServiceSpy = jasmine.createSpyObj('ThingTranslateService', [
'init',
]);
translateServiceSpy = jasmine.createSpyObj('TranslateService', ['setDefaultLang', 'use']);
thingTranslateServiceSpy = jasmine.createSpyObj('ThingTranslateService', ['init']);
settingsProvider = jasmine.createSpyObj('SettingsProvider', [
'getSettingValue',
'provideSetting',
@@ -63,20 +58,12 @@ describe('Tabs', () => {
'getDifferences',
'postDifferencesNotification',
]);
configProvider = jasmine.createSpyObj('ConfigProvider', [
'init',
'getAnyValue',
]);
configProvider = jasmine.createSpyObj('ConfigProvider', ['init', 'getAnyValue']);
configProvider.getAnyValue = jasmine.createSpy().and.callFake(function () {
return sampleAuthConfiguration;
});
ngxLogger = jasmine.createSpyObj('NGXLogger', ['log', 'error', 'warn']);
storageProvider = jasmine.createSpyObj('StorageProvider', [
'init',
'get',
'has',
'put',
]);
storageProvider = jasmine.createSpyObj('StorageProvider', ['init', 'get', 'has', 'put']);
TestBed.configureTestingModule({
declarations: [TabsComponent],

View File

@@ -1,5 +1,5 @@
<!--
~ Copyright (C) 2022 StApps
~ Copyright (C) 2023 StApps
~ This program is free software: you can redistribute it and/or modify it
~ under the terms of the GNU General Public License as published by the Free
~ Software Foundation, version 3.
@@ -46,8 +46,6 @@
[tab]="category.title"
>
<ion-icon [name]="category.icon"></ion-icon>
<ion-label>{{
category.translations[language].title | titlecase
}}</ion-label>
<ion-label>{{ category.translations[language].title | titlecase }}</ion-label>
</ion-tab-button>
</ion-tab-bar>