angular-slickgrid 4.1.2 → 4.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.browserslistrc +12 -0
- package/.codecov.yml +17 -0
- package/.editorconfig +18 -0
- package/.eslintrc.json +50 -0
- package/.github/CODE_OF_CONDUCT.md +76 -0
- package/.github/FUNDING.yml +8 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +54 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +44 -0
- package/.github/renovate.json5 +26 -0
- package/.github/stale.yml +7 -0
- package/.github/workflows/main.yml +83 -0
- package/.vscode/extensions.json +9 -0
- package/.vscode/launch.json +72 -0
- package/.vscode/settings.json +7 -0
- package/.vscode/tasks.json +77 -0
- package/CHANGELOG.md +1172 -0
- package/LICENSE +20 -20
- package/README.md +9 -7
- package/angular.json +148 -0
- package/dist/LICENSE +20 -0
- package/dist/README.md +182 -0
- package/{angular-slickgrid.d.ts → dist/angular-slickgrid.d.ts} +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/constants.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/extensions/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/extensions/slickRowDetailView.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/global-grid-options.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/angularComponentOutput.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/externalTestingDependencies.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/gridOption.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/rowDetailView.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/models/slickGrid.interface.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/angularUtil.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/bsDropdown.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/container.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/index.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/translater.service.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/services/utilities.d.ts +0 -0
- package/{app → dist/app}/modules/angular-slickgrid/slickgrid-config.d.ts +0 -0
- package/{esm2020 → dist/esm2020}/angular-slickgrid.mjs +0 -0
- package/dist/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1171 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/constants.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +2 -2
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/global-grid-options.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs +1 -1
- package/dist/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +2 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/models/index.mjs +1 -1
- package/dist/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +2 -0
- package/dist/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +2 -0
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +5 -5
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/angularUtil.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/container.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/index.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/translater.service.mjs +4 -4
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/services/utilities.mjs +1 -1
- package/{esm2020 → dist/esm2020}/app/modules/angular-slickgrid/slickgrid-config.mjs +1 -1
- package/{esm2020 → dist/esm2020}/public_api.mjs +1 -1
- package/{fesm2015 → dist/fesm2015}/angular-slickgrid.mjs +25 -22
- package/dist/fesm2015/angular-slickgrid.mjs.map +1 -0
- package/{fesm2020 → dist/fesm2020}/angular-slickgrid.mjs +25 -22
- package/dist/fesm2020/angular-slickgrid.mjs.map +1 -0
- package/{i18n → dist/i18n}/en.json +89 -89
- package/{i18n → dist/i18n}/fr.json +90 -90
- package/dist/package.json +79 -0
- package/{public_api.d.ts → dist/public_api.d.ts} +0 -0
- package/global.d.ts +1 -0
- package/ngcc.config.js +13 -0
- package/package.json +124 -37
- package/screenshots/column-picker.png +0 -0
- package/screenshots/composite-editor.png +0 -0
- package/screenshots/draggable-grouping.png +0 -0
- package/screenshots/editors.png +0 -0
- package/screenshots/export-to-file.png +0 -0
- package/screenshots/filter_and_sort.png +0 -0
- package/screenshots/formatters.png +0 -0
- package/screenshots/frozen.png +0 -0
- package/screenshots/multipleSelectFilter.png +0 -0
- package/screenshots/pagination.png +0 -0
- package/screenshots/selectFilter.png +0 -0
- package/screenshots/singleFilter.png +0 -0
- package/src/app/app-routing.module.ts +83 -0
- package/src/app/app.component.html +160 -0
- package/src/app/app.component.scss +65 -0
- package/src/app/app.component.ts +10 -0
- package/src/app/app.module.ts +175 -0
- package/src/app/examples/custom-angularComponentEditor.ts +184 -0
- package/src/app/examples/custom-angularComponentFilter.ts +126 -0
- package/src/app/examples/custom-inputEditor.ts +124 -0
- package/src/app/examples/custom-inputFilter.ts +142 -0
- package/src/app/examples/custom-titleFormatter.component.ts +8 -0
- package/src/app/examples/editor-ng-select.component.ts +37 -0
- package/src/app/examples/filter-ng-select.component.ts +32 -0
- package/src/app/examples/grid-additem.component.html +48 -0
- package/src/app/examples/grid-additem.component.ts +272 -0
- package/src/app/examples/grid-angular.component.html +79 -0
- package/src/app/examples/grid-angular.component.scss +28 -0
- package/src/app/examples/grid-angular.component.ts +370 -0
- package/src/app/examples/grid-autoheight.component.html +52 -0
- package/src/app/examples/grid-autoheight.component.ts +147 -0
- package/src/app/examples/grid-basic.component.html +29 -0
- package/src/app/examples/grid-basic.component.ts +82 -0
- package/src/app/examples/grid-clientside.component.html +51 -0
- package/src/app/examples/grid-clientside.component.ts +293 -0
- package/src/app/examples/grid-colspan.component.html +39 -0
- package/src/app/examples/grid-colspan.component.scss +11 -0
- package/src/app/examples/grid-colspan.component.ts +155 -0
- package/src/app/examples/grid-composite-editor.component.html +79 -0
- package/src/app/examples/grid-composite-editor.component.scss +19 -0
- package/src/app/examples/grid-composite-editor.component.ts +948 -0
- package/src/app/examples/grid-contextmenu.component.html +62 -0
- package/src/app/examples/grid-contextmenu.component.scss +44 -0
- package/src/app/examples/grid-contextmenu.component.ts +473 -0
- package/src/app/examples/grid-custom-tooltip.component.html +25 -0
- package/src/app/examples/grid-custom-tooltip.component.scss +77 -0
- package/src/app/examples/grid-custom-tooltip.component.ts +483 -0
- package/src/app/examples/grid-draggrouping.component.html +93 -0
- package/src/app/examples/grid-draggrouping.component.ts +397 -0
- package/src/app/examples/grid-editor.component.html +88 -0
- package/src/app/examples/grid-editor.component.ts +699 -0
- package/src/app/examples/grid-formatter.component.html +26 -0
- package/src/app/examples/grid-formatter.component.ts +162 -0
- package/src/app/examples/grid-frozen.component.html +65 -0
- package/src/app/examples/grid-frozen.component.scss +11 -0
- package/src/app/examples/grid-frozen.component.ts +303 -0
- package/src/app/examples/grid-graphql-nopage.component.html +33 -0
- package/src/app/examples/grid-graphql-nopage.component.scss +9 -0
- package/src/app/examples/grid-graphql-nopage.component.ts +242 -0
- package/src/app/examples/grid-graphql.component.html +87 -0
- package/src/app/examples/grid-graphql.component.ts +304 -0
- package/src/app/examples/grid-grouping.component.html +80 -0
- package/src/app/examples/grid-grouping.component.ts +313 -0
- package/src/app/examples/grid-headerbutton.component.html +31 -0
- package/src/app/examples/grid-headerbutton.component.scss +10 -0
- package/src/app/examples/grid-headerbutton.component.ts +233 -0
- package/src/app/examples/grid-headermenu.component.html +31 -0
- package/src/app/examples/grid-headermenu.component.scss +25 -0
- package/src/app/examples/grid-headermenu.component.ts +159 -0
- package/src/app/examples/grid-localization.component.html +54 -0
- package/src/app/examples/grid-localization.component.ts +293 -0
- package/src/app/examples/grid-menu.component.html +37 -0
- package/src/app/examples/grid-menu.component.scss +28 -0
- package/src/app/examples/grid-menu.component.ts +229 -0
- package/src/app/examples/grid-odata.component.html +116 -0
- package/src/app/examples/grid-odata.component.ts +441 -0
- package/src/app/examples/grid-range.component.html +74 -0
- package/src/app/examples/grid-range.component.ts +291 -0
- package/src/app/examples/grid-remote.component.html +37 -0
- package/src/app/examples/grid-remote.component.ts +153 -0
- package/src/app/examples/grid-resize-by-content.component.html +62 -0
- package/src/app/examples/grid-resize-by-content.component.scss +19 -0
- package/src/app/examples/grid-resize-by-content.component.ts +780 -0
- package/src/app/examples/grid-rowdetail.component.html +35 -0
- package/src/app/examples/grid-rowdetail.component.ts +205 -0
- package/src/app/examples/grid-rowmove.component.html +49 -0
- package/src/app/examples/grid-rowmove.component.ts +234 -0
- package/src/app/examples/grid-rowselection.component.html +76 -0
- package/src/app/examples/grid-rowselection.component.ts +267 -0
- package/src/app/examples/grid-state.component.html +36 -0
- package/src/app/examples/grid-state.component.ts +259 -0
- package/src/app/examples/grid-tabs.component.html +35 -0
- package/src/app/examples/grid-tabs.component.ts +115 -0
- package/src/app/examples/grid-trading.component.html +58 -0
- package/src/app/examples/grid-trading.component.scss +49 -0
- package/src/app/examples/grid-trading.component.ts +319 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.html +79 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.scss +47 -0
- package/src/app/examples/grid-tree-data-hierarchical.component.ts +311 -0
- package/src/app/examples/grid-tree-data-parent-child.component.html +108 -0
- package/src/app/examples/grid-tree-data-parent-child.component.scss +10 -0
- package/src/app/examples/grid-tree-data-parent-child.component.ts +351 -0
- package/src/app/examples/home.component.html +41 -0
- package/src/app/examples/home.component.ts +9 -0
- package/src/app/examples/rowdetail-preload.component.ts +10 -0
- package/src/app/examples/rowdetail-view.component.html +36 -0
- package/src/app/examples/rowdetail-view.component.ts +54 -0
- package/src/app/examples/swt-common-grid-pagination.component.ts +156 -0
- package/src/app/examples/swt-common-grid-test.component.html +30 -0
- package/src/app/examples/swt-common-grid-test.component.ts +219 -0
- package/src/app/examples/swt-common-grid.component.ts +436 -0
- package/src/app/examples/swt-logger.service.ts +165 -0
- package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.html +4 -0
- package/src/app/modules/angular-slickgrid/components/angular-slickgrid.component.ts +1395 -0
- package/src/app/modules/angular-slickgrid/constants.ts +97 -0
- package/src/app/modules/angular-slickgrid/extensions/index.ts +1 -0
- package/src/app/modules/angular-slickgrid/extensions/slickRowDetailView.ts +375 -0
- package/src/app/modules/angular-slickgrid/global-grid-options.ts +245 -0
- package/src/app/modules/angular-slickgrid/index.ts +11 -0
- package/src/app/modules/angular-slickgrid/models/angularComponentOutput.interface.ts +6 -0
- package/src/app/modules/angular-slickgrid/models/angularGridInstance.interface.ts +68 -0
- package/src/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.ts +37 -0
- package/src/app/modules/angular-slickgrid/models/gridOption.interface.ts +12 -0
- package/src/app/modules/angular-slickgrid/models/index.ts +6 -0
- package/src/app/modules/angular-slickgrid/models/rowDetailView.interface.ts +33 -0
- package/src/app/modules/angular-slickgrid/models/slickGrid.interface.ts +7 -0
- package/src/app/modules/angular-slickgrid/modules/angular-slickgrid.module.ts +37 -0
- package/src/app/modules/angular-slickgrid/services/angularUtil.service.ts +48 -0
- package/src/app/modules/angular-slickgrid/services/bsDropdown.service.ts +142 -0
- package/src/app/modules/angular-slickgrid/services/container.service.ts +24 -0
- package/src/app/modules/angular-slickgrid/services/index.ts +5 -0
- package/src/app/modules/angular-slickgrid/services/translater.service.ts +38 -0
- package/src/app/modules/angular-slickgrid/services/utilities.ts +19 -0
- package/src/app/modules/angular-slickgrid/slickgrid-config.ts +10 -0
- package/src/app/slickgrid-custom-variables.scss +10 -0
- package/src/assets/.gitkeep +0 -0
- package/src/assets/data/collection_100_numbers.json +12 -0
- package/src/assets/data/collection_500_numbers.json +52 -0
- package/src/assets/data/countries.json +245 -0
- package/src/assets/data/country_names.json +245 -0
- package/src/assets/data/customers_100.json +102 -0
- package/src/assets/i18n/en.json +90 -0
- package/src/assets/i18n/fr.json +91 -0
- package/src/environments/environment.prod.ts +3 -0
- package/src/environments/environment.ts +8 -0
- package/src/favicon.ico +0 -0
- package/src/index.html +18 -0
- package/src/main.ts +13 -0
- package/src/polyfills.ts +52 -0
- package/src/public_api.ts +1 -0
- package/src/styles.scss +66 -0
- package/src/typings.d.ts +10 -0
- package/tsconfig.app.json +25 -0
- package/tsconfig.json +40 -0
- package/tsconfig.spec.json +23 -0
- package/docs/assets/lib/multiple-select/README.md +0 -17
- package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +0 -1168
- package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs +0 -2
- package/esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs +0 -2
- package/fesm2015/angular-slickgrid.mjs.map +0 -1
- package/fesm2020/angular-slickgrid.mjs.map +0 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { Component, OnInit, } from '@angular/core';
|
|
2
|
+
import { HttpClient } from '@angular/common/http';
|
|
3
|
+
|
|
4
|
+
import { AngularGridInstance, Column, GridOption, Filters } from '../modules/angular-slickgrid';
|
|
5
|
+
|
|
6
|
+
const URL_CUSTOMERS = 'assets/data/customers_100.json';
|
|
7
|
+
|
|
8
|
+
@Component({
|
|
9
|
+
templateUrl: './grid-tabs.component.html'
|
|
10
|
+
})
|
|
11
|
+
export class GridTabsComponent implements OnInit {
|
|
12
|
+
title = 'Example 24: Grids in Bootstrap Tabs';
|
|
13
|
+
subTitle = `This example demonstrate the creation of multiple grids in Bootstrap Tabs
|
|
14
|
+
<ol>
|
|
15
|
+
<li>Regular mocked data with javascript</li>
|
|
16
|
+
<li>Load dataset through Http-Client. Also note we need to call a "resizeGrid()" after focusing on this tab</li>
|
|
17
|
+
</ol>`;
|
|
18
|
+
|
|
19
|
+
angularGrid2!: AngularGridInstance;
|
|
20
|
+
columnDefinitions1!: Column[];
|
|
21
|
+
columnDefinitions2!: Column[];
|
|
22
|
+
gridOptions1!: GridOption;
|
|
23
|
+
gridOptions2!: GridOption;
|
|
24
|
+
dataset1!: any[];
|
|
25
|
+
dataset2!: any[];
|
|
26
|
+
|
|
27
|
+
constructor(private http: HttpClient) { }
|
|
28
|
+
|
|
29
|
+
angularGrid2Ready(angularGrid: AngularGridInstance) {
|
|
30
|
+
this.angularGrid2 = angularGrid;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
ngOnInit(): void {
|
|
34
|
+
this.defineGrid1();
|
|
35
|
+
this.defineGrid2();
|
|
36
|
+
|
|
37
|
+
// mock some data (different in each dataset)
|
|
38
|
+
this.dataset1 = this.mockData();
|
|
39
|
+
|
|
40
|
+
// load data with Http-Client
|
|
41
|
+
this.http.get((URL_CUSTOMERS)).subscribe(((data: any[]) => this.dataset2 = data) as any);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Grid2 definition
|
|
45
|
+
defineGrid1() {
|
|
46
|
+
this.columnDefinitions1 = [
|
|
47
|
+
{ id: 'title', name: 'Title', field: 'title', sortable: true, minWidth: 100 },
|
|
48
|
+
{ id: 'duration', name: 'Duration (days)', field: 'duration', sortable: true, minWidth: 100 },
|
|
49
|
+
{ id: '%', name: '% Complete', field: 'percentComplete', sortable: true, minWidth: 100 },
|
|
50
|
+
{ id: 'start', name: 'Start', field: 'start', minWidth: 100 },
|
|
51
|
+
{ id: 'finish', name: 'Finish', field: 'finish', minWidth: 100 },
|
|
52
|
+
{ id: 'effort-driven', name: 'Effort Driven', field: 'effortDriven', sortable: true, minWidth: 100 }
|
|
53
|
+
];
|
|
54
|
+
this.gridOptions1 = {
|
|
55
|
+
enableAutoResize: true,
|
|
56
|
+
autoResize: {
|
|
57
|
+
container: '#demo-container',
|
|
58
|
+
rightPadding: 10
|
|
59
|
+
},
|
|
60
|
+
enableSorting: true
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Grid2 definition
|
|
65
|
+
defineGrid2() {
|
|
66
|
+
this.columnDefinitions2 = [
|
|
67
|
+
{ id: 'name', name: 'Name', field: 'name', filterable: true, sortable: true, },
|
|
68
|
+
{
|
|
69
|
+
id: 'gender', name: 'Gender', field: 'gender', filterable: true, sortable: true,
|
|
70
|
+
filter: {
|
|
71
|
+
model: Filters.singleSelect,
|
|
72
|
+
collection: [{ value: '', label: '' }, { value: 'male', label: 'male' }, { value: 'female', label: 'female' }]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true }
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
this.gridOptions2 = {
|
|
79
|
+
enableAutoResize: true,
|
|
80
|
+
autoResize: {
|
|
81
|
+
container: '#demo-container',
|
|
82
|
+
rightPadding: 10
|
|
83
|
+
},
|
|
84
|
+
enableFiltering: true,
|
|
85
|
+
enableSorting: true
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
mockData() {
|
|
90
|
+
// mock a dataset
|
|
91
|
+
const mockDataset = [];
|
|
92
|
+
for (let i = 0; i < 1000; i++) {
|
|
93
|
+
const randomYear = 2000 + Math.floor(Math.random() * 10);
|
|
94
|
+
const randomMonth = Math.floor(Math.random() * 11);
|
|
95
|
+
const randomDay = Math.floor((Math.random() * 29));
|
|
96
|
+
const randomPercent = Math.round(Math.random() * 100);
|
|
97
|
+
|
|
98
|
+
mockDataset[i] = {
|
|
99
|
+
id: i,
|
|
100
|
+
title: 'Task ' + i,
|
|
101
|
+
duration: Math.round(Math.random() * 100) + '',
|
|
102
|
+
percentComplete: randomPercent,
|
|
103
|
+
start: `${randomMonth}/${randomDay}/${randomYear}`,
|
|
104
|
+
finish: `${randomMonth}/${randomDay}/${randomYear}`,
|
|
105
|
+
effortDriven: (i % 5 === 0)
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return mockDataset;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
resizeGrid2() {
|
|
113
|
+
this.angularGrid2.resizerService.resizeGrid();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<div class="container-fluid">
|
|
2
|
+
<h2>
|
|
3
|
+
{{title}}
|
|
4
|
+
<span class="float-end">
|
|
5
|
+
<a style="font-size: 18px"
|
|
6
|
+
target="_blank"
|
|
7
|
+
href="https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/examples/grid-trading.component.ts">
|
|
8
|
+
<span class="fa fa-link"></span> code
|
|
9
|
+
</a>
|
|
10
|
+
</span>
|
|
11
|
+
</h2>
|
|
12
|
+
<div class="subtitle" [innerHTML]="subTitle"></div>
|
|
13
|
+
|
|
14
|
+
<div class="trading-platform">
|
|
15
|
+
<div class="row mb-4 simulation-form">
|
|
16
|
+
<div class="col-sm-12 d-flex align-items-center">
|
|
17
|
+
<div class="range">
|
|
18
|
+
<label for="refreshRateRange" class="form-label me-1">Changes Rate(ms)</label>
|
|
19
|
+
<input type="range" class="form-range" id="refreshRateRange" min="0" max="250" [(ngModel)]="refreshRate">
|
|
20
|
+
<span class="refresh-rate">
|
|
21
|
+
<input type="number" [(ngModel)]="refreshRate">
|
|
22
|
+
</span>
|
|
23
|
+
</div>
|
|
24
|
+
<span class="ms-3 me-1">
|
|
25
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="start-btn" (click)="startSimulation()">
|
|
26
|
+
<li class="fa fa-play"></li> Start Simulation
|
|
27
|
+
</button>
|
|
28
|
+
</span>
|
|
29
|
+
<span class="me-3">
|
|
30
|
+
<button class="btn btn-outline-secondary btn-sm" data-test="stop-btn" (click)="stopSimulation()">
|
|
31
|
+
<li class="fa fa-stop"></li> Stop Simulation
|
|
32
|
+
</button>
|
|
33
|
+
</span>
|
|
34
|
+
<span class="mx-1">
|
|
35
|
+
<label for="change-per-cycle-input">Changes p/Cycle</label>
|
|
36
|
+
<input type="number" id="change-per-cycle-input" [(ngModel)]="minChangePerCycle" [max]="maxChangePerCycle">
|
|
37
|
+
to
|
|
38
|
+
<input type="number" [(ngModel)]="maxChangePerCycle" [min]="minChangePerCycle">
|
|
39
|
+
</span>
|
|
40
|
+
<span class="ms-2">
|
|
41
|
+
<label for="highlight-input">Highlight Duration(ms)</label>
|
|
42
|
+
<input type="number" id="highlight-input" data-test="highlight-input" [(ngModel)]="highlightDuration">
|
|
43
|
+
</span>
|
|
44
|
+
<div class="ms-auto">
|
|
45
|
+
<button class="btn btn-outline-secondary btn-sm" (click)="toggleFullScreen()">
|
|
46
|
+
<li [class]="isFullScreen ? 'fa fa-compress' : 'fa fa-arrows-alt'"></li> Toggle Full-Screen
|
|
47
|
+
</button>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<angular-slickgrid gridId="grid33"
|
|
53
|
+
[columnDefinitions]="columnDefinitions"
|
|
54
|
+
[gridOptions]="gridOptions"
|
|
55
|
+
[dataset]="dataset"
|
|
56
|
+
(onAngularGridCreated)="angularGridReady($event.detail)">
|
|
57
|
+
</angular-slickgrid>
|
|
58
|
+
</div>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// @import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.lite.scss';
|
|
2
|
+
|
|
3
|
+
$sparkline-color: #00b78d;
|
|
4
|
+
// $sparkline-color: #573585;
|
|
5
|
+
|
|
6
|
+
.trading-platform.full-screen {
|
|
7
|
+
position: absolute;
|
|
8
|
+
top: 0;
|
|
9
|
+
left: 0;
|
|
10
|
+
right: 0;
|
|
11
|
+
bottom: 0;
|
|
12
|
+
padding: 10px 12px 0 10px;
|
|
13
|
+
background-color: white;
|
|
14
|
+
z-index: 8000;
|
|
15
|
+
position: fixed;
|
|
16
|
+
}
|
|
17
|
+
.changed-gain {
|
|
18
|
+
background-color: #eafae8 !important;
|
|
19
|
+
}
|
|
20
|
+
.changed-loss {
|
|
21
|
+
background-color: #ffeae8 !important;
|
|
22
|
+
}
|
|
23
|
+
.simulation-form {
|
|
24
|
+
input[type=number] {
|
|
25
|
+
height: 32px;
|
|
26
|
+
width: 50px;
|
|
27
|
+
border: 1px solid #c0c0c0;
|
|
28
|
+
border-radius: 3px;
|
|
29
|
+
}
|
|
30
|
+
div.range {
|
|
31
|
+
display: contents;
|
|
32
|
+
width: 200px;
|
|
33
|
+
label.form-label {
|
|
34
|
+
margin: 0;
|
|
35
|
+
}
|
|
36
|
+
input.form-range {
|
|
37
|
+
width: 120px;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
.refresh-rate input {
|
|
41
|
+
height: 30px;
|
|
42
|
+
width: 46px;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
.sparkline {
|
|
46
|
+
stroke: $sparkline-color;
|
|
47
|
+
// fill: none;
|
|
48
|
+
fill: rgba($sparkline-color, 0.03);
|
|
49
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { Component, OnDestroy, OnInit, ViewEncapsulation, } from '@angular/core';
|
|
2
|
+
import { faker } from '@faker-js/faker';
|
|
3
|
+
import sparkline from '@fnando/sparkline';
|
|
4
|
+
import {
|
|
5
|
+
Aggregators,
|
|
6
|
+
AngularGridInstance,
|
|
7
|
+
Column,
|
|
8
|
+
deepCopy,
|
|
9
|
+
FieldType,
|
|
10
|
+
Filters,
|
|
11
|
+
Formatter,
|
|
12
|
+
Formatters,
|
|
13
|
+
GridOption,
|
|
14
|
+
GroupTotalFormatters,
|
|
15
|
+
} from '../modules/angular-slickgrid';
|
|
16
|
+
|
|
17
|
+
const NB_ROWS = 200;
|
|
18
|
+
|
|
19
|
+
const currencyFormatter: Formatter = (cell: number, row: number, value: string) =>
|
|
20
|
+
`<img src="https://flags.fmcdn.net/data/flags/mini/${value.substr(0, 2).toLowerCase()}.png" width="20"/> ${value}`;
|
|
21
|
+
|
|
22
|
+
const priceFormatter: Formatter = (cell: number, row: number, value: number, col: Column, dataContext: any) => {
|
|
23
|
+
const direction = dataContext.priceChange >= 0 ? 'up' : 'down';
|
|
24
|
+
return `<span class="fa fa-arrow-${direction} text-${direction === 'up' ? 'success' : 'danger'}"></span> ${value}`;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const transactionTypeFormatter: Formatter = (row: number, cell: number, value: string) =>
|
|
28
|
+
`<span <span class="fa fa-${value === 'Buy' ? 'plus' : 'minus'}-circle ${value === 'Buy' ? 'text-info' : 'text-warning'}"></span> ${value}`;
|
|
29
|
+
|
|
30
|
+
const historicSparklineFormatter: Formatter = (row: number, cell: number, value: string, col: Column, dataContext: any) => {
|
|
31
|
+
const svgElem = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
32
|
+
svgElem.setAttributeNS(null, 'width', '135');
|
|
33
|
+
svgElem.setAttributeNS(null, 'height', '30');
|
|
34
|
+
svgElem.setAttributeNS(null, 'stroke-width', '2');
|
|
35
|
+
svgElem.classList.add('sparkline');
|
|
36
|
+
sparkline(svgElem, dataContext.historic, { interactive: true });
|
|
37
|
+
return svgElem.outerHTML;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
@Component({
|
|
41
|
+
templateUrl: './grid-trading.component.html',
|
|
42
|
+
styleUrls: ['./grid-trading.component.scss'],
|
|
43
|
+
encapsulation: ViewEncapsulation.None,
|
|
44
|
+
})
|
|
45
|
+
export class GridTradingComponent implements OnDestroy, OnInit {
|
|
46
|
+
title = 'Example 33: Real-Time Trading Platform';
|
|
47
|
+
subTitle = `Simulate a stock trading platform with lot of price changes
|
|
48
|
+
<ul>
|
|
49
|
+
<li>you can start/stop the simulation</li>
|
|
50
|
+
<li>optionally change random numbers, between 0 and 10 symbols, per cycle (higher numbers means more changes)</li>
|
|
51
|
+
<li>optionally change the simulation changes refresh rate in ms (lower number means more changes).</li>
|
|
52
|
+
<li>you can Group by 1 of these columns: Currency, Market or Type</li>
|
|
53
|
+
<li>to show SlickGrid HUGE PERF., do the following: (1) lower Changes Rate (2) increase both Changes per Cycle and (3) lower Highlight Duration
|
|
54
|
+
</ul>`;
|
|
55
|
+
angularGrid!: AngularGridInstance;
|
|
56
|
+
gridOptions!: GridOption;
|
|
57
|
+
columnDefinitions: Column[] = [];
|
|
58
|
+
dataset: any[] = [];
|
|
59
|
+
isFullScreen = false;
|
|
60
|
+
highlightDuration = 150;
|
|
61
|
+
itemCount = 200;
|
|
62
|
+
minChangePerCycle = 0;
|
|
63
|
+
maxChangePerCycle = 10;
|
|
64
|
+
refreshRate = 75;
|
|
65
|
+
timer: any;
|
|
66
|
+
|
|
67
|
+
constructor() { }
|
|
68
|
+
|
|
69
|
+
ngOnInit(): void {
|
|
70
|
+
this.defineGrid();
|
|
71
|
+
|
|
72
|
+
// mock a dataset
|
|
73
|
+
this.dataset = this.loadData(NB_ROWS);
|
|
74
|
+
|
|
75
|
+
setTimeout(() => {
|
|
76
|
+
this.startSimulation();
|
|
77
|
+
}, this.refreshRate);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
ngOnDestroy(): void {
|
|
81
|
+
this.stopSimulation();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
angularGridReady(angularGrid: AngularGridInstance) {
|
|
85
|
+
this.angularGrid = angularGrid;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Define grid Options and Columns */
|
|
89
|
+
defineGrid() {
|
|
90
|
+
// the columns field property is type-safe, try to add a different string not representing one of DataItems properties
|
|
91
|
+
this.columnDefinitions = [
|
|
92
|
+
{
|
|
93
|
+
id: 'currency', name: 'Currency', field: 'currency', filterable: true, sortable: true, minWidth: 65, width: 65,
|
|
94
|
+
formatter: currencyFormatter,
|
|
95
|
+
filter: {
|
|
96
|
+
model: Filters.singleSelect,
|
|
97
|
+
collection: [{ label: '', value: '' }, { label: 'CAD', value: 'CAD' }, { label: 'USD', value: 'USD' }]
|
|
98
|
+
},
|
|
99
|
+
grouping: {
|
|
100
|
+
getter: 'currency',
|
|
101
|
+
formatter: (g) => `Currency: <span style="color: #003597; font-weight: bold;">${g.value}</span> <span style="color: #659bff;">(${g.count} items)</span>`,
|
|
102
|
+
aggregators: [
|
|
103
|
+
new Aggregators.Sum('amount')
|
|
104
|
+
],
|
|
105
|
+
aggregateCollapsed: true,
|
|
106
|
+
collapsed: false
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
{ id: 'symbol', name: 'Symbol', field: 'symbol', filterable: true, sortable: true, minWidth: 65, width: 65 },
|
|
110
|
+
{
|
|
111
|
+
id: 'market', name: 'Market', field: 'market', filterable: true, sortable: true, minWidth: 75, width: 75,
|
|
112
|
+
grouping: {
|
|
113
|
+
getter: 'market',
|
|
114
|
+
formatter: (g) => `Market: <span style="color: #003597; font-weight: bold;">${g.value}</span> <span style="color: #659bff;">(${g.count} items)</span>`,
|
|
115
|
+
aggregators: [
|
|
116
|
+
new Aggregators.Sum('amount')
|
|
117
|
+
],
|
|
118
|
+
aggregateCollapsed: true,
|
|
119
|
+
collapsed: false
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true, minWidth: 80, width: 130 },
|
|
123
|
+
{
|
|
124
|
+
id: 'trsnType', name: 'Type', field: 'trsnType', filterable: true, sortable: true, minWidth: 60, width: 60,
|
|
125
|
+
formatter: transactionTypeFormatter,
|
|
126
|
+
filter: {
|
|
127
|
+
model: Filters.singleSelect,
|
|
128
|
+
collection: [{ label: '', value: '' }, { label: 'Buy', value: 'Buy' }, { label: 'Sell', value: 'Sell' }]
|
|
129
|
+
},
|
|
130
|
+
grouping: {
|
|
131
|
+
getter: 'trsnType',
|
|
132
|
+
formatter: (g) => `Type: <span style="color: #003597; font-weight: bold;">${g.value}</span> <span style="color: #659bff;">(${g.count} items)</span>`,
|
|
133
|
+
aggregators: [
|
|
134
|
+
new Aggregators.Sum('amount')
|
|
135
|
+
],
|
|
136
|
+
aggregateCollapsed: true,
|
|
137
|
+
collapsed: false
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
id: 'priceChange', name: 'Change', field: 'priceChange', filterable: true, sortable: true, minWidth: 80, width: 80,
|
|
142
|
+
filter: { model: Filters.compoundInputNumber }, type: FieldType.number,
|
|
143
|
+
formatter: Formatters.multiple,
|
|
144
|
+
params: {
|
|
145
|
+
formatters: [Formatters.dollarColored, priceFormatter],
|
|
146
|
+
maxDecimal: 2,
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: 'price', name: 'Price', field: 'price', filterable: true, sortable: true, minWidth: 70, width: 70,
|
|
152
|
+
filter: { model: Filters.compoundInputNumber }, type: FieldType.number,
|
|
153
|
+
formatter: Formatters.dollar, params: { maxDecimal: 2 }
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
id: 'quantity', name: 'Quantity', field: 'quantity', filterable: true, sortable: true, minWidth: 70, width: 70,
|
|
157
|
+
filter: { model: Filters.compoundInputNumber }, type: FieldType.number,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'amount', name: 'Amount', field: 'amount', filterable: true, sortable: true, minWidth: 70, width: 60,
|
|
161
|
+
filter: { model: Filters.compoundInputNumber }, type: FieldType.number,
|
|
162
|
+
formatter: Formatters.dollar, params: { maxDecimal: 2 },
|
|
163
|
+
groupTotalsFormatter: GroupTotalFormatters.sumTotalsDollarBold,
|
|
164
|
+
},
|
|
165
|
+
{ id: 'historic', name: 'Price History', field: 'historic', minWidth: 100, width: 150, maxWidth: 150, formatter: historicSparklineFormatter },
|
|
166
|
+
{
|
|
167
|
+
id: 'execution', name: 'Execution Timestamp', field: 'execution', filterable: true, sortable: true, minWidth: 125,
|
|
168
|
+
formatter: Formatters.dateTimeIsoAmPm, exportWithFormatter: true,
|
|
169
|
+
type: FieldType.dateTimeIsoAM_PM, filter: { model: Filters.compoundDate }
|
|
170
|
+
},
|
|
171
|
+
];
|
|
172
|
+
|
|
173
|
+
this.gridOptions = {
|
|
174
|
+
autoResize: {
|
|
175
|
+
container: '.trading-platform',
|
|
176
|
+
rightPadding: 0,
|
|
177
|
+
bottomPadding: 10,
|
|
178
|
+
},
|
|
179
|
+
formatterOptions: {
|
|
180
|
+
displayNegativeNumberWithParentheses: true,
|
|
181
|
+
thousandSeparator: ','
|
|
182
|
+
},
|
|
183
|
+
draggableGrouping: {
|
|
184
|
+
dropPlaceHolderText: 'Drop a column header here to group by any of these available columns: Currency, Market or Type',
|
|
185
|
+
deleteIconCssClass: 'fa fa-times',
|
|
186
|
+
},
|
|
187
|
+
enableDraggableGrouping: true,
|
|
188
|
+
createPreHeaderPanel: true,
|
|
189
|
+
showPreHeaderPanel: true,
|
|
190
|
+
preHeaderPanelHeight: 40,
|
|
191
|
+
enableCellNavigation: true,
|
|
192
|
+
enableFiltering: true,
|
|
193
|
+
cellHighlightCssClass: 'changed',
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
loadData(itemCount: number): any[] {
|
|
198
|
+
// mock a dataset
|
|
199
|
+
const tmpDataset = [];
|
|
200
|
+
for (let i = 0; i < itemCount; i++) {
|
|
201
|
+
const randomPercent = Math.round(Math.random() * 100);
|
|
202
|
+
const randomLowQty = this.randomNumber(1, 50);
|
|
203
|
+
const randomHighQty = this.randomNumber(125, 255);
|
|
204
|
+
const priceChange = this.randomNumber(-25, 35, false);
|
|
205
|
+
const price = this.randomNumber(priceChange, 300);
|
|
206
|
+
const quantity = price < 5 ? randomHighQty : randomLowQty;
|
|
207
|
+
const amount = price * quantity;
|
|
208
|
+
const now = new Date();
|
|
209
|
+
now.setHours(9, 30, 0);
|
|
210
|
+
const currency = (Math.floor(Math.random() * 10)) % 2 ? 'CAD' : 'USD';
|
|
211
|
+
const company = faker.company.companyName();
|
|
212
|
+
|
|
213
|
+
tmpDataset[i] = {
|
|
214
|
+
id: i,
|
|
215
|
+
currency,
|
|
216
|
+
trsnType: (Math.round(Math.random() * 100)) % 2 ? 'Buy' : 'Sell',
|
|
217
|
+
company,
|
|
218
|
+
symbol: currency === 'CAD' ? company.substr(0, 3).toUpperCase() + '.TO' : company.substr(0, 4).toUpperCase(),
|
|
219
|
+
market: currency === 'CAD' ? 'TSX' : price > 200 ? 'Nasdaq' : 'S&P 500',
|
|
220
|
+
duration: (i % 33 === 0) ? null : Math.random() * 100 + '',
|
|
221
|
+
percentCompleteNumber: randomPercent,
|
|
222
|
+
priceChange,
|
|
223
|
+
price,
|
|
224
|
+
quantity,
|
|
225
|
+
amount,
|
|
226
|
+
execution: now,
|
|
227
|
+
historic: [price]
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return tmpDataset;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
startSimulation() {
|
|
235
|
+
const changes: any = {};
|
|
236
|
+
const numberOfUpdates = this.randomNumber(this.minChangePerCycle, this.maxChangePerCycle);
|
|
237
|
+
|
|
238
|
+
for (let i = 0; i < numberOfUpdates; i++) {
|
|
239
|
+
const randomLowQty = this.randomNumber(1, 50);
|
|
240
|
+
const randomHighQty = this.randomNumber(125, 255);
|
|
241
|
+
const rowNumber = Math.round(Math.random() * (this.dataset.length - 1));
|
|
242
|
+
const priceChange = this.randomNumber(-25, 25, false);
|
|
243
|
+
const prevItem = deepCopy(this.dataset[rowNumber]);
|
|
244
|
+
const itemTmp = { ...this.dataset[rowNumber] };
|
|
245
|
+
itemTmp.priceChange = priceChange;
|
|
246
|
+
itemTmp.price = ((itemTmp.price + priceChange) < 0) ? 0 : itemTmp.price + priceChange;
|
|
247
|
+
itemTmp.quantity = itemTmp.price < 5 ? randomHighQty : randomLowQty;
|
|
248
|
+
itemTmp.amount = itemTmp.price * itemTmp.quantity;
|
|
249
|
+
itemTmp.trsnType = (Math.round(Math.random() * 100)) % 2 ? 'Buy' : 'Sell';
|
|
250
|
+
itemTmp.execution = new Date();
|
|
251
|
+
itemTmp.historic.push(itemTmp.price);
|
|
252
|
+
itemTmp.historic = itemTmp.historic.slice(-20); // keep a max of X historic values
|
|
253
|
+
|
|
254
|
+
if (!changes[rowNumber]) {
|
|
255
|
+
changes[rowNumber] = {};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// highlight whichever cell is being changed
|
|
259
|
+
changes[rowNumber]['id'] = 'changed';
|
|
260
|
+
this.renderCellHighlighting(itemTmp, this.findColumnById('priceChange'), priceChange);
|
|
261
|
+
if ((prevItem.priceChange < 0 && itemTmp.priceChange > 0) || (prevItem.priceChange > 0 && itemTmp.priceChange < 0)) {
|
|
262
|
+
this.renderCellHighlighting(itemTmp, this.findColumnById('price'), priceChange);
|
|
263
|
+
}
|
|
264
|
+
// if (prevItem.trsnType !== itemTmp.trsnType) {
|
|
265
|
+
// this.renderCellHighlighting(itemTmp, this.findColumnById('trsnType'), priceChange);
|
|
266
|
+
// }
|
|
267
|
+
|
|
268
|
+
// update the data
|
|
269
|
+
this.angularGrid.dataView.updateItem(itemTmp.id, itemTmp);
|
|
270
|
+
// NOTE: we should also invalidate/render the row after updating cell data to see the new data rendered in the UI
|
|
271
|
+
// but the cell highlight actually does that for us so we can skip it
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
this.timer = setTimeout(this.startSimulation.bind(this), this.refreshRate || 0);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
stopSimulation() {
|
|
278
|
+
clearTimeout(this.timer);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
findColumnById(columnName: string): Column {
|
|
282
|
+
return this.columnDefinitions.find(col => col.field === columnName) as Column;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
renderCellHighlighting(item: any, column: Column, priceChange: number) {
|
|
286
|
+
if (item && column) {
|
|
287
|
+
const row = this.angularGrid.dataView.getRowByItem(item) as number;
|
|
288
|
+
if (row >= 0) {
|
|
289
|
+
const hash = { [row]: { [column.id]: priceChange >= 0 ? 'changed-gain' : 'changed-loss' } };
|
|
290
|
+
this.angularGrid.slickGrid.setCellCssStyles(`highlight_${[column.id]}${row}`, hash);
|
|
291
|
+
|
|
292
|
+
// remove highlight after x amount of time
|
|
293
|
+
setTimeout(() => this.removeCellStyling(item, column, row), this.highlightDuration);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** remove change highlight css class from that cell */
|
|
299
|
+
removeCellStyling(_item: any, column: Column, row: number) {
|
|
300
|
+
this.angularGrid?.slickGrid?.removeCellCssStyles(`highlight_${[column.id]}${row}`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
toggleFullScreen() {
|
|
304
|
+
const container = document.querySelector('.trading-platform');
|
|
305
|
+
if (container?.classList.contains('full-screen')) {
|
|
306
|
+
container.classList.remove('full-screen');
|
|
307
|
+
this.isFullScreen = false;
|
|
308
|
+
} else if (container) {
|
|
309
|
+
container.classList.add('full-screen');
|
|
310
|
+
this.isFullScreen = true;
|
|
311
|
+
}
|
|
312
|
+
this.angularGrid.resizerService.resizeGrid();
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
private randomNumber(min: number, max: number, floor = true) {
|
|
316
|
+
const number = Math.random() * (max - min + 1) + min;
|
|
317
|
+
return floor ? Math.floor(number) : number;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<div class="container-fluid">
|
|
2
|
+
<h2>
|
|
3
|
+
<span [innerHTML]="title"></span>
|
|
4
|
+
<span class="float-end">
|
|
5
|
+
<a style="font-size: 18px"
|
|
6
|
+
target="_blank"
|
|
7
|
+
href="https://github.com/ghiscoding/Angular-Slickgrid/blob/master/src/app/examples/grid-tree-data-hierarchical.component.ts">
|
|
8
|
+
<span class="mdi mdi-link mdi-v-align-sub"></span> code
|
|
9
|
+
</a>
|
|
10
|
+
</span>
|
|
11
|
+
</h2>
|
|
12
|
+
<div class="subtitle" [innerHTML]="subTitle"></div>
|
|
13
|
+
|
|
14
|
+
<div class="row">
|
|
15
|
+
<div class="col-md-7">
|
|
16
|
+
<button (click)="addNewFile()" data-test="add-item-btn" class="btn btn-primary btn-sm">
|
|
17
|
+
<span class="icon mdi mdi-plus color-white"></span>
|
|
18
|
+
<span>Add New Pop Song</span>
|
|
19
|
+
</button>
|
|
20
|
+
<button (click)="collapseAll()" data-test="collapse-all-btn" class="btn btn-outline-secondary btn-sm">
|
|
21
|
+
<span class="icon mdi mdi-arrow-collapse"></span>
|
|
22
|
+
<span>Collapse All</span>
|
|
23
|
+
</button>
|
|
24
|
+
<button (click)="expandAll()" data-test="expand-all-btn" class="btn btn-outline-secondary btn-sm">
|
|
25
|
+
<span class="icon mdi mdi-arrow-expand"></span>
|
|
26
|
+
<span>Expand All</span>
|
|
27
|
+
</button>
|
|
28
|
+
<button (click)="logFlatStructure()" class="btn btn-outline-secondary btn-sm"
|
|
29
|
+
title="console.log of the Flat dataset">
|
|
30
|
+
<span>Log Flat Structure</span>
|
|
31
|
+
</button>
|
|
32
|
+
<button (click)="logHierarchicalStructure()" class="btn btn-outline-secondary btn-sm"
|
|
33
|
+
title="console.log of the Hierarchical Tree dataset">
|
|
34
|
+
<span>Log Hierarchical Structure</span>
|
|
35
|
+
</button>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div class="col-md-5">
|
|
39
|
+
<div class="input-group">
|
|
40
|
+
<input type="text" class="form-control search-string" data-test="search-string"
|
|
41
|
+
placeholder="search value" autocomplete="off" [(ngModel)]="searchString"
|
|
42
|
+
(ngModelChange)="searchStringChanged()">
|
|
43
|
+
<button class="btn btn-outline-secondary" data-test="clear-search-string" (click)="clearSearch()">
|
|
44
|
+
<span class="icon mdi mdi-close-thick"></span>
|
|
45
|
+
</button>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div>
|
|
51
|
+
<label class="checkbox-inline control-label" for="excludeChildWhenFiltering" style="margin-left: 20px">
|
|
52
|
+
<input type="checkbox" id="excludeChildWhenFiltering" data-test="exclude-child-when-filtering"
|
|
53
|
+
[checked]="isExcludingChildWhenFiltering"
|
|
54
|
+
(click)="changeExcludeChildWhenFiltering()">
|
|
55
|
+
<span
|
|
56
|
+
title="for example if we filter the word 'pop' and we exclude children, then only the folder 'pop' will show up without any content unless we uncheck this flag">
|
|
57
|
+
Exclude Children when Filtering Tree
|
|
58
|
+
</span>
|
|
59
|
+
</label>
|
|
60
|
+
<label class="checkbox-inline control-label" for="autoApproveParentItem" style="margin-left: 20px">
|
|
61
|
+
<input type="checkbox" id="autoApproveParentItem" data-test="auto-approve-parent-item"
|
|
62
|
+
[checked]="isAutoApproveParentItemWhenTreeColumnIsValid"
|
|
63
|
+
(click)="changeAutoApproveParentItem()">
|
|
64
|
+
<span
|
|
65
|
+
title="for example in this demo if we filter with 'music' and size '> 70' nothing will show up unless we have this flag enabled
|
|
66
|
+
because none of the files have both criteria at the same time, however the column with the tree 'file' does pass the filter criteria 'music'
|
|
67
|
+
and with this flag we tell the lib to skip any other filter(s) as soon as the with the tree (file in this demo) passes its own filter criteria">
|
|
68
|
+
Skip Other Filter Criteria when Parent with Tree is valid
|
|
69
|
+
</span>
|
|
70
|
+
</label>
|
|
71
|
+
</div>
|
|
72
|
+
|
|
73
|
+
<angular-slickgrid gridId="grid29"
|
|
74
|
+
[columnDefinitions]="columnDefinitions"
|
|
75
|
+
[gridOptions]="gridOptions"
|
|
76
|
+
[datasetHierarchical]="datasetHierarchical"
|
|
77
|
+
(onAngularGridCreated)="angularGridReady($event.detail)">
|
|
78
|
+
</angular-slickgrid>
|
|
79
|
+
</div>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/* make sure to add the @import the SlickGrid Theme AFTER the variables changes */
|
|
2
|
+
@import '@slickgrid-universal/common/dist/styles/sass/slickgrid-theme-salesforce.lite.scss';
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
www.OnlineWebFonts.Com
|
|
6
|
+
You must credit the author Copy this link on your web
|
|
7
|
+
<div>Font made from <a href="http://www.onlinewebfonts.com">oNline Web Fonts</a>is licensed by CC BY 3.0</div>
|
|
8
|
+
*/
|
|
9
|
+
@font-face {
|
|
10
|
+
font-family: "SalesforceSans-Regular";
|
|
11
|
+
src: url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.eot"); /* IE9*/
|
|
12
|
+
src: url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */
|
|
13
|
+
url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.woff2") format("woff2"), /* chrome firefox */
|
|
14
|
+
url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.woff") format("woff"), /* chrome firefox */
|
|
15
|
+
url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.ttf") format("truetype"), /* chrome firefox opera Safari, Android, iOS 4.2+*/
|
|
16
|
+
url("https://db.onlinewebfonts.com/t/0fadaa21fcac88ceee0bb8da992c221b.svg#SalesforceSans-Regular") format("svg"); /* iOS 4.1- */
|
|
17
|
+
}
|
|
18
|
+
.icon {
|
|
19
|
+
align-items: center;
|
|
20
|
+
display: inline-flex;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
height: 1rem;
|
|
23
|
+
width: 1rem;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** You can use the following code OR use the .color-x CSS classes */
|
|
27
|
+
|
|
28
|
+
// .icon.mdi-file-pdf-outline {
|
|
29
|
+
// /** 1. use `filter` color */
|
|
30
|
+
// // filter: invert(62%) sepia(93%) saturate(5654%) hue-rotate(325deg) brightness(100%) contrast(90%);
|
|
31
|
+
|
|
32
|
+
// /** 2. or use the SASS @mixin (from Angular-Slickgrid "sass-utilities.scss") that will produce the `filter` color */
|
|
33
|
+
// @include recolor(#f14668, 0.9);
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
// .icon.mdi-folder, .icon.mdi-folder-open {
|
|
37
|
+
// @include recolor(#ffa500, 0.9);
|
|
38
|
+
// }
|
|
39
|
+
// .icon.mdi-file-music-outline {
|
|
40
|
+
// @include recolor(#3298dc, 0.9);
|
|
41
|
+
// }
|
|
42
|
+
// .icon.mdi-file-excel-outline {
|
|
43
|
+
// @include recolor(#1E9F75, 0.9);
|
|
44
|
+
// }
|
|
45
|
+
// .icon.mdi-file-document-outline {
|
|
46
|
+
// @include recolor(#686868, 0.9);
|
|
47
|
+
// }
|