pivotgrid-js 0.1.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/LICENSE +29 -0
- package/LICENSE.commercial +60 -0
- package/README.dev.md +247 -0
- package/README.md +253 -0
- package/config/config-editor.css +298 -0
- package/config/config-editor.html +202 -0
- package/config/config-editor.js +687 -0
- package/demo_data/demo-config.js +38 -0
- package/demo_data/demo-data.js +1 -0
- package/dist/pivotgrid.cjs.js +2867 -0
- package/dist/pivotgrid.css +1091 -0
- package/dist/pivotgrid.esm.js +2867 -0
- package/dist/pivotgrid.js +2865 -0
- package/dist/pivotgrid.min.js +18 -0
- package/engine/aggregator.js +193 -0
- package/engine/column-store.js +99 -0
- package/engine/dictionary-encoder.js +30 -0
- package/package.json +50 -0
- package/providers/array-provider.js +255 -0
- package/providers/rest-provider.js +296 -0
- package/server/.env +5 -0
- package/server/README.md +88 -0
- package/server/configs/main_config.json +112 -0
- package/server/connectors/__init__.py +0 -0
- package/server/connectors/__pycache__/postgresql.cpython-312.pyc +0 -0
- package/server/connectors/postgresql.py +34 -0
- package/server/server.py +328 -0
- package/src/field-zones.css +167 -0
- package/src/field-zones.js +344 -0
- package/src/filter-manager.js +290 -0
- package/src/pivot.css +252 -0
- package/src/pivot.js +919 -0
- package/widget/cache-manager.js +253 -0
- package/widget/i18n.js +179 -0
- package/widget/pivot-widget.js +572 -0
- package/widget/widget.css +672 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
Copyright (c) 2026 Aleksandr Korolev
|
|
2
|
+
|
|
3
|
+
Non-Commercial License
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to use,
|
|
7
|
+
copy, modify, and distribute the Software for personal, educational, or
|
|
8
|
+
non-commercial purposes, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
1. The above copyright notice and this permission notice shall be included in
|
|
11
|
+
all copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
2. The Software may not be used, in whole or in part, for commercial purposes
|
|
14
|
+
without a separate commercial license obtained from the author.
|
|
15
|
+
|
|
16
|
+
3. "Commercial use" means any use of the Software intended for or directed
|
|
17
|
+
toward commercial advantage or monetary compensation, including but not
|
|
18
|
+
limited to: use in a commercial product or service, use by a for-profit
|
|
19
|
+
organization, or use in a client project for payment.
|
|
20
|
+
|
|
21
|
+
For commercial licensing, contact: korolevalexa@gmail.com
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
PIVOTGRID COMMERCIAL LICENSE AGREEMENT
|
|
2
|
+
|
|
3
|
+
This Commercial License Agreement ("Agreement") is entered into as of [DATE]
|
|
4
|
+
between Aleksandr Korolev ("Licensor") and [COMPANY/INDIVIDUAL NAME] ("Licensee").
|
|
5
|
+
|
|
6
|
+
1. GRANT OF LICENSE
|
|
7
|
+
|
|
8
|
+
Licensor grants Licensee a non-exclusive, non-transferable, worldwide license
|
|
9
|
+
to use, integrate, and deploy the PivotGrid software ("Software") in commercial
|
|
10
|
+
products and services, subject to the terms of this Agreement.
|
|
11
|
+
|
|
12
|
+
2. PERMITTED USES
|
|
13
|
+
|
|
14
|
+
Licensee may:
|
|
15
|
+
- Use the Software in commercial products or services
|
|
16
|
+
- Integrate the Software into client projects
|
|
17
|
+
- Modify the Software for internal use
|
|
18
|
+
- Deploy the Software on any number of servers owned or operated by Licensee
|
|
19
|
+
|
|
20
|
+
3. RESTRICTIONS
|
|
21
|
+
|
|
22
|
+
Licensee may not:
|
|
23
|
+
- Resell, sublicense, or redistribute the Software as a standalone product
|
|
24
|
+
- Remove or alter copyright notices in the Software
|
|
25
|
+
- Use the Software to create a competing product
|
|
26
|
+
|
|
27
|
+
4. LICENSE SCOPE
|
|
28
|
+
|
|
29
|
+
This license covers: [DESCRIPTION — e.g. "single commercial product",
|
|
30
|
+
"unlimited internal projects", "single client project"]
|
|
31
|
+
|
|
32
|
+
5. PAYMENT
|
|
33
|
+
|
|
34
|
+
License fee: [AMOUNT AND CURRENCY]
|
|
35
|
+
Payment date: [DATE]
|
|
36
|
+
|
|
37
|
+
6. TERM
|
|
38
|
+
|
|
39
|
+
This Agreement is effective from the date of payment and remains in force
|
|
40
|
+
indefinitely unless terminated due to breach of its terms.
|
|
41
|
+
|
|
42
|
+
7. TERMINATION
|
|
43
|
+
|
|
44
|
+
This Agreement terminates automatically if Licensee breaches any of its terms.
|
|
45
|
+
Upon termination, Licensee must cease all use of the Software.
|
|
46
|
+
|
|
47
|
+
8. WARRANTY DISCLAIMER
|
|
48
|
+
|
|
49
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. LICENSOR SHALL
|
|
50
|
+
NOT BE LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THE SOFTWARE.
|
|
51
|
+
|
|
52
|
+
9. CONTACT
|
|
53
|
+
|
|
54
|
+
Aleksandr Korolev
|
|
55
|
+
korolevalexa@gmail.com
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
___________________________ ___________________________
|
|
59
|
+
Aleksandr Korolev (Licensor) [NAME] (Licensee)
|
|
60
|
+
Date: ___________________ Date: ___________________
|
package/README.dev.md
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
# PivotGrid
|
|
2
|
+
|
|
3
|
+
Vanilla JS pivot table — no dependencies, no frameworks.
|
|
4
|
+
|
|
5
|
+
- **Fast** — virtual scroll, columnar storage on TypedArrays, in-memory cache
|
|
6
|
+
- **Flexible** — drag-and-drop dimensions, filters, hierarchical rows and columns
|
|
7
|
+
- **Simple** — one `<div>` and two attributes, nothing else needed
|
|
8
|
+
|
|
9
|
+
## Concept
|
|
10
|
+
|
|
11
|
+
All configuration is done through a config file. The grid API is intentionally minimal:
|
|
12
|
+
just create a container with `data-config` and the widget does the rest.
|
|
13
|
+
|
|
14
|
+
The config is stored on the server and loaded at startup —
|
|
15
|
+
no need to change application code to modify the grid structure.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<!-- Styles -->
|
|
21
|
+
<link rel="stylesheet" href="src/pivot.css">
|
|
22
|
+
<link rel="stylesheet" href="src/field-zones.css">
|
|
23
|
+
<link rel="stylesheet" href="widget/widget.css">
|
|
24
|
+
|
|
25
|
+
<!-- Engine -->
|
|
26
|
+
<script src="engine/dictionary-encoder.js"></script>
|
|
27
|
+
<script src="engine/aggregator.js"></script>
|
|
28
|
+
<script src="engine/column-store.js"></script>
|
|
29
|
+
|
|
30
|
+
<!-- Providers -->
|
|
31
|
+
<script src="providers/rest-provider.js"></script>
|
|
32
|
+
<script src="providers/array-provider.js"></script>
|
|
33
|
+
|
|
34
|
+
<!-- Component -->
|
|
35
|
+
<script src="src/pivot.js"></script>
|
|
36
|
+
<script src="src/field-zones.js"></script>
|
|
37
|
+
<script src="src/filter-manager.js"></script>
|
|
38
|
+
|
|
39
|
+
<!-- Widget -->
|
|
40
|
+
<script src="widget/i18n.js"></script>
|
|
41
|
+
<script src="widget/cache-manager.js"></script>
|
|
42
|
+
<script src="widget/pivot-widget.js"></script>
|
|
43
|
+
|
|
44
|
+
<!-- Grid -->
|
|
45
|
+
<div id="my-pivot"
|
|
46
|
+
data-config="sales"
|
|
47
|
+
data-server="http://localhost:8000">
|
|
48
|
+
</div>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The widget builds the entire UI structure inside the container automatically.
|
|
52
|
+
|
|
53
|
+
## Demo Without a Server
|
|
54
|
+
|
|
55
|
+
```html
|
|
56
|
+
<!-- Demo data and config -->
|
|
57
|
+
<script src="demo/demo-data.js"></script>
|
|
58
|
+
<script src="demo/demo-config.js"></script>
|
|
59
|
+
|
|
60
|
+
<div id="my-pivot" data-demo="true"></div>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Container Attributes
|
|
64
|
+
|
|
65
|
+
| Attribute | Description | Example |
|
|
66
|
+
|-----------|-------------|---------|
|
|
67
|
+
| `data-config` | Config name on the server | `"sales"` |
|
|
68
|
+
| `data-server` | Server URL | `"http://localhost:8000"` |
|
|
69
|
+
| `data-demo` | Demo mode without a server | `"true"` |
|
|
70
|
+
| `data-lang` | Interface language | `"ru"` / `"en"` |
|
|
71
|
+
| `data-standalone` | Use an existing HTML structure | `"true"` |
|
|
72
|
+
|
|
73
|
+
## Config
|
|
74
|
+
|
|
75
|
+
Configs are stored on the server at `configs/{name}.json`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"query": "SELECT * FROM sales_data",
|
|
80
|
+
|
|
81
|
+
"dimensions": ["region", "category", "channel"],
|
|
82
|
+
"measures": ["revenue", "units"],
|
|
83
|
+
"funcs": ["sum", "avg", "count", "min", "max"],
|
|
84
|
+
|
|
85
|
+
"fields": {
|
|
86
|
+
"region": { "label": "region", "title": "Region" },
|
|
87
|
+
"category": { "label": "category", "title": "Category" },
|
|
88
|
+
"channel": { "label": "channel", "title": "Channel" },
|
|
89
|
+
"revenue": { "label": "revenue", "title": "Revenue" },
|
|
90
|
+
"units": { "label": "units", "title": "Units" }
|
|
91
|
+
},
|
|
92
|
+
|
|
93
|
+
"cachedDimensions": ["region", "category"],
|
|
94
|
+
|
|
95
|
+
"rows": ["region"],
|
|
96
|
+
"columns": [],
|
|
97
|
+
"measure": "revenue",
|
|
98
|
+
"func": "sum",
|
|
99
|
+
|
|
100
|
+
"maxCachedRows": 500000,
|
|
101
|
+
"filterCheckboxLimit": 5
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Server
|
|
106
|
+
|
|
107
|
+
`server/server.py` — a lightweight Python proxy to the database.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install psycopg2-binary
|
|
111
|
+
python server/server.py
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Endpoints
|
|
115
|
+
|
|
116
|
+
| Method | Path | Description |
|
|
117
|
+
|--------|------|-------------|
|
|
118
|
+
| `POST` | `/query` | Execute a SQL query |
|
|
119
|
+
| `GET` | `/configs` | List all configs |
|
|
120
|
+
| `GET` | `/configs/{name}` | Get a config |
|
|
121
|
+
| `POST` | `/configs/{name}` | Save a config |
|
|
122
|
+
| `GET` | `/server-config` | DB settings (password excluded) |
|
|
123
|
+
| `POST` | `/server-config` | Save DB settings |
|
|
124
|
+
|
|
125
|
+
### DB Connectors
|
|
126
|
+
|
|
127
|
+
PostgreSQL is included by default. To add a custom database, create a file in `server/connectors/`:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
# server/connectors/mydb.py
|
|
131
|
+
NAME = "My Database"
|
|
132
|
+
|
|
133
|
+
def execute_query(query):
|
|
134
|
+
# your implementation
|
|
135
|
+
return [{"col": "val"}, ...]
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
The server picks up the new connector on next startup.
|
|
139
|
+
|
|
140
|
+
## Config Editor
|
|
141
|
+
|
|
142
|
+
A visual config editor — `config/config-editor.html`.
|
|
143
|
+
|
|
144
|
+
- Fetch columns from the database with one click
|
|
145
|
+
- Configure dimensions, measures, sortKey
|
|
146
|
+
- Drag-and-drop initial state (rows / columns / cache)
|
|
147
|
+
- Save config to the server
|
|
148
|
+
- Preview changes without saving
|
|
149
|
+
|
|
150
|
+
## Grid API
|
|
151
|
+
|
|
152
|
+
```js
|
|
153
|
+
// Expand / collapse rows
|
|
154
|
+
grid.expandAll()
|
|
155
|
+
grid.collapseAll()
|
|
156
|
+
grid.expandToDepth(depth)
|
|
157
|
+
|
|
158
|
+
// Expand / collapse columns
|
|
159
|
+
grid.expandAllCols()
|
|
160
|
+
grid.collapseAllCols()
|
|
161
|
+
|
|
162
|
+
// Subtotals
|
|
163
|
+
grid.toggleSubtotals(visible)
|
|
164
|
+
|
|
165
|
+
// Update data
|
|
166
|
+
grid.setResult(result, { rows, columns, measure, fieldDefs })
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Drillthrough
|
|
170
|
+
|
|
171
|
+
Clicking a cell dispatches a `drillthrough` event:
|
|
172
|
+
|
|
173
|
+
```js
|
|
174
|
+
container.addEventListener('drillthrough', (e) => {
|
|
175
|
+
const { context, value } = e.detail;
|
|
176
|
+
// context = { region: 'North', channel: 'Online' }
|
|
177
|
+
// value = aggregated cell value
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Click behaviour is configured in the config:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
"drillthroughQuery": "SELECT * FROM sales WHERE {filters} LIMIT 200"
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
or
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
"drillthroughUrl": "https://myapp.com/details"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Internationalization
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<div data-config="sales" data-lang="en"></div>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`ru` and `en` are supported. To add a language, extend the `I18N` object in `widget/i18n.js`.
|
|
200
|
+
|
|
201
|
+
## Project Structure
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
├── src/ # Component
|
|
205
|
+
│ ├── pivot.js
|
|
206
|
+
│ ├── pivot.css
|
|
207
|
+
│ ├── field-zones.js
|
|
208
|
+
│ ├── field-zones.css
|
|
209
|
+
│ └── filter-manager.js
|
|
210
|
+
│
|
|
211
|
+
├── engine/ # Aggregation engine
|
|
212
|
+
│ ├── aggregator.js
|
|
213
|
+
│ ├── column-store.js
|
|
214
|
+
│ └── dictionary-encoder.js
|
|
215
|
+
│
|
|
216
|
+
├── providers/ # Data providers
|
|
217
|
+
│ ├── rest-provider.js
|
|
218
|
+
│ └── array-provider.js
|
|
219
|
+
│
|
|
220
|
+
├── widget/ # Widget (UI + init)
|
|
221
|
+
│ ├── pivot-widget.js
|
|
222
|
+
│ ├── cache-manager.js
|
|
223
|
+
│ ├── i18n.js
|
|
224
|
+
│ └── widget.css
|
|
225
|
+
│
|
|
226
|
+
├── config/ # Config editor
|
|
227
|
+
│ ├── config-editor.html
|
|
228
|
+
│ ├── config-editor.css
|
|
229
|
+
│ └── config-editor.js
|
|
230
|
+
│
|
|
231
|
+
├── server/ # Python server
|
|
232
|
+
│ ├── server.py
|
|
233
|
+
│ └── connectors/
|
|
234
|
+
│ └── postgresql.py
|
|
235
|
+
│
|
|
236
|
+
└── demo/ # Demo
|
|
237
|
+
├── index.html
|
|
238
|
+
├── example.html
|
|
239
|
+
├── demo-example.html
|
|
240
|
+
├── demo-data.js
|
|
241
|
+
└── demo-config.js
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
## License
|
|
245
|
+
|
|
246
|
+
Free for personal and non-commercial use.
|
|
247
|
+
For commercial use, a license is required — contact [korolevalexa@gmail.com](mailto:korolevalexa@gmail.com).
|
package/README.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# PivotGrid JS
|
|
2
|
+
|
|
3
|
+
Vanilla JS pivot table — no dependencies, no frameworks.
|
|
4
|
+
|
|
5
|
+
- **Fast** — virtual scroll, columnar storage on TypedArrays, in-memory cache
|
|
6
|
+
- **Flexible** — drag-and-drop dimensions, filters, hierarchical rows and columns
|
|
7
|
+
- **Simple** — one `<div>` and few attributes, nothing else needed
|
|
8
|
+
|
|
9
|
+
**[Live Demo](https://windowrepino.ru/pivot/demo/demo-example.html)**
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install pivotgrid-js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<!DOCTYPE html>
|
|
23
|
+
<html>
|
|
24
|
+
<head>
|
|
25
|
+
<link rel="stylesheet" href="node_modules/pivotgrid-js/dist/pivotgrid.css">
|
|
26
|
+
</head>
|
|
27
|
+
<body>
|
|
28
|
+
|
|
29
|
+
<div id="my-pivot"
|
|
30
|
+
data-config="sales"
|
|
31
|
+
data-server="http://localhost:8000"
|
|
32
|
+
data-lang="en">
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<script src="node_modules/pivotgrid-js/dist/pivotgrid.js"></script>
|
|
36
|
+
<script src="node_modules/pivotgrid-js/widget/pivot-widget.js"></script>
|
|
37
|
+
|
|
38
|
+
</body>
|
|
39
|
+
</html>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Demo Mode (no server)
|
|
43
|
+
|
|
44
|
+
```html
|
|
45
|
+
<!DOCTYPE html>
|
|
46
|
+
<html>
|
|
47
|
+
<head>
|
|
48
|
+
<link rel="stylesheet" href="node_modules/pivotgrid-js/dist/pivotgrid.css">
|
|
49
|
+
</head>
|
|
50
|
+
<body>
|
|
51
|
+
<div id="my-pivot" data-demo="true" data-lang="en"></div>
|
|
52
|
+
|
|
53
|
+
<script src="node_modules/pivotgrid-js/dist/pivotgrid.js"></script>
|
|
54
|
+
<script src="node_modules/pivotgrid-js/demo_data/demo-data.js"></script>
|
|
55
|
+
<script src="node_modules/pivotgrid-js/demo_data/demo-config.js"></script>
|
|
56
|
+
<script src="node_modules/pivotgrid-js/widget/pivot-widget.js"></script>
|
|
57
|
+
</body>
|
|
58
|
+
</html>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Container Attributes
|
|
62
|
+
|
|
63
|
+
| Attribute | Description | Example |
|
|
64
|
+
|-----------|-------------|---------|
|
|
65
|
+
| `data-config` | Config name on the server | `"sales"` |
|
|
66
|
+
| `data-server` | Server URL | `"http://localhost:8000"` |
|
|
67
|
+
| `data-demo` | Demo mode without a server | `"true"` |
|
|
68
|
+
| `data-lang` | Interface language | `"ru"` / `"en"` |
|
|
69
|
+
| `data-standalone` | Use an existing HTML structure | `"true"` |
|
|
70
|
+
|
|
71
|
+
## Config
|
|
72
|
+
|
|
73
|
+
Configs are stored on the server at `server/configs/{name}.json`:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"query": "SELECT * FROM sales_data",
|
|
78
|
+
|
|
79
|
+
"dimensions": ["region", "category", "channel"],
|
|
80
|
+
"measures": ["revenue", "units"],
|
|
81
|
+
"funcs": ["sum", "avg", "count", "min", "max"],
|
|
82
|
+
|
|
83
|
+
"fields": {
|
|
84
|
+
"region": { "label": "region", "title": "Region" },
|
|
85
|
+
"category": { "label": "category", "title": "Category" },
|
|
86
|
+
"channel": { "label": "channel", "title": "Channel" },
|
|
87
|
+
"revenue": { "label": "revenue", "title": "Revenue" },
|
|
88
|
+
"units": { "label": "units", "title": "Units" }
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
"cachedDimensions": ["region", "category"],
|
|
92
|
+
|
|
93
|
+
"rows": ["region"],
|
|
94
|
+
"columns": [],
|
|
95
|
+
"measure": "revenue",
|
|
96
|
+
"func": "sum",
|
|
97
|
+
|
|
98
|
+
"maxCachedRows": 500000,
|
|
99
|
+
"filterCheckboxLimit": 5,
|
|
100
|
+
|
|
101
|
+
"drillthroughQuery": "SELECT * FROM sales_data WHERE {filters} LIMIT 200"
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Config Fields
|
|
106
|
+
|
|
107
|
+
| Field | Type | Description |
|
|
108
|
+
|-------|------|-------------|
|
|
109
|
+
| `query` | `string` | Base SQL query |
|
|
110
|
+
| `dimensions` | `string[]` | List of dimension field names |
|
|
111
|
+
| `measures` | `string[]` | List of measure field names |
|
|
112
|
+
| `funcs` | `string[]` | Aggregation functions: `sum`, `avg`, `count`, `min`, `max`, `stddev`, `variance` |
|
|
113
|
+
| `fields` | `object` | Field definitions — see below |
|
|
114
|
+
| `cachedDimensions` | `string[]` | Dimensions to pre-aggregate and cache on startup |
|
|
115
|
+
| `rows` | `string[]` | Initial row dimensions |
|
|
116
|
+
| `columns` | `string[]` | Initial column dimensions |
|
|
117
|
+
| `measure` | `string` | Initial active measure |
|
|
118
|
+
| `func` | `string` | Initial aggregation function |
|
|
119
|
+
| `maxCachedRows` | `number` | Maximum rows in cache (default: `500000`) |
|
|
120
|
+
| `filterCheckboxLimit` | `number` | Max distinct values to show as checkboxes in filter popup (default: `30`) |
|
|
121
|
+
| `drillthroughQuery` | `string` | SQL for drillthrough panel. Use `{filters}` as placeholder |
|
|
122
|
+
| `drillthroughUrl` | `string` | External URL for drillthrough. Filters are appended as query params |
|
|
123
|
+
|
|
124
|
+
### Field Definition
|
|
125
|
+
|
|
126
|
+
Each entry in `fields` can have:
|
|
127
|
+
|
|
128
|
+
| Property | Type | Description |
|
|
129
|
+
|----------|------|-------------|
|
|
130
|
+
| `label` | `string` | Actual column name in the database |
|
|
131
|
+
| `title` | `string` | Display name shown in the UI |
|
|
132
|
+
| `sortKey` | `string` | Column to sort by instead of the label (useful for month names etc.) |
|
|
133
|
+
|
|
134
|
+
Example — month sorted by number:
|
|
135
|
+
```json
|
|
136
|
+
"sale_month": {
|
|
137
|
+
"label": "sale_month_name",
|
|
138
|
+
"title": "Month",
|
|
139
|
+
"sortKey": "sale_month_num"
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Server
|
|
144
|
+
|
|
145
|
+
A lightweight Python proxy to your database is included:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
pip install psycopg2-binary
|
|
149
|
+
python node_modules/pivotgrid-js/server/server.py
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See `node_modules/pivotgrid-js/server/README.md` for full server documentation.
|
|
153
|
+
|
|
154
|
+
## Config Editor
|
|
155
|
+
|
|
156
|
+
A visual config editor is included. Open it locally:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
node_modules/pivotgrid-js/config/config-editor.html
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+

|
|
163
|
+
|
|
164
|
+
Features:
|
|
165
|
+
- Fetch columns from the database with one click
|
|
166
|
+
- Configure dimensions, measures, sortKey
|
|
167
|
+
- Drag-and-drop initial state (rows / columns / cache)
|
|
168
|
+
- Save config to the server
|
|
169
|
+
- Preview changes without saving
|
|
170
|
+
|
|
171
|
+
## Grid API
|
|
172
|
+
|
|
173
|
+
```js
|
|
174
|
+
// Expand / collapse rows
|
|
175
|
+
grid.expandAll()
|
|
176
|
+
grid.collapseAll()
|
|
177
|
+
grid.expandToDepth(depth) // e.g. expandToDepth(1) — first level only
|
|
178
|
+
|
|
179
|
+
// Expand / collapse columns
|
|
180
|
+
grid.expandAllCols()
|
|
181
|
+
grid.collapseAllCols()
|
|
182
|
+
|
|
183
|
+
// Subtotals
|
|
184
|
+
grid.toggleSubtotals(visible)
|
|
185
|
+
|
|
186
|
+
// Update data
|
|
187
|
+
grid.setResult(result, { rows, columns, measure, fieldDefs })
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## Drillthrough
|
|
191
|
+
|
|
192
|
+
Three ways to handle cell clicks:
|
|
193
|
+
|
|
194
|
+
### 1. Built-in panel (SQL query)
|
|
195
|
+
|
|
196
|
+
Add `drillthroughQuery` to your config:
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
"drillthroughQuery": "SELECT * FROM sales_data WHERE {filters} LIMIT 200"
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
A detail panel slides up at the bottom of the page showing the raw rows.
|
|
203
|
+
|
|
204
|
+
### 2. External URL
|
|
205
|
+
|
|
206
|
+
Add `drillthroughUrl` to your config:
|
|
207
|
+
|
|
208
|
+
```json
|
|
209
|
+
"drillthroughUrl": "https://myapp.com/details"
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Opens the URL in a new tab with filters appended as query parameters:
|
|
213
|
+
`https://myapp.com/details?region=North&channel=Online`
|
|
214
|
+
|
|
215
|
+
### 3. Custom handler
|
|
216
|
+
|
|
217
|
+
Listen for the `drillthrough` event on the container:
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
document.getElementById('my-pivot').addEventListener('drillthrough', (e) => {
|
|
221
|
+
const { context, value } = e.detail;
|
|
222
|
+
// context = { region: 'North', channel: 'Online' }
|
|
223
|
+
// value = aggregated cell value
|
|
224
|
+
// your custom logic here
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
If neither `drillthroughQuery` nor `drillthroughUrl` is set in the config,
|
|
229
|
+
only your custom handler fires.
|
|
230
|
+
|
|
231
|
+
## Internationalization
|
|
232
|
+
|
|
233
|
+
`ru` and `en` are supported out of the box:
|
|
234
|
+
|
|
235
|
+
```html
|
|
236
|
+
<div data-config="sales" data-lang="en"></div>
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
To add a language, extend the `I18N` object in `widget/i18n.js`.
|
|
240
|
+
|
|
241
|
+
## Using with a Bundler
|
|
242
|
+
|
|
243
|
+
```js
|
|
244
|
+
import { PivotGrid, Aggregator, RestProvider, ArrayProvider } from 'pivotgrid-js';
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Available exports: `PivotGrid`, `Aggregator`, `ColumnStore`, `DictionaryEncoder`,
|
|
248
|
+
`RestProvider`, `ArrayProvider`, `FieldZones`, `FilterManager`, `CacheManager`, `I18N`.
|
|
249
|
+
|
|
250
|
+
## License
|
|
251
|
+
|
|
252
|
+
Free for personal and non-commercial use.
|
|
253
|
+
For commercial use, a license is required — contact [korolevalexa@gmail.com](mailto:korolevalexa@gmail.com).
|