diff --git a/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.html b/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.html index cf04ba6cb70a..91d207a889f6 100644 --- a/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.html +++ b/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.html @@ -1,13 +1,13 @@ -@for (preview of linkPreviews; track trackLinks($index, preview)) { +@for (preview of linkPreviews(); track trackLinks($index, preview)) {
} diff --git a/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.ts b/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.ts index 6234e60bae60..1349476f4d0c 100644 --- a/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.ts +++ b/src/main/webapp/app/shared/link-preview/components/link-preview-container/link-preview-container.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnChanges, OnInit } from '@angular/core'; +import { ChangeDetectionStrategy, Component, OnChanges, OnInit, inject, input, signal } from '@angular/core'; import { LinkPreview, LinkPreviewService } from 'app/shared/link-preview/services/link-preview.service'; import { Link, LinkifyService } from 'app/shared/link-preview/services/linkify.service'; import { User } from 'app/core/user/user.model'; @@ -8,45 +8,41 @@ import { Posting } from 'app/entities/metis/posting.model'; selector: 'jhi-link-preview-container', templateUrl: './link-preview-container.component.html', styleUrls: ['./link-preview-container.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class LinkPreviewContainerComponent implements OnInit, OnChanges { - @Input() data: string | undefined; - @Input() author?: User; - @Input() posting?: Posting; - @Input() isEdited?: boolean; - @Input() isReply?: boolean; + private readonly linkPreviewService: LinkPreviewService = inject(LinkPreviewService); + private readonly linkifyService: LinkifyService = inject(LinkifyService); - linkPreviews: LinkPreview[] = []; - hasError: boolean; - loaded = false; - showLoadingsProgress = true; - multiple = false; + readonly data = input(); + readonly author = input(); + readonly posting = input(); + readonly isEdited = input(); + readonly isReply = input(); - constructor( - public linkPreviewService: LinkPreviewService, - public linkifyService: LinkifyService, - ) {} + readonly linkPreviews = signal([]); + readonly hasError = signal(false); + readonly loaded = signal(false); + readonly showLoadingsProgress = signal(true); + readonly multiple = signal(false); ngOnInit() { - this.data = this.data ?? ''; this.findPreviews(); } ngOnChanges() { - if (this.isEdited) { - this.reloadLinkPreviews(); - } + this.reloadLinkPreviews(); } private reloadLinkPreviews() { - this.loaded = false; - this.showLoadingsProgress = true; - this.linkPreviews = []; // Clear the existing link previews + this.loaded.set(false); + this.showLoadingsProgress.set(true); + this.linkPreviews.set([]); // Clear the existing link previews this.findPreviews(); } private findPreviews() { - const links: Link[] = this.linkifyService.find(this.data!); + const links: Link[] = this.linkifyService.find(this.data() ?? ''); // TODO: The limit of 5 link previews should be configurable (maybe in course level) links .filter((link) => !link.isLinkPreviewRemoved) @@ -56,17 +52,21 @@ export class LinkPreviewContainerComponent implements OnInit, OnChanges { next: (linkPreview) => { linkPreview.shouldPreviewBeShown = !!(linkPreview.url && linkPreview.title && linkPreview.description && linkPreview.image); - const existingLinkPreview = this.linkPreviews.find((preview) => preview.url === linkPreview.url); - if (existingLinkPreview) { - Object.assign(existingLinkPreview, linkPreview); + const existingLinkPreviewIndex = this.linkPreviews().findIndex((preview) => preview.url === linkPreview.url); + if (existingLinkPreviewIndex !== -1) { + this.linkPreviews.update((previews) => { + const existingLinkPreview = previews[existingLinkPreviewIndex]; + Object.assign(existingLinkPreview, linkPreview); + return previews; + }); } else { - this.linkPreviews.push(linkPreview); + this.linkPreviews.set([...this.linkPreviews(), linkPreview]); } - this.hasError = false; - this.loaded = true; - this.showLoadingsProgress = false; - this.multiple = this.linkPreviews.length > 1; + this.hasError.set(false); + this.loaded.set(true); + this.showLoadingsProgress.set(false); + this.multiple.set(this.linkPreviews().length > 1); }, }); }); diff --git a/src/test/javascript/spec/component/link-preview/link-preview-container.component.spec.ts b/src/test/javascript/spec/component/link-preview/link-preview-container.component.spec.ts index 6f17eeba735a..534aaad61e6f 100644 --- a/src/test/javascript/spec/component/link-preview/link-preview-container.component.spec.ts +++ b/src/test/javascript/spec/component/link-preview/link-preview-container.component.spec.ts @@ -37,7 +37,7 @@ describe('LinkPreviewContainerComponent', () => { }); it('should fetch link previews and update linkPreviews array', () => { - component.data = 'Check out these links: https://example.com/link1 and https://example.com/link2'; + fixture.componentRef.setInput('data', 'Check out these links: https://example.com/link1 and https://example.com/link2'); const links: Link[] = [ { type: '', value: '', href: 'https://example.com/link1' }, { type: '', value: '', href: 'https://example.com/link2' }, @@ -52,18 +52,18 @@ describe('LinkPreviewContainerComponent', () => { component.ngOnInit(); - expect(linkifyServiceSpy).toHaveBeenCalledWith(component.data); + expect(linkifyServiceSpy).toHaveBeenCalledWith(component.data()); expect(linkPreviewServiceSpy).toHaveBeenCalledTimes(2); expect(linkPreviewServiceSpy).toHaveBeenCalledWith('https://example.com/link1'); expect(linkPreviewServiceSpy).toHaveBeenCalledWith('https://example.com/link2'); - expect(component.linkPreviews).toEqual(mockLinkPreviews); - expect(component.hasError).toBeFalse(); - expect(component.loaded).toBeTrue(); - expect(component.showLoadingsProgress).toBeFalse(); + expect(component.linkPreviews()).toEqual(mockLinkPreviews); + expect(component.hasError()).toBeFalse(); + expect(component.loaded()).toBeTrue(); + expect(component.showLoadingsProgress()).toBeFalse(); }); it('should update existing link preview if it already exists', () => { - component.data = 'Check out these links: https://example.com/link1'; + fixture.componentRef.setInput('data', 'Check out these links: https://example.com/link1'); const links: Link[] = [{ type: '', value: '', href: 'https://example.com/link1' }]; const existingLinkPreview: LinkPreview = { url: 'https://example.com/link1', @@ -77,14 +77,14 @@ describe('LinkPreviewContainerComponent', () => { const linkifyServiceSpy = jest.spyOn(linkifyService, 'find').mockReturnValue(links); const linkPreviewServiceSpy = jest.spyOn(linkPreviewService, 'fetchLink').mockReturnValueOnce(of(newLinkPreview)); - component.linkPreviews.push(existingLinkPreview); + component.linkPreviews().push(existingLinkPreview); component.ngOnInit(); - expect(linkifyServiceSpy).toHaveBeenCalledWith(component.data); + expect(linkifyServiceSpy).toHaveBeenCalledWith(component.data()); expect(linkPreviewServiceSpy).toHaveBeenCalledOnce(); expect(linkPreviewServiceSpy).toHaveBeenCalledWith('https://example.com/link1'); - expect(component.linkPreviews).toHaveLength(1); - expect(component.linkPreviews[0]).toEqual(newLinkPreview); + expect(component.linkPreviews()).toHaveLength(1); + expect(component.linkPreviews()[0]).toEqual(newLinkPreview); }); });