Repository URL to install this package:
|
Version:
0.4.6 ▾
|
# -*- coding: utf-8 -*-
import uuid
from abc import abstractmethod
from typing import TYPE_CHECKING, List, Mapping, Union
from pydantic import Field
from kiara.api import Value, ValueMap
from kiara_plugin.streamlit.components import ComponentOptions, KiaraComponent
from kiara_plugin.streamlit.components.models import (
create_recursive_table_from_model_object,
)
from kiara_plugin.streamlit.utils.components import create_list_component
if TYPE_CHECKING:
from kiara_plugin.streamlit.api import KiaraStreamlitAPI
class PreviewOptions(ComponentOptions):
show_properties: bool = Field(
description="Whether to show the properties of the value.", default=True
)
height: Union[int, None] = Field(
description="The height of the preview.", default=None
)
display_style: str = Field(
description="The display style to use for this preview.", default="default"
)
value: Union[str, uuid.UUID, Value] = Field(description="The value to preview.")
class PreviewComponent(KiaraComponent[PreviewOptions]):
_options = PreviewOptions # type: ignore
@classmethod
@abstractmethod
def get_data_type(cls) -> str:
pass
@classmethod
def get_preview_name(cls) -> str:
return "default"
@abstractmethod
def render_preview(self, st: "KiaraStreamlitAPI", options: PreviewOptions):
pass
def _render(
self,
st: "KiaraStreamlitAPI",
options: PreviewOptions,
):
self.render_preview(st=st, options=options)
class PropertiesViewOptions(ComponentOptions):
"""Options for the properties view component."""
value: Union[str, uuid.UUID, Value] = Field(description="The value to preview.")
class PropertiesViewComponent(KiaraComponent[PropertiesViewOptions]):
"""Display the properties of a value."""
_component_name = "display_value_properties"
_options = PropertiesViewOptions
def _render(self, st: "KiaraStreamlitAPI", options: PropertiesViewOptions):
value = self.api.get_value(value=options.value)
for prop_name, prop_value in value.property_values.items():
_prop_name = prop_name.replace("metadata.", "")
st.write(f"Metadata item: **{_prop_name}**")
table_data = create_recursive_table_from_model_object(prop_value.data)
name_col, val_col = st.columns([1, 3])
for key, value in table_data.items():
with name_col:
name_col.write(key)
with val_col:
if isinstance(value, (Mapping, List)):
val_col.json(value, expanded=False)
else:
val_col.write(value)
class DefaultPreviewComponent(PreviewComponent):
"""The default preview component, will render a preview component dependent on the data type of the provided value."""
_component_name = "preview"
_examples = [
{"doc": "Preview a table value.", "args": {"value": "nodes_table"}},
]
@classmethod
def get_data_type(cls) -> str:
return "any"
def render_preview(
self,
st: "KiaraStreamlitAPI",
options: PreviewOptions,
):
preview_name = options.display_style
height = options.height
if not height:
height = 400
_value = self.api.get_value(options.value)
if not _value.is_set:
st.write("Value not set.")
return
component = self._kiara_streamlit.get_preview_component(
data_type=_value.data_type_name, preview_name=preview_name
)
if component is not None:
component.render_func(st)(value=_value, key=options.create_key("preview"))
else:
if isinstance(options.value, Value):
name = str(_value.value_id)
else:
name = str(options.value)
renderable = self.api.render_value(
value=_value, target_format="string", use_pretty_print=True
)
st.text_area(
f"Value: {name}",
value=renderable,
disabled=True,
height=height,
key=options.create_key("preview", "default"),
)
class PreviewListOptions(ComponentOptions):
data_types: Union[str, List[str], None] = Field(
description="The data types to display.", default=None
)
class ValueList(KiaraComponent[PreviewListOptions]):
_component_name = "value_list"
_options = PreviewListOptions
def _render(
self, st: "KiaraStreamlitAPI", options: PreviewListOptions
) -> Union[str, None]:
data_types = []
if options.data_types:
if isinstance(options.data_types, str):
data_types.append(options.data_types)
else:
data_types.extend(options.data_types)
values = self.api.list_aliases(data_types=data_types)
_key = options.create_key("value_list")
selected_alias = create_list_component(
st=st, key=_key, title="Values", items=list(values.keys())
)
return selected_alias
class ValueListPreview(KiaraComponent[PreviewListOptions]):
_component_name = "value_list_preview"
_options = PreviewListOptions
def _render(
self,
st: "KiaraStreamlitAPI",
options: PreviewListOptions,
) -> Union[str, None]:
ratio_preview: int = 3
data_list_column, preview_column = st.columns([1, ratio_preview])
_key = options.create_key("data_list")
comp = self.get_component("value_list")
selected_alias = comp.render_func(data_list_column)(
key=_key, data_types=options.data_types
)
if selected_alias:
value = self.api.get_value(selected_alias)
component = self.kiara_streamlit.get_preview_component(value.data_type_name)
if component is None:
component = self.kiara_streamlit.get_preview_component("any")
pr_opts = PreviewOptions(key=options.create_key("preview"), value=value)
component.render_preview(preview_column, options=pr_opts) # type: ignore
return selected_alias
class ValueMapPreviewOptions(ComponentOptions):
add_value_types: bool = Field(
description="Whether to add the type of the value to the tab titles.",
default=True,
)
add_save_option: bool = Field(
description="Whether to add a save option for every value.", default=False
)
value_map: Mapping[str, Union[str, uuid.UUID, Value]] = Field(
description="The values to display."
)
class ValueMapPreview(KiaraComponent[ValueMapPreviewOptions]):
_component_name = "value_map_preview"
_options = ValueMapPreviewOptions
def _render(
self,
st: "KiaraStreamlitAPI",
options: ValueMapPreviewOptions,
) -> Union[ValueMap, None]:
if not options.value_map:
st.write("-- no values --")
return None
_values = self.api.assemble_value_map(options.value_map)
field_names = sorted(_values.keys())
if not options.add_value_types:
tab_names = field_names
else:
tab_names = sorted(
(f"{x} ({_values[x].data_type_name})" for x in _values.keys())
)
tabs = st.tabs(tab_names)
for idx, field in enumerate(field_names):
value = _values[field]
if not value.is_set:
tabs[idx].markdown("-- value not set --")
else:
component = self.kiara_streamlit.get_preview_component(
value.data_type_name
)
if component is None:
component = self.kiara_streamlit.get_preview_component("any")
if options.add_save_option:
center, right = tabs[idx].columns([4, 1])
else:
center = tabs[idx]
right = None
_key = options.create_key("preview", f"{idx}_{field}")
preview_opts = PreviewOptions(key=_key, value=value)
component.render_preview(st=center, options=preview_opts) # type: ignore
if options.add_save_option:
assert right is not None
right.write("Save value")
with right.form(
key=options.create_key("save_form", f"{idx}_{field}")
):
_key = options.create_key("alias", f"{idx}_{field}")
alias = self._st.text_input(
"alias",
value="",
key=_key,
placeholder="alias",
label_visibility="hidden",
)
# _key = options.create_key("save", f"{idx}_{field}")
save = self._st.form_submit_button("Save")
if save and alias:
store_result = self.api.store_value(
value=value, alias=alias, allow_overwrite=False
)
if store_result.error:
right.error(store_result.error)
else:
right.success("Value saved")
st.experimental_rerun()
return _values