From cedd84733e918f10489996a7756f14655f8f354c Mon Sep 17 00:00:00 2001 From: Jane Sandberg Date: Fri, 26 Jun 2020 07:33:08 +0000 Subject: [PATCH] LP 1857351: admin-page grid column order respects specified fieldOrder Grid columns that aren't auto-generated and grids without a specified autoGeneratedColumnOrder are not affected. Signed-off-by: Jane Sandberg Signed-off-by: Ruth Frasur Signed-off-by: Michele Morgan --- Open-ILS/src/eg2/src/app/core/idl.service.ts | 30 ++++++++++++++ Open-ILS/src/eg2/src/app/core/idl.spec.ts | 48 ++++++++++++++++++++++ .../src/app/share/fm-editor/fm-editor.component.ts | 22 +--------- .../src/eg2/src/app/share/grid/grid.component.ts | 5 +++ Open-ILS/src/eg2/src/app/share/grid/grid.ts | 14 +++++-- .../share/admin-page/admin-page.component.html | 4 +- 6 files changed, 98 insertions(+), 25 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/core/idl.service.ts b/Open-ILS/src/eg2/src/app/core/idl.service.ts index 040bbba8da..4f00c53592 100644 --- a/Open-ILS/src/eg2/src/app/core/idl.service.ts +++ b/Open-ILS/src/eg2/src/app/core/idl.service.ts @@ -227,5 +227,35 @@ export class IdlService { const pkeyField = this.classes[idlClass].pkey || 'id'; return obj1[pkeyField]() === obj2[pkeyField](); } + + // Sort an array of fields from the IDL (like you might get from calling + // this.idlClasses[classname][fields]) + + sortIdlFields(fields: any[], desiredOrder: string[]): any[] { + let newList = []; + + desiredOrder.forEach(name => { + const match = fields.filter(field => field.name === name)[0]; + if (match) { newList.push(match); } + }); + + // Sort remaining fields by label + const remainder = fields.filter(f => !desiredOrder.includes(f.name)); + remainder.sort((a, b) => { + if (a.label && b.label) { + return (a.label < b.label) ? -1 : 1; + } else if (a.label) { + return -1; + } else if (b.label) { + return 1; + } + + // If no order specified and no labels to sort by, + // default to sorting by field name + return (a.label < b.label) ? -1 : 1; + }); + newList = newList.concat(remainder); + return newList; + } } diff --git a/Open-ILS/src/eg2/src/app/core/idl.spec.ts b/Open-ILS/src/eg2/src/app/core/idl.spec.ts index 49439fdb10..a97108d305 100644 --- a/Open-ILS/src/eg2/src/app/core/idl.spec.ts +++ b/Open-ILS/src/eg2/src/app/core/idl.spec.ts @@ -51,6 +51,54 @@ describe('IdlService', () => { expect(service.pkeyMatches(org, user)).toBe(false); }); + it('should sort an array of IDL fields according to an array of field names', () => { + const fieldNames = ['name', 'owner', 'active', 'id']; + const idlFields = [ + {'name': 'id', 'label': 'Object ID', 'dataType': 'id'}, + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + {'name': 'active', 'datatype': 'bool'}, + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'} + ]; + const expectedOrder = [ + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'}, + {'name': 'active', 'datatype': 'bool'}, + {'name': 'id', 'label': 'Object ID', 'dataType': 'id'}, + ]; + expect(service.sortIdlFields(idlFields, fieldNames)).toEqual(expectedOrder); + }); + + it('should sort IDL fields by label when it runs out of specified field names', () => { + const fieldNames = ['owner']; + const idlFields = [ + {'name': 'id', 'label': 'Object ID', 'dataType': 'id'}, + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'} + ]; + const expectedOrder = [ + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'}, + {'name': 'id', 'label': 'Object ID', 'dataType': 'id'}, + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + ]; + expect(service.sortIdlFields(idlFields, fieldNames)).toEqual(expectedOrder); + }); + + it('should sort IDL fields by name when it runs out of other ways to sort', () => { + const fieldNames = ['owner']; + const idlFields = [ + {'name': 'id', 'dataType': 'id'}, + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + {'name': 'active', 'datatype': 'bool'}, + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'} + ]; + const expectedOrder = [ + {'name': 'owner', 'type': 'link', 'key': 'id', 'class': 'aou', 'reltype': 'has_a', 'datatype': 'org_unit'}, + {'name': 'name', 'label': 'The name of this object', 'datatype': 'text'}, + {'name': 'active', 'datatype': 'bool'}, + {'name': 'id', 'dataType': 'id'}, + ]; + expect(service.sortIdlFields(idlFields, fieldNames)).toEqual(expectedOrder); + }); }); diff --git a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts index 4b6ee5ef4e..4ac2e2eac9 100644 --- a/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts +++ b/Open-ILS/src/eg2/src/app/share/fm-editor/fm-editor.component.ts @@ -447,26 +447,8 @@ export class FmRecordEditorComponent fields.map(field => this.constructOneField(field)) ).then(() => { - - if (!this.fieldOrder) { - this.fields = fields.sort((a, b) => a.label < b.label ? -1 : 1); - return; - } - - let newList = []; - const ordered = this.fieldOrder.split(/,/); - - ordered.forEach(name => { - const f1 = fields.filter(f2 => f2.name === name)[0]; - if (f1) { newList.push(f1); } - }); - - // Sort remaining fields by label - const remainder = fields.filter(f => !ordered.includes(f.name)); - remainder.sort((a, b) => a.label < b.label ? -1 : 1); - newList = newList.concat(remainder); - - this.fields = newList; + const order = this.fieldOrder ? this.fieldOrder.split(/,/) : []; + this.fields = this.idl.sortIdlFields(fields, order); }); } diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts b/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts index 23996ee26b..4c0885ae3c 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid.component.ts @@ -30,6 +30,10 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy { // IDL class for auto-generation of columns @Input() idlClass: string; + // Comma-separated list of column names, to set the order of columns + // from auto-generated columns only + @Input() autoGeneratedColumnOrder: string; + // True if any columns are sortable @Input() sortable: boolean; @@ -146,6 +150,7 @@ export class GridComponent implements OnInit, AfterViewInit, OnDestroy { this.context.idlClass = this.idlClass; this.context.dataSource = this.dataSource; this.context.persistKey = this.persistKey; + this.context.autoGeneratedColumnOrder = this.autoGeneratedColumnOrder; this.context.isSortable = this.sortable === true; this.context.isFilterable = this.filterable === true; this.context.stickyGridHeader = this.stickyHeader === true; diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid.ts b/Open-ILS/src/eg2/src/app/share/grid/grid.ts index f4e4396ee4..c45acb39f8 100644 --- a/Open-ILS/src/eg2/src/app/share/grid/grid.ts +++ b/Open-ILS/src/eg2/src/app/share/grid/grid.ts @@ -493,6 +493,7 @@ export class GridContext { disableSelect: boolean; dataSource: GridDataSource; columnSet: GridColumnSet; + autoGeneratedColumnOrder: string; rowSelector: GridRowSelector; toolbarButtons: GridToolbarButton[]; toolbarCheckboxes: GridToolbarCheckbox[]; @@ -1075,11 +1076,18 @@ export class GridContext { if (!this.columnSet.idlClass) { return; } const pkeyField = this.idl.classes[this.columnSet.idlClass].pkey; + const specifiedColumnOrder = this.autoGeneratedColumnOrder ? + this.autoGeneratedColumnOrder.split(/,/) : []; // generate columns for all non-virtual fields on the IDL class - this.idl.classes[this.columnSet.idlClass].fields - .filter(field => !field.virtual) - .forEach(field => { + const fields = this.idl.classes[this.columnSet.idlClass].fields + .filter(field => !field.virtual); + + const sortedFields = this.autoGeneratedColumnOrder ? + this.idl.sortIdlFields(fields, this.autoGeneratedColumnOrder.split(/,/)) : + fields; + + sortedFields.forEach(field => { if (!this.ignoredFields.filter(ignored => ignored === field.name).length) { const col = new GridColumn(); col.name = field.name; diff --git a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html index a7d71230de..f6e6397ed1 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/admin-page/admin-page.component.html @@ -53,8 +53,8 @@ - [stickyHeader]="true"> + [sortable]="true" persistKey="{{persistKey}}" autoGeneratedColumnOrder="{{fieldOrder}}" + [filterable]="true" [stickyHeader]="true"> -- 2.11.0