@datalabz_/dashboard-kit 6.0.3 → 6.0.4

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.
Files changed (5) hide show
  1. package/README.md +14 -7
  2. package/package.json +1 -1
  3. package/v4.js +1 -1
  4. package/v5.js +1 -1
  5. package/v6.js +41 -15
package/README.md CHANGED
@@ -57,8 +57,8 @@ URLs already pinned by live dashboards.
57
57
 
58
58
  A parent may post `{ type: 'DK_GET_FILTERS_INFO' }` to a dashboard's frame; the kit answers the parent with
59
59
  `{ type: 'DK_FILTERS_INFO', filters: [...] }`. It needs no token or period, so a parent can ask as soon as
60
- the frame has loaded. The list is the controls in the dashboard's header — what it can be opened
61
- with — one entry each:
60
+ the frame has loaded. The list is the header controls the dashboard can be opened with, which is
61
+ what the kit can write into a header control at its first boot, one entry each:
62
62
 
63
63
  ```js
64
64
  { id: 'playerUsername', label: 'Player username', type: 'text', // type: the input's type, 'select' or 'textarea'
@@ -69,11 +69,18 @@ with — one entry each:
69
69
  options: [{ value: 'BRL', label: 'Real' }] } // select only: the first 100 options
70
70
  ```
71
71
 
72
- The whole header is read, so a control the dashboard adds to it after `init` is listed too. Left
73
- out: a control with no `id`, a second control with an `id` already listed, a password field, and
74
- radio, file, hidden and button controls, which the kit cannot fill. A select's options are those
75
- it has when asked: one the dashboard fills by a query later has none yet, and `optionsTotal` says how
76
- many there were. The answer always goes to the dashboard's parent, whoever asked.
72
+ The list follows the fill, so it holds only what a filter can actually be given:
73
+
74
+ - Left out: a control with no `id`, a second control with an `id` already listed, and radio, file,
75
+ hidden, password and button controls, which the kit refuses to fill.
76
+ - A select lists only options with a value, since an empty value is refused, and `optionsTotal` counts
77
+ those. A select with none is left out: it takes no value.
78
+ - What exists when the dashboard boots is what counts. Once it has booted, the answer is the list taken
79
+ at that moment, so options a section loads later by query, and controls added later, are not in it, as
80
+ they were not there for the fill. Only `value` and `disabled` are read again. A filter whose options
81
+ come from a query must therefore use static `<option>`s or a plain input to be openable.
82
+
83
+ The answer always goes to the dashboard's parent, whoever asked.
77
84
 
78
85
  ## Rules
79
86
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalabz_/dashboard-kit",
3
- "version": "6.0.3",
3
+ "version": "6.0.4",
4
4
  "description": "DashboardKit runtime + styles, served from jsDelivr",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
package/v4.js CHANGED
@@ -20,7 +20,7 @@
20
20
  let _activeTabId = '';
21
21
  let _sections = []; // { id, label, load, loaded, errors }
22
22
  let _title = '';
23
- let _gitVer = '8ed9062'; // replaced at deploy: sed -i "s/8ed9062/$(git rev-parse --short HEAD)/g" v4.js
23
+ let _gitVer = 'ce29793'; // replaced at deploy: sed -i "s/ce29793/$(git rev-parse --short HEAD)/g" v4.js
24
24
  let _calls = []; // System Info call log
25
25
  let _sectionErrors = {}; // sectionId → error count
26
26
  let _generation = 0;
package/v5.js CHANGED
@@ -20,7 +20,7 @@
20
20
  let _activeTabId = '';
21
21
  let _sections = []; // { id, label, load, loaded, errors }
22
22
  let _title = '';
23
- let _gitVer = '8ed9062'; // replaced at deploy: sed -i "s/8ed9062/$(git rev-parse --short HEAD)/g" v4.js
23
+ let _gitVer = 'ce29793'; // replaced at deploy: sed -i "s/ce29793/$(git rev-parse --short HEAD)/g" v4.js
24
24
  let _calls = []; // System Info call log
25
25
  let _sectionErrors = {}; // sectionId → error count
26
26
  let _generation = 0;
package/v6.js CHANGED
@@ -20,7 +20,7 @@
20
20
  let _activeTabId = '';
21
21
  let _sections = []; // { id, label, load, loaded, errors }
22
22
  let _title = '';
23
- let _gitVer = '8ed9062'; // replaced at deploy: sed -i "s/8ed9062/$(git rev-parse --short HEAD)/g" v6.js
23
+ let _gitVer = 'ce29793'; // replaced at deploy: sed -i "s/ce29793/$(git rev-parse --short HEAD)/g" v6.js
24
24
  let _calls = []; // System Info call log
25
25
  let _sectionErrors = {}; // sectionId → error count
26
26
  let _generation = 0;
@@ -932,12 +932,17 @@ details.dk-call summary::-webkit-details-marker {
932
932
  }
933
933
 
934
934
  // ── Filters a parent can ask for ──────────────────────────────────────────────
935
- // DK_GET_FILTERS_INFO from the parent is answered with DK_FILTERS_INFO: the controls a dashboard keeps in
936
- // its header, which are what it can be opened with. It needs no token or period, so a parent can
937
- // ask as soon as the frame has loaded. Left out: controls the kit cannot fill (radio, file,
938
- // hidden, buttons), a password field, a control with no id, and a second control with an id
939
- // already listed. The whole header is read, so a control a dashboard adds to it after init is listed.
940
- const FILTER_SKIP_TYPES = ['radio', 'file', 'hidden', 'button', 'submit', 'reset', 'image', 'password'];
935
+ // DK_GET_FILTERS_INFO from the parent is answered with DK_FILTERS_INFO: the header controls a
936
+ // dashboard can be opened with, which is what the kit can write into a header control at its first boot. So
937
+ // the list follows that flow and nothing else: a control it cannot fill is not listed (radio,
938
+ // file, hidden, password, buttons; no id; a second control with an id already listed), a select
939
+ // lists only options a value may name, since an empty value is refused, and a select with none
940
+ // is left out. What exists when the dashboard boots is what counts: once it has booted, the list
941
+ // is the one taken at that moment, so options a section loads later by query are not in it, as
942
+ // they were not there for the fill. Only value and disabled are read again. It needs no token or
943
+ // period, so a parent can ask as soon as the frame has loaded.
944
+ const UNFILLABLE_TYPES = ['radio', 'file', 'hidden', 'password', 'button', 'submit', 'reset', 'image'];
945
+ let _bootFilters = null; // the list as it was when the dashboard booted
941
946
  const FILTER_MAX_OPTIONS = 100;
942
947
  const FILTER_MAX_TEXT = 500;
943
948
 
@@ -957,15 +962,24 @@ details.dk-call summary::-webkit-details-marker {
957
962
  return _clip(el.getAttribute('aria-label') || el.getAttribute('placeholder') || '', 200);
958
963
  }
959
964
 
965
+ function _controlValue(el) {
966
+ if (el.tagName === 'SELECT') {
967
+ return el.multiple ? Array.from(el.selectedOptions).map(function (o) { return o.value; }) : el.value;
968
+ }
969
+ return el.type === 'checkbox' ? el.checked : _clip(el.value, FILTER_MAX_TEXT);
970
+ }
971
+
960
972
  function _dashboardFilters() {
961
973
  const header = document.querySelector('[data-dk-header]');
962
974
  const out = [];
963
975
  if (!header) return out;
964
976
  const seen = {};
965
977
  header.querySelectorAll('input, select, textarea').forEach(function (el) {
966
- if (!el.id || seen[el.id] || FILTER_SKIP_TYPES.indexOf(el.type) >= 0) return;
967
- seen[el.id] = true;
978
+ if (!el.id || seen[el.id] || UNFILLABLE_TYPES.indexOf(el.type) >= 0) return;
968
979
  const isSelect = el.tagName === 'SELECT';
980
+ const named = isSelect ? Array.from(el.options).filter(function (o) { return o.value !== ''; }) : null;
981
+ if (isSelect && !named.length) return;
982
+ seen[el.id] = true;
969
983
  const f = {
970
984
  id: el.id,
971
985
  label: _filterLabel(el),
@@ -980,24 +994,35 @@ details.dk-call summary::-webkit-details-marker {
980
994
  }
981
995
  if (isSelect) {
982
996
  f.multiple = el.multiple;
983
- f.optionsTotal = el.options.length;
984
- f.options = Array.from(el.options).slice(0, FILTER_MAX_OPTIONS).map(function (o) {
997
+ f.optionsTotal = named.length;
998
+ f.options = named.slice(0, FILTER_MAX_OPTIONS).map(function (o) {
985
999
  return { value: _clip(o.value, 200), label: _clip(o.textContent.trim(), 200) };
986
1000
  });
987
- f.value = el.multiple ? Array.from(el.selectedOptions).map(function (o) { return o.value; }) : el.value;
988
- } else {
989
- f.value = el.type === 'checkbox' ? el.checked : _clip(el.value, FILTER_MAX_TEXT);
990
1001
  }
1002
+ f.value = _controlValue(el);
991
1003
  out.push(f);
992
1004
  });
993
1005
  return out;
994
1006
  }
995
1007
 
1008
+ // What DK_FILTERS_INFO carries: the booted list once there is one, with the values as they are now.
1009
+ function _filtersInfo() {
1010
+ const list = _bootFilters || _dashboardFilters();
1011
+ const header = document.querySelector('[data-dk-header]');
1012
+ list.forEach(function (f) {
1013
+ const el = header ? header.querySelector('#' + CSS.escape(f.id)) : null;
1014
+ if (!el) return;
1015
+ f.value = _controlValue(el);
1016
+ if (el.disabled) f.disabled = true; else delete f.disabled;
1017
+ });
1018
+ return list;
1019
+ }
1020
+
996
1021
 
997
1022
  function _onMessage(e) {
998
1023
  if (!e.data || typeof e.data !== 'object') return;
999
1024
  if (e.data.type === 'DK_GET_FILTERS_INFO') {
1000
- window.parent.postMessage({ type: 'DK_FILTERS_INFO', filters: _dashboardFilters() }, '*');
1025
+ window.parent.postMessage({ type: 'DK_FILTERS_INFO', filters: _filtersInfo() }, '*');
1001
1026
  return;
1002
1027
  }
1003
1028
  if (e.data.type === 'RK_SNAPSHOT') { _snapshot(); return; }
@@ -1027,6 +1052,7 @@ details.dk-call summary::-webkit-details-marker {
1027
1052
  }
1028
1053
 
1029
1054
  if (!_hasBooted && _authToken && _dateFromIso && _dateToIso && _timezone) {
1055
+ _bootFilters = _dashboardFilters(); // before any section runs
1030
1056
  _hasBooted = true;
1031
1057
  const wait = document.getElementById('dk-wait');
1032
1058
  if (wait) wait.hidden = true;