[ACS-7382] Standalone core directives, improved lint performance (#9559)

This commit is contained in:
Denys Vuika 2024-04-15 15:16:17 -04:00 committed by GitHub
parent 86d3ca7892
commit 7854cde20f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 86 additions and 108 deletions

View File

@ -1 +1,2 @@
.storybook .storybook
coverage

View File

@ -15,38 +15,17 @@
* limitations under the License. * limitations under the License.
*/ */
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { MaterialModule } from '../material.module';
import { HighlightDirective } from './highlight.directive'; import { HighlightDirective } from './highlight.directive';
import { LogoutDirective } from './logout.directive'; import { LogoutDirective } from './logout.directive';
import { UploadDirective } from './upload.directive'; import { UploadDirective } from './upload.directive';
import { TooltipCardDirective } from './tooltip-card/tooltip-card.directive'; import { TooltipCardDirective } from './tooltip-card/tooltip-card.directive';
import { OverlayModule } from '@angular/cdk/overlay';
import { TooltipCardComponent } from './tooltip-card/tooltip-card.component'; import { TooltipCardComponent } from './tooltip-card/tooltip-card.component';
import { InfiniteSelectScrollDirective } from './infinite-select-scroll.directive'; import { InfiniteSelectScrollDirective } from './infinite-select-scroll.directive';
@NgModule({ @NgModule({
imports: [ imports: [HighlightDirective, LogoutDirective, UploadDirective, TooltipCardDirective, TooltipCardComponent, InfiniteSelectScrollDirective],
CommonModule, exports: [HighlightDirective, LogoutDirective, UploadDirective, TooltipCardDirective, TooltipCardComponent, InfiniteSelectScrollDirective]
MaterialModule,
OverlayModule
],
declarations: [
HighlightDirective,
LogoutDirective,
UploadDirective,
TooltipCardDirective,
TooltipCardComponent,
InfiniteSelectScrollDirective
],
exports: [
HighlightDirective,
LogoutDirective,
UploadDirective,
TooltipCardDirective,
InfiniteSelectScrollDirective
]
}) })
/** @deprecated This module is deprecated and will be removed in a future release. Please consider importing standalone components and directives directly. */
export class DirectiveModule {} export class DirectiveModule {}

View File

@ -21,10 +21,10 @@ import { Directive, ElementRef, Input, Renderer2, AfterViewChecked } from '@angu
import { HighlightTransformService, HighlightTransformResult } from '../common/services/highlight-transform.service'; import { HighlightTransformService, HighlightTransformResult } from '../common/services/highlight-transform.service';
@Directive({ @Directive({
selector: '[adf-highlight]' selector: '[adf-highlight]',
standalone: true
}) })
export class HighlightDirective implements AfterViewChecked { export class HighlightDirective implements AfterViewChecked {
/** Class selector for highlightable elements. */ /** Class selector for highlightable elements. */
@Input('adf-highlight-selector') @Input('adf-highlight-selector')
selector: string = ''; selector: string = '';
@ -37,11 +37,7 @@ export class HighlightDirective implements AfterViewChecked {
@Input('adf-highlight-class') @Input('adf-highlight-class')
classToApply: string = 'adf-highlight'; classToApply: string = 'adf-highlight';
constructor( constructor(private el: ElementRef, private renderer: Renderer2, private highlightTransformService: HighlightTransformService) {}
private el: ElementRef,
private renderer: Renderer2,
private highlightTransformService: HighlightTransformService) {
}
ngAfterViewChecked() { ngAfterViewChecked() {
this.highlight(); this.highlight();
@ -52,7 +48,11 @@ export class HighlightDirective implements AfterViewChecked {
const elements = this.el.nativeElement.querySelectorAll(selector); const elements = this.el.nativeElement.querySelectorAll(selector);
elements.forEach((element) => { elements.forEach((element) => {
const highlightTransformResult: HighlightTransformResult = this.highlightTransformService.highlight(element.innerHTML, search, classToApply); const highlightTransformResult: HighlightTransformResult = this.highlightTransformService.highlight(
element.innerHTML,
search,
classToApply
);
if (highlightTransformResult.changed) { if (highlightTransformResult.changed) {
this.renderer.setProperty(element, 'innerHTML', highlightTransformResult.text); this.renderer.setProperty(element, 'innerHTML', highlightTransformResult.text);
} }

View File

@ -18,22 +18,21 @@
import { Component, ViewChild } from '@angular/core'; import { Component, ViewChild } from '@angular/core';
import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing'; import { ComponentFixture, fakeAsync, flush, TestBed } from '@angular/core/testing';
import { InfiniteSelectScrollDirective } from './infinite-select-scroll.directive'; import { InfiniteSelectScrollDirective } from './infinite-select-scroll.directive';
import { MatSelect, MatSelectModule } from '@angular/material/select'; import { MatSelect, MatSelectModule } from '@angular/material/select';
import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { HarnessLoader } from '@angular/cdk/testing'; import { HarnessLoader } from '@angular/cdk/testing';
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed'; import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { MatSelectHarness } from '@angular/material/select/testing'; import { MatSelectHarness } from '@angular/material/select/testing';
@Component({ @Component({
template: ` template: ` <mat-select adf-infinite-select-scroll (scrollEnd)="load()">
<mat-select adf-infinite-select-scroll (scrollEnd)="load()" > <mat-option *ngFor="let option of options; let idx = index">
<mat-option *ngFor="let option of options; let idx=index"> {{ option.text }}
{{ option.text }} </mat-option>
</mat-option> </mat-select>`
</mat-select>`
}) })
class TestComponent { class TestComponent {
options = new Array(50).fill({text: 'dummy'}); options = new Array(50).fill({ text: 'dummy' });
@ViewChild(MatSelect, { static: true }) @ViewChild(MatSelect, { static: true })
matSelect: MatSelect; matSelect: MatSelect;
@ -43,7 +42,7 @@ class TestComponent {
} }
load() { load() {
this.options.push(...new Array(10).fill({text: 'dummy'})); this.options.push(...new Array(10).fill({ text: 'dummy' }));
} }
} }
@ -54,14 +53,8 @@ describe('InfiniteSelectScrollDirective', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [MatSelectModule, NoopAnimationsModule, InfiniteSelectScrollDirective],
MatSelectModule, declarations: [TestComponent]
NoopAnimationsModule
],
declarations: [
TestComponent,
InfiniteSelectScrollDirective
]
}); });
fixture = TestBed.createComponent(TestComponent); fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
@ -77,7 +70,7 @@ describe('InfiniteSelectScrollDirective', () => {
it('should call an action on scrollEnd event', async () => { it('should call an action on scrollEnd event', async () => {
const select = await loader.getHarness(MatSelectHarness); const select = await loader.getHarness(MatSelectHarness);
const panel = (await select.host()); const panel = await select.host();
await panel.dispatchEvent('scrollEnd'); await panel.dispatchEvent('scrollEnd');

View File

@ -23,7 +23,8 @@ import { takeUntil } from 'rxjs/operators';
const SELECT_ITEM_HEIGHT_EM = 3; const SELECT_ITEM_HEIGHT_EM = 3;
@Directive({ @Directive({
selector: '[adf-infinite-select-scroll]' selector: '[adf-infinite-select-scroll]',
standalone: true
}) })
export class InfiniteSelectScrollDirective implements AfterViewInit, OnDestroy { export class InfiniteSelectScrollDirective implements AfterViewInit, OnDestroy {
static readonly MAX_ITEMS = 50; static readonly MAX_ITEMS = 50;
@ -37,14 +38,12 @@ export class InfiniteSelectScrollDirective implements AfterViewInit, OnDestroy {
constructor(@Inject(MatSelect) private matSelect: MatSelect) {} constructor(@Inject(MatSelect) private matSelect: MatSelect) {}
ngAfterViewInit() { ngAfterViewInit() {
this.matSelect.openedChange this.matSelect.openedChange.pipe(takeUntil(this.onDestroy$)).subscribe((opened: boolean) => {
.pipe(takeUntil(this.onDestroy$)) if (opened) {
.subscribe((opened: boolean) => { this.itemHeightToWaitBeforeLoadNext = this.getItemHeight() * (InfiniteSelectScrollDirective.MAX_ITEMS / 2);
if (opened) { this.matSelect.panel.nativeElement.addEventListener('scroll', (event: Event) => this.handleScrollEvent(event));
this.itemHeightToWaitBeforeLoadNext = (this.getItemHeight() * (InfiniteSelectScrollDirective.MAX_ITEMS / 2)); }
this.matSelect.panel.nativeElement.addEventListener('scroll', (event: Event) => this.handleScrollEvent(event)); });
}
});
} }
ngOnDestroy() { ngOnDestroy() {
@ -60,7 +59,7 @@ export class InfiniteSelectScrollDirective implements AfterViewInit, OnDestroy {
private isScrollInNextFetchArea(event: Event): boolean { private isScrollInNextFetchArea(event: Event): boolean {
const target = event.target as HTMLElement; const target = event.target as HTMLElement;
return target.scrollTop >= (target.scrollHeight - target.offsetHeight - this.itemHeightToWaitBeforeLoadNext); return target.scrollTop >= target.scrollHeight - target.offsetHeight - this.itemHeightToWaitBeforeLoadNext;
} }
private getItemHeight(): number { private getItemHeight(): number {

View File

@ -21,10 +21,10 @@ import { AppConfigService } from '../app-config/app-config.service';
import { AuthenticationService } from '../auth/services/authentication.service'; import { AuthenticationService } from '../auth/services/authentication.service';
@Directive({ @Directive({
selector: '[adf-logout]' selector: '[adf-logout]',
standalone: true
}) })
export class LogoutDirective implements OnInit { export class LogoutDirective implements OnInit {
/** URI to redirect to after logging out. */ /** URI to redirect to after logging out. */
@Input() @Input()
redirectUri: string; redirectUri: string;
@ -33,15 +33,15 @@ export class LogoutDirective implements OnInit {
@Input() @Input()
enableRedirect: boolean = true; enableRedirect: boolean = true;
constructor(private elementRef: ElementRef, constructor(
private renderer: Renderer2, private elementRef: ElementRef,
private router: Router, private renderer: Renderer2,
private appConfig: AppConfigService, private router: Router,
private authenticationService: AuthenticationService) { private appConfig: AppConfigService,
} private authenticationService: AuthenticationService
) {}
ngOnInit() { ngOnInit() {
if (this.elementRef.nativeElement) { if (this.elementRef.nativeElement) {
this.renderer.listen(this.elementRef.nativeElement, 'click', (evt) => { this.renderer.listen(this.elementRef.nativeElement, 'click', (evt) => {
evt.preventDefault(); evt.preventDefault();
@ -51,7 +51,7 @@ export class LogoutDirective implements OnInit {
} }
getRedirectUri() { getRedirectUri() {
if (this.redirectUri === undefined ) { if (this.redirectUri === undefined) {
return this.appConfig.get<string>('loginRoute', '/login'); return this.appConfig.get<string>('loginRoute', '/login');
} }
return this.redirectUri; return this.redirectUri;

View File

@ -15,10 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
export * from './tooltip-card/tooltip-card.directive';
export * from './tooltip-card/tooltip-card.component';
export * from './highlight.directive'; export * from './highlight.directive';
export * from './infinite-select-scroll.directive';
export * from './logout.directive'; export * from './logout.directive';
export * from './upload.directive'; export * from './upload.directive';
export * from './tooltip-card/tooltip-card.directive';
export * from './infinite-select-scroll.directive';
export * from './directive.module'; export * from './directive.module';

View File

@ -18,21 +18,18 @@
import { Component, Input, SecurityContext } from '@angular/core'; import { Component, Input, SecurityContext } from '@angular/core';
import { animate, style, transition, trigger } from '@angular/animations'; import { animate, style, transition, trigger } from '@angular/animations';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
@Component({ @Component({
selector: 'adf-tooltip-card-component', selector: 'adf-tooltip-card-component',
standalone: true,
imports: [CommonModule],
templateUrl: './tooltip-card.component.html', templateUrl: './tooltip-card.component.html',
styleUrls: ['./tooltip-card.component.scss'], styleUrls: ['./tooltip-card.component.scss'],
animations: [ animations: [
trigger('tooltip', [ trigger('tooltip', [
transition(':enter', [ transition(':enter', [style({ opacity: 0 }), animate(200, style({ opacity: 1 }))]),
style({ opacity: 0 }), transition(':leave', [animate(200, style({ opacity: 0 }))])
animate(200, style({ opacity: 1 }))
]),
transition(':leave', [
animate(200, style({ opacity: 0 }))
])
]) ])
] ]
}) })
@ -42,7 +39,7 @@ export class TooltipCardComponent {
@Input() htmlContent = ''; @Input() htmlContent = '';
@Input() width = '300'; @Input() width = '300';
constructor(private sanitizer: DomSanitizer) { } constructor(private sanitizer: DomSanitizer) {}
sanitizedHtmlContent(): string { sanitizedHtmlContent(): string {
return this.sanitizer.sanitize(SecurityContext.HTML, this.htmlContent); return this.sanitizer.sanitize(SecurityContext.HTML, this.htmlContent);

View File

@ -27,7 +27,14 @@ import { TooltipCardComponent } from './tooltip-card.component';
const IMAGE_URL = 'alfresco-logo.svg'; const IMAGE_URL = 'alfresco-logo.svg';
@Component({ @Component({
template: `<span #span [adf-tooltip-card]="'Sample text'" [image]="'${IMAGE_URL}'" [width]="'400'" [htmlContent]="'this is the <b>html</b> raw code'" class="test-component"></span>` template: `<span
#span
[adf-tooltip-card]="'Sample text'"
[image]="'${IMAGE_URL}'"
[width]="'400'"
[htmlContent]="'this is the <b>html</b> raw code'"
class="test-component"
></span>`
}) })
class TestComponent { class TestComponent {
@ViewChild(TooltipCardDirective, { static: true }) @ViewChild(TooltipCardDirective, { static: true })
@ -43,20 +50,12 @@ describe('TooltipCardDirective', () => {
let overlayService: Overlay; let overlayService: Overlay;
let overlayContainer: OverlayContainer; let overlayContainer: OverlayContainer;
beforeEach((() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [ imports: [CommonModule, OverlayModule, NoopAnimationsModule, TooltipCardDirective, TooltipCardComponent],
CommonModule, declarations: [TestComponent]
OverlayModule,
NoopAnimationsModule
],
declarations: [
TooltipCardDirective,
TooltipCardComponent,
TestComponent
]
}).compileComponents(); }).compileComponents();
})); });
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(TestComponent); fixture = TestBed.createComponent(TestComponent);

View File

@ -20,9 +20,11 @@ import { Overlay, OverlayPositionBuilder, OverlayRef } from '@angular/cdk/overla
import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentPortal } from '@angular/cdk/portal';
import { TooltipCardComponent } from './tooltip-card.component'; import { TooltipCardComponent } from './tooltip-card.component';
@Directive({ selector: '[adf-tooltip-card]' }) @Directive({
selector: '[adf-tooltip-card]',
standalone: true
})
export class TooltipCardDirective implements OnInit, OnDestroy { export class TooltipCardDirective implements OnInit, OnDestroy {
@Input('adf-tooltip-card') text = ''; @Input('adf-tooltip-card') text = '';
@Input() image = ''; @Input() image = '';
@Input() width = '300'; @Input() width = '300';
@ -36,11 +38,7 @@ export class TooltipCardDirective implements OnInit, OnDestroy {
private overlayRef: OverlayRef; private overlayRef: OverlayRef;
constructor( constructor(private overlay: Overlay, private overlayPositionBuilder: OverlayPositionBuilder, private elementRef: ElementRef) {}
private overlay: Overlay,
private overlayPositionBuilder: OverlayPositionBuilder,
private elementRef: ElementRef) {
}
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.overlayRef) { if (this.overlayRef) {
@ -49,24 +47,23 @@ export class TooltipCardDirective implements OnInit, OnDestroy {
} }
ngOnInit(): void { ngOnInit(): void {
const positionStrategy = this.overlayPositionBuilder const positionStrategy = this.overlayPositionBuilder.flexibleConnectedTo(this.elementRef).withPositions([
.flexibleConnectedTo(this.elementRef) {
.withPositions([{
originX: this.originX, originX: this.originX,
originY: this.originY, originY: this.originY,
overlayX: this.overlayX, overlayX: this.overlayX,
overlayY: this.overlayY, overlayY: this.overlayY,
offsetY: this.offsetY, offsetY: this.offsetY,
offsetX: this.offsetX offsetX: this.offsetX
}]); }
]);
this.overlayRef = this.overlay.create({ positionStrategy }); this.overlayRef = this.overlay.create({ positionStrategy });
} }
@HostListener('mouseenter') @HostListener('mouseenter')
show() { show() {
const tooltipRef: ComponentRef<TooltipCardComponent> const tooltipRef: ComponentRef<TooltipCardComponent> = this.overlayRef?.attach(new ComponentPortal(TooltipCardComponent));
= this.overlayRef?.attach(new ComponentPortal(TooltipCardComponent));
tooltipRef.instance.text = this.text; tooltipRef.instance.text = this.text;
tooltipRef.instance.image = this.image; tooltipRef.instance.image = this.image;
tooltipRef.instance.width = this.width; tooltipRef.instance.width = this.width;

View File

@ -21,7 +21,8 @@ import { Directive, ElementRef, HostListener, Input, NgZone, OnDestroy, OnInit,
import { FileInfo, FileUtils } from '../common/utils/file-utils'; import { FileInfo, FileUtils } from '../common/utils/file-utils';
@Directive({ @Directive({
selector: '[adf-upload]' selector: '[adf-upload]',
standalone: true
}) })
export class UploadDirective implements OnInit, OnDestroy { export class UploadDirective implements OnInit, OnDestroy {
/** Enables/disables uploading. */ /** Enables/disables uploading. */

View File

@ -0,0 +1,2 @@
.storybook
coverage

View File

@ -0,0 +1,2 @@
.storybook
coverage

3
lib/js-api/.eslintignore Normal file
View File

@ -0,0 +1,3 @@
.storybook
coverage
docs

View File

@ -1 +1,2 @@
.storybook .storybook
coverage

View File

@ -0,0 +1,2 @@
.storybook
coverage