Skip to content

Commit

Permalink
Ensure data models are reused
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Dec 18, 2024
1 parent ad154df commit 2b0f050
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 32 deletions.
5 changes: 4 additions & 1 deletion panel/io/datamodel.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,10 @@ def create_linked_datamodel(obj, root=None):
else:
_DATA_MODELS[cls] = model = construct_data_model(obj)
properties = model.properties()
model = model(**{k: v for k, v in obj.param.values().items() if k in properties})
props = {k: v for k, v in obj.param.values().items() if k in properties}
if root:
props['name'] = f"{root.ref['id']}-{id(obj)}"
model = model(**props)
_changing = []

def cb_bokeh(attr, old, new):
Expand Down
66 changes: 35 additions & 31 deletions panel/io/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ class Notification(param.Parameterized):

notification_type = param.String(default=None, constant=True, label='type')

_rendered = param.Boolean(default=False)

_destroyed = param.Boolean(default=False)

def destroy(self) -> None:
Expand Down Expand Up @@ -194,46 +196,48 @@ def __css__(cls):
})
""",
"notifications": """
var notification = state.current || data.notifications[data.notifications.length-1]
if (notification._destroyed) {
return
}
var config = {
duration: notification.duration,
type: notification.notification_type,
message: notification.message
}
if (notification.background != null) {
config.background = notification.background;
}
if (notification.icon != null) {
config.icon = notification.icon;
}
var toast = state.toaster.open(config);
function destroy() {
if (state.current !== notification) {
notification._destroyed = true;
let to_render = []
for (notification of data.notifications) {
if (notification._destroyed || notification._rendered) {
return
}
var config = {
duration: notification.duration,
type: notification.notification_type,
message: notification.message
}
if (notification.background != null) {
config.background = notification.background;
}
if (notification.icon != null) {
config.icon = notification.icon;
}
let toast = state.toaster.open(config);
function destroy() {
if (state.current !== notification) {
notification._destroyed = true;
}
}
notification._rendered = true
toast.on('dismiss', destroy)
if (notification.duration) {
setTimeout(destroy, notification.duration)
}
if (notification.properties === undefined)
return
view.connect(notification.properties._destroyed.change, function () {
state.toaster.dismiss(toast)
})
}
toast.on('dismiss', destroy)
if (notification.duration) {
setTimeout(destroy, notification.duration)
}
if (notification.properties === undefined)
return
view.connect(notification.properties._destroyed.change, function () {
state.toaster.dismiss(toast)
})
""",
"_clear": "state.toaster.dismissAll()",
"position": """
script('_clear');
script('render');
for (notification of data.notifications) {
state.current = notification;
script('notifications');
notification._rendered = false;
}
state.current = undefined
script('notifications');
"""
}

Expand Down
21 changes: 21 additions & 0 deletions panel/reactive.py
Original file line number Diff line number Diff line change
Expand Up @@ -2170,6 +2170,27 @@ def _update_model(
)
):
continue
elif isinstance(v, list) and all(isinstance(vs, param.Parameterized) for vs in v):
from .io.datamodel import create_linked_datamodel
old = getattr(model.data, prop)
if isinstance(old, list):
mapping = {o.name: o for o in old}
vals = []
for vs in v:
if (vname:=f"{root.ref['id']}-{id(vs)}") in mapping:
vals.append(mapping[vname])
else:
vals.append(create_linked_datamodel(vs, root))
v = vals
data_msg[prop] = v
elif isinstance(v, param.Parameterized):
from .io.datamodel import create_linked_datamodel
old = getattr(model.data, prop)
if old.name == f"{root.ref['id']}-{id(v)}":
v = old
else:
v = create_linked_datamodel(vs, root)
data_msg[prop] = v
elif isinstance(v, str):
data_msg[prop] = HTML_SANITIZER.clean(v)
else:
Expand Down

0 comments on commit 2b0f050

Please sign in to comment.