@internetstiftelsen/styleguide 5.1.15 → 5.1.16
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.
|
@@ -76,120 +76,353 @@ function _interop_require_wildcard(obj, nodeInterop) {
|
|
|
76
76
|
_aggridcommunity.ModuleRegistry.registerModules([
|
|
77
77
|
_aggridcommunity.AllCommunityModule
|
|
78
78
|
]);
|
|
79
|
-
//
|
|
79
|
+
// ---- THEME -----------------------------------------------------------
|
|
80
80
|
const iisTheme = _aggridcommunity.themeQuartz.withPart(_aggridcommunity.iconSetMaterial).withParams({
|
|
81
|
-
accentColor:
|
|
82
|
-
backgroundColor:
|
|
81
|
+
accentColor: '#0477CE',
|
|
82
|
+
backgroundColor: '#FFFFFF',
|
|
83
83
|
borderRadius: 3,
|
|
84
|
-
browserColorScheme:
|
|
85
|
-
cellTextColor:
|
|
84
|
+
browserColorScheme: 'light',
|
|
85
|
+
cellTextColor: '#1F2A36',
|
|
86
86
|
chromeBackgroundColor: {
|
|
87
|
-
ref:
|
|
87
|
+
ref: 'foregroundColor',
|
|
88
88
|
mix: 0.07,
|
|
89
|
-
onto:
|
|
89
|
+
onto: 'backgroundColor'
|
|
90
90
|
},
|
|
91
|
-
fontFamily:
|
|
91
|
+
fontFamily: 'inherit',
|
|
92
92
|
fontSize: 16,
|
|
93
|
-
foregroundColor:
|
|
94
|
-
headerBackgroundColor:
|
|
95
|
-
headerFontFamily:
|
|
93
|
+
foregroundColor: '#1F2A36',
|
|
94
|
+
headerBackgroundColor: '#D8D8D8',
|
|
95
|
+
headerFontFamily: 'inherit',
|
|
96
96
|
headerFontSize: 16,
|
|
97
97
|
headerFontWeight: 400,
|
|
98
|
-
headerTextColor:
|
|
99
|
-
oddRowBackgroundColor:
|
|
98
|
+
headerTextColor: '#1F2A36',
|
|
99
|
+
oddRowBackgroundColor: '#EDEDED',
|
|
100
100
|
wrapperBorderRadius: 3
|
|
101
101
|
});
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
sortable: true,
|
|
112
|
-
filter: true
|
|
102
|
+
// ---- RENDERERS -------------------------------------------------------
|
|
103
|
+
const renderStatusIcon = (params)=>{
|
|
104
|
+
const status = params.value;
|
|
105
|
+
if (!status) return '';
|
|
106
|
+
const map = {
|
|
107
|
+
passed: {
|
|
108
|
+
icon: '#icon-security-variant',
|
|
109
|
+
color: '#25c279',
|
|
110
|
+
label: 'Passed'
|
|
113
111
|
},
|
|
114
|
-
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
filter: 'agNumberColumnFilter',
|
|
119
|
-
width: 120
|
|
112
|
+
failed: {
|
|
113
|
+
icon: '#icon-unsecure-variant',
|
|
114
|
+
color: '#d9002f',
|
|
115
|
+
label: 'Failed'
|
|
120
116
|
},
|
|
121
|
-
{
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
117
|
+
warning: {
|
|
118
|
+
icon: '#icon-warning-variant',
|
|
119
|
+
color: '#f99963',
|
|
120
|
+
label: 'Warning'
|
|
121
|
+
},
|
|
122
|
+
error: {
|
|
123
|
+
icon: '#icon-unsecure-variant',
|
|
124
|
+
color: '#8E9297',
|
|
125
|
+
label: 'Error'
|
|
126
|
+
},
|
|
127
|
+
not_tested: {
|
|
128
|
+
icon: '#icon-unsecure-variant',
|
|
129
|
+
color: '#d8d8d8',
|
|
130
|
+
label: 'Not tested'
|
|
127
131
|
},
|
|
132
|
+
informational: {
|
|
133
|
+
icon: '#icon-info-variant',
|
|
134
|
+
color: '#50b2fc',
|
|
135
|
+
label: 'Informational'
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const { icon, color, label } = map[status] || {};
|
|
139
|
+
return icon ? `<span class="cell-center">
|
|
140
|
+
<svg class="status-icon" fill="${color}" width="20" height="20" aria-label="${label}">
|
|
141
|
+
<use xlink:href="${icon}"></use>
|
|
142
|
+
</svg>
|
|
143
|
+
<span class="status-text">${label}</span>
|
|
144
|
+
</span>` : status;
|
|
145
|
+
};
|
|
146
|
+
// ---- HELPERS ---------------------------------------------------------
|
|
147
|
+
const titleCase = (s)=>s.replace(/[_\-\.]+/g, ' ').replace(/\b\w/g, (c)=>c.toUpperCase());
|
|
148
|
+
function buildColumnDefsFromData(data) {
|
|
149
|
+
if (!Array.isArray(data) || data.length === 0) return [
|
|
128
150
|
{
|
|
151
|
+
headerName: 'No Data',
|
|
152
|
+
field: 'noData'
|
|
153
|
+
}
|
|
154
|
+
];
|
|
155
|
+
const sample = data[0];
|
|
156
|
+
// Internet.nl-like shape
|
|
157
|
+
if (sample && sample.results && typeof sample.results === 'object') {
|
|
158
|
+
const base = [
|
|
159
|
+
{
|
|
160
|
+
headerName: 'Domain',
|
|
161
|
+
field: 'domain',
|
|
162
|
+
minWidth: 200
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
headerName: 'Score (%)',
|
|
166
|
+
field: 'score_percent',
|
|
167
|
+
filter: 'agNumberColumnFilter',
|
|
168
|
+
minWidth: 140
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
headerName: 'Report',
|
|
172
|
+
field: 'report_url',
|
|
173
|
+
cellRenderer: (p)=>p.value ? `<a href="${p.value}" target="_blank" rel="noopener">View</a>` : '',
|
|
174
|
+
maxWidth: 220,
|
|
175
|
+
flex: 0
|
|
176
|
+
}
|
|
177
|
+
];
|
|
178
|
+
const resultKeys = Object.keys(sample.results);
|
|
179
|
+
const childColIds = [];
|
|
180
|
+
const children = resultKeys.map((k, idx)=>{
|
|
181
|
+
const colId = `results.${k}.status`;
|
|
182
|
+
childColIds.push(colId);
|
|
183
|
+
return {
|
|
184
|
+
colId,
|
|
185
|
+
headerName: titleCase(k),
|
|
186
|
+
field: colId,
|
|
187
|
+
cellRenderer: renderStatusIcon,
|
|
188
|
+
tooltipValueGetter: (p)=>{
|
|
189
|
+
var _p_data_results_k, _p_data_results, _p_data;
|
|
190
|
+
const since = p == null ? void 0 : (_p_data = p.data) == null ? void 0 : (_p_data_results = _p_data.results) == null ? void 0 : (_p_data_results_k = _p_data_results[k]) == null ? void 0 : _p_data_results_k.since;
|
|
191
|
+
return since ? `Since: ${since}` : '';
|
|
192
|
+
},
|
|
193
|
+
cellClass: (p)=>`status-${p.value}`,
|
|
194
|
+
minWidth: 150,
|
|
195
|
+
sortable: true,
|
|
196
|
+
filter: true,
|
|
197
|
+
hide: idx > 0
|
|
198
|
+
};
|
|
199
|
+
});
|
|
200
|
+
base.push({
|
|
129
201
|
headerName: 'Results',
|
|
130
|
-
|
|
202
|
+
headerGroupComponent: 'ExpandHeader',
|
|
203
|
+
headerGroupComponentParams: {
|
|
204
|
+
childColIds,
|
|
205
|
+
startExpanded: false
|
|
206
|
+
},
|
|
207
|
+
children
|
|
208
|
+
});
|
|
209
|
+
return base;
|
|
210
|
+
}
|
|
211
|
+
// Generic fallback
|
|
212
|
+
const cols = [];
|
|
213
|
+
for (const [key, val] of Object.entries(sample)){
|
|
214
|
+
if (val && typeof val === 'object' && !Array.isArray(val)) {
|
|
215
|
+
for (const subKey of Object.keys(val)){
|
|
216
|
+
if (val[subKey] !== null && typeof val[subKey] !== 'object') {
|
|
217
|
+
cols.push({
|
|
218
|
+
headerName: `${titleCase(key)} • ${titleCase(subKey)}`,
|
|
219
|
+
field: `${key}.${subKey}`,
|
|
220
|
+
sortable: true,
|
|
221
|
+
filter: true,
|
|
222
|
+
minWidth: 140
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
cols.push({
|
|
228
|
+
headerName: titleCase(key),
|
|
229
|
+
field: key,
|
|
230
|
+
sortable: true,
|
|
231
|
+
filter: true,
|
|
232
|
+
minWidth: 120
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return cols;
|
|
237
|
+
}
|
|
238
|
+
// Version-safe column state helper
|
|
239
|
+
function setColumnsState(params, { state = [], defaultState = {
|
|
240
|
+
hide: false,
|
|
241
|
+
pinned: null
|
|
242
|
+
} }) {
|
|
243
|
+
const columnApi = params.columnApi || (params.api && typeof params.api.getColumnApi === 'function' ? params.api.getColumnApi() : null);
|
|
244
|
+
if (columnApi && typeof columnApi.applyColumnState === 'function') {
|
|
245
|
+
columnApi.applyColumnState({
|
|
246
|
+
state,
|
|
247
|
+
defaultState
|
|
248
|
+
});
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
if (params.api && typeof params.api.applyColumnState === 'function') {
|
|
252
|
+
params.api.applyColumnState({
|
|
253
|
+
state,
|
|
254
|
+
defaultState
|
|
255
|
+
});
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (columnApi && typeof columnApi.setColumnState === 'function') {
|
|
259
|
+
if (typeof columnApi.resetColumnState === 'function') columnApi.resetColumnState();
|
|
260
|
+
columnApi.setColumnState(state);
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
console.warn('No applicable column state API found in this AG Grid version.');
|
|
264
|
+
}
|
|
265
|
+
// Per-grid responsive visibility
|
|
266
|
+
function applyResponsiveVisibility(params, el) {
|
|
267
|
+
const w = (el == null ? void 0 : el.getBoundingClientRect().width) || (el == null ? void 0 : el.clientWidth) || 0;
|
|
268
|
+
if (w < 520) {
|
|
269
|
+
setColumnsState(params, {
|
|
270
|
+
state: [
|
|
131
271
|
{
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
sortable: true,
|
|
135
|
-
filter: true,
|
|
136
|
-
cellClass: (params)=>`status-${params.value}`
|
|
272
|
+
colId: 'domain',
|
|
273
|
+
pinned: 'left'
|
|
137
274
|
},
|
|
138
275
|
{
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
sortable: true,
|
|
142
|
-
filter: true,
|
|
143
|
-
cellClass: (params)=>`status-${params.value}`
|
|
276
|
+
colId: 'results.rpki.status',
|
|
277
|
+
hide: true
|
|
144
278
|
},
|
|
145
279
|
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
sortable: true,
|
|
149
|
-
filter: true,
|
|
150
|
-
cellClass: (params)=>`status-${params.value}`
|
|
280
|
+
colId: 'results.security_options.status',
|
|
281
|
+
hide: true
|
|
151
282
|
},
|
|
152
283
|
{
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
284
|
+
colId: 'results.ipv6.status',
|
|
285
|
+
hide: true
|
|
286
|
+
}
|
|
287
|
+
]
|
|
288
|
+
});
|
|
289
|
+
} else if (w < 760) {
|
|
290
|
+
setColumnsState(params, {
|
|
291
|
+
state: [
|
|
292
|
+
{
|
|
293
|
+
colId: 'domain',
|
|
294
|
+
pinned: null
|
|
158
295
|
},
|
|
159
296
|
{
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
sortable: true,
|
|
163
|
-
filter: true,
|
|
164
|
-
cellClass: (params)=>`status-${params.value}`
|
|
297
|
+
colId: 'results.rpki.status',
|
|
298
|
+
hide: true
|
|
165
299
|
}
|
|
166
300
|
]
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
function setWidthAndHeight(size) {
|
|
174
|
-
const eGridDiv = document.querySelector("#myGrid");
|
|
175
|
-
eGridDiv.style.setProperty("width", size);
|
|
176
|
-
eGridDiv.style.setProperty("height", size);
|
|
301
|
+
});
|
|
302
|
+
} else {
|
|
303
|
+
setColumnsState(params, {
|
|
304
|
+
state: []
|
|
305
|
+
});
|
|
306
|
+
}
|
|
177
307
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
308
|
+
// ---- EXPAND/COLLAPSE GROUP HEADER -----------------------------------
|
|
309
|
+
class ExpandHeader {
|
|
310
|
+
init(params) {
|
|
311
|
+
this.params = params;
|
|
312
|
+
this.childColIds = params.childColIds || [];
|
|
313
|
+
this.expanded = !!params.startExpanded;
|
|
314
|
+
// Debug: prove we mounted
|
|
315
|
+
console.log('[ExpandHeader] init for group:', params.displayName, 'children:', this.childColIds);
|
|
316
|
+
// Create a full-width, clickable label (no AG classes needed)
|
|
317
|
+
const e = document.createElement('div');
|
|
318
|
+
e.className = 'expand-header';
|
|
319
|
+
e.style.cssText = 'display:flex;align-items:center;gap:6px;cursor:pointer;width:100%;';
|
|
320
|
+
var _params_displayName;
|
|
321
|
+
e.innerHTML = `
|
|
322
|
+
<span class="expander" style="display:inline-block;transition:transform .15s">▶</span>
|
|
323
|
+
<span class="title">${(_params_displayName = params.displayName) != null ? _params_displayName : 'Group'}</span>
|
|
324
|
+
`;
|
|
325
|
+
e.addEventListener('click', ()=>{
|
|
326
|
+
this.expanded = !this.expanded;
|
|
327
|
+
this.updateIcon();
|
|
328
|
+
toggleChildColumnsVisibility(params, this.childColIds, this.expanded);
|
|
329
|
+
});
|
|
330
|
+
this.eGui = e;
|
|
331
|
+
this.updateIcon();
|
|
332
|
+
// Apply initial expanded state
|
|
333
|
+
if (this.expanded) {
|
|
334
|
+
toggleChildColumnsVisibility(params, this.childColIds, true);
|
|
189
335
|
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
336
|
+
}
|
|
337
|
+
updateIcon() {
|
|
338
|
+
const icon = this.eGui.querySelector('.expander');
|
|
339
|
+
if (icon) icon.style.transform = this.expanded ? 'rotate(90deg)' : 'rotate(0deg)';
|
|
340
|
+
}
|
|
341
|
+
getGui() {
|
|
342
|
+
return this.eGui;
|
|
343
|
+
}
|
|
344
|
+
refresh() {
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
function toggleChildColumnsVisibility(params, colIds, makeVisible) {
|
|
349
|
+
var _params_api_sizeColumnsToFit, _params_api;
|
|
350
|
+
const columnApi = params.columnApi || (params.api && typeof params.api.getColumnApi === 'function' ? params.api.getColumnApi() : null);
|
|
351
|
+
if (!columnApi) return;
|
|
352
|
+
columnApi.setColumnsVisible(colIds, !!makeVisible);
|
|
353
|
+
(_params_api = params.api) == null ? void 0 : (_params_api_sizeColumnsToFit = _params_api.sizeColumnsToFit) == null ? void 0 : _params_api_sizeColumnsToFit.call(_params_api);
|
|
354
|
+
}
|
|
355
|
+
// Factory to create per-grid options with the correct closures
|
|
356
|
+
function makeGridOptionsFor(el) {
|
|
357
|
+
return {
|
|
358
|
+
theme: iisTheme,
|
|
359
|
+
components: {
|
|
360
|
+
ExpandHeader
|
|
361
|
+
},
|
|
362
|
+
defaultColDef: {
|
|
363
|
+
resizable: true,
|
|
364
|
+
sortable: true,
|
|
365
|
+
filter: true,
|
|
366
|
+
flex: 1,
|
|
367
|
+
minWidth: 150,
|
|
368
|
+
unSortIcon: true
|
|
369
|
+
},
|
|
370
|
+
columnDefs: [],
|
|
371
|
+
rowData: [],
|
|
372
|
+
onGridReady (params) {
|
|
373
|
+
return _async_to_generator(function*() {
|
|
374
|
+
try {
|
|
375
|
+
// dynamic JSON import based on *this* element's data attribute
|
|
376
|
+
const attr = el.dataset.json || './table.json';
|
|
377
|
+
const jsonUrl = new URL(attr, require("url").pathToFileURL(__filename).toString()).toString();
|
|
378
|
+
const mod = yield Promise.resolve(/* @vite-ignore */ jsonUrl).then((p)=>/*#__PURE__*/ _interop_require_wildcard(require(p)));
|
|
379
|
+
var _mod_default;
|
|
380
|
+
const data = (_mod_default = mod == null ? void 0 : mod.default) != null ? _mod_default : mod;
|
|
381
|
+
const cols = buildColumnDefsFromData(data);
|
|
382
|
+
params.api.setGridOption('columnDefs', cols);
|
|
383
|
+
params.api.setGridOption('rowData', data);
|
|
384
|
+
applyResponsiveVisibility(params, el);
|
|
385
|
+
params.api.sizeColumnsToFit();
|
|
386
|
+
} catch (e) {
|
|
387
|
+
console.error('Dynamic JSON import failed for grid:', el, e);
|
|
388
|
+
}
|
|
389
|
+
})();
|
|
390
|
+
},
|
|
391
|
+
onGridSizeChanged (params) {
|
|
392
|
+
applyResponsiveVisibility(params, el);
|
|
393
|
+
params.api.sizeColumnsToFit();
|
|
394
|
+
},
|
|
395
|
+
animateRows: true
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
// ---- INIT ALL GRIDS --------------------------------------------------
|
|
399
|
+
document.addEventListener('DOMContentLoaded', ()=>{
|
|
400
|
+
// Use a class selector so you can have multiple grids;
|
|
401
|
+
// make sure your HTML uses: <div class="ag-theme-quartz js-ag-grid" data-json="./table1.json"></div>
|
|
402
|
+
const containers = document.querySelectorAll('.js-ag-grid');
|
|
403
|
+
containers.forEach((el)=>{
|
|
404
|
+
// Ensure theme class + measurable size BEFORE createGrid (each grid separately)
|
|
405
|
+
if (!el.classList.contains('ag-theme-quartz')) el.classList.add('ag-theme-quartz');
|
|
406
|
+
//if (!el.style.height) el.style.height = '600px';
|
|
407
|
+
if (!el.style.width) el.style.width = '100%';
|
|
408
|
+
const gridOptions = makeGridOptionsFor(el);
|
|
409
|
+
const api = _aggridcommunity.createGrid(el, gridOptions);
|
|
410
|
+
// Per-grid ResizeObserver (don’t reuse one global API)
|
|
411
|
+
const ro = new ResizeObserver(()=>{
|
|
412
|
+
var _gridOptions_api, _gridOptions_api1;
|
|
413
|
+
(_gridOptions_api = gridOptions.api) == null ? void 0 : _gridOptions_api.onGridSizeChanged();
|
|
414
|
+
(_gridOptions_api1 = gridOptions.api) == null ? void 0 : _gridOptions_api1.sizeColumnsToFit();
|
|
415
|
+
});
|
|
416
|
+
ro.observe(el);
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
// ---- TOGGLE FULLSCREEN CLASS ON PARENT CONTAINER WHEN CLICKING FULLSCREEN BUTTON ----
|
|
420
|
+
document.querySelectorAll('[data-ag-grid-fullscreen]').forEach((btn)=>{
|
|
421
|
+
btn.addEventListener('click', (e)=>{
|
|
422
|
+
// Find the nearest parent container for this button
|
|
423
|
+
const gridEl = btn.closest('.js-ag-grid');
|
|
424
|
+
if (!gridEl) return;
|
|
425
|
+
// Toggle fullscreen class only for this specific element
|
|
426
|
+
gridEl.classList.toggle('has-fullscreen');
|
|
427
|
+
});
|
|
195
428
|
});
|