Skip to content

Commit

Permalink
Tweak ChatMessage layout (#7209)
Browse files Browse the repository at this point in the history
  • Loading branch information
ahuang11 authored Sep 1, 2024
1 parent 0274f69 commit cf8fd2e
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 21 deletions.
7 changes: 6 additions & 1 deletion panel/chat/icon.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,12 @@ def _render_icons(self):
icon._reaction = option
icon.param.watch(self._update_value, "value")
self._rendered_icons[option] = icon
self._composite[:] = [self.default_layout(*list(self._rendered_icons.values()))]
self._composite[:] = [
self.default_layout(
*list(self._rendered_icons.values()),
sizing_mode=self.param.sizing_mode,
stylesheets=self._stylesheets + self.param.stylesheets.rx(),
)]

@param.depends("value", watch=True)
def _update_icons(self):
Expand Down
18 changes: 14 additions & 4 deletions panel/chat/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ def __init__(self, object=None, **params):

reaction_icons = params.get("reaction_icons", {"favorite": "heart"})
if isinstance(reaction_icons, dict):
params["reaction_icons"] = ChatReactionIcons(options=reaction_icons, default_layout=Row)
params["reaction_icons"] = ChatReactionIcons(options=reaction_icons, default_layout=Row, sizing_mode=None)
self._internal = True
super().__init__(object=object, **params)
self.chat_copy_icon = ChatCopyIcon(
Expand Down Expand Up @@ -294,18 +294,20 @@ def _build_layout(self):
self.param.user, height=20,
css_classes=["name"],
visible=self.param.show_user,
sizing_mode=None,
)

self._activity_dot = HTML(
"●",
css_classes=["activity-dot"],
margin=(5, 0),
sizing_mode=None,
visible=self.param.show_activity_dot,
)

meta_row = Row(
self._user_html,
self._activity_dot,
sizing_mode="stretch_width",
css_classes=["meta"],
stylesheets=self._stylesheets + self.param.stylesheets.rx(),
)
Expand Down Expand Up @@ -344,8 +346,8 @@ def _build_layout(self):
header_col,
self._center_row,
footer_col,
self._timestamp_html,
self._icons_row,
self._timestamp_html,
css_classes=["right"],
sizing_mode=None,
stylesheets=self._stylesheets + self.param.stylesheets.rx(),
Expand Down Expand Up @@ -556,6 +558,11 @@ def _render_reaction_icons(self):

def _update_reaction_icons(self, _):
self._icons_row[-1] = self._render_reaction_icons()
self._icon_divider.visible = (
len(self.reaction_icons.options) > 0 and
self.show_reaction_icons and
self.chat_copy_icon.visible
)

def _update(self, ref, old_models):
"""
Expand Down Expand Up @@ -598,7 +605,10 @@ def _update_chat_copy_icon(self):
if isinstance(object_panel, str) and self.show_copy_icon:
self.chat_copy_icon.value = object_panel
self.chat_copy_icon.visible = True
self._icon_divider.visible = True
self._icon_divider.visible = (
len(self.reaction_icons.options) > 0 and
self.show_reaction_icons
)
else:
self.chat_copy_icon.value = ""
self.chat_copy_icon.visible = False
Expand Down
2 changes: 1 addition & 1 deletion panel/dist/css/chat_copy_icon.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
:host {
margin-top: 5px;
margin-top: 8px;
}
7 changes: 3 additions & 4 deletions panel/dist/css/chat_message.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

.name {
font-size: 1em;
width: fit-content;
}

.center {
Expand Down Expand Up @@ -141,11 +142,9 @@
display: inline-block;
animation: fadeOut 2s infinite cubic-bezier(0.68, -0.55, 0.27, 1.55);
color: #32cd32;
/* since 1.25em, fix margins to everything is perceived to be more aligned */
/* since 1.25em, adjust line-height */
font-size: 1.25em;
margin-left: -2.5px;
margin-top: 2px;
margin-bottom: 5px;
line-height: 0.9em;
}

.divider {
Expand Down
4 changes: 4 additions & 0 deletions panel/dist/css/chat_reaction_icons.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:host {
margin-top: 4px;
width: fit-content;
}
1 change: 0 additions & 1 deletion panel/dist/css/icon.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,4 @@
.bk-IconRow {
display: flex;
align-items: center;
justify-content: center;
}
30 changes: 20 additions & 10 deletions panel/tests/chat/test_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def test_layout(self):
assert isinstance(object_pane, Markdown)
assert object_pane.object == "ABC"

icons = columns[1][5][2]
icons = columns[1][4][2]
assert isinstance(icons, ChatReactionIcons)

footer_col = columns[1][3]
Expand All @@ -65,22 +65,29 @@ def test_layout(self):
assert isinstance(footer_col[1], Markdown)
assert footer_col[1].object == "Footer 2"

timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
assert isinstance(timestamp_pane, HTML)

def test_reactions_dynamic(self):
message = ChatMessage(reactions=["favorite"])
message = ChatMessage("hi", reactions=["favorite"])
assert message.reaction_icons.value == ["favorite"]

message.reactions = ["thumbs-up"]
assert message.reaction_icons.value == ["thumbs-up"]

def test_reaction_icons_dynamic(self):
message = ChatMessage(reaction_icons={"favorite": "heart"})
message = ChatMessage("hi", reaction_icons={"favorite": "heart"})
assert message.reaction_icons.options == {"favorite": "heart"}

message.reaction_icons = ChatReactionIcons(options={"like": "thumb-up"})
assert message._icons_row[-1] == message.reaction_icons
assert message._icon_divider.visible

message.reaction_icons = ChatReactionIcons(options={})
assert not message._icon_divider.visible

message = ChatMessage("hi", reaction_icons={})
assert not message._icon_divider.visible

def test_reactions_link(self):
# on init
Expand Down Expand Up @@ -171,39 +178,39 @@ def test_update_object(self):
def test_update_timestamp(self):
message = ChatMessage()
columns = message._composite.objects
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
assert isinstance(timestamp_pane, HTML)
dt_str = datetime.datetime.now().strftime("%H:%M")
assert timestamp_pane.object == dt_str

message = ChatMessage(timestamp_tz="UTC")
columns = message._composite.objects
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
assert isinstance(timestamp_pane, HTML)
dt_str = datetime.datetime.now(datetime.timezone.utc).strftime("%H:%M")
assert timestamp_pane.object == dt_str

message = ChatMessage(timestamp_tz="US/Pacific")
columns = message._composite.objects
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
assert isinstance(timestamp_pane, HTML)
dt_str = datetime.datetime.now(tz=ZoneInfo("US/Pacific")).strftime("%H:%M")
assert timestamp_pane.object == dt_str

special_dt = datetime.datetime(2023, 6, 24, 15)
message.timestamp = special_dt
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
dt_str = special_dt.strftime("%H:%M")
assert timestamp_pane.object == dt_str

mm_dd_yyyy = "%b %d, %Y"
message.timestamp_format = mm_dd_yyyy
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
dt_str = special_dt.strftime(mm_dd_yyyy)
assert timestamp_pane.object == dt_str

message.show_timestamp = False
timestamp_pane = columns[1][4][0]
timestamp_pane = columns[1][5][0]
assert not timestamp_pane.visible

def test_does_not_turn_widget_into_str(self):
Expand Down Expand Up @@ -322,17 +329,20 @@ def test_chat_copy_icon_text_widget(self, widget):
message = ChatMessage(object=widget(value="testing"))
assert message.chat_copy_icon.visible
assert message.chat_copy_icon.value == "testing"
assert message._icon_divider.visible

def test_chat_copy_icon_disabled(self):
message = ChatMessage(object="testing", show_copy_icon=False)
assert not message.chat_copy_icon.visible
assert not message.chat_copy_icon.value
assert not message._icon_divider.visible

@pytest.mark.parametrize("component", [Column, FileInput])
def test_chat_copy_icon_not_string(self, component):
message = ChatMessage(object=component())
assert not message.chat_copy_icon.visible
assert not message.chat_copy_icon.value
assert not message._icon_divider.visible

def test_serialize_text_prefix_with_viewable_type(self):
message = ChatMessage(Markdown("string"))
Expand Down

0 comments on commit cf8fd2e

Please sign in to comment.