@@ -146,6 +146,8 @@ def render(self):
146146 label = self ._label ,
147147 )
148148 datadict .update (img_dict )
149+ if self .id is not None :
150+ datadict ["id" ] = self .id
149151 return datadict
150152
151153
@@ -194,6 +196,8 @@ def render(self):
194196 datadict ["columns" ] = self ._headers
195197 datadict ["data" ] = self ._data
196198 datadict ["vertical" ] = self ._vertical
199+ if self .id is not None :
200+ datadict ["id" ] = self .id
197201 return datadict
198202
199203
@@ -295,6 +299,8 @@ def __init__(self, title=None, subtitle=None, data={}):
295299 def render (self ):
296300 datadict = super ().render ()
297301 datadict ["data" ] = self ._data
302+ if self .id is not None :
303+ datadict ["id" ] = self .id
298304 return datadict
299305
300306
@@ -308,6 +314,8 @@ def __init__(self, text=None):
308314 def render (self ):
309315 datadict = super ().render ()
310316 datadict ["source" ] = self ._text
317+ if self .id is not None :
318+ datadict ["id" ] = self .id
311319 return datadict
312320
313321
@@ -319,7 +327,13 @@ class TaskInfoComponent(MetaflowCardComponent):
319327 """
320328
321329 def __init__ (
322- self , task , page_title = "Task Info" , only_repr = True , graph = None , components = []
330+ self ,
331+ task ,
332+ page_title = "Task Info" ,
333+ only_repr = True ,
334+ graph = None ,
335+ components = [],
336+ runtime = False ,
323337 ):
324338 self ._task = task
325339 self ._only_repr = only_repr
@@ -328,6 +342,7 @@ def __init__(
328342 self ._page_title = page_title
329343 self .final_component = None
330344 self .page_component = None
345+ self .runtime = runtime
331346
332347 def render (self ):
333348 """
@@ -340,7 +355,8 @@ def render(self):
340355 self ._task , graph = self ._graph
341356 )
342357 # ignore the name as an artifact
343- del task_data_dict ["data" ]["name" ]
358+ if "name" in task_data_dict ["data" ]:
359+ del task_data_dict ["data" ]["name" ]
344360
345361 _metadata = dict (version = 1 , template = "defaultCardTemplate" )
346362 # try to parse out metaflow version from tags, but let it go if unset
@@ -370,11 +386,12 @@ def render(self):
370386 "Task Created On" : task_data_dict ["created_at" ],
371387 "Task Finished On" : task_data_dict ["finished_at" ],
372388 # Remove Microseconds from timedelta
373- "Task Duration" : str (self ._task .finished_at - self ._task .created_at ).split (
374- "."
375- )[0 ],
376389 "Tags" : ", " .join (tags ),
377390 }
391+ if not self .runtime :
392+ task_metadata_dict ["Task Duration" ] = str (
393+ self ._task .finished_at - self ._task .created_at
394+ ).split ("." )[0 ]
378395 if len (user_info ) > 0 :
379396 task_metadata_dict ["User" ] = user_info [0 ].split ("user:" )[1 ]
380397
@@ -580,6 +597,10 @@ class DefaultCard(MetaflowCard):
580597
581598 ALLOW_USER_COMPONENTS = True
582599
600+ IS_RUNTIME_CARD = True
601+
602+ RELOAD_POLICY = MetaflowCard .RELOAD_POLICY_ONCHANGE
603+
583604 type = "default"
584605
585606 def __init__ (self , options = dict (only_repr = True ), components = [], graph = None ):
@@ -589,7 +610,7 @@ def __init__(self, options=dict(only_repr=True), components=[], graph=None):
589610 self ._only_repr = options ["only_repr" ]
590611 self ._components = components
591612
592- def render (self , task ):
613+ def render (self , task , runtime = False ):
593614 RENDER_TEMPLATE = read_file (RENDER_TEMPLATE_PATH )
594615 JS_DATA = read_file (JS_PATH )
595616 CSS_DATA = read_file (CSS_PATH )
@@ -598,6 +619,7 @@ def render(self, task):
598619 only_repr = self ._only_repr ,
599620 graph = self ._graph ,
600621 components = self ._components ,
622+ runtime = runtime ,
601623 ).render ()
602624 pt = self ._get_mustache ()
603625 data_dict = dict (
@@ -611,11 +633,27 @@ def render(self, task):
611633 )
612634 return pt .render (RENDER_TEMPLATE , data_dict )
613635
636+ def render_runtime (self , task , data ):
637+ return self .render (task , runtime = True )
638+
639+ def refresh (self , task , data ):
640+ return data ["components" ]
641+
642+ def reload_content_token (self , task , data ):
643+ if task .finished :
644+ return "final"
645+ else :
646+ return "runtime"
647+
614648
615649class BlankCard (MetaflowCard ):
616650
617651 ALLOW_USER_COMPONENTS = True
618652
653+ IS_RUNTIME_CARD = True
654+
655+ RELOAD_POLICY = MetaflowCard .RELOAD_POLICY_ONCHANGE
656+
619657 type = "blank"
620658
621659 def __init__ (self , options = dict (title = "" ), components = [], graph = None ):
@@ -653,6 +691,18 @@ def render(self, task, components=[]):
653691 )
654692 return pt .render (RENDER_TEMPLATE , data_dict )
655693
694+ def render_runtime (self , task , data ):
695+ return self .render (task )
696+
697+ def refresh (self , task , data ):
698+ return data ["components" ]
699+
700+ def reload_content_token (self , task , data ):
701+ if task .finished :
702+ return "final"
703+ else :
704+ return "runtime"
705+
656706
657707class TaskSpecCard (MetaflowCard ):
658708 type = "taskspec_card"
0 commit comments