KB-PLUGIN-043: padroes de UX de card kanban (anatomia nativa, own_ticket, is_private, TTR, prioridade, gotchas CSS/JS)
Aprendizados do mindscrum 0.7.0-0.9.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6827e7fcd5
commit
63e650ed66
2 changed files with 121 additions and 0 deletions
23
index.json
23
index.json
|
|
@ -826,6 +826,29 @@
|
|||
"severity": "high",
|
||||
"path": "records/plugin-dev/KB-PLUGIN-042-glpi11-effective-duration-overwrite-native-effort-rollup.md",
|
||||
"summary": "id: KB-PLUGIN-042"
|
||||
},
|
||||
{
|
||||
"id": "KB-PLUGIN-043",
|
||||
"title": "\"GLPI 11 — Padrões de UX de card kanban em plugin: anatomia do card nativo, own_ticket, is_private, TTR, cores de prioridade e gotchas de CSS\"",
|
||||
"domain": "plugin-dev",
|
||||
"tags": [
|
||||
"glpi11",
|
||||
"plugin",
|
||||
"kanban",
|
||||
"card",
|
||||
"ux",
|
||||
"own-ticket",
|
||||
"itilfollowup",
|
||||
"time-to-resolve",
|
||||
"priority",
|
||||
"css",
|
||||
"gotcha",
|
||||
"mindscrum"
|
||||
],
|
||||
"status": "active",
|
||||
"severity": "medium",
|
||||
"path": "records/plugin-dev/KB-PLUGIN-043-glpi11-kanban-card-ux-patterns.md",
|
||||
"summary": "id: KB-PLUGIN-043"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,98 @@
|
|||
---
|
||||
id: KB-PLUGIN-043
|
||||
title: "GLPI 11 — Padrões de UX de card kanban em plugin: anatomia do card nativo, own_ticket, is_private, TTR, cores de prioridade e gotchas de CSS"
|
||||
domain: plugin-dev
|
||||
tags:
|
||||
- glpi11
|
||||
- plugin
|
||||
- kanban
|
||||
- card
|
||||
- ux
|
||||
- own-ticket
|
||||
- itilfollowup
|
||||
- time-to-resolve
|
||||
- priority
|
||||
- css
|
||||
- gotcha
|
||||
- mindscrum
|
||||
status: active
|
||||
severity: medium
|
||||
created_at: 2026-07-13
|
||||
updated_at: 2026-07-13
|
||||
applies_to:
|
||||
- GLPI 11.0.8 dev
|
||||
- plugin mindscrum 0.7.0–0.9.0
|
||||
related_records:
|
||||
- KB-PLUGIN-040
|
||||
- KB-PLUGIN-041
|
||||
- KB-PLUGIN-042
|
||||
---
|
||||
|
||||
# GLPI 11 — Padrões de UX de card kanban em plugin (aprendizados mindscrum 0.7–0.9)
|
||||
|
||||
## Anatomia do card do Kanban NATIVO (receita para replicar)
|
||||
|
||||
Fonte: `Project::getKanbanColumns()` + Vue `Kanban-Card` (compilado em
|
||||
`public/build/vue/vue-sfc/`). O card nativo carrega:
|
||||
- `title`; **descrição** via `RichText::getTextFromHtml($content)` (em `_metadata`);
|
||||
- **link do pai** ("Subtask of X") → `getFormURLWithID` do pai;
|
||||
- contador "x / y tasks complete" a partir de `_steps` (`percent_done === 100`);
|
||||
- **barra de progresso** `Html::progress(100, $percent)` (Tabler `.progress`);
|
||||
- `_team` (badges de membros), `due_date` = `Html::convDateTime(plan_end_date)`;
|
||||
- `_form_link`; hooks de plugin `PRE/POST_KANBAN_CONTENT` e `KANBAN_ITEM_METADATA`.
|
||||
|
||||
Replicar server-side com queries EM LOTE (1 p/ equipes, 1 p/ contagens
|
||||
`COUNT/SUM(GROUPBY)`, 1 p/ pais via join, 1 p/ nomes de usuários) — sem N+1.
|
||||
|
||||
## Técnicos elegíveis para atribuição (dropdown nativo)
|
||||
|
||||
`User::getSqlSearchResult(false, 'own_ticket', $entities_id, 0, [], '', 0, $limit)`
|
||||
→ retorna o **iterator** pronto. `'own_ticket'` é o right que o próprio core usa
|
||||
para o ator "atribuído" de Ticket (exclui contas só-requisitantes). Para equipe de
|
||||
projeto, right `'all'` na entidade do projeto.
|
||||
|
||||
## Followup privado (nota "só técnico")
|
||||
|
||||
`ITILFollowup` nativo: campo `is_private`; right `followup` com
|
||||
`ITILFollowup::SEEPRIVATE`. Visibilidade: privada aparece só para o AUTOR ou quem
|
||||
tem SEEPRIVATE — replicar esse filtro ao listar followups por fora da API padrão.
|
||||
|
||||
## time_to_resolve (prazo/SLA manual)
|
||||
|
||||
- `Ticket` NÃO tem data prevista de início nativa. Datas do chamado: `date`
|
||||
(abertura), `time_to_resolve`, `time_to_own` (+ `internal_*`). Início planejado
|
||||
vive nas tasks (`TicketTask.begin/end`, `ProjectTask.plan_*`).
|
||||
- `time_to_resolve` aceita valor manual no `add()`/`update()` — herdar
|
||||
`plan_end_date` da task de projeto ao criar chamado dá visão de estouro "de graça".
|
||||
- ⚠️ **Gotcha:** o core DESCARTA SILENCIOSAMENTE `time_to_resolve` anterior à data
|
||||
de abertura (`update()` retorna true e o campo fica null). Em testes, usar
|
||||
abertura retroativa (`date` no input do add) para simular estouro.
|
||||
- Barrinha de "SLA": `% = (now - date) / (time_to_resolve - date)`, capado em 100.
|
||||
|
||||
## Cores/ícones de prioridade
|
||||
|
||||
Cores nativas configuráveis em `$CFG_GLPI['priority_1'..'priority_6']`
|
||||
(tons de vermelho claro — são cores de FUNDO). Para UI discreta, preferir ícone
|
||||
Tabler + tooltip (`getPriorityName`): chevrons (baixas), `ti-equal` (média),
|
||||
`ti-exclamation-circle`/`ti-alert-triangle`/`ti-alert-octagon` (altas).
|
||||
|
||||
## Gotchas de CSS/JS em modal custom
|
||||
|
||||
- **Keyframe que anima `transform` SUBSTITUI o transform do elemento** durante a
|
||||
animação: se a centralização usa `translate(-50%,-50%)`, o elemento "nasce"
|
||||
deslocado e pula ao final. Solução: centralizar com flex no wrapper
|
||||
(`position:fixed; inset:0; display:flex`) e deixar o keyframe só com scale.
|
||||
- Flatpickr com `altInput`: estilizar via `altInputClass` (o input visível é NOVO;
|
||||
regras no input original não pegam) — senão o layout quebra.
|
||||
- `.catch()` de `fetch(...).then(render)` captura exceções do RENDER também — um
|
||||
erro de JS no template do modal aparece como se fosse falha de rede/endpoint.
|
||||
(Sintoma clássico: "modal funciona pra um itemtype e não pra outro".)
|
||||
- Popover/sub-modal empilhado sobre modal custom: z-index acima (1070+) e Esc
|
||||
tratado em pilha (fecha o de cima primeiro).
|
||||
|
||||
## Espelhamento de descrição (padrão mindscrum)
|
||||
|
||||
Spawn task→chamado importa título + `content` (texto via RichText) + prazo. A
|
||||
seção "Descrição" do modal aponta para a FONTE: projeto → `Project.content`;
|
||||
chamado → `ProjectTask.content` da task de origem (fallback: do chamado). Editar
|
||||
grava na fonte via `update()` — allowlist de itemtype/campo no endpoint.
|
||||
Loading…
Reference in a new issue