Redesign the screen editor's element tree and add duplication
The "Éléments de cet écran" tree now renders every level of nesting (previously stopped after one level of children) as a compact single-line list, and right-clicking a row opens a context menu to duplicate the element (and its full subtree) in place, in its current container. Also: all property panels start collapsed instead of some being open by default, the redundant nested element list inside "Ajouter DANS ce conteneur" is removed (it only needs the widget picker), and the now-unneeded "a container is selected" warning banner is gone. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
3039489e39
commit
bb79f2f93d
@@ -0,0 +1,60 @@
|
||||
import db
|
||||
|
||||
|
||||
def duplicate_element(slug, element_id):
|
||||
"""Duplique un élément et tout son sous-arbre DANS SON CONTENEUR ACTUEL
|
||||
(même écran, même parent_id que l'original) — le clic droit "Dupliquer"
|
||||
de l'arborescence n'a pas à faire choisir où poser la copie, elle
|
||||
apparaît juste à côté de l'original. Renvoie l'id de la copie (celui à
|
||||
sélectionner ensuite), ou None si l'élément n'existe pas."""
|
||||
conn = db.connect(slug)
|
||||
root_row = conn.execute("SELECT * FROM _screen_elements WHERE id = ?", (element_id,)).fetchone()
|
||||
if not root_row:
|
||||
conn.close()
|
||||
return None
|
||||
root = dict(root_row)
|
||||
source = [
|
||||
dict(r) for r in conn.execute(
|
||||
"SELECT * FROM _screen_elements WHERE screen_id = ?", (root["screen_id"],)
|
||||
).fetchall()
|
||||
]
|
||||
conn.close()
|
||||
|
||||
def copy_one(src, new_parent_id, is_root):
|
||||
conn = db.connect(slug)
|
||||
max_z = conn.execute(
|
||||
"SELECT MAX(z_index) AS m FROM _screen_elements WHERE screen_id = ?", (src["screen_id"],)
|
||||
).fetchone()["m"]
|
||||
x, y = src["x"], src["y"]
|
||||
if is_root and not new_parent_id:
|
||||
# Petit décalage pour que la copie ne recouvre pas exactement
|
||||
# l'original (qui serait alors invisible en dessous).
|
||||
x = min(100, (x or 0) + 4)
|
||||
y = min(100, (y or 0) + 4)
|
||||
name = src.get("name")
|
||||
if is_root and name:
|
||||
name = f"{name} (copie)"
|
||||
conn.execute(
|
||||
"""INSERT INTO _screen_elements
|
||||
(screen_id, parent_id, widget, element_type_id, name, content, attributes,
|
||||
x, y, width, height, z_index, style)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
(
|
||||
src["screen_id"], new_parent_id, src["widget"], src.get("element_type_id"), name,
|
||||
src["content"], src["attributes"], x, y, src["width"], src["height"],
|
||||
(max_z or 0) + 1, src["style"],
|
||||
),
|
||||
)
|
||||
new_id = conn.execute("SELECT last_insert_rowid() AS id").fetchone()["id"]
|
||||
conn.commit()
|
||||
conn.close()
|
||||
return new_id
|
||||
|
||||
def walk(src_parent_id, new_parent_id):
|
||||
for child in [s for s in source if s.get("parent_id") == src_parent_id]:
|
||||
new_child_id = copy_one(child, new_parent_id, is_root=False)
|
||||
walk(child["id"], new_child_id)
|
||||
|
||||
new_root_id = copy_one(root, root.get("parent_id"), is_root=True)
|
||||
walk(root["id"], new_root_id)
|
||||
return new_root_id
|
||||
Reference in New Issue
Block a user