llamadas a la api creadas
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
{
|
||||
"version": "1",
|
||||
"metadata": {
|
||||
"marimo_version": "0.17.0"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"id": "Hbol",
|
||||
"code_hash": "1d0db38904205bec4d6f6f6a1f6cec3e",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "mmzP",
|
||||
"code_hash": "e53b82f6768020aad4940c56dd2fae07",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"listar-proyectos\">Listar Proyectos</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "soEq",
|
||||
"code_hash": "35bcfe34cc3625a28a154254259b76de",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"application/json": "{\"jsonrpc\": \"2.0\", \"result\": [{\"id\": 1, \"name\": \"CodeProyects\", \"is_active\": true, \"token\": \"\", \"last_modified\": 1761063849, \"is_public\": false, \"is_private\": false, \"description\": null, \"identifier\": \"\", \"start_date\": \"\", \"end_date\": \"\", \"owner_id\": 2, \"priority_default\": 0, \"priority_start\": 0, \"priority_end\": 3, \"email\": null, \"predefined_email_subjects\": null, \"per_swimlane_task_limits\": false, \"task_limit\": 0, \"enable_global_tags\": true, \"url\": {\"board\": \"http://localhost/board/1\", \"list\": \"http://localhost/list/1\"}}], \"id\": 1}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "COzz",
|
||||
"code_hash": "8593497dfb93ffdc4d481231f22ff886",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"listar-usuarios\">Listar usuarios</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "fRcd",
|
||||
"code_hash": "036c95a347f6de634be1a5277fc99daa",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\u2705 Usuarios encontrados:\nID 1 | Usuario: admin | Nombre: None\nID 2 | Usuario: Egutierrez | Nombre: Enmanuel\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ucix",
|
||||
"code_hash": "80ced1b6d20bb63695c909cca312c33c",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"listar-tareas\">Listar tareas</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "fRXL",
|
||||
"code_hash": "18ea3c992e655e4fb8f64b7d24a41bbb",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "Tarea ID 5: Otra tarea autom\u00e1tica con etiquetas\nTarea ID 6: Otra tarea autom\u00e1tica con etiquetas\nTarea ID 7: Otra tarea autom\u00e1tica con etiquetas\nTarea ID 8: Otra tarea autom\u00e1tica con etiquetas\nTarea ID 9: Tarea con maxima prioridad\nTarea ID 10: Tarea con maxima prioridad\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "jMzO",
|
||||
"code_hash": "808fe59b3702664ab0b7e4e4a920629a",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h3 id=\"listar-subtareas\">Listar subtareas</h3></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "qrHy",
|
||||
"code_hash": "7a03102141b244eb5054544c39ec0feb",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "rkGP",
|
||||
"code_hash": "ed4d72d20e904f8baad87c095b3d3471",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"listar-tareas-columnas\">Listar tareas columnas</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "HTUm",
|
||||
"code_hash": "f8d752251cf677e701b0a7b1ed2cc1cc",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\n\ud83d\udce6 Backlog (4 tareas):\n \u251c\u2500 [5] Otra tarea autom\u00e1tica con etiquetas\n \u251c\u2500 [8] Otra tarea autom\u00e1tica con etiquetas\n \u251c\u2500 [9] Tarea con maxima prioridad\n \u251c\u2500 [10] Tarea con maxima prioridad\n\n\ud83d\udce6 Ready (1 tareas):\n \u251c\u2500 [7] Otra tarea autom\u00e1tica con etiquetas\n\n\ud83d\udce6 Work in progress (1 tareas):\n \u251c\u2500 [6] Otra tarea autom\u00e1tica con etiquetas\n\n\ud83d\udce6 Done (0 tareas):\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "DHdl",
|
||||
"code_hash": "557d1157ae68f568602eeb5e5ed09c76",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"mover-tareas-entre-columnas\">Mover tareas entre columnas</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "WhTX",
|
||||
"code_hash": "f88d3bdcbdaf4bbbf6f070b536cd24d6",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\u26a0\ufe0f No se pudo mover la tarea 6.\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "DBDn",
|
||||
"code_hash": null,
|
||||
"outputs": [],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "LoIk",
|
||||
"code_hash": "7590f79b2fa20f3da53fcbbaf31c3e70",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"crear-tarea\">Crear tarea</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "dbns",
|
||||
"code_hash": "c3260268117f17ff51af0ebe7c5c413b",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\u2705 Tarea creada correctamente (ID 10) en el proyecto 1\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\ud83c\udff7\ufe0f Etiquetas a\u00f1adidas: etl, prioridad-alta\n"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "HDME",
|
||||
"code_hash": "8c2e1134753947cea243b3a8e020383d",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/html": "<span class=\"markdown prose dark:prose-invert\"><h2 id=\"editar-tarea\">Editar tarea</h2></span>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "NQhy",
|
||||
"code_hash": "29ac83f0938d9e28f09291ac8e870ad7",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\u2705 Tarea 8 actualizada correctamente en Kanboard.\n"
|
||||
},
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stdout",
|
||||
"text": "\ud83c\udff7\ufe0f Etiquetas actualizadas: automatizada, revisi\u00f3n, python\n"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"version": "1",
|
||||
"metadata": {
|
||||
"marimo_version": "0.17.0"
|
||||
},
|
||||
"cells": [
|
||||
{
|
||||
"id": "Hbol",
|
||||
"code_hash": "1d0db38904205bec4d6f6f6a1f6cec3e",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "data",
|
||||
"data": {
|
||||
"text/plain": ""
|
||||
}
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
},
|
||||
{
|
||||
"id": "MJUe",
|
||||
"code_hash": "30549382a489a6758d4eda0a633ecec7",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "exception",
|
||||
"evalue": "401 Client Error: Unauthorized for url: http://127.0.0.1:8080/jsonrpc.php",
|
||||
"traceback": []
|
||||
}
|
||||
],
|
||||
"console": [
|
||||
{
|
||||
"type": "stream",
|
||||
"name": "stderr",
|
||||
"text": "<span class=\"codehilite\"><div class=\"highlight\"><pre><span></span><span class=\"gt\">Traceback (most recent call last):</span>\n File <span class=\"nb\">"/tmp/marimo_86378/__marimo__cell_MJUe_.py"</span>, line <span class=\"m\">67</span>, in <span class=\"n\"><module></span>\n<span class=\"w\"> </span><span class=\"n\">projects</span> <span class=\"o\">=</span> <span class=\"n\">get_all_projects_with_tasks</span><span class=\"p\">(</span><span class=\"n\">API_URL</span><span class=\"p\">,</span> <span class=\"n\">USERNAME</span><span class=\"p\">,</span> <span class=\"n\">API_TOKEN</span><span class=\"p\">)</span>\n File <span class=\"nb\">"/tmp/marimo_86378/__marimo__cell_MJUe_.py"</span>, line <span class=\"m\">33</span>, in <span class=\"n\">get_all_projects_with_tasks</span>\n<span class=\"w\"> </span><span class=\"n\">projects</span> <span class=\"o\">=</span> <span class=\"n\">rpc</span><span class=\"p\">(</span><span class=\"s2\">"getAllProjects"</span><span class=\"p\">)</span>\n File <span class=\"nb\">"/tmp/marimo_86378/__marimo__cell_MJUe_.py"</span>, line <span class=\"m\">27</span>, in <span class=\"n\">rpc</span>\n<span class=\"w\"> </span><span class=\"n\">r</span><span class=\"o\">.</span><span class=\"n\">raise_for_status</span><span class=\"p\">()</span>\n<span class=\"w\"> </span><span class=\"pm\">~~~~~~~~~~~~~~~~~~^^</span>\n File <span class=\"nb\">"/home/lucas/DataProyects/kanboard/.venv/lib/python3.13/site-packages/requests/models.py"</span>, line <span class=\"m\">1026</span>, in <span class=\"n\">raise_for_status</span>\n<span class=\"w\"> </span><span class=\"k\">raise</span> <span class=\"n\">HTTPError</span><span class=\"p\">(</span><span class=\"n\">http_error_msg</span><span class=\"p\">,</span> <span class=\"n\">response</span><span class=\"o\">=</span><span class=\"bp\">self</span><span class=\"p\">)</span>\n<span class=\"gr\">requests.exceptions.HTTPError</span>: <span class=\"n\">401 Client Error: Unauthorized for url: http://127.0.0.1:8080/jsonrpc.php</span>\n</pre></div>\n</span>"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "LMtK",
|
||||
"code_hash": "b150d3f7475c3d17e5c1bffbdbc6d5fe",
|
||||
"outputs": [
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "multiple-defs",
|
||||
"evalue": "The variable 'API_TOKEN' was defined by another cell",
|
||||
"traceback": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "multiple-defs",
|
||||
"evalue": "The variable 'API_URL' was defined by another cell",
|
||||
"traceback": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "multiple-defs",
|
||||
"evalue": "The variable 'HTTPBasicAuth' was defined by another cell",
|
||||
"traceback": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "multiple-defs",
|
||||
"evalue": "The variable 'USERNAME' was defined by another cell",
|
||||
"traceback": []
|
||||
},
|
||||
{
|
||||
"type": "error",
|
||||
"ename": "multiple-defs",
|
||||
"evalue": "The variable 'requests' was defined by another cell",
|
||||
"traceback": []
|
||||
}
|
||||
],
|
||||
"console": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,578 @@
|
||||
import marimo
|
||||
|
||||
__generated_with = "0.17.0"
|
||||
app = marimo.App(width="columns")
|
||||
|
||||
|
||||
@app.cell(column=0)
|
||||
def _():
|
||||
import marimo as mo
|
||||
return (mo,)
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""## Listar Proyectos""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _():
|
||||
import requests
|
||||
from requests.auth import HTTPBasicAuth
|
||||
import json
|
||||
|
||||
url = "http://localhost:8080/jsonrpc.php" # o http://host.docker.internal:8080/jsonrpc.php desde WSL
|
||||
auth = HTTPBasicAuth("jsonrpc", "792d8fdd6cbf69b3a32d800beaf48b958e4490dd9185c72c06c56061a591")
|
||||
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getAllProjects",
|
||||
"id": 1
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
url,
|
||||
json=payload,
|
||||
auth=auth,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10
|
||||
)
|
||||
|
||||
# 👇 Convierte el cuerpo en JSON (Python dict)
|
||||
resultado = response.json()
|
||||
|
||||
# Muestra el JSON bonito
|
||||
resultado
|
||||
|
||||
return HTTPBasicAuth, requests
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""## Listar usuarios""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, TOKEN, USER, requests):
|
||||
def obtener_usuarios(api_url, usuario, token):
|
||||
"""
|
||||
Devuelve la lista completa de usuarios disponibles en Kanboard.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC (por ejemplo, http://host.docker.internal:8080/jsonrpc.php)
|
||||
usuario (str): Usuario con permisos API (ej. 'jsonrpc' o 'admin')
|
||||
token (str): Token de autenticación del usuario
|
||||
|
||||
Retorna:
|
||||
list[dict]: Lista de usuarios, cada uno con su 'id', 'username', 'name', etc.
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getAllUsers",
|
||||
"id": 1
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
api_url,
|
||||
json=payload,
|
||||
auth=auth,
|
||||
headers={"Content-Type": "application/json"},
|
||||
timeout=10
|
||||
)
|
||||
|
||||
data = response.json()
|
||||
if "error" in data:
|
||||
raise Exception(f"❌ Error al obtener usuarios: {data['error']}")
|
||||
|
||||
return data.get("result", [])
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso
|
||||
if __name__ == "__main__":
|
||||
|
||||
usuarios = obtener_usuarios(API_URL, USER, TOKEN)
|
||||
print("✅ Usuarios encontrados:")
|
||||
for u in usuarios:
|
||||
print(f"ID {u['id']:>2} | Usuario: {u['username']:<15} | Nombre: {u.get('name', '')}")
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""## Listar tareas""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, PROJECT_ID, TOKEN, USER, requests):
|
||||
def listar_tareas(api_url, usuario, token, project_id):
|
||||
"""
|
||||
Lista todas las tareas de un proyecto en Kanboard.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API
|
||||
token (str): Token del usuario
|
||||
project_id (int): ID del proyecto donde obtener las tareas
|
||||
|
||||
Retorna:
|
||||
list[dict]: Lista de tareas en el proyecto
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getAllTasks",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"project_id": project_id
|
||||
}
|
||||
}
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers={"Content-Type": "application/json"})
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al obtener tareas:", data["error"])
|
||||
return []
|
||||
|
||||
return data.get("result", [])
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso:
|
||||
tareas = listar_tareas(API_URL, USER, TOKEN, PROJECT_ID)
|
||||
for tarea in tareas:
|
||||
print(f"Tarea ID {tarea['id']}: {tarea['title']}")
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""### Listar subtareas""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, TOKEN, USER, requests):
|
||||
def listar_subtareas(api_url, usuario, token, task_id):
|
||||
"""
|
||||
Lista todas las subtareas de una tarea.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API
|
||||
token (str): Token del usuario
|
||||
task_id (int): ID de la tarea principal para obtener sus subtareas
|
||||
|
||||
Retorna:
|
||||
list[dict]: Lista de subtareas asociadas
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getAllSubtasks",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"task_id": task_id
|
||||
}
|
||||
}
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers={"Content-Type": "application/json"})
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al obtener subtareas:", data["error"])
|
||||
return []
|
||||
|
||||
return data.get("result", [])
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso:
|
||||
task_id = 10 # ID de la tarea principal
|
||||
subtareas = listar_subtareas(API_URL, USER, TOKEN, task_id)
|
||||
for sub in subtareas:
|
||||
print(f"Subtarea ID {sub['id']}: {sub['title']}")
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""## Listar tareas columnas""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, PROJECT_ID, TOKEN, USER, requests):
|
||||
def listar_tareas_por_columna(api_url, usuario, token, project_id):
|
||||
"""
|
||||
Devuelve todas las _tareas agrupadas por columna dentro de un proyecto Kanboard.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API
|
||||
token (str): Token del usuario
|
||||
project_id (int): ID del proyecto
|
||||
|
||||
Retorna:
|
||||
dict: { 'columna': [ {_tarea}, {_tarea} ] }
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getBoard",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"project_id": project_id
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers={"Content-Type": "application/json"})
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al obtener el tablero:", data["error"])
|
||||
return {}
|
||||
|
||||
board = data.get("result", [])
|
||||
tareas_por_columna = {}
|
||||
|
||||
for swimlane in board:
|
||||
for columna in swimlane.get("columns", []):
|
||||
nombre_columna = columna["title"]
|
||||
tareas_por_columna[nombre_columna] = columna.get("tasks", [])
|
||||
|
||||
return tareas_por_columna
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso
|
||||
if __name__ == "__main__":
|
||||
|
||||
tareas_columna = listar_tareas_por_columna(API_URL, USER, TOKEN, PROJECT_ID)
|
||||
for columna, _tareas in tareas_columna.items():
|
||||
print(f"\n📦 {columna} ({len(_tareas)} tareas):")
|
||||
for _tarea in _tareas:
|
||||
print(f" ├─ [{_tarea['id']}] {_tarea['title']}")
|
||||
|
||||
return
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""## Mover tareas entre columnas""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, PROJECT_ID, TOKEN, USER, requests):
|
||||
def mover_tarea_columna(api_url, usuario, token, project_id, task_id, column_id, position=1, swimlane_id=0):
|
||||
"""
|
||||
Mueve una tarea a otra columna dentro de un proyecto Kanboard.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API (por ejemplo 'jsonrpc' o tu bot)
|
||||
token (str): Token de autenticación
|
||||
project_id (int): ID del proyecto
|
||||
task_id (int): ID de la tarea a mover
|
||||
column_id (int): ID de la columna destino
|
||||
position (int): Posición dentro de la columna (por defecto 1)
|
||||
swimlane_id (int): ID de la swimlane (0 = principal)
|
||||
|
||||
Retorna:
|
||||
bool: True si el movimiento fue exitoso, False en caso de error.
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "moveTaskPosition",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"project_id": project_id,
|
||||
"task_id": task_id,
|
||||
"column_id": column_id,
|
||||
"position": position,
|
||||
"swimlane_id": swimlane_id
|
||||
}
|
||||
}
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers=headers, timeout=10)
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al mover tarea:", data["error"])
|
||||
return False
|
||||
|
||||
result = data.get("result", False)
|
||||
if result:
|
||||
print(f"✅ Tarea {task_id} movida correctamente a la columna {column_id}.")
|
||||
else:
|
||||
print(f"⚠️ No se pudo mover la tarea {task_id}.")
|
||||
return result
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso
|
||||
if __name__ == "__main__":
|
||||
# API_URL = "http://host.docker.internal:8080/jsonrpc.php"
|
||||
# USER = "jsonrpc"
|
||||
# TOKEN = "792d8fdd6cbf69b3a32d800beaf48b958e4490dd9185c72c06c56061a591"
|
||||
# PROJECT_ID = 1
|
||||
TASK_ID = 6 # ID de la tarea a mover
|
||||
COLUMN_ID = 3 # Nueva columna (por ejemplo "En progreso")
|
||||
|
||||
mover_tarea_columna(API_URL, USER, TOKEN, PROJECT_ID, TASK_ID, COLUMN_ID)
|
||||
return
|
||||
|
||||
|
||||
@app.cell(column=1)
|
||||
def _():
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(mo):
|
||||
mo.md(r"""## Crear tarea""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(HTTPBasicAuth, requests):
|
||||
import random
|
||||
|
||||
def crear_tarea(api_url, usuario, token, project_id, titulo, descripcion="", swimlane_id=None, assignee_id=None, tags=None, priority=None):
|
||||
"""
|
||||
Crea una tarea en el backlog del proyecto indicado en Kanboard,
|
||||
con un color aleatorio, etiquetas (tags), prioridad
|
||||
y (opcionalmente) asignada a un usuario.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API
|
||||
token (str): Token del usuario
|
||||
project_id (int): ID del proyecto donde crear la tarea
|
||||
titulo (str): Título de la tarea
|
||||
descripcion (str): Descripción de la tarea
|
||||
swimlane_id (int): ID de la swimlane (opcional)
|
||||
assignee_id (int): ID del usuario a quien se asignará la tarea (opcional)
|
||||
tags (list[str]): Lista de etiquetas a añadir (opcional)
|
||||
priority (int): Prioridad numérica de la tarea (opcional)
|
||||
|
||||
Retorna:
|
||||
dict: Respuesta completa de la API
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
|
||||
# 🎨 Colores disponibles
|
||||
colores = [
|
||||
"yellow", "blue", "green", "purple",
|
||||
"red", "orange", "grey", "brown",
|
||||
"deep_orange", "dark_grey", "lime", "cyan"
|
||||
]
|
||||
color_aleatorio = random.choice(colores)
|
||||
|
||||
# 🧩 Payload principal
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "createTask",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"title": titulo,
|
||||
"description": descripcion,
|
||||
"project_id": project_id,
|
||||
"color_id": color_aleatorio
|
||||
}
|
||||
}
|
||||
|
||||
if swimlane_id is not None:
|
||||
payload["params"]["swimlane_id"] = swimlane_id
|
||||
|
||||
if assignee_id is not None:
|
||||
payload["params"]["owner_id"] = assignee_id
|
||||
|
||||
if priority is not None:
|
||||
payload["params"]["priority"] = priority
|
||||
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
# 🚀 Crear la tarea
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers=headers, timeout=10)
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al crear tarea:", data["error"])
|
||||
return data
|
||||
|
||||
task_id = data.get("result")
|
||||
print(f"✅ Tarea creada correctamente (ID {task_id}) en el proyecto {project_id}")
|
||||
|
||||
# 🏷️ Añadir etiquetas (si se proporcionaron)
|
||||
if tags:
|
||||
tag_payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "setTaskTags",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"project_id": project_id,
|
||||
"task_id": task_id,
|
||||
"tags": tags
|
||||
}
|
||||
}
|
||||
tag_response = requests.post(api_url, json=tag_payload, auth=auth, headers=headers, timeout=10)
|
||||
tag_data = tag_response.json()
|
||||
|
||||
if "error" in tag_data:
|
||||
print("⚠️ Error al añadir etiquetas:", tag_data["error"])
|
||||
else:
|
||||
print(f"🏷️ Etiquetas añadidas: {', '.join(tags)}")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso:
|
||||
if __name__ == "__main__":
|
||||
API_URL = "http://localhost:8080/jsonrpc.php" # desde WSL
|
||||
USER = "jsonrpc"
|
||||
TOKEN = "792d8fdd6cbf69b3a32d800beaf48b958e4490dd9185c72c06c56061a591"
|
||||
PROJECT_ID = 1
|
||||
ASSIGNEE_ID = 2 # ID de Egutierrez
|
||||
|
||||
crear_tarea(
|
||||
api_url=API_URL,
|
||||
usuario=USER,
|
||||
token=TOKEN,
|
||||
project_id=PROJECT_ID,
|
||||
titulo="Tarea con maxima prioridad",
|
||||
descripcion="Esta tarea tiene prioridad 3 y etiquetas automáticas.",
|
||||
assignee_id=ASSIGNEE_ID,
|
||||
tags=["etl", "prioridad-alta"],
|
||||
priority=3
|
||||
)
|
||||
return API_URL, PROJECT_ID, TOKEN, USER
|
||||
|
||||
|
||||
@app.cell(hide_code=True)
|
||||
def _(mo):
|
||||
mo.md(r"""## Editar tarea""")
|
||||
return
|
||||
|
||||
|
||||
@app.cell
|
||||
def _(API_URL, HTTPBasicAuth, TOKEN, USER, requests):
|
||||
def editar_tarea(api_url, usuario, token, task_id, titulo=None, descripcion=None,
|
||||
swimlane_id=None, assignee_id=None, tags=None, priority=None):
|
||||
"""
|
||||
Edita una tarea existente en Kanboard.
|
||||
Solo se envían los parámetros que se indiquen explícitamente.
|
||||
|
||||
Parámetros:
|
||||
api_url (str): URL del endpoint JSON-RPC
|
||||
usuario (str): Usuario con permisos API
|
||||
token (str): Token del usuario
|
||||
task_id (int): ID de la tarea a editar
|
||||
titulo (str): Nuevo título (opcional)
|
||||
descripcion (str): Nueva descripción (opcional)
|
||||
swimlane_id (int): Nueva swimlane (opcional)
|
||||
assignee_id (int): Nuevo responsable (opcional)
|
||||
tags (list[str]): Lista de etiquetas (opcional)
|
||||
priority (int): Nueva prioridad (opcional)
|
||||
|
||||
Retorna:
|
||||
dict: Respuesta completa de la API
|
||||
"""
|
||||
auth = HTTPBasicAuth(usuario, token)
|
||||
headers = {"Content-Type": "application/json"}
|
||||
|
||||
# 🧩 Construir payload con solo los campos que se quieren cambiar
|
||||
params = {"id": task_id}
|
||||
|
||||
if titulo is not None:
|
||||
params["title"] = titulo
|
||||
if descripcion is not None:
|
||||
params["description"] = descripcion
|
||||
if swimlane_id is not None:
|
||||
params["swimlane_id"] = swimlane_id
|
||||
if assignee_id is not None:
|
||||
params["owner_id"] = assignee_id
|
||||
if priority is not None:
|
||||
params["priority"] = priority
|
||||
|
||||
# Si no hay cambios, no se hace nada
|
||||
if len(params) == 1:
|
||||
print("⚠️ No se proporcionaron campos a modificar.")
|
||||
return {"warning": "sin cambios"}
|
||||
|
||||
payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "updateTask",
|
||||
"id": 1,
|
||||
"params": params
|
||||
}
|
||||
|
||||
# 🚀 Ejecutar la actualización
|
||||
response = requests.post(api_url, json=payload, auth=auth, headers=headers, timeout=10)
|
||||
data = response.json()
|
||||
|
||||
if "error" in data:
|
||||
print("❌ Error al editar tarea:", data["error"])
|
||||
return data
|
||||
|
||||
print(f"✅ Tarea {task_id} actualizada correctamente en Kanboard.")
|
||||
|
||||
# 🏷️ Actualizar etiquetas si se proporcionan
|
||||
if tags:
|
||||
# Para setTaskTags se requiere el project_id, lo obtenemos antes
|
||||
get_task_payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "getTask",
|
||||
"id": 1,
|
||||
"params": {"task_id": task_id}
|
||||
}
|
||||
task_response = requests.post(api_url, json=get_task_payload, auth=auth, headers=headers, timeout=10)
|
||||
project_id = task_response.json().get("result", {}).get("project_id")
|
||||
|
||||
if project_id:
|
||||
tag_payload = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "setTaskTags",
|
||||
"id": 1,
|
||||
"params": {
|
||||
"project_id": project_id,
|
||||
"task_id": task_id,
|
||||
"tags": tags
|
||||
}
|
||||
}
|
||||
tag_response = requests.post(api_url, json=tag_payload, auth=auth, headers=headers, timeout=10)
|
||||
tag_data = tag_response.json()
|
||||
|
||||
if "error" in tag_data:
|
||||
print("⚠️ Error al actualizar etiquetas:", tag_data["error"])
|
||||
else:
|
||||
print(f"🏷️ Etiquetas actualizadas: {', '.join(tags)}")
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# 🧪 Ejemplo de uso:
|
||||
if __name__ == "__main__":
|
||||
_TASK_ID = 8 # ID de la tarea existente
|
||||
|
||||
editar_tarea(
|
||||
api_url=API_URL,
|
||||
usuario=USER,
|
||||
token=TOKEN,
|
||||
task_id=_TASK_ID,
|
||||
titulo="🔥 Actualización directa desde Python",
|
||||
descripcion="Descripción actualizada sin afectar otros campos.",
|
||||
assignee_id=2,
|
||||
tags=["automatizada", "revisión", "python"],
|
||||
priority=2
|
||||
)
|
||||
|
||||
return
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run()
|
||||
Reference in New Issue
Block a user