diff --git a/www/i18n/locale-en.json b/www/i18n/locale-en.json index 530d982252cf5a0f67ff90d3445176155e62cb84..f44db8824efd42e56034ca5cffbdd586fa82abe8 100644 --- a/www/i18n/locale-en.json +++ b/www/i18n/locale-en.json @@ -13,7 +13,9 @@ "MENU": { "TITLE": "Cesium", "HOME": "Home", - "CURRENCIES": "Currencies", + "REGISTRY": "Registry", + "MARKET": "Market place", + "CURRENCIES": "Expore currencies", "ACCOUNT": "My Account" }, "HOME": { @@ -83,15 +85,40 @@ "COMMENTS": "Comments", "COMMENTS_HELP": "Comments" }, - "RECORD": { + "MARKET": { "COMMON": { "CATEGORY": "Category", "CATEGORIES": "Categories", "ISSUER": "Issuer" }, "SEARCH": { - "TITLE": "Explore", - "SEARCH_HELP": "Search (e.g. car, store)", + "TITLE": "Market", + "SEARCH_HELP": "Search (car, store)", + "BTN_ADD": "New", + "BTN_OPTIONS": "Search tool" + }, + "VIEW": { + "TITLE": "" + }, + "EDIT": { + "TITLE": "New", + "BTN_ADD_PICTURES": "Add pictures", + "RECORD_TITLE": "Title", + "RECORD_TITLE_HELP": "Title", + "RECORD_DESCRIPTION": "Description", + "RECORD_DESCRIPTION_HELP": "Description", + "RECORD_LOCATION": "Location" + } + }, + "REGISTRY": { + "COMMON": { + "CATEGORY": "Category", + "CATEGORIES": "Categories", + "ISSUER": "Issuer" + }, + "SEARCH": { + "TITLE": "Registry", + "SEARCH_HELP": "Search (name, pseudo, public key...)", "BTN_ADD": "New", "BTN_OPTIONS": "Search tool" }, diff --git a/www/i18n/locale-fr.json b/www/i18n/locale-fr.json index 2edae23d2fe98e395c97ae7bc6badb08543fe614..a93db70421f847cb218a103b7758ad6e95475dd4 100644 --- a/www/i18n/locale-fr.json +++ b/www/i18n/locale-fr.json @@ -13,6 +13,8 @@ "MENU": { "TITLE": "Cesium", "HOME": "Accueil", + "REGISTRY": "Annuaire", + "MARKET": "Offres/Demandes", "CURRENCIES": "Monnaies", "ACCOUNT": "Mon compte" }, @@ -83,14 +85,14 @@ "COMMENTS": "Commentaires", "COMMENTS_HELP": "Commentaires" }, - "RECORD": { + "MARKET": { "COMMON": { "CATEGORY": "Catégorie", "CATEGORIES": "Catégories", "ISSUER": "Soumis par" }, "SEARCH": { - "TITLE": "Recherche", + "TITLE": "Offres/Demandes", "SEARCH_HELP": "Recherche (voiture, livre...)", "BTN_ADD": "Nouveau", "BTN_OPTIONS": "Outil de recherche" diff --git a/www/index.html b/www/index.html index cb48e6a3e702bec88bb96e9bcc3436d3e07bfd72..8948db87d52c6f51784f1403a0925aaa65e4416e 100644 --- a/www/index.html +++ b/www/index.html @@ -37,7 +37,8 @@ <script src="js/services/utils-services.js"></script> <script src="js/services/wallet-services.js"></script> <script src="js/services/bma-services.js"></script> - <script src="js/services/record-services.js"></script> + <script src="js/services/market-services.js"></script> + <script src="js/services/registry-services.js"></script> <!-- entities --> <script src="js/entity/peer.js"></script> @@ -48,13 +49,13 @@ <script src="js/controllers/peer-controllers.js"></script> <script src="js/controllers/currency-controllers.js"></script> <script src="js/controllers/wallet-controllers.js"></script> - <script src="js/controllers/record-controllers.js"></script> + <script src="js/controllers/market-controllers.js"></script> + <script src="js/controllers/registry-controllers.js"></script> <!-- App --> <script src="js/app.js"></script> <script src="js/services.js"></script> <script src="js/controllers.js"></script> - <script src="js/translate.js"></script> </head> <body ng-app="cesium"> diff --git a/www/js/controllers.js b/www/js/controllers.js index 6fc900c15ef3ab26c018863cc37afdf2f69096e1..81be6b422af80592b5c3b4602d55e1c3954f9064 100644 --- a/www/js/controllers.js +++ b/www/js/controllers.js @@ -4,7 +4,8 @@ angular.module('cesium.controllers', [ 'cesium.wallet.controllers', 'cesium.currency.controllers', 'cesium.wot.controllers', - 'cesium.record.controllers' + 'cesium.market.controllers', + 'cesium.registry.controllers' ]) .config(function($httpProvider) { diff --git a/www/js/controllers/currency-controllers.js b/www/js/controllers/currency-controllers.js index d8989dbaaf86b494701f1e6c22bb65e4c7aa979f..7c8bed42b7170be8234be806b03d63b5aebbc10c 100644 --- a/www/js/controllers/currency-controllers.js +++ b/www/js/controllers/currency-controllers.js @@ -5,7 +5,7 @@ angular.module('cesium.currency.controllers', ['cesium.services']) $stateProvider .state('app.explore_currency', { - url: "/home/explore", + url: "/currency", views: { 'menuContent': { templateUrl: "templates/explore/explore_currency.html", @@ -15,7 +15,7 @@ angular.module('cesium.currency.controllers', ['cesium.services']) }) .state('app.explore_tabs', { - url: "/currency", + url: "/currency/view", views: { 'menuContent': { templateUrl: "templates/explore/explore_tabs.html", diff --git a/www/js/controllers/record-controllers.js b/www/js/controllers/market-controllers.js similarity index 76% rename from www/js/controllers/record-controllers.js rename to www/js/controllers/market-controllers.js index b6e3da31a925a7f4746a942da642b318a1c9773e..9150d59372a0f48d3e67d8613c94b5f10924e660 100644 --- a/www/js/controllers/record-controllers.js +++ b/www/js/controllers/market-controllers.js @@ -1,63 +1,63 @@ -angular.module('cesium.record.controllers', ['cesium.services']) +angular.module('cesium.market.controllers', ['cesium.services']) .config(function($stateProvider, $urlRouterProvider) { $stateProvider - .state('app.lookup_record', { - url: "/record", + .state('app.market_lookup', { + url: "/market", views: { 'menuContent': { - templateUrl: "templates/record/lookup.html", - controller: 'RecordLookupCtrl' + templateUrl: "templates/market/lookup.html", + controller: 'MarketLookupCtrl' } } }) - .state('app.view_record', { - url: "/record/:id", + .state('app.market_view_record', { + url: "/market/:id", views: { 'menuContent': { - templateUrl: "templates/record/view_record.html", - controller: 'RecordCtrl' + templateUrl: "templates/market/view_record.html", + controller: 'MarketRecordViewCtrl' } } }) - .state('app.add_record', { - url: "/record/add", + .state('app.market_add_record', { + url: "/market/add", views: { 'menuContent': { - templateUrl: "templates/record/edit_record.html", - controller: 'RecordEditCtrl' + templateUrl: "templates/market/edit_record.html", + controller: 'MarketRecordEditCtrl' } } }) - .state('app.edit_record', { - url: "/record/:id/edit", + .state('app.market_edit_record', { + url: "/market/:id/edit", views: { 'menuContent': { - templateUrl: "templates/record/edit_record.html", - controller: 'RecordEditCtrl' + templateUrl: "templates/market/edit_record.html", + controller: 'MarketRecordEditCtrl' } } }); }) - .controller('RecordLookupCtrl', RecordLookupController) + .controller('MarketLookupCtrl', MarketLookupController) - .controller('RecordCtrl', RecordController) + .controller('MarketRecordViewCtrl', MarketRecordViewController) - .controller('RecordEditCtrl', RecordEditController) + .controller('MarketRecordEditCtrl', MarketRecordEditController) ; -function CategoryModalController($scope, Record, $state, $ionicModal) { +function MarketCategoryModalController($scope, Market, $state, $ionicModal) { $scope.categoryModal = null; // category lookup modal - $ionicModal.fromTemplateUrl('templates/record/modal_category.html', { + $ionicModal.fromTemplateUrl('templates/market/modal_category.html', { scope: $scope, focusFirstInput: true }).then(function(modal) { @@ -67,7 +67,7 @@ function CategoryModalController($scope, Record, $state, $ionicModal) { $scope.openCategoryModal = function() { // load categories - Record.record.category.all() + Market.category.all() .then(function(categories){ $scope.categories = categories; $scope.categoryModal.show(); @@ -85,9 +85,9 @@ function CategoryModalController($scope, Record, $state, $ionicModal) { }; } -function RecordLookupController($scope, Record, $state, $ionicModal) { +function MarketLookupController($scope, Market, $state, $ionicModal) { - CategoryModalController.call(this, $scope, Record, $state, $ionicModal); + MarketCategoryModalController.call(this, $scope, Market, $state, $ionicModal); $scope.search = { text: '', @@ -148,7 +148,7 @@ function RecordLookupController($scope, Record, $state, $ionicModal) { request.query.match = matches[0].match; } - return Record.record.search(request) + return Market.record.search(request) .then(function(res){ $scope.search.looking = false; if (res.hits.total == 0) { @@ -156,18 +156,18 @@ function RecordLookupController($scope, Record, $state, $ionicModal) { } else { $scope.search.results = res.hits.hits.reduce(function(result, hit) { - var record = hit._source; - record.id = hit._id; - record.type = hit._type; + var market = hit._source; + market.id = hit._id; + market.type = hit._type; if (hit.highlight) { if (hit.highlight.title) { - record.title = hit.highlight.title[0]; + market.title = hit.highlight.title[0]; } if (hit.highlight.description) { - record.description = hit.highlight.description[0]; + market.description = hit.highlight.description[0]; } } - return result.concat(record); + return result.concat(market); }, []); } }) @@ -178,11 +178,11 @@ function RecordLookupController($scope, Record, $state, $ionicModal) { }; $scope.select = function(id) { - $state.go('app.view_record', {id: id}); + $state.go('app.market_view_record', {id: id}); }; } -function RecordController($scope, $ionicModal, Wallet, Record, UIUtils, $state, CryptoUtils, $q) { +function MarketRecordViewController($scope, $ionicModal, Wallet, Market, UIUtils, $state, CryptoUtils, $q) { $scope.formData = {}; $scope.id = null; @@ -196,16 +196,16 @@ function RecordController($scope, $ionicModal, Wallet, Record, UIUtils, $state, $scope.load($state.stateParams.id); } else { - $state.go('app.lookup_record'); + $state.go('app.market_lookup'); } }); $scope.load = function(id) { UIUtils.loading.show(); $q.all([ - Record.record.category.all() + Market.category.all() .then(function(categories) { - Record.record.get({id: id}) + Market.record.get({id: id}) .then(function (hit) { $scope.formData = hit._source; $scope.category = categories[hit._source.category]; @@ -219,17 +219,17 @@ function RecordController($scope, $ionicModal, Wallet, Record, UIUtils, $state, UIUtils.loading.hide(); }) }) - ]).catch(UIUtils.onError('Could not load record')); + ]).catch(UIUtils.onError('Could not load market')); }; $scope.edit = function() { - $state.go('app.edit_record', {id: $scope.id}); + $state.go('app.market_edit_record', {id: $scope.id}); }; } -function RecordEditController($scope, $ionicModal, Wallet, Record, UIUtils, $state, CryptoUtils, $q, $ionicPopup) { +function MarketRecordEditController($scope, $ionicModal, Wallet, Market, UIUtils, $state, CryptoUtils, $q, $ionicPopup) { - CategoryModalController.call(this, $scope, Record, $state, $ionicModal); + MarketCategoryModalController.call(this, $scope, Market, $state, $ionicModal); $scope.walletData = {}; $scope.formData = {}; @@ -258,9 +258,9 @@ function RecordEditController($scope, $ionicModal, Wallet, Record, UIUtils, $sta $scope.load = function(id) { UIUtils.loading.show(); $q.all([ - Record.record.category.all() + Market.category.all() .then(function(categories) { - Record.record.get({id: id}) + Market.record.get({id: id}) .then(function (hit) { $scope.formData = hit._source; $scope.category = categories[hit._source.category]; @@ -274,7 +274,7 @@ function RecordEditController($scope, $ionicModal, Wallet, Record, UIUtils, $sta }); }) ]) - .catch(UIUtils.onError('Could not load record')) + .catch(UIUtils.onError('Could not load market')) }; $scope.save = function() { @@ -284,22 +284,22 @@ function RecordEditController($scope, $ionicModal, Wallet, Record, UIUtils, $sta return res.concat({src: pic.src}); }, []); if (!$scope.id) { // Create - Record.record.add($scope.formData, $scope.walletData.keypair) + Market.record.add($scope.formData, $scope.walletData.keypair) .then(function(id) { UIUtils.loading.hide(); - $state.go('app.view_record', {id: id}) + $state.go('app.market_view_record', {id: id}) resolve(); }) - .catch(UIUtils.onError('Could not save record')); + .catch(UIUtils.onError('Could not save market')); } else { // Update - Record.record.update($scope.formData, {id: $scope.id}, $scope.walletData.keypair) + Market.record.update($scope.formData, {id: $scope.id}, $scope.walletData.keypair) .then(function() { UIUtils.loading.hide(); - $state.go('app.view_record', {id: $scope.id}) + $state.go('app.market_view_record', {id: $scope.id}) resolve(); }) - .catch(UIUtils.onError('Could not update record')); + .catch(UIUtils.onError('Could not update market')); } }); }; @@ -399,7 +399,7 @@ function RecordEditController($scope, $ionicModal, Wallet, Record, UIUtils, $sta .then(function(walletData) { UIUtils.loading.show(); $scope.walletData = walletData; - Record.auth.token(walletData.keypair) + Market.auth.token(walletData.keypair) .then(function(token) { UIUtils.loading.hide(); console.log('authentication token is:' + token); diff --git a/www/js/controllers/registry-controllers.js b/www/js/controllers/registry-controllers.js new file mode 100644 index 0000000000000000000000000000000000000000..a207be80c65ee0264a2de490fb27a6c9cebf86c1 --- /dev/null +++ b/www/js/controllers/registry-controllers.js @@ -0,0 +1,411 @@ +angular.module('cesium.registry.controllers', ['cesium.services']) + + .config(function($stateProvider, $urlRouterProvider) { + $stateProvider + + .state('app.registry_lookup', { + url: "/registry", + views: { + 'menuContent': { + templateUrl: "templates/registry/lookup.html", + controller: 'RegistryLookupCtrl' + } + } + }) + + .state('app.registry_view_record', { + url: "/registry/:id", + views: { + 'menuContent': { + templateUrl: "templates/registry/view_record.html", + controller: 'RegistryRecordViewCtrl' + } + } + }) + + .state('app.registry_add_record', { + url: "/registry/add", + views: { + 'menuContent': { + templateUrl: "templates/registry/edit_record.html", + controller: 'RegistryRecordEditCtrl' + } + } + }) + + .state('app.registry_edit_record', { + url: "/registry/:id/edit", + views: { + 'menuContent': { + templateUrl: "templates/registry/edit_record.html", + controller: 'RegistryRecordEditCtrl' + } + } + }); + }) + + .controller('RegistryLookupCtrl', RegistryLookupController) + + .controller('RegistryRecordViewCtrl', RegistryRecordViewController) + + .controller('RegistryRecordEditCtrl', RegistryRecordEditController) + +; + +function RegistryCategoryModalController($scope, Registry, $state, $ionicModal) { + + $scope.categoryModal = null; + + // category lookup modal + $ionicModal.fromTemplateUrl('templates/registry/modal_category.html', { + scope: $scope, + focusFirstInput: true + }).then(function(modal) { + $scope.categoryModal = modal; + $scope.categoryModal.hide(); + }); + + $scope.openCategoryModal = function() { + // load categories + Registry.category.all() + .then(function(categories){ + $scope.categories = categories; + $scope.categoryModal.show(); + }); + }; + + $scope.closeCategoryModal = function() { + $scope.categoryModal.hide(); + }; + + $scope.selectCategory = function(cat) { + if (!cat.parent) return; + console.log('Category ' + cat.name + 'selected. Method selectCategory(cat) not overwritten.'); + $scope.closeCategoryModal(); + }; +} + +function RegistryLookupController($scope, Registry, $state, $ionicModal) { + + RegistryCategoryModalController.call(this, $scope, Registry, $state, $ionicModal); + + $scope.search = { + text: '', + results: {}, + category: null, + options: false + }; + + $scope.$watch('search.options', $scope.doSearch, true); + + $scope.isFilter = function(filter) { + return ($scope.filter == filter); + } + + $scope.selectCategory = function(cat) { + if (!cat.parent) return; + $scope.search.category = cat; + $scope.closeCategoryModal(); + $scope.doSearch(); + }; + + $scope.searchChanged = function() { + $scope.search.text = $scope.search.text.toLowerCase(); + if ($scope.search.text.length > 1) { + $scope.doSearch(); + } + else { + $scope.search.results = []; + } + }; + + $scope.doSearch = function(query) { + $scope.search.looking = true; + + var request = { + query: {}, + highlight: { + fields : { + title : {}, + description : {} + } + }, + from: 0, + size: 20, + _source: ["title", "time", "description", "pictures"] + }; + var matches = []; + if ($scope.search.text.length > 1) { + matches.push({match : { title: $scope.search.text}}); + } + if ($scope.search.options && $scope.search.category) { + matches.push({match : { category: $scope.search.category.id}}); + } + if (matches.length > 1) { + request.query.bool = { should: matches }; + } + else { + request.query.match = matches[0].match; + } + + return Registry.record.search(request) + .then(function(res){ + $scope.search.looking = false; + if (res.hits.total == 0) { + $scope.search.results = []; + } + else { + $scope.search.results = res.hits.hits.reduce(function(result, hit) { + var registry = hit._source; + registry.id = hit._id; + registry.type = hit._type; + if (hit.highlight) { + if (hit.highlight.title) { + registry.title = hit.highlight.title[0]; + } + if (hit.highlight.description) { + registry.description = hit.highlight.description[0]; + } + } + return result.concat(registry); + }, []); + } + }) + .catch(function(err) { + $scope.search.looking = false; + $scope.search.results = []; + }); + }; + + $scope.select = function(id) { + $state.go('app.registry_view_record', {id: id}); + }; +} + +function RegistryRecordViewController($scope, $ionicModal, Wallet, Registry, UIUtils, $state, CryptoUtils, $q) { + + $scope.formData = {}; + $scope.id = null; + $scope.isMember = false; + $scope.category = {}; + $scope.pictures = []; + $scope.canEdit = false; + + $scope.$on('$ionicView.enter', function(e, $state) { + if ($state.stateParams && $state.stateParams.id) { // Load by id + $scope.load($state.stateParams.id); + } + else { + $state.go('app.lookup_registry'); + } + }); + + $scope.load = function(id) { + UIUtils.loading.show(); + $q.all([ + Registry.category.all() + .then(function(categories) { + Registry.record.get({id: id}) + .then(function (hit) { + $scope.formData = hit._source; + $scope.category = categories[hit._source.category]; + $scope.id= hit._id; + if (hit._source.pictures) { + $scope.pictures = hit._source.pictures.reduce(function(res, pic) { + return res.concat({src: pic.src}); + }, []); + } + $scope.canEdit = !$scope.isLogged() || ($scope.formData && $scope.formData.issuer == Wallet.getData().pubkey) + UIUtils.loading.hide(); + }) + }) + ]).catch(UIUtils.onError('Could not load registry')); + }; + + $scope.edit = function() { + $state.go('app.registry_edit_record', {id: $scope.id}); + }; +} + +function RegistryRecordEditController($scope, $ionicModal, Wallet, Registry, UIUtils, $state, CryptoUtils, $q, $ionicPopup) { + + RegistryCategoryModalController.call(this, $scope, Registry, $state, $ionicModal); + + $scope.walletData = {}; + $scope.formData = {}; + $scope.id = null; + $scope.isMember = false; + $scope.category = {}; + $scope.pictures = []; + + ionic.Platform.ready(function() { + if (!navigator.camera) { + delete $scope.camera; return; + } + $scope.camera = navigator.camera; + }); + + $scope.$on('$ionicView.enter', function(e, $state) { + $scope.loadWallet() + .then(function(walletData) { + $scope.walletData = walletData; + if ($state.stateParams && $state.stateParams.id) { // Load by id + $scope.load($state.stateParams.id); + } + }); + }); + + $scope.load = function(id) { + UIUtils.loading.show(); + $q.all([ + Registry.category.all() + .then(function(categories) { + Registry.record.get({id: id}) + .then(function (hit) { + $scope.formData = hit._source; + $scope.category = categories[hit._source.category]; + $scope.id= hit._id; + if (hit._source.pictures) { + $scope.pictures = hit._source.pictures.reduce(function(res, pic) { + return res.concat({src: pic.src}); + }, []); + } + UIUtils.loading.hide(); + }); + }) + ]) + .catch(UIUtils.onError('Could not load registry')) + }; + + $scope.save = function() { + UIUtils.loading.show(); + return $q(function(resolve, reject) { + $scope.formData.pictures = $scope.pictures.reduce(function(res, pic) { + return res.concat({src: pic.src}); + }, []); + if (!$scope.id) { // Create + Registry.record.add($scope.formData, $scope.walletData.keypair) + .then(function(id) { + UIUtils.loading.hide(); + $state.go('app.registry_view_record', {id: id}) + resolve(); + }) + .catch(UIUtils.onError('Could not save registry')); + } + else { // Update + Registry.record.update($scope.formData, {id: $scope.id}, $scope.walletData.keypair) + .then(function() { + UIUtils.loading.hide(); + $state.go('app.registry_view_record', {id: $scope.id}) + resolve(); + }) + .catch(UIUtils.onError('Could not update registry')); + } + }); + }; + + $scope.selectCategory = function(cat) { + if (!cat.parent) return; + $scope.category = cat; + $scope.formData.category = cat.id; + $scope.closeCategoryModal(); + }; + + $scope.openPicturePopup = function() { + $ionicPopup.show({ + title: 'Choose picture source :', + buttons: [ + { + text: 'Gallery', + type: 'button', + onTap: function(e) { + return navigator.camera.PictureSourceType.PHOTOLIBRARY; + } + }, + { + text: '<b>Camera</b>', + type: 'button button-positive', + onTap: function(e) { + return navigator.camera.PictureSourceType.CAMERA; + } + } + ] + }) + .then(function(sourceType){ + $scope.getPicture(sourceType); + }); + }; + + $scope.getPicture = function(sourceType) { + var options = { + quality: 50, + destinationType: navigator.camera.DestinationType.DATA_URL, + sourceType: sourceType, + encodingType: navigator.camera.EncodingType.PNG, + targetWidth : 400, + targetHeight : 400 + } + $scope.camera.getPicture( + function (imageData) { + $scope.pictures.push({src: "data:image/png;base64," + imageData}); + $scope.$apply(); + }, + UIUtils.onError('Could not get picture'), + options); + }; + + $scope.fileChanged = function(event) { + UIUtils.loading.show(); + return $q(function(resolve, reject) { + var file = event.target.files[0]; + var reader = new FileReader(); + + reader.addEventListener("load", function () { + //console.log(reader.result); + $scope.pictures.push({src: reader.result}); + $scope.$apply(); + }, false); + + if (file) { + reader.readAsDataURL(file); + } + UIUtils.loading.hide(); + resolve(); + }); + }; + + /* + // See doc : + // http://stackoverflow.com/questions/20958078/resize-base64-image-in-javascript-without-using-canvas + $scope.imageToDataUri function(img, width, height) { + + // create an off-screen canvas + var canvas = document.createElement('canvas'), + ctx = canvas.getContext('2d'); + + // set its dimension to target size + canvas.width = width; + canvas.height = height; + + // draw source image into the off-screen canvas: + ctx.drawImage(img, 0, 0, width, height); + + // encode image to data-uri with base64 version of compressed image + return canvas.toDataURL(); + }*/ + + $scope.auth = function() { + $scope.loadWallet() + .then(function(walletData) { + UIUtils.loading.show(); + $scope.walletData = walletData; + Registry.auth.token(walletData.keypair) + .then(function(token) { + UIUtils.loading.hide(); + console.log('authentication token is:' + token); + }) + .catch(onError('Could not computed authentication token')); + }) + .catch(onError('Could not computed authentication token')); + }; +} \ No newline at end of file diff --git a/www/js/services.js b/www/js/services.js index f899053048f37b6ff980a907b21a3c83102690c3..dd892437dc92e0ea919773f0a6ab50a9d8d31bdc 100644 --- a/www/js/services.js +++ b/www/js/services.js @@ -3,5 +3,7 @@ angular.module('cesium.services', [ 'cesium.crypto.services', 'cesium.utils.services', 'cesium.wallet.services', - 'cesium.record.services']) + 'cesium.market.services', + 'cesium.registry.services' + ]) ; diff --git a/www/js/services/record-services.js b/www/js/services/market-services.js similarity index 87% rename from www/js/services/record-services.js rename to www/js/services/market-services.js index bdab21e393d6ddb73d720448b49d15f9e9a6c2eb..b8efc1f26ac348be84753d9d72e66d044c6e0239 100644 --- a/www/js/services/record-services.js +++ b/www/js/services/market-services.js @@ -1,8 +1,8 @@ -angular.module('cesium.record.services', ['ngResource', 'cesium.services']) +angular.module('cesium.market.services', ['ngResource', 'cesium.services']) -.factory('Record', function($http, $q, CryptoUtils) { +.factory('Market', function($http, $q, CryptoUtils) { - function Record(server, wsServer) { + function Market(server, wsServer) { var categories = []; @@ -95,7 +95,7 @@ angular.module('cesium.record.services', ['ngResource', 'cesium.services']) return; } - getResource('http://' + server + '/store/category/_search?pretty&from=0&size=1000')() + getResource('http://' + server + '/market/category/_search?pretty&from=0&size=1000')() .then(function(res) { if (res.hits.total == 0) { categories = []; @@ -147,7 +147,7 @@ angular.module('cesium.record.services', ['ngResource', 'cesium.services']) }); } - var postRecord = postResource('http://' + server + '/store/record'); + var postRecord = postResource('http://' + server + '/market/record'); function addRecord(record, keypair) { return $q(function(resolve, reject) { @@ -197,23 +197,23 @@ angular.module('cesium.record.services', ['ngResource', 'cesium.services']) hit: { empty: emptyHit }, + category: { + all: getCategories + }, record: { - get: getResource('http://' + server + '/store/record/:id'), + get: getResource('http://' + server + '/market/record/:id'), add: addRecord, - update: postResource('http://' + server + '/store/record/:id'), - searchText: getResource('http://' + server + '/store/record/_search?q=:search'), - search: postResource('http://' + server + '/store/record/_search?pretty'), - category: { - all: getCategories - } + update: postResource('http://' + server + '/market/record/:id'), + searchText: getResource('http://' + server + '/market/record/_search?q=:search'), + search: postResource('http://' + server + '/market/record/_search?pretty') } } } - var service = Record('localhost:9200'); + var service = Market('localhost:9200'); //var service = ES('metab.ucoin.fr:9288'); - service.instance = Record; + service.instance = Market; return service; }) ; diff --git a/www/js/services/registry-services.js b/www/js/services/registry-services.js new file mode 100644 index 0000000000000000000000000000000000000000..9d2b3c786e94590bf9ecc24d131990837cbadf0a --- /dev/null +++ b/www/js/services/registry-services.js @@ -0,0 +1,219 @@ +angular.module('cesium.registry.services', ['ngResource', 'cesium.services']) + +.factory('Registry', function($http, $q, CryptoUtils) { + + function Registry(server, wsServer) { + + var categories = []; + + if (wsServer == "undefined" || wsServer == null) { + wsServer = server; + } + + function processError(reject, data) { + if (data != null && data.message != "undefined" && data.message != null) { + reject(data.ucode + ": " + data.message); + } + else { + reject('Unknown error from ucoin node'); + } + } + + function prepare(uri, params, config, callback) { + var pkeys = [], queryParams = {}, newUri = uri; + if (typeof params == 'object') { + pkeys = _.keys(params); + } + + pkeys.forEach(function(pkey){ + var prevURI = newUri; + newUri = newUri.replace(new RegExp(':' + pkey), params[pkey]); + if (prevURI == newUri) { + queryParams[pkey] = params[pkey]; + } + }); + config.params = queryParams; + callback(newUri, config); + } + + function getResource(uri) { + return function(params) { + return $q(function(resolve, reject) { + var config = { + timeout: 4000 + }; + + prepare(uri, params, config, function(uri, config) { + $http.get(uri, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + processError(reject, data); + }); + }); + }); + } + } + + function postResource(uri) { + return function(data, params) { + return $q(function(resolve, reject) { + var config = { + timeout: 4000, + headers : {'Content-Type' : 'application/json'} + }; + + prepare(uri, params, config, function(uri, config) { + $http.post(uri, data, config) + .success(function(data, status, headers, config) { + resolve(data); + }) + .error(function(data, status, headers, config) { + processError(reject, data); + }); + }); + }); + } + } + + function ws(uri) { + var sock = new WebSocket(uri); + return { + on: function(type, callback) { + sock.onmessage = function(e) { + callback(JSON.parse(e.data)); + }; + } + }; + } + + function getCategories() { + return $q(function(resolve, reject) { + if (categories.length != 0) { + resolve(categories); + return; + } + + getResource('http://' + server + '/registry/category/_search?pretty&from=0&size=1000')() + .then(function(res) { + if (res.hits.total == 0) { + categories = []; + } + else { + categories = res.hits.hits.reduce(function(result, hit) { + var cat = hit._source; + cat.id = hit._id; + return result.concat(cat); + }, []); + // add as map also + categories.forEach(function(cat) { + categories[cat.id] = cat; + }); + } + resolve(categories); + }) + .catch(function(err) { + reject(err); + }); + }); + } + + function getToken(keypair) { + return $q(function(resolve, reject) { + var errorFct = function(err) { + reject(err); + } + var getChallenge = getResource('http://' + server + '/auth'); + var postAuth = postResource('http://' + server + '/auth'); + + getChallenge() // get the challenge phrase to sign + .then(function(challenge) { + CryptoUtils.sign(challenge, keypair) // sign the challenge + .then(function(signature) { + postAuth({ + pubkey: CryptoUtils.util.encode_base58(keypair.signPk), + challenge: challenge, + signature: signature + }) // get token + .then(function(token) { + resolve(token) + }) + .catch(errorFct); + }) + .catch(errorFct); + }) + .catch(errorFct); + }); + } + + var postRecord = postResource('http://' + server + '/registry/record'); + + function addRecord(record, keypair) { + return $q(function(resolve, reject) { + var errorFct = function(err) { + reject(err); + } + var obj = {}; + angular.copy(record, obj); + delete obj.signature; + delete obj.hash; + obj.issuer = CryptoUtils.util.encode_base58(keypair.signPk); + var str = JSON.stringify(obj); + + CryptoUtils.util.hash_sha256(str) + .then(function(hash_array) { + CryptoUtils.sign(str, keypair) + .then(function(signature) { + obj.hash = CryptoUtils.util.encode_base58(hash_array); + obj.signature = signature; + postRecord(obj).then(function (id){ + resolve(id); + }) + .catch(errorFct); + }) + .catch(errorFct); + }) + .catch(errorFct); + }); + } + + function emptyHit() { + return { + _id: null, + _index: null, + _type: null, + _version: null, + _source: {} + } + } + + return { + auth: { + get: getResource('http://' + server + '/auth'), + post: postResource('http://' + server + '/auth'), + token: getToken + }, + hit: { + empty: emptyHit + }, + category: { + all: getCategories + }, + record: { + get: getResource('http://' + server + '/registry/record/:id'), + add: addRecord, + update: postResource('http://' + server + '/registry/record/:id'), + searchText: getResource('http://' + server + '/registry/record/_search?q=:search'), + search: postResource('http://' + server + '/registry/record/_search?pretty') + } + } + } + + var service = Registry('localhost:9200'); + //var service = ES('metab.ucoin.fr:9288'); + + service.instance = Registry; + return service; +}) +; diff --git a/www/templates/home.html b/www/templates/home.html index f16e609cc7706d6bee8666f17b336d379f34157d..c68e6a3b67a63e31bce9bb187620c75a0d0187e7 100644 --- a/www/templates/home.html +++ b/www/templates/home.html @@ -13,10 +13,11 @@ <h1 translate>HOME.WELCOME</h1> <h2 translate>HOME.MESSAGE</h2> - <a ui-sref="app.explore_currency" class="button button-block button-stable icon icon-left ion-search" translate>HOME.EXPLORE_CURRENCIES</a> + <a ui-sref="app.registry_lookup" class="button button-block button-stable icon icon-left ion-person-stalker" translate>HOME.BTN_REGISTRY</a> - <a ui-sref="app.lookup_record" class="button button-block button-stable icon icon-left ion-search" translate>HOME.EXPLORE_MARKET</a> + <a ui-sref="app.market_lookup" class="button button-block button-stable icon icon-left ion-bag" translate>HOME.BTN_MARKET</a> + <a ui-sref="app.explore_currency" class="button button-block button-stable icon icon-left ion-ios-world-outline" translate>HOME.BTN_CURRENCIES</a> <button ng-click="login()" ng-show="!isLogged()" class="button button-block button-positive icon icon-left ion-log-in" translate>COMMON.BTN_LOGIN</button> <!-- <button ng-click="addAccount()" ng-show="!isLogged()" class="button button-block button-assertive icon icon-left ion-ios-color-wand">Add an account</button> --> diff --git a/www/templates/record/edit_record.html b/www/templates/market/edit_record.html similarity index 84% rename from www/templates/record/edit_record.html rename to www/templates/market/edit_record.html index 89363bc4648927aaf9c1e320b0108dce89b0e042..fdf76561f5eeb165d6f91ebf1c9c99462faebcf4 100644 --- a/www/templates/record/edit_record.html +++ b/www/templates/market/edit_record.html @@ -1,4 +1,4 @@ -<ion-view view-title="{{'RECORD.EDIT.TITLE'|translate}}" left-buttons="leftButtons"> +<ion-view view-title="{{'MARKET.EDIT.TITLE'|translate}}" left-buttons="leftButtons"> <ion-nav-buttons side="secondary"> <button class="button button-positive" ng-click="save()"> <i class="icon ion-android-send" ng-if="!id"></i> @@ -14,14 +14,14 @@ ng-if="pictures && pictures.length>0"></ion-gallery> <div class="item item-icon-right" ng-if="camera"> - <span translate>RECORD.EDIT.BTN_ADD_PICTURES</span> + <span translate>MARKET.EDIT.BTN_ADD_PICTURES</span> <a class="dark" href="#" ng-click="openPicturePopup()"> <i class="icon ion-camera"></i> </a> </div> <div class="item item-input item-icon-right" ng-if="!camera" > - <span class="input-label has-input" translate>RECORD.EDIT.BTN_ADD_PICTURES</span> + <span class="input-label has-input" translate>MARKET.EDIT.BTN_ADD_PICTURES</span> <input type="file" id="file" accept=".png,.jpeg,.jpg" onchange="angular.element(this).scope().fileChanged(event)"/> <!--a class="dark" href="#" ng-if="!camera" ng-click="addPictureFile()"> <i class="icon ion-plus"></i> @@ -30,28 +30,28 @@ <span class="item item-icon-left" ng-if="id && formData.issuer"> <i class="icon ion-key"></i> - <span translate>RECORD.COMMON.ISSUER</span> + <span translate>MARKET.COMMON.ISSUER</span> <span class="badge">{{formData.issuer | formatPubkey}}</span> </span> <span class="item item-button-right" ng-click="openCategoryModal()"> - <span translate>RECORD.COMMON.CATEGORY</span> + <span translate>MARKET.COMMON.CATEGORY</span> <span class="badge badge-royal">{{category.name}}</span> <i class="button button-clear ion-chevron-right"></i> </span> <div class="item item-input item-floating-label"> - <span class="input-label" translate>RECORD.EDIT.RECORD_TITLE</span> - <input type="text" placeholder="{{'RECORD.EDIT.RECORD_TITLE_HELP'|translate}}" ng-model="formData.title" /> + <span class="input-label" translate>MARKET.EDIT.RECORD_TITLE</span> + <input type="text" placeholder="{{'MARKET.EDIT.RECORD_TITLE_HELP'|translate}}" ng-model="formData.title" /> </div> <div class="item item-input item-floating-label"> - <span class="input-label" translate>RECORD.EDIT.RECORD_DESCRIPTION</span> - <textarea placeholder="{{'RECORD.EDIT.RECORD_DESCRIPTION_HELP'|translate}}" ng-model="formData.description"></textarea> + <span class="input-label" translate>MARKET.EDIT.RECORD_DESCRIPTION</span> + <textarea placeholder="{{'MARKET.EDIT.RECORD_DESCRIPTION_HELP'|translate}}" ng-model="formData.description"></textarea> </div> <div class="item item-floating-label"> - <span class="input-label" translate>RECORD.EDIT.RECORD_LOCATION</span> + <span class="input-label" translate>MARKET.EDIT.RECORD_LOCATION</span> <div class="item-input-inset"> <label class="item-input-wrapper"> <input type="text" placeholder="Location" ng-model="formData.location"> diff --git a/www/templates/record/lookup.html b/www/templates/market/lookup.html similarity index 83% rename from www/templates/record/lookup.html rename to www/templates/market/lookup.html index 007380d56c1cc81b0ab704f378849224ca5062f4..3164e9e3f3219861ed29c88ca8d880bcbc7357bf 100644 --- a/www/templates/record/lookup.html +++ b/www/templates/market/lookup.html @@ -1,20 +1,19 @@ -<ion-view view-title="{{'RECORD.SEARCH.TITLE'|translate}}" left-buttons="leftButtons"> +<ion-view view-title="{{'MARKET.SEARCH.TITLE'|translate}}" left-buttons="leftButtons"> <ion-nav-buttons side="secondary"> - <button ui-sref="app.add_record" class="button button-positive"> + <button ui-sref="app.market_add_record" class="button button-positive"> <i class="icon ion-plus"></i> - <span translate>RECORD.SEARCH.BTN_ADD</span> + <span translate>MARKET.SEARCH.BTN_ADD</span> </button> </ion-nav-buttons> <ion-content class="lookupForm padding"> <label class="item item-input"> <i class="icon ion-search placeholder-icon"></i> - <input type="text" placeholder="{{'RECORD.SEARCH.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> + <input type="text" placeholder="{{'MARKET.SEARCH.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> </label> - <div class="item item-toggle dark" ng-if="search.text"> - <span translate>RECORD.SEARCH.BTN_OPTIONS</span> + <span translate>MARKET.SEARCH.BTN_OPTIONS</span> <label class="toggle toggle-royal"> <input type="checkbox" ng-model="search.options"> <div class="track"> @@ -24,7 +23,7 @@ </div> <span class="item item-button-right" ng-click="openCategoryModal()" ng-if="search.options"> - <span translate>RECORD.COMMON.CATEGORY</span> + <span translate>MARKET.COMMON.CATEGORY</span> <span class="badge badge-royal">{{search.category.name}}</span> <i class="button button-clear ion-chevron-right"></i> </span> diff --git a/www/templates/record/modal_category.html b/www/templates/market/modal_category.html similarity index 100% rename from www/templates/record/modal_category.html rename to www/templates/market/modal_category.html diff --git a/www/templates/record/view_record.html b/www/templates/market/view_record.html similarity index 87% rename from www/templates/record/view_record.html rename to www/templates/market/view_record.html index 392e27da1451f1204997ba9d7f0846f2f5feb46a..065805d305c93c7cd64aa6b2b1f548e7d335ffb2 100644 --- a/www/templates/record/view_record.html +++ b/www/templates/market/view_record.html @@ -1,4 +1,4 @@ -<ion-view left-buttons="leftButtons" view-title="{{'RECORD.VIEW.TITLE'|translate}}"> +<ion-view left-buttons="leftButtons" view-title="{{'MARKET.VIEW.TITLE'|translate}}"> <ion-nav-buttons side="secondary"> <button class="button button-positive" ng-click="edit()" ng-if="canEdit"> <i class="icon ion-android-create"></i> @@ -24,12 +24,12 @@ <span class="item item-icon-left"> <i class="icon ion-person"></i> - <span translate>RECORD.COMMON.ISSUER</span> + <span translate>MARKET.COMMON.ISSUER</span> <span class="badge" ng-class="{'badge-positive': isMember, 'badge-assertive': !isMember}">{{formData.issuer | formatPubkey}}</span> </span> <div class="item"> - <span translate>RECORD.COMMON.CATEGORY</span> + <span translate>MARKET.COMMON.CATEGORY</span> <span class="badge badge-positive">{{category.name}}</span> </div> diff --git a/www/templates/menu.html b/www/templates/menu.html index 9b3f490f5f147cd398f1b30ac7db9d07f3163d80..870b4bd6d41fdb549c1097dc76c55b2c2c5cd855 100644 --- a/www/templates/menu.html +++ b/www/templates/menu.html @@ -8,22 +8,28 @@ </h1> <button class="button button-assertive" ng-click="logout()" ng-if="isLogged()"> <i class="icon ion-log-out"></i> - {{'COMMON.BTN_LOGOUT'|translate}} + <span translate>COMMON.BTN_LOGOUT</span> </button> </ion-header-bar> <ion-content scroll="false"> <ion-item menu-close href="#/app/home"> - {{'MENU.HOME'|translate}} + <span translate>MENU.HOME</span> </ion-item> - <ion-item menu-close href="#/app/home/explore"> - {{'MENU.CURRENCIES'|translate}} + <ion-item menu-close href="#/app/registry"> + <span translate>MENU.REGISTRY</span> + </ion-item> + <ion-item menu-close href="#/app/market"> + <span translate>MENU.MARKET</span> + </ion-item> + <ion-item menu-close href="#/app/currency"> + <span translate>MENU.CURRENCIES</span> </ion-item> <ion-item menu-close ng-click="login()" ng-if="!isLogged()"> - {{'MENU.ACCOUNT'|translate}} + <span translate>MENU.ACCOUNT</span> </ion-item> <ion-item menu-close href="#" ui-sref="app.view_wallet" ng-if="isLogged()"> - {{'MENU.ACCOUNT'|translate}} + <span translate>MENU.ACCOUNT</span> </ion-item> <!-- <ion-item menu-close ng-click="addAccount()"> Add account diff --git a/www/templates/registry/edit_record.html b/www/templates/registry/edit_record.html new file mode 100644 index 0000000000000000000000000000000000000000..e1e52625303cd27ed87e8f652ef1f1f9fa3ccaf8 --- /dev/null +++ b/www/templates/registry/edit_record.html @@ -0,0 +1,81 @@ +<ion-view view-title="{{'REGISTRY.EDIT.TITLE'|translate}}" left-buttons="leftButtons"> + <ion-nav-buttons side="secondary"> + <button class="button button-positive" ng-click="save()"> + <i class="icon ion-android-send" ng-if="!id"></i> + <i class="icon ion-android-done" ng-if="id"></i> + </button> + </ion-nav-buttons> + + <ion-content> + <div class="scroll"> + <div class="list"> + + <ion-gallery ion-gallery-items="pictures" + ng-if="pictures && pictures.length>0"></ion-gallery> + + <div class="item item-icon-right" ng-if="camera"> + <span translate>REGISTRY.EDIT.BTN_ADD_PICTURES</span> + <a class="dark" href="#" ng-click="openPicturePopup()"> + <i class="icon ion-camera"></i> + </a> + </div> + + <div class="item item-input item-icon-right" ng-if="!camera" > + <span class="input-label has-input" translate>REGISTRY.EDIT.BTN_ADD_PICTURES</span> + <input type="file" id="file" accept=".png,.jpeg,.jpg" onchange="angular.element(this).scope().fileChanged(event)"/> + <!--a class="dark" href="#" ng-if="!camera" ng-click="addPictureFile()"> + <i class="icon ion-plus"></i> + </a--> + </div> + + <span class="item item-icon-left" ng-if="id && formData.issuer"> + <i class="icon ion-key"></i> + <span translate>REGISTRY.COMMON.ISSUER</span> + <span class="badge">{{formData.issuer | formatPubkey}}</span> + </span> + + <span class="item item-button-right" ng-click="openCategoryModal()"> + <span translate>REGISTRY.COMMON.CATEGORY</span> + <span class="badge badge-royal">{{category.name}}</span> + <i class="button button-clear ion-chevron-right"></i> + </span> + + <div class="item item-input item-floating-label"> + <span class="input-label" translate>REGISTRY.EDIT.RECORD_TITLE</span> + <input type="text" placeholder="{{'REGISTRY.EDIT.RECORD_TITLE_HELP'|translate}}" ng-model="formData.title" /> + </div> + + <div class="item item-input item-floating-label"> + <span class="input-label" translate>REGISTRY.EDIT.RECORD_DESCRIPTION</span> + <textarea placeholder="{{'REGISTRY.EDIT.RECORD_DESCRIPTION_HELP'|translate}}" ng-model="formData.description"></textarea> + </div> + + <div class="item item-floating-label"> + <span class="input-label" translate>REGISTRY.EDIT.RECORD_LOCATION</span> + <div class="item-input-inset"> + <label class="item-input-wrapper"> + <input type="text" placeholder="Location" ng-model="formData.location"> + </label> + <button class="button button-small button-positive" ng-click="localize()" ng-if="location.enable"> + <i class="icon ion-pinpoint"></i> + </button> + </div> + </div> + + + <!--<div class="item item-toggle dark"> + Public visibility + <label class="toggle toggle-royal"> + <input type="checkbox" ng-model="formData.public"> + <div class="track"> + <div class="handle"></div> + </div> + </label> + </div>--> + </div> + <div class="scroll-bar scroll-bar-v"></div> + </div> + </ion-content> + + +</ion-view> \ No newline at end of file diff --git a/www/templates/registry/lookup.html b/www/templates/registry/lookup.html new file mode 100644 index 0000000000000000000000000000000000000000..32a6f4db5917c4ba4afd429d22c0471881d26123 --- /dev/null +++ b/www/templates/registry/lookup.html @@ -0,0 +1,51 @@ +<ion-view view-title="{{'REGISTRY.SEARCH.TITLE'|translate}}" left-buttons="leftButtons"> + <ion-nav-buttons side="secondary"> + <button ui-sref="app.registry_add_record" class="button button-positive"> + <i class="icon ion-plus"></i> + <span translate>REGISTRY.SEARCH.BTN_ADD</span> + </button> + </ion-nav-buttons> + + <ion-content class="lookupForm padding"> + <label class="item item-input"> + <i class="icon ion-search placeholder-icon"></i> + <input type="text" placeholder="{{'REGISTRY.SEARCH.SEARCH_HELP'|translate}}" ng-model="search.text" ng-change="searchChanged()"> + </label> + + <div class="item item-toggle dark" ng-if="search.text"> + <span translate>REGISTRY.SEARCH.BTN_OPTIONS</span> + <label class="toggle toggle-royal"> + <input type="checkbox" ng-model="search.options"> + <div class="track"> + <div class="handle"></div> + </div> + </label> + </div> + + <span class="item item-button-right" ng-click="openCategoryModal()" ng-if="search.options"> + <span translate>REGISTRY.COMMON.CATEGORY</span> + <span class="badge badge-royal">{{search.category.name}}</span> + <i class="button button-clear ion-chevron-right"></i> + </span> + + <div class="list list-inset"> + + <label class="item center" ng-if="search.looking"> + <ion-spinner icon="android"></ion-spinner> + </label> + + <a class="item row item-product" ng-repeat="found in search.results" ng-click="select('{{found.id}}')"> + <div class="col col-2"> + <img style="height:70px" ng-src="{{found.pictures[0].src}}" nf-if="found.pictures && found.pictures > 0"> + <span nf-if="!found.pictures || found.pictures == 0"> </span> + </div> + <div class="col col-80 padding"> + <h2 ng-bind-html="found.title"></h2> + <h3 class="light" ng-bind-html="found.description"></h3> + <span class="badge item-note">{{found.time | formatDate}}</span> + </div> + </a> + + </div> + </ion-content> +</ion-view> \ No newline at end of file diff --git a/www/templates/registry/modal_category.html b/www/templates/registry/modal_category.html new file mode 100644 index 0000000000000000000000000000000000000000..a27af8575f731a09577f2f9562560449622ed53e --- /dev/null +++ b/www/templates/registry/modal_category.html @@ -0,0 +1,23 @@ +<ion-modal-view> + <ion-header-bar class="bar-positive"> + <h1 class="title" translate>RECORD.COMMON.CATEGORIES</h1> + <button class="button button-positive" ng-click="closeCategoryModal()" translate>COMMON.BTN_CANCEL</button> + </ion-header-bar> + + <ion-content class="lookupForm"> + <div class="list"> + <label class="item item-input"> + <i class="icon ion-search placeholder-icon"></i> + <input type="text" placeholder="Search" ng-model="search.text" ng-change="searchChanged()"> + </label> + + <label class="item center" ng-if="search.looking"> + <ion-spinner icon="android"></ion-spinner> + </label> + + <a class="item" ng-repeat="found in categories" ng-class="{'item-divider': (found.parent==null)}" href="#" ng-click="selectCategory(found)"> + <h2 ng-bind-html="found.name"></h2> + </a> + </div> +</ion-content> +</ion-modal-view> \ No newline at end of file diff --git a/www/templates/registry/view_record.html b/www/templates/registry/view_record.html new file mode 100644 index 0000000000000000000000000000000000000000..f9bd74d5adfa0f175c33d66bd89e6e70b404aa6a --- /dev/null +++ b/www/templates/registry/view_record.html @@ -0,0 +1,42 @@ +<ion-view left-buttons="leftButtons" view-title="{{'REGISTRY.VIEW.TITLE'|translate}}"> + <ion-nav-buttons side="secondary"> + <button class="button button-positive" ng-click="edit()" ng-if="canEdit"> + <i class="icon ion-android-create"></i> + </button> + </ion-nav-buttons> + + <ion-content class="item-text-wrap"> + + <div class="scroll"> + <div class="list"> + + <ion-gallery ion-gallery-items="pictures" ng-if="pictures && pictures.length>0"></ion-gallery> + + <div class="item"> + <h2 ng-bind-html="formData.title"></h2> + </div> + + <div class="item"> + <p ng-bind-html="formData.description"></p> + </div> + + <div class="item-divider"></div> + + <span class="item item-icon-left"> + <i class="icon ion-person"></i> + <span translate>REGISTRY.COMMON.ISSUER</span> + <span class="badge" ng-class="{'badge-positive': isMember, 'badge-assertive': !isMember}">{{formData.issuer | formatPubkey}}</span> + </span> + + <div class="item"> + <span translate>REGISTRY.COMMON.CATEGORY</span> + <span class="badge badge-positive">{{category.name}}</span> + </div> + + + + </div> + <div class="scroll-bar scroll-bar-v"></div> + </div> + </ion-content> +</ion-view> \ No newline at end of file