Skip to content

Commit b5a94a6

Browse files
jnrpalmarafaellmarques
authored andcommitted
feat(image): implementa diretiva NgOptimizedImage
Implementa diretiva `NgOptimizedImage` fornecendo melhor desempenho para carregamento de imagens. fixes DTHFUI-7013
1 parent c2cd165 commit b5a94a6

File tree

6 files changed

+110
-21
lines changed

6 files changed

+110
-21
lines changed

projects/ui/src/lib/components/po-image/po-image-base.component.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,10 @@ describe('PoImageBaseComponent:', () => {
66
it('should be created', () => {
77
expect(component instanceof PoImageBaseComponent).toBeTruthy();
88
});
9+
10+
it('should isBase64 to true for valid image base64 string', () => {
11+
const validBase64 = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD';
12+
component.source = validBase64;
13+
expect(component.isBase64).toBe(true);
14+
});
915
});

projects/ui/src/lib/components/po-image/po-image-base.component.ts

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import { Directive, Input } from '@angular/core';
2+
import { isValidImageBase64 } from '../../utils/util';
3+
4+
type PoImageLoading = 'lazy' | 'eager' | 'auto';
25

36
/**
47
* @description
@@ -29,6 +32,9 @@ import { Directive, Input } from '@angular/core';
2932
*/
3033
@Directive()
3134
export class PoImageBaseComponent {
35+
isBase64: boolean = false;
36+
private _source: string;
37+
3238
/**
3339
* @optional
3440
*
@@ -56,5 +62,46 @@ export class PoImageBaseComponent {
5662
* Fonte da imagem que pode ser um caminho local (`./assets/images/logo-black-small.png`)
5763
* ou um servidor externo (`https://po-ui.io/assets/images/logo-black-small.png`).
5864
*/
59-
@Input('p-src') source: string;
65+
@Input('p-src') set source(value: string) {
66+
if (isValidImageBase64(value)) {
67+
this.isBase64 = true;
68+
}
69+
this._source = value;
70+
}
71+
72+
get source(): string {
73+
return this._source;
74+
}
75+
76+
/**
77+
* @optional
78+
*
79+
* @description
80+
*
81+
* Defini a prioridade de carregamento da imagem.
82+
* > Para as imagens com carregamento prioritátio ativo é necessário incluir
83+
* > uma tag link no head do arquivo index.html da sua aplicação.
84+
*
85+
* ```
86+
* <link rel="preconnect" href="<url_base_da_imagem>">
87+
* ```
88+
*
89+
* @default `false`
90+
*/
91+
@Input('p-priority') priority: boolean = false;
92+
93+
/**
94+
* @optional
95+
*
96+
* @description
97+
*
98+
* Defini o carregamento que pode ser dos tipo:
99+
*
100+
* — lazy
101+
* — eager
102+
* — auto
103+
*
104+
* > Não é permitido definir esta propriedade em conjunto com a propriedade `p-priority`.
105+
*/
106+
@Input('p-loading') loading?: PoImageLoading;
60107
}
Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1-
<po-container *ngIf="source">
2-
<img class="po-image" [attr.alt]="alternate" [attr.height]="height" [attr.src]="source" />
1+
<po-container class="po-container-image" *ngIf="source" [p-height]="height">
2+
<img
3+
*ngIf="!isBase64; else imageBase64"
4+
class="po-image"
5+
[attr.alt]="alternate"
6+
[priority]="priority"
7+
[loading]="loading"
8+
[fill]="true"
9+
[ngSrc]="source"
10+
/>
311
</po-container>
12+
13+
<ng-template #imageBase64>
14+
<img class="po-image" [attr.alt]="alternate" [loading]="loading" [src]="source" />
15+
</ng-template>

projects/ui/src/lib/components/po-image/po-image.module.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { NgModule } from '@angular/core';
2-
import { CommonModule } from '@angular/common';
2+
import { CommonModule, NgOptimizedImage } from '@angular/common';
33
import { PoImageComponent } from './po-image.component';
44
import { PoContainerModule } from '../po-container';
55

@@ -10,7 +10,7 @@ import { PoContainerModule } from '../po-container';
1010
*/
1111
@NgModule({
1212
declarations: [PoImageComponent],
13-
imports: [CommonModule, PoContainerModule],
13+
imports: [CommonModule, PoContainerModule, NgOptimizedImage],
1414
exports: [PoImageComponent]
1515
})
1616
export class PoImageModule {}

projects/ui/src/lib/utils/util.spec.ts

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import {
3131
validValue,
3232
valuesFromObject,
3333
removeDuplicatedOptionsWithFieldValue,
34-
removeUndefinedAndNullOptionsWithFieldValue
34+
removeUndefinedAndNullOptionsWithFieldValue,
35+
isValidImageBase64
3536
} from './util';
3637

3738
import * as UtilFunctions from './util';
@@ -1600,20 +1601,31 @@ describe('sortFields:', () => {
16001601
expect(result).toEqual(expectedFields);
16011602
});
16021603

1603-
describe('replaceFormatSeparator: ', () => {
1604-
it('should show date separator as . according to russian locale selected', () => {
1605-
const separator = '.';
1606-
const format = 'dd/mm/yyyy';
1607-
const expectedFormat = 'dd.mm.yyyy';
1608-
const newFormat = UtilFunctions.replaceFormatSeparator(format, separator);
1609-
expect(newFormat).toBe(expectedFormat);
1610-
});
1611-
it('should show date separator as / according to portuguese locale selected', () => {
1612-
const separator = '/';
1613-
const format = 'dd/mm/yyyy';
1614-
const expectedFormat = 'dd/mm/yyyy';
1615-
const newFormat = UtilFunctions.replaceFormatSeparator(format, separator);
1616-
expect(newFormat).toBe(expectedFormat);
1617-
});
1604+
it('returns true for valid image base64 string', () => {
1605+
const validBase64 = 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD';
1606+
expect(isValidImageBase64(validBase64)).toBe(true);
1607+
});
1608+
1609+
it('returns false for invalid image base64 string', () => {
1610+
const invalidBase64 = 'not a valid base64 string';
1611+
expect(isValidImageBase64(invalidBase64)).toBe(false);
1612+
});
1613+
});
1614+
1615+
describe('replaceFormatSeparator: ', () => {
1616+
it('should show date separator as . according to russian locale selected', () => {
1617+
const separator = '.';
1618+
const format = 'dd/mm/yyyy';
1619+
const expectedFormat = 'dd.mm.yyyy';
1620+
const newFormat = UtilFunctions.replaceFormatSeparator(format, separator);
1621+
expect(newFormat).toBe(expectedFormat);
1622+
});
1623+
1624+
it('should show date separator as / according to portuguese locale selected', () => {
1625+
const separator = '/';
1626+
const format = 'dd/mm/yyyy';
1627+
const expectedFormat = 'dd/mm/yyyy';
1628+
const newFormat = UtilFunctions.replaceFormatSeparator(format, separator);
1629+
expect(newFormat).toBe(expectedFormat);
16181630
});
16191631
});

projects/ui/src/lib/utils/util.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,18 @@ export function convertImageToBase64(file: File): Promise<any> {
547547
});
548548
}
549549

550+
/**
551+
* Valida se a imagem é do tipo base64 valida
552+
*
553+
*/
554+
export function isValidImageBase64(value: string): boolean {
555+
try {
556+
return !!value.match(/^data:image\/([a-zA-Z]*);base64,([^\"]*)$/);
557+
} catch (err) {
558+
return false;
559+
}
560+
}
561+
550562
/**
551563
* Converte um número em decimal baseado na quantidade de casas decimais.
552564
*

0 commit comments

Comments
 (0)