|
""" |
|
🟡 Outils de création d'éléments FigJam |
|
""" |
|
from .config import figma_config, make_figma_request |
|
|
|
def create_figjam_sticky_note(x: str, y: str, text: str, width: str = "240", height: str = "240") -> str: |
|
""" |
|
Crée un post-it (sticky note) dans FigJam avec les dimensions officielles. |
|
|
|
Args: |
|
x (str): Position X du post-it en pixels |
|
y (str): Position Y du post-it en pixels |
|
text (str): Texte à afficher sur le post-it |
|
width (str): Largeur du post-it en pixels (défaut: 240) |
|
height (str): Hauteur du post-it en pixels (défaut: 240) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
w, h = float(width), float(height) |
|
|
|
comment_text = f"Sticky Note a creer a ({x_pos}, {y_pos}) taille {w}x{h} texte: {text}" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Instructions Sticky Note créées à ({x_pos}, {y_pos}) - Taille: {w}x{h}px" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées et dimensions doivent être des nombres" |
|
|
|
def create_figjam_connector_between_elements(element1_name: str, element2_name: str, style: str = "solid") -> str: |
|
""" |
|
Crée un connecteur entre deux éléments FigJam. |
|
|
|
Args: |
|
element1_name (str): Nom du premier élément à connecter |
|
element2_name (str): Nom du deuxième élément à connecter |
|
style (str): Style du connecteur (défaut: solid) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
comment_text = f"Connecteur a creer entre {element1_name} et {element2_name} style {style}" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": 0, |
|
"y": 0 |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Instructions connecteur créées entre {element1_name} et {element2_name}" |
|
|
|
def create_figjam_shape_with_text(x: str, y: str, shape_type: str, text: str, width: str = "208", height: str = "208") -> str: |
|
""" |
|
Crée une forme avec texte intégré dans FigJam. |
|
|
|
Args: |
|
x (str): Position X de la forme en pixels |
|
y (str): Position Y de la forme en pixels |
|
shape_type (str): Type de forme (rectangle, circle, triangle, diamond, star, hexagon) |
|
text (str): Texte à afficher dans la forme |
|
width (str): Largeur de la forme en pixels (défaut: 208) |
|
height (str): Hauteur de la forme en pixels (défaut: 208) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
w, h = float(width), float(height) |
|
|
|
comment_text = f"Forme {shape_type} avec texte a creer a ({x_pos}, {y_pos}) taille {w}x{h} texte: {text}" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Instructions forme {shape_type} avec texte créées à ({x_pos}, {y_pos})" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées et dimensions doivent être des nombres" |
|
|
|
def create_figjam_table(rows: str, columns: str, x: str = "0", y: str = "0") -> str: |
|
""" |
|
Crée un tableau dans FigJam (API officielle). |
|
|
|
Args: |
|
rows (str): Nombre de lignes du tableau |
|
columns (str): Nombre de colonnes du tableau |
|
x (str): Position X du tableau en pixels (défaut: 0) |
|
y (str): Position Y du tableau en pixels (défaut: 0) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
num_rows, num_cols = int(rows), int(columns) |
|
x_pos, y_pos = float(x), float(y) |
|
|
|
comment_text = f"📊 **Tableau FigJam (API officielle) :**\n- Position: ({x_pos}, {y_pos})\n- Dimensions: {num_rows} lignes × {num_cols} colonnes\n\n📋 **Code Plugin Figma :**\n```javascript\nconst table = figma.createTable({num_rows}, {num_cols})\ntable.x = {x_pos}\ntable.y = {y_pos}\n\n// Exemple: ajouter du texte dans les cellules\nawait figma.loadFontAsync(table.cellAt(0, 0).text.fontName)\ntable.cellAt(0, 0).text.characters = 'Titre 1'\ntable.cellAt(0, 1).text.characters = 'Titre 2'\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Instructions tableau {num_rows}×{num_cols} créées à ({x_pos}, {y_pos})" |
|
|
|
except ValueError: |
|
return "❌ Les dimensions et coordonnées doivent être des nombres" |
|
|
|
def create_figjam_code_block(x: str, y: str, code: str, language: str = "javascript") -> str: |
|
""" |
|
Crée un bloc de code dans FigJam (API officielle). |
|
|
|
Args: |
|
x (str): Position X du bloc de code en pixels |
|
y (str): Position Y du bloc de code en pixels |
|
code (str): Code source à afficher |
|
language (str): Langage de programmation (défaut: javascript) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
|
|
|
|
escaped_code = code.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n') |
|
|
|
comment_text = f"💻 **Bloc de code FigJam (API officielle) :**\n- Position: ({x_pos}, {y_pos})\n- Langage: {language}\n- Code: \"{code[:100]}{'...' if len(code) > 100 else ''}\"\n\n📋 **Code Plugin Figma :**\n```javascript\nconst codeBlock = figma.createCodeBlock()\ncodeBlock.x = {x_pos}\ncodeBlock.y = {y_pos}\nawait figma.loadFontAsync(codeBlock.codeBlockText.fontName)\ncodeBlock.codeBlockText.characters = \"{escaped_code}\"\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Instructions bloc de code {language} créées à ({x_pos}, {y_pos})" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées doivent être des nombres" |
|
|
|
def create_figjam_background_shape(x: str, y: str, width: str, height: str, color: str = "#F3F4F6", title: str = "", corner_radius: str = "8") -> str: |
|
""" |
|
Crée une forme de fond rectangulaire pour organiser le contenu FigJam. |
|
|
|
Args: |
|
x (str): Position X de la forme en pixels |
|
y (str): Position Y de la forme en pixels |
|
width (str): Largeur de la forme en pixels |
|
height (str): Hauteur de la forme en pixels |
|
color (str): Couleur de fond en format hex (défaut: #F3F4F6) |
|
title (str): Titre de la zone (optionnel) |
|
corner_radius (str): Rayon des coins en pixels (défaut: 8) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
w, h = float(width), float(height) |
|
radius = float(corner_radius) |
|
|
|
comment_text = f"📐 **Forme de fond FigJam (zone de travail) :**\n- Position: ({x_pos}, {y_pos})\n- Taille: {w}x{h}px\n- Couleur: {color}\n- Titre: \"{title}\"\n- Rayon coins: {radius}px\n\n📋 **Code Plugin Figma :**\n```javascript\n// Créer la forme de fond\nconst background = figma.createRectangle()\nbackground.x = {x_pos}\nbackground.y = {y_pos}\nbackground.resize({w}, {h})\nbackground.cornerRadius = {radius}\nbackground.fills = [{{\n type: 'SOLID',\n color: {{ r: 0.95, g: 0.96, b: 0.97 }} // {color}\n}}]\nbackground.name = 'Zone - {title}'\n\n// Optionnel: ajouter un titre\nif ('{title}') {{\n const titleText = figma.createText()\n titleText.x = {x_pos + 16}\n titleText.y = {y_pos + 16}\n await figma.loadFontAsync(titleText.fontName)\n titleText.characters = '{title}'\n titleText.fontSize = 18\n}}\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Zone de travail \"{title}\" créée à ({x_pos}, {y_pos}) - {w}x{h}px" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées et dimensions doivent être des nombres" |
|
|
|
def create_figjam_sticker(x: str, y: str, sticker_type: str, size: str = "40") -> str: |
|
""" |
|
Crée un sticker/emoji dans FigJam pour les réactions et annotations. |
|
|
|
Args: |
|
x (str): Position X du sticker en pixels |
|
y (str): Position Y du sticker en pixels |
|
sticker_type (str): Type de sticker (thumbs_up, heart, fire, etc.) |
|
size (str): Taille du sticker en pixels (défaut: 40) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
sticker_size = float(size) |
|
|
|
|
|
stickers = { |
|
"thumbs_up": "👍", |
|
"thumbs_down": "👎", |
|
"heart": "❤️", |
|
"star": "⭐", |
|
"fire": "🔥", |
|
"rocket": "🚀", |
|
"bulb": "💡", |
|
"warning": "⚠️", |
|
"check": "✅", |
|
"cross": "❌", |
|
"question": "❓", |
|
"idea": "💭", |
|
"clock": "⏰", |
|
"money": "💰", |
|
"target": "🎯", |
|
"celebrate": "🎉", |
|
"thinking": "🤔", |
|
"confused": "😕" |
|
} |
|
|
|
emoji = stickers.get(sticker_type.lower(), sticker_type) |
|
|
|
comment_text = f"🎭 **Sticker FigJam :**\n- Position: ({x_pos}, {y_pos})\n- Type: {sticker_type} → {emoji}\n- Taille: {sticker_size}px\n\n📋 **Code Plugin Figma :**\n```javascript\n// Créer un sticker comme texte stylisé\nconst sticker = figma.createText()\nsticker.x = {x_pos}\nsticker.y = {y_pos}\nsticker.resize({sticker_size}, {sticker_size})\nawait figma.loadFontAsync({{ family: 'Inter', style: 'Regular' }})\nsticker.characters = '{emoji}'\nsticker.fontSize = {sticker_size}\nsticker.textAlignHorizontal = 'CENTER'\nsticker.textAlignVertical = 'CENTER'\nsticker.name = 'Sticker - {sticker_type}'\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Sticker {emoji} créé à ({x_pos}, {y_pos}) - Taille: {sticker_size}px" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées et la taille doivent être des nombres" |
|
|
|
def create_figjam_workshop_template(template_type: str, x: str = "0", y: str = "0") -> str: |
|
""" |
|
Crée des templates d'atelier FigJam prêts à utiliser. |
|
|
|
Args: |
|
template_type (str): Type de template (retrospective, brainstorm, user_journey) |
|
x (str): Position X du template en pixels (défaut: 0) |
|
y (str): Position Y du template en pixels (défaut: 0) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
|
|
templates = { |
|
"retrospective": { |
|
"title": "Rétrospective Sprint", |
|
"zones": [ |
|
{"title": "😊 Ce qui s'est bien passé", "x": 0, "y": 100, "width": 300, "height": 400, "color": "#D1FAE5"}, |
|
{"title": "😐 Ce qui peut être amélioré", "x": 320, "y": 100, "width": 300, "height": 400, "color": "#FEF3C7"}, |
|
{"title": "🚀 Actions à prendre", "x": 640, "y": 100, "width": 300, "height": 400, "color": "#DBEAFE"} |
|
] |
|
}, |
|
"brainstorm": { |
|
"title": "Session Brainstorming", |
|
"zones": [ |
|
{"title": "🎯 Objectif", "x": 0, "y": 100, "width": 960, "height": 120, "color": "#F3E8FF"}, |
|
{"title": "💡 Idées", "x": 0, "y": 240, "width": 480, "height": 400, "color": "#FEF3C7"}, |
|
{"title": "⭐ Meilleures idées", "x": 500, "y": 240, "width": 460, "height": 400, "color": "#D1FAE5"} |
|
] |
|
}, |
|
"user_journey": { |
|
"title": "Parcours Utilisateur", |
|
"zones": [ |
|
{"title": "👤 Persona", "x": 0, "y": 100, "width": 200, "height": 300, "color": "#F3E8FF"}, |
|
{"title": "🎯 Découverte", "x": 220, "y": 100, "width": 180, "height": 300, "color": "#DBEAFE"}, |
|
{"title": "🔍 Exploration", "x": 420, "y": 100, "width": 180, "height": 300, "color": "#FEF3C7"}, |
|
{"title": "✅ Conversion", "x": 620, "y": 100, "width": 180, "height": 300, "color": "#D1FAE5"}, |
|
{"title": "💝 Fidélisation", "x": 820, "y": 100, "width": 180, "height": 300, "color": "#FECACA"} |
|
] |
|
} |
|
} |
|
|
|
template = templates.get(template_type.lower()) |
|
|
|
if not template: |
|
available = ", ".join(templates.keys()) |
|
return f"❌ Template non trouvé. Disponibles: {available}" |
|
|
|
|
|
zones_code = [] |
|
for i, zone in enumerate(template["zones"]): |
|
zone_x = x_pos + zone["x"] |
|
zone_y = y_pos + zone["y"] |
|
zones_code.append(f""" |
|
// Zone {i+1}: {zone['title']} |
|
const zone{i+1} = figma.createRectangle() |
|
zone{i+1}.x = {zone_x} |
|
zone{i+1}.y = {zone_y} |
|
zone{i+1}.resize({zone['width']}, {zone['height']}) |
|
zone{i+1}.cornerRadius = 8 |
|
zone{i+1}.fills = [{{ type: 'SOLID', color: {{ r: 0.95, g: 0.96, b: 0.97 }} }}] |
|
zone{i+1}.name = '{zone['title']}' |
|
|
|
const title{i+1} = figma.createText() |
|
title{i+1}.x = {zone_x + 16} |
|
title{i+1}.y = {zone_y + 16} |
|
await figma.loadFontAsync(title{i+1}.fontName) |
|
title{i+1}.characters = '{zone['title']}' |
|
title{i+1}.fontSize = 16""") |
|
|
|
comment_text = f"🏗️ **Template FigJam: {template['title']} :**\n- Position: ({x_pos}, {y_pos})\n- {len(template['zones'])} zones de travail\n\n📋 **Code Plugin Figma :**\n```javascript\n// Template: {template['title']}{''.join(zones_code)}\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Template \"{template['title']}\" créé avec {len(template['zones'])} zones à ({x_pos}, {y_pos})" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées doivent être des nombres" |
|
|
|
def create_figjam_organized_zone(title: str, x: str, y: str, width: str = "400", height: str = "500", max_stickies: str = "12") -> str: |
|
""" |
|
Crée une zone organisée avec grille pour post-its dans FigJam. |
|
|
|
Args: |
|
title (str): Titre de la zone organisée |
|
x (str): Position X de la zone en pixels |
|
y (str): Position Y de la zone en pixels |
|
width (str): Largeur de la zone en pixels (défaut: 400) |
|
height (str): Hauteur de la zone en pixels (défaut: 500) |
|
max_stickies (str): Nombre maximum de post-its dans la grille (défaut: 12) |
|
|
|
Returns: |
|
str: Message de confirmation ou d'erreur |
|
""" |
|
if not figma_config["file_id"]: |
|
return "❌ ID du fichier requis. Utilisez configure_figma_file_id() d'abord." |
|
|
|
try: |
|
x_pos, y_pos = float(x), float(y) |
|
w, h = float(width), float(height) |
|
max_notes = int(max_stickies) |
|
|
|
|
|
cols = 3 if max_notes <= 9 else 4 |
|
rows = (max_notes + cols - 1) // cols |
|
|
|
sticky_width = (w - 80) // cols |
|
sticky_height = 120 |
|
|
|
comment_text = f"📋 **Zone organisée FigJam :**\n- Titre: \"{title}\"\n- Position: ({x_pos}, {y_pos})\n- Taille: {w}x{h}px\n- Grille: {cols}×{rows} ({max_notes} post-its max)\n\n📋 **Code Plugin Figma :**\n```javascript\n// Zone de fond\nconst zone = figma.createRectangle()\nzone.x = {x_pos}\nzone.y = {y_pos}\nzone.resize({w}, {h})\nzone.cornerRadius = 12\nzone.fills = [{{ type: 'SOLID', color: {{ r: 0.98, g: 0.98, b: 0.99 }} }}]\nzone.strokes = [{{ type: 'SOLID', color: {{ r: 0.9, g: 0.9, b: 0.92 }} }}]\nzone.strokeWeight = 2\nzone.name = 'Zone - {title}'\n\n// Titre\nconst titleText = figma.createText()\ntitleText.x = {x_pos + 20}\ntitleText.y = {y_pos + 20}\nawait figma.loadFontAsync(titleText.fontName)\ntitleText.characters = '{title}'\ntitleText.fontSize = 20\ntitleText.fontName = {{ family: 'Inter', style: 'Bold' }}\n\n// Grille de post-its exemple\nfor (let row = 0; row < {rows}; row++) {{\n for (let col = 0; col < {cols}; col++) {{\n const index = row * {cols} + col\n if (index >= {max_notes}) break\n \n const sticky = figma.createSticky()\n sticky.x = {x_pos + 20} + col * ({sticky_width} + 10)\n sticky.y = {y_pos + 70} + row * ({sticky_height} + 10)\n sticky.resize({sticky_width}, {sticky_height})\n await figma.loadFontAsync(sticky.text.fontName)\n sticky.text.characters = `Idée ${{index + 1}}`\n sticky.name = `Sticky ${{index + 1}}`\n }}\n}}\n```" |
|
|
|
comment_data = { |
|
"message": comment_text, |
|
"client_meta": { |
|
"x": x_pos, |
|
"y": y_pos |
|
} |
|
} |
|
|
|
result = make_figma_request(f"files/{figma_config['file_id']}/comments", "POST", comment_data) |
|
|
|
if "error" in result: |
|
return f"❌ Erreur lors de la création du commentaire : {result['error']}" |
|
|
|
return f"✅ Zone organisée \"{title}\" créée avec grille {cols}×{rows} pour {max_notes} post-its" |
|
|
|
except ValueError: |
|
return "❌ Les coordonnées et dimensions doivent être des nombres" |