]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/grid/grid.component.ts
LP1858138 Grid IDL field definition repairs and more
[working/Evergreen.git] / Open-ILS / src / eg2 / src / app / share / grid / grid.component.ts
1 import {Component, Input, Output, OnInit, AfterViewInit, EventEmitter,
2     OnDestroy, ViewChild, ViewEncapsulation} from '@angular/core';
3 import {IdlService} from '@eg/core/idl.service';
4 import {OrgService} from '@eg/core/org.service';
5 import {ServerStoreService} from '@eg/core/server-store.service';
6 import {FormatService} from '@eg/core/format.service';
7 import {GridContext, GridColumn, GridDataSource, GridRowFlairEntry} from './grid';
8 import {GridToolbarComponent} from './grid-toolbar.component';
9
10 /**
11  * Main grid entry point.
12  */
13
14 @Component({
15   selector: 'eg-grid',
16   templateUrl: './grid.component.html',
17   styleUrls: ['grid.component.css'],
18   // share grid css globally once imported so all grid component CSS
19   // can live in grid.component.css and to avoid multiple copies of
20   // the CSS when multiple grids are displayed.
21   encapsulation: ViewEncapsulation.None
22 })
23
24 export class GridComponent implements OnInit, AfterViewInit, OnDestroy {
25
26     // Source of row data.
27     @Input() dataSource: GridDataSource;
28
29     // IDL class for auto-generation of columns
30     @Input() idlClass: string;
31
32     // True if any columns are sortable
33     @Input() sortable: boolean;
34
35     // True if the grid supports sorting of multiple columns at once
36     @Input() multiSortable: boolean;
37
38     // If true, grid sort requests only operate on data that
39     // already exists in the grid data source -- no row fetching.
40     // The assumption is all data is already available.
41     @Input() useLocalSort: boolean;
42
43     // Storage persist key / per-grid-type unique identifier
44     // The value is prefixed with 'eg.grid.'
45     //
46     // If persistKey is set to "disabled", or does not exist,
47     // the grid will not display a Save button to the user
48     @Input() persistKey: string;
49
50     @Input() disableSelect: boolean;
51
52     // Prevent selection of multiple rows
53     @Input() disableMultiSelect: boolean;
54
55     // Show an extra column in the grid where the caller can apply
56     // row-specific flair (material icons).
57     @Input() rowFlairIsEnabled: boolean;
58
59     // Returns a material icon name to display in the flar column
60     // (if enabled) for the given row.
61     @Input() rowFlairCallback: (row: any) => GridRowFlairEntry;
62
63     // Returns a space-separated list of CSS class names to apply to
64     // a given row
65     @Input() rowClassCallback: (row: any) => string;
66
67     // Returns a space-separated list of CSS class names to apply to
68     // a given cell or all cells in a column.
69     @Input() cellClassCallback: (row: any, col: GridColumn) => string;
70
71     // comma-separated list of fields to show by default.
72     // This field takes precedence over hideFields.
73     // When a value is applied, any field not in this list will
74     // be hidden.
75     @Input() showFields: string;
76
77     // comma-separated list of fields to hide.
78     // This does not imply all other fields should be visible, only that
79     // the selected fields will be hidden.
80     @Input() hideFields: string;
81
82     // When true, only display columns that are declared in the markup
83     // and leave all auto-generated fields hidden.
84     @Input() showDeclaredFieldsOnly: boolean;
85
86     // Allow the caller to jump directly to a specific page of
87     // grid data.
88     @Input() pageOffset: number;
89     // Pass in a default page size.  May be overridden by settings.
90     @Input() pageSize: number;
91
92     @Input() showLinkSelectors: boolean;
93
94     @Input() disablePaging: boolean;
95
96     // result filtering
97     //
98     // filterable: true if the result filtering controls
99     // should be displayed
100     @Input() filterable: boolean;
101
102     // sticky grid header
103     //
104     // stickyHeader: true of the grid header should be
105     // "sticky", i.e., remain visible if if the table is long
106     // and the user has scrolled far enough that the header
107     // would go out of view
108     @Input() stickyHeader: boolean;
109
110     context: GridContext;
111
112     // These events are emitted from our grid-body component.
113     // They are defined here for ease of access to the caller.
114     @Output() onRowActivate: EventEmitter<any>;
115     @Output() onRowClick: EventEmitter<any>;
116
117     @ViewChild('toolbar', { static: true }) toolbar: GridToolbarComponent;
118
119     constructor(
120         private idl: IdlService,
121         private org: OrgService,
122         private store: ServerStoreService,
123         private format: FormatService
124     ) {
125         this.context =
126             new GridContext(this.idl, this.org, this.store, this.format);
127         this.onRowActivate = new EventEmitter<any>();
128         this.onRowClick = new EventEmitter<any>();
129     }
130
131     ngOnInit() {
132
133         if (!this.dataSource) {
134             throw new Error('<eg-grid/> requires a [dataSource]');
135         }
136
137         this.context.idlClass = this.idlClass;
138         this.context.dataSource = this.dataSource;
139         this.context.persistKey = this.persistKey;
140         this.context.isSortable = this.sortable === true;
141         this.context.isFilterable = this.filterable === true;
142         this.context.stickyGridHeader = this.stickyHeader === true;
143         this.context.isMultiSortable = this.multiSortable === true;
144         this.context.useLocalSort = this.useLocalSort === true;
145         this.context.disableSelect = this.disableSelect === true;
146         this.context.disableMultiSelect = this.disableMultiSelect === true;
147         this.context.rowFlairIsEnabled = this.rowFlairIsEnabled  === true;
148         this.context.showDeclaredFieldsOnly = this.showDeclaredFieldsOnly;
149         this.context.rowFlairCallback = this.rowFlairCallback;
150         this.context.disablePaging = this.disablePaging === true;
151         if (this.showFields) {
152             this.context.defaultVisibleFields = this.showFields.split(',');
153         }
154         if (this.hideFields) {
155             this.context.defaultHiddenFields = this.hideFields.split(',');
156         }
157
158         if (this.pageOffset) {
159             this.context.pager.offset = this.pageOffset;
160         }
161
162         if (this.pageSize) {
163             this.context.pager.limit = this.pageSize;
164         }
165
166         // TS doesn't seem to like: let foo = bar || () => '';
167         this.context.rowClassCallback =
168             this.rowClassCallback || function () { return ''; };
169         this.context.cellClassCallback =
170             this.cellClassCallback || function() { return ''; };
171
172         if (this.showLinkSelectors) {
173             console.debug(
174                 'showLinkSelectors is deprecated and no longer has any effect');
175         }
176
177         this.context.init();
178     }
179
180     ngAfterViewInit() {
181         this.context.initData();
182     }
183
184     ngOnDestroy() {
185         this.context.destroy();
186     }
187
188     print = () => {
189         this.toolbar.printHtml();
190     }
191
192     reload() {
193         this.context.reload();
194     }
195     reloadWithoutPagerReset() {
196         this.context.reloadWithoutPagerReset();
197     }
198
199
200 }
201
202
203