diff --git a/apps/api/openapi.json b/apps/api/openapi.json index 92cae59..1869fb5 100644 --- a/apps/api/openapi.json +++ b/apps/api/openapi.json @@ -15066,7 +15066,7 @@ "path": { "type": "string", "nullable": true, - "example": "/p/WEB/proponer", + "example": "/p/WEB/propose", "description": "The form in the web app, while it takes them" }, "top": { diff --git a/apps/mcp/src/app/api/taskstream.schema.ts b/apps/mcp/src/app/api/taskstream.schema.ts index 0fd9df1..c86878d 100644 --- a/apps/mcp/src/app/api/taskstream.schema.ts +++ b/apps/mcp/src/app/api/taskstream.schema.ts @@ -3012,7 +3012,7 @@ export interface components { open: boolean; /** * @description The form in the web app, while it takes them - * @example /p/WEB/proponer + * @example /p/WEB/propose */ path: string | null; /** @description Open proposals, most voted first */ diff --git a/apps/web/src/app/app.routes.spec.ts b/apps/web/src/app/app.routes.spec.ts index 5c37eb6..1f2ed27 100644 --- a/apps/web/src/app/app.routes.spec.ts +++ b/apps/web/src/app/app.routes.spec.ts @@ -12,6 +12,8 @@ describe('appRoutes', () => { const children = app?.children ?? []; expect(children.map((route) => route.path)).toEqual([ '', + 'portfolio', + 'explore', 'cartera', 'explorar', 'p/:key', @@ -19,7 +21,10 @@ describe('appRoutes', () => { expect(children[0].canActivate).toContain(authGuard); expect(children[1].canActivate).toContain(authGuard); expect(children[2].canActivate).toBeUndefined(); - expect(children[3].canActivate).toBeUndefined(); + expect(children[5].canActivate).toBeUndefined(); + // The Spanish paths of shared links lead to the English ones. + expect(children[3].redirectTo).toBe('portfolio'); + expect(children[4].redirectTo).toBe('explore'); }); it('exposes every project section', () => { @@ -28,8 +33,9 @@ describe('appRoutes', () => { ?.children?.find((route) => route.path === 'p/:key'); expect(project?.children?.map((route) => route.path)).toEqual([ '', - 'board', 'proponer', + 'board', + 'propose', 'list', 'issues/:issueKey', 'backlog', diff --git a/apps/web/src/app/app.ts b/apps/web/src/app/app.ts index 229c7bb..be820e7 100644 --- a/apps/web/src/app/app.ts +++ b/apps/web/src/app/app.ts @@ -45,7 +45,7 @@ import { Cartera @@ -54,7 +54,7 @@ import { Explorar diff --git a/docs/03-api.md b/docs/03-api.md index 4bc39c9..94bb170 100644 --- a/docs/03-api.md +++ b/docs/03-api.md @@ -70,7 +70,7 @@ lee igual que un anónimo. Las subscriptions exigen sesión; con ella, también en el primer estado, de tipo Bug o Feature (o el primer tipo activo). No se pide correo, porque quedaría a la vista. Contra el spam, el campo `website` es una trampa (si llega relleno se responde como si nada y no se guarda) y cada dirección envía como mucho 5 cada 15 minutos (429); el contador vive en Redis (`RateLimitStore`), así que vale igual con -varias instancias. Los propietarios y admins del proyecto reciben un aviso (`PROPOSED`). La web tiene el formulario en `/p/{CLAVE}/proponer`, enlazado en la cabecera del proyecto. +varias instancias. Los propietarios y admins del proyecto reciben un aviso (`PROPOSED`). La web tiene el formulario en `/p/{CLAVE}/propose`, enlazado en la cabecera del proyecto. **Votos**: quien tenga sesión vota los tickets de un proyecto público, y los miembros los de uno privado (`voteIssue(issueId, on)`, `PUT/DELETE /api/issues/{issue}/vote`). Cada ticket da `votes` y `voted` (si he votado diff --git a/docs/04-cliente-web.md b/docs/04-cliente-web.md index 53a7463..13ae381 100644 --- a/docs/04-cliente-web.md +++ b/docs/04-cliente-web.md @@ -270,7 +270,7 @@ visualización de la plataforma: ### Proyectos públicos y visitantes sin sesión -- Solo la portada (`/`) exige sesión. `/explorar` y las páginas de proyecto (`/p/:key/…`) no: la API decide qué ve +- Solo la portada (`/`) exige sesión. `/explore` y las páginas de proyecto (`/p/:key/…`) no: la API decide qué ve cada visitante, y las páginas ya ocultan lo que no puede cambiar (`canContribute`, `canManage`). - Sin sesión, la cabecera muestra «Explorar» e «Iniciar sesión»; dentro de un proyecto público aparece un aviso de modo lectura, y en uno privado (o inexistente), el enlace para iniciar sesión volviendo a esa página (`returnUrl`). @@ -287,8 +287,8 @@ visualización de la plataforma: | `/login` | Inicio de sesión (solo sin sesión) | | `/auth/callback` | Retorno de Pireon (PKCE) | | `/` | Inicio: saludo según la hora con el resumen del día, «Ir a…» (`WEB-12`), primeros pasos, cuatro cifras (`ts-home-kpis`: abiertos míos, esperando QA, terminados por mí y por el equipo esta semana), la semana (`ts-week-agenda`), mis vistas guardadas y dos columnas: mis tickets y lo último en mis proyectos; sprints en curso, esperando QA, que sigo, próximas releases, quién está ahora y «Retomar». Debajo, mis proyectos con su actividad | -| `/cartera` | Cartera (con sesión): una tarjeta por proyecto activo con lo abierto y en riesgo, el sprint en curso (¿llega?), las próximas releases con su previsión y las épicas abiertas | -| `/explorar` | Proyectos públicos (sin sesión) | +| `/portfolio` | Cartera (con sesión): una tarjeta por proyecto activo con lo abierto y en riesgo, el sprint en curso (¿llega?), las próximas releases con su previsión y las épicas abiertas; en directo: se vuelve a leer sola cuando cambia un ticket, sprint o release de esos proyectos | +| `/explore` | Proyectos públicos (sin sesión) | | `/p/:key/board` | Tablero kanban (`?release=` y `?assignee=` preseleccionan los filtros) | | `/p/:key/issues/:issueKey` | Ticket. Encima del título, quién más lo está viendo o editando ahora (`PresenceFacade`: late cada 10 s; editar es tener abierto el formulario del ticket o de un comentario, o estar escribiendo uno) | | `/p/:key/releases` | Releases | @@ -296,10 +296,12 @@ visualización de la plataforma: | `/p/:key/roadmap` | Hoja de ruta: épicas en el tiempo, con sprints y releases; flechas «bloquea» / «depende de» entre épicas y aviso si una empieza antes de que acabe la que la bloquea | | `/p/:key/dashboard` | Seguimiento: cifras, flujo por estado, lo que ha cambiado desde tu última visita (guardada en este navegador), sprint en curso, tickets en riesgo, previsión de las próximas releases, antigüedad de lo que está en curso, cuellos de botella, salud del backlog (cada número abre la lista filtrada: `?missing=estimate`, `area`, `assignee` o `?staleDays=90`), calidad (bugs por prioridad y por semana, QA por área, bugs tras cada release), abiertos por un campo de lista a elegir, equipo con sus puntos abiertos y tipos. Se recarga solo con cada cambio | | `/p/:key/analytics` | Estadísticas: creados vs. resueltos, flujo acumulado, burnup de una release, tiempos de ciclo y entrega, QA y resueltos por persona (30 días a 1 año) | -| `/p/:key/settings` | Configuración (propietario y admins; pestaña oculta para el resto), con un menú de secciones (`?seccion=`): General (visibilidad, propuestas), Flujo de trabajo (estados, transiciones, definición de «Hecho»), Tickets (tipos, áreas, campos), Equipos, Automatizaciones, Integraciones (Git, webhooks), Importar y exportar y Zona peligrosa; archivar en lugar de borrar, y un punto en el menú donde hay cambios sin guardar | +| `/p/:key/settings` | Configuración (propietario y admins; pestaña oculta para el resto), con un menú de secciones (`?section=`): General (visibilidad, propuestas), Flujo de trabajo (estados, transiciones, definición de «Hecho»), Tickets (tipos, áreas, campos), Equipos, Automatizaciones, Integraciones (Git, webhooks), Importar y exportar y Zona peligrosa; archivar en lugar de borrar, y un punto en el menú donde hay cambios sin guardar | | `/p/:key/activity` | Actividad en vivo | +| `/p/:key/propose` | Formulario público para reportar un error o proponer una idea sin cuenta (si el proyecto lo tiene abierto); llegan como tickets con la etiqueta «propuesta» | | `/p/:key/members` | Miembros, con su rol (propietario, admin, miembro, lector o invitado). Un invitado de un proyecto privado solo tiene Tablero, Lista y Miembros, ve solo sus tickets y abre tickets sin asignarlos ni planificarlos | Solo `/` está protegida por `authGuard` (redirige a `/login?returnUrl=…`); `/login` y `/auth/callback` son para quien no tiene sesión, y el resto se puede abrir sin ella si el proyecto es público. Los parámetros de ruta llegan como inputs de -los componentes (`withComponentInputBinding`). +los componentes (`withComponentInputBinding`). Las rutas van en inglés; las antiguas en castellano (`/cartera`, +`/explorar`, `/p/:key/proponer`) redirigen a las nuevas, para que sigan valiendo los enlaces ya compartidos. diff --git a/docs/10-futuro.md b/docs/10-futuro.md index 3520aec..9f62967 100644 --- a/docs/10-futuro.md +++ b/docs/10-futuro.md @@ -121,7 +121,7 @@ Mucho trabajo para lo que aportan hoy; se pueden recuperar si alguien los necesi - Presencia: en cada ticket se ve quién más lo está viendo o editando en ese momento. - Rol «invitado»: para clientes o gente de fuera; en un proyecto privado solo ve los tickets en los que participa, abre tickets y comenta en los suyos. -- Vista de cartera (`/cartera`): todos tus proyectos activos de un vistazo, con su riesgo, sprint, releases y épicas. +- Vista de cartera (`/portfolio`): todos tus proyectos activos de un vistazo, con su riesgo, sprint, releases y épicas. - Una portada con vida: saludo y resumen del día, la semana que viene, lo último en tus proyectos, quién está ahora, la semana en cifras (tuya y del equipo, con racha), sprints en curso, «Retomar», tarjetas de proyecto con actividad, qué coger cuando no tienes nada y primeros pasos para quien empieza. También por MCP (`get_my_week`). diff --git a/docs/TaskStream-Documentacion.docx b/docs/TaskStream-Documentacion.docx index 341092e..9d1eec1 100644 Binary files a/docs/TaskStream-Documentacion.docx and b/docs/TaskStream-Documentacion.docx differ diff --git a/docs/TaskStream-Documentacion.pdf b/docs/TaskStream-Documentacion.pdf index 7daef32..d8d66f3 100644 Binary files a/docs/TaskStream-Documentacion.pdf and b/docs/TaskStream-Documentacion.pdf differ diff --git a/libs/api/tracker/application/src/lib/queries/get-showcase.query.ts b/libs/api/tracker/application/src/lib/queries/get-showcase.query.ts index d48e04e..9aa34a3 100644 --- a/libs/api/tracker/application/src/lib/queries/get-showcase.query.ts +++ b/libs/api/tracker/application/src/lib/queries/get-showcase.query.ts @@ -169,7 +169,7 @@ export class GetShowcaseQueryHandler })), proposals: { open: project.acceptsProposals, - path: project.acceptsProposals ? `/p/${project.key}/proponer` : null, + path: project.acceptsProposals ? `/p/${project.key}/propose` : null, top: [...proposals.items] .sort((a, b) => b.votes - a.votes) .slice(0, 10) diff --git a/libs/api/tracker/presenters/src/lib/http/dto/responses.dto.ts b/libs/api/tracker/presenters/src/lib/http/dto/responses.dto.ts index 9d3358c..2a91fa4 100644 --- a/libs/api/tracker/presenters/src/lib/http/dto/responses.dto.ts +++ b/libs/api/tracker/presenters/src/lib/http/dto/responses.dto.ts @@ -361,7 +361,7 @@ class ShowcaseProposalsDto { @ApiProperty({ type: String, nullable: true, - example: '/p/WEB/proponer', + example: '/p/WEB/propose', description: 'The form in the web app, while it takes them', }) path!: string | null; diff --git a/libs/web/identity/presenters/src/lib/pages/login.page.ts b/libs/web/identity/presenters/src/lib/pages/login.page.ts index 98359cf..bed720c 100644 --- a/libs/web/identity/presenters/src/lib/pages/login.page.ts +++ b/libs/web/identity/presenters/src/lib/pages/login.page.ts @@ -113,7 +113,7 @@ const SAMPLE_FEED = [

¿Solo quieres mirar? - Proyectos públicos → + Proyectos públicos →