From 9334bf4eae425551b8a575ed5a345b2b43dae42f Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Thu, 19 Dec 2019 14:50:59 +1100 Subject: minimaws: display software lists for selected slot options on machine pages --- scripts/minimaws/lib/assets/machine.js | 103 +++++++++++++++++++++++++++++++++ scripts/minimaws/lib/htmltmpl.py | 4 +- scripts/minimaws/lib/wsgiserve.py | 38 +++++++----- 3 files changed, 128 insertions(+), 17 deletions(-) diff --git a/scripts/minimaws/lib/assets/machine.js b/scripts/minimaws/lib/assets/machine.js index d40dca12be0..b7f600f04d6 100644 --- a/scripts/minimaws/lib/assets/machine.js +++ b/scripts/minimaws/lib/assets/machine.js @@ -4,6 +4,7 @@ var slot_info = Object.create(null); var bios_sets = Object.create(null); var machine_flags = Object.create(null); +var softwarelist_info = Object.create(null); function make_slot_popup_id(name) { return ('select-slot-choice-' + name).replace(/:/g, '-'); } @@ -197,6 +198,47 @@ var fetch_machine_flags = (function () })(); +var fetch_softwarelist_info = (function () + { + var pending = Object.create(null); + return function (device) + { + if (!Object.prototype.hasOwnProperty.call(softwarelist_info, device) && !Object.prototype.hasOwnProperty.call(pending, device)) + { + pending[device] = true; + var req = new XMLHttpRequest(); + req.open('GET', appurl + 'rpc/softwarelists/' + encodeURIComponent(device), true); + req.responseType = 'json'; + req.onload = + function () + { + delete pending[device]; + if (req.status == 200) + { + softwarelist_info[device] = req.response; + var slotslist = document.getElementById('list-slot-options'); + if (slotslist) + { + for (var item = slotslist.firstChild; item; item = item.nextSibling) + { + if ((item.nodeName == 'DT') && (item.getAttribute('data-slotcard') == device)) + { + var slotname = item.getAttribute('data-slotname'); + add_softwarelist_rows( + device, + slotname, + document.getElementById('select-slot-choice-' + slotname.replace(/:/g, '-')).value); + } + } + } + } + }; + req.send(); + } + }; + })(); + + function add_flag_rows(table, device) { var sorted_features = Object.keys(machine_flags[device].features).sort(); @@ -228,6 +270,51 @@ function add_flag_rows(table, device) } +function add_softwarelist_rows(device, slot, card) +{ + var sorted_softwarelists = Object.keys(softwarelist_info[device]).sort(); + var cardtag = slot + ':' + card; + if (sorted_softwarelists.length) + { + var table = document.getElementById('tbl-softwarelists').tBodies[0]; + sorted_softwarelists.forEach( + function (tag) + { + var cell, link; + var info = softwarelist_info[device][tag]; + var href = appurl + 'softwarelist/' + encodeURIComponent(info.shortname); + var row = table.appendChild(document.createElement('tr')); + row.setAttribute('id', 'row-softwarelists-' + (cardtag + tag).replace(/:/g, '-')) + row.appendChild(document.createElement('td')).textContent = cardtag; + link = row.appendChild(document.createElement('td')).appendChild(document.createElement('a')); + link.setAttribute('href', href); + link.textContent = info.shortname; + link = row.appendChild(document.createElement('td')).appendChild(document.createElement('a')); + link.setAttribute('href', href); + link.textContent = info.description; + row.appendChild(document.createElement('td')).textContent = info.status; + total = info.total; + cell = row.appendChild(document.createElement('td')); + cell.textContent = total.toString(10); + cell.style.textAlign = 'right'; + if (!total) + total = 1; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.supported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.partiallysupported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + cell = row.appendChild(document.createElement('td')); + cell.textContent = (info.unsupported * 100.0 / total).toFixed(1) + '%'; + cell.style.textAlign = 'right'; + }); + document.getElementById('heading-softwarelists').style.removeProperty('display'); + document.getElementById('tbl-softwarelists').style.removeProperty('display'); + } +} + + function add_bios_row(slot, table, device) { var sorted_sets = Object.keys(bios_sets[device]).sort(); @@ -394,6 +481,16 @@ function make_slot_change_handler(name, slot, defaults, dfltbtn) slotslist.removeChild(next); } + // clear out any software lists from previous selection + var softwarelist_rowid_prefix = 'row-softwarelists-' + prefix.replace(/:/g, '-'); + for (var candidate = document.getElementById('tbl-softwarelists').tBodies[0].rows[0]; candidate; ) + { + var next = candidate.nextSibling; + if ((candidate.nodeName == 'TR') && candidate.getAttribute('id').startsWith(softwarelist_rowid_prefix)) + candidate.parentNode.removeChild(candidate); + candidate = next; + } + if (selection === null) { // no selection, remove the slot card details table @@ -427,6 +524,12 @@ function make_slot_change_handler(name, slot, defaults, dfltbtn) else add_bios_row(slotname, tbl, selection.device); + // if we have software list info, populate now, otherweise fetch asynchronously + if (!Object.prototype.hasOwnProperty.call(softwarelist_info, selection.device)) + fetch_softwarelist_info(selection.device); + else + add_softwarelist_rows(selection.device, slotname, choice); + // drop the details table into the list if (def.firstChild) def.replaceChild(tbl, def.firstChild); diff --git a/scripts/minimaws/lib/htmltmpl.py b/scripts/minimaws/lib/htmltmpl.py index 6a16f305d8d..7c9246865b1 100644 --- a/scripts/minimaws/lib/htmltmpl.py +++ b/scripts/minimaws/lib/htmltmpl.py @@ -75,6 +75,7 @@ MACHINE_SOFTWARELISTS_TABLE_PROLOGUE = string.Template( '\n' \ ' \n' \ ' \n' \ + ' \n' \ ' \n' \ ' \n' \ ' \n' \ @@ -87,7 +88,8 @@ MACHINE_SOFTWARELISTS_TABLE_PROLOGUE = string.Template( ' \n') MACHINE_SOFTWARELISTS_TABLE_ROW = string.Template( - ' \n' \ + ' \n' \ + ' \n' \ ' \n' \ ' \n' \ ' \n' \ diff --git a/scripts/minimaws/lib/wsgiserve.py b/scripts/minimaws/lib/wsgiserve.py index 8312b6f66fe..e77bb3f637f 100644 --- a/scripts/minimaws/lib/wsgiserve.py +++ b/scripts/minimaws/lib/wsgiserve.py @@ -133,9 +133,7 @@ class QueryPageHandler(HandlerBase): def slot_data(self, machine): result = { 'defaults': { }, 'slots': { } } - # get defaults and slot options - for slot, default in self.dbcurs.get_slot_defaults(machine): - result['defaults'][slot] = default + # get slot options prev = None for slot, option, shortname, description in self.dbcurs.get_slot_options(machine): if slot != prev: @@ -147,12 +145,17 @@ class QueryPageHandler(HandlerBase): prev = slot options[option] = { 'device': shortname, 'description': description } - # remove slots that come from default cards in other slots - for slot in tuple(result['slots'].keys()): - slot += ':' - for candidate in tuple(result['slots'].keys()): - if candidate.startswith(slot): - del result['slots'][candidate] + # if there are any slots, get defaults + if result['slots']: + for slot, default in self.dbcurs.get_slot_defaults(machine): + result['defaults'][slot] = default + + # remove slots that come from default cards in other slots + for slot in tuple(result['slots'].keys()): + slot += ':' + for candidate in tuple(result['slots'].keys()): + if candidate.startswith(slot): + del result['slots'][candidate] return result @@ -171,11 +174,12 @@ class QueryPageHandler(HandlerBase): 'unsupported': softwarelist['unsupported'] } # remove software lists that come from default cards in slots - for slot, default in self.dbcurs.get_slot_defaults(machine): - slot += ':' - for candidate in tuple(result.keys()): - if candidate.startswith(slot): - del result[candidate] + if result: + for slot, default in self.dbcurs.get_slot_defaults(machine): + slot += ':' + for candidate in tuple(result.keys()): + if candidate.startswith(slot): + del result[candidate] return result @@ -305,6 +309,7 @@ class MachineHandler(QueryPageHandler): for softwarelist in self.dbcurs.get_machine_softwarelists(id): total = softwarelist['total'] yield htmltmpl.MACHINE_SOFTWARELISTS_TABLE_ROW.substitute( + rowid=cgi.escape(softwarelist['tag'].replace(':', '-'), True), href=self.softwarelist_href(softwarelist['shortname']), shortname=cgi.escape(softwarelist['shortname']), description=cgi.escape(softwarelist['description']), @@ -368,8 +373,9 @@ class MachineHandler(QueryPageHandler): haveextra.add(carddev) cardid = self.dbcurs.get_machine_id(carddev) carddev = self.sanitised_json(carddev) - yield (' bios_sets[%s] = %s;\n' % (carddev, self.sanitised_json(self.bios_data(cardid)))).encode('utf-8') - yield (' machine_flags[%s] = %s;\n' % (carddev, self.sanitised_json(self.flags_data(cardid)))).encode('utf-8') + yield ( + ' bios_sets[%s] = %s;\n machine_flags[%s] = %s;\n softwarelist_info[%s] = %s;\n' % + (carddev, self.sanitised_json(self.bios_data(cardid)), carddev, self.sanitised_json(self.flags_data(cardid)), carddev, self.sanitised_json(self.softwarelist_data(cardid)))).encode('utf-8') yield htmltmpl.MACHINE_SLOTS_PLACEHOLDER_EPILOGUE.substitute( machine=self.sanitised_json(self.shortname)).encode('utf=8') -- cgit v1.2.3
CardShort nameDescriptionStatus
${shortname}${description}${status}