Skip to content

Commit

Permalink
fix(TabbedGroupPicker): Emit selected values on cancel (#1613)
Browse files Browse the repository at this point in the history
* fix(TabbedGroupPicker): Emit selected values on cancel

* style(TabbedGroupPicker): remove unused import

* Emit cancel event

* Emit current tabs on cancel instead of only selected data

* Add unit test for cancel
  • Loading branch information
monroepe authored Oct 7, 2024
1 parent 5597781 commit 0d7f558
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(component.loading).toEqual(false);
});
});

describe('function: filter', () => {
const getLetter = (n: number) => String.fromCharCode((n % 26) + 65);

Expand Down Expand Up @@ -110,6 +111,7 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(timeItTakesToSearchAMillionItems).toBeLessThan(amountOfTimeInMillisecondsThatIndicatesAGrosslyInefficientAlgorithm);
});
});

describe('function: createChildrenReferences', () => {
it('should make it so that children of data list items are references to other data list items', () => {
const dinosaurs = [
Expand Down Expand Up @@ -233,6 +235,7 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(parent.indeterminate).toEqual(true);
});
});

describe('function: getSelectedValue', () => {
it('should return indeterminate if one value is selected', () => {
const childArray = [
Expand All @@ -259,6 +262,7 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(result).toEqual(undefined);
});
});

describe('function: updateParentsAndQuickSelect', () => {
it('should select each item in the quick select group', () => {
const data = [
Expand Down Expand Up @@ -288,6 +292,7 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(quickSelectItem.selected).toEqual(true);
});
});

describe('function: onItemToggled', () => {
it('should use an algorithm more efficient than O(MxN^2)', () => {
// this dataset takes about 3 orders of magnitude longer for MxN^2 vs MxN
Expand Down Expand Up @@ -483,5 +488,23 @@ describe('Elements: NovoTabbedGroupPickerElement', () => {
expect(selection).toBeUndefined();
expect(activation).toEqual({ ...chicken, scope: 'quickselect' });
});
})
});

describe('function: cancel', () => {
it('should revert to original state and emit cancel event with current tabs', () => {
spyOn(component, 'revertState');
spyOn(component.cancelChange, 'emit');
component.dropdown = {
closePanel: () => {},
} as any;
const chickenTab = getChickenTab();
component.tabs = [
chickenTab,
];

component.cancel();
expect(component.revertState).toHaveBeenCalled();
expect(component.cancelChange.emit).toHaveBeenCalledWith([chickenTab]);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
OnInit,
Output,
ViewChild,
viewChild,
} from '@angular/core';
import { BehaviorSubject, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
Expand Down Expand Up @@ -95,6 +94,7 @@ export class NovoTabbedGroupPickerElement implements OnDestroy, OnInit {
@Output() activation = new EventEmitter<any>();
@Output() selectionChange = new EventEmitter<TabbedGroupPickerTab[]>();
@Output() applyChange: EventEmitter<any> = new EventEmitter<any>();
@Output() cancelChange: EventEmitter<any> = new EventEmitter<any>();

displayTabs: TabbedGroupPickerTab[];
displayTabIndex: number = 0;
Expand Down Expand Up @@ -374,6 +374,7 @@ export class NovoTabbedGroupPickerElement implements OnDestroy, OnInit {

cancel() {
this.revertState();
this.cancelChange.emit(this.tabs);
this.ref.markForCheck();
this.dropdown.closePanel();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './tabbed-group-picker-no-selection-example';
export * from './tabbed-group-picker-basic';
export * from './tabbed-group-picker-big-groups-example';
export * from './tabbed-group-picker-footer-example';
export * from './tabbed-group-picker-groups-example';
export * from './tabbed-group-picker-quick-select-example';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './tabbed-group-picker-footer-example';
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<div class="tabbed-group-picker-example">
<novo-tabbed-group-picker
[tabs]="example_tab"
[quickSelectConfig]="example_quickSelectConfig"
[buttonConfig]="example_buttonConfig"
(selectionChange)="onSelectionChange($event)"
(cancelChange)="onCancelChange($event)"
[showFooter]="true"
></novo-tabbed-group-picker>
<div class="selected-data-wrapper">
<h6>Selected Animal IDs:</h6>
<div>{{ selectedAnimals.join(', ') }}</div>
<h6>Selected Animal Category IDs:</h6>
<div>{{ selectedAnimalCategories.join(', ') }}</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { Component } from '@angular/core';
import { ChildTab, ParentTab, TabbedGroupPickerTab } from 'novo-elements';

/**
* @title Tabbed Group Picker - Footer Example
*/
@Component({
selector: 'tabbed-group-picker-footer-example',
templateUrl: 'tabbed-group-picker-footer-example.html',
styleUrls: ['../tabbed-group-picker-example.scss'],
})
export class TabbedGroupPickerFooterExample {
getAnimals = (): { animalId: number; name: string }[] =>
['Dog', 'Cat', 'Mouse', 'Horse', 'Cow', 'Chicken', 'Pig', 'Sheep', 'Goat', 'Goose'].map((name, index) => ({
name,
animalId: index + 1,
}));

getAnimalCategories = (): { groupId: number; name: string; children?: { animalId: number; name: string }[] }[] => {
const animals = this.getAnimals();
const birds = ['Chicken', 'Goose'].map((name) => animals.find((animal) => animal.name === name));
const livestock = ['Cow', 'Pig', 'Sheep', 'Goat'].map((name) => animals.find((animal) => animal.name === name));
return [
{
name: 'Birds',
groupId: 1,
children: birds,
},
{
name: 'Livestock',
groupId: 2,
children: livestock,
},
];
};
example_tab = [
{
typeName: 'animals',
typeLabel: 'Animals',
valueField: 'animalId',
labelField: 'name',
data: this.getAnimals(),
},
{
typeName: 'animalCategories',
typeLabel: 'Animal Categories',
valueField: 'groupId',
labelField: 'name',
childTypeName: 'animals',
data: this.getAnimalCategories(),
},
];
public example_quickSelectConfig = {
label: 'Quick Select',
items: [
{
childTypeName: 'animals',
children: [2],
label: 'Pure Evil',
},
{
childTypeName: 'animals',
children: [1, 6, 9],
label: 'My Pets',
},
{
childTypeName: 'animals',
all: true,
label: 'All Animals',
},
],
};

public buttonLabel: string = 'Nothing Selected';
public example_buttonConfig = {
theme: 'select',
side: 'right',
icon: 'collapse',
label: this.buttonLabel,
selector: 'buttonConfig',
};

selectedAnimals: string[] = [];
selectedAnimalCategories: string[] = [];

onSelectionChange(selectedData: TabbedGroupPickerTab[]) {
this.selectedAnimals = (selectedData.find(({ typeName }) => typeName === 'animals') as ChildTab).data.map(({ animalId }) => animalId);
this.selectedAnimalCategories = (selectedData.find(({ typeName }) => typeName === 'animalCategories') as ParentTab).data.map(
({ groupId }) => groupId,
);
this.example_buttonConfig.label = this.buildButtonLabel();
}

onCancelChange([animalsTab, animalCategoriesTab]: TabbedGroupPickerTab[]) {
this.selectedAnimals = animalsTab.data.filter((animal) => animal.selected).map(({ animalId }) => animalId);
this.selectedAnimalCategories = animalCategoriesTab.data.filter((group) => group.selected).map(({ groupId }) => groupId);
this.example_buttonConfig.label = this.buildButtonLabel();
}

buildButtonLabel(): string {
return this.selectedAnimals.length ? `Animals (${this.selectedAnimals.length})` : 'Nothing Selected';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,8 @@ Tabbed Group Picker provides a configurable quick select interface. For each qui

When checkboxes are disabled in the activation picker, we can still listen for "activation" events when an item has been clicked.

<code-example example="tabbed-group-picker-no-selection"></code-example>
<code-example example="tabbed-group-picker-no-selection"></code-example>

## Footer

<code-example example="tabbed-group-picker-footer"></code-example>
2 changes: 2 additions & 0 deletions projects/novo-examples/src/examples.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2831,6 +2831,8 @@ export class SwitchPage {
<h2>Selection Disabled</h2>
<p>When checkboxes are disabled in the activation picker, we can still listen for &quot;activation&quot; events when an item has been clicked.</p>
<p><code-example example="tabbed-group-picker-no-selection"></code-example></p>
<h2>Footer</h2>
<p><code-example example="tabbed-group-picker-footer"></code-example></p>
`,
host: { class: 'markdown-page' }
})
Expand Down

0 comments on commit 0d7f558

Please sign in to comment.