zettapi_client
Version:
Client side CRUD operations in angular to use with zettapi_server rest api to get started quickly in any CMS project
1,773 lines (1,528 loc) • 214 kB
JavaScript
var app = angular.module('zapi', [
'ngSanitize',
'ngAnimate',
'ui.bootstrap',
'blockUI',
'inform',
'chart.js',
'btford.socket-io',
'ngCsv',
'ngTable',
'selector',
'angularUtils.directives.dirPagination',
'angularMoment',
'ngIdle',
'pascalprecht.translate'
]).config(function (TitleProvider) {
TitleProvider.enabled(false);
}).provider('zapi', function (apiEntityMap) {
var map = {};
var idle = false;
return {
getRoutes: function (param) {
if (typeof map[param.entity] === 'undefined') return 'client/entity/entity.notfound.html';
if (typeof map[param.entity][param.action] === 'undefined') return 'client/entity/entity.notfound.html';
switch (param.action) {
case 'edit':
return 'client/entity/entity.edit.html';
case 'view':
if (typeof param.id === 'undefined') return 'client/entity/entity.notfound.html';
return 'client/entity/entity.view.html';
case 'list':
if (typeof param.id !== 'undefined') return 'client/entity/entity.notfound.html';
return 'client/entity/entity.list.html';
default:
return 'client/entity/entity.notfound.html';
}
},
setMap: function (entityMap) {
map = apiEntityMap;
for (var key in entityMap) {
map[key] = entityMap[key];
}
},
setIdle: function (state) {
idle = state;
},
$get: function () {
return {
entityMap: map,
idle: idle
};
}
};
});
app.controller('entityCtrl', function ($entity, zapi, ErrorSvc, $page, mySocket, $window, $routeParams, $controller, $location, $scope, $uibModal, blockUI, inform, $route, NgTableParams, $translate) {
//set scope variables
$scope.table = { params: null };
$scope.console = null;
$scope.entities = zapi.entityMap;
$scope.entityName = $routeParams.entity;
$scope.lookup = {};
$scope.items = [];
$scope.item = {};
$scope.newFile = {};
//set scope functions
$scope.add = function (item, beforeAdd, callback) {
$translate('api.entity.sendData').then(function(text){
blockUI.start(text);
});
var next = typeof beforeAdd === 'function' ? beforeAdd : skip;
next(function (err) {
if (err) return inform.add(err, { ttl: 2000, type: 'danger' });
$entity.add($routeParams.entity, item).then(function (response) {
$translate([$scope.entity.title,'api.entity.newRecordSuccess','api.entity.editRecordSuccess']).then(function (translations) {
if (item._id) inform.add(translations[$scope.entity.title] + translations['api.entity.newRecordSuccess'], { ttl: 2000, type: 'info' });
else inform.add(translations[$scope.entity.title] + translations['api.entity.editRecordSuccess'], { ttl: 2000, type: 'info' });
});
if (typeof callback === 'function') callback();
}).catch(function (response) {
inform.add(response.data, { ttl: 2000, type: 'danger' });
if (typeof callback === 'function') callback(response.data);
}).finally(function () {
blockUI.stop();
});
});
};
$scope.remove = function (item) {
$translate('api.entity.checkRemove').then(function(text){
blockUI.start(text);
});
$entity.remove($routeParams.entity, item).then(function (response) {
$translate([$scope.entity.title,'api.entity.deleteRecordSuccess']).then(function (translations) {
inform.add(translations[$scope.entity.title] + translations['api.entity.deleteRecordSuccess'], { ttl: 2000, type: 'info' });
});
}).catch(function (response) {
inform.add(response.error ? response.error : response.data, { ttl: 2000, type: 'danger' });
}).finally(function () {
blockUI.stop();
});
};
$scope.openEdit = function (item) {
if (!$scope.entity.modal) {
var url = $location.path();
url = url.substring(0, url.lastIndexOf('/')) + '/edit';
if (item) {
return $location.path(url + '/' + item._id);
} else {
return $location.path(url);
}
}
setEdit(item);
var modalInstance = $uibModal.open({
animation: true,
templateUrl: 'client/entity/entity.modal.html',
controller: 'entityModalCtrl',
size: 'lg',
backdrop: 'static',
scope: $scope
});
modalInstance.result.then(function (newItem) {
//item added
}, function () {
$translate('api.entity.cancelRecord').then(function (text) {
inform.add(text, { ttl: 2000, type: 'info' });
});
$scope.item = {};
});
};
$scope.validate = function () {
if (typeof $scope.getError === 'function') {
var response = $scope.getError($scope.item, $scope.items);
if (response.disabled) {
$scope.console = response.tooltip;
return true;
}
}
$scope.console = null;
return false;
};
$scope.unflattenArray = $entity.unflattenArray;
$scope.flattenArray = $entity.flattenArray;
$scope.applySearch = function (search) {
var criteria = angular.copy(search.text);
if (search.inverted) {
criteria = "!" + criteria;
}
$scope.table.params.filter({ $: criteria });
};
//set private methods
function get(entity, id, callback) {
$translate('api.entity.getData').then(function(text){
blockUI.start(text);
});
getLookups($scope.lookup, function (err, lookups) {
if (err) {
$translate('api.entity.errorData').then(function (text) {
inform.add(text, { ttl: 2000, type: 'danger' });
});
blockUI.stop();
return callback(err);
}
$scope.lookup = lookups;
//if user is creating a new record
if (!$routeParams.id && $routeParams.action === 'edit') {
blockUI.stop();
return callback();
}
$entity.get(entity, id).then(function (response) {
if (id) {
$scope.item = response.data;
} else {
$scope.items = response.data;
$scope.table.params = new NgTableParams({}, { dataset: $scope.items });
}
}).catch(function (response) {
$translate('api.entity.errorData').then(function (text) {
inform.add(text, { ttl: 2000, type: 'danger' });
});
}).finally(function () {
blockUI.stop();
callback();
});
});
}
function getLookups(lookup, callback) {
if (lookup) {
if (lookup.length) return callback(null, lookup);
}
$entity.getLookups($routeParams.entity, function (err, data) {
if (err) return callback(err);
callback(null, data);
});
}
function setEdit(item) {
if (item) {
$scope.item = angular.copy(item);
} else {
$scope.item = typeof $scope.blank === 'function' ? $scope.blank() : {};
}
}
function loadFinished() {
//inject child controller
try {
$controller($routeParams.entity + 'Ctrl', { $scope: $scope });
} catch (err) {
console.log(err);
}
var websocket;
if (typeof zapi.entityMap[$routeParams.entity].websocket === 'undefined') {
websocket = $routeParams.entity;
} else {
websocket = eval(zapi.entityMap[$routeParams.entity].websocket) + "." + $routeParams.entity;
}
mySocket.on(websocket + '.remove', onThisEntityRemove);
mySocket.on(websocket + '.new', onThisEntityAdd);
mySocket.on(websocket + '.edit', onThisEntityEdit);
}
function onThisEntityAdd(data) {
switch ($routeParams.action) {
case 'list':
$scope.items.unshift(data);
$scope.table.params.reload();
break;
}
//todo update lookup
}
function onThisEntityEdit(data) {
switch ($routeParams.action) {
case 'list':
for (var i = 0; i < $scope.items.length; i++) {
if ($scope.items[i]._id === data._id) {
$scope.items[i] = data;
$scope.table.params.reload();
break;
}
}
break;
case 'view':
case 'edit':
if ($scope.item._id === data._id) {
$scope.item = data;
$scope.table.params.reload();
}
break;
}
//todo update lookup
}
function onThisEntityRemove(data) {
switch ($routeParams.action) {
case 'list':
for (var i = 0; i < $scope.items.length; i++) {
if ($scope.items[i]._id === data) {
$scope.items.splice(i, 1);
$scope.table.params.reload();
break;
}
}
break;
case 'view':
case 'edit':
if ($scope.item._id === data._id) {
$location.path('/' + $routeParams.entity + '/list');
}
break;
}
//todo update lookup
}
//initialization
function initialize(callback) {
$translate('api.entity.whereyougo').then(function (text) {
$page.setTitle(text);
});
$scope.entity = zapi.entityMap[$routeParams.entity];
if (!$scope.entity) {
return;
}
switch ($routeParams.action) {
case 'edit':
if (!$routeParams.id) {
$translate([$scope.entity.title, 'api.entity.newRecord']).then(function (translations) {
$page.setTitle(translations[$scope.entity.title] + "-" + translations['api.entity.newRecord']);
});
get($routeParams.entity, null, callback);
} else {
$translate([$scope.entity.title, 'api.entity.editRecord']).then(function (translations) {
$page.setTitle(translations[$scope.entity.title] + "-" + translations['api.entity.editRecord']);
});
get($routeParams.entity, $routeParams.id, callback);
}
break;
case 'view':
if (!$routeParams.id) {
return;
}
$translate([$scope.entity.title, 'api.entity.viewRecord']).then(function (translations) {
$page.setTitle(translations[$scope.entity.title] + "-" + translations['api.entity.viewRecord']);
});
get($routeParams.entity, $routeParams.id, callback);
break;
case 'list':
if ($routeParams.id) {
return;
}
$translate($scope.entity.title).then(function (title) {
$page.setTitle(title);
});
get($routeParams.entity, null, callback);
break;
default:
return;
}
}
function skip(callback) {
callback();
}
initialize(loadFinished);
});
app.controller('entityModalCtrl', function ($uibModalInstance, $scope) {
$scope.ok = function () {
$scope.add($scope.item, $scope.onBeforeSave, function (err) {
if (!err) $scope.$close($scope.item);
});
};
$scope.cancel = function () {
$scope.$dismiss('cancel');
};
});
app.controller('activityCtrl', function($scope) {
});
app.controller('alertCtrl', function() {
});
app.controller('countryCtrl', function ($scope) {
});
app.controller('errorCtrl', function($scope, $modal) {
$scope.openModal = $modal._open;
});
app.controller('holidayCtrl', function (ErrorSvc, $scope, $holiday) {
$scope.getError = function (holiday, holidays) {
$scope.nextOccurrence = null;
if (!holiday) {
return ErrorSvc.validationArgs(true);
}
if (!holiday.name) {
return ErrorSvc.validationArgs(true, "Introduza um nome do feriado");
}
if (holiday.name.trim() === "") {
return ErrorSvc.validationArgs(true, "Introduza um nome do feriado");
}
for (var i = 0; i < holidays.length; i++) {
if (holidays[i].name == holiday.name && holiday._id != holidays[i]._id) {
return ErrorSvc.validationArgs(true, "Feriado já existente");
}
}
if (!holiday.date && !holiday.formula) {
return ErrorSvc.validationArgs(true, "Impossivel calcular próxima ocorrência para este feriado");
}
if (holiday.date) {
var pattern = /^(?:(?:[12][0-9]|0[1-9])\/(02)|(?:30|[12][0-9]|0[1-9])\/(?:(?:0[469]|11))|(?:3[01]|[12][0-9]|0[1-9])\/(?:(?:0[13578]|1[02])))$/;
if (!pattern.test(holiday.date)) {
return ErrorSvc.validationArgs(true, "A data deve ser no formato dd/mm");
}
}
else if (holiday.formula) {
try {
var currentYear = new Date().getFullYear();
eval('my_function = ' + holiday.formula);
var d = my_function(currentYear);
if (Object.prototype.toString.call(d) === "[object Date]") {
//it is a date
if (isNaN(d.getTime())) {
return ErrorSvc.validationArgs(true, "Data inválida");
}
}
else {
return ErrorSvc.validationArgs(true, "Data inválida");
}
}
catch (err) {
return ErrorSvc.validationArgs(true, "A formula que introduziu contém um erro: " + err);
}
}
return ErrorSvc.validationArgs(false);
};
$scope.items.forEach(function (item) {
item.next = $holiday.calculateNextOccurrence(item);
});
});
app.controller('maintenanceCtrl', function () {
});
app.controller('messageCtrl', function ($scope, $modal) {
$scope.openModal = $modal._open;
});
app.controller('roleCtrl', function (ErrorSvc, $scope, $role) {
$scope.permissions = {};
$role.getPermissions().then(function (response) {
$scope.permissions = response.data;
});
$scope.togglePermissions = function (value) {
if (!$scope.item.permissions) {
$scope.item.permissions = {};
}
for (var entity in $scope.permissions) {
if (!$scope.item.permissions[entity]) {
$scope.item.permissions[entity] = {};
}
for (var action in $scope.permissions[entity]) {
if (action === 'label') {
continue;
}
$scope.item.permissions[entity][action] = value;
}
}
};
$scope.getError = function (role, roles) {
if (!role) {
return ErrorSvc.validationArgs(true);
}
if (!role.name) {
return ErrorSvc.validationArgs(true, "Introduza um nome para o perfil de utilizador");
}
if (role.name.trim() === "") {
return ErrorSvc.validationArgs(true, "Introduza um nome para o perfil de utilizador");
}
for (var i = 0; i < roles.length; i++) {
if (roles[i].name == role.name && roles[i]._id != role._id) {
return ErrorSvc.validationArgs(true, "Perfil de utilizador já existente");
}
}
return ErrorSvc.validationArgs(false);
};
$scope.blank = function () {
var permissions = {};
for (var entity in $scope.permissions) {
permissions[entity] = {};
for (var action in $scope.permissions[entity]) {
if (action === 'label') {
continue;
}
permissions[entity][action] = true;
}
}
return {
name: "",
approvalLevel: 0,
admin: false,
permissions: permissions
};
};
});
//manage tasks Controller
app.controller('taskCtrl', function ($scope, $date, ErrorSvc, $task, mySocket, blockUI) {
$scope.taskTypes = [];
$scope.getError = function (task, tasks) {
if (!task) {
return ErrorSvc.validationArgs(true);
}
if (!task.name) {
return ErrorSvc.validationArgs(true, "Indique um nome para a tarefa");
}
if (task.name.trim() === "") {
return ErrorSvc.validationArgs(true, "Indique um nome para a tarefa");
}
if (!task.type) {
return ErrorSvc.validationArgs(true, "Escolha um tipo de tarefa");
}
if (!task.criteria) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
if (!task.criteria.month) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
if (!task.criteria.monthday) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
if (!task.criteria.weekday) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
if (!task.criteria.hour) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
if (!task.criteria.minute) {
return ErrorSvc.validationArgs(true, "Complete o critério de periodicidade");
}
return ErrorSvc.validationArgs(false);
};
$scope.formatDatetime = $date.formatDatetime;
$scope.calculateTimespan = $date.calculateTimespan;
$scope.toggleState = $task.toggleState;
$scope.run = function (task) {
$task.run(task)
.then(function (response) {
blockUI.start('A executar...');
})
.catch(function (response) {
swal('Ocorreu um erro ao iniciar a tarefa manualmente.', response.data, 'error');
});
};
mySocket.on($scope.login._id, function(data) {
swal('Tarefa executada com sucesso.', null, 'success');
blockUI.stop();
});
$task.getTypes(function (types) {
$scope.taskTypes = types;
});
});
app.controller('userCtrl', function($scope, $http, inform, ErrorSvc) {
$scope.getError = function(user, users) {
if (!user) {
return ErrorSvc.validationArgs(true);
}
if (!user.username) {
return ErrorSvc.validationArgs(true, "Introduza um username");
}
if (user.username.trim() === "") {
return ErrorSvc.validationArgs(true, "Introduza um username");
}
if (!user.email) {
return ErrorSvc.validationArgs(true, "Introduza um email");
}
if (user.email.trim() === "") {
return ErrorSvc.validationArgs(true, "Introduza um email");
}
for (var i = 0; i < users.length; i++) {
if (users[i].username == user.username && users[i]._id != user._id) {
return ErrorSvc.validationArgs(true, "Utilizador já existente");
}
}
return ErrorSvc.validationArgs(false);
};
});
app.controller('stackTraceCtrl', function($scope, $uibModalInstance, data) {
$scope.item = data;
$scope.cancel = function () {
$uibModalInstance.dismiss({ type: $scope.type });
};
$scope.ok = function() {
$uibModalInstance.close({ type: $scope.type });
};
});
app.controller('viewMsgCtrl', function($scope, $uibModalInstance, data) {
$scope.item = data;
$scope.cancel = function () {
$uibModalInstance.dismiss({ type: $scope.type });
};
$scope.ok = function() {
$uibModalInstance.close({ type: $scope.type });
};
});
app.controller('attachmentsCtrl', function() {
});
app.controller('ccCtrl', function() {
});
app.controller('emailCtrl', function() {
});
app.controller('fromCtrl', function() {
});
app.controller('toCtrl', function() {
});
app.filter("dateFilter", function(moment) {
return function(items, from, to) {
if (!from || !to) {
return items;
}
from = moment(from);
to = moment(to);
var result = [];
for (var i = 0; i < items.length; i++) {
var date = moment(items[i].data_pagamento);
if (date >= from && date <= to) {
result.push(items[i]);
}
}
return result;
};
});
app.filter('orderObjectBy', function () {
return function (items, field, reverse) {
var filtered = [];
angular.forEach(items, function (item) {
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if (reverse) filtered.reverse();
return filtered;
};
});
app.directive('zlActivation', function (zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/activation/activation.html',
controller: function ($scope, $auth, $location, $routeParams) {
$scope.user = null;
$auth.activateAccount($routeParams.code, function (err, user) {
if (err) {
return $location.path('/');
}
$scope.user = user;
});
$scope.changePassword = function (newPassword1, newPassword2) {
$auth.changePassword($scope.user, newPassword1, newPassword2, function (err) {
if (!err) {
return $location.path('/');
}
});
};
}
};
});
app.directive('zlAddress', function (zapiPath) {
return {
restrict: 'E',
scope: {
item: '=',
countries: '='
},
replace: false,
templateUrl: zapiPath + '/directives/address/address.html',
controller: function ($scope, $address, inform) {
$scope.getAddressPT = function(zipcode) {
$address.getAddressPT(zipcode, function (err, data) {
if (err) {
$scope.item.address = "";
$scope.item.city = "";
$scope.item.country = "";
$scope.item.district = "";
$scope.item.county = "";
$scope.item.locality = "";
return inform.add("Não foi possível completar o arruamento", { ttl: 2000, type: "warning" });
}
$scope.item.address = data.address;
$scope.item.city = data.city;
$scope.item.country = data.country;
$scope.item.district = data.district;
$scope.item.county = data.county;
$scope.item.locality = data.locality;
$address.getCoordinates(zipcode, function (err, coords) {
if (!err) {
$scope.item.coords = coords;
}
});
});
};
$scope.validateZipcode = $address.validateZipcode;
}
};
});
app.directive('apiMenuItem', function (zapiPath) {
return {
restrict: 'E',
scope: false,
replace: true,
templateUrl: zapiPath + '/directives/apiMenuItem/apiMenuItem.html',
};
});
app.directive('console', function(zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/console/console.html'
};
});
app.directive('zlContainer', function(zapiPath) {
return {
restrict: 'E',
replace: false,
templateUrl: zapiPath + '/directives/container/container.html',
scope: {
entity: '@',
item: '=',
lookup: '=',
label: '@',
var: '@',
key: '@',
isVisible: '&?',
isMovable: '@',
noInsert: '@',
removable: '@',
approvalMaxLevel: '@'
},
controller: function($scope, $rootScope, $controller, $timeout) {
if ($scope.key) {
$scope.newContainerItem = {};
}
else {
$scope.newContainerItem = "";
}
$scope.append = function(newContainerItem) {
append(newContainerItem, function(err) {
if (err) {
return swal("Atenção", err, "warning");
}
//clear new container item fields
if ($scope.key) {
$scope.newContainerItem = {};
}
else {
$scope.newContainerItem = "";
}
});
};
$scope.remove = function(containerItem) {
var index = $scope.item[$scope.var].indexOf(containerItem);
if (index != -1) {
$scope.item[$scope.var].splice(index, 1);
}
};
$scope.validate = function(newContainerItem) {
if (!newContainerItem) {
return true;
}
if ($scope.key) {
if (Object.keys(newContainerItem).length === 0 && JSON.stringify(newContainerItem) === JSON.stringify({})) {
return true;
}
}
if (typeof $scope.getError === 'function') {
var response = $scope.getError(newContainerItem, $scope.item[$scope.var]);
if (response.disabled) {
$scope.console = response.tooltip;
return true;
}
}
$scope.console = null;
return false;
};
$scope.pushBack = function(index) {
var _containerItem = $scope.item[$scope.var].splice(index, 1);
$scope.item[$scope.var].splice(index - 1, 0, _containerItem[0]);
};
$scope.pushForward = function(index) {
var _containerItem = $scope.item[$scope.var].splice(index, 1);
$scope.item[$scope.var].splice(index + 1, 0, _containerItem[0]);
};
//$timeout is only ready after directive has fully loaded
//this way when the controller loads, $scope will be fully populated
$timeout(function() {
//inject child controller
$controller($scope.var + 'Ctrl', {$scope: $scope});
});
function append(newContainerItem, callback) {
var i, property;
if (!$scope.item[$scope.var]) {
$scope.item[$scope.var] = [];
}
//check if containerItem is not empty
if ($scope.key) {
var key = {
property: null,
key: null
};
if (newContainerItem[$scope.key]) {
key.key = newContainerItem[$scope.key];
}
else {
for (property in newContainerItem) {
if (newContainerItem[property][$scope.key]) {
key.property = property;
key.key = newContainerItem[property][$scope.key];
break;
}
}
}
if (key.key) {
//check if containerItem already exists in container
for (i = 0; i < $scope.item[$scope.var].length; i++) {
var obj = key.property ? $scope.item[$scope.var][i][key.property] : $scope.item[$scope.var][i];
if (obj[$scope.key] === key.key) {
return callback('Registo duplicado em ' + $scope.label);
}
}
}
}
else {
for (i = 0; i < $scope.item[$scope.var].length; i++) {
if ($scope.item[$scope.var][i] === newContainerItem) {
return callback('Registo duplicado em ' + $scope.label);
}
}
}
//append item to container
$scope.item[$scope.var].unshift(newContainerItem);
//approvable containers only
if ($scope.approvalMaxLevel) {
//assign approval
if ($scope.approvalMaxLevel) {
newContainerItem.approval = {
level: $rootScope.login.role.approvalLevel,
maxLevel: $scope.approvalMaxLevel
};
}
}
callback();
}
}
};
});
app.directive("contenteditable", function() {
return {
require: "ngModel",
link: function(scope, element, attrs, ngModel) {
function read() {
ngModel.$setViewValue(element.html());
}
ngModel.$render = function() {
element.html(ngModel.$viewValue || "");
};
element.bind("blur keyup change", function() {
scope.$apply(read);
});
}
};
});
app.directive('zlCountry', function(zapiPath) {
return {
restrict: 'E',
scope: {
item: '=',
'var': '@',
label: '@',
lookup: '='
},
replace: false,
templateUrl: zapiPath + '/directives/country/country.html'
};
});
app.directive('zlFile', function(zapiPath) {
return {
restrict: 'A',
scope: {
item: '=',
var: '=',
docid: '='
},
replace: false,
link: function (scope, element, attrs) {
if (scope.docid) {
if (scope.docid._id) {
scope.docid = scope.docid._id;
}
}
},
templateUrl: zapiPath + '/directives/document/file.html'
};
});
app.directive('fileModel', function ($parse) {
return {
restrict: 'A',
replace: false,
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function() {
scope.$apply(function() {
modelSetter(scope, element[0].files[0]);
});
});
}
};
});
app.directive('zlDynamicField', function (zapiPath) {
return {
restrict: 'E',
scope: {
field: '=',
value: '='
},
replace: false,
template: '<div ng-include src="contentUrl" include-replace></div>',
controller: function ($scope) {
$scope.$watch('field.type', onFieldChange);
function onFieldChange(newField) {
if (!newField) return;
var type = $scope.field.type || 'Unknown';
if ($scope.field.type === 'ObjectId' && typeof $scope.field.ref === 'undefined') {
type = "String";
}
$scope.contentUrl = zapiPath + "/directives/dynamicField/" + type + ".html";
}
}
};
});
app.directive('entityEdit', function(zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
link: function(scope, element, attrs) {
var scaffoldUrl = scope.entity.custom ? 'client/entity/' : (zapiPath + '/entity/');
scope.contentUrl = scaffoldUrl + scope.entityName + '/' + scope.entityName + '.edit.html';
},
template: '<div ng-include="contentUrl"></div>'
};
});
app.directive('entityList', function(zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
link: function(scope, element, attrs) {
var scaffoldUrl = scope.entity.custom ? 'client/entity/' : (zapiPath + '/entity/');
scope.contentUrl = scaffoldUrl + scope.entityName + '/' + scope.entityName + '.list.html';
},
template: '<div ng-include src="contentUrl" include-replace></div>'
};
});
app.directive('entityView', function(zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
link: function(scope, element, attrs) {
var scaffoldUrl = scope.entity.custom ? 'client/entity/' : (zapiPath + 'entity/');
scope.contentUrl = scaffoldUrl + scope.entityName + '/' + scope.entityName + '.view.html';
},
template: '<div ng-include="contentUrl"></div>'
};
});
app.directive('zlGraph', function (zapiPath) {
return {
restrict: 'E',
scope: {
item: '=',
custom: '@?'
},
replace: false,
templateUrl: zapiPath + '/directives/graph/graph.html',
controller: function ($scope, blockUI, $graph) {
var chartTypes = [
['bar', 'doughnut', 'pie', 'horizontalBar'],
['line', 'radar'],
['bubble', 'polar-area']
];
$scope.getNext = function () {
var index = chartTypes[$scope.item.dimension].indexOf($scope.item.type) + 1;
return chartTypes[$scope.item.dimension][index === chartTypes[$scope.item.dimension].length ? 0 : index];
};
$scope.toggle = function () {
$scope.item.type = $scope.getNext();
};
$scope.chart = {};
var graphBlockUI = blockUI.instances.get('graphBlockUI');
graphBlockUI.start("A criar gráfico...");
if (typeof $scope.custom === 'string') {
var parts = $scope.custom.split('|');
$graph.custom(parts[0], parts[1], finished);
}
else {
$graph.get(
$scope.item.namespace,
$scope.item.collection,
$scope.item.query,
$scope.item.obj,
$scope.item.seriesKey,
$scope.item.dataKey,
$scope.item.labelsKey,
finished
);
}
function finished(chart) {
$scope.chart = chart;
graphBlockUI.stop();
}
}
};
});
app.directive('zlIdle', function () {
return {
restrict: 'A',
scope: true,
controller: function ($scope, $location, $auth) {
$scope.$on('IdleStart', function () {
swal("Atenção", "Devido à sua inactividade irá ser disconectado em 5 segundos", "info");
});
$scope.$on('IdleEnd', function () {
console.log('IdleEnd');
});
$scope.$on('IdleTimeout', function () {
$auth.logout();
$location.path('/');
});
}
};
});
app.directive('zlList', function (zapiPath) {
return {
restrict: 'E',
scope: {
dbs: '=',
channel: '@'
},
replace: false,
templateUrl: zapiPath + '/directives/list/list.html',
controller: function ($scope, $list, NgTableParams, $httpParamSerializer) {
$scope.items = [];
$scope.tableParams = null;
$scope.list = { name: "", parameters: [], values: {} };
$scope.selectedDbs = [];
$list.getMetadata(function (lists) {
$scope.lists = lists;
});
$scope.reset = function () {
$scope.items = [];
$scope.tableParams = null;
};
$scope.get = function (list) {
$list.get(list, $scope.selectedDbs, $scope.channel, function (items) {
var initialParams = {}, params = { dataset: items };
if (list.group) {
initialParams.group = list.group;
}
if (typeof list.groupOptions !== 'undefined') {
params.groupOptions = list.groupOptions;
}
$scope.items = items;
$scope.tableParams = new NgTableParams(initialParams, params);
});
};
$scope.getExcelUrl = function (list) {
return '/api/list/values/' + list.name + '?xls=1&' + $httpParamSerializer({ query: list.values, dbs: $scope.selectedDbs });
};
$scope.applySearch = function (search) {
var criteria = angular.copy(search.text);
if (search.inverted) {
criteria = "!" + criteria;
}
$scope.tableParams.filter({ $: criteria });
};
}
};
});
app.directive('zlLogin', function (zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/login/login.html',
controller: function (blockUI, $auth, $location, $scope, $uibModalStack) {
$scope.login = function () {
if ($scope.validateLogin()) {
return;
}
$auth.login($scope.username, $scope.password, function (err) {
if (err) {
reset();
}
else {
$location.path('/profile');
$uibModalStack.dismissAll();
}
});
};
$scope.validateLogin = function () {
if (!$scope.username) {
return true;
}
if (!$scope.password) {
return true;
}
return false;
};
function reset() {
$scope.username = "";
$scope.password = "";
}
}
};
});
app.directive('zlMaintenance', function () {
return {
restrict: 'A',
scope: true,
controller: function (mySocket, $timeout) {
mySocket.on('maintenance', function (data) {
swal("Manutenção Programada", data, "info");
});
}
};
});
app.directive('zlNewsletter', function (zapiPath, blockUI, inform, $entity) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/newsletter/newsletter.html',
controller: function ($scope, $newsletter) {
$scope.saveEmail = function (item) {
$newsletter.subscribe(item, function () {
$scope.newsItem = {};
});
};
}
};
});
app.directive('asDate', function () {
return {
require: '^ngModel',
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
ctrl.$formatters.splice(0, ctrl.$formatters.length);
ctrl.$parsers.splice(0, ctrl.$parsers.length);
ctrl.$formatters.push(function (modelValue) {
if (!modelValue) {
return;
}
return new Date(modelValue).toISOString().slice(0,10);
});
ctrl.$parsers.push(function (modelValue) {
return modelValue;
});
}
};
});
app.directive('dlKeyCode', dlKeyCode);
function dlKeyCode() {
return {
restrict: 'A',
link: function($scope, $element, $attrs) {
$element.bind("keypress", function(event) {
var keyCode = event.which || event.keyCode;
if (keyCode == $attrs.code) {
$scope.$apply(function() {
$scope.$eval($attrs.dlKeyCode, {$event: event});
});
}
});
}
};
}
app.directive('asFloat', function () {
return {
require: '^ngModel',
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
ctrl.$formatters.splice(0, ctrl.$formatters.length);
ctrl.$parsers.splice(0, ctrl.$parsers.length);
ctrl.$formatters.push(function (modelValue) {
if (!modelValue) {
return;
}
return parseFloat(modelValue);
});
ctrl.$parsers.push(function (modelValue) {
return modelValue;
});
}
};
});
app.directive('asInteger', function () {
return {
require: '^ngModel',
restrict: 'A',
link: function (scope, element, attrs, ctrl) {
ctrl.$formatters.splice(0, ctrl.$formatters.length);
ctrl.$parsers.splice(0, ctrl.$parsers.length);
ctrl.$formatters.push(function (modelValue) {
if (!modelValue) {
return;
}
return parseInt(modelValue);
});
ctrl.$parsers.push(function (modelValue) {
return modelValue;
});
}
};
});
app.directive('lettersOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function onlyLetters(text) {
if (text) {
var transformedInput = text.replace(/[^A-Za-z]/g, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
if (attr.lettersOnly === 'true') {
ngModelCtrl.$parsers.push(onlyLetters);
}
}
};
});
app.directive('numbersOnly', function () {
return {
require: 'ngModel',
link: function (scope, element, attr, ngModelCtrl) {
function onlyNumbers(text) {
if (text) {
var transformedInput = text.replace(/[^0-9]/g, '');
if (transformedInput !== text) {
ngModelCtrl.$setViewValue(transformedInput);
ngModelCtrl.$render();
}
return transformedInput;
}
return undefined;
}
if (attr.numbersOnly === 'true') {
ngModelCtrl.$parsers.push(onlyNumbers);
}
}
};
});
app.directive('zlQueryBuilder', function (zapiPath) {
return {
restrict: 'E',
scope: {
field: '=',
value: '='
},
replace: false,
template: '<div ng-include src="contentUrl" include-replace></div>',
controller: function ($scope) {
$scope.$watch('field.type', onFieldChange);
function onFieldChange(newField) {
if (!newField) return;
var type = $scope.field.type || 'Unknown';
if ($scope.field.type === 'ObjectId' && typeof $scope.field.ref === 'undefined') {
type = "String";
}
$scope.contentUrl = zapiPath + "/directives/queryBuilder/" + type + ".html";
}
}
};
});
app.directive('zlReport', function (zapiPath) {
return {
restrict: 'E',
scope: {
field: '=',
condition: '='
},
replace: false,
templateUrl: zapiPath + '/directives/report/report.html',
controller: function ($scope, $report) {
$scope.metadata = {};
$scope.item = {
type: 'exp',
database: '',
collection: '',
query: [],
select: {},
limit: 0,
sort: {},
populate: ''
};
$scope.map = {
"id_animal": "Número SIA",
"id_eletronico": "Brinco Electrónico",
"sexo": "Sexo",
"raca": "Raça",
"data_nascimento": "Dt. Nascimento",
"mae": "Mãe",
"pai": "Pai",
"tipo": "Aptidão",
"fenotipo": "Fenotipo"
};
$report.getMetadata(function (err, metadata) {
$scope.metadata = metadata;
});
$scope.appendQuery = function (fieldName, field) {
$scope.item.query.push({
field: field,
fieldName: fieldName
});
};
}
};
});
app.directive('zlReset', function (zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/reset/reset.html',
controller: function ($scope, $auth, $location, blockUI) {
$scope.reset = function (item) {
if ($scope.validateReset(item)) {
return;
}
$auth.resetPassword(item.email, item.username, function (err) {
if (!err) {
return $location.path("/");
}
});
};
$scope.validateReset = function (item) {
if (!item) {
return true;
}
if (!item.email) {
return true;
}
if (!item.username) {
return true;
}
return false;
};
}
};
});
app.directive('zlSignup', function (zapiPath) {
return {
restrict: 'E',
scope: true,
replace: false,
templateUrl: zapiPath + '/directives/signup/signup.html',
controller: function ($scope, blockUI, $entity, $uibModalStack) {
$scope.signup = function (item) {
if ($scope.validateSignup(item)) {
return;
}
blockUI.start("A reservar conta...");
$entity.add('user', item)
.then(function (response) {
swal("Está quase!", "Consulte o seu email para ativar a conta de utilizador", "success");
$uibModalStack.dismissAll();
})
.catch(function (response) {
swal("Erro", response.data, "error");
})
.finally(function () {
blockUI.stop();
});
};
$scope.validateSignup = function (item) {
if (!item) {
return true;
}
if (!item.username) {
return true;
}
var validUsername = new RegExp('^[a-zA-Z0-9.\-_$@*!]{3,30}$');
if (!validUsername.test(item.username)) {
return true;
}
if (!item.email) {
return true;
}
return false;
};
}
};
});
app.service('$address', function($http, blockUI) {
this.getAddressPT = function(zipcode, callback) {
if (this.validateZipcode(zipcode)) {
return callback("Código postal inválido");
}
blockUI.start('A procurar arruamento...');
$http.get("./api/address/pt/" + zipcode)
.then(function(response) {
callback(null, response.data);
})
.catch(function(response) {
callback(response);
})
.finally(function() {
blockUI.stop();
});
};
this.validateZipcode = function(zipcode) {
if (!zipcode) {
return true;
}
if (typeof zipcode !== 'string') {
zipcode = zipcode + '';
}
var cps = zipcode.split('-');
if (cps.length < 1 || cps.length > 2) {
return true;
}
if (isNaN(cps[0])) {
return true;
}
if (cps.length > 1) {
if (isNaN(cps[1])) {
return true;
}
}
return false;
};
this.getCoordinates = function(zipcode, callback) {
try {
var geocoder = new google.maps.Geocoder();
geocoder.geocode({ 'address': zipcode }, function (results, status) {
if (status !== google.maps.GeocoderStatus.OK) {
callback(status);
}
callback(null, {
lat: results[0].geometry.location.lat(),
lng: results[0].geometry.location.lng()
});
});
}
catch (error) {
callback(error);
}
};
});
app.factory('$auth', function ($http, $crypto, blockUI, $location, anonymousPages, $rootScope, Idle, zapi, $translate) {
var service = {
currentUser: null,
login: function (username, password, callback) {
$translate('api.services.auth.loginLoad', function (text) {
blockUI.start(text);
}, function (translationId) {
blockUI.start(translationId);
});
return $http.post('/api/session/login/', {
username: username,
password: $crypto.md5(password)
}).then(function (response) {
if (zapi.idle) Idle.watch();
service.currentUser = response.data.user;
callback();
}).catch(function (response) {
$translate(['api.services.auth.loginErrorTitle', 'api.services.auth.loginErrorContent']).then(function (translations) {
swal(translations['api.services.auth.loginErrorTitle'], translations['api.services.auth.loginErrorContent'], "error");
//swal(loginErrorTitle, response.data, "danger");
}, function (translationsId) {
swal(translationsId.api_service_auth_loginerrortitle, translationsId.api_service_auth_loginerrorcontent, "error");
});
callback(true);
}).finally(function () {
blockUI.stop();
});
},
logout: function () {
$http.get('/api/session/logout').then(function (response) {
if (zapi.idle) Idle.unwatch();
service.currentUser = null;
$rootScope.login = {};
$location.path('/');
});
},
requestCurrentUser: function (callback) {
if (service.isAuthenticated()) return callback(null, service.currentUser);
$http.get('/api/session/currentuser').then(function (response) {
service.currentUser = response.data.user;
callback(null, service.currentUser);
}).catch(function (response) {
service.currentUser = null;
callback(response);
});
},
isAuthenticated: function () {
return !!service.currentUser;
},
activateAccount: function (rawCode, callback) {
if (!rawCode) return callback(true);
var codes = rawCode.split('&');
if (codes.length !== 2) return callback(true);
$translate('api.services.auth.activateAccountLoad', function (text) {
blockUI.start(text);
}, function (translationId) {
blockUI.start(translationId);
});
$http.post('/api/user/activate/', {
email: codes[0],
code: codes[1]
}).then(function (response) {
callback(null, response.data);
}).catch(function (response) {
$translate(['api.services.auth.activateAccountErrorTitle', 'api.services.auth.activateAccountErrorContent']).then(function (translations) {
swal({
title: translations['api.services.auth.activateAccountErrorTitle'],
text: translations['api.services.auth.activateAccountErrorContent'],
type: "info",
confirmButtonText: "OK"
});
}, function (translationsId) {
swal({
title: translationsId.api_service_auth_activateaccounterrortitle,
text: translationsId.api_service_auth_activateaccounterrorcontent,
type: "info",
confirmButtonText: "OK"
});
});
callback(true);
}).finally(function () {
blockUI.stop();
});
},
resetPassword: function (email, username, callback) {
$translate('api.services.auth.resetPasswordLoad', function (text) {
blockUI.start(text);
}, function (translationId) {
blockUI.start(translationId);
});
return $http.post('/api/user/resetpassword/', {
email: email,
username: username
}).then(function (response) {
$translate(['api.services.auth.resetPasswordSuccessTitle', 'api.services.auth.resetPasswordSuccessContent']).then(function (translations) {
swal(translations['api.services.auth.resetPasswordSuccessTitle'], translations['api.services.auth.resetPasswordSuccessContent'], "success");
}, function (translationsId) {
swal(translationsId.api_service_auth_resetpasswordsuccesstitle, translationsId.api_service_auth_resetpasswordsuccesscontent, "success");
});
callback();
}).catch(function (response) {
$translate(['api.services.auth.resetPasswordErrorTitle', 'api.services.auth.resetPasswordErrorContent']).then(function (translations) {
swal(translations['api.services.auth.resetPasswordErrorTitle'], translations['api.services.auth.resetPasswordErrorContent'], "error");
}, function (translationsId) {
swal(translationsId.api_service_auth_resetpassworderrortitle, translationsId.api_service_auth_resetpassworderrorcontent, "error");
});
callback(true);
}).finally(function () {
blockUI.stop();
});
},
changePassword: function (user, newPassword1, newPassword2, callback) {
if (!newPassword1) return;
if (newPassword1 !== newPassword2) {
$translate(['api.services.auth.changepasswordWrongPasswordTitle', 'api.services.auth.changepasswordWrongPasswordContent']).then(function (translations) {
swal(translations['api.services.auth.changepasswordWrongPasswordTitle'], translations['api.services.auth.changepasswordWrongPasswordContent'], "error");
}, function (translationsId) {
swal(