Création d'une galerie Photo en JavaScript avec ZetaPush

Tutoriel pas à pas

Morvan Mikael

Dans ce tutoriel je vous guide pas à pas sur l'utilisation du BaaS (Backend As A Service) ZetaPush et sur l'usage du SDK JavaScript permettant de connecter vos pages web en temps réel.
Commentez

- Titre : Création d'une galerie Photo en JavaScript avec ZetaPush

- Auteur : Morvan Mikael

- Parution : 10 novembre 2016

- Mise à jour : 10 novembre 2016

- Public visé :

- Licence : Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright ® 2016 Morvan Mikael. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Introduction

- II. Mise en place de l'environnement de développement

- II-A. En résumé

- II-B. Création d'un compte gratuit sur ZetaPush

- II-C. Création d'une nouvelle recette

- II-C-1. Description

- II-C-2. Paramétrage du fichier zms.user.properties

- II-C-3. Paramétrage du fichier zms.properties

- II-C-4. Ajout d'un compte utilisateur

- II-C-5. Déployons la recette sur ZetaPush (lançons la fusée)

- II-D. Bilan de la première étape

- III. Connexion à ZetaPush en JavaScript

- III-A. Description

- III-B. Code JavaScript

- III-C. Test

- IV. Récupération des photos

- IV-A. Description

- IV-B. Modification de la recette

- IV-C. Code JavaScript

- IV-D. Test

- V. Upload des photos

- V-A. Description

- V-B. Modification de la recette

- V-C. Code JavaScript

- V-D. Test

- VI. Suppression des photos

- VI-A. Description

- VI-B. Modification de la recette

- VI-C. Code JavaScript

- VI-D. Test

- VII. Affichage des miniatures

- VII-A. Description

- VII-B. Modification de la recette

- VII-C. Code JavaScript

- VII-D. Test

- VIII. Recherche par tag

- VIII-A. Description

- VIII-B. Modification de la recette

- VIII-C. Code JavaScript

- VIII-D. Test

- IX. Conclusion

- X. Remerciements

I - Introduction

ZetaPush est un Realtime BaaS ( Backend As A Service) fournissant toute l'infrastructure serveur dont vous avez besoin quand vous réalisez des application connectées. Nous gérons la partie serveur, vous vous occupez de connecter vos applications mobiles, web, serveur et vos objets connectés.

Pour illustrer la mise en œuvre d'un vrai cas d'usage, je vous propose de réaliser pas à pas une application de galerie photo à la Flickr.

Cette application web va permettre de gérer sa galerie de photos en recherchant les photos par tag. Pour la démonstration, on a ajouté un système qui supprime automatiquement les photos au bout d'une minute.

Voici l'aperçu de ce que vous obtiendrez à la fin de ce tutoriel :

II - Mise en place de l'environnement de développement

Voici le lien (en anglais) de la documentation d'installation d'Eclipse et du plugin ZMS (ZetaPush Macro Script) :

Quickstart ZetaPush (en anglais).

II-A - En résumé

1. Installation du JDK 1.8
Installation du JDK 1.8.

2. Installation d'Eclipse ( version 4.2 ou supérieure)
Téléchargement d'Eclipse.

3. Installation du plugin ZetaPush
Dans le menu Eclipse « Aide/Installer un nouveau logiciel », ajoutez une nouvelle URL https://zms-site.zetapush.com/releases/.
Cochez « Installer ZMS ».
Redémarrez Eclipse.

Vous devriez obtenir une vue similaire à cette copie d'écran une fois que vous aurez activé la perspective ZMS (Menu Fenêtre / Ouvrir la perspective / ZMS).

II-B - Création d'un compte gratuit sur ZetaPush

Rendez-vous sur le site d'administration de ZetaPush et créez un compte gratuit.

Par défaut, lors de la création d'un compte sur ZetaPush, une sandbox gratuite est créée. Cette sandbox est identifiée de manière unique par son SandboxId.

II-C - Création d'une nouvelle recette

II-C-1 - Description

Une recette contient l'ensemble des éléments nécessaires au déploiement et au paramétrage de votre Sandbox. Ce code source permet de déclarer les services techniques que vous souhaitez déployer (stockage de fichiers, moteurs de recherche, envoi de mails…) ainsi que le code d'initialisation de ceux-ci. Bien entendu, vous pouvez également écrire du code métier spécifique à votre application.

Dans Eclipse, allez dans le menu « Fichier » et choisissez « Nouveau/ZMS Recipe » :

Dans la fenêtre qui suit, donnez un nom à votre recette (généralement votre nom de domaine suivi de votre nom de projet, par exemple fr.zetapush.gallery) et saisissez votre SandboxId récupéré précédemment.

Un nouveau projet est créé avec les éléments suivants :

- un répertoire src avec un fichier exemple welcome.zms ;

- un fichier init.zms qui sert à initialiser les services une fois qu'ils ont été déployés ;

- un fichier README.md ;

- un fichier recipe.zms qui permet de créer les services que vous souhaitez utiliser ;

- un fichier zms.properties qui sert à gérer les properties globales au projet ;

- un fichier zms.user.properties qui sert à gérer les properties du développeur.

II-C-2 - Paramétrage du fichier zms.user.properties

Afin de déployer la recette ZMS en production, il est nécessaire d'indiquer les éléments suivants :

- zms.businessId ⇒ votre SandboxId ;

- zms.username ⇒ le mail qui vous a servi à vous connecter au site admin.zpush.io ;

- zms.password ⇒ le mot de passe qui vous a permis de vous connecter au site admin.zpush.io ;

- passez zms.upload.enabled à true.

II-C-3 - Paramétrage du fichier zms.properties

Le fichier zms.properties est un fichier permettant de gérer les propriétés du projet. Si une propriété est commune au fichier zms.properties et au fichier zms.user.properties, seule la valeur contenue dans le fichier zms.user.properties sera utilisée.

Dans le fichier zms.properties, vous pouvez modifier le mot de passe de la propriété zms.test.password.

II-C-4 - Ajout d'un compte utilisateur

Pour les besoins de notre application de galerie photo, nous allons créer un compte utilisateur qui se connectera à ZetaPush.

Dans le fichier init.zms, copiez le code suivant :

Création d'un compte utilisateur

auth.memauth_createUser({
login: 'demo',
password: 'demo',
idempotence: Idempotence_IGNORE_IDENTICAL
});

Ce code permet de créer un nouveau compte utilisateur (s'il n'existe pas déjà). Vous pouvez trouver la documentation du service ici : Service d'authentification simple.

II-C-5 - Déployons la recette sur ZetaPush (lançons la fusée)

Dans la barre d'outils ZMS, cliquez sur la fusée rouge…

La recette se déploie sur ZetaPush et au bout de 30 s maximum, vous obtenez un « SUCCESS ».

Si ça ne fonctionne pas, vérifiez que vous avez bien saisi vos login, mot de passe et sandboxId dans le fichier zms.user.properties.

II-D - Bilan de la première étape

Qu'avons-nous obtenu suite à cette première étape ?

Nous avons une sandbox en production sur le cloud de ZetaPush :

- elle a un service de macros déployé (https://ref.zpush.io/#it_macro);

- elle a un service d'authentification avec deux utilisateurs créés ;

- elle a une macro appelée welcome.

Et maintenant que cette étape est terminée, passons au code client en JavaScript et connectons notre page web à ZetaPush.

Afin de se concentrer sur la partie essentielle, j'ai préparé le code source client et je l'ai séparée en étapes de « step-1 » à « step-final ». Vous pouvez cloner ou télécharger ce code source depuis l'adresse dépot github.

Dans chaque répertoire constituant une étape, il y a deux fichiers :

- index.html ;

- index.js.

Seul le fichier index.js nous intéresse ici, car c'est là qu'est situé le code utile. Le fichier index.html charge quelques bibliothèques utiles pour l'affichage et également le SDK JavaScript de ZetaPush.

Pour tester chaque étape, vous pouvez ouvrir le fichier index.html dans votre navigateur préféré ou bien utiliser un serveur web local.

Si vous voulez coder pas à pas la partie cliente, vous pouvez commencer par le répertoire step-0.

Vous remarquerez qu'un répertoire recipe est présent avec le code source de la recette. Ne regardez pas tout de suite, gardez le suspens :).

III - Connexion à ZetaPush en JavaScript

III-A - Description

Cette étape va vous montrer comment il est simple de se connecter à ZetaPush.

III-B - Code JavaScript

Le code JavaScript est très simple : il crée un objet client ZetaPush avec comme paramètre le SandboxId ainsi qu'une authentification avec login/mot de passe.

Connexion à ZetaPush

// Création du client ZetaPush
const client = new ZetaPush.Client({
sandboxId: 'Votre_SandboxId',
authentication() {
return ZetaPush.Authentication.simple({
login: 'demo',
password: 'demo'
})
}
})

Une fois que le client est créé, on peut s'inscrire sur les callbacks de connexion/déconnexion pour afficher l'état de la connexion à ZetaPush.

Callback de connexion

// Event de connexion
client.onConnectionEstablished(() => {
$status.textContent=('signal_wifi_4_bar')
})
client.onConnectionClosed(() => {
$status.textContent=('signal_wifi_off')
})

Et pour finir, on appelle la fonction connect() pour effectuer la connexion à ZetaPush.

Connexion à ZetaPush

// Connexion au backend
client.connect()

III-C - Test

Si tout se passe bien, on a l'indicateur de connexion qui a changé.

Si vous ouvrez les outils pour les développeurs, vous pouvez constater dans la partie « network » qu'une connexion websocket est établie avec les serveurs de ZetaPush.

IV - Récupération des photos

IV-A - Description

Maintenant qu'on a réussi à se connecter à ZetaPush, on va s'intéresser un peu à la manière de récupérer les photos.

Pour ce faire, on va écrire notre première macro qui aura pour but de retourner toutes les photos précédemment stockées. On va appeler cette macro : listFiles.

IV-B - Modification de la recette

Pour gérer les fichiers, ZetaPush dispose d'un service nommé zpfs_hdfs décrit dans la documentation de référence ici : Documentation du service de gestion de fichiers.

Ce service de fichiers a le même comportement que le système de fichier unix : mkdir, ls, cp… avec des éléments en plus pour uploader des fichiers. Ce service peut être paramétré pour automatiquement générer des miniatures des photos qu'il reçoit, c'est ce paramétrage que nous allons utiliser dans l'application.

Pour pouvoir commencer à utiliser le service de fichiers, il faut le déclarer dans notre recette dans le fichier recipe.zms.

Fichier recipe.zms

/** create a file storage with thumbnail auto creation */
service fs = zpfs_hdfs('zpfs_hdfs_0').options({
upload_thumbnails: '250,500,1000' // auto-magically create thumbnails
});

Avec cette simple déclaration, nous avons accès à un service de gestion de fichiers générant automatiquement des vignettes de 250, 500 et 1 000 pixels de large quand le fichier est une image.

Déployons ce nouveau service avant de l'utiliser

Maintenant, on va pouvoir utiliser ce service dans une macro.

Dans Eclipse, créez un nouveau fichier nommé files.zms dans le répertoire src. (en cliquant sur le répertoire src, clic droit puis nouveau.. fichier).

Dans ce nouveau fichier, ajoutez le code suivant :

Fichier files.zms

/** Déclaration d'un macro nommée listFiles */
macroscript listFiles(
string folder = '/'
) {
var listing = fs.ls({ folder });
} return { listing } on channel __selfName

Remarquez la déclaration du retour de fonction :

Le «  return { listing } » permet de retourner le contenu de la variable listing

et le « on channel __selName » permet de retourner ce contenu sur un channel d'écoute ayant le même nom que la fonction « __selfName ». Vous comprendrez comment ça marche dans le code JavaScript.

Et on déploie le code.

IV-C - Code JavaScript

Dans notre JavaScript, ajoutez le code suivant :

Création du service de macro

const api = client.createService({
Type: ZetaPush.services.Macro,
listener: {
listFiles({ data: { result } }) {
const cards = result.listing.entries.content
$cards.textContent=(JSON.stringify(cards))
}
}
})

Ce code permet de créer un nouveau service de type ZetaPush.services.Macro. Lors de la création de ce nouveau service, on va déclarer un listener « listFiles » qui a le même nom que la macro créée précédemment. Vous vous souvenez du __selfName ?

Maintenant qu'on a déclaré ce nouveau service, on va l'appeler.

Modifiez le code de la callback de connexion comme suit :

Événement de connexion

// Event de connexion
client.onConnectionEstablished(() => {
api.call({ name: 'listFiles' }) // Appel du service déclaré précédemment avec comme paramètre la macro qu'on a créée.
$status.textContent=('signal_wifi_4_bar')
})

IV-D - Test

Rien d'éblouissant dans ce test, on a simplement en retour un tableau Json vide, car on n'a aucun fichier. Justement, on va maintenant ajouter des fichiers.

V - Upload des photos

V-A - Description

Pour ajouter des photos, on va bien entendu créer de nouvelles macros pour ajouter un fichier sur ZetaPush.

Une petite précision sur le fonctionnement de l'upload du service de gestion de fichiers. L'upload se passe en plusieurs étapes :

1. Je demande au service une URL d'upload de fichier ;

2. J'upload mon fichier sur l'URL renvoyée ;

3. J'appelle la fonction de validation d'upload.

Dans cette étape, on va également ajouter la description du fichier dans le moteur de recherche.

V-B - Modification de la recette

Tout d'abord, il faut déclarer notre nouveau service de moteur de recherche. Vous trouverez la documentation de référence ici : Documentation du service de recherche.

Comme précédemment, vous déclarez ce nouveau service dans le fichier recipe.zms

Déclaration du service de recherche

service es = search('search_0');

Un changement par rapport aux services déclarés précédemment, le service de moteur de recherche a besoin d'être initialisé. En effet, le cluster ElasticSearch que nous utilisons doit créer un nouvel index pour votre service. Ce nouvel index doit être déclaré dans le fichier init.zms

Déclaration de l'index ElasticSearch

es.search_createIndex({
index: 'gallery',
mappings: {
file: {
properties: {
tags: {
type: "string"
},
name: {
type: "string"
}
}
}
}
});

Je ne vais pas décrire plus avant la syntaxe de déclaration d'index, car c'est une pure syntaxe ElasticSearch.

Vous déployez le nouveau service en production.

Maintenant que le service de recherche est déployé, on va l'utiliser conjointement au service de gestion de fichiers.

Dans le fichier files.zms, ajoutez la macro suivante :

Macro uploadFile

macroscript uploadFile(
string path = '/'
) {
var upload = fs.newUploadUrl({ path });
} return { upload } on channel __selfName

Comme expliqué dans la description, l'appel à la fonction newUploadUrl va demander à ZetaPush une URL d'upload de fichier qu'on va renvoyer à l'appelant de la macro.

Continuons la modification des recettes en traitant le cas de la fin de l'ajout de fichier :

Macro addFile

/** Déclaration d'une macro appelée après l'upload effectif d'un fichier */
macroscript addFile(
string guid,
map metadata,
array tags
) {
// Confirmation de l'upload effectif du fichier
var file = fs.newFile({ guid, metadata, tags });

// Ajout de la description du fichier dans le moteur de recherche
es.index({
id: file.url.guid,
data: file,
index: 'gallery',
type: 'file'
});
} broadcast { file } on channel __selfName

et on déploie le code.

Avant de vous expliquer ce mot clef, il faut comprendre le fonctionnement de ZetaPush : c'est un système temps réel sur lequel les utilisateurs sont connectés en permanence. Un même utilisateur, s'il dispose de plusieurs périphériques, peut être connecté plusieurs fois sur ZetaPush.

Quand un utilisateur fait appel à un service ou à une macro, ce n'est que l'utilisateur sur la connexion qui a effectué l'appel qui recevra la notification. Et donc le mot clef « broadcast » permet d'appeler tous les périphériques de l'utilisateur connecté. C'est simple non ?

Dans le cas de la macro d'ajout de fichier, on va afficher une nouvelle image dans l'interface quand on recevra la callback d'ajout. Donc, si on est connecté sur plusieurs fenêtres en même temps, l'image sera ajoutée sur toutes les fenêtres simultanément et pas uniquement sur la fenêtre ayant ajouté le fichier.

V-C - Code JavaScript

Pour tester cela, on va modifier notre code JavaScript et un peu le code du fichier index.html (step-3).

Dans le index.html, remplacez la partie <main> par :

Fichier index.html

<main>
<form id="form" class="row">
<div class="file-field input-field col m4 s12">
<div class="btn">
<span>File</span>
<input type="file" accept="image/*" required>
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text">
</div>
</div>
<div class="input-field col m4 s12">
<input id="tags" type="text" class="validate" required>
<label class="active" for="tags">Tags</label>
</div>
<div class="input-field col m4 s12">
<button class="btn waves-effect waves-light" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div>
<div class="progress hide">
<div class="indeterminate"></div>
</div>
</form>
<div id="cards" class="row"></div>
</main>

et dans le code JavaScript du fichier index.js, ajoutez de nouveaux listeners lors de la création du service de macros :

Ajout de listeners

const api = client.createService({
Type: ZetaPush.services.Macro,
listener: {
addFile({ data: { result } }) {
$progress.classList.add('hide')
api.call({ name: 'listFiles' })
},
listFiles({ data: { result } }) {
const cards = result.listing.entries.content
$cards.textContent=(JSON.stringify(cards))
},
uploadFile({ data: { result } }) {
const [ file ] = $file.files
const { url, httpMethod, guid } = result.upload
const tags = $tags.value ? $tags.value.split(' ') : []
upload({ file, url, httpMethod, guid, tags }).then(() => {
$form.reset()
api.call({ name: 'addFile', parameters: { guid, tags } })
})
}
}
})

Et on ajoute une callback lors de la soumission du formulaire d'upload de photos

Ajout de callback

// Manager Form Submit
$form.addEventListener('submit', (event) => {
event.preventDefault()
$progress.classList.remove('hide')
api.call({ name: 'uploadFile' })
})

V-D - Test

Lors du test, une fois que vous avez ajouté un fichier, vous devriez voir apparaître la description du fichier.

VI - Suppression des photos

VI-A - Description

Pour supprimer les photos, on va le faire de manière originale en les supprimant automatiquement au bout d'un certain temps. L'intérêt est faible bien entendu pour une vraie application, mais c'est l'occasion de vous montrer l'utilisation d'un nouveau service : le « Scheduler » ou « Cron » (planificateur en bon français). Vous pouvez retrouver la documentation de référence du service « Cron » ici :Documentation du service de Cron.

VI-B - Modification de la recette

Maintenant que vous avez l'habitude, on va déclarer ce nouveau service dans le fichier recipe.zms :

Recipe.zms

service task = cron('cron_0');

Et vous déployez le nouveau service en production.

Dans notre macro d'ajout de fichier, on va planifier l'effacement de celui-ci au bout d'un certain temps. Notre macro addFile devient :

Modification de la macro addFile

/** Déclaration d'une macro appelée après l'upload effectif d'un fichier */
macroscript addFile(
string guid,
map metadata,
array tags
) {
// Confirmation de l'upload effectif du fichier
var file = fs.newFile({ guid, metadata, tags });

// Ajout de la description du fichier dans le moteur de recherche
es.index({
id: file.url.guid,
data: file,
index: 'gallery',
type: 'file'
});

// Suppression du fichier au bout de 60 secondes
// On appelle la macro deleteFile
task.setTimeout({
delay: 60,
deploymentId : 'macro_0',
verb : 'call',
parameter : {
name: 'deleteFile',
parameters: { guid }
}
});

} broadcast { file } on channel __selfName

Lors de l'appel au task.setTimeout, on appelle la macro deleteFile qu'il faut maintenant créer :

Macro deleteFile

/** Macro permettant d'effacer un fichier du service de fichiers et du service de recherches' */
macroscript deleteFile(
string guid
) {
fs.rm({
path: '/' + guid
});
es.delete({
id: guid,
index: 'gallery',
type: 'file'
});
} broadcast { guid } on channel __selfName

On déploie le code

et on va tester tout ça dans le JavaScript.

VI-C - Code JavaScript

Peu de modifications par rapport à l'étape précédente, seule une callback à rajouter lors de la création du service de macros. On a également modifié le rendu d'affichage pour afficher la photo.

Suppression d'une photo

const api = client.createService({
Type: ZetaPush.services.Macro,
listener: {
addFile({ data: { result } }) {
$progress.classList.add('hide')
api.call({ name: 'listFiles' })
},
deleteFile({ data: { result } }) {
api.call({ name: 'listFiles' })
},
listFiles({ data: { result } }) {
const cards = result.listing.entries.content
render(cards)
},
uploadFile({ data: { result } }) {
const [ file ] = $file.files
const { url, httpMethod, guid } = result.upload
const tags = $tags.value ? $tags.value.split(' ') : []
upload({ file, url, httpMethod, guid, tags }).then(() => {
$form.reset()
api.call({ name: 'addFile', parameters: { guid, tags } })
})
}
}
})

VI-D - Test

Le test montre maintenant nos images affichées dans la fenêtre avec leur disparition au bout d'une minute.

VII - Affichage des miniatures

VII-A - Description

Vous avez certainement remarqué que les photos affichées avaient la même taille que les photos envoyées. Ce n'est pas ce qu'on souhaite, on veut afficher les miniatures des images.

Côté ZetaPush, ces miniatures sont réalisées de manière asynchrone et une fois le travail terminé, un message est propagé pour prévenir que les miniatures sont prêtes. Dans le code JavaScript, il suffit alors d'avoir un listener sur « updateMeta » pour être prévenu lorsque les miniatures sont prêtes.

VII-B - Modification de la recette

Rien à faire pour cette étape, le service de gestion de fichiers a été initialisé pour créer automatiquement des miniatures.

VII-C - Code JavaScript

Le code JavaScript est simple, on va créer un nouveau service de type ZetaPush.services.Zpft_hdfs et on va ajouter un listener sur updateMeta :

Callback updateMetadata

const fs = client.createService({
Type: ZetaPush.services.Zpfs_hdfs,
listener: {
updateMeta({ data }) {
document.querySelector(`[card-name="${data.name}"] img`).src = thumnail(data)
}
}
})

VII-D - Test

Pour le test, on a le même visuel que l'étape précédente. On remarque juste un nouveau chargement d'image lorsque le thumbnail est affiché en lieu et place de la photo originale.

VIII - Recherche par tag

VIII-A - Description

Dernière étape de ce tutoriel, la recherche par tag. Depuis qu'on a mis en place le moteur de recherche, on ne l'a pas utilisé. On va mettre en place une recherche par tag qui permettra, lorsque l'utilisateur cliquera sur le tag d'une des photos, de sélectionner toutes les photos ayant le même tag.

VIII-B - Modification de la recette

Dans le fichier files.zms, on va ajouter une nouvelle macro de recherche prenant en paramètre un tableau de tag.

Le service de recherches va être appelé à travers une requête classique ElasticSearch.

Macro searchFiles

/** Macro permettant de rechercher des fichiers par un tableau de tag */
macroscript searchFiles(
array tags
) {
// Ceci est une requête typique ElasticSearch
var result = es.search({
indices: ['gallery'],
query: {
match: {
tags: {
query: str:join(' ', tags),
operator: 'and'
}
}
},
types: ['file']
});
/** Mise en forme du résultat */
var items = result.items;
} return { items } on channel __selfName

On déploie le code

et on va tester que la recherche fonctionne.

VIII-C - Code JavaScript

On va modifier notre code de création de service de macro pour ajouter un nouveau listener « searchFiles ».

Le code devient :

Ajout d'un listener searchFiles

const api = client.createService({
Type: ZetaPush.services.Macro,
listener: {
error(message) {
console.error('error', message)
},
addFile({ data: { result } }) {
$progress.classList.add('hide')
api.call({ name: 'listFiles' })
},
deleteFile({ data: { result } }) {
api.call({ name: 'listFiles' })
},
listFiles({ data: { result } }) {
const cards = result.listing.entries.content
render(cards)
},
searchFiles({ data: { result } }) {
const cards = result.items.content.map(({ data }) => data)
render(cards)
},
uploadFile({ data: { result } }) {
const [ file ] = $file.files
const { url, httpMethod, guid } = result.upload
const tags = $tags.value ? $tags.value.split(' ') : []
upload({ file, url, httpMethod, guid, tags }).then(() => {
$form.reset()
api.call({ name: 'addFile', parameters: { guid, tags } })
})
}
}
})

Et côté interface, on va appeler la recherche après un clic sur un tag. L'appui sur la touche echap du clavier annulera la recherche.

On ajoute donc le code suivant au fichier index.js :

Gestion d'événements

$('main').on('click', '[data-tag]', (event) => {
api.call({ name: 'searchFiles', parameters: { tags: [ event.target.dataset.tag ] } })
})
$(window).on('keyup', ({ key }) => {
if (key === 'Escape') {
api.call({ name: 'listFiles' })
}
})

VIII-D - Test

Lorsqu'on ajoute trois images avec différents tags (tag1, tag2, tag3), sans la recherche, toutes les images sont affichées.

Et une fois qu'on a effectué une recherche en cliquant sur le tag1 par exemple, seules les photos contenant le tag1 sont affichées.

IX - Conclusion

Ce tutoriel vous a montré comment réaliser simplement une application de galerie photo à l'aide de ZetaPush. Bien entendu, il manque de nombreuses fonctionnalités à cette application pour être directement exploitable. Pour autant, comme cette application exploite un BaaS, elle peut déjà tenir certaines promesses :

- elle est capable de monter en charge par construction ;

- les macros développées sont directement accessibles aux smartphones et aux objets connectés ;

Et pour vous dans le cadre du développement d'application :

- réduction du temps de développement ;

- réduction du temps de déploiement ;

- réduction de la maintenance ;

- utilisation de briques techniques directement utilisables.

Pour aller plus loin, vous pouvez ajouter simplement de nouvelles fonctionnalités à cette démonstration :

- notifications par mail/sms/push notif lorsqu'une photo est ajoutée ou supprimée ;

- gestion des comptes utilisateurs ;

- gestion du partage de photos entre utilisateurs.

Et pour aller encore plus loin, sachez qu'il sera possible d'importer des recettes ZetaPush déjà prêtes : que pensez-vous de l'en tête d'une recette de :

import com.zetapush.gallery ?

Et bien ça existe déjà et je vous en parlerai dans un futur article.

X - Remerciements

Je tiens à remercier Malick SECK pour sa relecture orthographique.