diff --git a/README.md b/README.md index 4f9d085..a7f1563 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,13 @@ PITAYA_LOG_LEVEL=debug NODE_ENV=development npm start Vous pouvez configurer le comportement de Pitaya en passant des variables d'environnement: -| Variable | Description | Valeurs possibles | Valeur par défaut | -|-------------------|----------------------------------------|-------------------------------|-------------------------------| -| PITAYA_MODE | Mode d'exécution de Pitaya | launcher, edit | launcher | -| PITAYA_PROFILE | Chemin du fichier profil à charger | -- | ./default-profile.json | -| PITAYA_AS_DESKTOP | Afficher Pitaya en mode "Bureau" | 1, 0 | 0 | -| PITAYA_LOG_FILE | Enregistrer les logs dans un fichier | Chemin absolu vers un fichier | aucune (pas d'enregistrement) | -| PITAYA_LOG_LEVEL | Niveau de log | debug, info, error, fatal | info | +| Variable | Description | Valeurs possibles | Valeur par défaut | +|-------------------|-----------------------------------------------|-------------------------------|-------------------------------| +| PITAYA_MODE | Mode d'exécution de Pitaya | launcher, edit | launcher | +| PITAYA_PROFILE | Chemin ou URL du fichier profil à charger | -- | ./default-profile.json | +| PITAYA_AS_DESKTOP | Afficher Pitaya en mode "Bureau" | 1, 0 | 0 | +| PITAYA_LOG_FILE | Enregistrer les logs dans un fichier | Chemin absolu vers un fichier | aucune (pas d'enregistrement) | +| PITAYA_LOG_LEVEL | Niveau de log | debug, info, error, fatal | info | ## Comment construire l'application depuis les sources @@ -39,6 +39,49 @@ npm run build Un dossier `pitaya--` sera créé dans le répertoire `./build`. Celui ci contient tous les fichiers nécessaires à l'application. +## Profils + +Un fichier de profil est utilisé par Pitaya afin de définir l'arborescence d'applications affichée par le lanceur. +Ce fichier est au format JSON et a la structure récursive suivante: + +```json +{ + "items": [ + { + "label": "Label de mon item de type catégorie", + "icon": "Chemin vers l'image d'icône", + "background": "Chemin vers l'image de fond, si besoin", + "items": [ + { + "label": "Label de mon sous-item 1 de type application", + "icon": "Chemin vers l'image d'icône", + "exec": "Commande d'exécution de mon application" + }, + { + "label": "Label de mon sous-item 2 de type catégorie", + "items": [ + { + "label": "etc..." + } + ] + } + ] + } + ] +} +``` + +### Différence entre catégories et applications + +Un item comprenant un tableau `items` sera automatiquement considéré comme une catégorie et non plus une application, même si la propriété `exec` est également définie. + +### Import de profils externes + +Il est possible d'ajouter une propriété `import` avec comme valeur un chemin de fichier ou une URL sur un item. + +Lors du chargement du profil, le lanceur "montera" automatiquement le fichier externe désigné sur l'item portant la propriété. + +Voir le fichier `default-profile.json` pour un exemple. ## Comment contribuer diff --git a/img/hourglass.svg b/img/hourglass.svg index a75ae8a..9ac5376 100644 --- a/img/hourglass.svg +++ b/img/hourglass.svg @@ -43,7 +43,7 @@ id="namedview30" showgrid="false" inkscape:zoom="13.350176" - inkscape:cx="-3.9872051" + inkscape:cx="-17.807248" inkscape:cy="18.89309" inkscape:window-x="0" inkscape:window-y="0" diff --git a/package.json b/package.json index 0294413..a58aae1 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "recursive-iterator": "^2.0.0", "redux": "^2.0.0", "redux-thunk": "^0.1.0", + "request": "^2.65.0", "winston": "^1.1.2" } } diff --git a/partial-profile.json b/partial-profile.json index ee92b8b..f036f83 100644 --- a/partial-profile.json +++ b/partial-profile.json @@ -1,5 +1,17 @@ { "label": "Partial Level 1", "icon": "chromium-browser", - "background": "./img/background2.jpg" + "background": "./img/background2.jpg", + "items": [ + { + "label": "Firefox", + "icon": "firefox", + "exec": "firefox" + }, + { + "label": "Libreoffice Writer", + "icon": "libreoffice-writer", + "exec": "libreoffice --writer" + } + ] } diff --git a/src/components/launcher/launcher-view.js b/src/components/launcher/launcher-view.js index 975d330..b6e8086 100644 --- a/src/components/launcher/launcher-view.js +++ b/src/components/launcher/launcher-view.js @@ -88,9 +88,19 @@ var LauncherView = React.createClass({ onItemClick: function(evt, itemPath, item) { - if(item.exec) { + console.log(item); + + if(item.items) { + + this.play(this.refs.appList, 'slide-out-left 250ms ease-in-out') + .then(function() { + this.setState({ currentItemPath: itemPath, currentItem: item }); + return this.play(this.refs.appList, 'slide-in-right 250ms ease-in-out'); + }.bind(this)) + ; + + } else if(item.exec) { - logger.debug('Launching application "'+item.exec+'"...'); var el = evt.currentTarget; el.classList.add('pulse'); @@ -104,12 +114,7 @@ var LauncherView = React.createClass({ ; } else { - this.play(this.refs.appList, 'slide-out-left 250ms ease-in-out') - .then(function() { - this.setState({ currentItemPath: itemPath, currentItem: item }); - return this.play(this.refs.appList, 'slide-in-right 250ms ease-in-out'); - }.bind(this)) - ; + logger.info('No action associated with item "'+item.label+'".'); } }, diff --git a/src/util/system.js b/src/util/system.js index 0e7688d..23f3927 100644 --- a/src/util/system.js +++ b/src/util/system.js @@ -3,14 +3,47 @@ var cp = require('child_process'); var glob = require('glob'); var ini = require('ini'); var Cache = require('./cache'); +var request = require('request'); +var HTTP_REGEX = /^https?:\/\//i; /** - * Load a JSON file + * Load a JSON file (http or local) * * @param filePath The path of the json file * @return Promise */ -exports.loadJSON = function(filePath) { +exports.loadJSON = function(jsonUrl) { + if( HTTP_REGEX.test(jsonUrl) ) { + return exports.fetchRemoteJSON(jsonUrl); + } else { + return exports.loadLocalJSON(jsonUrl); + } +}; + +/** + * Load a remote JSON file via http + * + * @param filePath The path of the json file + * @return Promise + */ +exports.fetchRemoteJSON = function(fileUrl) { + return new Promise(function(resolve, reject) { + request(fileUrl, { followRedirect: true, json: true }, function (err, res, body) { + if(err) return reject(err); + console.log(body); + return resolve(body); + }); + }); +}; + + +/** + * Load a local JSON file + * + * @param filePath The path of the json file + * @return Promise + */ +exports.loadLocalJSON = function(filePath) { return new Promise(function(resolve, reject) { fs.readFile(filePath, 'utf8', function(err, fileContent) { if(err) return reject(err); diff --git a/test/profile.js b/test/profile.js index c175c81..3e21cc9 100644 --- a/test/profile.js +++ b/test/profile.js @@ -6,7 +6,6 @@ ProfileSuite.loadProfileWithImport = function(test) { Profile.load(__dirname+'/../default-profile.json') .then(function(profile) { - console.log('%j', profile); test.ok(profile.items[0].label === "Partial Level 1", "It should have loaded the partial import !"); test.done(); })