Skip to content

Commit

Permalink
feat(frontend): Sort south items
Browse files Browse the repository at this point in the history
  • Loading branch information
nagyszabi authored and burgerni10 committed Jan 6, 2025
1 parent 9fb59b2 commit 8c588fa
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@
@if (!inMemory) {
<th></th>
}
<th translate="south.items.name"></th>
<th class="w-25">
<button type="button" style="background: none; border: none; font-weight: bold" (click)="toggleColumnSort('name')">
<span translate="south.items.name" class="me-2"></span>
<span class="fa {{ ['fa-sort', 'fa-sort-asc', 'fa-sort-desc'][columnSortStates.name] }}"></span>
</button>
</th>
@if (!southManifest.items.scanMode.subscriptionOnly) {
<th translate="south.items.scan-mode" style="width: 8rem"></th>
}
Expand Down
30 changes: 30 additions & 0 deletions frontend/src/app/south/south-items/south-items.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,14 @@ class SouthItemsComponentTester extends ComponentTester<TestComponent> {
get spinner() {
return this.element('#import-button .spinner-border')!;
}

get sortByNameBtn() {
return this.button('button:has( > span[translate="south.items.name"])')!;
}

get tableItemNames() {
return this.elements<HTMLTableCellElement>('tbody tr.south-item td:nth-child(2)').map(e => e.nativeElement.innerText);
}
}

describe('SouthItemsComponent', () => {
Expand Down Expand Up @@ -173,4 +181,26 @@ describe('SouthItemsComponent', () => {
expect(southConnectorService.deleteAllItems).toHaveBeenCalledTimes(1);
expect(notificationService.success).toHaveBeenCalledWith('south.items.all-deleted');
});

it('should sort items by name', () => {
const expectedOrder = tester.tableItemNames;

// Ascending
tester.sortByNameBtn.click();
expect(tester.tableItemNames).toEqual(expectedOrder);

// Descending
tester.sortByNameBtn.click();
expectedOrder.reverse();
expect(tester.tableItemNames).toEqual(expectedOrder);

// Unset
tester.sortByNameBtn.click();
expect(tester.tableItemNames).toEqual(expectedOrder);

// Ascending (this call reverses the list to the original sorting, if omitted, tests fail)
tester.sortByNameBtn.click();
expectedOrder.reverse();
expect(tester.tableItemNames).toEqual(expectedOrder);
});
});
46 changes: 46 additions & 0 deletions frontend/src/app/south/south-items/south-items.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ import { ImportItemModalComponent } from '../../shared/import-item-modal/import-
import { SouthItemTestModalComponent } from '../south-item-test-modal/south-item-test-modal.component';

const PAGE_SIZE = 20;
const enum ColumnSortState {
INDETERMINATE = 0,
ASCENDING = 1,
DESCENDING = 2
}

export interface TableData {
name: string;
}

@Component({
selector: 'oib-south-items',
Expand Down Expand Up @@ -80,6 +89,11 @@ export class SouthItemsComponent implements OnInit {

searchControl = inject(NonNullableFormBuilder).control(null as string | null);

columnSortStates: { [key in keyof TableData]: ColumnSortState } = {
name: ColumnSortState.INDETERMINATE
};
currentColumnSort: keyof TableData | null = 'name';

ngOnInit() {
this.fetchItemsAndResetPage(false);
this.displaySettings = this.southManifest.items.settings.filter(setting => setting.displayInViewMode);
Expand All @@ -92,6 +106,10 @@ export class SouthItemsComponent implements OnInit {
}

fetchItemsAndResetPage(fromMemory: boolean) {
// reset column sorting
this.columnSortStates = { name: ColumnSortState.INDETERMINATE };
this.currentColumnSort = 'name';

if (this.southConnector && !fromMemory) {
this.southConnectorService.listItems(this.southConnector.id).subscribe(items => {
this.allItems = items;
Expand All @@ -107,6 +125,7 @@ export class SouthItemsComponent implements OnInit {
}

changePage(pageNumber: number) {
this.sortTable();
this.displayedItems = this.createPage(pageNumber);
}

Expand Down Expand Up @@ -386,4 +405,31 @@ export class SouthItemsComponent implements OnInit {
}
return value;
}

toggleColumnSort(columnName: keyof TableData) {
this.currentColumnSort = columnName;
// Toggle state
this.columnSortStates[this.currentColumnSort] = (this.columnSortStates[this.currentColumnSort] + 1) % 3;

// Reset state for every other column
Object.keys(this.columnSortStates).forEach(key => {
if (this.currentColumnSort !== key) {
this.columnSortStates[key as keyof typeof this.columnSortStates] = 0;
}
});

this.changePage(0);
}

private sortTable() {
if (this.currentColumnSort && this.columnSortStates[this.currentColumnSort] !== ColumnSortState.INDETERMINATE) {
const ascending = this.columnSortStates[this.currentColumnSort] === ColumnSortState.ASCENDING;

switch (this.currentColumnSort) {
case 'name':
this.filteredItems.sort((a, b) => (ascending ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name)));
break;
}
}
}
}

0 comments on commit 8c588fa

Please sign in to comment.