import sys import traceback from h2o_wave import Q, expando_to_dict, ui # App name app_name = 'NER Annotation' # Link to repo. Report bugs/features here :) repo_url = 'https://github.com/vopani/waveton' issue_url = f'{repo_url}/issues/new?assignees=vopani&labels=bug&template=error-report.md&title=%5BERROR%5D' # A meta card to hold the app's title, layouts, dialogs, theme and other meta information meta = ui.meta_card( box='', title='WaveTon', layouts=[ ui.layout( breakpoint='xs', zones=[ ui.zone(name='header'), ui.zone( name='main', size='calc(100vh - 150px)', direction='row', zones=[ ui.zone(name='ner_entities', size='20%'), ui.zone(name='ner_annotator', size='80%') ] ), ui.zone(name='footer') ] ) ], theme='h2o-dark' ) # The header shown on all the app's pages header = ui.header_card( box='header', title='NER Annotation', subtitle='Annotate entities for Named-Entity Recognition tasks', icon='Handwriting', icon_color='black', items=[ ui.toggle(name='theme_dark', label='Dark Mode', value=True, trigger=True) ] ) # The footer shown on all the app's pages footer = ui.footer_card( box='footer', caption=f'Learn more about WaveTon: 💯 Wave Applications' ) # A fallback card for handling bugs fallback = ui.form_card( box='fallback', items=[ui.text('Uh-oh, something went wrong!')] ) def ner_entities(ner_tags: list[dict]) -> ui.FormCard: """ Card for NER entities. """ card = ui.form_card( box='ner_entities', items=[ ui.textbox(name='new_entity_name', label='Type a new entity to be added'), ui.buttons( items=[ ui.button(name='add', label='Add', primary=True) ], justify='center' ), ui.separator(), ui.dropdown( name='delete_entity_name', label='Select an entity to delete', choices=[ui.choice(name=tag['name'], label=tag['label']) for tag in ner_tags] ), ui.buttons( items=[ ui.button(name='delete', label='Delete', primary=True) ], justify='center' ) ] ) return card def ner_annotator( ner_tags: list[dict], ner_items: list[dict], disable_next: bool = False, disable_previous: bool = False ) -> ui.FormCard: """ Card for NER annotator. """ card = ui.form_card( box='ner_annotator', items=[ ui.text_annotator( name='ner_annotator', title='Click and/or drag text to annotate', tags=[ui.text_annotator_tag(**tag) for tag in ner_tags], items=[ui.text_annotator_item(**item) for item in ner_items] ), ui.buttons( items=[ ui.button(name='next', label='Next', primary=True, disabled=disable_next), ui.button(name='previous', label='Previous', disabled=disable_previous) ] ) ] ) return card def crash_report(q: Q) -> ui.FormCard: """ Card for capturing the stack trace and current application state, for error reporting. This function is called by the main serve() loop on uncaught exceptions. """ def code_block(content): return '\n'.join(['```', *content, '```']) type_, value_, traceback_ = sys.exc_info() stack_trace = traceback.format_exception(type_, value_, traceback_) dump = [ '### Stack Trace', code_block(stack_trace), ] states = [ ('q.app', q.app), ('q.user', q.user), ('q.client', q.client), ('q.events', q.events), ('q.args', q.args) ] for name, source in states: dump.append(f'### {name}') dump.append(code_block([f'{k}: {v}' for k, v in expando_to_dict(source).items()])) return ui.form_card( box='main', items=[ ui.stats( items=[ ui.stat( label='', value='Oops!', caption='Something went wrong', icon='Error' ) ], ), ui.separator(), ui.text_l(content='Apologies for the inconvenience!'), ui.buttons(items=[ui.button(name='reload', label='Reload', primary=True)]), ui.expander(name='report', label='Error Details', items=[ ui.text( f'To report this issue, please open an issue with the details below:'), ui.text_l(content=f'Report Issue in App: **{app_name}**'), ui.text(content='\n'.join(dump)), ]) ] )