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