diff --git a/packages/components-dev/filter-bar/module.ts b/packages/components-dev/filter-bar/module.ts
index eaea0b3ba..a6f6b4577 100644
--- a/packages/components-dev/filter-bar/module.ts
+++ b/packages/components-dev/filter-bar/module.ts
@@ -31,6 +31,9 @@ import { DevLocaleSelector } from '../locale-selector';
imports: [FilterBarExamplesModule],
selector: 'dev-docs-examples',
template: `
+
+
+
@@ -613,6 +616,25 @@ export class DemoComponent implements AfterViewInit {
removable: false,
disabled: false
},
+ {
+ name: 'mySelect',
+ type: KbqPipeTypes.Select,
+ id: 'mySelect',
+ values: [
+ { name: 'Option 1', id: '1', type: 'error' },
+ { name: 'Option 2', id: '2', type: 'warning' },
+ { name: 'Option 3', id: '3', type: 'success' },
+ { name: 'Option 4', id: '4', type: 'error' },
+ { name: 'Option 5', id: '5', type: 'warning' }
+ ],
+ valueTemplate: this.optionTemplate,
+ search: true,
+
+ required: false,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
{
name: 'MultiSelect',
type: KbqPipeTypes.MultiSelect,
@@ -636,6 +658,25 @@ export class DemoComponent implements AfterViewInit {
removable: true,
disabled: false
},
+ {
+ name: 'myMultiSelect',
+ type: KbqPipeTypes.MultiSelect,
+ id: 'myMultiSelect',
+ values: [
+ { name: 'Option 1', id: '1', type: 'error' },
+ { name: 'Option 2', id: '2', type: 'warning' },
+ { name: 'Option 3', id: '3', type: 'success' },
+ { name: 'Option 4', id: '4', type: 'error' },
+ { name: 'Option 5', id: '5', type: 'warning' }
+ ],
+ valueTemplate: this.optionTemplate,
+ search: true,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
{
name: 'Text',
type: KbqPipeTypes.Text,
@@ -645,6 +686,16 @@ export class DemoComponent implements AfterViewInit {
removable: false,
disabled: false
},
+ {
+ name: 'myText',
+ type: KbqPipeTypes.Text,
+ id: 'myText',
+
+ required: false,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
{
name: 'Date',
type: KbqPipeTypes.Date,
@@ -661,6 +712,23 @@ export class DemoComponent implements AfterViewInit {
removable: false,
disabled: false
},
+ {
+ name: 'myDate',
+ type: KbqPipeTypes.Date,
+ id: 'myDate',
+ values: [
+ { name: 'Последний день', end: null, start: { days: -1 } },
+ { name: 'Последние 3 дня', end: null, start: { days: -3 } },
+ { name: 'Последние 7 дней', end: null, start: { days: -7 } },
+ { name: 'Последние 30 дней', end: null, start: { days: -30 } },
+ { name: 'Последние 90 дней', end: null, start: { days: -90 } },
+ { name: 'Последний год', end: null, start: { years: -1 } }
+ ],
+ required: false,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
{
name: 'Datetime',
type: KbqPipeTypes.Datetime,
@@ -676,6 +744,23 @@ export class DemoComponent implements AfterViewInit {
cleanable: true,
removable: false,
disabled: false
+ },
+ {
+ name: 'myDatetime',
+ type: KbqPipeTypes.Datetime,
+ id: 'myDatetime',
+ values: [
+ { name: 'Последний день', end: null, start: { days: -1 } },
+ { name: 'Последние 3 дня', end: null, start: { days: -3 } },
+ { name: 'Последние 7 дней', end: null, start: { days: -7 } },
+ { name: 'Последние 30 дней', end: null, start: { days: -30 } },
+ { name: 'Последние 90 дней', end: null, start: { days: -90 } },
+ { name: 'Последний год', end: null, start: { years: -1 } }
+ ],
+ required: false,
+ cleanable: true,
+ removable: false,
+ disabled: false
}
];
}
diff --git a/packages/components/filter-bar/examples.filter-bar.en.md b/packages/components/filter-bar/examples.filter-bar.en.md
index 8ee4766f6..317222a19 100644
--- a/packages/components/filter-bar/examples.filter-bar.en.md
+++ b/packages/components/filter-bar/examples.filter-bar.en.md
@@ -1 +1,7 @@
+#### Example of adding a custom pipe
+
+
+#### Example of multiple pipes with the same type
+
+
diff --git a/packages/components/filter-bar/examples.filter-bar.ru.md b/packages/components/filter-bar/examples.filter-bar.ru.md
index d30519895..4df7b39ce 100644
--- a/packages/components/filter-bar/examples.filter-bar.ru.md
+++ b/packages/components/filter-bar/examples.filter-bar.ru.md
@@ -1,3 +1,7 @@
#### Пример добавления пользовательского пайпа
+
+#### Пример множества пайпов с одинаковым типом
+
+
diff --git a/packages/components/filter-bar/pipe-add.ts b/packages/components/filter-bar/pipe-add.ts
index d445965ea..dded35ee5 100644
--- a/packages/components/filter-bar/pipe-add.ts
+++ b/packages/components/filter-bar/pipe-add.ts
@@ -18,6 +18,7 @@ import { KbqSelect, KbqSelectModule } from '@koobiq/components/select';
import { KbqToolTipModule } from '@koobiq/components/tooltip';
import { KbqFilterBar } from './filter-bar';
import { KbqFilter, KbqPipe, KbqPipeTemplate } from './filter-bar.types';
+import { getId } from './pipes/base-pipe';
@Component({
standalone: true,
@@ -92,14 +93,14 @@ export class KbqPipeAdd {
constructor() {
this.filterBar.changes.pipe(takeUntilDestroyed()).subscribe(() => {
if (this.filterBar?.filter) {
- this.addedPipes = this.filterBar.filter.pipes.map((pipe: KbqPipe) => pipe.id || pipe.name);
+ this.addedPipes = this.filterBar.filter.pipes.map((pipe: KbqPipe) => getId(pipe));
}
});
}
addPipeFromTemplate(option: KbqOption) {
if (option.selected) {
- this.filterBar.openPipe.next(option.value.id || option.value.name);
+ this.filterBar.openPipe.next(getId(option.value));
} else {
option.select();
@@ -125,6 +126,6 @@ export class KbqPipeAdd {
* should be returned.
*/
compareWith(o1: KbqPipe, o2: string): boolean {
- return (o1.id || o1.name) === o2;
+ return getId(o1) === o2;
}
}
diff --git a/packages/components/filter-bar/pipes/base-pipe.ts b/packages/components/filter-bar/pipes/base-pipe.ts
index 6009b74bc..92d33d08d 100644
--- a/packages/components/filter-bar/pipes/base-pipe.ts
+++ b/packages/components/filter-bar/pipes/base-pipe.ts
@@ -13,11 +13,16 @@ import { isMac } from '@koobiq/components/core';
import { Subject } from 'rxjs';
import { delay, filter } from 'rxjs/operators';
import { KbqFilterBar } from '../filter-bar';
-import { KbqPipeData, KbqPipeTemplate } from '../filter-bar.types';
+import { KbqPipeData, KbqPipeTemplate, KbqPipeType } from '../filter-bar.types';
/** Injection Token for providing configuration of filter-bar */
export const KBQ_PIPE_DATA = new InjectionToken('KBQ_PIPE_DATA');
+/** function to get unique identifier of an element */
+export function getId(item: KbqPipeTemplate): KbqPipeType | string | number {
+ return item?.id ?? item?.name;
+}
+
@Directive({
standalone: true,
host: {
@@ -86,8 +91,8 @@ export abstract class KbqBasePipe implements AfterViewInit {
this.open();
}
- this.filterBar?.openPipe.pipe(filter(Boolean)).subscribe((name) => {
- if (this.data.name === name) {
+ this.filterBar?.openPipe.pipe(filter(Boolean)).subscribe((id) => {
+ if (getId(this.data) === id) {
this.open();
}
});
@@ -100,7 +105,7 @@ export abstract class KbqBasePipe implements AfterViewInit {
/** updates values for selection and value template */
updateTemplates = (templates: KbqPipeTemplate[] | null) => {
- const template = templates?.find((template) => template.type === this.data?.type);
+ const template = templates?.find((template) => getId(template) === getId(this.data));
if (template?.values) {
this.values = template.values;
diff --git a/packages/docs-examples/components/filter-bar/filter-bar-removable/filter-bar-removable-example.ts b/packages/docs-examples/components/filter-bar/filter-bar-removable/filter-bar-removable-example.ts
index b556422e6..be937a84a 100644
--- a/packages/docs-examples/components/filter-bar/filter-bar-removable/filter-bar-removable-example.ts
+++ b/packages/docs-examples/components/filter-bar/filter-bar-removable/filter-bar-removable-example.ts
@@ -41,7 +41,7 @@ export class FilterBarRemovableExample {
disabled: false
},
{
- name: 'SelectMultiple',
+ name: 'MultiSelect',
type: KbqPipeTypes.MultiSelect,
value: [],
diff --git a/packages/docs-examples/components/filter-bar/filter-bar-uniq-pipes/filter-bar-uniq-pipes-example.ts b/packages/docs-examples/components/filter-bar/filter-bar-uniq-pipes/filter-bar-uniq-pipes-example.ts
new file mode 100644
index 000000000..c5df17c1c
--- /dev/null
+++ b/packages/docs-examples/components/filter-bar/filter-bar-uniq-pipes/filter-bar-uniq-pipes-example.ts
@@ -0,0 +1,420 @@
+import { Component } from '@angular/core';
+import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter';
+import { KbqFilter, KbqFilterBarModule, KbqPipeTemplate, KbqPipeTypes } from '@koobiq/components/filter-bar';
+
+/**
+ * @title filter bar
+ */
+@Component({
+ standalone: true,
+ selector: 'filter-bar-uniq-pipes-example',
+ imports: [
+ KbqFilterBarModule,
+ LuxonDateModule
+ ],
+ template: `
+
+
+
+ @for (pipe of activeFilter?.pipes; track pipe) {
+
+ }
+
+
+
+ @if (activeFilter?.name !== defaultFilter?.name || activeFilter?.changed) {
+
+ }
+
+
+
+ `
+})
+export class FilterBarUniqPipesExample {
+ filters: KbqFilter[] = [
+ {
+ name: 'Saved Filter 1',
+ readonly: false,
+ disabled: false,
+ changed: false,
+ saved: true,
+ pipes: [
+ {
+ name: 'Datetime',
+ value: {
+ name: 'Последние 7 дней',
+ end: null,
+ start: { days: -7 }
+ },
+ type: KbqPipeTypes.Datetime,
+
+ required: true,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
+ {
+ name: 'Select',
+ value: { name: 'Option 6', id: '6' },
+ type: KbqPipeTypes.Select,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Text',
+ value: 'Angular Rules',
+ type: KbqPipeTypes.Text,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ }
+ ]
+ },
+ {
+ name: 'Saved Filter 2',
+ readonly: false,
+ disabled: false,
+ changed: false,
+ saved: true,
+ pipes: [
+ {
+ name: 'Datetime',
+ value: {
+ name: 'Последний год',
+ end: null,
+ start: { years: -1 }
+ },
+ type: KbqPipeTypes.Datetime,
+
+ required: true,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
+ {
+ name: 'MultiSelect',
+ value: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 3', id: '3' },
+ { name: 'Option 4', id: '4' }
+ ],
+ type: KbqPipeTypes.MultiSelect,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Date',
+ value: {
+ name: 'Последние 7 дней',
+ end: null,
+ start: { days: -7 }
+ },
+ type: KbqPipeTypes.Date,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ }
+ ]
+ },
+ {
+ name: 'Saved Filter 3',
+ readonly: false,
+ disabled: false,
+ changed: false,
+ saved: true,
+ pipes: [
+ {
+ name: 'Datetime',
+ value: {
+ name: 'Последние 3 дня',
+ end: null,
+ start: { days: -3 }
+ },
+ type: KbqPipeTypes.Datetime,
+
+ required: true,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ },
+ {
+ name: 'Select',
+ value: { name: 'Option 5', id: '5' },
+ type: KbqPipeTypes.Select,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'MultiSelect',
+ value: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 2', id: '2' }
+ ],
+ type: KbqPipeTypes.MultiSelect,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ }
+ ]
+ }
+ ];
+ savedFilters: KbqFilter[] = structuredClone(this.filters);
+
+ defaultFilter: KbqFilter | null = this.getDefaultFilter();
+ activeFilter: KbqFilter | null = this.getDefaultFilter();
+
+ pipeTemplates: KbqPipeTemplate[] = [
+ {
+ name: 'Date',
+ type: KbqPipeTypes.Date,
+ values: [
+ { name: 'Последний день', start: { days: -1 }, end: null },
+ { name: 'Последние 3 дня', start: { days: -3 }, end: null },
+ { name: 'Последние 7 дней', start: { days: -7 }, end: null },
+ { name: 'Последние 30 дней', start: { days: -30 }, end: null },
+ { name: 'Последние 90 дней', start: { days: -90 }, end: null },
+ { name: 'Последний год', start: { years: -1 }, end: null }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'myDate',
+ type: KbqPipeTypes.Date,
+ values: [
+ { name: 'Последний день', start: { days: -1 }, end: null },
+ { name: 'Последние 3 дня', start: { days: -3 }, end: null },
+ { name: 'Последние 7 дней', start: { days: -7 }, end: null }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Datetime',
+ type: KbqPipeTypes.Datetime,
+ values: [
+ { name: 'Последний час', start: { hours: -1 }, end: null },
+ { name: 'Последние 3 часа', start: { hours: -3 }, end: null },
+ { name: 'Последние 24 часа', start: { hours: -24 }, end: null },
+ { name: 'Последние 3 дня', start: { days: -3 }, end: null },
+ { name: 'Последние 7 дней', start: { days: -7 }, end: null },
+ { name: 'Последние 30 дней', start: { days: -30 }, end: null },
+ { name: 'Последние 90 дней', start: { days: -90 }, end: null },
+ { name: 'Последний год', start: { years: -1 }, end: null }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Datetime_1',
+ id: 'myDatetime',
+ type: KbqPipeTypes.Datetime,
+ values: [
+ { name: 'Последний час', start: { hours: -1 }, end: null },
+ { name: 'Последние 3 часа', start: { hours: -3 }, end: null },
+ { name: 'Последние 24 часа', start: { hours: -24 }, end: null }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'MultiSelect',
+ type: KbqPipeTypes.MultiSelect,
+ values: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 2', id: '2' },
+ { name: 'Option 3', id: '3' },
+ { name: 'Option 4', id: '4' },
+ { name: 'Option 5', id: '5' },
+ { name: 'Option 6', id: '6' },
+ { name: 'Option 7', id: '7' }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'MultiSelect_1',
+ id: 'myMultiSelect',
+ type: KbqPipeTypes.MultiSelect,
+ values: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 2', id: '2' },
+ { name: 'Option 3', id: '3' },
+ { name: 'Option 4', id: '4' }
+ ],
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Select',
+ type: KbqPipeTypes.Select,
+ values: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 2', id: '2' },
+ { name: 'Option 3', id: '3' },
+ { name: 'Option 4', id: '4' },
+ { name: 'Option 5', id: '5' },
+ { name: 'Option 6', id: '6' },
+ { name: 'Option 7', id: '7' }
+ ],
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Select_1',
+ id: 'mySelect',
+ type: KbqPipeTypes.Select,
+ values: [
+ { name: 'Option 1', id: '1' },
+ { name: 'Option 2', id: '2' },
+ { name: 'Option 3', id: '3' },
+ { name: 'Option 4', id: '4' },
+ { name: 'Option 5', id: '5' },
+ { name: 'Option 6', id: '6' },
+ { name: 'Option 7', id: '7' }
+ ],
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Text',
+ type: KbqPipeTypes.Text,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ },
+ {
+ name: 'Text_1',
+ id: 'myText',
+ type: KbqPipeTypes.Text,
+
+ required: false,
+ cleanable: false,
+ removable: true,
+ disabled: false
+ }
+ ];
+
+ onFilterChange(filter: KbqFilter | null) {
+ console.log('onFilterChange: ', filter);
+ }
+
+ onResetFilter() {
+ console.log('onResetFilter: ');
+ this.activeFilter = this.getDefaultFilter();
+ }
+
+ onResetFilterChanges(filter: KbqFilter | null) {
+ console.log('onResetFilterChanges: ');
+ const defaultFilter = this.getSavedFilter(filter);
+
+ this.filters.splice(
+ this.filters.findIndex(({ name }) => name === filter?.name),
+ 1,
+ defaultFilter
+ );
+
+ this.activeFilter = defaultFilter;
+ }
+
+ onDeleteFilter(filter: KbqFilter) {
+ const currentFilterIndex = this.filters.findIndex(({ name }) => name === filter?.name);
+
+ this.filters.splice(currentFilterIndex, 1);
+
+ this.activeFilter = null;
+ }
+
+ onSaveFilter({ filter, filterBar }) {
+ console.log('filter to save: ', filter);
+
+ this.filters.splice(
+ this.filters.findIndex(({ name }) => name === filter?.name),
+ 1,
+ filter
+ );
+
+ filterBar.filters.filterSavedSuccessfully();
+ }
+
+ onSaveAsNewFilter({ filter, filterBar }) {
+ if (filter) {
+ this.filters.push(filter);
+ }
+
+ this.activeFilter = filter;
+
+ filterBar.filters.filterSavedSuccessfully();
+ }
+
+ getSavedFilter(filter: KbqFilter | null): KbqFilter {
+ return structuredClone(this.savedFilters.find(({ name }) => name === filter?.name)!);
+ }
+
+ getDefaultFilter(): KbqFilter {
+ return {
+ name: '',
+ readonly: false,
+ disabled: false,
+ changed: false,
+ saved: false,
+ pipes: [
+ {
+ name: 'Datetime',
+ value: { name: 'Последние 24 часа', end: null, start: { hours: -24 } },
+ type: KbqPipeTypes.Datetime,
+
+ required: true,
+ cleanable: false,
+ removable: false,
+ disabled: false
+ }
+ ]
+ };
+ }
+}
diff --git a/packages/docs-examples/components/filter-bar/index.ts b/packages/docs-examples/components/filter-bar/index.ts
index ac1b89ff2..882e8eb61 100644
--- a/packages/docs-examples/components/filter-bar/index.ts
+++ b/packages/docs-examples/components/filter-bar/index.ts
@@ -8,6 +8,7 @@ import { FilterBarRemovableExample } from './filter-bar-removable/filter-bar-rem
import { FilterBarRequiredExample } from './filter-bar-required/filter-bar-required-example';
import { FilterBarSavedFiltersExample } from './filter-bar-saved-filters/filter-bar-saved-filters-example';
import { FilterBarSearchExample } from './filter-bar-search/filter-bar-search-example';
+import { FilterBarUniqPipesExample } from './filter-bar-uniq-pipes/filter-bar-uniq-pipes-example';
export {
FilterBarCleanableExample,
@@ -18,7 +19,8 @@ export {
FilterBarRemovableExample,
FilterBarRequiredExample,
FilterBarSavedFiltersExample,
- FilterBarSearchExample
+ FilterBarSearchExample,
+ FilterBarUniqPipesExample
};
const EXAMPLES = [
@@ -30,7 +32,8 @@ const EXAMPLES = [
FilterBarSearchExample,
FilterBarCompleteFunctionsExample,
FilterBarSavedFiltersExample,
- FilterBarCustomPipeExample
+ FilterBarCustomPipeExample,
+ FilterBarUniqPipesExample
];
@NgModule({
diff --git a/packages/docs-examples/example-module.ts b/packages/docs-examples/example-module.ts
index 0ae9770da..cd69da818 100644
--- a/packages/docs-examples/example-module.ts
+++ b/packages/docs-examples/example-module.ts
@@ -1502,6 +1502,18 @@ export const EXAMPLE_COMPONENTS: {[id: string]: LiveExample} = {
"primaryFile": "filter-bar-search-example.ts",
"importPath": "components/filter-bar"
},
+ "filter-bar-uniq-pipes": {
+ "packagePath": "components/filter-bar/filter-bar-uniq-pipes",
+ "title": "filter bar",
+ "componentName": "FilterBarUniqPipesExample",
+ "files": [
+ "filter-bar-uniq-pipes-example.ts"
+ ],
+ "selector": "filter-bar-uniq-pipes-example",
+ "additionalComponents": [],
+ "primaryFile": "filter-bar-uniq-pipes-example.ts",
+ "importPath": "components/filter-bar"
+ },
"form-field-password-overview": {
"packagePath": "components/form-field/form-field-password-overview",
"title": "Form field password overview",
@@ -4290,6 +4302,8 @@ return import('@koobiq/docs-examples/components/filter-bar');
case 'filter-bar-saved-filters':
return import('@koobiq/docs-examples/components/filter-bar');
case 'filter-bar-search':
+return import('@koobiq/docs-examples/components/filter-bar');
+ case 'filter-bar-uniq-pipes':
return import('@koobiq/docs-examples/components/filter-bar');
case 'form-field-password-overview':
return import('@koobiq/docs-examples/components/form-field');
diff --git a/tools/public_api_guard/components/filter-bar.api.md b/tools/public_api_guard/components/filter-bar.api.md
index 15c905571..9a886327a 100644
--- a/tools/public_api_guard/components/filter-bar.api.md
+++ b/tools/public_api_guard/components/filter-bar.api.md
@@ -37,6 +37,9 @@ import { UntypedFormControl } from '@angular/forms';
// @public
export const defaultFilterBarPipes: [string, unknown][];
+// @public
+export function getId(item: KbqPipeTemplate): KbqPipeType | string | number;
+
// @public
export const KBQ_FILTER_BAR_CONFIGURATION: InjectionToken;