#!/bin/env python
################################################################
import os
from abc import ABC, abstractmethod
import markdown
import streamlit as st
from streamlit_ace import st_ace
from streamlit_editable_list import editable_list
from streamlit_quill import st_quill
################################################################
################################################################
[docs]
class EditTextBox(EditWidget):
def __init__(self, value, fmt="{0}", on_apply=None, single_line=False, **kwargs):
super().__init__(**kwargs)
self.fmt = fmt
self.value = value
self.on_apply = on_apply
self.single_line = single_line
self.show()
[docs]
def edit(self):
_edit = st.empty()
view, edit = _edit.columns(2)
_view = view.empty()
self.view(_view)
with edit:
inp = st.text_area
if self.single_line:
inp = st.text_input
content = inp("", value=self.value, key=f"text_area_{self.key}")
if content != self.value:
self.value = content
self.view(_view)
if st.button("Apply", key=f"apply_{self.key}") and self.on_apply:
try:
self.on_apply(self.value)
self.edit_mode = False
_edit.empty()
self.show()
except Exception as err:
st.error(err)
[docs]
def view(self, layout=None):
if layout is None:
layout = self.layout
if isinstance(self.fmt, str):
formatted = self.fmt.format(self.value)
if callable(self.fmt):
formatted = self.fmt(self.value)
layout.markdown(formatted, unsafe_allow_html=True)
################################################################
[docs]
class EditRichTextBox(EditWidget):
def __init__(self, value, fmt="{0}", on_apply=None, **kwargs):
super().__init__(**kwargs)
self.fmt = fmt
self.value = value
self.on_apply = on_apply
self.show()
[docs]
def edit(self):
_edit = st.empty()
edit = _edit.container()
with edit:
content = st_quill(value=self.value, html=True, preserve_whitespace=False, key=f"rich_text_area_{self.key}")
if content != self.value:
self.value = content
if self.on_apply:
self.on_apply(self.value)
[docs]
def view(self, layout=None):
if layout is None:
layout = self.layout
layout.markdown(self.fmt.format(self.value), unsafe_allow_html=True)
[docs]
def show(self):
self.edit()
################################################################
[docs]
class EditList(EditWidget):
def __init__(self, data, input_params=[], fmt="{0}", on_apply=None, **kwargs):
super().__init__(**kwargs)
self.fmt = fmt
self.data = data
self.input_params = input_params
self.on_apply = on_apply
self.component_key = f"component_{self.key}"
self.show()
[docs]
def edit(self):
self.data = editable_list(self.data, self.input_params, key=self.component_key)
if self.on_apply:
try:
self.on_apply(self.data)
except Exception as err:
st.error(err)
[docs]
def view(self, layout=None):
if layout is None:
layout = self.layout
if isinstance(self.fmt, str):
formatted = self.fmt.format(self.data)
if callable(self.fmt):
formatted = self.fmt(self.data)
layout.markdown(formatted, unsafe_allow_html=True)
################################################################
[docs]
class EditProgBox(EditWidget):
def __init__(self, value, fmt="{0}", language="text", on_apply=None, single_line=False, **kwargs):
super().__init__(**kwargs)
self.fmt = fmt
self.value = value
self.language = language
self.on_apply = on_apply
self.single_line = single_line
self.show()
[docs]
def edit(self):
_edit = st.empty()
edit = _edit.container()
with edit:
content = st_ace(
value=self.value,
language=self.language,
theme="textmate",
show_gutter=False,
key=f"prog_area_{self.key}",
)
if content != self.value:
self.value = content
self.edit_mode = False
if self.on_apply:
self.on_apply(self.value)
self.value = content
_edit.empty()
st.rerun()
ex = st.button(
"Exit",
key=f"exit_button_{self.key}",
)
if ex:
self.edit_mode = False
_edit.empty()
self.show()
[docs]
def view(self, layout=None):
if layout is None:
layout = self.layout
if isinstance(self.fmt, str):
formatted = _format(self.fmt, self.value)
if callable(self.fmt):
formatted = self.fmt(self.value)
if self.language == "markdown":
formatted = markdown.markdown(formatted, tab_length=2)
formatted = f'<div style="font-size: 10em"> {formatted} </div>'
st.write(formatted, unsafe_allow_html=True)
# st_quill(
# value=formatted,
# toolbar=[],
# readonly=True,
# html=True,
# preserve_whitespace=False,
# key=f"rich_text_area_read_only_{self.key}",
# )
else:
layout.text(formatted)
################################################################
[docs]
class SpeechBubble:
def __init__(self, author, value):
self.value = value
self.author = author
self.show()
[docs]
def show(self):
st.markdown(f"<style> {css} </style>", unsafe_allow_html=True)
html = open(html_path).read()
html = html.replace("<blockquote>", f"<blockquote>{self.value}")
html = html.replace('<p id="author">', f'<p id="author">{self.author}')
st.markdown(html, unsafe_allow_html=True)
################################################################
css_path = os.path.join(os.path.dirname(__file__), "speech_bubble.css")
html_path = os.path.join(os.path.dirname(__file__), "speech_bubble.html")
css = open(css_path).read()