jueves, 12 de noviembre de 2015

Virtualenv python3 django

sudo apt-get install python-virtualenv
cd ~
virtualenv -p python3 env_django
source ~/env_django/bin/activate
pip install Django==1.8.6


Para MacOS este tutorial incluye información de cómo configurar pyvenv.

brew install python3
python3 --version
pip install --upgrade pip
pip install virtualenv
pip install virtualenvwrapper
mkdir ~/.virtualenvs
vi ~/.bashrc
--> Añadir:
export WORKON_HOME=~/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
--<
source .bashrc
--> buscar directorio de python3 con
which python3
mkvirtualenv --python=python3_path env-django
--> ya tenemos el entorno con python3 activado
deactivate
workon env-django
pip install Django==1.9



martes, 3 de noviembre de 2015

Instalar LaTeX y pandoc en Ubuntu

Desde el software center, instalar TexMaker

Para instalar  packages

sudo apt-get install xzdec
tlmgr install nombre_paquete


Opcionalmente, para los paquetes de idiomas de babel

sudo apt-get install texlive-lang-spanish
sudo apt-get install texlive-lang-european

Probar

\documentclass[10pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage[spanish]{babel}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\author{Pere Vilás}
\begin{document}
dddd

\end{document}


Para instalar pandoc

sudo apt-get install cabal-install
cabal update
PATH=$HOME/.cabal/bin:$PATH
cabal update
cabal install alex happy
sudo apt-get install libghc-zlib-dev  libghc-zlib-bindings-dev
cabal install pandoc pandoc-citeproc
pandoc --version

viernes, 30 de octubre de 2015

Aplicaciones web de gestión con Oracle JET. ¿Porqué no habías salido antes?

Oracle acaba de sacar su framework JET para la creación de front-end de aplicaciones web usando Javascript.

Me figuraba que sería otro de los "tochos" de esta empresa, con documentación críptica y montones de manuales por leerse. Nada de eso: El producto va como como la seda. Con JET se pueden empezar aplicaciones con un par de clicks, sabiendo que estás sobre un framework muy bien estructurado y que te quita la mayoría de dolores de cabeza típicos de una aplicación de gestión.

Una vez descargada la plantilla, sólo hay que hacer copia-pegar de las "recetas" que cubren una gran cantidad de supuestos de uso o "patterns" que nos encontramos en este tipo de aplicaciones. La plantilla está diseñada para que el código esté ordenado y sea fácil de mantener.

Está basado sobre código abierto (aunque JET no lo es al 100% de momento). Usa, entre otros, jquery y knockout para la sincronización.

Las plantillas vienen por defecto con mobile first, lo que nos ahorra tener que pensar también en el aspecto del renderizado en múltiples plataformas.

Para aplicaciones de gestión es especialmente interesante el apartado de Data collections, podemos asociar los UI widgets a nuestras fuentes de datos de forma bastante fácil.

Sólo necesitamos un sencillo servidor web corriendo en la raiz del proyecto para poder trabajar.

A diferencia de otros frameworks más especializados, JET decide un montón de cosas del front de tu aplicación. El aspecto, menús,  interacción,... Esto puede ser bueno si lo que necesitas es concentrarte en el backend.

Lo que me gusta es que trabajas con él de la misma forma en que tú ya estás trabajando: Cuando necesitas algo, lo buscas, le haces copiar-pegar y lo adaptas a tu necesidad.

El contar con el respaldo de una empresa como Oracle también es un tanto a favor en cuanto a la estabilidad y mantenimiento del framework. Oracle quiere meterse en las tablets y los móviles y me da la impresión de que por este camino, ayudando a los desarrolladores, va a conseguirlo.

No es para nada casualidad que hace poco Oracle creaba su centro de soporte para Node y sacara los drivers oficiales (node-oracledb) para conectar este con su gestor de base de datos. La apuesta de Oracle por Javascript y el mobile va muy en serio.

Un servidor web, ¡rapido!

python -m SimpleHTTPServer 8000

jueves, 8 de octubre de 2015

Github da soporte al formato jupyter notebook

Desde Mayo de 2015 github da soporte directo a los notebooks de jupyter. Esto significa que serán renderizados en github antes de visualizarse. Hasta ahora, la única forma de ver los notebooks de otros era usando el servicio gratuito o tenerlos hosteados en alguna plataforma.

Desde ahora, ya tenemos a nuestra disposición todo el poder de github y su control de versiones más el añadido de poder visualizar los cuadernos directamente... Sin duda una combinación que cambiará muchas cosas en la publicación de documentos.

Ejemplo.

jueves, 17 de septiembre de 2015

Javascript atravesar árbol JSON

El problema

Tenemos el árbol de menú de una aplicación. Cada hoja tiene unos permisos asociados. Sólo queremos mostrar los nodos de los que el usuario tenga algún permiso.

Una posible forma de hacerlo es recorrer el árbol una vez y acumular en los nodos los permisos del nivel por debajo. El recorrido sería en postorden.

Los usuarios tienen grupos de permisos (roles). En el momento de generar el menú de un usuario particular, deberemos volver a recorrer el árbol, esta vez en anchura (por niveles), tomando sólo aquellos nodos que tengan algún permiso coincidente. Si no hay ninguno, no es necesario bajar al siguiente nivel de esa rama.

Árbol de menús

var modulos = [


    {permiso: [], descripcion: 'Almacenes', url: '#',
        submenus: [
            {permiso: ['compras.alb.ver'], descripcion: 'Artículos',   url: '/app/articulos'},
            {permiso: ['compras.prov.ver'], descripcion: 'Proveedores', url: '/app/proveedores'},
            {permiso: ['alm.inv.ver'], descripcion: 'Inventario',  url: '/app/inventario'},
            {permiso: ['alm.edit'], descripcion: 'Almacenes',   url: '/app/almacenes'}
        ]
    },

    {permiso: [], descripcion: 'Compras', url: '#',
        submenus: [
            {permiso: ['compras.pedidos.ver'], descripcion: 'Pedidos', url: '/app/compras/pedidos'},
            {permiso: ['compras.albaranes.ver'], descripcion: 'Albaranes', url: '/app/compras/albaranes', 
            submenus: [
             {permiso: ['compras.alb.edt'], descripcion: 'Editar',   url: '/app/albaranes/edit'},
            {permiso: ['compras.alb.lst'], descripcion: 'Listar', url: '/app/albaranes/list'},
            ]},
        ]
    },
];

El nodo Almacenes debería contener los permisos de los que tiene por debajo, el nodo Albaranes debería contener [compras.alb.edt, compras.alb.lst] y el nodo Compras [compras.pedidos.ver, compras.albaranes.ver, compras.alb.edt, compras.alb.lst].

Recorrido de un árbol JSON en postorden

Observamos que tenemos tanto objects como arrays: Atravesamos los arrays con forEach y los objetos examinando sus claves con for (var key in obj) . Bajamos hasta la primera hoja de la izquierda, visitando las hermanas para subir después al nodo superior. El proceso se repite de forma recursiva hasta haber visitado todos los nodos. Mantenemos la referencia al nodo inmediatamente superior con parent para poder acumular en él los permisos.

var _und = require("underscore");

// último nodo visitado
var lastObject=null;

/** 
* Atraviesa un arbol JSON en postorden
* @param x - el nodo actual
* @param level - sólo para debug, caracter para imprimir delante de los nodos
* @parent - referencia al nodo padre o null
*/
function traverse(x, level, parent) {
    if (isArray(x)) {
        traverseArray(x, level, parent);
    } else if ((typeof x === 'object') && (x !== null)) {
        traverseObject(x, level, parent);
    } else {
        // tipus primitiu
    }
}

/**
* Determina si el tipo es array
* @param o - el objeto javascript
* @return true si es un aray
*/
function isArray(o) {
    return Object.prototype.toString.call(o) === '[object Array]';
}

function traverseArray(arr, level, parent) {
    arr.forEach(function(x) {
        traverse(x, level + "  ", parent);
    });
    //console.log(level + "<array>");
}

function traverseObject(obj, level, parent) {
    //console.log(level + "<object>");

    for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
            lastObj=parent
            traverse(obj[key], level + "    ", obj);
        }
    }

    // Acumulamos los permisos en el padre
    // usamos _und.union para evitar permisos duplicados
    if (obj && obj.descripcion) {
        var p=''
        if (parent) {
            p=parent.descripcion           
            parent.permiso=_und.union(parent.permiso, obj.permiso)
        } else {
            p='/'
        }
        console.log('visitant', obj.descripcion,'amb pare', p);
    }
}

Ahora ya sólo queda hacer

traverse(modulos, '')

Para mostrar los menús, podemos poner una marca de visibilidad y enviar el árbol al renderizador de plantillas que sólo mostrará los que tengan visible==true.

var recurseMenus= function(permisos, m) {
    _und.each(m, function(md) {
        //logger.debug('mirant si menu', md.descripcion, 'te el permís', md.permiso)
        // hacemos la intersección del conjunto de permisos del usuario con los del nodo actual
        var interseccio=_und.intersection(md.permiso, permisos)
        // si el resultado de la intersección es diferente del conjunto vacío el usuario puede ver este menú
        if (_und.size(interseccio)>0) {
            //logger.debug('te permis de ', md.permiso)
            md.visible=true
            if (md.submenus) {
                recurseMenus(permisos, md.submenus)
            }
        } else {
            //logger.debug('no te el permis')
            md.visible = false;
        }
    })
}

Referencias

https://www.quora.com/How-do-you-loop-through-a-complex-JSON-tree-of-objects-and-arrays-in-JavaScript