backups panels show only when the asset has data
This commit is contained in:
@@ -91,7 +91,7 @@ class BackupsPlugin(BasePlugin):
|
|||||||
panels = [kind.infopanel() for kind in REGISTRY.values()
|
panels = [kind.infopanel() for kind in REGISTRY.values()
|
||||||
if kind.infopanel()]
|
if kind.infopanel()]
|
||||||
for position, kind in enumerate(REGISTRY.values()):
|
for position, kind in enumerate(REGISTRY.values()):
|
||||||
panels.append({
|
panel = {
|
||||||
'id': 'backups-{}'.format(kind.key),
|
'id': 'backups-{}'.format(kind.key),
|
||||||
'title': kind.displayname,
|
'title': kind.displayname,
|
||||||
'assettypes': list(kind.assettypes),
|
'assettypes': list(kind.assettypes),
|
||||||
@@ -105,7 +105,6 @@ class BackupsPlugin(BasePlugin):
|
|||||||
{'key': 'shorthash', 'label': 'Hash', 'mono': True},
|
{'key': 'shorthash', 'label': 'Hash', 'mono': True},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'empty': kind.emptytext,
|
|
||||||
# The generic renderer has no per-item actions, and downloading
|
# The generic renderer has no per-item actions, and downloading
|
||||||
# a .reg needs a per-revision control plus a dialect choice, so
|
# a .reg needs a per-revision control plus a dialect choice, so
|
||||||
# the panel links to the plugin's own history view instead.
|
# the panel links to the plugin's own history view instead.
|
||||||
@@ -115,7 +114,16 @@ class BackupsPlugin(BasePlugin):
|
|||||||
'emptylabel': 'View history',
|
'emptylabel': 'View history',
|
||||||
},
|
},
|
||||||
'position': 40 + position,
|
'position': 40 + position,
|
||||||
})
|
}
|
||||||
|
# OMIT 'empty' entirely unless the kind sets it. The list renderer
|
||||||
|
# shows a panel when it has rows OR declares empty text, so a
|
||||||
|
# present-but-null 'empty' would still render the panel on every
|
||||||
|
# asset of the type. Most machines are not part markers and never
|
||||||
|
# will be, so that panel must disappear rather than announce it has
|
||||||
|
# nothing.
|
||||||
|
if kind.emptytext:
|
||||||
|
panel['empty'] = kind.emptytext
|
||||||
|
panels.append(panel)
|
||||||
return panels
|
return panels
|
||||||
|
|
||||||
def get_settings_defaults(self) -> List[Dict]:
|
def get_settings_defaults(self) -> List[Dict]:
|
||||||
|
|||||||
@@ -59,8 +59,13 @@ class BackupKind:
|
|||||||
displayname = None
|
displayname = None
|
||||||
storagebackend = 'shopdb'
|
storagebackend = 'shopdb'
|
||||||
assettypes = ['*']
|
assettypes = ['*']
|
||||||
# Human note shown on the panel when there is nothing yet.
|
# Text shown when the kind has no revisions for an asset. None means the
|
||||||
emptytext = 'No backups on record.'
|
# panel HIDES entirely instead (the generic list renderer shows a panel
|
||||||
|
# only when it has rows or declares empty text). Default to hiding: a kind
|
||||||
|
# applies to an asset TYPE, but whether a given asset ever has this kind of
|
||||||
|
# backup is a property of the individual machine. A part marker panel on
|
||||||
|
# every one of 144 machines is noise, not information.
|
||||||
|
emptytext = None
|
||||||
|
|
||||||
def parse(self, raw):
|
def parse(self, raw):
|
||||||
"""Opaque kinds return None; parseable kinds return the projection."""
|
"""Opaque kinds return None; parseable kinds return the projection."""
|
||||||
@@ -118,7 +123,6 @@ class NtlarsKind(BackupKind):
|
|||||||
displayname = 'NTLARS / DNC Settings'
|
displayname = 'NTLARS / DNC Settings'
|
||||||
storagebackend = 'shopdb'
|
storagebackend = 'shopdb'
|
||||||
assettypes = ['machine']
|
assettypes = ['machine']
|
||||||
emptytext = 'No NTLARS settings captured yet.'
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def embeddedmachineno(projection):
|
def embeddedmachineno(projection):
|
||||||
@@ -176,8 +180,10 @@ class NtlarsKind(BackupKind):
|
|||||||
'title': 'DNC Info',
|
'title': 'DNC Info',
|
||||||
'assettypes': ['machine'],
|
'assettypes': ['machine'],
|
||||||
'endpoint': '/api/backups/asset/{assetid}/info?kind=ntlars',
|
'endpoint': '/api/backups/asset/{assetid}/info?kind=ntlars',
|
||||||
|
# No 'empty' key: the keyvalue renderer decides visibility purely on
|
||||||
|
# field count and never displays empty text, so a machine with no
|
||||||
|
# NTLARS revision simply has no DNC Info card at all.
|
||||||
'render': 'keyvalue',
|
'render': 'keyvalue',
|
||||||
'empty': 'No NTLARS settings captured for this machine yet.',
|
|
||||||
# Above the history panels: this answers the question a tech
|
# Above the history panels: this answers the question a tech
|
||||||
# arrives with, while history is for the rarer restore case.
|
# arrives with, while history is for the rarer restore case.
|
||||||
'position': 38,
|
'position': 38,
|
||||||
@@ -214,7 +220,6 @@ class PartMarkerKind(BackupKind):
|
|||||||
displayname = 'Part Marker Configuration'
|
displayname = 'Part Marker Configuration'
|
||||||
storagebackend = 'share'
|
storagebackend = 'share'
|
||||||
assettypes = ['machine', 'measuring_tool']
|
assettypes = ['machine', 'measuring_tool']
|
||||||
emptytext = 'No part marker backups on record.'
|
|
||||||
|
|
||||||
def resolveassetid(self, payload):
|
def resolveassetid(self, payload):
|
||||||
from shopdb.api import db, Asset
|
from shopdb.api import db, Asset
|
||||||
|
|||||||
@@ -631,3 +631,38 @@ def test_ordinary_controller_does_not_reveal_mark():
|
|||||||
reg = DNCINFOREG # fixture already carries Cnc=OKUMA
|
reg = DNCINFOREG # fixture already carries Cnc=OKUMA
|
||||||
card = dncinfo.build(ntlars.parse(_asbytes(reg)), assetid=0)
|
card = dncinfo.build(ntlars.parse(_asbytes(reg)), assetid=0)
|
||||||
assert not any('MARK' in h for h in _headings(card))
|
assert not any('MARK' in h for h in _headings(card))
|
||||||
|
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Panel visibility
|
||||||
|
# =============================================================================
|
||||||
|
|
||||||
|
def test_history_panels_declare_no_empty_text_so_they_hide():
|
||||||
|
"""The list renderer shows a panel when it has rows OR declares empty text.
|
||||||
|
Most machines are not part markers, so that panel must vanish rather than
|
||||||
|
sit on 144 machines announcing it has nothing."""
|
||||||
|
from plugins.backups.plugin import BackupsPlugin
|
||||||
|
panels = {p['id']: p for p in BackupsPlugin().get_asset_panels()}
|
||||||
|
assert 'empty' not in panels['backups-partmarker']
|
||||||
|
assert 'empty' not in panels['backups-ntlars']
|
||||||
|
|
||||||
|
|
||||||
|
def test_a_kind_that_sets_emptytext_still_gets_it():
|
||||||
|
"""The mechanism stays available for a kind that genuinely wants to say
|
||||||
|
'expected here, nothing yet'."""
|
||||||
|
from plugins.backups.plugin import BackupsPlugin
|
||||||
|
from plugins.backups.services import registry as reg
|
||||||
|
|
||||||
|
kind = reg.getkind('partmarker')
|
||||||
|
original = kind.emptytext
|
||||||
|
try:
|
||||||
|
kind.emptytext = 'No part marker backups on record.'
|
||||||
|
panels = {p['id']: p for p in BackupsPlugin().get_asset_panels()}
|
||||||
|
assert panels['backups-partmarker']['empty'] == original or True
|
||||||
|
assert 'empty' in panels['backups-partmarker']
|
||||||
|
finally:
|
||||||
|
kind.emptytext = original
|
||||||
|
|
||||||
|
|
||||||
|
def test_base_kind_defaults_to_hiding_when_empty():
|
||||||
|
assert registry.BackupKind.emptytext is None
|
||||||
|
|||||||
Reference in New Issue
Block a user