Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(search): implementa animaliaDS e externaliza para uso no portal #1870

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions projects/portal/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ <h4>
</div>

<script src="https://vlibras.gov.br/app/vlibras-plugin.js"></script>
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<script>
new window.VLibras.Widget('https://vlibras.gov.br/app');
</script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* @description
*
* Define o tipo de busca usado no po-multiselect.
* Define o tipo de busca usado no po-search.
*/
export enum PoSearchFilterMode {
/** Verifica se o texto *inicia* com o valor pesquisado. */
Expand Down
3 changes: 2 additions & 1 deletion projects/ui/src/lib/components/po-search/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './po-search.component';
export * from './po-search.module';
export * from './po-search-filter-mode.enum';
export * from './enum/po-search-filter-mode.enum';
export * from './literals/po-search-literals';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { PoSearchLiterals } from './po-search-literals';

export const poSearchLiteralsDefault = {
en: <PoSearchLiterals>{
search: 'Search',
clean: 'Clean'
},
es: <PoSearchLiterals>{
search: 'Buscar',
clean: 'limpiar'
},
pt: <PoSearchLiterals>{
search: 'Pesquisar',
clean: 'Apagar'
},
ru: <PoSearchLiterals>{
search: 'Поиск',
clean: 'чистый'
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,18 @@ export interface PoSearchLiterals {
*
* @description
*
* search: Texto exibido no *placeholder* do filtro do componente menu.
* search: Texto exibido no *placeholder* do filtro do componente `po-search`.
*/
search?: string;

/**
* @usedBy PoSearchComponent
*
* @optional
*
* @description
*
* search: Texto usado no leitor de tela para acessibilidade.
*/
clean?: string;
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,53 @@
import { PoSearchBaseComponent } from './po-search-base.component';
import { PoLanguageService } from '../../services/po-language/po-language.service';
import { poSearchLiteralsDefault } from './literals/po-search-literals-default';
import { poLocaleDefault } from '../../services/po-language/po-language.constant';
import * as Utils from '../../utils/util';

describe('PoSearchBaseComponent', () => {
let component: PoSearchBaseComponent;

beforeEach(() => {
component = new PoSearchBaseComponent();
component = new PoSearchBaseComponent(new PoLanguageService());
});

it('should create an instance', () => {
expect(component).toBeTruthy();
});

describe('Properties:', () => {
it('label: should set label when is setted', () => {
component.ariaLabel = 'Search';

expect(component.ariaLabel).toBe('Search');
});

it('label: should concat label with literals', () => {
component.ariaLabel = 'label button';
expect(component.ariaLabel).toBe('label button Search');
});

it('should be set `literals` with browser language if `literals` is `undefined`', () => {
component['language'] = Utils.browserLanguage();
component.literals = undefined;

expect(component.literals).toEqual(poSearchLiteralsDefault[Utils.browserLanguage()]);
});

it('should be in portuguese if browser is set with `pt`.', () => {
component['language'] = 'pt';

component.literals = {};

expect(component.literals).toEqual(poSearchLiteralsDefault[poLocaleDefault]);
});

it('should be in english if browser is set with `en`.', () => {
component['language'] = 'en';

component.literals = {};

expect(component.literals).toEqual(poSearchLiteralsDefault.en);
});
});
});
176 changes: 171 additions & 5 deletions projects/ui/src/lib/components/po-search/po-search-base.component.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,187 @@
import { PoFilterMode } from './po-search-filter-mode.enum';
import { PoLanguageService } from '../../services/po-language/po-language.service';
import { poLocaleDefault } from '../../services/po-language/po-language.constant';

import { Directive, EventEmitter, Input, Output } from '@angular/core';
import { Directive, EventEmitter, Input, Output, TemplateRef } from '@angular/core';
import { convertToBoolean } from '../../utils/util';
import { PoSearchLiterals } from './literals/po-search-literals';
import { poSearchLiteralsDefault } from './literals/po-search-literals-default';
import { PoSearchFilterMode } from './enum/po-search-filter-mode.enum';

/**
* @description
*
* O componente search, também conhecido como barra de pesquisa, é utilizado para ajudar os usuários a localizar um determinado conteúdo
*
* Normalmente localizado no canto superior direito, junto com o ícone de lupa, uma vez que este ícone é amplamente reconhecido.
*
* Portanto, é de extrema importância que, ao utilizar este componente, as pessoas responsáveis por seu desenvolvimento considerem os seguintes critérios.
*
* #### Boas práticas
*
* Foram estruturados os padrões de usabilidade para auxiliar na utilização do componente e garantir uma boa experiência aos usuários. Por isso, é muito importante que ao utilizar este componente, as pessoas que o projetarem devem levar em consideração os seguintes critérios:
* - Utilize labels para apresentar resultados que estão sendo exibidos e apresente os resultados mais relevantes primeiro.
* - Exiba uma mensagem clara quando não forem encontrados resultados para busca e sempre que possível ofereça outras sugestões de busca.
* - Mantenha o texto original no campo de input, que facilita a ação do usuário caso queira fazer uma nova busca com alguma modificação na pesquisa.
* - Caso seja possível detectar um erro de digitação, mostre os resultados para a palavra "corrigida", isso evita a frustração de não obter resultados e não força o usuário a realizar uma nova busca.
* - Quando apropriado, destaque os termos da busca nos resultados.
* - A entrada do campo de pesquisa deve caber em uma linha. Não use entradas de pesquisa de várias linhas.
* - Recomenda-se ter apenas uma pesquisa por página. Se você precisar de várias pesquisas, rotule-as claramente para indicar sua finalidade.
* - Se possível, forneça sugestões de pesquisa, seja em um helptext ou sugestão de pesquisa que é um autocomplete. Isso ajuda os usuários a encontrar o que estão procurando, especialmente se os itens pesquisáveis forem complexos.
*
* #### Acessibilidade tratada no componente
*
* Algumas diretrizes de acessibilidade já são tratadas no componente, internamente, e não podem ser alteradas pelo proprietário do conteúdo. São elas:
*
* - Permitir a interação via teclado (2.1.1: Keyboard (A));
* - Alteração entre os estados precisa ser indicada por mais de um elemento além da cor (1.4.1: Use of Color);
*/
@Directive()
export class PoSearchBaseComponent {
@Input({ alias: 'p-disabled', transform: convertToBoolean }) disabled?: boolean;
private _literals?: PoSearchLiterals;
private _ariaLabel?: string;
private language: string;

@Input('p-loading') loading: boolean;
/**
* @optional
*
* @description
*
* Desabilita o po-search e não permite que o usuário interaja com o mesmo.
*
* @default `false`
*/
@Input({ alias: 'p-disabled', transform: convertToBoolean }) disabled?: boolean;

/**
* @optional
*
* @description
*
* Lista de itens que serão utilizados para pesquisa
*/
@Input('p-items') items: Array<any> = [];

/**
* @optional
*
* @description
*
* Define um aria-label para o po-search.
*
* > Devido o componente não possuir uma label assim como outros campos de texto, o `aria-label` é utilizado para acessibilidade.
*/
@Input('p-aria-label') set ariaLabel(value: string) {
this._ariaLabel = value;

if (value !== this.literals.search) {
this._ariaLabel = `${this._ariaLabel} ${this.literals.search}`;
}
}

get ariaLabel(): string {
return this._ariaLabel;
}

/**
* @optional
*
* @description
*
* Deve ser informado o nome da propriedade do objeto que será utilizado para a conversão dos itens apresentados na lista do componente (p-items), esta propriedade será responsável pelo texto de apresentação de cada item da lista.
*/
@Input('p-filter-keys') filterKeys: Array<any> = [];

@Input('p-filter-type') filterType: PoFilterMode = PoFilterMode.startsWith;
/**
* @optional
*
* @description
*
* Deve ser informado o nome da propriedade do objeto que será utilizado para a conversão dos itens apresentados na lista do componente (p-items), esta propriedade será responsável pelo texto de apresentação de cada item da lista.
*/
@Input('p-icon') icon: string | TemplateRef<void>;

/**
* @optional
*
* @description
*
* Objeto com as literais usadas no `po-search`.
*
* Para utilizar basta passar a literal que deseja customizar:
*
* ```
* const customLiterals: PoSearchLiterals = {
* search: 'Pesquisar',
* clean: 'Limpar',
* };
* ```
*
* E para carregar a literal customizada, basta apenas passar o objeto para o componente.
*
* ```
* <po-search
* [p-literals]="customLiterals">
* </po-search>
* ```
*
* > O objeto padrão de literais será traduzido de acordo com o idioma do
* [`PoI18nService`](/documentation/po-i18n) ou do browser.
*/
@Input('p-literals') set literals(value: PoSearchLiterals) {
if (value instanceof Object && !(value instanceof Array)) {
this._literals = {
...poSearchLiteralsDefault[poLocaleDefault],
...poSearchLiteralsDefault[this.language],
...value
};
} else {
this._literals = poSearchLiteralsDefault[this.language];
}
}

get literals() {
return this._literals || poSearchLiteralsDefault[this.language];
}

/**
* @optional
*
* @description
*
* Define o modo de pesquisa utilizado no campo de busca, quando habilitado. Valores definidos no enum: PoSearchFilterMode
*
* @default `startsWith`
*/
@Input('p-filter-type') filterType: PoSearchFilterMode = PoSearchFilterMode.startsWith;

/**
* @optional
*
* @description
*
* Evento disparado ao alterar valor do model.
*/
@Output('p-change-model') changeModel: EventEmitter<any> = new EventEmitter();

/**
* @optional
*
* @description
*
* Pode ser informada uma função que será disparada quando houver alterações no input.
*/
@Output('p-filtered-items-change') filteredItemsChange = new EventEmitter<Array<any>>();

/**
* @optional
*
* @description
*
* Pode ser informada uma função que será disparada quando houver alterações nos filtros.
*/
@Output('p-filter') filter: EventEmitter<any> = new EventEmitter<any>();

constructor(languageService: PoLanguageService) {
this.language = languageService.getShortLanguage();
}
}

This file was deleted.

19 changes: 14 additions & 5 deletions projects/ui/src/lib/components/po-search/po-search.component.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
<div class="po-search">
<div class="po-search" [class.po-search-disabled]="disabled">
<div class="po-search-icon">
<po-icon *ngIf="!loading" p-icon="po-icon-search"></po-icon>
<po-loading-icon *ngIf="loading" p-size="sm"></po-loading-icon>
<po-icon [p-icon]="icon ? icon : 'po-icon-search'"></po-icon>
</div>

<input
#poSearchInput
type="text"
class="po-search-input"
[ariaLabel]="ariaLabel"
[class.po-search-icon-right]="!!poSearchInput.value && !disabled"
[disabled]="disabled"
[placeholder]="literals.search"
(blur)="onBlur()"
(focus)="onFocus()"
(input)="onSearchChange($event.target.value)"
/>

<div *ngIf="!!poSearchInput.value && !disabled" class="po-search-clean" [tabindex]="!disabled ? 0 : -1">
<po-clean [p-element-ref]="poSearchInput" (p-change-event)="clearSearch()"></po-clean>
<div *ngIf="!!poSearchInput.value && !disabled" class="po-search-container-clean">
<button
class="po-search-clean"
[ariaLabel]="literals.clean"
(click)="clearSearch()"
(keydown.enter)="clearSearch()"
>
<po-icon p-icon="po-icon-clear-content"></po-icon>
</button>
</div>
</div>
Loading