diff --git a/apps/datahub-e2e/src/e2e/organizations.cy.ts b/apps/datahub-e2e/src/e2e/organizations.cy.ts
index 106610cfcc..7a5e521697 100644
--- a/apps/datahub-e2e/src/e2e/organizations.cy.ts
+++ b/apps/datahub-e2e/src/e2e/organizations.cy.ts
@@ -5,7 +5,7 @@ describe('organizations', () => {
cy.visit('/home/organisations')
// aliases
- cy.get('gn-ui-organisations-sort')
+ cy.get('gn-ui-organisations-filter')
.find('gn-ui-dropdown-selector')
.as('sort')
cy.get('gn-ui-pagination').children('div').as('pagination')
@@ -21,6 +21,12 @@ describe('organizations', () => {
cy.get('@organizations')
.find('[data-cy="organizationRecordsCount"]')
.as('organizationsRecordsCount')
+ cy.get('gn-ui-organisations-filter')
+ .find('gn-ui-search-input')
+ .as('organisationsSearch')
+ cy.get('gn-ui-organisations')
+ .find('gn-ui-organisations-result')
+ .as('organisationsResult')
})
describe('general display', () => {
@@ -32,7 +38,7 @@ describe('organizations', () => {
.should('eq', 'decoration-primary')
})
it('should display the welcome panel', () => {
- cy.get('gn-ui-organisations-sort').should('be.visible')
+ cy.get('gn-ui-organisations-filter').should('be.visible')
cy.get('@sort').openDropdown().children('button').should('have.length', 4)
})
it('should display organizations with thumbnail, title and description', () => {
@@ -135,4 +141,37 @@ describe('organizations', () => {
})
})
})
+
+ describe('search filter', () => {
+ it('should display filtered results ignoring accents and case', () => {
+ cy.get('@organisationsSearch').type('geo2france')
+ cy.get('@organizationsName').should('have.length', 1)
+ cy.get('@organisationsResult').should('contain', '1')
+ cy.get('@organizationsName')
+ .eq(0)
+ .invoke('text')
+ .should('contain', 'Géo2France')
+ })
+ it('should display filtered results containing multiple words', () => {
+ cy.get('@organisationsSearch').type('dreal hdf')
+ cy.get('@organizationsName').should('have.length', 1)
+ cy.get('@organisationsResult').should('contain', '1')
+ cy.get('@organizationsName')
+ .eq(0)
+ .invoke('text')
+ .should('contain', 'DREAL HdF')
+ })
+ it('should display multiple results and refine search', () => {
+ cy.get('@organisationsSearch').type('de')
+ cy.get('@organizationsName').should('have.length', 10)
+ cy.get('@organisationsResult').should('contain', '10')
+ cy.get('@organisationsSearch').type(' Lille')
+ cy.get('@organizationsName').should('have.length', 1)
+ cy.get('@organisationsResult').should('contain', '1')
+ })
+ it('should display a message for no results found', () => {
+ cy.get('@organisationsSearch').type('An organisation that does not exist')
+ cy.get('@organisationsResult').should('contain', 'No organizations found')
+ })
+ })
})
diff --git a/libs/feature/catalog/src/lib/organisations/organisations.component.html b/libs/feature/catalog/src/lib/organisations/organisations.component.html
index 14f76db490..f832e2289e 100644
--- a/libs/feature/catalog/src/lib/organisations/organisations.component.html
+++ b/libs/feature/catalog/src/lib/organisations/organisations.component.html
@@ -1,6 +1,14 @@
-
+ (filterBy)="setFilterBy($event)"
+>
+
+
+
diff --git a/libs/feature/catalog/src/lib/organisations/organisations.component.spec.ts b/libs/feature/catalog/src/lib/organisations/organisations.component.spec.ts
index 87708db479..c20394acca 100644
--- a/libs/feature/catalog/src/lib/organisations/organisations.component.spec.ts
+++ b/libs/feature/catalog/src/lib/organisations/organisations.component.spec.ts
@@ -16,10 +16,10 @@ import { OrganisationsComponent } from './organisations.component'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
@Component({
- selector: 'gn-ui-organisations-sort',
+ selector: 'gn-ui-organisations-filter',
template: '
',
})
-class OrganisationsSortMockComponent {
+class OrganisationsFilterMockComponent {
@Output() sortBy = new EventEmitter
()
}
@Component({
@@ -31,6 +31,15 @@ class OrganisationPreviewMockComponent {
@Output() clickedOrganisation = new EventEmitter()
}
+@Component({
+ selector: 'gn-ui-organisations-result',
+ template: '',
+})
+class OrganisationsResultMockComponent {
+ @Input() hits: number
+ @Input() total: number
+}
+
@Component({
selector: 'gn-ui-pagination',
template: '',
@@ -43,6 +52,7 @@ class PaginationMockComponent {
class OrganisationsServiceMock {
organisations$ = of(ORGANISATIONS_FIXTURE)
+ organisationsCount$ = of(ORGANISATIONS_FIXTURE.length)
}
const organisationMock = {
@@ -63,9 +73,10 @@ describe('OrganisationsComponent', () => {
await TestBed.configureTestingModule({
declarations: [
OrganisationsComponent,
- OrganisationsSortMockComponent,
+ OrganisationsFilterMockComponent,
OrganisationPreviewMockComponent,
PaginationMockComponent,
+ OrganisationsResultMockComponent,
ContentGhostComponent,
],
providers: [
@@ -93,6 +104,7 @@ describe('OrganisationsComponent', () => {
describe('on component init', () => {
let orgPreviewComponents: OrganisationPreviewMockComponent[]
+ let orgResultComponent: OrganisationsResultMockComponent
let paginationComponentDE: DebugElement
let setCurrentPageSpy
let setSortBySpy
@@ -156,7 +168,7 @@ describe('OrganisationsComponent', () => {
beforeEach(() => {
setSortBySpy = jest.spyOn(component, 'setSortBy')
de.query(
- By.directive(OrganisationsSortMockComponent)
+ By.directive(OrganisationsFilterMockComponent)
).triggerEventHandler('sortBy', ['desc', 'recordCount'])
fixture.detectChanges()
orgPreviewComponents = de
@@ -181,6 +193,69 @@ describe('OrganisationsComponent', () => {
)
})
})
+ describe('filter organisations', () => {
+ describe('initial state', () => {
+ beforeEach(() => {
+ orgResultComponent = de.query(
+ By.directive(OrganisationsResultMockComponent)
+ )
+ })
+ it('should display number of organisations found to equal all', () => {
+ expect(orgResultComponent.componentInstance.hits).toEqual(
+ ORGANISATIONS_FIXTURE.length
+ )
+ })
+ it('should display number of all organisations', () => {
+ expect(orgResultComponent.componentInstance.total).toEqual(
+ ORGANISATIONS_FIXTURE.length
+ )
+ })
+ })
+ describe('entering search terms', () => {
+ beforeEach(() => {
+ orgResultComponent = de.query(
+ By.directive(OrganisationsResultMockComponent)
+ )
+ })
+ it('should ignore case and display 11 matches for "Data", "DATA" or "data"', () => {
+ component.filterBy$.next('Data')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(11)
+ component.filterBy$.next('DATA')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(11)
+ component.filterBy$.next('data')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(11)
+ })
+ it('should ignore accents and case and display 2 matches for "é Data Org", "e Data Org" or "E Data Org"', () => {
+ component.filterBy$.next('é Data Org')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(2)
+ component.filterBy$.next('e Data Org')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(2)
+ component.filterBy$.next('E Data Org')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(2)
+ })
+ it('should combine multiple termes with "AND" logic and display 1 match for "a data"', () => {
+ component.filterBy$.next('a data')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(1)
+ })
+ it('should combine multiple termes with "AND" logic and display 11 matches for "data org"', () => {
+ component.filterBy$.next('data org')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(11)
+ })
+ it('should display 12 matches for "ORG"', () => {
+ component.filterBy$.next('ORG')
+ fixture.detectChanges()
+ expect(orgResultComponent.componentInstance.hits).toEqual(12)
+ })
+ })
+ })
describe('click on organisation', () => {
let orgSelected
beforeEach(() => {
diff --git a/libs/feature/catalog/src/lib/organisations/organisations.component.ts b/libs/feature/catalog/src/lib/organisations/organisations.component.ts
index 79d1c3e25c..12b07a70ec 100644
--- a/libs/feature/catalog/src/lib/organisations/organisations.component.ts
+++ b/libs/feature/catalog/src/lib/organisations/organisations.component.ts
@@ -33,27 +33,34 @@ export class OrganisationsComponent {
totalPages: number
currentPage$ = new BehaviorSubject(1)
+ organisationResults: number
sortBy$: BehaviorSubject = new BehaviorSubject(['asc', 'name'])
-
- organisationsSorted$: Observable = combineLatest([
+ filterBy$: BehaviorSubject = new BehaviorSubject('')
+ organisationsTotal$ = this.organisationsService.organisationsCount$
+ organisationsFilteredAndSorted$: Observable = combineLatest([
this.organisationsService.organisations$.pipe(
startWith(Array(this.itemsOnPage).fill({}))
),
this.sortBy$,
+ this.filterBy$,
]).pipe(
- map(([organisations, sortBy]) =>
- this.sortOrganisations(organisations, sortBy)
- )
+ map(([organisations, sortBy, filterBy]) => {
+ const filteredOrganisations = this.filterOrganisations(
+ organisations,
+ filterBy
+ )
+ return this.sortOrganisations(filteredOrganisations, sortBy)
+ })
)
organisations$: Observable = combineLatest([
- this.organisationsSorted$,
+ this.organisationsFilteredAndSorted$,
this.currentPage$,
]).pipe(
- tap(
- ([organisations]) =>
- (this.totalPages = Math.ceil(organisations.length / this.itemsOnPage))
- ),
+ tap(([organisations]) => {
+ this.organisationResults = organisations.length
+ this.totalPages = Math.ceil(organisations.length / this.itemsOnPage)
+ }),
map(([organisations, page]) =>
organisations.slice(
(page - 1) * this.itemsOnPage,
@@ -66,10 +73,35 @@ export class OrganisationsComponent {
this.currentPage$.next(page)
}
+ protected setFilterBy(value: string): void {
+ this.filterBy$.next(value)
+ }
+
protected setSortBy(value: SortByField): void {
this.sortBy$.next(value)
}
+ private filterOrganisations(organisations: Organization[], filterBy: string) {
+ if (!filterBy) return organisations
+ const filterRegex = new RegExp(
+ this.normalizeString(filterBy) //ignore accents and case
+ .replace(/[^a-z0-9\s]/g, '') //ignore special characters
+ .replace(/\s(?=.)/g, '.*') //replace whitespaces by "AND" separator
+ .replace(/\s/g, ''), //remove potential whitespaces left
+ 'i'
+ )
+ return [...organisations].filter((org) => {
+ return this.normalizeString(org.name).match(filterRegex)
+ })
+ }
+
+ private normalizeString(str: string) {
+ return str
+ .normalize('NFD')
+ .replace(/[\u0300-\u036f]/g, '')
+ .toLowerCase()
+ }
+
private sortOrganisations(
organisations: Organization[],
sortBy: SortByField
diff --git a/libs/ui/catalog/src/index.ts b/libs/ui/catalog/src/index.ts
index 97165c1c8f..3cebead339 100644
--- a/libs/ui/catalog/src/index.ts
+++ b/libs/ui/catalog/src/index.ts
@@ -2,4 +2,4 @@ export * from './lib/ui-catalog.module'
export * from './lib/catalog-title/catalog-title.component'
export * from './lib/language-switcher/language-switcher.component'
export * from './lib/organisation-preview/organisation-preview.component'
-export * from './lib/organisations-sort/organisations-sort.component'
+export * from './lib/organisations-filter/organisations-filter.component'
diff --git a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.html b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.html
similarity index 52%
rename from libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.html
rename to libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.html
index 6edd40bab9..6fd793a552 100644
--- a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.html
+++ b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.html
@@ -1,8 +1,11 @@
-
- organisation.sort.intro
+
+
{
- let component: OrganisationsSortComponent
- let fixture: ComponentFixture
+ let component: OrganisationsFilterComponent
+ let fixture: ComponentFixture
beforeEach(async () => {
await TestBed.configureTestingModule({
- declarations: [OrganisationsSortComponent, DropdownSelectorMockComponent],
+ declarations: [
+ OrganisationsFilterComponent,
+ DropdownSelectorMockComponent,
+ ],
imports: [TranslateModule.forRoot()],
}).compileComponents()
- fixture = TestBed.createComponent(OrganisationsSortComponent)
+ fixture = TestBed.createComponent(OrganisationsFilterComponent)
component = fixture.componentInstance
fixture.detectChanges()
})
diff --git a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.stories.ts b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.stories.ts
similarity index 69%
rename from libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.stories.ts
rename to libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.stories.ts
index de2da26bd9..62adb35991 100644
--- a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.stories.ts
+++ b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.stories.ts
@@ -9,12 +9,12 @@ import {
TRANSLATE_DEFAULT_CONFIG,
UtilI18nModule,
} from '@geonetwork-ui/util/i18n'
-import { OrganisationsSortComponent } from './organisations-sort.component'
+import { OrganisationsFilterComponent } from './organisations-filter.component'
import { DropdownSelectorComponent } from '@geonetwork-ui/ui/inputs'
export default {
- title: 'Catalog/OrganisationsSortComponent',
- component: OrganisationsSortComponent,
+ title: 'Catalog/OrganisationsFilterComponent',
+ component: OrganisationsFilterComponent,
decorators: [
moduleMetadata({
declarations: [DropdownSelectorComponent],
@@ -27,6 +27,6 @@ export default {
(story) => `${story}
`
),
],
-} as Meta
+} as Meta
-export const Primary: StoryObj = {}
+export const Primary: StoryObj = {}
diff --git a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.ts b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.ts
similarity index 69%
rename from libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.ts
rename to libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.ts
index 682eb36f7f..b6f2049525 100644
--- a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.ts
+++ b/libs/ui/catalog/src/lib/organisations-filter/organisations-filter.component.ts
@@ -6,14 +6,14 @@ import {
} from '@angular/core'
import { marker } from '@biesbjerg/ngx-translate-extract-marker'
import { SortByField } from '@geonetwork-ui/common/domain/model/search'
+import { Subject, debounceTime } from 'rxjs'
@Component({
- selector: 'gn-ui-organisations-sort',
- templateUrl: './organisations-sort.component.html',
- styleUrls: ['./organisations-sort.component.css'],
+ selector: 'gn-ui-organisations-filter',
+ templateUrl: './organisations-filter.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
-export class OrganisationsSortComponent {
+export class OrganisationsFilterComponent {
choices: { value: string; label: string }[] = [
{
value: 'asc,name',
@@ -33,8 +33,14 @@ export class OrganisationsSortComponent {
},
]
@Output() sortBy = new EventEmitter()
+ filterByValueChange = new Subject()
+ @Output() filterBy = this.filterByValueChange.pipe(debounceTime(300))
selectOrderToDisplay(selectValue: string) {
this.sortBy.emit(selectValue.split(',') as SortByField)
}
+
+ filterOrganisations(inputValue: string) {
+ this.filterByValueChange.next(inputValue)
+ }
}
diff --git a/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.html b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.html
new file mode 100644
index 0000000000..f9dc225276
--- /dev/null
+++ b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.html
@@ -0,0 +1,5 @@
+
+ organisations.hits.found
+
diff --git a/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.spec.ts b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.spec.ts
new file mode 100644
index 0000000000..4c9a6314a7
--- /dev/null
+++ b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing'
+
+import { OrganisationsResultComponent } from './organisations-result.component'
+
+describe('OrganisationsResultComponent', () => {
+ let component: OrganisationsResultComponent
+ let fixture: ComponentFixture
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [OrganisationsResultComponent],
+ })
+ fixture = TestBed.createComponent(OrganisationsResultComponent)
+ component = fixture.componentInstance
+ fixture.detectChanges()
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+})
diff --git a/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.ts b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.ts
new file mode 100644
index 0000000000..3ed741624b
--- /dev/null
+++ b/libs/ui/catalog/src/lib/organisations-result/organisations-result.component.ts
@@ -0,0 +1,11 @@
+import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
+
+@Component({
+ selector: 'gn-ui-organisations-result',
+ templateUrl: './organisations-result.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class OrganisationsResultComponent {
+ @Input() hits: number
+ @Input() total: number
+}
diff --git a/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.css b/libs/ui/catalog/src/lib/organisations-sort/organisations-sort.component.css
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/libs/ui/catalog/src/lib/ui-catalog.module.ts b/libs/ui/catalog/src/lib/ui-catalog.module.ts
index d1b97a9597..990100a7f3 100644
--- a/libs/ui/catalog/src/lib/ui-catalog.module.ts
+++ b/libs/ui/catalog/src/lib/ui-catalog.module.ts
@@ -5,16 +5,18 @@ import { OrganisationPreviewComponent } from './organisation-preview/organisatio
import { TranslateModule } from '@ngx-translate/core'
import { MatIconModule } from '@angular/material/icon'
import { UiElementsModule } from '@geonetwork-ui/ui/elements'
-import { OrganisationsSortComponent } from './organisations-sort/organisations-sort.component'
+import { OrganisationsFilterComponent } from './organisations-filter/organisations-filter.component'
import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
import { LanguageSwitcherComponent } from './language-switcher/language-switcher.component'
+import { OrganisationsResultComponent } from './organisations-result/organisations-result.component'
@NgModule({
declarations: [
CatalogTitleComponent,
OrganisationPreviewComponent,
- OrganisationsSortComponent,
+ OrganisationsFilterComponent,
LanguageSwitcherComponent,
+ OrganisationsResultComponent,
],
imports: [
CommonModule,
@@ -26,8 +28,9 @@ import { LanguageSwitcherComponent } from './language-switcher/language-switcher
exports: [
CatalogTitleComponent,
OrganisationPreviewComponent,
- OrganisationsSortComponent,
+ OrganisationsFilterComponent,
LanguageSwitcherComponent,
+ OrganisationsResultComponent,
],
})
export class UiCatalogModule {}
diff --git a/libs/ui/inputs/src/lib/search-input/search-input.component.html b/libs/ui/inputs/src/lib/search-input/search-input.component.html
new file mode 100644
index 0000000000..6a3b995e34
--- /dev/null
+++ b/libs/ui/inputs/src/lib/search-input/search-input.component.html
@@ -0,0 +1,25 @@
+
+
+
+ search
+
+
+
diff --git a/libs/ui/inputs/src/lib/search-input/search-input.component.spec.ts b/libs/ui/inputs/src/lib/search-input/search-input.component.spec.ts
new file mode 100644
index 0000000000..09b77fe969
--- /dev/null
+++ b/libs/ui/inputs/src/lib/search-input/search-input.component.spec.ts
@@ -0,0 +1,54 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing'
+
+import { SearchInputComponent } from './search-input.component'
+
+describe('SearchInputComponent', () => {
+ let component: SearchInputComponent
+ let fixture: ComponentFixture
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ declarations: [SearchInputComponent],
+ })
+ fixture = TestBed.createComponent(SearchInputComponent)
+ component = fixture.componentInstance
+ fixture.detectChanges()
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+
+ describe('text input', () => {
+ let inputEl
+ beforeEach(() => {
+ fixture.detectChanges()
+ inputEl = fixture.nativeElement.querySelector('input')
+ })
+ it('emits the value on a change event', () => {
+ let emitted
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = 'Aaabcd'
+ inputEl.dispatchEvent(new Event('change'))
+ expect(emitted).toBe('Aaabcd')
+ })
+ it('emits the value on an input event', () => {
+ let emitted
+ component.valueChange.subscribe((v) => (emitted = v))
+ inputEl.value = 'Aaabcd'
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emitted).toBe('Aaabcd')
+ })
+ it('emits only unique values', () => {
+ let emittedCount = 0
+ component.valueChange.subscribe(() => emittedCount++)
+ inputEl.value = 'Aaabcd'
+ inputEl.dispatchEvent(new Event('input'))
+ inputEl.value = 'Aaabcd'
+ inputEl.dispatchEvent(new Event('input'))
+ inputEl.value = 'bbb'
+ inputEl.dispatchEvent(new Event('input'))
+ expect(emittedCount).toBe(2)
+ })
+ })
+})
diff --git a/libs/ui/inputs/src/lib/search-input/search-input.component.ts b/libs/ui/inputs/src/lib/search-input/search-input.component.ts
new file mode 100644
index 0000000000..622f74d53d
--- /dev/null
+++ b/libs/ui/inputs/src/lib/search-input/search-input.component.ts
@@ -0,0 +1,29 @@
+import {
+ ChangeDetectionStrategy,
+ Component,
+ Input,
+ Output,
+} from '@angular/core'
+import { Subject, distinctUntilChanged } from 'rxjs'
+
+@Component({
+ selector: 'gn-ui-search-input',
+ templateUrl: './search-input.component.html',
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class SearchInputComponent {
+ @Input() value = ''
+ @Input() placeholder = ''
+ rawChange = new Subject()
+ @Output() valueChange = this.rawChange.pipe(distinctUntilChanged())
+
+ handleChange($event) {
+ const value = $event.target.value
+ this.rawChange.next(value)
+ }
+
+ clear() {
+ this.value = null
+ this.rawChange.next(null)
+ }
+}
diff --git a/libs/ui/inputs/src/lib/ui-inputs.module.ts b/libs/ui/inputs/src/lib/ui-inputs.module.ts
index a595dbf425..4e9fa30fe7 100644
--- a/libs/ui/inputs/src/lib/ui-inputs.module.ts
+++ b/libs/ui/inputs/src/lib/ui-inputs.module.ts
@@ -35,6 +35,7 @@ import { CopyTextButtonComponent } from './copy-text-button/copy-text-button.com
import { MatTooltipModule } from '@angular/material/tooltip'
import { CommonModule } from '@angular/common'
import { CheckboxComponent } from './checkbox/checkbox.component'
+import { SearchInputComponent } from './search-input/search-input.component'
@NgModule({
declarations: [
@@ -60,6 +61,7 @@ import { CheckboxComponent } from './checkbox/checkbox.component'
CheckToggleComponent,
CopyTextButtonComponent,
CheckboxComponent,
+ SearchInputComponent,
],
imports: [
CommonModule,
@@ -92,6 +94,7 @@ import { CheckboxComponent } from './checkbox/checkbox.component'
CheckToggleComponent,
CopyTextButtonComponent,
CheckboxComponent,
+ SearchInputComponent,
],
})
export class UiInputsModule {}
diff --git a/translations/de.json b/translations/de.json
index b1cb3219cc..6ecb5d6d4a 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "Suche",
"nav.back": "Zurück",
"next": "weiter",
- "organisation.sort.intro": "Datengeber sind hier aufgelistet.",
+ "organisation.filter.placeholder": "Ergebnisse filtern",
"organisation.sort.sortBy": "Sortieren nach:",
+ "organisations.hits.found": "{hits, plural, =0{Keine Organisation gefunden} other{{hits} von {total} Organisationen angezeigt}}",
"organisations.sortBy.nameAsc": "Name A → Z",
"organisations.sortBy.nameDesc": "Name Z → A",
"organisations.sortBy.recordCountAsc": "Veröffentlichungen 0 → 9",
diff --git a/translations/en.json b/translations/en.json
index d6aaeb0b89..cce6353f66 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "Search",
"nav.back": "Back",
"next": "next",
- "organisation.sort.intro": "Dataset providers are listed here.",
+ "organisation.filter.placeholder": "Filter results",
"organisation.sort.sortBy": "Sort by:",
+ "organisations.hits.found": "{hits, plural, =0{No organizations found} other{{hits} out of {total} organizations shown}}",
"organisations.sortBy.nameAsc": "Name A → Z",
"organisations.sortBy.nameDesc": "Name Z → A",
"organisations.sortBy.recordCountAsc": "Publications 0 → 9",
diff --git a/translations/es.json b/translations/es.json
index a9be25643d..9e4bd02a79 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
- "organisation.sort.intro": "",
+ "organisation.filter.placeholder": "",
"organisation.sort.sortBy": "",
+ "organisations.hits.found": "",
"organisations.sortBy.nameAsc": "",
"organisations.sortBy.nameDesc": "",
"organisations.sortBy.recordCountAsc": "",
diff --git a/translations/fr.json b/translations/fr.json
index 88bf7fa157..795fff860d 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "Rechercher",
"nav.back": "Retour",
"next": "suivant",
- "organisation.sort.intro": "Retrouvez sur cette page l'ensemble des fournisseurs de données de la plateforme.",
+ "organisation.filter.placeholder": "Filtrer les résultats",
"organisation.sort.sortBy": "Trier par :",
+ "organisations.hits.found": "{hits, plural, =0{Aucune organisation trouvé} one{1 organisation sur {total} affichée} other{{hits} organisations sur {total} affichées}}",
"organisations.sortBy.nameAsc": "Nom A → Z",
"organisations.sortBy.nameDesc": "Nom Z → A",
"organisations.sortBy.recordCountAsc": "Données 0 → 9",
diff --git a/translations/it.json b/translations/it.json
index 83caee58a4..b5c7f49092 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
- "organisation.sort.intro": "",
+ "organisation.filter.placeholder": "",
"organisation.sort.sortBy": "",
+ "organisations.hits.found": "",
"organisations.sortBy.nameAsc": "",
"organisations.sortBy.nameDesc": "",
"organisations.sortBy.recordCountAsc": "",
diff --git a/translations/nl.json b/translations/nl.json
index bf47237a21..2176b77624 100644
--- a/translations/nl.json
+++ b/translations/nl.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
- "organisation.sort.intro": "",
+ "organisation.filter.placeholder": "",
"organisation.sort.sortBy": "",
+ "organisations.hits.found": "",
"organisations.sortBy.nameAsc": "",
"organisations.sortBy.nameDesc": "",
"organisations.sortBy.recordCountAsc": "",
diff --git a/translations/pt.json b/translations/pt.json
index 6156d65526..4a2bdba25c 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "",
"nav.back": "",
"next": "",
- "organisation.sort.intro": "",
+ "organisation.filter.placeholder": "",
"organisation.sort.sortBy": "",
+ "organisations.hits.found": "",
"organisations.sortBy.nameAsc": "",
"organisations.sortBy.nameDesc": "",
"organisations.sortBy.recordCountAsc": "",
diff --git a/translations/sk.json b/translations/sk.json
index 1128d73bba..c43cce6973 100644
--- a/translations/sk.json
+++ b/translations/sk.json
@@ -178,8 +178,9 @@
"multiselect.filter.placeholder": "Hľadať",
"nav.back": "Späť",
"next": "Ďalej",
- "organisation.sort.intro": "Zoradenie poskytovateľov datasetov.",
+ "organisation.filter.placeholder": "",
"organisation.sort.sortBy": "Zoradiť podľa:",
+ "organisations.hits.found": "",
"organisations.sortBy.nameAsc": "Názov A → Z",
"organisations.sortBy.nameDesc": "Názov Z → A",
"organisations.sortBy.recordCountAsc": "Publikácie 0 → 9",