Merge manually pull-request #2658
This commit is contained in:
parent
f1d6673050
commit
20c187880c
|
|
@ -0,0 +1,24 @@
|
|||
Análisis para tareas
|
||||
===================
|
||||
|
||||
Cada tarea tiene una sección de análisis disponible en el menu izquierdo en la vista de tarea.
|
||||
|
||||
Espera y tiempo de ciclo
|
||||
-------------------
|
||||
|
||||

|
||||
|
||||
- El tiempo de espera es el tiempo entre la creacion de la tarea y la fecha de finalización (Tarea cerrada).
|
||||
- El tiempo de ciclo es el tiempo entre la fecha de inicio y la fecha de finalización.
|
||||
- Si la tarea no esta cerrada el tiempo actual es usado en lugar de la fecha de finalización.
|
||||
- Si la fecha de inicio no es especificada, el tiempo de ciclo no es calculado.
|
||||
|
||||
Nota: Puede configurar una accion automatica para definir la fecha de inicio automaticamente cuando se mueve una tarea a la columna de su eleccion.
|
||||
|
||||
El tiempo invertido en cada columna
|
||||
---------------------------
|
||||
|
||||

|
||||
|
||||
- Esta gráfico muestra el total de tiempo invertido en cada columna para la tarea.
|
||||
- El tiempo invertido es calculado hasta que la tarea es cerrada.
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
Modo colapsar y expandir
|
||||
===========================
|
||||
|
||||
Las tares en el tablero pueden visualizarse en modo colapsado o en modo expandido.
|
||||
El cambio entre el desplazamiento horizontal y la vista compacta se puede hacer con la combinación de teclas **"s"** o usar el menu drop-down que esta parte superior izquierda.
|
||||
|
||||
Modo de colapsado
|
||||
--------------
|
||||
|
||||

|
||||
|
||||
- Si la tarea es asignada a alguien, las iniciales de la persona se muestran junto al número de tareas
|
||||
- Si el titulo de la tarea es demasiado largo, tu puedes poner el puntero del ratón sobre la tarea de mostrar una información sobre herramientas con el título completo
|
||||
|
||||
Modo expansivo
|
||||
--------------
|
||||
|
||||

|
||||
|
|
@ -0,0 +1,25 @@
|
|||
Configuración del tablero
|
||||
==========================
|
||||
|
||||
Ir al menu **Configuraciones **, elije **Ajustes de tablero ** a la izquierda.
|
||||
|
||||

|
||||
|
||||
### Resaltado de tarea
|
||||
|
||||
Esta caracterista muestra una sombra alrededor de la tarea cuando una tarea se trasladó recientemente
|
||||
|
||||
Establecer el valor 0 para desactivar esta caracterista, 2 dias por default (172800 segundos).
|
||||
|
||||
Todo lo trasladó desde de 2 dias tendra una sombra alrededor de la tarea.
|
||||
|
||||
### Recargar el intervalo para la pizarra publica
|
||||
|
||||
Cuando tu compartes un tablero, la pagina se refresca cada 60 segundos automaticamente por default.
|
||||
|
||||
### Refrescar el intervalo para un tablero privado
|
||||
|
||||
Cuando su navegador está abierto un tablero, Kanboard comprueba cada 10 segundos si algo ha sido cambiado por otra persona.
|
||||
|
||||
Técnicamente este proceso se lleva a cabo por el Ajax.
|
||||
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
Horizontal scrolling y modo compacto
|
||||
=====================================
|
||||
|
||||
Cuando el tablero no puede caber en su pantalla , una barra de scroll horizontal
|
||||
When the board cannot fit on your screen, a horizontal scroll bar aparecerá en la parte inferior.
|
||||
|
||||
Sin embargo, es posible cambiar a una vista de modo compacto para visualizar todas las columnas en su pantalla.
|
||||
|
||||

|
||||
|
||||
Cambiar entre scrolling y vista compacta
|
||||
El cambio entre el desplazamiento horizontal y la vista compacta se puede hacer con la combinación de teclas **"c"** o usar el menu drop-down que esta parte superior izquierda.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
Mostrar y ocultar columnas en el tablero
|
||||
==================================
|
||||
|
||||
Se puede ocultar o visualizar columnas muy facilmente en el tablero:
|
||||
|
||||

|
||||
|
||||
Para ocultar una columna, click en la columna escoge en el menu dropdown "ocultar esta columna" :
|
||||
|
||||

|
||||
|
||||
Para mostar nuevamente la columna, click en el icono con el simbolo de suma "plus icon"
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
Directrices del contribuyente
|
||||
======================
|
||||
|
||||
¿Cómo puedo ayudar?
|
||||
-----------------
|
||||
|
||||
Kanboard no es perfecto, pero hay muchas maneras de ayudar:
|
||||
|
||||
- Dar opinión
|
||||
- Informar de los errores
|
||||
- Añadir o actualizar traducciones
|
||||
- Mejorar la documentación
|
||||
- Código de Escritura
|
||||
- Dile a tus amigos que Kanboard es impresionante
|
||||
|
||||
Antes de hacer cualquier empresa grande, abrir un nuevo tema y explicar su propuesta.
|
||||
|
||||
Quiero dar retroalimentación
|
||||
-----------------------
|
||||
- Usted piensa que algo debe ser mejorado (interface de usuario, peticiones de características)
|
||||
- Comprobar si aún no se propuso su idea
|
||||
- Abrir un nuevo tema
|
||||
- Describir su idea
|
||||
- Puede también hacer un voto con +1 en las propuestas existentes
|
||||
|
||||
Quiero informar de un error
|
||||
---------------------------
|
||||
|
||||
- Compruebe si el problema no se ha comunicado anteriormente
|
||||
- Abrir un nuevo ticket
|
||||
- Explicar lo que está roto
|
||||
- Describir la forma de reproducir el error
|
||||
- Describir su entorno (versión Kanboard, sistema operativo, servidor web, Versión de PHP , la versión de la base de datos, el proveedor de alojamiento)}
|
||||
|
||||
Deseo traducir Kanboard
|
||||
----------------------------
|
||||
Kanboard se traduce en muchos idiomas.
|
||||
|
||||
Sin embargo, las traducciones no están completas, observe la [guía de traducción para contribuir] (https://kanboard.net/documentation/translations).
|
||||
|
||||
|
||||
Quiero mejorar la documentación
|
||||
-----------------------------------
|
||||
- ¿Crees que algo no está claro, existen errores gramaticales, errores tipográficos, otra cosa ?
|
||||
- La documentación está escrita en Markdown y se almacena en la carpeta `docs`.
|
||||
- Editar los archivos y enviar un Pull-Request
|
||||
- La documentación se sincroniza con el repositorio y el sitio web oficial .
|
||||
|
||||
Quiero contribuir al código
|
||||
--------------------------------
|
||||
Los pulls son siempre bienvenidos , al ser aceptado se tiene que seguir estas directrices:
|
||||
|
||||
- ** Antes de hacer cualquier cambio grande o propuesta de diseño, abrir un nuevo ticket en comenzar una discusión **.
|
||||
- Si desea agregar una nueva función, respetar la filosofía detrás de Kanboard. ** Nos centramos en la simplicidad **, no queremos tener un software sobrecargado .
|
||||
- Lo mismo se aplica para la interface de usuario, ** ** simplicidad y eficiencia.
|
||||
- Enviar un solo pull por característica o corrección de errores.
|
||||
- Un pull más pequeño es más fácil y más rápido para revisar y fusionarlo.
|
||||
- Asegurarse [ de hacer las pruebas unitarias (tests.markdown).
|
||||
- Respetar los [estandares de codificación] (coding-standards.markdown).
|
||||
- Escribir código mantenible, evitar la duplicación de código, usar las buenas practicas de PHP.
|
||||
En cualquier caso, si no está seguro acerca de algo abierto crear un uevo ticket.
|
||||
|
||||
Dile a tus amigos que Kanboard es impresionante
|
||||
---------------------------------------------
|
||||
|
||||
Si utiliza Kanboard, corre la voz que le rodean.
|
||||
Diles que es software libre y de código abierto esto es cool.
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
Arquitectura de autenticación
|
||||
=============================
|
||||
|
||||
Kanboard provee una flexible y conectable arquitectura de autenticación.
|
||||
|
||||
Por default, el usuario puede autenticarse con multiple metodos:
|
||||
|
||||
- Autenticación por usuario y password (Base de datos local y LDAP)
|
||||
- Autenticación OAuth2
|
||||
- Autenticación Reverse-Proxy
|
||||
- Autenticación basada en Cookie (Recuerdame)
|
||||
|
||||
Además, despues de una autenticación satisfactoria un puede hacerse post de autenticación Two-Factor .
|
||||
Kanboard sopoarta nativamente el standart TOTP.
|
||||
|
||||
Interfaces de autenticación
|
||||
----------------------------
|
||||
|
||||
Para tener un sistema conectable, los drivers de autenticación deben implementar un conjunto de interfaces
|
||||
|
||||
| Interface | Rol |
|
||||
|------------------------------------------|------------------------------------------------------------------|
|
||||
| AuthenticationProviderInterface | Interface base para otras interfaces de autenticación |
|
||||
| PreAuthenticationProviderInterface | The user is already authenticated al alcanzar la aplicación, Usualmente los servidores web definen algunas variables de entorno |
|
||||
| PasswordAuthenticationProviderInterface | El metodo de autenticación que usa el username y password provienen del formulario de login |
|
||||
| OAuthAuthenticationProviderInterface | Proveedores OAuth2 |
|
||||
| PostAuthenticationProviderInterface | Drivers de autenticación Two-Factor ,pide el código a confirmar |
|
||||
| SessionCheckProviderInterface | Los proveedores que son capaces de comprobar si la sesión de usuario es válida |
|
||||
|
||||
### Ejemplos de autenticación de proveedores:
|
||||
|
||||
- Database por default metodos a implementar `PasswordAuthenticationProviderInterface` y `SessionCheckProviderInterface`
|
||||
- Reverse-Proxy metodos a implementar `PreAuthenticationProviderInterface` y `SessionCheckProviderInterface`
|
||||
- Google metodos a implementar `OAuthAuthenticationProviderInterface`
|
||||
- LDAP metodos a implementar `PasswordAuthenticationProviderInterface`
|
||||
- RememberMe cookie metodos a implementar `PreAuthenticationProviderInterface`
|
||||
- Two-Factor TOTP metodos a implementar `PostAuthenticationProviderInterface`
|
||||
|
||||
flujo de trabajo de autenticación ** Workflow **
|
||||
------------------------------------------------
|
||||
|
||||
Para cada peticion HTTP:
|
||||
|
||||
1. Si la sesión de usuario esta abierta, ejecuta el registro de proveedores que implementa`SessionCheckProviderInterface`
|
||||
2. Ejecuta todos los proveedores que implementa `PreAuthenticationProviderInterface`
|
||||
3. Si el usuario final hace un submit al formulario del login, Los proveedores que implementa `PasswordAuthenticationProviderInterface` are executed
|
||||
4. Si el usuario final quiere usar OAuth2, el selecciona el proveedor a ejecutar
|
||||
5. Despues de una autenticación satisfactoria, el ultimo registro utilizará `PostAuthenticationProviderInterface`
|
||||
6. Sincronizar la información del usuario si es necesario
|
||||
|
||||
Este workflow es manejado por la clase `Kanboard\Core\Security\AuthenticationManager`.
|
||||
|
||||
Eventos disparados:
|
||||
|
||||
- `AuthenticationManager::EVENT_SUCCESS`: autenticación satisfactoria
|
||||
- `AuthenticationManager::EVENT_FAILURE`: autenticación fallida
|
||||
|
||||
Cada vez que se produce un evento de fallo , el contador de intentos fallidos se incrementa.
|
||||
|
||||
La cuenta de usuario se puede bloquear para el período de tiempo configurado y un captcha puede ser mostrado para evitar ataques de fuerza bruta .
|
||||
|
||||
Interface de usuario del proveedor
|
||||
---------------------------------
|
||||
|
||||
Cuando la autenticación es satisfactoria, la `AuthenticationManager` pedura la información del usuario para que el driver llame al metodo `getUser()`.
|
||||
Este metodo debe regresar un objeto que implementa la interface `Kanboard\Core\User\UserProviderInterface`.
|
||||
|
||||
Esta clase abstracta reune la información dede otro sistema.
|
||||
|
||||
Ejemplos :
|
||||
|
||||
- `DatabaseUserProvider` proporciona información para un usuario interno
|
||||
- `LdapUserProvider` para un usuario LDAP
|
||||
- `ReverseProxyUserProvider` para un usuario Reverse-Proxy
|
||||
- `GoogleUserProvider` represtan un usuario de Google
|
||||
|
||||
Los métodos para la interface del proveedor de Usuario:
|
||||
|
||||
- `isUserCreationAllowed()`: Regresa true para permitir la creación automática de usuarios
|
||||
- `getExternalIdColumn()`: Obtener Identificación del nombre de la columna externa (google_id, github_id, gitlab_id...)
|
||||
- `getInternalId()`: Obtener el id interno de la base de datos
|
||||
- `getExternalId()`: Obtener el id externo(Unique id)
|
||||
- `getRole()`: Obtener el rol de usuario
|
||||
- `getUsername()`: Obtener en nombre de usuario ** username **
|
||||
- `getName()`: Obtener nombre completo del usuario
|
||||
- `getEmail()`: Obtener el correo electronico del usuario
|
||||
- `getExternalGroupIds()`: Obtiene los ids externos del grupo, automáticamente sincroniza la membresia del grupo y la presenta
|
||||
- `getExtraAttributes()`: Obtiene los atributos extras para ser mostrados a el usuario durante la sincronización local
|
||||
|
||||
No es obligatorio que el metodo devuelva un valor.
|
||||
|
||||
Sincronización de un usuario local
|
||||
----------------------------------
|
||||
|
||||
La información del usuario puede ser sincronizada automáticamente con la base de datos local.
|
||||
|
||||
- Si el metodo`getInternalId()` regresa un valor no realiza la sincronización
|
||||
- Los metodos `getExternalIdColumn()` y `getExternalId()` debe regresar un valor para sincronizar el usuario
|
||||
- Las propiedades que regresan un ** String ** vacios no se sincronizan
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
Plugin de autenticación
|
||||
=====================
|
||||
|
||||
EL nuevo backend de autenticación se puede escribir con muy pocas lineas de codigo.
|
||||
|
||||
Registro de proveedores
|
||||
-----------------------
|
||||
|
||||
En el metodo `initialize()` nuestro plugin, llama al metodo `register()` de la clase `AuthenticationManager`:
|
||||
|
||||
```php
|
||||
public function initialize()
|
||||
{
|
||||
$this->authenticationManager->register(new ReverseProxyLdapAuth($this->container));
|
||||
}
|
||||
```
|
||||
|
||||
El objeto proveniente de el metodo `register()` debe implementar one de las interfaces de autenticación predefidas.
|
||||
|
||||
Esas interfaces estan definidas en los namespace `Kanboard\Core\Security`:
|
||||
|
||||
- `Kanboard\Core\Security\PreAuthenticationProviderInterface`
|
||||
- `Kanboard\Core\Security\PostAuthenticationProviderInterface`
|
||||
- `Kanboard\Core\Security\PasswordAuthenticationProviderInterface`
|
||||
- `Kanboard\Core\Security\OAuthAuthenticationProviderInterface`
|
||||
|
||||
|
||||
|
||||
El único requisito es implementar las interfaces, la clase se puede escribir de la manera deseada y situado en cualquier lugar en el disco
|
||||
|
||||
Usuario del proveedor
|
||||
----------------------
|
||||
|
||||
Cuando la autenticación es satisfactoria, tu driver debe regresar un objato que representa al usuario.
|
||||
Este objeto debe implementasr la interface `Kanboard\Core\User\UserProviderInterface`.
|
||||
|
||||
Ejemplo de plugin de autenticación
|
||||
----------------------------------
|
||||
|
||||
- [Autenticación de proveedores incluido en kanboard](https://github.com/kanboard/kanboard/tree/master/app/Auth)
|
||||
- [Reverse-Proxy Autenticación con soporte LDAP](https://github.com/kanboard/plugin-reverse-proxy-ldap)
|
||||
- [Two-Factor Autenticación SMS](https://github.com/kanboard/plugin-sms-2fa)
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
Arquitecuta de autorización
|
||||
===========================
|
||||
|
||||
Kanboard [soporta multiples roles](roles.markdown) a nivel de aplicación y a nivel de proyecto.
|
||||
|
||||
Workflow de autorización
|
||||
--------------------------
|
||||
|
||||
Para cada solicitud HTTP:
|
||||
|
||||
1. Autorizar o no el acceso a los recursos en base a la lista de acceso a las aplicaciones
|
||||
2. Si el recurso es para un projecto (board, tarea...):
|
||||
1. Extrae los roles de usuario para este proyecto
|
||||
2. Permitir/Denegar accesos basados en el mapa de acceso del proyecto
|
||||
|
||||
Extendiendo mapa de accesos
|
||||
---------------------------
|
||||
|
||||
Lista de accesos (ACL) se basa en el nombre de clase del controlador y el nombre del método
|
||||
La lista de acceso está a cargo de la clase `Kanboard\Core\Security\AccessMap`.
|
||||
|
||||
Hay dos mapa de acceso: una para la aplicación y la otra para un proyecto.
|
||||
|
||||
- Acceso al mapa de aplicación : `$this->applicationAccessMap`
|
||||
- Acceso al mapa del proyecto: `$this->projectAccessMap`
|
||||
|
||||
Ejemplos para definir una nueva política para tu plugin:
|
||||
|
||||
```php
|
||||
// Todos los metodos de la clase MyController:
|
||||
$this->projectAccessMap->add('MyController', '*', Role::PROJECT_MANAGER);
|
||||
|
||||
// Todos los metodos:
|
||||
$this->projectAccessMap->add('MyOtherController', array('create', 'save'), Role::PROJECT_MEMBER);
|
||||
```
|
||||
|
||||
Los roles estan defidos en la clase `Kanboard\Core\Security\Role`.
|
||||
|
||||
Clase de autorización (`Kanboard\Core\Security\Authorization`) comprobará el acceso de cada página.
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
Agregando acciones automáticas
|
||||
===============================
|
||||
|
||||
Agregando una nueva acccion automática es bastante simple.
|
||||
|
||||
Creando una nueva accion
|
||||
------------------------
|
||||
|
||||
Tus acciones automáticas deben heradarse de la clase `Kanboard\Action\Base`.
|
||||
|
||||
Varios métodos abstractos deben ser implementadas por sí mismo:
|
||||
|
||||
| Metodos | Descripción |
|
||||
|-------------------------------------|------------------------------------------------------------------|
|
||||
| `getDescription()` | Descripcion visible en la interface del usuario |
|
||||
| `getCompatibleEvents()` | Obtener las listas de eventos compatibles |
|
||||
| `getActionRequiredParameters()` | Obtener los parametros requeridos para la acción (definidos por el usuario)|
|
||||
| `getEventRequiredParameters()` | Obtener los parametros requeridos para el evento |
|
||||
| `doAction(array $data)` | Ejecutar la acción, Debe regresar true si fue satisfactorio |
|
||||
| `hasRequiredCondition(array $data)` | Comprobar si los datos de eventos cumplen la condición de acción |
|
||||
|
||||
Tu accion automatica es identificada en kanboard utilizando el nombre de la clase absoluta con el espacio de nombre incluido
|
||||
|
||||
Agregando nuevos eventos
|
||||
------------------------
|
||||
|
||||
La lista de eventos de la aplicación está disponible en la clase `Kanboard\Core\Event\EventManager::getAll()`.
|
||||
Sin embargo, si tu plugin dispara nuevos eventos, tu puedes registrar estos eventos :
|
||||
|
||||
```php
|
||||
$this->actionManager->getAction('\Kanboard\Plugin\MyPlugin\MyActionName')->addEvent('my.event', 'My event description');
|
||||
```
|
||||
|
||||
Tu puedes extender la lista de eventos compatibles de acciones existentes para ser usada en algun metodo.
|
||||
|
||||
Registra la acción
|
||||
----------------------
|
||||
|
||||
Tu tienes que llamar el metodo `register()` desde la clase `Kanboard\Core\Action\ActionManager`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\AutomaticAction;
|
||||
|
||||
use Kanboard\Core\Plugin\Base;
|
||||
use Kanboard\Plugin\AutomaticAction\Action\TaskRename;
|
||||
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->actionManager->register(new TaskRename($this->container));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ejemplo
|
||||
-------
|
||||
|
||||
- [Ejemplo de acción automatica](https://github.com/kanboard/plugin-example-automatic-action)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
Agregando un nuevo avatar del proveedor
|
||||
=======================================
|
||||
|
||||
Registrar
|
||||
------------
|
||||
|
||||
```php
|
||||
$this->avatarManager->register(new CustomAvatarProvider());
|
||||
```
|
||||
|
||||
Interface
|
||||
---------
|
||||
|
||||
El proveedor debe implementar la interface `Kanboard\Core\User\Avatar\AvatarProviderInterface`:
|
||||
|
||||
|
||||
| Metodo | Descripcion |
|
||||
|-------------------------------|---------------------------------------------------------------|
|
||||
| `render(array $user, $size)` | Renderizar HTML |
|
||||
| `isActive(array $user)` | Regresa un boolean si el proveedor esta activo |
|
||||
|
||||
|
||||
El argumento `$user` es un directorio que contiene estas llaves :
|
||||
|
||||
```php
|
||||
[
|
||||
'id' => 123,
|
||||
'username' => 'admin',
|
||||
'name' => 'Administrator',
|
||||
'email' => 'me@localhost',
|
||||
]
|
||||
```
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Plugin de configuración del directorio
|
||||
======================================
|
||||
|
||||
Para instalar, actualizar y eliminar plugins dede la interface de usuario, debes tener estos requerimientos:
|
||||
|
||||
- El directorio del plugin debe ser de escritura por el usuario del servidor web
|
||||
- La extensión Zip debe estar disponible en tu server.
|
||||
- Los parametros de configuración `PLUGIN_INSTALLER` deben estar en `true`
|
||||
|
||||
Para desactivar esta función , cambie el valor de `PLUGIN_INSTALLER` a `false` en tu archivo de configuración.
|
||||
También puede cambiar los permisos de la carpeta Plugin en el filesystem.
|
||||
|
||||
Sólo los administradores pueden instalar plugins desde la interfaz de usuario.
|
||||
|
||||
Por defecto, sólo plug-in que aparece en la página web de Kanboard están disponibles .
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
Uso de eventos
|
||||
===============
|
||||
|
||||
Kanboard usar internamente el [ Componente EventDispatcher de Symfony ](https://symfony.com/doc/2.3/components/event_dispatcher/index.html) para manegar internamente los eventos.
|
||||
|
||||
Eventos escucha ** Listening **
|
||||
-------------------------------
|
||||
|
||||
```php
|
||||
$this->on('app.bootstrap', function($container) {
|
||||
// tu codigo
|
||||
});
|
||||
```
|
||||
|
||||
- El primer argumento es el nombre del evento (string)
|
||||
- El segundo argumento es una funcion PHP callable (finalización o metodos de la clase)
|
||||
|
||||
Agregando un nuevo evento
|
||||
-------------------------
|
||||
|
||||
Para agregar un nuevo, tienes que llamar al metodo `register()` de la clase `Kanboard\Core\Event\EventManager`:
|
||||
|
||||
```php
|
||||
$this->eventManager->register('my.event.name', 'Mi descripcion del nuevo evento');
|
||||
```
|
||||
|
||||
Estos eventos pueden ser utilizados por otros componentes de Kanboard como acciones automáticas .
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
Vinculación externa de proveedores
|
||||
==================================
|
||||
|
||||
Esta funcionalidad le permite vincular una tarea a los elementos adicionales almacenados en otro sistema.
|
||||
|
||||
Por ejemplo, tu puedes vincular una tarea a:
|
||||
For example, you can link a task to:
|
||||
|
||||
- Una pagina web tradicional
|
||||
- Datos adjuntos (Documentos PDF almacenados en la web, archivos ...)
|
||||
- Cualquier sitema de tickets (bug tracker, soporte personalizado de tickets...)
|
||||
|
||||
Cada item tiene un tipo, u na URL, un tipo dedependencia y un titulo.
|
||||
|
||||
Por default,Kanboard incluye dos tipos de proveedores
|
||||
|
||||
- Vinculación Web : Copiar y pegar un enlace y Kanboard se ha podido ir a la página de título de forma automática.
|
||||
- Datos adjuntos: Enlace a todo lo que no es una página web
|
||||
|
||||
Flujo de trabajo ** Workflow **
|
||||
--------------------------------
|
||||
|
||||
1. El usuario final copia y pega el URL al submit del formulario.
|
||||
2.- Si el tipo de link es "auto", Kanboard crea un bucle a través de todos los proveedores registrados hasta que hay una coincidencia
|
||||
3. Entonces , el proveedor de enlace devuelve un objeto que implementa la interfaz de `ExternalLinkInterface`
|
||||
4. El formulario se muestra al usuario con todos los datos precargados antes de guardar el enlace
|
||||
|
||||
Interfaces
|
||||
----------
|
||||
|
||||
Para implementar un nuevo vinculo al proveedor desde un plugin, es necesario crear 2 clases que implementarlas en las interfaces:
|
||||
|
||||
- `Kanboard\Core\ExternalLink\ExternalLinkProviderInterface`
|
||||
- `Kanboard\Core\ExternalLink\ExternalLinkInterface`
|
||||
|
||||
### ExternalLinkProviderInterface
|
||||
|
||||
| Method | Usage |
|
||||
|----------------------------|---------------------------------------------------------------------------------|
|
||||
| `getName()` | Obtener el nombre del proveedor(label) |
|
||||
| `getType()` | Obtener el tipo de link (se guardarán en la base de datos) |
|
||||
| `getDependencies()` | Obtener un diccionario de los tipos de dependencia soportados por el proveedor |
|
||||
| `setUserTextInput($input)` | Texto introducido por el usuario |
|
||||
| `match()` | Regresa true si el proveedor puede analizar correctamente la entrada del usuario|
|
||||
| `getLink()` | Obtener el enlace que se encuentra con las propiedades |
|
||||
|
||||
### ExternalLinkInterface
|
||||
|
||||
| Method | Usage |
|
||||
|-------------------|-----------------------------|
|
||||
| `getTitle()` | Obtiene un titulo de link |
|
||||
| `getUrl()` | Obtiene una link de URL |
|
||||
| `setUrl($url)` | URL del enlace |
|
||||
|
||||
El registro de un nuevo proveedor de enlace
|
||||
------------------------------------------
|
||||
|
||||
En tu `Plugin.php`, solo puedes llamar al metodo `register()` desde el objeto `ExternalLinkManager`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\MyExternalLink;
|
||||
|
||||
use Kanboard\Core\Plugin\Base;
|
||||
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->externalLinkManager->register(new MyLinkProvider());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ejemplos
|
||||
--------
|
||||
|
||||
- Kanboard incluye proveedores por default "WebLink" y "Attachment"
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
Personalizar grupos de proveedores
|
||||
==================================
|
||||
|
||||
Kanboard es capaz de cargar grupos de un sistema externo.
|
||||
Esta caracteristica es principalmente usada para permisos de proyectos.
|
||||
|
||||
Los **Projects Managers** pueden permitir el acceso a un proyecto para un grupo
|
||||
El usuario final **end-user** utilizara una caja de autocomplementar y busquedas para un grupo
|
||||
|
||||
Cada vez que se ejecuta una consulta de grupo , todos los proveedores de grupo registrados se ejecutan .
|
||||
|
||||
Flujo de trabajo del Grupo de Proveedores **Workflow**
|
||||
-----------------------------------------------------
|
||||
|
||||
1. El usuario final **end-user** comienza a escribir el nombre del grupo y el campo se autocompleta
|
||||
2. EL `GroupManager` la clase ejecuta la consulta para todos los proveedores de grupo registrados
|
||||
3. Los resultados son fusionados y regresados a la interface de usuario
|
||||
4. Antes de seleccionar un grupo, a información del grupo se sincronizan con la base de datos local si es necesario
|
||||
|
||||
Interface del grupo de proveedores
|
||||
----------------------------------
|
||||
|
||||
interface a implementar: `Kanboard\Core\Group\GroupProviderInterface`.
|
||||
|
||||
Las clases que implementa esta interface abstracta del grupo de información, solo hay 3 metodos:
|
||||
|
||||
- `getInternalId()`: Obtiene el id interno de la base de datos, de otra manera regresa 0
|
||||
- `getExternalId()`: Obtiene un id unico externo
|
||||
- `getName()`: Obtiene el nombre de grupo
|
||||
|
||||
Kanboard utilizará el ID externo para sincronizar con la base de datos local.
|
||||
|
||||
Interface Backend del grupo de proveedores
|
||||
------------------------------------------
|
||||
Interface a implementar: `Kanboard\Core\Group\GroupBackendProviderInterface`.
|
||||
|
||||
Esta interface requiere solo un metodo: `find($input)`.
|
||||
El argumento `$input` es el texto introducido desde la interfaz de usuario.
|
||||
|
||||
Este metodo debe regresar una lista de `GroupProviderInterface`, es es el resultado de la busqueda.
|
||||
|
||||
Backend de registro desde Plugins
|
||||
---------------------------------
|
||||
|
||||
En el metodo `initialize()` de su plugins registrado se puede personalizar el backend :
|
||||
|
||||
```php
|
||||
$groupManager->register(new MyCustomLdapBackendGroupProvider($this->container));
|
||||
```
|
||||
|
||||
Ejemplos
|
||||
--------
|
||||
|
||||
- [Kanboard incluye el grupo de provedores (LDAP y base de datos)](https://github.com/kanboard/kanboard/tree/master/app/Group)
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
Registrar nuevos helpers
|
||||
=======================
|
||||
|
||||
Estrucura del helper:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\MyPlugin\Helper\MyHelper;
|
||||
|
||||
use Kanboard\Core\Base;
|
||||
|
||||
class MyHelper extends Base
|
||||
{
|
||||
public function doSomething()
|
||||
{
|
||||
return 'foobar';
|
||||
}
|
||||
}
|
||||
```
|
||||
Registrar tu helper en la clase:
|
||||
|
||||
```php
|
||||
$this->helper->register('myHelper', '\Kanboard\Plugin\MyPlugin\Helper\MyHelper');
|
||||
```
|
||||
|
||||
Usar tu helper desde una plantilla **Template**:
|
||||
|
||||
```php
|
||||
<p>
|
||||
<?= $this->myHelper->doSomething() ?>
|
||||
</p>
|
||||
```
|
||||
|
||||
Usar tu helper dese otra clase:
|
||||
|
||||
```php
|
||||
$this->helper->myHelper->doSomething();
|
||||
```
|
||||
|
|
@ -0,0 +1,249 @@
|
|||
Plugin Hooks
|
||||
============
|
||||
|
||||
Hooks de aplicación
|
||||
-----------------
|
||||
|
||||
Los hooks pueden extender , reemplazar, filtar datos o cambiar los comportamientos por default, cad hook es identificado con unico nombre, ejemplo : `controller:calendar:user:events`
|
||||
|
||||
### Escuchar en eventos hook
|
||||
|
||||
En tu metodo `initialize()` tu necesitas llamar al metodo `on()` de la clase `Kanboard\Core\Plugin\Hook`:
|
||||
|
||||
```php
|
||||
$this->hook->on('hook_name', $callable);
|
||||
```
|
||||
|
||||
El primer argumento es el nombre del hook y el segundo es un callable PHP
|
||||
|
||||
### Hooks ejecutado sólo una vez
|
||||
|
||||
Algunos hooks solo tienen un listener:
|
||||
|
||||
#### model:subtask-time-tracking:calculate:time-spent
|
||||
|
||||
- Anular el cálculo del tiempo anterior cuando se detiene el temporizador de la subtarea
|
||||
- Argumentos :
|
||||
- `$user_id` (integer)
|
||||
- `$start` (DateTime)
|
||||
- `$end` (DateTime)
|
||||
|
||||
### Fusionar hooks
|
||||
|
||||
"Fusionar hooks" actuar de la misma manera que la función de `array_merge`. el hook callback solo regresa un array. Este array se fusionará con la que viene por defecto.
|
||||
|
||||
Ejemplo para agregar eventos en el calendario del usuario:
|
||||
|
||||
```php
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$container = $this->container;
|
||||
|
||||
$this->hook->on('controller:calendar:user:events', function($user_id, $start, $end) use ($container) {
|
||||
$model = new SubtaskForecast($container);
|
||||
return $model->getCalendarEvents($user_id, $end); // Return new events
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Ejemplo para sobrescribir los valores por default de las tareas:
|
||||
|
||||
```php
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->hook->on('controller:task:form:default', function (array $default_values) {
|
||||
return empty($default_values['score']) ? array('score' => 4) : array();
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Lista de fusión de hooks:
|
||||
|
||||
#### controller:task:form:default
|
||||
|
||||
- sobrescribir los valores por default de las tareas
|
||||
- Argumentos:
|
||||
- `$default_values`: actual default values (array)
|
||||
|
||||
#### controller:calendar:project:events
|
||||
|
||||
- Agregar mas eventos a el calendario del projecto
|
||||
- Argumentos:
|
||||
- `$project_id` (integer)
|
||||
- `$start` Calendar start date (string, ISO-8601 format)
|
||||
- `$end` Calendar` end date (string, ISO-8601 format)
|
||||
|
||||
#### controller:calendar:user:events
|
||||
|
||||
- Agregar mas eventos a el calendario de usuario
|
||||
- Argumentos:
|
||||
- `$user_id` (integer)
|
||||
- `$start` Calendar start date (string, ISO-8601 format)
|
||||
- `$end` Calendar end date (string, ISO-8601 format)
|
||||
|
||||
Asset Hooks
|
||||
-----------
|
||||
|
||||
Asset hooks pueden ser usados para agregar nuevas stylesheet facilmente o un nuevo archivo JavaScript en el layout. tu puedes usar estas caracteristicas para crear un tema y sobreescribir todo los estilos por dafault del kanboard.
|
||||
|
||||
Ejemplo para agregar un stylesheet **hoja de estilo**
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\Css;
|
||||
|
||||
use Kanboard\Core\Plugin\Base;
|
||||
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->hook->on('template:layout:css', array('template' => 'plugins/Css/skin.css'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Lista de asset Hooks:
|
||||
|
||||
- `template:layout:css`
|
||||
- `template:layout:js`
|
||||
|
||||
|
||||
Referencia de hooks
|
||||
---------------
|
||||
|
||||
La reference hooks son pasados a una variable por referencia.
|
||||
|
||||
Ejemplo:
|
||||
|
||||
```php
|
||||
$this->hook->on('formatter:board:query', function (\PicoDb\Table &query) {
|
||||
$query->eq('color_id', 'red');
|
||||
});
|
||||
```
|
||||
|
||||
El código anterior mostrará sólo las tareas en rojo en el tablero.
|
||||
|
||||
Lista de referencias de hooks:
|
||||
|
||||
| Hook | Description |
|
||||
|--------------------------------------------|---------------------------------------------------------------|
|
||||
| `formatter:board:query` | Alterar consulta a la base antes de tablero de renderizado |
|
||||
| `pagination:dashboard:task:query` | Alterar consulta de base de datos para las tareas de la paginación en el dashboard |
|
||||
| `pagination:dashboard:subtask:query` | Alterar consulta a la base de la paginación en el subtareas del dashboard |
|
||||
| `model:task:creation:prepare` | Alterar los valores del formulario antes de guardar una tarea |
|
||||
| `model:task:modification:prepare` | Alterar los valores del formulario antes de editar una tarea
|
||||
|
||||
Template Hooks
|
||||
--------------
|
||||
|
||||
Template hooks permitirá añadir nuevos contenidos en las plantillas existentes.
|
||||
|
||||
Ejemplo para agregar nuevos contenidos en el sidebar del dashboard:
|
||||
|
||||
```php
|
||||
$this->template->hook->attach('template:dashboard:sidebar', 'myplugin:dashboard/sidebar');
|
||||
```
|
||||
|
||||
Ejemplo para adjuntar un template con variables locales:
|
||||
|
||||
```php
|
||||
$this->template->hook->attach('template:dashboard:sidebar', 'myplugin:dashboard/sidebar', array(
|
||||
'variable' => 'foobar',
|
||||
));
|
||||
```
|
||||
|
||||
Ejemplo para adjuntar un template con un callable:
|
||||
|
||||
```php
|
||||
$this->template->hook->attach('template:dashboard:sidebar', 'myplugin:dashboard/sidebar', function($hook_param1, $hook_param2) {
|
||||
return array('new_template_variable' => 'foobar'); // Inyectar una nueva variable en la plantilla Plugin
|
||||
});
|
||||
```
|
||||
|
||||
Este llamada es usualmente definida en el metodo `initialize()`
|
||||
El primer argumento es el nombre del hook y el segundo argumento es el nombre del template.
|
||||
|
||||
Los nombres de plantillas con el prefijo del nombre del plugin y los dos puntos indican la ubicación de la plantilla.
|
||||
|
||||
Ejemplo con `myplugin:dashboard/sidebar`:
|
||||
|
||||
- `myplugin` Es el nombre de tu plugin (minusculas)
|
||||
- `dashboard/sidebar` es el nombre del template
|
||||
- En el filesystem, El plugin esta localizado aqui: `plugins\Myplugin\Template\dashboard\sidebar.php`
|
||||
- Templates estan escritos en puro PHP (no se olvide de escapar los datos)
|
||||
|
||||
Los nombres de plantillas sin prefijo son plantillas básicas.
|
||||
|
||||
Lista de templates hooks:
|
||||
|
||||
| Hook | Descripción |
|
||||
|--------------------------------------------|----------------------------------------------------|
|
||||
| `template:analytic:sidebar` | Sidebar en paginas analiticas |
|
||||
| `template:app:filters-helper:before` | Filtro helper dropdown (top) |
|
||||
| `template:app:filters-helper:after` | Filtro helper dropdown (bottom) |
|
||||
| `template:auth:login-form:before` | Pagina de login (top) |
|
||||
| `template:auth:login-form:after` | Pagina de login (bottom) |
|
||||
| `template:board:private:task:before-title` | Tarea en un tablero privado : despues del titulo |
|
||||
| `template:board:private:task:after-title` | Tarea en un tablero privado : antes del titulo |
|
||||
| `template:board:public:task:before-title` | Tarea en un tablero publico : despues del titulo |
|
||||
| `template:board:public:task:after-title` | Tarea en un tablero publico : antes del titulo |
|
||||
| `template:board:task:footer` | Tarea en el tablero : footer |
|
||||
| `template:board:task:icons` | Tarea en el tablero: tooltip icon |
|
||||
| `template:board:column:dropdown` | Menu Dropdown en las columnas del tablero |
|
||||
| `template:config:sidebar` | Sidebar pagina de configuración |
|
||||
| `template:config:application ` | Aplicación de configuración del formulario |
|
||||
| `template:config:email` | Email settings page |
|
||||
| `template:config:integrations` | Integration page in global settings |
|
||||
| `template:dashboard:sidebar` | Sidebar en la pagina del dashboard |
|
||||
| `template:dashboard:show` | Pagina principal del dashboard |
|
||||
| `template:export:sidebar` | Sidebar para exportar paginas |
|
||||
| `template:import:sidebar` | Sidebar para importar paginas |
|
||||
| `template:header:dropdown` | Dropdown menu Pagina header (icono avatar de usuario) |
|
||||
| `template:header:creation-dropdown` | Dropdown menu Pagina header (plus icon) |
|
||||
| `template:layout:head` | Layout de la pagina `<head/>` tag |
|
||||
| `template:layout:top` | Layout de la pagina top header |
|
||||
| `template:layout:bottom` | Layout de la pagina footer |
|
||||
| `template:project:dropdown` | "Actions" menu a la izquierda vista para diferentes proyectos |
|
||||
| `template:project:header:before` | Filtros de Proyectos (antes) |
|
||||
| `template:project:header:after` | Filtros de Proyectos (despues) |
|
||||
| `template:project:integrations` | Pagina de integracion de configuración de proyectos|
|
||||
| `template:project:sidebar` | Sidebar configuración de proyectos |
|
||||
| `template:project-user:sidebar` | Sidebar en la página de la información de usuario del proyecto |
|
||||
| `template:task:layout:top` | Task layout top (antes page header) |
|
||||
| `template:task:details:top` | Resumen de tarea top |
|
||||
| `template:task:details:bottom` | Resumen de tarea bottom |
|
||||
| `template:task:details:first-column` | Resumen de tarea columna |
|
||||
| `template:task:details:second-column` | Resumen de tarea dos columnas |
|
||||
| `template:task:details:third-column` | Resumen de tarea tres columnas |
|
||||
| `template:task:details:fourth-column` | Resumen de tarea cuatro columnas |
|
||||
| `template:task:dropdown` | Task dropdown menu en listado de paginas |
|
||||
| `template:task:sidebar:actions` | Sidebar on task page (sección de acciones) |
|
||||
| `template:task:sidebar:information` | Sidebar on task page (sección de información) |
|
||||
| `template:task:form:first-column` | 1st columna en forma de tarea |
|
||||
| `template:task:form:second-column` | 2nd columna en forma de tarea |
|
||||
| `template:task:form:third-column` | 3nd columna en forma de tarea |
|
||||
| `template:task:show:top ` | Mostrar página de tareas : top |
|
||||
| `template:task:show:bottom` | Mostrar página de tareas : bottom |
|
||||
| `template:task:show:before-description` | Mostrar página de tareas : despues de la descripción |
|
||||
| `template:task:show:before-tasklinks` | Mostrar página de tareas : despues tasklinks |
|
||||
| `template:task:show:before-subtasks` | Mostrar página de tareas : despues subtareas |
|
||||
| `template:task:show:before-timetracking` | Mostrar página de tareas : despues timetracking |
|
||||
| `template:task:show:before-attachments` | Mostrar página de tareas : despues archivos adjuntos |
|
||||
| `template:task:show:before-comments` | Mostrar página de tareas : despues comentarios |
|
||||
| `template:user:authentication:form` | "Editar autenticación" formulario de perfil de usuario |
|
||||
| `template:user:create-remote:form` | "Crear un usuario remoto" formulario |
|
||||
| `template:user:external` | "Autenticación externa" la página de perfil de usuario |
|
||||
| `template:user:integrations` | Integración en el perfil de usuario |
|
||||
| `template:user:sidebar:actions` | Sidebar en el perfil de usuario (sección de acciones) |
|
||||
| `template:user:sidebar:information` | Sidebar en el perfil de usuario (sección de información) |
|
||||
|
||||
|
||||
Otro de los ganchos plantilla se pueden añadir en caso necesario , sólo hay que preguntar en el seguimiento de incidencias ** issue tracking **.
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
Libreria LDAP
|
||||
============
|
||||
|
||||
Para facilirar la integracion LDAP. kanboard tiene su propia libreria LDAP
|
||||
Esta libreria puede ejecutar operaciones comunes.
|
||||
|
||||
Cliente
|
||||
-------
|
||||
|
||||
Clase: `Kanboard\Core\Ldap\Client`
|
||||
|
||||
Para conectar a tu servidor LDAP facilmente, usa este metodo:
|
||||
|
||||
```php
|
||||
use Kanboard\Core\Ldap\Client as LdapClient;
|
||||
use Kanboard\Core\Ldap\ClientException as LdapException;
|
||||
|
||||
try {
|
||||
$client = LdapClient::connect();
|
||||
|
||||
// Get native LDAP resource
|
||||
$resource = $client->getConnection();
|
||||
|
||||
// ...
|
||||
|
||||
} catch (LdapException $e) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Consultas LDAP
|
||||
--------------
|
||||
|
||||
Classes:
|
||||
|
||||
- `Kanboard\Core\Ldap\Query`
|
||||
- `Kanboard\Core\Ldap\Entries`
|
||||
- `Kanboard\Core\Ldap\Entry`
|
||||
|
||||
Ejemplo para una consulta al directorio LDAP:
|
||||
|
||||
```php
|
||||
|
||||
$query = new Query($client)
|
||||
$query->execute('ou=People,dc=kanboard,dc=local', 'uid=my_user', array('cn', 'mail'));
|
||||
|
||||
if ($query->hasResult()) {
|
||||
$entries = $query->getEntries(); // Return an instance of Entries
|
||||
}
|
||||
```
|
||||
|
||||
Leer una entrada:
|
||||
|
||||
```php
|
||||
$firstEntry = $query->getEntries()->getFirstEntry();
|
||||
$email = $firstEntry->getFirstValue('mail');
|
||||
$name = $firstEntry->getFirstValue('cn', 'Default Name');
|
||||
```
|
||||
|
||||
Leer multiples entradas:
|
||||
|
||||
```php
|
||||
foreach ($query->getEntries()->getAll() as $entry) {
|
||||
$emails = $entry->getAll('mail'); // Fetch all emails
|
||||
$dn = $entry->getDn(); // Get LDAP DN of this user
|
||||
|
||||
// Check if a value is present for an attribute
|
||||
if ($entry->hasValue('mail', 'user2@localhost')) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Usuario Helper
|
||||
--------------
|
||||
|
||||
Clase: `Kanboard\Core\Ldap\User`
|
||||
|
||||
Obtener usuario en una sola linea
|
||||
|
||||
```php
|
||||
// Return an instance of LdapUserProvider
|
||||
$user = User::getUser($client, 'my_username');
|
||||
```
|
||||
|
||||
Grupo Helper
|
||||
------------
|
||||
|
||||
Clase: `Kanboard\Core\Ldap\Group`
|
||||
|
||||
Obtener grupos en una linea:
|
||||
|
||||
```php
|
||||
// Define LDAP filter
|
||||
$filter = '(&(objectClass=group)(sAMAccountName=My group*))';
|
||||
|
||||
// Return a list of LdapGroupProvider
|
||||
$groups = Group::getGroups($client, $filter);
|
||||
```
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
Plugin: Agregar trasporte de email
|
||||
==================================
|
||||
|
||||
Por default Kanboard soporta 3 estadares de trasporte de email:
|
||||
|
||||
- Mail (PHP mail function)
|
||||
- Smtp
|
||||
- Sendmail command
|
||||
|
||||
Con la API del plugin tu puedes agregar un driver para cualquier proveedor de email.
|
||||
Por ejemplo, nuestro plugin puede agregar un trasporte de email para un proveedor que usa un API HTTP.
|
||||
|
||||
Implementación
|
||||
--------------
|
||||
|
||||
Nuestro plugin dede implementgar la interface `Kanboard\Core\Mail\ClientInterface` y extiende desde `Kanboard\Core\Base`.
|
||||
El único método que necesita para implementar es `sendEmail()`:
|
||||
|
||||
```php
|
||||
interface ClientInterface
|
||||
{
|
||||
/**
|
||||
* Send a HTML email
|
||||
*
|
||||
* @access public
|
||||
* @param string $email
|
||||
* @param string $name
|
||||
* @param string $subject
|
||||
* @param string $html
|
||||
* @param string $author
|
||||
*/
|
||||
public function sendEmail($email, $name, $subject, $html, $author);
|
||||
}
|
||||
```
|
||||
|
||||
Para registrar el nuevo trasporte de email, usa el metodo `setTransport($transport, $class)` desde la clase `Kanboard\Core\Mail\Client`:
|
||||
|
||||
```php
|
||||
$this->emailClient->setTransport('myprovider', '\Kanboard\Plugin\MyProvider\MyEmailHandler');
|
||||
```
|
||||
|
||||
EL segundo argumento contiene el absoluto namespace de tu clase especifica
|
||||
|
||||
Ejemplos de plugins para trasporte de email
|
||||
----------------------------------
|
||||
|
||||
- [Sendgrid](https://github.com/kanboard/plugin-sendgrid)
|
||||
- [Mailgun](https://github.com/kanboard/plugin-mailgun)
|
||||
- [Postmark](https://github.com/kanboard/plugin-postmark)
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
Metadatos
|
||||
=========
|
||||
|
||||
Tu piedes adjutnar metadatos para cada projecto,tarea , usuaio o para toda la aplicación
|
||||
Los metadatos son campos personalisados, es una key/value de una tabla.
|
||||
|
||||
Por ejemplo nuestro plugin puede almacenar información externa para una tarea o nuevas configuraciones para un proyecto.
|
||||
Básicamente le permiten ampliar los campos predeterminados sin tener que crear nuevas tablas .
|
||||
|
||||
Adjuntar y eliminar metadatos para tareas
|
||||
--------------------------------------------
|
||||
|
||||
```php
|
||||
|
||||
// Return a dictionary of metadata (keys/values) for the $task_id
|
||||
$this->taskMetadataModel->getAll($task_id);
|
||||
|
||||
// Get a value only for a task
|
||||
$this->taskMetadataModel->get($task_id, 'my_plugin_variable', 'default_value');
|
||||
|
||||
// Return true if the metadata my_plugin_variable exists
|
||||
$this->taskMetadataModel->exists($task_id, 'my_plugin_variable');
|
||||
|
||||
// Create or update metadata for the task
|
||||
$this->taskMetadataModel->save($task_id, ['my_plugin_variable' => 'something']);
|
||||
|
||||
// Remove a metadata from a project
|
||||
$this->projectMetadataModel->remove($project_id, my_plugin_variable);
|
||||
```
|
||||
|
||||
Tipos de metadatos
|
||||
------------------
|
||||
|
||||
- TaskMetadata: `$this->taskMetadataModel`
|
||||
- ProjectMetadata: `$this->projectMetadataModel`
|
||||
- UserMetadata: `$this->userMetadataModel`
|
||||
- Settings/Config: `$this->configModel`
|
||||
|
||||
Notas
|
||||
-----
|
||||
|
||||
- Siempre prefijo del nombre de metadatos con el nombre del plugin
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
Agregar notificaciones con los tipos de plugin
|
||||
==============================================
|
||||
|
||||
Puede enviar notificaciones a casi cualquier sistema mediante la adición de un nuevo tipo .
|
||||
There are two kinds of notifications: project and user.
|
||||
|
||||
- Project: Notificaciones configuradas a nivel de proyecto
|
||||
- Usuario: Notificaciones enviadas individualmente y configurada a cada perfil de usuario.
|
||||
|
||||
Registra un nuevo tipo de notificación
|
||||
--------------------------------------
|
||||
|
||||
En tu archivo de registro del plugin llama el metodo `setType()`:
|
||||
|
||||
```php
|
||||
$this->userNotificationTypeModel->setType('irc', t('IRC'), '\Kanboard\Plugin\IRC\Notification\IrcHandler');
|
||||
$this->projectNotificationTypeModel->setType('irc', t('IRC'), '\Kanboard\Plugin\IRC\Notification\IrcHandler');
|
||||
```
|
||||
|
||||
Su controlador puede ser registrado por el usuario o la notificación del proyecto. No necesariamente tienen que soportarlo .
|
||||
Cuando tu handler es registrdo, el usuario final **end-user** puede elegir recibir el nuevo tipo de notificación o no
|
||||
|
||||
Notificación de Handler
|
||||
-----------------------
|
||||
|
||||
Su controlador de notificación debe implementar la interfaz `Kanboard\Core\Notification\NotificationInterface`:
|
||||
|
||||
```php
|
||||
interface NotificationInterface
|
||||
{
|
||||
/**
|
||||
* Envia notificación a un usuario
|
||||
*
|
||||
* @access public
|
||||
* @param array $user
|
||||
* @param string $event_name
|
||||
* @param array $event_data
|
||||
*/
|
||||
public function notifyUser(array $user, $event_name, array $event_data);
|
||||
|
||||
/**
|
||||
* Envia notificacion a un projecto
|
||||
*
|
||||
* @access public
|
||||
* @param array $project
|
||||
* @param string $event_name
|
||||
* @param array $event_data
|
||||
*/
|
||||
public function notifyProject(array $project, $event_name, array $event_data);
|
||||
}
|
||||
```
|
||||
|
||||
Ejemplo de notificacion de plugins
|
||||
---------------------------------
|
||||
|
||||
- [Slack](https://github.com/kanboard/plugin-slack)
|
||||
- [Hipchat](https://github.com/kanboard/plugin-hipchat)
|
||||
- [Jabber](https://github.com/kanboard/plugin-jabber)
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
Plugin Reescritura
|
||||
================
|
||||
|
||||
Reesritura HTTP Contenido Política de Seguridad
|
||||
-----------------------------------------------
|
||||
|
||||
Si desea reemplazar el encabezado HTTP predeterminado de la directiva de seguridad del contenido, puede utilizar el método`setContentSecurityPolicy()`:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\Csp;
|
||||
|
||||
use Kanboard\Core\Plugin\Base;
|
||||
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->setContentSecurityPolicy(array('script-src' => 'something'));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Plantillas de reescrituras
|
||||
--------------------------
|
||||
|
||||
Las plantillas definidas en el núcleo se pueden anular . Por ejemplo , se puede redefinir el diseño predeterminado o cambiar notificaciones por correo electrónico.
|
||||
|
||||
Ejemolo de plantilla de reescritura:
|
||||
|
||||
```php
|
||||
$this->template->setTemplateOverride('header', 'theme:layout/header');
|
||||
```
|
||||
|
||||
El primer argumento es el nombre de la plantilla original y el segundo argumento de la plantilla para usar como reemplazo.
|
||||
|
||||
Puede seguir utilizando la plantilla original utilizando el prefijo "kanboard:" :
|
||||
|
||||
```php
|
||||
<?= $this->render('kanboard:header') ?>
|
||||
```
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
Registracion de Plugin
|
||||
======================
|
||||
|
||||
Estructura del directorio
|
||||
--------------------------
|
||||
|
||||
Los Plugins estan almacenados en el subdirectorio `plugins. Un ejemplo de estructura del directorio de un plugin:
|
||||
|
||||
```bash
|
||||
plugins
|
||||
└── Budget <= Plugin name
|
||||
├── Asset <= Javascript/CSS files
|
||||
├── Controller
|
||||
├── LICENSE <= Plugin license
|
||||
├── Locale
|
||||
│ ├── fr_FR
|
||||
│ ├── it_IT
|
||||
│ ├── ja_JP
|
||||
│ └── zh_CN
|
||||
├── Model
|
||||
├── Plugin.php <= Plugin registration file
|
||||
├── README.md
|
||||
├── Schema <= Database migrations
|
||||
├── Template
|
||||
└── Test <= Unit tests
|
||||
```
|
||||
|
||||
Solamente el archivo de registración `Plugin.php` es requerido. Las otras carpetas son opcionales.
|
||||
|
||||
La primera letra del nombre del plugin debe ser capitalizada.
|
||||
|
||||
Archivo de registración del plugin
|
||||
----------------------------------
|
||||
|
||||
Kanboard Kanboard escaneará el directorio `plugins` y cargara automaticamente todo en este directorio. el archivo `Plugin.php` se utiliza para cargar y registrar el plugin.
|
||||
|
||||
Ejemplo del archivo `Plugin.php` (`plugins/Foobar/Plugin.php`):
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\Foobar;
|
||||
|
||||
use Kanboard\Core\Plugin\Base;
|
||||
|
||||
class Plugin extends Base
|
||||
{
|
||||
public function initialize()
|
||||
{
|
||||
$this->template->hook->attach('template:layout:head', 'theme:layout/head');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Este archivo debera contener una clase `Plugin` se define en el namespace `Kanboard\Plugin\Yourplugin` y extiende `Kanboard\Core\Plugin\Base`.
|
||||
|
||||
El único método requerido es `initialize()`. Este método se llama para cada petición cuando el plugin es cargado.
|
||||
|
||||
Metodos del plugin
|
||||
--------------
|
||||
|
||||
Los métodos disponibles son `Kanboard\Core\Plugin\Base`:
|
||||
|
||||
- `initialize()`: ejecuta cuando el plugin es cargafo
|
||||
- `getClasses()`: Regresa todas las clases que se deben almacenar en el contenedor de inyección de dependencias
|
||||
- `on($event, $callback)`: Escucha eventos internos.
|
||||
- `getPluginName()`: devuelve el nombre del plugin.
|
||||
- `getPluginAuthor()`: Devuelve el autor del plugin.
|
||||
- `getPluginVersion()`: Devuelve la versíon del plugin.
|
||||
- `getPluginDescription()`: Devuelve la descripcion del plugin.
|
||||
- `getPluginHomepage()`: Devuelve la pagina inicial del plugin (link)
|
||||
- `setContentSecurityPolicy(array $rules)`: Reescribe las reglas por default del HTTP CSP.
|
||||
- `onStartup()`: Si está presente este método, se ejecuta automáticamente cuando el evento "app.bootstrap" se dispara.
|
||||
|
||||
Su registro de plugin tambien puede heradar de la clase Kanboard\Core\Base, de esta manera se puede acceder a todas las clases y los métodos de Kanboard facilmente.
|
||||
|
||||
En este ejemplo se obtendrá el usuario #123:
|
||||
|
||||
```php
|
||||
$this->user->getById(123);
|
||||
```
|
||||
|
||||
Plugin de traducción
|
||||
-------------------
|
||||
|
||||
Este plugin se puede traducir en la misma forma que el resto de la aplicación . Debe cargar las traducciones a sí mismo cuando se crea la sesión :
|
||||
|
||||
```php
|
||||
public function onStartup()
|
||||
{
|
||||
Translator::load($this->languageModel->getCurrentLanguage(), __DIR__.'/Locale');
|
||||
}
|
||||
```
|
||||
|
||||
Las traducciones deben ser almacenadas en el archivo `plugins/Myplugin/Locale/xx_XX/translations.php` (remplazar xx_XX por el codigo del lenguaje fr_FR, en_US...).
|
||||
|
||||
Las traducciones estan almacenadas en un diccionario, Si desea sobreescribir una cadena existente, sólo tiene que utilizar la misma clave en el archivo de traducción.
|
||||
|
||||
Inyección de dependencias de contenedores
|
||||
------------------------------
|
||||
Kanboard utiliza la Pimple , un simple inyección de contenedores de dependencia PHP . Sin embargo , Kanboard puede registrar cualquier clase en el contenedor fácilmente.
|
||||
|
||||
Estas clases están disponibles en todas partes en la aplicación y se crea una única instancia .
|
||||
|
||||
Aquí un ejemplo para registrar sus propios modelos en el contenedor:
|
||||
|
||||
```php
|
||||
public function getClasses()
|
||||
{
|
||||
return array(
|
||||
'Plugin\Budget\Model' => array(
|
||||
'HourlyRateModel',
|
||||
'BudgetModel',
|
||||
)
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Ahora bien, si se utiliza una clase que se extiende desde `Core\Base`, tu puedes acceder directamente cualquier instancia de la clase:
|
||||
|
||||
```php
|
||||
$this->hourlyRateModel->remove(123);
|
||||
$this->budgetModel->getDailyBudgetBreakdown(456);
|
||||
|
||||
// It's the same thing as using the container:
|
||||
$this->container['hourlyRateModel']->getAll();
|
||||
```
|
||||
|
||||
Llaves de los contenedores son únicos a través de la aplicación . Si reemplaza una clase existente , que va a cambiar el comportamiento por defecto .
|
||||
|
||||
Agregar un metodo nuevo en la API
|
||||
---------------------------------
|
||||
|
||||
Kanboard usa la libreria [JSON-RPC](https://github.com/fguillot/JsonRPC) para manejar las llamadas de la api.
|
||||
|
||||
Para agregar un nuevo metodo tu puedes que puede hacer algo para llamar a tu plugin:
|
||||
|
||||
```php
|
||||
$this->api->getProcedureHandler()->withCallback('my_method', function() {
|
||||
return 'foobar';
|
||||
});
|
||||
```
|
||||
|
||||
`$this->container['api']` or `$this->api` expose an instance of the object `JsonRPC\Server`.
|
||||
|
||||
Leer la documentacion de la libreria para mas información.
|
||||
|
||||
Agregar una nueva consola de comandos
|
||||
--------------------------------------
|
||||
|
||||
Kanboard usa la libreria [Symfony Console](http://symfony.com/doc/current/components/console/introduction.html) para manejar las lineas de comandos.
|
||||
|
||||
Kanboard genera una instancia del objeto `Symfony\Component\Console\Application` via `$this->cli`.
|
||||
Tu puedes agregar nuevos comandos desde tu plugin:
|
||||
|
||||
```php
|
||||
$this->cli->add(new MyCommand());
|
||||
```
|
||||
|
||||
Lea la documentación de la biblioteca para obtener más información.
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
Personalizar Rutas
|
||||
==================
|
||||
|
||||
Cuando está habilitada la reescritura de URL, tu puedes definir rutas personalizadas desde tus plugins.
|
||||
|
||||
Definir nuevas rutas
|
||||
--------------------
|
||||
|
||||
Las rutas son manejadas por la clase `Kanboard\Core\Http\Route`.
|
||||
|
||||
Las nuevas rutas se pueden agregar mediante el uso del método `addRoute($path, $controller, $action, $plugin)`, here an example:
|
||||
|
||||
```php
|
||||
$this->route->addRoute('/my/custom/route', 'myController', 'myAction', 'myplugin');
|
||||
```
|
||||
|
||||
Cuando el usuario final **end-user** van a la URL `/my/custom/route`, el metodo `Kanboard\Plugin\Myplugin\Controller\MyController::myAction()` será ejecutado.
|
||||
|
||||
El primer caracter del contraldor y el nombre del plugin serán convertidos en mayusculas con la funcion `ucfirst()`.
|
||||
|
||||
Tu puedes ademas definir rutas con variables:
|
||||
|
||||
```php
|
||||
$this->route->addRoute('/my/route/:my_variable', 'myController', 'myAction', 'myplugin');
|
||||
```
|
||||
|
||||
El prefijo colon `:`, define una variable.
|
||||
Por ejemplo `:my_variable` declare el nombre de la nueva variable `my_variable`.
|
||||
|
||||
Para extraer los valores de la variable puedes usar el metodo `getStringParam()` or `getIntegerParam()` desde la clase `Kanboard\Core\Http\Request`:
|
||||
|
||||
Si tenemos la URL `/my/route/foobar`, el valor de `my_variable` es `foobar`:
|
||||
|
||||
```php
|
||||
$this->request->getStringParam('my_variable'); // Return foobar
|
||||
```
|
||||
|
||||
Generate links based on the routing table
|
||||
-----------------------------------------
|
||||
|
||||
Desde las plantillas , se tiene que usar el helper `Kanboard\Helper\Url`.
|
||||
|
||||
### Generar un link HTML
|
||||
|
||||
```php
|
||||
<?= $this->url->link('My link', 'mycontroller', 'myaction', array('plugin' => 'myplugin')) ?>
|
||||
```
|
||||
|
||||
Generara este HTML:
|
||||
|
||||
```html
|
||||
<a href="/my/custom/route">My link</a>
|
||||
```
|
||||
|
||||
### Generara solamente el atributo `href`:
|
||||
|
||||
```php
|
||||
<?= $this->url->href('My link', 'mycontroller', 'myaction', array('plugin' => 'myplugin')) ?>
|
||||
```
|
||||
|
||||
HTML salida:
|
||||
|
||||
```html
|
||||
/my/custom/route
|
||||
```
|
||||
|
||||
Salida HTML cuando la reescritura del URL no esta habilitada:
|
||||
|
||||
```html
|
||||
?controller=mycontroller&action=myaction&plugin=myplugin
|
||||
```
|
||||
|
||||
### Generar enlace de redirección:
|
||||
|
||||
Desde un controlador, si tu necesitas para From a controller, si tu necesitas realizar una redirección:
|
||||
|
||||
```php
|
||||
$this->url->to('mycontroller', 'myaction', array('plugin' => 'myplugin'));
|
||||
```
|
||||
|
||||
Generar:
|
||||
|
||||
```
|
||||
?controller=mycontroller&action=myaction&plugin=myplugin
|
||||
```
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
Plugin Migración de esquemas
|
||||
============================
|
||||
|
||||
Kanboard realiza migraciones de base de datos automaticamente para ti.
|
||||
Las migraciones deben ser almacenadas en una carpeta **Schema** y el nombre de archivo debe ser el mismo que el controlador de base de datos:
|
||||
|
||||
```bash
|
||||
Schema
|
||||
├── Mysql.php
|
||||
├── Postgres.php
|
||||
└── Sqlite.php
|
||||
```
|
||||
|
||||
Cada archivo contiene todas las migraciones, aqui un ejemple para Sqlite:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace Kanboard\Plugin\Something\Schema;
|
||||
|
||||
const VERSION = 1;
|
||||
|
||||
function version_1($pdo)
|
||||
{
|
||||
$pdo->exec('CREATE TABLE IF NOT EXISTS something (
|
||||
"id" INTEGER PRIMARY KEY,
|
||||
"project_id" INTEGER NOT NULL,
|
||||
"something" TEXT,
|
||||
FOREIGN KEY(project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||
)');
|
||||
}
|
||||
```
|
||||
|
||||
- La constante `VERSION` es la ultima versión de tu esquema
|
||||
- Cada funcion es una migración `version_1()`, `version_2()`, etc.
|
||||
- Una instancia `PDO` es pasado como un primer argumneto
|
||||
- Todo se ejecuta dentro de una transacción , si algo no funciona se realiza una operación de rollback y se muestra el error al usuario
|
||||
|
||||
Kanboard siempre compara la version definida en tu esquema y la version almacenada en la base de datos. Si la versiones son diferentes, kanboard siempre ejecuta cada migración una por una hasta alcanzar la ultima version.
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
Desarrollo de Plugin
|
||||
====================
|
||||
|
||||
Nota : el plugin API es **considerado alpha** en estos momentos.
|
||||
|
||||
Los plugins son útiles para extender las funcionalidades básicas de Kanboard , la adición de características , la creación de temas o cambiar el comportamiento por defecto .
|
||||
|
||||
Los creadores de plugins deben especificar explícitamente las versiones compatibles de Kanboard . El código interno de Kanboard puede cambiar con el tiempo y su extensión debe ser probado con nuevas versiones . Compruebe siempre el [ChangeLog](https://github.com/kanboard/kanboard/blob/master/ChangeLog) para realizar los cambios.
|
||||
|
||||
- [Crear tu plugin](plugin-registration.markdown)
|
||||
- [Usar plugins hooks](plugin-hooks.markdown)
|
||||
- [Eventos](plugin-events.markdown)
|
||||
- [Rescribir compartamientos por default en la aplicación](plugin-overrides.markdown)
|
||||
- [Agregar plugins para migrar esquemas](plugin-schema-migrations.markdown)
|
||||
- [Personalizar rutas](plugin-routes.markdown)
|
||||
- [Agregar helpers](plugin-helpers.markdown)
|
||||
- [Agregar trasportes de email ](plugin-mail-transports.markdown)
|
||||
- [Agregar tipos de notificaciones](plugin-notifications.markdown)
|
||||
- [Agregar acciones automaticas](plugin-automatic-actions.markdown)
|
||||
- [Adjuntar metados para usuarios,tareas y proyectos](plugin-metadata.markdown)
|
||||
- [Arquitectura de autenticación](plugin-authentication-architecture.markdown)
|
||||
- [Registración de plugins de autenticación](plugin-authentication.markdown)
|
||||
- [Arquitectura de autorización](plugin-authorization-architecture.markdown)
|
||||
- [Personlizar grupos de proveedores](plugin-group-provider.markdown)
|
||||
- [Links externos para proveedores](plugin-external-link.markdown)
|
||||
- [Agregar avatar a proveedores](plugin-avatar-provider.markdown)
|
||||
- [Cliente LDAP](plugin-ldap-client.markdown)
|
||||
|
||||
Ejemplos de plugins
|
||||
-------------------
|
||||
|
||||
- [SMS Two-Factor Authentication](https://github.com/kanboard/plugin-sms-2fa)
|
||||
- [Reverse-Proxy Authentication with LDAP support](https://github.com/kanboard/plugin-reverse-proxy-ldap)
|
||||
- [Slack](https://github.com/kanboard/plugin-slack)
|
||||
- [Hipchat](https://github.com/kanboard/plugin-hipchat)
|
||||
- [Jabber](https://github.com/kanboard/plugin-jabber)
|
||||
- [Sendgrid](https://github.com/kanboard/plugin-sendgrid)
|
||||
- [Mailgun](https://github.com/kanboard/plugin-mailgun)
|
||||
- [Postmark](https://github.com/kanboard/plugin-postmark)
|
||||
- [Amazon S3](https://github.com/kanboard/plugin-s3)
|
||||
- [Budget planning](https://github.com/kanboard/plugin-budget)
|
||||
- [User timetables](https://github.com/kanboard/plugin-timetable)
|
||||
- [Subtask Forecast](https://github.com/kanboard/plugin-subtask-forecast)
|
||||
- [Automatic Action example](https://github.com/kanboard/plugin-example-automatic-action)
|
||||
- [Theme plugin example](https://github.com/kanboard/plugin-example-theme)
|
||||
- [CSS plugin example](https://github.com/kanboard/plugin-example-css)
|
||||
Loading…
Reference in New Issue