Sharepoint-search: un componente Polymer para usar la búsqueda de SharePoint On-Line

Muy buenas a todos.

En una entrada anterior, os contaba cómo usar la búsqueda de SharePoint a través de su servicio API REST. El enlace ha dicha entrada es la siguiente:

Search Driven Development. Usando la API REST de SharePoint para el servicio de búsqueda

Al final de esta entrada os contaba que como objetivo, tenía el desarrollo de un componente Polymer que permitiera usar este servicio, algo que me resultaba muy útil e interesante. Después de varios días de trabajo, quería compartir con vosotros una primera “versión” de dicho componente. Aún queda trabajo por delante, pero ya hay un punto de partida funcional a partir del cual seguir trabajando.

El componente debía cumplir con los siguientes requisitos:

  • Permitir la posibilidad de usar refinadores.
  • Permitir la posibilidad de establecer opciones de ordenamiento.
  • Controlar la paginación y el número de resultados por página en los resultados de búsqueda.
  • Dar la posibilidad de estilar el contenido del componente en función de como se desee.

El componente “sharepoint-search” nos permite cubrir estos requisitos. Para usarlo, necesitaremos tener cargados los ficheros de Polymer y los propios del componente y utilizaremos la etiqueta de la siguiente manera:

<sharepoint-search tenant="organizer" clientid="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" refinement="author,size,created" ordination="size,created" pageElement="15">
</sharepoint-search>

Para que funcione correctamente, necesitaremos el clientID de una aplicación de Azure AD con los permisos para el servicio de búsqueda de SharePoint concedidos, y obviamente estar logado en nuestra aplicación contra esa aplicación de Azure AD, para ello podemos usar el componente para la autenticación que creé en una entrada anterior y seguir los correspondientes pasos para obtener el clientid:

Registrando una aplicación en Azure Active Directory

login-azuread: Un Componente Web con Polymer y Javascript ADAL

Además deberemos de configurar la aplicación de nuestra Azure AD para permitir el OAuth 2.0 implicit grant flow, lo haremos de la siguiente forma:

  • Acceder a la configuración de la aplicación de Azure AD correspondiente
  • Descargamos el manifiesto
  • Modificamos el parámetro oauth2AllowImplicitFlow dándole el valor true en lugar de false que tiene establecido inicialmente
  • Cargamos de nuevo el manifiesto modificado

El componente “sharepoint-search” permite configurar los siguientes parámetros:

  • tenant: Indicar el tenant al que nos queremos conectar
  • clientid: Clientid de la aplicación con los permisos adecuados
  • refinement: Propiedades para las cuales queremos obtener refinamiento
  • ordination: Propiedades por las que queremos hacer ordenación
  • pageElement: Número de elementos por página a mostrar

Una vez que lo añadimos, funciona como vemos a continuación.

sharepointsearchinit

sharepointsearchsearched

Por defecto, el componente nos muestra los resultados en una lista con el título del documento y la posibilidad de descargar el mismo. Aunque como se indica a continuación, en futuras mejoras, se trabajará en flexibilizar este aspecto del componente.

Os dejo el enlace a mi cuenta de GitHub donde podéis descargar el código del componente web y donde podréis encontrar información sobre cómo usarlo.

https://github.com/jcroav/sharepoint-search

Y esto es todo por hoy, este componente aún tiene áreas de mejora, a las que intentaré dedicarle tiempo en las próximas semanas. Os dejo algunas de las ideas:

  • El componente está pensado para que los resultados de búsqueda usen a su vez un subcomponente para ser mostrados, queda pendiente de desarrollar esa parte.
  • Completar el componente con la funcionalidad de sugerencias
  • Mejorar toda la parte de estilado
  • Refactorizar y trabajar sobre la optimiazación del código para hacer un componente más robusto

Como siempre, todo aquel que quiera colaborar, o quiera usar el componente que os he mostrado hoy para mejorarlo, es libre de hacerlo. El objetivo de estos desarrollos, a parte de para aprender a usar las funcionalidades de Office 365 y SharePoint On-Line, es contribuir a la comunidad.

Un saludo y espero que os sea útil

Anuncios

login-azuread: Un Componente Web con Polymer y Javascript ADAL

Hola a todos,

En la entrada anterior os contaba como se podía usar la librería Javascript ADAL para autenticar una aplicación contra Azure AD usando Javascript y terminaba diciendo que os contaría sobre el componente Polymer que había desarrollado para la autenticación.

Autenticación de nuestra Aplicación usando Javascript ADAL

Lo que he hecho ha sido crear un componente web que permite de una forma sencilla hacer la autenticación y que añadiéndolo a cualquiera de nuestras aplicaciones, podamos gestionar el sign in contra Azure AD de la misma. El código del componente web lo podéis encontrar en mi cuenta de GitHub.

Azuread-login en GitHub

El modo de empleo es muy sencillo, solo tendremos que insertar la siguiente línea en donde queramos tener nuestro modulo de login.

<login-azuread domain="<tenantdomainhere>" clientid="<clientidhere>"
</login-azuread>

Antes, deberemos haber registrado la aplicación en Azure AD, lo que nos proporcionará un client ID. Para que el componente funcione correctamente, deberemos indicar en el atributo domain, el dominio de nuestro tenant y en el atributo clientid el dato obtenido tras el registro de la aplicación en Azure AD.

¿Cuál es el resultado?

Vamos a ver como funciona el componente web una vez lo usamos en un ejemplo.

Cuando un usuario no se ha autenticado.

azureadlogin1

azureadlogin2

Cuando un usuario se ha autenticado
azureadlogin3

Además el componente se ha diseñado de manera que los elementos que lo forman, no se encuentran dentro del Shadow DOM que usa Polymer, sino que están renderizados por el DOM de la página, de manera que podemos estilarlos por medio del CSS de nuestra aplicación. Para ello, solo tenemos que redefinir las clases loginad-name, loginad-a, logoutad-a.

¿Vemos algo de código?

El código es muy sencillo, y aunque lo podéis ver en GitHub os lo pongo aquí y explico algunos detalles. El componente lo forman dos ficheros, uno .html y otro .js

<script src="../../Scripts/polymer.min.js"></script>
<script src="../../Scripts/adal.js"></script>

<polymer-element name="login-azuread" attributes="domain clientID" />
    <template>
        <content select="span"></content>
        <content select="a"></content>
        <content select="a"></content>
    </template>
    <script src="login.js"></script>
</polymer-element>

El fichero .html contiene la definición del componente web. Como véis el template utiliza la etiqueta content, que nos va a permitir que el contenido del componente no esté renderizado en el Shadow DOM y si en el DOM de la página.

window.config = {
    tenant: '',
    clientId: '',
    postLogoutRedirectUri: window.location.origin,
    cacheLocation: 'localStorage', // enable this for IE, as sessionStorage does not work for localhost.
};

var authContext;

Polymer({
    userName: '',
    domain: '',
    clientID: '',
    ready: function () {
        window.config.tenant = this.domain;
        window.config.clientId = this.clientID;

        authContext = new AuthenticationContext(config);

        var isCallback = authContext.isCallback(window.location.hash);
        authContext.handleWindowCallback();

        if (isCallback &amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp; !authContext.getLoginError()) {
            window.location = authContext._getItem(authContext.CONSTANTS.STORAGE.LOGIN_REQUEST);
        }

        // Check Login Status, Update UI
        var user = authContext.getCachedUser();

        if (user)
            this.userName = user.userName;
        else
            this.userName = '';

    },
    attached: function () {
        var name = document.createElement("span");
        name.innerHTML = this.userName;
        name.className = "loginad-name";

        var login = document.createElement("a");
        login.href = "javascript:;";
        login.innerText = "Login";
        login.className = "loginad-a";
        login.addEventListener("click", this.login, true);

        if (this.userName != '')
            login.style.display = "none";
        else
            login.style.display = "inline-block";

        var logout = document.createElement("a");
        logout.href = "javascript:;";
        logout.innerText = "Logout";
        logout.className = "logoutad-a";
        logout.addEventListener("click", this.logout, true);

        if (this.userName != '')
            logout.style.display = "inline-block";
        else
            logout.style.display = "none";

        this.appendChild(name);
        this.appendChild(login);
        this.appendChild(logout);
    },
    login: function () {
        authContext.login();
    },
    logout: function () {
        authContext.logOut();
    }
});

La particularidad de este código es que, como podemos ver, utiliza la función ready de Polymer para cargar el objeto de configuración y comprobar si está autenticado el usuario y la función attached para inyectar todos los elementos que forman el componente, con la funcionalidad de cada uno.

¿Es mejorable?, como siempre, claro que lo es. Y me encantaría recibir feedback de qué más podríamos hacer para que este componente fuera realmente útil y pudiéramos usarlo en nuestras aplicaciones como una alternativa más.

Saludos, espero que lo hayáis encontrado interesante.

Polymer. Usando Arrays en el modelo de datos del Componente Web

Muy buenas a tod@s.

Sigo profundizando en este framework de Javascript, con el objetivo de llegar a un conocimiento del mismo que me permita poder usarlo activamente en mis desarrollos en proyectos reales. En post anteriores de esta serie relacionada con Polymer, habíamos visto por un lado la estructura básica para definir un elemento, y por otro cómo usar CSS dentro del componente definido y cómo renderizar elementos dentro del mismo.

Introducción a Polymer. Mi primer componente web

Polymer: CSS y cómo renderizar elementos dentro del componente web

Hoy quiero mostrar cómo podríamos trabajar con un array dentro de nuestro modelo de datos del componente. Es muy sencillo, así que voy a pasar directamente a mostraros el código del componente y mostraros los aspectos importantes del mismo.

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="example-posts">
	<template>
		<ul>
			<template repeat="{{post in posts}}">
				<li>
					<h2>{{post.title}}</h2>
					<p>{{post.body}}</p>
				</li>
			</template>
		</ul>
	</template>
	<script>
		Polymer({
			posts: [
				{title: 'Example post 1', body: 'This is the body of this post'},
				{title: 'Example post 2', body: 'This is the body of this post. The second of this array'},
				{title: 'Example post 3', body: 'This is the body of the last post'}
			]
		});
	</script>
</polymer-element>

El código, como os decía, por sí solo es muy sencillo, pero vamos a explicar los aspectos más importantes del mismo.

  • El atributo repeat del template, le dice a Polymer que tiene que crear un fragmento de código para cada elemento del array.
  • En el interior de ese template se establece cómo será el aspecto de ese fragmento.
  • Por medio de la expresión {{post.title}} o {{post.body}} se pueden acceder a las propiedades de los objetos del array.

El resultado de usar este componente en un proyecto web.

Captura de pantalla 2015-01-31 a las 17.25.03

Por supuesto podríamos mejorar este código y usar el concepto propio de Polymer de crear Componentes Web, para crear un componente web que representara a un post, y usarlo dentro del ejemplo anterior. Vamos a ver cómo sería este código, dónde se ve la creación del componente post y como se usa posteriormente.

<link rel="import" href="../bower_components/polymer/polymer.html">

<polymer-element name="example-post" attributes="title body">
	<template>
		<li>
			<h2>{{title}}</h2>
			<p>{{body}}</p>
		</li>
	</template>
	<script>
		Polymer({
			title: '',
			body: ''
		});
	</script>
</polymer-element>

<polymer-element name="example-posts">
	<template>
		<ul>
			<template repeat="{{post in posts}}">
				<example-post title="{{post.title}}" body="{{post.body}}"></example-post>
			</template>
		</ul>
	</template>
	<script>
		Polymer({
			posts: [
				{title: 'Example post 1', body: 'This is the body of this post'},
				{title: 'Example post 2', body: 'This is the body of this post. The second of this array'},
				{title: 'Example post 3', body: 'This is the body of the last post'}
			]
		});
	</script>
</polymer-element>

Y esto es todo por hoy, con este post, completo ya por fin bastantes de los aspectos que quería trabajar de Polymer, ahora espero empezar a usar este framework de forma intensiva en mis proyectos webs, ya que en mi opinión ofrece muchas ventajas y aspectos interesantes a tener en cuenta.

Un saludo a todos

Polymer: CSS y cómo renderizar elementos dentro del componente web

Muy buenas a todos,

En una entrada anterior, os contaba cómo podríamos usar este framework para crear un componente web que fuese fácilmente reutilizable. Os contaba también, algunos de los aspectos básicos de funcionamiento de Polymer para dotar a ese componente web de atributos y el binding que incorpora el framework y las oportunidades que nos ofrece.

Introducción a Polymer. Mi primer componente web

Hoy os quiero contar otras dos funcionalidades relevantes que nos ofrece este framework Javascript en un breve post, y que espero que junto con el anterior os aporte un conocimiento más profundo sobre el uso de esta herramienta para desarrollo web.

¿Podemos estilar nuestro componente web?

Pues la respuesta es si, podemos añadir código CSS para estilar el componente. Para ver cómo hacerlo voy a utilizar el componente que había creado en el post anterior y le voy a añadir código CSS.

<polymer-element name="example-polymer" attributes="attr1 attr2">
	<template>
		<style>
			:host
			{
				width:50%;
				margin-left:25%;
				margin-top:5%;
				background-color:#DDD;
				display: block;
				padding: 1em;
			}

			h1
			{
				color:red;
			}

			.ejemploClase
			{
				color:blue;
				cursor:pointer;
			}
		</style>
		<h1>Esto es un ejemplo de uso de Polymer</h1>
		<p>{{attr1}}</p>
		<input type="text" value="{{attr2}}" />

		<h2>Usando el binding</h2>
		<p class="ejemploClase">Ejemplo de binding {{attr2}}</p>
	</template>
	<script>
		Polymer({
			attr2Changed: function(){
				if(this.attr2.length == 11)
					console.log("Esta es una cadena de 11 caracteres");
			}
		});
	</script>
</polymer-element>

Aquí hay solo un aspecto importante que destacar y es el uso de la pseudo-clase :host en el CSS. Esta clase hace referencia a la raíz del componente web, es decir, al propio componente web. Además de esto, podemos definir los estilos y clases de CSS como habitualmente lo hacemos, con la única salvedad de que solo afectarán a los elementos en el interior del componente. Vamos a ver el resultado de aplicar estos estilos.

Captura de pantalla 2015-01-24 a las 18.30.26

¿Cómo puedo renderizar elementos insertados dentro de mi componente web?

Volviendo al ejemplo del post anterior, se nos puede ocurrir, como hacemos con cualquier etiqueta del HTML estándar, hacer algo como lo siguiente:

<example-polymer attr1="Ejemplo" attr2="Otro ejemplo">
	<h3>Ejemplo</h3>
</example-polymer>

Si probamos este código, observaremos que no funciona correctamente, es decir, el navegador no renderiza los elementos hijos del componente web, lo que se traduce en que el tag h3 no se ve en nuestro navegador. ¿Quiere decir esto que no puedo insertar elementos dentro del componente web?, pues no. Podemos hacerlo, pero para ello tenemos que crear lo que se conoce en Polymer como Insertion Points, lo que le dirá al navegador donde tiene que renderizar los hijos en nuestro componente.

<polymer-element name="example-polymer" attributes="attr1 attr2">
	<template>
		<style>
			:host
			{
				width:50%;
				margin-left:25%;
				margin-top:5%;
				background-color:#DDD;
				display: block;
				padding: 1em;
			}

			h1
			{
				color:red;
			}

			.ejemploClase
			{
				color:blue;
				cursor:pointer;
			}
		</style>
		<h1>Esto es un ejemplo de uso de Polymer</h1>
		<p>{{attr1}}</p>
		<input type="text" value="{{attr2}}" />

		<h2>Usando el binding</h2>
		<p class="ejemploClase">Ejemplo de binding {{attr2}}</p>
                <content select="h3"></content>
	</template>
	<script>
		Polymer({
			attr2Changed: function(){
				if(this.attr2.length == 11)
					console.log("Esta es una cadena de 11 caracteres");
			}
		});
	</script>
</polymer-element>

Para crear lo que hemos denominado Insertion Points, utilizamos el tag content y en el atributo select indicamos la etiqueta que queramos. Con esto, estamos indicándole a Polymer que en el caso de que haya un nodo hijo con la etiqueta h3, se renderice en ese lugar. Si volvemos ahora a usar el componente web como dijimos anteriormente veremos el resultado que nos da, y como ahora si renderiza la etiqueta h3

Captura de pantalla 2015-01-24 a las 18.48.01

¿Puedo estilar esos elementos renderizados por medio de <content>?

Nuevamente la respuesta es si. Para ello haremos uso de la siguiente estructura dentro del style del componente

polyfill-next-selector { content: 'h3'; }
::content h3 {
     color: green;
}

con la pseudo-clase ::content se selecciona un Insertion Point (creado por el tag content), y con ::content h3 se selecciona cualquier h3 definido a través de content como Insertion Point.

Para los navegadores que no soportan Shadow DOM se utiliza la regla polyfill-next-selector, para indicarle cómo proceder con la pseudo-clase ::content.

Si nuevamente probamos nuestro código, vemos que el estilo se ha aplicado correctamente.

Captura de pantalla 2015-01-24 a las 19.07.18

Y esto es todo por hoy, espero que os sirva de utilidad para conocer en más profundidad formas de trabajar con Polymer. Próximamente, veremos cómo usar modelos dentro de un componente Polymer.

Un saludo a todos, buen fin de semana