Skip to content

Commit

Permalink
feat: annotator component #227
Browse files Browse the repository at this point in the history
  • Loading branch information
mturoci committed Apr 30, 2021
1 parent 17b404d commit 1fe0c1d
Show file tree
Hide file tree
Showing 7 changed files with 627 additions and 1 deletion.
32 changes: 32 additions & 0 deletions py/examples/annotator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

# Form / Annotator
# Use annotator when you need to highlight text phrases.
# #form #annotator
# ---
from h2o_wave import main, app, Q, ui


@app('/demo')
async def serve(q: Q):
if q.args.annotator:
q.page['example'].items = [
ui.text(f'annotator={q.args.annotator}'),
ui.button(name='show_form', label='Back', primary=True),
]
else:
q.page['example'] = ui.form_card(box='1 1 4 10', items=[
ui.annotator(
name='annotator',
tags=[
ui.annotator_tag(name='p', label='Person', color='$red'),
ui.annotator_tag(name='o', label='Org', color='$green'),
],
items=[
ui.annotator_item(text='Killer Mike', tag='p'),
ui.annotator_item(text=' is a member, of the hip hop supergroup '), # no tag
ui.annotator_item(text='Run the Jewels', tag='o'),
],
),
ui.button(name='submit', label='Submit', primary=True)
])
await q.page.save()
159 changes: 159 additions & 0 deletions py/h2o_wave/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -5343,6 +5343,155 @@ def load(__d: Dict) -> 'Inline':
)


class AnnotatorTag:
"""Create a tag.
"""
def __init__(
self,
name: str,
label: str,
color: str,
):
_guard_scalar('AnnotatorTag.name', name, (str,), True, False, False)
_guard_scalar('AnnotatorTag.label', label, (str,), False, False, False)
_guard_scalar('AnnotatorTag.color', color, (str,), False, False, False)
self.name = name
"""An identifying name for this component."""
self.label = label
"""Text to be displayed alongside the checkbox."""
self.color = color
"""HEX or RGB color string used as background for highlighted phrases."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
_guard_scalar('AnnotatorTag.name', self.name, (str,), True, False, False)
_guard_scalar('AnnotatorTag.label', self.label, (str,), False, False, False)
_guard_scalar('AnnotatorTag.color', self.color, (str,), False, False, False)
return _dump(
name=self.name,
label=self.label,
color=self.color,
)

@staticmethod
def load(__d: Dict) -> 'AnnotatorTag':
"""Creates an instance of this class using the contents of a dict."""
__d_name: Any = __d.get('name')
_guard_scalar('AnnotatorTag.name', __d_name, (str,), True, False, False)
__d_label: Any = __d.get('label')
_guard_scalar('AnnotatorTag.label', __d_label, (str,), False, False, False)
__d_color: Any = __d.get('color')
_guard_scalar('AnnotatorTag.color', __d_color, (str,), False, False, False)
name: str = __d_name
label: str = __d_label
color: str = __d_color
return AnnotatorTag(
name,
label,
color,
)


class AnnotatorItem:
"""Create an annotator item with initial selected tags or no tag for plaintext.
"""
def __init__(
self,
text: str,
tag: Optional[str] = None,
):
_guard_scalar('AnnotatorItem.text', text, (str,), False, False, False)
_guard_scalar('AnnotatorItem.tag', tag, (str,), False, True, False)
self.text = text
"""Text to be highlighted."""
self.tag = tag
"""Tag connected to the highlighted text."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
_guard_scalar('AnnotatorItem.text', self.text, (str,), False, False, False)
_guard_scalar('AnnotatorItem.tag', self.tag, (str,), False, True, False)
return _dump(
text=self.text,
tag=self.tag,
)

@staticmethod
def load(__d: Dict) -> 'AnnotatorItem':
"""Creates an instance of this class using the contents of a dict."""
__d_text: Any = __d.get('text')
_guard_scalar('AnnotatorItem.text', __d_text, (str,), False, False, False)
__d_tag: Any = __d.get('tag')
_guard_scalar('AnnotatorItem.tag', __d_tag, (str,), False, True, False)
text: str = __d_text
tag: Optional[str] = __d_tag
return AnnotatorItem(
text,
tag,
)


class Annotator:
"""Create an annotator component.
The annotator component enables user to manually annotate parts of text. Useful for NLP data prep.
"""
def __init__(
self,
name: str,
tags: List[AnnotatorTag],
items: List[AnnotatorItem],
trigger: Optional[bool] = None,
):
_guard_scalar('Annotator.name', name, (str,), True, False, False)
_guard_vector('Annotator.tags', tags, (AnnotatorTag,), False, False, False)
_guard_vector('Annotator.items', items, (AnnotatorItem,), False, False, False)
_guard_scalar('Annotator.trigger', trigger, (bool,), False, True, False)
self.name = name
"""An identifying name for this component."""
self.tags = tags
"""List of tags the user can annotate with."""
self.items = items
"""Pretagged parts of text content."""
self.trigger = trigger
"""True if the form should be submitted when the annotator value changes."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
_guard_scalar('Annotator.name', self.name, (str,), True, False, False)
_guard_vector('Annotator.tags', self.tags, (AnnotatorTag,), False, False, False)
_guard_vector('Annotator.items', self.items, (AnnotatorItem,), False, False, False)
_guard_scalar('Annotator.trigger', self.trigger, (bool,), False, True, False)
return _dump(
name=self.name,
tags=[__e.dump() for __e in self.tags],
items=[__e.dump() for __e in self.items],
trigger=self.trigger,
)

@staticmethod
def load(__d: Dict) -> 'Annotator':
"""Creates an instance of this class using the contents of a dict."""
__d_name: Any = __d.get('name')
_guard_scalar('Annotator.name', __d_name, (str,), True, False, False)
__d_tags: Any = __d.get('tags')
_guard_vector('Annotator.tags', __d_tags, (AnnotatorTag,), False, False, False)
__d_items: Any = __d.get('items')
_guard_vector('Annotator.items', __d_items, (AnnotatorItem,), False, False, False)
__d_trigger: Any = __d.get('trigger')
_guard_scalar('Annotator.trigger', __d_trigger, (bool,), False, True, False)
name: str = __d_name
tags: List[AnnotatorTag] = [AnnotatorTag.load(__e) for __e in __d_tags]
items: List[AnnotatorItem] = [AnnotatorItem.load(__e) for __e in __d_items]
trigger: Optional[bool] = __d_trigger
return Annotator(
name,
tags,
items,
trigger,
)


class Component:
"""Create a component.
"""
Expand Down Expand Up @@ -5386,6 +5535,7 @@ def __init__(
vega_visualization: Optional[VegaVisualization] = None,
stats: Optional[Stats] = None,
inline: Optional[Inline] = None,
annotator: Optional[Annotator] = None,
):
_guard_scalar('Component.text', text, (Text,), False, True, False)
_guard_scalar('Component.text_xl', text_xl, (TextXl,), False, True, False)
Expand Down Expand Up @@ -5425,6 +5575,7 @@ def __init__(
_guard_scalar('Component.vega_visualization', vega_visualization, (VegaVisualization,), False, True, False)
_guard_scalar('Component.stats', stats, (Stats,), False, True, False)
_guard_scalar('Component.inline', inline, (Inline,), False, True, False)
_guard_scalar('Component.annotator', annotator, (Annotator,), False, True, False)
self.text = text
"""Text block."""
self.text_xl = text_xl
Expand Down Expand Up @@ -5501,6 +5652,8 @@ def __init__(
"""Stats"""
self.inline = inline
"""Inline components"""
self.annotator = annotator
"""Annotator."""

def dump(self) -> Dict:
"""Returns the contents of this object as a dict."""
Expand Down Expand Up @@ -5542,6 +5695,7 @@ def dump(self) -> Dict:
_guard_scalar('Component.vega_visualization', self.vega_visualization, (VegaVisualization,), False, True, False)
_guard_scalar('Component.stats', self.stats, (Stats,), False, True, False)
_guard_scalar('Component.inline', self.inline, (Inline,), False, True, False)
_guard_scalar('Component.annotator', self.annotator, (Annotator,), False, True, False)
return _dump(
text=None if self.text is None else self.text.dump(),
text_xl=None if self.text_xl is None else self.text_xl.dump(),
Expand Down Expand Up @@ -5581,6 +5735,7 @@ def dump(self) -> Dict:
vega_visualization=None if self.vega_visualization is None else self.vega_visualization.dump(),
stats=None if self.stats is None else self.stats.dump(),
inline=None if self.inline is None else self.inline.dump(),
annotator=None if self.annotator is None else self.annotator.dump(),
)

@staticmethod
Expand Down Expand Up @@ -5662,6 +5817,8 @@ def load(__d: Dict) -> 'Component':
_guard_scalar('Component.stats', __d_stats, (Stats,), False, True, False)
__d_inline: Any = __d.get('inline')
_guard_scalar('Component.inline', __d_inline, (Inline,), False, True, False)
__d_annotator: Any = __d.get('annotator')
_guard_scalar('Component.annotator', __d_annotator, (Annotator,), False, True, False)
text: Optional[Text] = None if __d_text is None else Text.load(__d_text)
text_xl: Optional[TextXl] = None if __d_text_xl is None else TextXl.load(__d_text_xl)
text_l: Optional[TextL] = None if __d_text_l is None else TextL.load(__d_text_l)
Expand Down Expand Up @@ -5700,6 +5857,7 @@ def load(__d: Dict) -> 'Component':
vega_visualization: Optional[VegaVisualization] = None if __d_vega_visualization is None else VegaVisualization.load(__d_vega_visualization)
stats: Optional[Stats] = None if __d_stats is None else Stats.load(__d_stats)
inline: Optional[Inline] = None if __d_inline is None else Inline.load(__d_inline)
annotator: Optional[Annotator] = None if __d_annotator is None else Annotator.load(__d_annotator)
return Component(
text,
text_xl,
Expand Down Expand Up @@ -5739,6 +5897,7 @@ def load(__d: Dict) -> 'Component':
vega_visualization,
stats,
inline,
annotator,
)


Expand Down
65 changes: 65 additions & 0 deletions py/h2o_wave/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -2016,6 +2016,71 @@ def inline(
))


def annotator_tag(
name: str,
label: str,
color: str,
) -> AnnotatorTag:
"""Create a tag.
Args:
name: An identifying name for this component.
label: Text to be displayed alongside the checkbox.
color: HEX or RGB color string used as background for highlighted phrases.
Returns:
A `h2o_wave.types.AnnotatorTag` instance.
"""
return AnnotatorTag(
name,
label,
color,
)


def annotator_item(
text: str,
tag: Optional[str] = None,
) -> AnnotatorItem:
"""Create an annotator item with initial selected tags or no tag for plaintext.
Args:
text: Text to be highlighted.
tag: Tag connected to the highlighted text.
Returns:
A `h2o_wave.types.AnnotatorItem` instance.
"""
return AnnotatorItem(
text,
tag,
)


def annotator(
name: str,
tags: List[AnnotatorTag],
items: List[AnnotatorItem],
trigger: Optional[bool] = None,
) -> Component:
"""Create an annotator component.
The annotator component enables user to manually annotate parts of text. Useful for NLP data prep.
Args:
name: An identifying name for this component.
tags: List of tags the user can annotate with.
items: Pretagged parts of text content.
trigger: True if the form should be submitted when the annotator value changes.
Returns:
A `h2o_wave.types.Annotator` instance.
"""
return Component(annotator=Annotator(
name,
tags,
items,
trigger,
))


def form_card(
box: str,
items: Union[List[Component], str],
Expand Down
Loading

0 comments on commit 1fe0c1d

Please sign in to comment.