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
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/* ── Config Editor styles ─────────────────────────────────────────────────── */
|
|
2
|
+
|
|
3
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
4
|
+
|
|
5
|
+
body {
|
|
6
|
+
font-family: -apple-system, 'Segoe UI', sans-serif;
|
|
7
|
+
background: #f4f5f7;
|
|
8
|
+
color: #1a1a1a;
|
|
9
|
+
padding: 24px;
|
|
10
|
+
min-height: 100vh;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* ── Layout ── */
|
|
14
|
+
|
|
15
|
+
.editor-layout {
|
|
16
|
+
display: grid;
|
|
17
|
+
grid-template-columns: 1fr 1fr;
|
|
18
|
+
gap: 16px;
|
|
19
|
+
align-items: start;
|
|
20
|
+
}
|
|
21
|
+
@media (max-width: 1100px) { .editor-layout { grid-template-columns: 1fr; } }
|
|
22
|
+
|
|
23
|
+
.col-left, .col-right {
|
|
24
|
+
display: flex;
|
|
25
|
+
flex-direction: column;
|
|
26
|
+
gap: 16px;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* ── Card ── */
|
|
30
|
+
|
|
31
|
+
.card {
|
|
32
|
+
background: #fff;
|
|
33
|
+
border: 1px solid #e0e0e0;
|
|
34
|
+
border-radius: 8px;
|
|
35
|
+
padding: 16px;
|
|
36
|
+
}
|
|
37
|
+
.card-title {
|
|
38
|
+
font-size: 11px;
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
color: #999;
|
|
41
|
+
text-transform: uppercase;
|
|
42
|
+
letter-spacing: 0.05em;
|
|
43
|
+
margin-bottom: 12px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/* ── Form elements ── */
|
|
47
|
+
|
|
48
|
+
.field-label {
|
|
49
|
+
display: block;
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
color: #555;
|
|
52
|
+
margin-bottom: 4px;
|
|
53
|
+
margin-top: 12px;
|
|
54
|
+
}
|
|
55
|
+
.field-label:first-child { margin-top: 0; }
|
|
56
|
+
|
|
57
|
+
input[type="text"], textarea, select {
|
|
58
|
+
width: 100%;
|
|
59
|
+
padding: 6px 10px;
|
|
60
|
+
font-size: 12px;
|
|
61
|
+
border: 1px solid #d0d0d0;
|
|
62
|
+
border-radius: 6px;
|
|
63
|
+
background: #fff;
|
|
64
|
+
color: #333;
|
|
65
|
+
outline: none;
|
|
66
|
+
font-family: inherit;
|
|
67
|
+
}
|
|
68
|
+
input[type="text"]:focus, textarea:focus, select:focus { border-color: #1a73e8; }
|
|
69
|
+
textarea {
|
|
70
|
+
resize: vertical;
|
|
71
|
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
72
|
+
font-size: 12px;
|
|
73
|
+
line-height: 1.5;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* ── Buttons ── */
|
|
77
|
+
|
|
78
|
+
.btn {
|
|
79
|
+
padding: 6px 14px;
|
|
80
|
+
font-size: 12px;
|
|
81
|
+
border: 1px solid #d0d0d0;
|
|
82
|
+
border-radius: 6px;
|
|
83
|
+
background: #fff;
|
|
84
|
+
cursor: pointer;
|
|
85
|
+
color: #333;
|
|
86
|
+
transition: background 0.1s, border-color 0.1s;
|
|
87
|
+
white-space: nowrap;
|
|
88
|
+
}
|
|
89
|
+
.btn:hover:not(:disabled) { background: #f0f0f0; border-color: #bbb; }
|
|
90
|
+
.btn:disabled { opacity: 0.45; cursor: default; }
|
|
91
|
+
.btn-primary { background: #1a73e8; border-color: #1a73e8; color: #fff; }
|
|
92
|
+
.btn-primary:hover:not(:disabled) { background: #1558b0; }
|
|
93
|
+
.btn-row { display: flex; gap: 8px; margin-top: 12px; flex-wrap: wrap; }
|
|
94
|
+
|
|
95
|
+
/* ── Columns checklist ── */
|
|
96
|
+
.cols-list {
|
|
97
|
+
display: flex;
|
|
98
|
+
flex-direction: column;
|
|
99
|
+
border: 1px solid #e0e0e0;
|
|
100
|
+
border-radius: 6px;
|
|
101
|
+
overflow-y: auto;
|
|
102
|
+
max-height: 320px;
|
|
103
|
+
margin-top: 8px;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.cols-list-header,
|
|
107
|
+
.col-row {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 8px;
|
|
111
|
+
padding: 6px 8px;
|
|
112
|
+
border-bottom: 1px solid #f4f4f4;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.cols-list-header {
|
|
116
|
+
background: #fafafa;
|
|
117
|
+
border-bottom: 1px solid #e0e0e0;
|
|
118
|
+
position: sticky;
|
|
119
|
+
top: 0;
|
|
120
|
+
z-index: 1;
|
|
121
|
+
font-size: 11px;
|
|
122
|
+
font-weight: 600;
|
|
123
|
+
color: #999;
|
|
124
|
+
text-transform: uppercase;
|
|
125
|
+
letter-spacing: 0.04em;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.col-row {
|
|
129
|
+
margin-bottom: 4px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.col-db-name {
|
|
133
|
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
134
|
+
font-size: 11px;
|
|
135
|
+
color: #555;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.cols-list-header span:nth-child(1) { width: 24px; flex-shrink: 0; }
|
|
139
|
+
.cols-list-header span:nth-child(2) { flex: 0.5; }
|
|
140
|
+
.cols-list-header span:nth-child(3) { flex: 1; }
|
|
141
|
+
.cols-list-header span:nth-child(4) { width: 120px; flex-shrink: 0; }
|
|
142
|
+
.cols-list-header span:nth-child(5) { width: 120px; flex-shrink: 0; }
|
|
143
|
+
|
|
144
|
+
.col-row input[type="checkbox"] { width: 24px; flex-shrink: 0; cursor: pointer; }
|
|
145
|
+
.col-row .col-db-name { flex: 0.5; min-width: 0; }
|
|
146
|
+
.col-row input[type="text"] { flex: 1; min-width: 0; }
|
|
147
|
+
.col-row select:nth-of-type(1) { width: 120px; flex-shrink: 0; }
|
|
148
|
+
.col-row select:nth-of-type(2) { width: 120px; flex-shrink: 0; }
|
|
149
|
+
|
|
150
|
+
.col-row:hover { background: #f9fbff; }
|
|
151
|
+
.col-row.is-checked { background: #f5f8ff; }
|
|
152
|
+
|
|
153
|
+
/* ── Drag zones ── */
|
|
154
|
+
|
|
155
|
+
.zones-wrap {
|
|
156
|
+
display: flex;
|
|
157
|
+
gap: 8px;
|
|
158
|
+
flex-wrap: wrap;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.dz-zone {
|
|
162
|
+
display: flex;
|
|
163
|
+
flex-direction: column;
|
|
164
|
+
gap: 4px;
|
|
165
|
+
flex: 1;
|
|
166
|
+
min-width: 100px;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.dz-zone--free { flex: 2; }
|
|
170
|
+
.dz-zone--rows { flex: 1.5; }
|
|
171
|
+
.dz-zone--columns { flex: 1.5; }
|
|
172
|
+
.dz-zone--cache { flex: 1.5; }
|
|
173
|
+
|
|
174
|
+
.dz-zone-label {
|
|
175
|
+
font-size: 10px;
|
|
176
|
+
font-weight: 600;
|
|
177
|
+
color: #999;
|
|
178
|
+
text-transform: uppercase;
|
|
179
|
+
letter-spacing: 0.06em;
|
|
180
|
+
padding: 0 4px;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.dz-zone-body {
|
|
184
|
+
display: flex;
|
|
185
|
+
flex-wrap: wrap;
|
|
186
|
+
gap: 4px;
|
|
187
|
+
min-height: 36px;
|
|
188
|
+
padding: 4px 6px;
|
|
189
|
+
border: 1.5px dashed #d0d0d0;
|
|
190
|
+
border-radius: 6px;
|
|
191
|
+
background: #fff;
|
|
192
|
+
transition: background 0.15s, border-color 0.15s;
|
|
193
|
+
}
|
|
194
|
+
.dz-zone-body.dz-over {
|
|
195
|
+
background: #e8f0fe;
|
|
196
|
+
border-color: #1a73e8;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Chips */
|
|
200
|
+
.dz-chip {
|
|
201
|
+
display: inline-flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
gap: 4px;
|
|
204
|
+
padding: 3px 8px;
|
|
205
|
+
border: 1px solid #d0d0d0;
|
|
206
|
+
border-radius: 4px;
|
|
207
|
+
font-size: 12px;
|
|
208
|
+
color: #333;
|
|
209
|
+
background: #fff;
|
|
210
|
+
cursor: grab;
|
|
211
|
+
user-select: none;
|
|
212
|
+
white-space: nowrap;
|
|
213
|
+
transition: box-shadow 0.1s, border-color 0.1s;
|
|
214
|
+
}
|
|
215
|
+
.dz-chip:hover { border-color: #1a73e8; color: #1a73e8; }
|
|
216
|
+
|
|
217
|
+
[data-dz-zone="rows"] .dz-chip { background: #f0f4ff; border-color: #c5d3f7; color: #2c4bad; }
|
|
218
|
+
[data-dz-zone="columns"] .dz-chip { background: #f0fdf4; border-color: #a7d7b8; color: #1a6638; }
|
|
219
|
+
[data-dz-zone="cache"] .dz-chip { background: #f5f0ff; border-color: #c9b8f4; color: #5b21b6; }
|
|
220
|
+
|
|
221
|
+
.dz-chip--dragging { opacity: 0.3; cursor: grabbing; }
|
|
222
|
+
.dz-chip--ghost { cursor: grabbing; box-shadow: 0 4px 12px rgba(0,0,0,0.15); opacity: 0.9; }
|
|
223
|
+
|
|
224
|
+
.dz-chip-remove {
|
|
225
|
+
font-size: 13px;
|
|
226
|
+
line-height: 1;
|
|
227
|
+
color: #bbb;
|
|
228
|
+
cursor: pointer;
|
|
229
|
+
padding: 0 1px;
|
|
230
|
+
}
|
|
231
|
+
.dz-chip-remove:hover { color: #e53935; }
|
|
232
|
+
|
|
233
|
+
.dz-placeholder {
|
|
234
|
+
width: 3px;
|
|
235
|
+
height: 24px;
|
|
236
|
+
background: #1a73e8;
|
|
237
|
+
border-radius: 2px;
|
|
238
|
+
pointer-events: none;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/* ── Config preview ── */
|
|
242
|
+
|
|
243
|
+
.config-preview {
|
|
244
|
+
font-family: 'SF Mono', 'Fira Code', monospace;
|
|
245
|
+
font-size: 11px;
|
|
246
|
+
line-height: 1.6;
|
|
247
|
+
background: #1e1e2e;
|
|
248
|
+
color: #cdd6f4;
|
|
249
|
+
border: 1px solid #313244;
|
|
250
|
+
border-radius: 6px;
|
|
251
|
+
padding: 12px;
|
|
252
|
+
resize: vertical;
|
|
253
|
+
width: 100%;
|
|
254
|
+
height: 600px;
|
|
255
|
+
outline: none;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* ── Status ── */
|
|
259
|
+
|
|
260
|
+
.status {
|
|
261
|
+
font-size: 12px;
|
|
262
|
+
padding: 6px 10px;
|
|
263
|
+
border-radius: 5px;
|
|
264
|
+
margin-top: 8px;
|
|
265
|
+
display: none;
|
|
266
|
+
}
|
|
267
|
+
.status.ok { background: #f0fdf4; color: #1a6638; border: 1px solid #a7d7b8; display: block; }
|
|
268
|
+
.status.error { background: #fff3f3; color: #c00; border: 1px solid #fcc; display: block; }
|
|
269
|
+
|
|
270
|
+
/* ── Empty ── */
|
|
271
|
+
|
|
272
|
+
.fields-empty {
|
|
273
|
+
padding: 20px;
|
|
274
|
+
text-align: center;
|
|
275
|
+
color: #bbb;
|
|
276
|
+
font-size: 12px;
|
|
277
|
+
font-style: italic;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* ── Spinner ── */
|
|
281
|
+
|
|
282
|
+
.spinner {
|
|
283
|
+
display: inline-block;
|
|
284
|
+
width: 12px; height: 12px;
|
|
285
|
+
border: 2px solid #d0d0d0;
|
|
286
|
+
border-top-color: #1a73e8;
|
|
287
|
+
border-radius: 50%;
|
|
288
|
+
animation: spin 0.6s linear infinite;
|
|
289
|
+
vertical-align: middle;
|
|
290
|
+
margin-right: 6px;
|
|
291
|
+
}
|
|
292
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
293
|
+
|
|
294
|
+
.col-right .card { position: sticky; top: 24px; }
|
|
295
|
+
|
|
296
|
+
.col-row select:disabled {
|
|
297
|
+
opacity: 0.15;
|
|
298
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Config Editor for PivotGrid</title>
|
|
7
|
+
<link rel="stylesheet" href="config-editor.css">
|
|
8
|
+
</head>
|
|
9
|
+
|
|
10
|
+
<body data-lang="en">
|
|
11
|
+
<div class="editor-layout">
|
|
12
|
+
|
|
13
|
+
<!-- ── Left column ── -->
|
|
14
|
+
<div class="col-left">
|
|
15
|
+
|
|
16
|
+
<!-- Server -->
|
|
17
|
+
<div class="card">
|
|
18
|
+
<div class="card-title" data-i18n="ce_server"></div>
|
|
19
|
+
<label class="field-label">URL</label>
|
|
20
|
+
<input type="text" id="server-url" value="http://localhost:8000">
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<!-- Database -->
|
|
24
|
+
<div class="card">
|
|
25
|
+
<div class="card-title" data-i18n="ce_database"></div>
|
|
26
|
+
|
|
27
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
|
|
28
|
+
<div style="grid-column:1/-1">
|
|
29
|
+
<label class="field-label" data-i18n="ce_connector"></label>
|
|
30
|
+
<select id="db-connector"></select>
|
|
31
|
+
</div>
|
|
32
|
+
<div>
|
|
33
|
+
<label class="field-label">Host</label>
|
|
34
|
+
<input type="text" id="db-host" placeholder="localhost">
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
<label class="field-label">Port</label>
|
|
38
|
+
<input type="text" id="db-port" placeholder="5432">
|
|
39
|
+
</div>
|
|
40
|
+
<div>
|
|
41
|
+
<label class="field-label">Database</label>
|
|
42
|
+
<input type="text" id="db-name" placeholder="postgres">
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<label class="field-label">User</label>
|
|
46
|
+
<input type="text" id="db-user" placeholder="postgres">
|
|
47
|
+
</div>
|
|
48
|
+
<div style="grid-column:1/-1">
|
|
49
|
+
<label class="field-label">Password</label>
|
|
50
|
+
<input type="password" id="db-password" placeholder="••••••••">
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
<div class="btn-row">
|
|
55
|
+
<button class="btn btn-primary" id="btn-save-db" data-i18n="ce_save"></button>
|
|
56
|
+
<button class="btn" id="btn-load-db" data-i18n="ce_loadFromServer"></button>
|
|
57
|
+
<button class="btn" id="btn-test-db" data-i18n="ce_testConnection"></button>
|
|
58
|
+
</div>
|
|
59
|
+
<div class="status" id="db-status"></div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- Query -->
|
|
63
|
+
<div class="card">
|
|
64
|
+
<div class="card-title" data-i18n="ce_query"></div>
|
|
65
|
+
<label class="field-label" data-i18n="ce_mainQuery"></label>
|
|
66
|
+
<textarea id="main-query" rows="5" placeholder="SELECT * FROM sales_data"></textarea>
|
|
67
|
+
<label class="field-label" data-i18n="ce_colsQuery"></label>
|
|
68
|
+
<textarea id="cols-query" rows="3"></textarea>
|
|
69
|
+
<label class="field-label" data-i18n="ce_funcs"></label>
|
|
70
|
+
<div id="funcs-wrap" style="display:flex;gap:12px;flex-wrap:wrap;font-size:12px;margin-bottom:4px;">
|
|
71
|
+
<label><input type="checkbox" value="sum" checked> sum</label>
|
|
72
|
+
<label><input type="checkbox" value="avg" checked> avg</label>
|
|
73
|
+
<label><input type="checkbox" value="count" checked> count</label>
|
|
74
|
+
<label><input type="checkbox" value="min" checked> min</label>
|
|
75
|
+
<label><input type="checkbox" value="max" checked> max</label>
|
|
76
|
+
<label><input type="checkbox" value="stddev"> stddev</label>
|
|
77
|
+
<label><input type="checkbox" value="variance"> variance</label>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="btn-row">
|
|
80
|
+
<button class="btn btn-primary" id="btn-fetch-cols" data-i18n="ce_fetchCols"></button>
|
|
81
|
+
</div>
|
|
82
|
+
<div class="status" id="fetch-status"></div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<!-- Drillthrough -->
|
|
86
|
+
<div class="card">
|
|
87
|
+
<div class="card-title" data-i18n="ce_drillthrough"></div>
|
|
88
|
+
|
|
89
|
+
<div style="display:flex;gap:16px;margin-bottom:12px;">
|
|
90
|
+
<label style="display:flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;">
|
|
91
|
+
<input type="radio" name="dt-type" value="sql" checked> SQL
|
|
92
|
+
</label>
|
|
93
|
+
<label style="display:flex;align-items:center;gap:6px;font-size:12px;cursor:pointer;">
|
|
94
|
+
<input type="radio" name="dt-type" value="url"> URL
|
|
95
|
+
</label>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<div id="dt-sql-wrap">
|
|
99
|
+
<label class="field-label" data-i18n="ce_dtSqlLabel"></label>
|
|
100
|
+
<textarea id="dt-query" rows="4" placeholder="SELECT * FROM sales_data WHERE {filters} LIMIT 200"></textarea>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
<div id="dt-url-wrap" style="display:none">
|
|
104
|
+
<label class="field-label" data-i18n="ce_dtUrlLabel"></label>
|
|
105
|
+
<input type="text" id="dt-url" placeholder="https://myapp.com/details">
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<!-- Column list with checkboxes -->
|
|
110
|
+
<div class="card">
|
|
111
|
+
<div class="card-title" data-i18n="ce_cols"></div>
|
|
112
|
+
<div id="cols-wrap">
|
|
113
|
+
<div class="fields-empty" data-i18n="ce_emptyFields"></div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<!-- Initial state — drag zones -->
|
|
118
|
+
<div class="card">
|
|
119
|
+
<div class="card-title" data-i18n="ce_initialState"></div>
|
|
120
|
+
<div class="zones-wrap">
|
|
121
|
+
|
|
122
|
+
<div class="dz-zone dz-zone--free">
|
|
123
|
+
<div class="dz-zone-label" data-i18n="fields"></div>
|
|
124
|
+
<div class="dz-zone-body" id="dz-free" data-dz-zone="free"></div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
127
|
+
<div class="dz-zone dz-zone--rows">
|
|
128
|
+
<div class="dz-zone-label" data-i18n="rows"></div>
|
|
129
|
+
<div class="dz-zone-body" id="dz-rows" data-dz-zone="rows"></div>
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div class="dz-zone dz-zone--columns">
|
|
133
|
+
<div class="dz-zone-label" data-i18n="columns"></div>
|
|
134
|
+
<div class="dz-zone-body" id="dz-columns" data-dz-zone="columns"></div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
137
|
+
<div class="dz-zone dz-zone--cache">
|
|
138
|
+
<div class="dz-zone-label" data-i18n="cache"></div>
|
|
139
|
+
<div class="dz-zone-body" id="dz-cache" data-dz-zone="cache"></div>
|
|
140
|
+
</div>
|
|
141
|
+
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<!-- Additional parameters -->
|
|
145
|
+
<div style="display:flex;gap:12px;margin-top:12px;flex-wrap:wrap;">
|
|
146
|
+
<div style="display:flex;flex-direction:column;gap:4px;flex:1;min-width:120px;">
|
|
147
|
+
<label class="field-label"
|
|
148
|
+
style="margin:0;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.04em;"
|
|
149
|
+
data-i18n="measure"></label>
|
|
150
|
+
<select id="init-measure"></select>
|
|
151
|
+
</div>
|
|
152
|
+
<div style="display:flex;flex-direction:column;gap:4px;flex:1;min-width:120px;">
|
|
153
|
+
<label class="field-label"
|
|
154
|
+
style="margin:0;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.04em;"
|
|
155
|
+
data-i18n="func"></label>
|
|
156
|
+
<select id="init-func"></select>
|
|
157
|
+
</div>
|
|
158
|
+
<div style="display:flex;flex-direction:column;gap:4px;flex:1;min-width:120px;">
|
|
159
|
+
<label class="field-label"
|
|
160
|
+
style="margin:0;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.04em;"
|
|
161
|
+
data-i18n="ce_maxCacheRows"></label>
|
|
162
|
+
<input type="text" id="init-max-rows" value="500000">
|
|
163
|
+
</div>
|
|
164
|
+
<div style="display:flex;flex-direction:column;gap:4px;flex:1;min-width:120px;">
|
|
165
|
+
<label class="field-label"
|
|
166
|
+
style="margin:0;font-size:11px;font-weight:600;color:#999;text-transform:uppercase;letter-spacing:.04em;"
|
|
167
|
+
data-i18n="ce_filterLimit"></label>
|
|
168
|
+
<input type="text" id="init-filter-limit" value="30">
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
|
|
173
|
+
</div>
|
|
174
|
+
|
|
175
|
+
<!-- ── Right column ── -->
|
|
176
|
+
<div class="col-right">
|
|
177
|
+
<div class="card">
|
|
178
|
+
<div class="card-title" data-i18n="ce_configJs"></div>
|
|
179
|
+
<div style="display:flex;gap:8px;margin-bottom:12px;align-items:center;">
|
|
180
|
+
<select id="sel-config-name" style="flex:1">
|
|
181
|
+
<option value="" data-i18n="ce_selectConfig"></option>
|
|
182
|
+
</select>
|
|
183
|
+
<button class="btn" id="btn-new-config" data-i18n="ce_newConfig"></button>
|
|
184
|
+
<button class="btn" id="btn-delete-config" data-i18n="ce_deleteConfig" style="color:#c00;border-color:#fcc;"
|
|
185
|
+
disabled></button>
|
|
186
|
+
<input type="text" id="inp-config-name" data-i18n-placeholder="ce_configName" style="flex:1">
|
|
187
|
+
<button class="btn btn-primary" id="btn-save-config" data-i18n="ce_saveConfig"></button>
|
|
188
|
+
</div>
|
|
189
|
+
<textarea class="config-preview" id="config-preview" readonly spellcheck="false"></textarea>
|
|
190
|
+
<div class="btn-row">
|
|
191
|
+
<button class="btn" id="btn-preview" data-i18n="ce_preview"></button>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
</div>
|
|
197
|
+
|
|
198
|
+
<script src="../widget/i18n.js"></script>
|
|
199
|
+
<script src="config-editor.js"></script>
|
|
200
|
+
</body>
|
|
201
|
+
|
|
202
|
+
</html>
|