1 2//// File web.js //// 3'use strict' 4 5function startApp() { 6 7 $angular.modules = [ "ngRoute", "ngCookies", "ngTouch", "ui.bootstrap", 8 "pascalprecht.translate", "ngSanitize", "ngAnimate", 'angular-bind-html-compile', 'thatisuday.dropzone', 9 '720kb.datepicker', "ngMap", "ui.select", "monospaced.elastic", "youtube-embed" ]; 10 11 $angular.init(); 12 13 // init root scope 14 $angular.app.run(function($rootScope, $location, $http, $window, $timeout, $templateCache) { 15 $init.log("start run web"); 16 $angular.initRootScope($rootScope, $location, $window, $timeout, true); 17 18 $rootScope.getItemLinkBy = function(o) { 19 var entity = o.sys_entity ? o.sys_entity : o.entity; 20 var id = o.sys_id ? o.sys_id : (o.id ? o.id : (o._id ? o._id : o.entity_id)); 21 return $rootScope.getItemLink(entity, id); 22 }; 23 24 $rootScope.getItemLink = function(entity, id) { 25 if (entity === 'instance') { 26 return contextPath + '/home/' + id; 27 } 28 var url = $instance.getBaseUrl() + entity; 29 if (id != null) { 30 url += "/" + id; 31 } 32 return url; 33 }; 34 35 $init.log("end run"); 36 }); 37 38 $angular.app.controller('header', function($rootScope, $scope) { 39 $angular.headerScope = $scope; 40 41 $rootScope.openSearch = function(e) { 42 $utils.preventDefault(e); 43 44 $("body").addClass("searching"); 45 var $form = $('#search') 46 $form.addClass('active'); 47 setTimeout(function() { 48 $form.find('input')[0].focus(); 49 }, 200); 50 51 $rootScope.search(); 52 }; 53 54 $rootScope.closeSearch = function() { 55 var $body = $("body"); 56 if (!$body.hasClass("searching")) { 57 return; 58 } 59 $body.removeClass("searching"); 60 var $form = $('#search.active'); 61 $form.removeClass('active'); 62 }; 63 64 $rootScope.searchList = []; 65 $rootScope.search = function(e) { 66 if (e && e.keyCode === 27) { 67 $rootScope.closeSearch(); 68 return; 69 } 70 71 var txt = $rootScope.mysearch; 72 if ($utils.isBlank(txt)) { 73 $rootScope.searchList = []; 74 return; 75 } 76 txt = $utils.removeDiacritics(txt.trim().toLowerCase()); 77 78 // generic search 79 $rest.get({ 80 url: contextPath + "/www/instance/"+$instance.getId()+"/search.json?_q=" + txt 81 }).then(function(o) { 82 $rootScope.searchList = o.list; 83 }); 84 }; 85 86 $rootScope.clickGroup = function(e, page) { 87 $utils.preventDefault(e); 88 if (page.open == null) page.open = false; 89 page.open = !page.open; 90 }; 91 92 }); 93 94 $angular.app.controller('menu', function($rootScope, $scope) { 95 $angular.menuScope = $scope; 96 $scope.selectedPage = ""; 97 $scope.swipeLeft = function() { 98 $events.toggleMenu(); 99 }; 100 }); 101 102 $angular.app.controller('cartAsMenu', function($scope, $location) { 103 $angular.menuScope = $scope; 104 $scope.goToCheckout = function() { 105 $location.path($instance.getBaseUrl() + 'cart'); 106 } 107 }); 108 109 $angular.app.controller('cookies', function($rootScope, $scope) { 110 // cookies message 111 var version = "2"; 112 var cookieMsg = $storageService.get("_cookies"); 113 if (cookieMsg != version) { 114 $("#cookies").removeClass("hidden"); 115 116 $scope.accept = function() { 117 $angular.acceptLicense('cookies', null, function() { 118 $("#cookies").addClass("hidden"); 119 $storageService.put("_cookies", version); 120 $angular.initGA(); 121 }); 122 } 123 } else { 124 $angular.initGA(); 125 } 126 }); 127 128 $angular.prepareRouteProvider = function($routeProvider) { 129 130 if ($utils.isBlank(appInstance)) { 131 $routeProvider.when('/', $angular.resolveRoute('web-select')); 132 $routeProvider.when('/home', $angular.resolveRoute('web-select')); 133 } else { 134 $routeProvider.when('/', $angular.resolveRoute('web-home')); 135 $routeProvider.when('/home', $angular.resolveRoute('web-home')); 136 $routeProvider.when('/p/:id', $angular.resolveRoute('web-home')); 137 } 138 139 $routeProvider.when('/home/:instanceId', $angular.resolveRoute('web-home')); 140 $routeProvider.when('/home/:instanceId/p/:id', $angular.resolveRoute('web-home')); 141 142 $routeProvider.when('/home/:instanceId/preferences', $angular.resolveRoute('preferences', false, true)); 143 $routeProvider.when('/home/:instanceId/login', $angular.resolveRoute('login', false, true)); 144 $routeProvider.when('/home/:instanceId/logout', $angular.resolveRoute('logout', false, true)); 145 $routeProvider.when('/home/:instanceId/plan', $angular.resolveRoute('web-plan')); 146 $routeProvider.when('/home/:instanceId/agenda', $angular.resolveRoute('web-agenda')); 147 $routeProvider.when('/home/:instanceId/user', $angular.resolveRoute('web-user', true)); 148 $routeProvider.when('/home/:instanceId/pos', $angular.resolveRoute('web-pos', true)); 149 $routeProvider.when('/home/:instanceId/cart', $angular.resolveRoute('web-cart')); 150 $routeProvider.when('/home/:instanceId/orders', $angular.resolveRoute('web-orders', true)); 151 $routeProvider.when('/home/:instanceId/order/:id', $angular.resolveRoute('web-order')); 152 $routeProvider.when('/home/:instanceId/bookings', $angular.resolveRoute('web-bookings', true)); 153 $routeProvider.when('/home/:instanceId/booking/:id', $angular.resolveRoute('web-booking', true)); 154 $routeProvider.when('/home/:instanceId/:entity', $angular.resolveRoute('web-list')); 155 $routeProvider.when('/home/:instanceId/:entity/:entityId', $angular.resolveRoute('web-item')); 156 $routeProvider.when('/home/:instanceId/:entity/:entityId/pay', $angular.resolveRoute('web-cart')); 157 158 $routeProvider.when('/preferences', $angular.resolveRoute('preferences', false, true)); 159 $routeProvider.when('/login', $angular.resolveRoute('login', false, true)); 160 $routeProvider.when('/logout', $angular.resolveRoute('logout', false, true)); 161 $routeProvider.when('/plan', $angular.resolveRoute('web-plan')); 162 $routeProvider.when('/agenda', $angular.resolveRoute('web-agenda'));
163 $routeProvider.when('/user', $angular.resolveRoute('web-user', true)); 164 $routeProvider.when('/pos', $angular.resolveRoute('web-pos', true)); 165 $routeProvider.when('/cart', $angular.resolveRoute('web-cart')); 166 $routeProvider.when('/orders', $angular.resolveRoute('web-orders', true)); 167 $routeProvider.when('/order/:id', $angular.resolveRoute('web-order', true)); 168 $routeProvider.when('/bookings', $angular.resolveRoute('web-bookings', true)); 169 $routeProvider.when('/booking/:id', $angular.resolveRoute('web-booking', true)); 170 $routeProvider.when('/:entity', $angular.resolveRoute('web-list')); 171 $routeProvider.when('/:entity/:entityId', $angular.resolveRoute('web-item')); 172 $routeProvider.when('/:entity/:entityId/pay', $angular.resolveRoute('web-cart')); 173 174 $routeProvider.otherwise($angular.resolveRoute('not-found')); 175 }; 176 177 $angular.start(); 178}; 179 180//// File i18n.js //// 181var $i18n = { 182 183 "currencies": { 184 "USD" : { 185 "name": "US Dollars", 186 "symbol": "$", 187 "symbolAfterNumber": false, 188 "decimalDigits": 2, 189 "decimalNameKey": "msg.currency.USD.decimals" 190 }, 191 "EUR" : { 192 "name": "Euros", 193 "symbol": "â¬", 194 "symbolAfterNumber": true, 195 "decimalDigits": 2, 196 "decimalNameKey": "msg.currency.EUR.decimals" 197 }, 198 "MXN" : { 199 "name": "Pesos Mexicanos", 200 "symbol": "$", 201 "symbolAfterNumber": false, 202 "decimalDigits": 2, 203 "decimalNameKey": "msg.currency.MXN.decimals" 204 } 205 }, 206 207 "messages": { 208 "en" : { 209 // GENERIC MESSAGES 210 "msg.error": "¡Oops! Something went wrong.", 211 "msg.error.noConnection": "No internet connection", 212 "msg.error.502" : "The server is not available. Please try again in a moment.", 213 "msg.notFound": "Resource not found", 214 "msg.accessDenied": "You don't have permission to access to this resource.", 215 "msg.tooManyAttempts": "Too many attempts. Please, wait just a moment and try it again.", 216 "msg.data.conflict": "Please refresh the page due to a data conflict.", 217 "msg.data.invalid" : "Incorrect data. Please check your details.", 218 "msg.role.notAllowed" : "Role not allowed", 219 "msg.invalid": "Invalid", 220 "msg.noDataFound" : "No data found", 221 222 "msg.language": "Language", 223 "msg.lang.en": "English", 224 "msg.lang.es": "Spanish", 225 "msg.lang.fr": "French", 226 227 "role.super": "Super user", 228 "role.admin": "Administrator", 229 "role.coordinator": "Coordinator", 230 "role.basic": "Associated user", 231 232 "msg.cybersource" : "Credit/debit card", 233 234 "msg.path": "Path", 235 "msg.title": "Title", 236 "msg.subtitle": "Subtitle", 237 "msg.status": "Status", 238 "msg.code": "Code", 239 "msg.name": "Name", 240 "msg.name.extra": "Suffix", 241 "msg.key": "Key", 242 "msg.value": "Value", 243 "msg.text": "Text", 244 "msg.type": "Type", 245 "msg.color": "Color", 246 "msg.priority": "Priority", 247 "msg.email": "Email", 248 "msg.phone": "Phone", 249 "msg.phoneInt": "International phone", 250 "msg.description": "Description", 251 "msg.comments": "Comments", 252 "msg.address": "Address", 253 "msg.hint": "Hint", 254 "msg.username": "Username", 255 "msg.usernameOrEmail": "Username or email", 256 "msg.password": "Password", 257 "msg.password.new": "Password new", 258 "msg.sortBy": "Sort by", 259 "msg.enabled": "Enabled", 260 "msg.disabled": "Disabled", 261 "msg.tags": "Tags", 262 "msg.category": "Category", 263 "msg.categories": "Categories", 264 "msg.category.types": "Categories by entity", 265 "msg.category.parents": "Parents", 266 "msg.category.children": "Children", 267 "msg.category.notExisting": "Not existing", 268 "msg.date": "Date", 269 "msg.datetime": "Date time", 270 "msg.time": "Time", 271 "msg.day": "Day", 272 "msg.empty": "Empty", 273 "msg.keywords": "Keywords", 274 "msg.radius": "Radius", 275 "msg.customId": "Custom Id", 276 "msg.customId.placeholder": "Use a self-describing id (e.g. first letters of name)", 277 "msg.role": "Role", 278 "msg.morning": "Morning", 279 "msg.afternoon": "Afternoon", 280 "msg.night": "Night", 281 "msg.skipped": "Skipped", 282 "msg.behavior": "Behavior", 283 "msg.total": "Total", 284 "msg.subtotal": "Subtotal", 285 "msg.fixed": "Fixed", 286 "msg.url": "Url", 287 "msg.elements": "elements", 288 "msg.dashboard": "Dashboard", 289 "msg.spreadsheet": "Spreadsheet", 290 "msg.recovered": "Recovered", 291 "msg.inRisk": "In Risk", 292 "msg.sick": "Sick", 293 "msg.suspicious": "Suspicious", 294 "msg.actions": "Actions", 295 "msg.products": "Products", 296 "msg.employee": "Employee", 297 "msg.inheritance": "Inheritance", 298 "msg.plusDays": "Plus days", 299 "msg.more": "More", 300 "msg.less": "Less", 301 "msg.reloadInSeconds": "Reload in {{seconds}} seconds", 302 "msg.showMoreOptions": "show more options", 303 "msg.alignment" : "Alignment", 304 "msg.queryBuilder" : "Query builder", 305 "msg.filters" : "Filters", 306 "msg.filters.add" : "Add filter", 307 "msg.limit" : "Limit (Max number of rows)", 308 "msg.sort" : "Sort", 309 "msg.sort.add" : "Add sort", 310 "msg.direction" : "Direction", 311 "msg.direction.asc" : "Asc", 312 "msg.direction.desc" : "Desc", 313 "msg.projection" : "Projection (Data needed from database)", 314 "msg.projection.add" : "Add projection column", 315 "msg.query" : "Query", 316 "msg.query.empty": "no query built", 317 318 "msg.formula": "Formula", 319 "msg.formula.argument": "Argument", 320 "msg.formula.argument.add": "Add another argument", 321 "msg.formular.optional": "optional", 322 "msg.formula.empty": "no formula built", 323 "msg.formula.builder": "Formula builder", 324 "msg.formula.func.display.desc": "Get value from column (or path) to show", 325 "msg.formula.func.math.desc": "Do arithmetic operations", 326 "msg.formula.func.string.desc": "Parse numbers, booleans... to string", 327 "msg.formula.func.number.desc": "Parse string to number", 328 "msg.formula.func.bool.desc": "Parse string (True, yes...) or number (1/0) to boolean", 329 "msg.formula.func.not.desc": "Negate boolean value: true => false or false => true", 330 "msg.formula.func.and.desc": "Return true only if all booleans are true", 331 "msg.formula.func.or.desc": "Return true if any of booleans are true", 332 "msg.formula.func.eq.desc": "Return true if two values are equals", 333 "msg.formula.func.ne.desc": "Return true if two values are different", 334 "msg.formula.func.gt.desc": "Return true if first value is greater than second value", 335 "msg.formula.func.gte.desc": "Return true if first value is greater than second value or are equals", 336 "msg.formula.func.lt.desc": "Return true if first value is less than second value", 337 "msg.formula.func.lte.desc": "Return true if first value is less than second value or are equals", 338 "msg.formula.func.empty.desc": "Return true if value is empty string/list or value is null", 339 "msg.formula.func.length.desc": "Return number of characters in a string or number of items in a list", 340 "msg.formula.func.replace.desc": "Replace a text in a string by another text", 341 "msg.formula.func.substring.desc": "Get part of a string", 342 "msg.formula.func.contains.desc": "Check if text contains another text", 343 "msg.formula.func.round.desc": "Round a number", 344 "msg.formula.func.round_ceil.desc": "Round to ceil a number", 345 "msg.formula.func.round_floor.desc": "Round to floor a number", 346 "msg.formula.func.sum.desc": "Add all numbers from a list", 347 "msg.formula.func.avg.desc": "Calculate average of all numbers from a list", 348 "msg.formula.func.if.desc": "Return some value if a condition is true or another value if it's false", 349 "msg.formula.func.convert_to_text.desc": "Write a number with words", 350 "msg.formula.arg.operation": "Apply operations to fix numbers or columns with numbers.<br />Available operators: <strong> + - * / div mod</strong><br />Examples: <strong>5 + 8</strong> , <strong>age - 10</strong> , <strong>price * amount</strong>", 351 "msg.formula.arg.decimals": "Number of decimals to show", 352 353 "msg.operator.eq": "is equal to", 354 "msg.operator.ne": "is not equal to", 355 "msg.operator.gt": "is greater than", 356 "msg.operator.gte": "is greater or equal to", 357 "msg.operator.lt": "is less than", 358 "msg.operator.lte": "is less or equal to", 359 "msg.operator.in": "is in",
360 "msg.operator.nin": "is not in", 361 "msg.operator.like": "is like", 362 "msg.operator.exists": "exists", 363 364 "msg.dashboard.map.title": "COVID-19 cases map", 365 "msg.dashboard.map.description": "It displays confirmed cases location", 366 "msg.dashboard.graph.title": "COVID-19 cases graph", 367 "msg.dashboard.graph.description": "It displays daily cumulative cases", 368 369 "msg.datamixer.builder": "Datamixer Builder", 370 "msg.datamixer.addFromEntity": "Add data from entity", 371 "msg.datamixer.addFromVar": "Transform data from", 372 "msg.datamixer.variable": "Variable", 373 "msg.datamixer.process": "Process data", 374 "msg.datamixer.fromItem": "From item", 375 "msg.datamixer.fromItemPath": "From item <strong>{{from}}</strong>", 376 "msg.datamixer.fromEntity": "From entity <strong>{{from}}</strong>", 377 "msg.datamixer.fromVariable": "From variable <strong>{{from}}</strong>", 378 "msg.datamixer.storeData": "Store data", 379 "msg.datamixer.storedInVariable": "Data stored in variable", 380 "msg.datamixer.newVariable": "Name of variable where store processed data", 381 "msg.datamixer.fromData": "From data", 382 "msg.datamixer.toData": "Result after execute operation", 383 "msg.datamixer.function": "Function", 384 "msg.datamixer.operation": "Operation", 385 "msg.datamixer.operations": "Operations to be applied", 386 "msg.datamixer.addOperation": "Add operation", 387 "msg.datamixer.sampleData": "Sample data", 388 "msg.datamixer.removeOperation": "Remove operation", 389 "msg.datamixer.removeData": "Remove variable and its operations", 390 "msg.datamixer.variableAlreadyExists": "Variable name already exists", 391 "msg.datamixer.invalidVariableName": "Variable name must only have alphanumeric characters and underscores", 392 "msg.datamixer.by": "by", 393 "msg.datamixer.from": "from", 394 "msg.datamixer.atPosition": "at position", 395 "msg.datamixer.valueOf": "value of", 396 "msg.datamixer.num": "num", 397 "msg.datamixer.property": "property", 398 "msg.datamixer.regex": "regular expression", 399 "msg.datamixer.times": "times", 400 "msg.datamixer.loadFormulas": "calculate formulas", 401 "msg.datamixer.changeToExpression": "change to expression", 402 "msg.datamixer.changeToValue": "change to value", 403 "msg.datamixer.operation.count": "Count", 404 "msg.datamixer.operation.count.list": "<strong>Count</strong> items", 405 "msg.datamixer.operation.count.string": "<strong>Count</strong> characters", 406 "msg.datamixer.operation.sum": "Sum", 407 "msg.datamixer.operation.sum.list": "<strong>Sum</strong> all items", 408 "msg.datamixer.operation.filter.list": "<strong>Filter</strong> items", 409 "msg.datamixer.operation.filter.list.params": "<strong>Filter</strong> items by <strong>{{params.path}}</strong> {{operator}} <strong>{{filterValue}}</strong>", 410 "msg.datamixer.operation.query.list": "Apply <strong>query</strong> to items", 411 "msg.datamixer.operation.query.list.params": "Apply to items the <strong>query</strong>: <strong>{{params.query}}</strong>", 412 "msg.datamixer.operation.group.list": "<strong>Group</strong> items", 413 "msg.datamixer.operation.group.list.params": "<strong>Group</strong> items by <strong>{{params.by}}</strong>", 414 "msg.datamixer.operation.sort.list": "<strong>Sort</strong> items", 415 "msg.datamixer.operation.sort.list.params": "<strong>Sort</strong> items by <strong>{{params.by}}</strong>", 416 "msg.datamixer.operation.get.object": "<strong>Get</strong> value", 417 "msg.datamixer.operation.get.object.params": "<strong>Get</strong> value of <strong>{{params.at}}</strong>", 418 "msg.datamixer.operation.get.list": "<strong>Get</strong> item", 419 "msg.datamixer.operation.get.list.params": "<strong>Get</strong> item at position <strong>{{params.at}}</strong>", 420 "msg.datamixer.operation.get.string": "<strong>Get</strong> character", 421 "msg.datamixer.operation.get.string.params": "<strong>Get</strong> character at position <strong>{{params.at}}</strong>", 422 "msg.datamixer.operation.add.day": "<strong>Add</strong> days", 423 "msg.datamixer.operation.add.day.params": "<strong>Add</strong> <strong>{{params.value}}</strong> days", 424 "msg.datamixer.operation.add.time": "<strong>Add</strong> minutes", 425 "msg.datamixer.operation.add.time.params": "<strong>Add</strong> <strong>{{params.value}}</strong> minutes", 426 "msg.datamixer.operation.add.object": "<strong>Add</strong> property", 427 "msg.datamixer.operation.add.object.params": "<strong>Add</strong> property <strong>{{params.new_var}}</strong> with:", 428 "msg.datamixer.operation.add.list": "<strong>Add</strong> to each item", 429 "msg.datamixer.operation.add.list.params": "<strong>Add</strong> to each item:", 430 "msg.datamixer.operation.add.list.object.params": "<strong>Add</strong> property <strong>{{params.new_var}}</strong> to each item:", 431 "msg.datamixer.operation.add.integer": "<strong>Add</strong> <strong>{{params.value}}</strong>", 432 "msg.datamixer.operation.add.decimal": "<strong>Add</strong> <strong>{{params.value}}</strong>", 433 "msg.datamixer.operation.add.string": "<strong>Add</strong> text", 434 "msg.datamixer.operation.add.string.params": "<strong>Add</strong> text <strong>{{params.value}}</strong> to end", 435 "msg.datamixer.operation.subtract.day": "<strong>Subtract</strong> days", 436 "msg.datamixer.operation.subtract.day.params": "<strong>Subtract</strong> <strong>{{params.value}}</strong> days", 437 "msg.datamixer.operation.subtract.time": "<strong>Subtract</strong> minutes", 438 "msg.datamixer.operation.subtract.time.params": "<strong>Subtract</strong> <strong>{{params.value}}</strong> minutes", 439 "msg.datamixer.operation.subtract.object": "<strong>Remove</strong> property", 440 "msg.datamixer.operation.subtract.object.params": "<strong>Remove</strong> property <strong>{{params.value}}</strong>", 441 "msg.datamixer.operation.subtract.list": "<strong>Subtract</strong> to each item", 442 "msg.datamixer.operation.subtract.list.params": "<strong>Subtract</strong> to each item by <strong>{{params.value}}</strong>", 443 "msg.datamixer.operation.subtract.integer": "<strong>Subtract</strong> <strong>{{params.value}}</strong>", 444 "msg.datamixer.operation.subtract.decimal": "<strong>Subtract</strong> <strong>{{params.value}}</strong>", 445 "msg.datamixer.operation.subtract.string": "<strong>Subtract</strong> text", 446 "msg.datamixer.operation.subtract.string.params": "<strong>Subtract</strong> text matched by regular expression <strong>{{params.value}}</strong>", 447 "msg.datamixer.operation.multiply.list": "<strong>Multiply</strong> to each item", 448 "msg.datamixer.operation.multiply.list.params": "<strong>Multiply</strong> to each item by <strong>{{params.value}}</strong>", 449 "msg.datamixer.operation.multiply.integer": "<strong>Multiply</strong> <strong>{{params.value}}</strong>", 450 "msg.datamixer.operation.multiply.decimal": "<strong>Multiply</strong> <strong>{{params.value}}</strong>", 451 "msg.datamixer.operation.divide.list": "<strong>Divide</strong> to each item", 452 "msg.datamixer.operation.divide.list.params": "<strong>Divide</strong> to each item by <strong>{{params.value}}</strong>", 453 "msg.datamixer.operation.divide.integer": "<strong>Divide</strong> <strong>{{params.value}}</strong>", 454 "msg.datamixer.operation.divide.decimal": "<strong>Divide</strong> <strong>{{params.value}}</strong>", 455 "msg.datamixer.operation.replace.list": "<strong>Replace</strong> each item", 456 "msg.datamixer.operation.replace.list.params": "<strong>Replace</strong> each item by:", 457 "msg.datamixer.operation.fetch.list": "<strong>Fetch</strong> items", 458 "msg.datamixer.operation.fetch.list.params": "<strong>Fetch</strong> items {{params.load_formulas ? '& calculate formulas' : ''}}", 459 "msg.datamixer.operation.fetch.string": "<strong>Fetch</strong> to entity <strong>{{params.entity}}</strong>", 460 "msg.datamixer.operation.clone.day": "<strong>Duplicate</strong> day", 461 "msg.datamixer.operation.clone.day.params": "<strong>Duplicate</strong> day <strong>{{params.times}}</strong> times", 462 "msg.datamixer.operation.clone.time": "<strong>Duplicate</strong> time", 463 "msg.datamixer.operation.clone.time.params": "<strong>Duplicate</strong> time <strong>{{params.times}}</strong> times", 464 "msg.datamixer.operation.clone.object": "<strong>Duplicate</strong> object", 465 "msg.datamixer.operation.clone.object.params": "<strong>Duplicate</strong> object <strong>{{params.times}}</strong> times", 466 "msg.datamixer.operation.clone.list": "<strong>Duplicate</strong> list", 467 "msg.datamixer.operation.clone.list.params": "<strong>Duplicate</strong> list <strong>{{params.times}}</strong> times", 468 "msg.datamixer.operation.clone.integer": "<strong>Duplicate</strong> number", 469 "msg.datamixer.operation.clone.integer.params": "<strong>Duplicate</strong> number <strong>{{params.times}}</strong> times", 470 "msg.datamixer.operation.clone.decimal": "<strong>Duplicate</strong> number", 471 "msg.datamixer.operation.clone.decimal.params": "<strong>Duplicate</strong> number <strong>{{params.times}}</strong> times", 472 "msg.datamixer.operation.clone.string": "<strong>Duplicate</strong> text", 473 "msg.datamixer.operation.clone.string.params": "<strong>Duplicate</strong> text <strong>{{params.times}}</strong> times", 474 "msg.datamixer.operation.clone.boolean": "<strong>Duplicate</strong> boolean", 475 "msg.datamixer.operation.clone.boolean.params": "<strong>Duplicate</strong> boolean <strong>{{params.times}}</strong> times", 476 "msg.datamixer.operation.wrap": "<strong>Wrap</strong> in object", 477 "msg.datamixer.operation.wrap.params": "<strong>Wrap</strong> in object property <strong>{{params.new_var}}</strong>", 478 "msg.datamixer.operation.unwrap.list": "<strong>Unwrap</strong> list of lists", 479 "msg.datamixer.operation.formula.object": "Execute <strong>formula</strong>", 480 "msg.datamixer.operation.formula.object.params": "Execute formula: <strong>{{params.formula}}</strong>", 481 "msg.datamixer.operation.formula.list": "Execute <strong>formula</strong> on each item", 482 "msg.datamixer.operation.formula.list.params": "Execute formula on each item: <strong>{{params.formula}}</strong>", 483 "msg.datamixer.operation.invalid": "Function <strong>{{function}}</strong> cannot be applied to data type <strong>{{from_type}}</strong>", 484 "msg.datamixer.component.new": "New component", 485 "msg.datamixer.component.edit": "Edit component", 486 "msg.datamixer.component.wizard": "Component Wizard", 487 "msg.datamixer.component.type.choose": "Choose component type", 488 "msg.datamixer.component.icon.choose": "Icon: choose from <a href=\"https://fonts.google.com/icons\" target=\"_blank\">Material Icons</a>", 489 "msg.datamixer.component.value.choose": "Define value to show", 490 "msg.datamixer.component.style.choose": "Modify component styles", 491 "msg.datamixer.component.series.choose": "Define data series",
492 "msg.datamixer.component.markers.choose": "Select geo located data", 493 "msg.datamixer.component.tableData.choose": "Define data to show on table", 494 "msg.datamixer.component.operation.choose": "Grouped data operation", 495 "msg.datamixer.component.innerEntity": "Inner entity", 496 "msg.datamixer.component.innerEntity.path": "Path", 497 "msg.datamixer.component.color": "Color", 498 "msg.datamixer.component.width": "Width (12 is full width)", 499 "msg.datamixer.component.type.counter": "Counter", 500 "msg.datamixer.component.type.chart": "Chart", 501 "msg.datamixer.component.type.map": "Map", 502 "msg.datamixer.component.type.table": "Table", 503 "msg.datamixer.component.counter.value": "Values column (or path)", 504 "msg.datamixer.component.chart.type": "Chart type", 505 "msg.datamixer.component.chart.type.line": "Line", 506 "msg.datamixer.component.chart.type.area": "Area", 507 "msg.datamixer.component.chart.type.bar": "Bar", 508 "msg.datamixer.component.chart.type.radar": "Radar", 509 "msg.datamixer.component.chart.type.histogram": "Histogram", 510 "msg.datamixer.component.chart.type.pie": "Pie", 511 "msg.datamixer.component.chart.type.donut": "Donut", 512 "msg.datamixer.component.chart.type.radialBar": "Radial bar", 513 "msg.datamixer.component.chart.type.scatter": "Scatter", 514 "msg.datamixer.component.chart.type.heatmap": "HeatMap", 515 "msg.datamixer.component.chart.series": "Indicate one or more series", 516 "msg.datamixer.component.chart.series.name": "Serie name", 517 "msg.datamixer.component.chart.series.serie": "Serie values column (or path)", 518 "msg.datamixer.component.chart.series.serie.add": "Add another serie", 519 "msg.datamixer.component.chart.series.labels": "Labels column (or path)", 520 "msg.datamixer.component.chart.axis.x": "X axis column (or path)", 521 "msg.datamixer.component.chart.group": "Group data", 522 "msg.datamixer.component.chart.group.by": "By", 523 "msg.datamixer.component.chart.operation": "Operation", 524 "msg.datamixer.component.chart.timeline": "Timeline", 525 "msg.datamixer.component.chart.timeline.range": "Show data from last", 526 "msg.datamixer.component.chart.timeline.minutes": "Minutes", 527 "msg.datamixer.component.chart.timeline.hours": "Hours", 528 "msg.datamixer.component.chart.timeline.days": "Days", 529 "msg.datamixer.component.chart.timeline.weeks": "Weeks", 530 "msg.datamixer.component.chart.timeline.months": "Months", 531 "msg.datamixer.component.chart.timeline.years": "Years", 532 "msg.datamixer.component.chart.pie.portionsByColumns": "Portions by columns", 533 "msg.datamixer.component.chart.pie.portions.add": "Add portion", 534 "msg.datamixer.component.chart.pie.portion.label": "Portion label", 535 "msg.datamixer.component.chart.pie.portion.path": "Path to field", 536 "msg.datamixer.component.table.columns": "Table columns", 537 "msg.datamixer.component.table.columns.path": "Path to field", 538 "msg.datamixer.component.table.columns.label": "Column title", 539 "msg.datamixer.component.table.columns.add": "Add another columns", 540 "msg.datamixer.component.map.labels": "Markers title column (or path)", 541 "msg.datamixer.userInputs.sampleData": "Fill data to be used in samples", 542 "msg.datamixer.error.tooMuchTime": "Calculations take too much time. Contact systems department to improve processes.", 543 544 "msg.all": "All", 545 "msg.show": "Show", 546 "msg.required": "Required", 547 "msg.app_object": "App object", 548 "msg.listing": "Listing", 549 "msg.link": "Link", 550 "msg.noPlan": "No plan", 551 "msg.noShadow": "No shadow", 552 "msg.font": "Main font", 553 "msg.fontDisplay": "Special font", 554 "msg.rounded": "Rounded", 555 "msg.roundedBtns": "Rounded buttons", 556 "msg.disableDefault" : "Disable default template", 557 "msg.styles": "Styles / css", 558 "msg.cssImports": "CSS imports", 559 "msg.css.settings": "Settings", 560 "msg.css.variables": "Page and content styles", 561 "msg.css.imports": "Import fonts or styles", 562 "msg.css.sections": "Section styles", 563 "msg.css.editor": "CSS Editor", 564 "msg.variables": "Variables", 565 "msg.title.plan": "Plan title", 566 "msg.title.result": "Result title", 567 "msg.extension": "Extension", 568 "msg.trash": "Trash", 569 "msg.ips": "IPs", 570 "msg.level": "Level", 571 "msg.sys_changes": "Change history", 572 "msg.change.path": "Modified element", 573 "msg.change.old": "Before", 574 "msg.change.new": "After", 575 "msg.show.in.map": "Show in map", 576 "msg.sync": "Sync", 577 "msg.public": "Public", 578 "msg.uploadImage": "Upload image", 579 "msg.uploadAudio": "Upload audio", 580 "msg.uploadVideo": "Upload video", 581 "msg.uploadFile": "Upload file", 582 "msg.notify": "Notify", 583 "msg.set_value": "Set value", 584 "msg.copy_to_column": "Copy to column", 585 "msg.multiActions": "Multiple actions", 586 "msg.saveBeforeExecute": "Save before execute", 587 "msg.stock": "Stock", 588 "msg.stock.exceeded": "Out of stock", 589 "msg.stock.show": "Show stock", 590 "msg.multiple": "Multiple", 591 "msg.youtube.url": "YouTube URL", 592 "msg.playlist": "Playlist", 593 "msg.property": "Property", 594 "msg.col": "Column", 595 "msg.row": "Row", 596 "msg.colNum": "Column number", 597 "msg.rowNum": "Row number", 598 "msg.customFilters": "Custom filters", 599 "msg.spreadsheet.query": "Query to apply always", 600 "msg.spreadsheet.query.sample": "example: name:like=john&age:$gt=18", 601 602 "msg.reload": "Reload", 603 "msg.reservation": "Booking", 604 "msg.places": "Places", 605 "msg.purchases": "Purchases", 606 "msg.reset": "Reset", 607 "msg.free": "Free", 608 "msg.units": "Units", 609 "msg.currency": "Currency", 610 "msg.price": "Price", 611 "msg.discount": "Discount", 612 "msg.quantity": "Quantity", 613 "msg.checkout": "Checkout", 614 "msg.orders": "My orders", 615 "msg.order": "Order", 616 "msg.order.code": "Order code", 617 "msg.order.total": "Order summary", 618 "msg.order.data": "Order data", 619 "msg.order.items": "Order items", 620 "msg.order.new": "New order", 621 "msg.order.list": "Order list", 622 "msg.order.base": "Subtotal", 623 "msg.order.vat": "TAX", 624 "msg.order.add.discount": "Add discount", 625 "msg.clients": "Clients", 626 "msg.client": "Client", 627 "msg.operator": "Operator", 628 "msg.note": "Note", 629 "msg.tips": "Tip", 630 "msg.tips.allowed": "Tips allowed", 631 "msg.tips.add": "Add tip:", 632 "msg.anonymous.allowed": "Allow purchases without login", 633 "msg.cart.userRequired": "User required when add to cart", 634 "msg.customEntityOrder": "Custom entity order", 635 "msg.customEntityBooking": "Custom entity booking", 636 "msg.message" : "Message", 637 638 "msg.print": "Print", 639 "msg.print.next" : "Print next", 640 "msg.pay": "Pay", 641 "msg.pay.mode": "Method of payment", 642 "msg.goToPay": "Go to checkout", 643 "msg.paid": "Payed", 644 "msg.paid.web": "Paid on the web", 645 "msg.delivered": "Delivered", 646 "msg.to_pay": "To pay", 647 "msg.to_deliver": "To deliver", 648 "msg.to_deliver_web": "To deliver web", 649 "msg.paymentMethods": "Payment methods", 650 "msg.paymentMethods.choose": "Choose payment method:", 651 "msg.paymentMethods.noAvailable": "There are no payment methods available", 652 "msg.payment.card.number": "Card number", 653 "msg.payment.card.expiration": "Expiration date (MM/YY)", 654 "msg.payment.card.control": "CVV/CVC", 655 "msg.payment.declined": "Payment declined", 656 "msg.payment.failed": "Payment not completed. The confirmation process was unsuccessful, so your payment was not processed. Please try again to complete your purchase. If the problem persists, please contact our support team.", 657 "msg.booking": "Booking", 658 "msg.bookings": "Bookings", 659 "msg.booking.title": "Make a booking", 660 "msg.book": "Book", 661 "msg.book.on": "Book on", 662 "msg.capacity": "Capacity", 663 "msg.max_bookings": "Max Bookings", 664 "msg.capacity_per_booking": "Capacity per Booking", 665 "msg.numPlaces": "Number of places", 666 "msg.booking.day": "Booking day", 667 "msg.booking.time": "Booking time", 668 "msg.booking.quantity": "Booking quantity", 669 "msg.booking.success": "Your booking has been successfully processed.", 670 "msg.booking.date.not.enough.places": "There are not enough free places. Choose another date/time.", 671 "msg.booking.status.confirmed": "Confirmed", 672 "msg.booking.status.pending_payment": "Pending payment", 673 "msg.booking.status.canceled": "Canceled", 674 "msg.booking.cancel": "Cancel booking", 675 "msg.booking.cancel.confirm.title": "Confirm booking cancellation", 676 "msg.booking.cancel.confirm.text": "Are you sure you want to cancel this booking? It cannot be undone.", 677 "msg.goto.user.bookings": "See my bookings", 678 679 "msg.deliveryMethod": "Delivery method", 680 "msg.deliveryMethods": "Delivery methods", 681 "msg.deliveryMethods.choose": "Choose delivery method:", 682 "msg.delivery": "Delivery", 683 "msg.deliveryMethod.entity.tip": "Select a Form entity to request more delivery details or a Booking entity to link the purchase to a booking", 684 "msg.shippingCosts": "Shipping costs", 685 686 "msg.item.entity.tip": "Select a Form entity to request more product details during checkout process", 687
688 "msg.saved": "Saved", 689 "msg.created": "Created", 690 "msg.updated": "Updated", 691 "msg.sys.updated": "Updated", 692 "msg.removed": "Removed", 693 "msg.restored": "Restored", 694 "msg.moved": "Moved", 695 "msg.copied": "Copied", 696 "msg.done": "Done", 697 "msg.added": "Added", 698 "msg.verified": "Verified", 699 700 "msg.yes": "Yes", 701 "msg.no": "No", 702 "msg.exists": "Exists", 703 "msg.exit": "Exit", 704 "msg.back": "Back", 705 "msg.next": "Next", 706 "msg.start": "Start", 707 "msg.end": "End", 708 "msg.finish": "Finish", 709 "msg.close": "Close", 710 "msg.accept": "Accept", 711 "msg.accept.all": "Accept all", 712 "msg.reject": "Reject", 713 "msg.cancel": "Cancel", 714 "msg.update": "Update", 715 "msg.send": "Send", 716 "msg.save": "Save", 717 "msg.saveAndBack": "Save & Back", 718 "msg.saveAll": "Save all", 719 "msg.showAll": "Show list", 720 "msg.remove": "Remove", 721 "msg.removeAll": "Remove results", 722 "msg.delete": "Delete", 723 "msg.copy": "Copy", 724 "msg.copy.from": "Copy from", 725 "msg.copy.to": "Copy to", 726 "msg.copy.content": "Duplicate content", 727 "msg.copy.system": "Duplicate system entities", 728 "msg.edit": "Edit", 729 "msg.add": "Add", 730 "msg.add.to": "Add to", 731 "msg.add.multiple": "Add multiple", 732 "msg.add.multiple.auto": "Add auto", 733 "msg.see": "See", 734 "msg.change": "Change", 735 "msg.search": "Search", 736 "msg.search.reset" : "Remove filters", 737 "msg.search.advanced": "Advanced search", 738 "msg.search.simple": "Simple search", 739 "msg.search.placeholder": "Search", 740 "msg.search.location": "Name, address or lat,lon", 741 "msg.create": "Create", 742 "msg.create_simple": "Create simple", 743 "msg.lazyformulas": "Lazy formulas", 744 "msg.modeler": "Modeler", 745 "msg.finalize": "Finalize", 746 "msg.upload": "Upload", 747 "msg.upload.preview": "Preview of first row", 748 "msg.upload.execute": "It's ok! Save all rows", 749 "msg.download": "Download", 750 "msg.download.stats": "Download Stats", 751 "msg.report": "Report", 752 "msg.reports": "Reports", 753 "msg.move": "Move", 754 "msg.clone": "Clone", 755 "msg.merge": "Merge", 756 "msg.new": "New", 757 "msg.document": "Document", 758 "msg.documents": "Documents", 759 "msg.notUsed": "Not used", 760 "msg.forbidden": "Forbidden", 761 "msg.go": "Go", 762 "msg.clear": "Clear", 763 "msg.logo": "Logo", 764 "msg.logo.footer": "Logo footer", 765 "msg.mode.test": "Test", 766 "msg.attach_documents": "Attach documents", 767 "msg.display_table": "Show list as table", 768 "msg.display_table_web": "Show list as table (web)", 769 "msg.normal": "Normal", 770 "msg.read" : "Read", 771 "msg.no_instance_required" : "No instance required", 772 "msg.no_user_required" : "No user required", 773 "msg.myaccount" : "Show in my account", 774 "msg.mycart" : "Show in my cart", 775 "msg.home_super" : "Show at super user home", 776 "msg.home_instance" : "Show in all instance homes", 777 "msg.auto_location" : "Auto location", 778 "msg.show_properties" : "Show properties", 779 "msg.show_key_values" : "Show key values", 780 "msg.duplicate_copy" : "Duplicate if copy", 781 "msg.one_item": "One item", 782 "msg.readonly": "Readonly", 783 "msg.hide_media": "Hide media", 784 "msg.security" : "Security", 785 "msg.options" : "Options", 786 "msg.tabs.hidden" : "Hide tabs", 787 "msg.change_status": "Change status", 788 "msg.workflow": "Workflow", 789 "msg.columnTimestamp": "Timestamp column", 790 "msg.columnStatus": "Status column", 791 "msg.calendar_date": "Date for Calendar", 792 "msg.resultType": "Result type", 793 "msg.app_object.desc" : "Entidad principal del modelado propio de un cliente (Los coordinadores solamente ven este tipo)", 794 "msg.listing.desc" : "Entidad secundaria del modelado propio de un cliente", 795 "msg.system.desc" : "Entidad de sistema. Ahi van, todos nuestrros syncronizers, notifiers etc", 796 "msg.order.desc" : "Path for default order. By default: app_object:priority:desc - schecule:by dates - otherwise:default column", 797 "msg.calendar_date.desc": "Path to the date column to be used in the calendar view, or the paths to the day and time columns separated by comma, or \"geo_schedule\" to show all generated dates. Default: sys.created", 798 799 "msg.user.desc" : "Datos sensibles de usuario donde se guardará automáticamente el usuario en âgeo_userâ. Este tipo de entidades solo se podrán consultar desde el backend. Desde el frontend como mucho podremos dar acceso a su propio usuario para que lo vea y/o lo modifique.", 800 "msg.form.desc" : "Entidad de tipo formulario. Si además, es de tipo 'usuario' -> login required to access from frontend", 801 "msg.location.desc" : "De tipo ubicación", 802 "msg.geofence.desc" : "De tipo área de ubicación", 803 "msg.schedule.desc" : "De tipo 'evento'. Permite añadir fechas y/o programarlas", 804 "msg.trivia.desc" : "De tipo trivia", 805 "msg.prize.desc" : "De tipo premio", 806 "msg.buy.desc" : "De tipo producto para poder ser añadido al carrito de la compra", 807
808 "msg.security.desc" : "Esta solo aplica para el frontend. Por default, la entidad es restrictiva al 100% por lo que si queremos que sea pública, tenemos que ir seleccionando los checks que necesitemos.", 809 "msg.read.desc" : "Permite lectura", 810 "msg.create.desc" : "Permite crear", 811 "msg.update.desc" : "Permite actualizar", 812 "msg.delete.desc" : "Permite borrar", 813 "msg.no_instance_required.desc" : "La instancia no es requerida", 814 "msg.no_user_required.desc" : "No necesita usuario logueado", 815 "msg.myaccount.desc" : "Mostrar entidad en mi cuenta", 816 "msg.mycart.desc" : "Mostrar entidad con datos extras a guardar en el carrito de la compra", 817 818 "msg.create_simple.desc" : "Create with default column", 819 "msg.lazyformulas.desc": "No execute formulas when is list", 820 "msg.modeler.desc" : "Entity visible for modelers", 821 "msg.attach_documents.desc" : "Show attach documents at frontend", 822 "msg.show_properties.desc" : "Add extra properties at backend", 823 "msg.show_key_values.desc" : "Add extra key values at backend", 824 "msg.duplicate_copy.desc" : "Duplicate entity when copying", 825 "msg.one_item.desc" : "Entity only allows one item", 826 "msg.readonly.desc" : "Entity data is not updatable", 827 "msg.hide_media.desc" : "Hide media at backend", 828 "msg.display_table.desc" : "Show list as table", 829 "msg.display_table_web.desc" : "Show list as table (web)", 830 "msg.home_super.desc" : "Para indicar los que queremos que salgan al home de superusuario", 831 "msg.home_instance.desc" : "Sale por defecto en todas las instancias", 832 "msg.auto_location.desc" : "Llena automáticamente la ubicación en el momento de la creación del registro", 833 834 "msg.section": "Section", 835 "msg.header": "Header", 836 "msg.footer": "Footer", 837 "msg.footer.text": "Footer text", 838 "msg.background": "Background", 839 "msg.secondary": "Secondary", 840 "msg.card": "Card", 841 "msg.template": "Template", 842 "msg.button": "Button", 843 "msg.config": "Config", 844 "msg.pages": "Pages", 845 "msg.page": "Page", 846 "msg.add.page": "New page", 847 "msg.add.item": "New item", 848 "msg.action": "Action", 849 "msg.none": "None", 850 "msg.instance.entity": "Entity/Instance", 851 "msg.default": "Default", 852 "msg.template1": "Template1", 853 "msg.fullImage": "Full image", 854 "msg.imageTexts": "Image and texts", 855 "msg.carousel": "Carousel", 856 "msg.gallery": "Gallery", 857 "msg.preview": "Preview", 858 "msg.classes": "Classes", 859 "msg.column": "Column", 860 "msg.left": "Left", 861 "msg.right": "Right", 862 "msg.imageText": "Text on image", 863 "msg.horizontal": "Horizontal", 864 "msg.enum.option": "Option", 865 "msg.restricted": "Restricted", 866 867 "msg.select": "Select", 868 "msg.select.all": "Select all", 869 "msg.select.search": "Select or search", 870 "msg.select.media": "Select media", 871 "msg.select.target": "Select target", 872 "msg.select.entity": "Select entity", 873 "msg.select.instance": "Select instance", 874 "msg.select.instance.last": "Last selected", 875 "msg.select.from": "Select from", 876 "msg.select.addItem": "Add new item", 877 878 "msg.new.copy": "Copy", 879 "msg.new.search": "Search", 880 "msg.new.multiple": "Multiple", 881 "msg.new.showCreated": "Show created", 882 "msg.new.hideCreated": "Hide created", 883 "msg.new.empty.extended": "Empty extended", 884 "msg.new.locations": "Search locations", 885 "msg.new.locations.auto": "Search locations auto", 886 "msg.new.add": "Add existing", 887 888 "msg.new.version": "There is a new update available", 889 "msg.new.version.desc": "Would you like to update now?", 890 891 "msg.photos.add": "Add photos", 892 "msg.photos.google": "Google photos", 893 "msg.photos.wikipedia": "Wikipedia photos", 894 895 "msg.folder": "Section", 896 "msg.my_smart": "Agenda", 897 "msg.new_smart": "Planner", 898 899 "msg.property.type.category": "Section", 900 "msg.property.type.text": "Text", 901 "msg.property.type.link": "Link", 902 "msg.property.type.boolean": "Boolean", 903 "msg.property.type.number": "Number", 904 "msg.property.type.date": "Date", 905 "msg.property.type.color": "Color", 906 "msg.property.type.tags": "Tags", 907 "msg.property.type.list": "List", 908 "msg.property.type.asin": "ASIN", 909 "msg.property.type.hidden": "Hidden", 910 911 "msg.column.type.text": "Translatable text", 912 "msg.column.type.boolean_int": "Boolean number", 913 "msg.column.type.entity": "Entity type", 914 "msg.column.type.list": "Entity list", 915 "msg.column.type.any": "Any object", 916 "msg.column.type.any_entity": "Any entity", 917 "msg.column.type.any_entity_list": "Any entity list", 918 "msg.column.type.columnList": "Column entity list", 919 "msg.column.type.columnEntity": "Column entity", 920 "msg.column.type.cron": "Cron expression", 921 "msg.column.type.enum": "Choose one", 922 "msg.column.type.enum_list": "Choose many", 923 924 "msg.column.default": "Default", 925 "msg.column.hidden": "Hidden",
926 "msg.column.unexposed": "Unexposed", 927 "msg.column.lazyformula": "Lazy formula", 928 "msg.column.long": "Long", 929 "msg.column.html": "Html", 930 "msg.column.tab": "New tab", 931 "msg.column.calendar": "Calendar", 932 "msg.column.sort": "Sortable list", 933 "msg.column.updatable": "Updatable", 934 "msg.column.display": "Display", 935 "msg.column.nolabel": "No label", 936 "msg.column.required": "Required", 937 "msg.column.readonly": "Readonly", 938 "msg.column.search": "Search", 939 "msg.column.user": "User", 940 "msg.column.uppercase": "Uppercase", 941 "msg.column.autosave": "Autosave", 942 "msg.column.unique": "Unique", 943 944 "msg.column.classes" : "Classes", 945 "msg.column.size": "Size", 946 "msg.column.default_value": "Default value", 947 "msg.column.number": "Number", 948 "msg.column.min": "Min", 949 "msg.column.max": "Max", 950 "msg.column.maxlength": "Max length", 951 "msg.column.minlength": "Min length", 952 "msg.column.pattern": "Pattern", 953 "msg.column.super": "Super", 954 "msg.column.admin": "Admin", 955 "msg.column.admincreate": "Admin create", 956 "msg.column.condition": "Condition (javascript)", 957 "msg.column.delimiter": "Delimiter (or row-break)", 958 "msg.column.buttonStyle": "Button style", 959 960 "msg.column.default.desc": "Default column (only one permitted)", 961 "msg.column.hidden.desc": "Hidden column at frontend", 962 "msg.column.unexposed.desc": "Hidden column also in backend", 963 "msg.column.lazyformula.desc": "No execute the formula when is list", 964 "msg.column.long.desc": "Column full width (size:12)", 965 "msg.column.html.desc": "Text is html", 966 "msg.column.tab.desc": "Show column in a new tab", 967 "msg.column.calendar.desc": "Show listed data in a calendar", 968 "msg.column.sort.desc": "Permite ordenar si la columna es de tipo list", 969 "msg.column.updatable.desc": "Columna modificable en frontend", 970 "msg.column.autosave.desc": "Save form automatically when this column was modified (it applies only in web forms)", 971 "msg.column.unique.desc": "Validate column unique", 972 "msg.column.display.desc": "Los campos que quieres que se desplieguen en las listas", 973 "msg.column.nolabel.desc": "Oculta nombre de columna (solo para frontend)", 974 "msg.column.required.desc": "Columna requerida en formas", 975 "msg.column.readonly.desc": "La columna se muestra en modo lectura si hay valor", 976 "msg.column.search.desc": "Aparece en la sección de búsqueda (tambien sirve para las ordenaciones)", 977 "msg.column.user.desc": "Campo actualizable de reservas/carrito", 978 "msg.column.uppercase.desc": "Guarda el valor en mayusculas", 979 980 "msg.column.size.desc": "Tamaño de la columna. Default:4, max:12", 981 "msg.column.default_value.desc": "Para indicar un valor por defecto cuando se crea y no tiene valor", 982 "msg.column.min.desc": "Validación de valor mÃnimo numérico", 983 "msg.column.max.desc": "Validación de valor máximo numérico", 984 "msg.column.maxlength.desc": "Validación de longitud mÃnima", 985 "msg.column.minlength.desc": "Validación de longitud máxima", 986 "msg.column.pattern.desc": "Validación con expressión regular", 987 "msg.column.condition.desc": "Se mostrará el campo sólo si se cumple la condición (javascript). Ej.: obj.name == 'Alice'", 988 989 "msg.group": "Group", 990 "msg.system": "System", 991 "msg.configuration": "Configuration", 992 "msg.myEntities": "My entities", 993 "msg.lists": "Listings", 994 995 "msg.preferences": "Info", 996 "msg.preferences.powered": "Powered by GEO®", 997 998 "msg.number.decimal.separator": "point", 999 "msg.currency.decimal.separator": "and", 1000 "msg.currency.USD.decimals": "cents", 1001 "msg.currency.EUR.decimals": "cent", 1002 "msg.currency.MXN.decimals": "centavos", 1003 1004 "msg.trigger": "Trigger", 1005 "msg.trigger.contextEntity": "Context Entity", 1006 "msg.trigger.contextEntity.or": "or", 1007 "msg.trigger.event": "Event", 1008 "msg.trigger.event.add": "Add starting event", 1009 "msg.trigger.event.ctx.notSame": "All events must apply at same entity", 1010 "msg.trigger.event.condition.notFormula": "Condition is not a formula", 1011 "msg.trigger.event.column.empty": "Column is empty", 1012 "msg.trigger.event.time.empty": "Time is empty", 1013 "msg.trigger.event.scheduler.empty": "Scheduler is not defined", 1014 "msg.trigger.action": "Action", 1015 "msg.trigger.action.add": "Add action to do", 1016 "msg.trigger.action.notifier.empty": "No notifier selected", 1017 "msg.trigger.action.notifier.notFound": "Notifier selected not found", 1018 "msg.trigger.action.notifier.disabled": "Notifier selected is disabled", 1019 "msg.trigger.action.synchronizer.empty": "No synchronizer selected", 1020 "msg.trigger.action.synchronizer.notFound": "Synchronizer selected not found", 1021 "msg.trigger.action.synchronizer.disabled": "Synchronizer selected is disabled", 1022 "msg.trigger.action.spreadsheet.empty": "No synchronizer selected", 1023 "msg.trigger.action.spreadsheet.notFound": "Spreadsheet selected not found", 1024 "msg.trigger.action.spreadsheet.disabled": "Spreadsheet selected is disabled", 1025 "msg.trigger.action.entity.empty": "No entity selected", 1026 "msg.trigger.action.entity.notFound": "Entity selected not found", 1027 "msg.trigger.action.entity.disabled": "Entity selected is disabled", 1028 "msg.trigger.action.value.empty": "Value is empty", 1029 "msg.trigger.action.path.empty": "Path is empty", 1030 "msg.trigger.action.set_to.empty": "It's mandatory to indicate where to set value", 1031 "msg.trigger.action.custom_function.empty": "It's mandatory to indicate function to execute", 1032 1033 // LOGIN 1034 "msg.login": "Sign in", 1035 "msg.login.google": "Sign in with Google", 1036 "msg.login.register": "No account yet?", 1037 "msg.login.resetPwd": "I forgot my password", 1038 "msg.login.error": "Invalid credentials", 1039 "msg.register": "Sign up", 1040 "msg.register.update": "Account update", 1041 "msg.register.update.desc": "Please, indicate your email and review the Terms of Service and Licenses", 1042 "msg.register.exists": "This account already exists. Please, try to restore your password.",
1043 "msg.register.exists.validate": "This account already exists.", 1044 "msg.restore": "Restore", 1045 "msg.restore.title": "Create new password", 1046 "msg.restore.body" : "Hello,<br><br>Click this link to set your account password.<br><br><a href='{0}'>Create password</a><br><br>If you did not request this change, please ignore this email.<br><br>Thank you", 1047 "msg.restore.sent1": "Please check your email.", 1048 "msg.restore.sent2": "You will have received an email from WE with a link where you can indicate your password.", 1049 "msg.restore.sent3": "If you do not receive the email, check that the email is correct or wait 5 minutes please.", 1050 "msg.verify.title": "Account not verified", 1051 "msg.verify.desc": "Check your email to finish the verification of your account please", 1052 "msg.verify.error": "The account is not yet verified", 1053 "msg.verify.btn": "Done", 1054 "msg.verify": "Verify account", 1055 "msg.verify.body" : "Hello,<br><br>Click this link to verify your account.<br><br><a href='{0}'>Verify account</a><br><br>If you did not request this change, please ignore this email.<br><br>Thank you", 1056 "msg.disabled.register": "Sign up not allowed", 1057 "msg.password.new.invalid": "The new password is invalid", 1058 "msg.licenses.accept": "I have read and accept the Terms of Service and Licenses", 1059 "msg.logout": "Sign out", 1060 "msg.mslogin" : "MS Login", 1061 1062 // CALENDAR 1063 "msg.calendar.default" : "Default calendar", 1064 "msg.calendar.timetable" : "Timetable", 1065 "msg.calendar.holidays" : "Holidays", 1066 "msg.calendar.holiday.set" : "Holiday", 1067 "msg.calendar.am": "AM", 1068 "msg.calendar.pm": "PM", 1069 "msg.calendar.time": "Time", 1070 "msg.calendar.week": "Day", 1071 "msg.calendar.drag": "Drag to select hours", 1072 "msg.calendar.reset": "Reset", 1073 "msg.calendar.monday":"Monday", 1074 "msg.calendar.tuesday":"Tuesday", 1075 "msg.calendar.wednesday":"Wednesday", 1076 "msg.calendar.thursday":"Thursday", 1077 "msg.calendar.friday":"Friday", 1078 "msg.calendar.saturday":"Saturday", 1079 "msg.calendar.sunday":"Sunday", 1080 1081 // CONFIRM 1082 "msg.confirm": "Are you sure you want to perform this operation?", 1083 "msg.confirm.removeInstance": "<span style='color:red'>Warning!</span> <b>This is going to remove all related data.</b>", 1084 "msg.confirm.removeAll": "<span style='color:red'>Warning!</span> <b>This is going to remove all results.</b>", 1085 "msg.confirm.leave": "Are you sure you want to leave this page?", 1086 1087 "msg.remove.warns.title": "Warning!", 1088 "msg.remove.warns.to_remove": "This will delete:", 1089 "msg.remove.warns.in_use": "This object still has relationships with:", 1090 1091 // COOKIES 1092 "msg.cookies.title": "Cookies policy", 1093 "msg.cookies.description": "<p>We use cookies in order to offer you a correct use of the site and our services.</p><p>You can get more information in our <a onclick='$angular.openLicense(\"cookies\", false)'>Cookies Policy</a>.</p><p>Press the ACCEPT button, to confirm that you have read and accepted the information.</p>", 1094 1095 // TERMS 1096 "msg.terms.title": "Review our Terms of Service and Licenses", 1097 "msg.terms.description": "By continuing to use this service your are agreeing to these terms.", 1098 "msg.terms.cookies": "Cookies policy", 1099 "msg.terms.eula": "EULA", 1100 "msg.terms.privacy": "Privacy Policy", 1101 "msg.terms.terms": "Terms of Service", 1102 "msg.terms.platform": "Platform Terms of Service Fidesur", 1103 1104 // FORM VALIDATIONS 1105 "required": "This field is required.", 1106 "fields.required": "Fields required.", 1107 "email.required": "Email required", 1108 1109 // SERVER MESSAGES 1110 "server.alreadyExists": "already exists", 1111 "server.entityExists": "Id '{0}' already exists", 1112 "server.entityNotExists": "Id '{1}' does not exist in '{0}'", 1113 "server.entity.allColumnsRequired": "All columns fields are required", 1114 "server.entity.incorrectColumn": "Incorrect column {0}", 1115 "server.entity.repeatedColumn": "Repeated column {0}", 1116 "server.geoFence.invalid": "Invalid Area", 1117 "server.geo.id.required": "Id required", 1118 "server.geo.customId.invalid": "Invalid custom id '{0}'", 1119 "server.geo.hasData": "This entity has data in '{0}'", 1120 "server.geo.used": "This is used in '{0}' '{1}'", 1121 "server.geo.noInstance": "No instance selected", 1122 "server.geo.name.required": "Name is required", 1123 "server.geo.instanceBelongItself": "Instance cannot belong to itself", 1124 "server.geo.instanceContainsItself": "Instance cannot contains itself", 1125 "server.media.typeRequired": "MediaType is required", 1126 "server.media.noSourceLink": "No source link provided to create the media", 1127 "server.media.sourceLink.incorrect": "Source link incorrect", 1128 "server.media.sourceLink.noData": "No data for source link",
1129 "server.schedule.timeFrom.invalid": "Time from is invalid. Format HH:mm", 1130 "server.schedule.timeTo.invalid": "Time to is invalid. Format HH:mm", 1131 "server.schedule.date.required": "Date cannot be empty", 1132 "server.schedule.cron.invalid": "Cron expression invalid: {0}", 1133 "server.noEntities": "No entities defined", 1134 "server.noEntities.found": "No entities found", 1135 "server.words.required": "Search words are required", 1136 "server.area.required": "Area is required", 1137 "server.noPlacesFound": "No places found", 1138 "server.wikiPage.required": "Wikipedia page is required", 1139 "server.smarts.disabled": "Smarts disabled", 1140 "server.spreadsheet.empty": "Spreadsheet has no rows", 1141 1142 // APP MESSAGES 1143 "msg.app.title": "GEO", 1144 "msg.app.description": "GEO", 1145 1146 "msg.home": "Home", 1147 "msg.settings": "Settings", 1148 1149 "msg.instances": "Instances", 1150 "msg.instance": "Instance", 1151 "msg.subInstance": "SubInstance", 1152 "msg.belongsTo": "Belongs to", 1153 "msg.contains": "Contains", 1154 "msg.instance.home": "Home", 1155 "msg.instance.showCurrent": "Show current instance", 1156 "msg.type.add": "Add type", 1157 "msg.entities": "Entities", 1158 "msg.entity": "Entity", 1159 "msg.entity.name": "Entity name", 1160 "msg.entity.type": "Entity type", 1161 "msg.entity.value": "Entity value", 1162 "msg.entity.filter.unused": "Unused non-system entities", 1163 "msg.users": "Users", 1164 "msg.user": "User", 1165 "msg.user.account": "My account", 1166 "msg.user.qr": "My QR code", 1167 "msg.user.name": "User name", 1168 "msg.menu": "Menu", 1169 "msg.target": "Target", 1170 "msg.recents": "Recents", 1171 "msg.generateQR": "View QR code", 1172 1173 "msg.translations": "Translations", 1174 "msg.translations.allowedVariables": "This text allows variables", 1175 "msg.translations.variables": "variables", 1176 "msg.translations.variables.info.text": "In this text it's allowed to add variables that will be resolved with the value they have at the time of displaying the text.", 1177 "msg.translations.variables.info.list": "Enabled variables:", 1178 "msg.translations.variables.info.sample.title": "How to use variables", 1179 "msg.translations.variables.info.sample.text": "Each variable has assigned a number. In the part of the text that we want the variable to be written, we put the number between braces. Example:", 1180 "msg.translations.variables.info.sample.original.label": "We save the text:", 1181 "msg.translations.variables.info.sample.original.value": "Hi {0}! You have visited {1} countries!", 1182 "msg.translations.variables.info.sample.result.label": "It's resolved:", 1183 "msg.translations.variables.info.sample.result.value": "Hi John! You have visited 15 countries!", 1184 "msg.translations.media.description": "It allows to overwrite the media file by another file for an specific language.", 1185 1186 "msg.general": "General", 1187 "msg.sourceEntity": "Source entity", 1188 "msg.resultEntities": "Entities", 1189 "msg.use": "Use", 1190 "msg.useTypes": "Use types", 1191 "msg.usePriority": "Use priority", 1192 "msg.useProximity": "Use proximity", 1193 "msg.usePeople": "Use people", 1194 "msg.useDates": "Use dates", 1195 "msg.useLocation": "Use location", 1196 "msg.useLocationInitial": "Use initial location", 1197 "msg.useCategories": "Use categories", 1198 "msg.useTranslations": "Use translations", 1199 "msg.dateFrom": "Date from", 1200 "msg.dateTo": "Date to", 1201 "msg.until": "Until", 1202 "msg.timeFrom": "Time from", 1203 "msg.timeTo": "Time to", 1204 "msg.people": "People", 1205 "msg.senior": "Senior", 1206 "msg.adult": "Adult", 1207 "msg.teen": "Teen", 1208 "msg.kid": "Kid", 1209 "msg.dates": "Dates", 1210 "msg.types": "Types", 1211 "msg.first_time": "First time", 1212 "msg.been_here": "Been here", 1213 "msg.live_here": "Live here", 1214 "msg.numResults": "Number of results", 1215 "msg.maxResults": "Max results", 1216 "msg.defaultTimeBetween": "Time between items", 1217 "msg.useAverageTime": "Use average time", 1218 "msg.defaultAverageTime": "Default duration", 1219 "msg.includeRestaurants": "Include restaurants", 1220 "msg.useInitialPosition": "Use initial position", 1221 "msg.maxDays": "Max days", 1222 "msg.defaultMaxDistance": "Default max distance", 1223 "msg.maxDistance": "Max distance", 1224 "msg.walking": "Walking", 1225 "msg.driving": "Driving", 1226 "msg.zoom": "Zoom", 1227 "msg.countryCode": "Country code", 1228 "msg.timezone": "Time zone", 1229 "msg.doNotPlan": "Do not plan", 1230 1231 "msg.averageTime": "Average time", 1232 "msg.outdoor": "OutDoor", 1233 1234 "msg.info": "Info", 1235 "msg.location": "Location", 1236 "msg.locationList": "Locations", 1237 "msg.list": "List", 1238 "msg.map": "Map", 1239 "msg.calendar": "Calendar", 1240 "msg.trivia": "Trivia", 1241 "msg.prize": "Prize", 1242 "msg.form": "Form", 1243 "msg.buy": "Buy", 1244 "msg.buy.verb": "Buy", 1245 "msg.buyer": "Buyer", 1246 "msg.identity": "Identity",
1247 "msg.schedule": "Schedule", 1248 "msg.schedules": "Schedules", 1249 "msg.properties": "Properties", 1250 "msg.media": "Media", 1251 "msg.media.add": "Add media", 1252 "msg.relations": "Relations", 1253 "msg.smarter": "Smarts", 1254 "msg.smartRate": "Rating", 1255 1256 "msg.latitude": "Latitude", 1257 "msg.longitude": "Longitude", 1258 "msg.mobile": "Mobile", 1259 "msg.indoorLevel": "Indoor Level", 1260 "msg.extraInfo": "Extra Info", 1261 "msg.googlePlaceId": "Google Place ID", 1262 "msg.timetables": "Timetables", 1263 "msg.timetable.invalidHours": "Invalid hours", 1264 "msg.website": "Website", 1265 1266 "msg.image": "Image", 1267 "msg.audio": "Audio", 1268 "msg.video": "Video", 1269 "msg.others": "Others", 1270 "msg.images": "Images", 1271 "msg.image.byUrl": "From url", 1272 "msg.licenses": "Licenses", 1273 "msg.license": "License", 1274 "msg.author": "Author", 1275 "msg.sourceLink": "Source link", 1276 "msg.sourceMediaUrl": "Source media url", 1277 "msg.dropzone.drop": "Drag and drop files here or <label class='btn-link'>click to select</label>", 1278 "msg.tags.placeholder": "Add tags", 1279 "msg.wikipedia": "Wikipedia", 1280 "msg.wikipedia.url": "Wikipedia url", 1281 "msg.wikipedia.search": "Search in Wikipedia", 1282 "msg.wikiPage": "Wikipedia page", 1283 "msg.google": "Google", 1284 "msg.flickr": "Flickr", 1285 "msg.seeOriginal": "See original", 1286 "msg.seeBig": "See big", 1287 "msg.seeResized": "See resized", 1288 "msg.seeThumb": "See thumb", 1289 "msg.seeOnMap": "See on map", 1290 1291 "msg.schedule.allDay": "All day", 1292 1293 "msg.searchLocation": "Search single point", 1294 "msg.searchLocations": "Search multiple points", 1295 "msg.geofence": "Area", 1296 "msg.geofence.select": "Select area", 1297 "msg.geofence.search": "Search or draw area", 1298 "msg.geofence.radius": "Set area by radius", 1299 "msg.geofence.draw": "Draw", 1300 "msg.geofence.drawMinimum": "Set 3 points minimum", 1301 1302 "msg.locationList.dragToSort": "Drag to sort", 1303 "msg.locationList.routeUseFirstLocations": "Route only use 10 first locations", 1304 "msg.locationList.calculateRoute": "Calculate route", 1305 "msg.locationList.calculateRouteSort": "Calculate route and sort", 1306 "msg.locationList.calculateRoute.walking": "Walking", 1307 "msg.locationList.calculateRoute.driving": "Driving", 1308 1309 "msg.columns": "Columns", 1310 "msg.columns.add": "Add column", 1311 "msg.columns.addEntity": "Add entity", 1312 "msg.columns.default": "Default columns", 1313 "msg.entity.inner": "Inner entities", 1314 "msg.instance.add": "Add new instance", 1315 1316 "msg.question": "Question", 1317 "msg.answers": "Answers", 1318 "msg.answer.correct": "Correct", 1319 "msg.answerExplanation": "Explanation", 1320 "msg.answers.is_survey": "Is survey", 1321 1322 "msg.prize.image_inactive": "Image inactive", 1323 "msg.prize.image_active": "Image active", 1324 1325 "msg.data": "Data", 1326 "msg.google.data": "Google data", 1327 "msg.wiki.data": "Wikipedia data", 1328 "msg.place.exists": "This place already exists", 1329 1330 "status.pending": "Pending review", 1331 "status.working": "Working", 1332 "status.resolved": "Resolved", 1333 "status.accepted": "Accepted", 1334 "status.rejected": "Rejected", 1335 1336 "day.sunday": "Sunday", 1337 "day.monday": "Monday", 1338 "day.tuesday": "Tuesday", 1339 "day.wednesday": "Wednesday", 1340 "day.thursday": "Thursday", 1341 "day.friday": "Friday", 1342 "day.saturday": "Saturday", 1343 1344 "msg.time.format": "Time HH:mm", 1345 "msg.distance.kms": "Distance Kms", 1346 1347 "msg.move.desc": "This operation move all items of current instance to the target entity.", 1348 "msg.similars.found": "Similiars found!", 1349 "msg.similars.found2": "Similar entities found", 1350 "msg.similars.found3": "Would you still like to create it?", 1351 1352 "msg.nearbyUsers.title": "Proximity with other users", 1353 "msg.nearbyUsers.distance": "Max distance (in meters)", 1354 "msg.nearbyUsers.time": "Max time difference (in minutes)", 1355 1356 "msg.tax.includedInPrice": "Prices with taxes included", 1357 "msg.tax.vat": "Tax", 1358 "msg.tax.vat.percent": "Tax (%)", 1359 1360 "msg.email.header": "Please, DO NOT RESPOND TO THIS EMAIL.\nThis message has been generated automatically.", 1361 "msg.email.footer": "This message is intended exclusively for its recipient and may contain privileged or confidential information. If you are not the intended recipient, you are notified that unauthorized use, disclosure and/or copying is prohibited under current legislation. If you have received this message by mistake, we ask you to notify us immediately by this
1361same means and proceed to its destruction.", 1362 1363 "msg.scheduler.title": "Schedule this event", 1364 "msg.scheduler": "Scheduler", 1365 "msg.recurrent": "Recurrent", 1366 "msg.allDay": "All day", 1367 "msg.useDuration" : "Use duration", 1368 "msg.day.from": "Starting date", 1369 "msg.day.to": "Ending date", 1370 "msg.starting": "Starting", 1371 "msg.ending": "Ending", 1372 "msg.duration": "Duration", 1373 "msg.blockDates": "Block dates", 1374 "msg.blockDates.description": "You won't be able to schedule events on blocked dates", 1375 "msg.blockDays": "Block days", 1376 "msg.blockHours": "Block hours", 1377 "msg.generatedDates": "Generated dates", 1378 "msg.endDay": "End day", 1379 "msg.endTime": "End time", 1380 "msg.repeat": "Repeat", 1381 "msg.minutes": "Minutes", 1382 "msg.newDate": "New date", 1383 1384 "msg.timeAndAttendance": "Time and Attendance", 1385 "msg.worked": "Worked", 1386 "msg.workedHours": "Worked hours", 1387 "msg.extraHours": "Extra hours", 1388 "msg.attendantsEntity": "Attendants entity", 1389 "msg.workdaysEntity": "Workdays entity", 1390 "msg.accessRecordsEntities": "Access records entities", 1391 "msg.attendantColumn": "Attendant column", 1392 "msg.dateColumn": "Date column", 1393 "msg.numFutureWorkdays": "Num future workdays", 1394 "msg.access.type": "Access type", 1395 "msg.access.planned": "Planned time", 1396 "msg.access.record": "Record time", 1397 "msg.difference": "Difference", 1398 "msg.access.type.in": "In", 1399 "msg.access.type.out": "Out", 1400 "msg.access.status.registered": "Registered", 1401 "msg.access.status.unregistered": "Unregistered", 1402 "msg.access.status.unplanned": "Unplanned", 1403 1404 "msg.action.login": "Login", 1405 "msg.action.logout": "Logout", 1406 "msg.action.licenses": "Accept licenses", 1407 "msg.action.download": "Download", 1408 "msg.action.location": "Locate", 1409 "msg.action.prize": "Win prize", 1410 "msg.action.qr": "Read QR", 1411 "msg.action.details": "View details", 1412 "msg.action.favorite": "Mark favorite", 1413 "msg.action.checkin": "Check in", 1414 "msg.action.rate": "Rate", 1415 "msg.action.comment": "Comment", 1416 "msg.action.play_audio": "Play audio", 1417 "msg.action.play_video": "Play video", 1418 "msg.action.share_media": "Share media", 1419 "msg.action.smart": "Smart system", 1420 "msg.action.smart_create": "Smart system: Create", 1421 "msg.action.smart_add": "Smart system: Add", 1422 "msg.action.smart_remove": "Smart system: Remove", 1423 "msg.action.smart_move": "Smart system: Move", 1424 "msg.action.smart_move_to_day": "Smart system: Move to day", 1425 "msg.action.trivia_answer": "Trivia: Answer question", 1426 "msg.action.trivia_results": "Trivia: View results", 1427 "msg.action.survey": "Fill survey", 1428 "msg.action.book": "Book", 1429 "msg.action.buy": "Purchase order", 1430 1431 "msg.safeemployee": "Safe Employee", 1432 1433 "msg.scheduler.minutely": "Minutes", 1434 "msg.scheduler.hourly": "Hours", 1435 "msg.scheduler.daily": "Daily", 1436 "msg.scheduler.weekly": "Weekly", 1437 "msg.scheduler.monthly": "Monthly", 1438 "msg.scheduler.yearly": "Yearly", 1439 "msg.scheduler.advanced": "Advanced", 1440 "msg.scheduler.every": "Every", 1441 "msg.scheduler.on": "on", 1442 "msg.scheduler.onThe": "On the", 1443 "msg.scheduler.at": "at", 1444 "msg.scheduler.of": "of", 1445 "msg.scheduler.and": "and", 1446 "msg.scheduler.second": "second", 1447 "msg.scheduler.seconds": "second(s)", 1448 "msg.scheduler.minute": "minute", 1449 "msg.scheduler.minutes": "minute(s)", 1450 "msg.scheduler.hour": "hour", 1451 "msg.scheduler.hours": "hour(s)", 1452 "msg.scheduler.day": "day", 1453 "msg.scheduler.days": "day(s)", 1454 "msg.scheduler.month": "month", 1455 "msg.scheduler.months": "months(s)", 1456 "msg.scheduler.weekDay": "week day (Monday through Friday)", 1457 "msg.scheduler.dayOfWeek.MON": "Monday", 1458 "msg.scheduler.dayOfWeek.TUE": "Tuesday", 1459 "msg.scheduler.dayOfWeek.WED": "Wednesday", 1460 "msg.scheduler.dayOfWeek.THU": "Thursday", 1461 "msg.scheduler.dayOfWeek.FRI": "Friday", 1462 "msg.scheduler.dayOfWeek.SAT": "Saturday", 1463 "msg.scheduler.dayOfWeek.SUN": "Sunday", 1464 "msg.scheduler.cronExpression": "Cron expression", 1465 "msg.scheduler.cronExpressionDetails": "More details about how to create these expressions can be found", 1466 "msg.scheduler.here": "here", 1467 "msg.scheduler.monthDay.1W": "First weekday", 1468 "msg.scheduler.monthDay.LW": "Last weekday", 1469 "msg.scheduler.monthDay.L": "Last day", 1470 "msg.scheduler.monthWeek.#1": "First", 1471 "msg.scheduler.monthWeek.#2": "Second", 1472 "msg.scheduler.monthWeek.#3": "Third", 1473 "msg.scheduler.monthWeek.#4": "Fourth", 1474 "msg.scheduler.monthWeek.#5": "Fifth", 1475 "msg.scheduler.monthWeek.L": "Last", 1476 "msg.scheduler.month.1": "January", 1477 "msg.scheduler.month.2": "February", 1478 "msg.scheduler.month.3": "March", 1479 "msg.scheduler.month.4": "April", 1480 "msg.scheduler.month.5": "May", 1481 "msg.scheduler.month.6": "June", 1482 "msg.scheduler.month.7": "July", 1483 "msg.scheduler.month.8": "August", 1484 "msg.scheduler.month.9": "September", 1485 "msg.scheduler.month.10": "October", 1486 "msg.scheduler.month.11": "November", 1487 "msg.scheduler.month.12": "December", 1488 1489 // FRONT END MESSAGES 1490 "msg.web.whatDo": "What to do?", 1491 "msg.web.know": "Know", 1492 "msg.web.knowMore": "Know more", 1493 "msg.web.destinations": "Destinations", 1494 "msg.web.seeAll": "See all", 1495 "msg.web.seeMore": "See more", 1496 "msg.web.select": "Where to go?", 1497 "msg.web.recommendations": "Do you want personalized recommendations?", 1498 "msg.web.discover": "Discover our destinations", 1499 "msg.web.filters": "Filters", 1500 1501 "msg.web.cart": "Shopping cart", 1502 "msg.web.cart.empty": "Shopping cart empty", 1503 "msg.web.cart.checkout": "Checkout", 1504 "msg.web.cart.validateCard": "Validate card", 1505 "msg.web.cart.finish": "Finish payment", 1506 "msg.web.cart.continue": "Continue buying", 1507 "msg.web.cart.done.desc": "Your order has been successfully processed.", 1508 "msg.web.cart.contact": "Contact", 1509 "msg.web.cart.identity.guest": "Checkout as guest", 1510 "msg.web.cart.identity.user": "Checkout with account", 1511 1512 "msg.web.plan": "Create agenda", 1513 "msg.web.plan.new": "New", 1514 "msg.web.plan.people": "Who travels?",
1515 "msg.web.plan.types": "Did you visit previously?", 1516 "msg.web.plan.location": "Location", 1517 "msg.web.plan.categories": "Preferences", 1518 "msg.web.plan.dates": "Dates", 1519 "msg.web.plan.results": "See results", 1520 1521 "msg.web.agenda": "My Agenda", 1522 "msg.web.agenda.open": "Open", 1523 "msg.web.agenda.duration": "Duration", 1524 "msg.web.agenda.noResults": "No data found", 1525 1526 "msg.web.footer": "Powered by GEO®" 1527 }, 1528 1529 "es" : { 1530 // GENERIC MESSAGES 1531 "msg.error": "¡Oops! Algo salió mal.", 1532 "msg.error.noConnection": "Sin conexión a Internet", 1533 "msg.error.502" : "El servidor no está disponible. Por favor, vuelva a intentarlo en un momento.", 1534 "msg.notFound": "Recurso no encontrado", 1535 "msg.accessDenied": "Usted no tiene permisos para acceder a este recurso.", 1536 "msg.tooManyAttempts": "Demasiados intentos. Por favor, espere un momento y vuelve a intentarlo.", 1537 "msg.data.conflict": "Por favor, actualice la página debido a un conflicto de datos.", 1538 "msg.data.invalid" : "Hay datos incorrectos. Por favor, revise sus datos.", 1539 "msg.role.notAllowed" : "Rol no permitido", 1540 "msg.invalid": "Inválido", 1541 "msg.noDataFound" : "No se han encontrado resultados", 1542 1543 "msg.language": "Idioma", 1544 "msg.lang.en": "Inglés", 1545 "msg.lang.es": "Español", 1546 "msg.lang.fr": "Francés", 1547 1548 "role.super": "Super usuario", 1549 "role.admin": "Administrador", 1550 "role.coordinator": "Coordinador", 1551 "role.basic": "Usuario asociado", 1552 1553 "msg.cybersource" : "Tarjeta de crédito/débito", 1554 1555 "msg.title": "TÃtulo", 1556 "msg.subtitle": "SubtÃtulo", 1557 "msg.status": "Estado", 1558 "msg.name": "Nombre", 1559 "msg.name.extra": "Sufijo", 1560 "msg.code": "Código", 1561 "msg.value": "Valor", 1562 "msg.text": "Texto", 1563 "msg.type": "Tipo", 1564 "msg.color": "Color", 1565 "msg.priority": "Prioridad", 1566 "msg.email": "Email", 1567 "msg.phone": "Teléfono", 1568 "msg.phoneInt": "Teléfono internacional", 1569 "msg.description": "Descripción", 1570 "msg.comments": "Comentarios", 1571 "msg.address": "Dirección", 1572 "msg.hint": "Pista", 1573 "msg.userName": "Nombre de usuario", 1574 "msg.usernameOrEmail": "Nombre de usuario o email", 1575 "msg.password": "Contraseña", 1576 "msg.password.new": "Contraseña nueva", 1577 "msg.sortBy": "Ordenar por", 1578 "msg.enabled": "Habilitado", 1579 "msg.disabled": "Deshabilitado", 1580 "msg.tags": "Tags", 1581 "msg.category": "CategorÃa", 1582 "msg.categories": "CategorÃas", 1583 "msg.category.types": "CategorÃas por entidad", 1584 "msg.category.parents": "Padres", 1585 "msg.category.children": "Hijos", 1586 "msg.category.notExisting": "No existentes", 1587 "msg.date": "Fecha", 1588 "msg.datetime": "Fecha y hora", 1589 "msg.time": "Hora", 1590 "msg.day": "DÃa", 1591 "msg.empty": "VacÃo", 1592 "msg.keywords": "Palabras clave", 1593 "msg.radius": "Radio", 1594 "msg.customId": "Código personalizado", 1595 "msg.customId.placeholder": "Utilice un código auto descriptivo (ej: primeras letras)", 1596 "msg.role": "Rol", 1597 "msg.morning": "Mañana", 1598 "msg.afternoon": "Tarde", 1599 "msg.night": "Noche", 1600 "msg.skipped": "Omitidos", 1601 "msg.behavior": "Comportamiento", 1602 "msg.total": "Total", 1603 "msg.subtotal": "Subtotal", 1604 "msg.fixed": "Fijo", 1605 "msg.url": "Url", 1606 "msg.elements": "elementos", 1607 "msg.dashboard": "Dashboard", 1608 "msg.spreadsheet": "Spreadsheet", 1609 "msg.recovered": "Recuperados", 1610 "msg.inRisk": "En Riesgo", 1611 "msg.sick": "Enfermos", 1612 "msg.suspicious": "Sospechosos", 1613 "msg.actions": "Acciones", 1614 "msg.products": "Productos", 1615 "msg.employee": "Empleado", 1616 "msg.inheritance": "Herencia", 1617 "msg.plusDays": "Sumar dÃas", 1618 "msg.more" : "Más", 1619 "msg.less" : "Menos", 1620 "msg.reloadInSeconds": "Recargar en {{seconds}} segundos", 1621 "msg.showMoreOptions": "mostrar más opciones", 1622 "msg.alignment" : "Alineación", 1623 1624 "msg.operator.eq": "es igual que", 1625 "msg.operator.ne": "no es igual que", 1626 "msg.operator.gt": "es mayor que", 1627 "msg.operator.gte": "es mayor o igual que", 1628 "msg.operator.lt": "es menor que", 1629 "msg.operator.lte": "es menor o igual que", 1630 1631 "msg.dashboard.map.title": "Mapa de casos de COVID-19", 1632 "msg.dashboard.map.description": "Se muestran las ubicaciones de casos confirmados", 1633 "msg.dashboard.graph.title": "Gráfica de casos de COVID-19", 1634 "msg.dashboard.graph.description": "Se muestran los casos acumulados diarios", 1635 "msg.datamixer.error.tooMuchTime": "Los cálculos toman demasiado tiempo. Contactar con el departamento de sistemas para mejorar los procesos.", 1636 1637 "msg.all": "Todos", 1638 "msg.show": "Mostrar", 1639 "msg.required": "Requerido", 1640 "msg.app_object": "Objecto de App", 1641 "msg.listing": "Listado", 1642 "msg.link": "VÃnculo", 1643 "msg.noPlan": "No planificar", 1644 "msg.noShadow": "Sin sombra", 1645 "msg.font": "Fuente principal", 1646 "msg.fontDisplay": "Fuente especial", 1647 "msg.rounded": "Redondeado", 1648 "msg.roundedBtns": "Botones redondeados", 1649 "msg.disableDefault" : "Deshabilitar plantilla por defecto", 1650 "msg.styles": "Estilos / css", 1651 "msg.cssImports": "CSS imports", 1652 "msg.css.settings": "Ajustes", 1653 "msg.css.variables": "Estilos de página y contenido", 1654 "msg.css.imports": "Importar fuentes o estilos", 1655 "msg.css.sections": "Estilos de sección", 1656 "msg.css.editor": "Editor CSS", 1657 "msg.variables": "Variables", 1658 "msg.title.plan": "TÃtulo planificar", 1659 "msg.title.result": "TÃtulo resultado", 1660 "msg.extension": "Extensión", 1661 "msg.trash": "Papelera", 1662 "msg.level": "Nivel", 1663 "msg.sys_changes": "Histórico de cambios", 1664 "msg.change.path": "Elemento modificado", 1665 "msg.change.old": "Antes", 1666 "msg.change.new": "Después", 1667 "msg.show.in.map": "Mostrar en el mapa", 1668 "msg.sync": "Sincronizar", 1669 "msg.public": "Público", 1670 "msg.uploadImage": "Subir imagen", 1671 "msg.uploadAudio": "Subir audio", 1672 "msg.uploadVideo": "Subir video", 1673 "msg.uploadFile": "Subir archivo", 1674 "msg.notify": "Notificar", 1675 "msg.set_value": "Asignar valor", 1676 "msg.copy_to_column": "Copiar a columna",
1677 "msg.multiActions": "Múltiples acciones", 1678 "msg.saveBeforeExecute": "Guardar antes de ejecutar", 1679 "msg.stock": "Stock", 1680 "msg.stock.exceeded": "Agotado", 1681 "msg.stock.show": "Mostrar stock", 1682 "msg.multiple": "Múltiple", 1683 "msg.youtube.url": "YouTube URL", 1684 "msg.playlist": "Lista de reproducción", 1685 "msg.property": "Propiedad", 1686 "msg.col": "Columna", 1687 "msg.row": "Fila", 1688 "msg.colNum": "Número de columna", 1689 "msg.rowNum": "Número de fila", 1690 "msg.customFilters": "Filtros personalizados", 1691 "msg.spreadsheet.query": "Query que se aplicará siempre", 1692 "msg.spreadsheet.query.sample": "ejemplo: name:like=john&age:$gt=18", 1693 1694 "msg.reload": "Recargar", 1695 "msg.reservation": "Compras", 1696 "msg.places": "Lugares", 1697 "msg.purchases": "Compras", 1698 "msg.reset": "Reiniciar", 1699 "msg.free": "Gratis", 1700 "msg.units": "Unidades", 1701 "msg.currency": "Moneda", 1702 "msg.price": "Precio", 1703 "msg.discount": "Descuento", 1704 "msg.quantity": "Cantidad", 1705 "msg.checkout": "Pagar", 1706 "msg.orders": "Mis pedidos", 1707 "msg.order": "Pedido", 1708 "msg.order.code": "Número de pedido", 1709 "msg.order.total": "Resumen del pedido", 1710 "msg.order.data": "Datos del pedido", 1711 "msg.order.items": "ArtÃculos del pedido", 1712 "msg.order.new": "Nuevo pedido", 1713 "msg.order.list": "Lista de pedidos", 1714 "msg.order.base": "Subtotal", 1715 "msg.order.vat": "IVA", 1716 "msg.order.add.discount": "Añadir descuento", 1717 "msg.clients": "Clientes", 1718 "msg.client": "Cliente", 1719 "msg.operator": "Operador", 1720 "msg.note": "Nota", 1721 "msg.tips": "Propina", 1722 "msg.tips.allowed": "Propinas permitidas", 1723 "msg.tips.add": "Añadir propina:", 1724 "msg.anonymous.allowed": "Permitir comprar sin login", 1725 "msg.cart.userRequired": "Usuario requerido para añadir al carrito", 1726 "msg.customEntityOrder": "Entidad de pedidos propia", 1727 "msg.customEntityBooking": "Entidad de reservas propia", 1728 "msg.message" : "Mensaje", 1729 1730 "msg.print": "Imprimir", 1731 "msg.print.next" : "Imprimir siguiente", 1732 "msg.pay": "Pagar", 1733 "msg.pay.mode": "Forma de pago", 1734 "msg.goToPay": "Iniciar proceso de pago", 1735 "msg.paid": "Pagado", 1736 "msg.paid.web": "Pagado en el web", 1737 "msg.delivered": "Entregado", 1738 "msg.to_pay": "Por pagar", 1739 "msg.to_deliver": "Por entregar", 1740 "msg.to_deliver_web": "Por entregar web", 1741 "msg.paymentMethods": "Métodos de pago", 1742 "msg.paymentMethods.choose": "Elija el método de pago:", 1743 "msg.paymentMethods.noAvailable": "No hay métodos de pago disponibles", 1744 "msg.payment.card.number": "Número de la tarjeta", 1745 "msg.payment.card.expiration": "Fecha de caducidad (MM/AA)", 1746 "msg.payment.card.control": "CVV/CVC", 1747 "msg.payment.declined": "Pago rechazado", 1748 "msg.payment.failed": "Pago no completado. El proceso de confirmación no se ha realizado correctamente, por lo que tu pago no ha sido efectivo. Por favor, vuelve a intentarlo para finalizar tu compra. Si el problema persiste, contacta con nuestro equipo de soporte.", 1749 "msg.booking": "Reserva", 1750 "msg.bookings": "Reservas", 1751 "msg.booking.title": "Haz una reserva", 1752 "msg.book": "Reservar", 1753 "msg.book.on": "Reservar en", 1754 "msg.capacity": "Aforo", 1755 "msg.max_bookings": "Max Reservas", 1756 "msg.capacity_per_booking": "Aforo por reserva", 1757 "msg.numPlaces": "Número de plazas", 1758 "msg.booking.day": "DÃa de la reserva", 1759 "msg.booking.time": "Hora de la reserva", 1760 "msg.booking.quantity": "Cantidad de la reserva", 1761 "msg.booking.success": "Su reserva ha sido procesado correctamente.", 1762 "msg.booking.date.not.enough.places": "No hay suficientes plazas libres. Elija otra fecha/hora.", 1763 "msg.booking.status.confirmed": "Confirmada", 1764 "msg.booking.status.pending_payment": "Pago pendiente", 1765 "msg.booking.status.canceled": "Cancelada", 1766 "msg.booking.cancel": "Cancelar reserva", 1767 "msg.booking.cancel.confirm.title": "Confirmar cancelación de la reserva", 1768 "msg.booking.cancel.confirm.text": "¿Estás seguro de que deseas cancelar esta reserva? No se puede deshacer.", 1769 "msg.goto.user.bookings": "Ver mis reservas", 1770 1771 "msg.deliveryMethod": "Método de entrega", 1772 "msg.deliveryMethods": "Métodos de entrega", 1773 "msg.deliveryMethods.choose": "Elija el método de entrega:", 1774 "msg.delivery": "Entrega", 1775 "msg.deliveryMethod.entity.tip": "Seleccionar una entidad tipo Forma para pedir más datos de entrega o una entidad tipo Reservas para vincular la compra con una reserva", 1776 "msg.shippingCosts": "Gastos de envÃo", 1777 1778 "msg.item.entity.tip": "Seleccionar una entidad tipo Forma para pedir más datos del producto en el proceso de compra", 1779
1780 "msg.saved": "Guardado", 1781 "msg.created": "Creado", 1782 "msg.updated": "Actualizado", 1783 "msg.sys.updated": "Actualizado", 1784 "msg.removed": "Eliminado", 1785 "msg.restored": "Restaurado", 1786 "msg.moved": "Movido", 1787 "msg.copied": "Copiado", 1788 "msg.done": "Hecho", 1789 "msg.added": "Añadido", 1790 "msg.verified": "Verificado", 1791 1792 "msg.yes": "SÃ", 1793 "msg.no": "No", 1794 "msg.exists": "Existe", 1795 "msg.exit": "Salir", 1796 "msg.back": "Volver", 1797 "msg.next": "Siguiente", 1798 "msg.start": "Inicio", 1799 "msg.end": "Fin", 1800 "msg.finish": "Terminar", 1801 "msg.close": "Cerrar", 1802 "msg.accept": "Aceptar", 1803 "msg.accept.all": "Aceptar todo", 1804 "msg.reject": "Rechazar", 1805 "msg.cancel": "Cancelar", 1806 "msg.update": "Modificar", 1807 "msg.send": "Enviar", 1808 "msg.save": "Guardar", 1809 "msg.saveAndBack": "Guardar y Volver", 1810 "msg.saveAll": "Guardar todos", 1811 "msg.showAll": "Mostrar lista", 1812 "msg.remove": "Borrar", 1813 "msg.removeAll": "Borrar resultados", 1814 "msg.delete": "Eliminar", 1815 "msg.copy": "Copiar", 1816 "msg.copy.from": "Copiar de", 1817 "msg.copy.to": "Copiar a", 1818 "msg.copy.content": "Duplicar contenido", 1819 "msg.copy.system": "Duplicar entidades de sistema", 1820 "msg.edit": "Editar", 1821 "msg.add": "Añadir", 1822 "msg.add.to": "Añadir a", 1823 "msg.add.multiple": "Añadir multiples", 1824 "msg.add.multiple.auto": "Añadir auto", 1825 "msg.see": "Ver", 1826 "msg.change": "Cambiar", 1827 "msg.search": "Buscar", 1828 "msg.search.reset" : "Eliminar filtros", 1829 "msg.search.advanced": "Búsqueda avanzada", 1830 "msg.search.simple": "Búsqueda sencilla", 1831 "msg.search.placeholder": "Búsqueda", 1832 "msg.search.location": "Nombre, dirección o lat,long", 1833 "msg.create": "Crear", 1834 "msg.create_simple": "Crear simple", 1835 "msg.modeler": "Modelador", 1836 "msg.finalize": "Finalizar", 1837 "msg.upload": "Cargar", 1838 "msg.upload.preview": "Vista previa de la primera fila", 1839 "msg.upload.execute": "Esta bien! Guardar todas las filas", 1840 "msg.download": "Descargar", 1841 "msg.download.stats": "Descargar Stats", 1842 "msg.report": "Reporte", 1843 "msg.reports": "Reportes", 1844 "msg.move": "Mover", 1845 "msg.clone": "Clonar", 1846 "msg.merge": "Unir", 1847 "msg.new": "Nuevo", 1848 "msg.document": "Documento", 1849 "msg.documents": "Documentos", 1850 "msg.notUsed": "No utilizado", 1851 "msg.forbidden": "Prohibido", 1852 "msg.go": "Ir", 1853 "msg.clear": "Vaciar", 1854 "msg.logo": "Logo cabecera", 1855 "msg.logo.footer": "Logo pie de página", 1856 "msg.mode.test": "Test", 1857 "msg.attach_documents": "Adjuntar documentos", 1858 "msg.display_table": "Mostrar lista como tabla", 1859 "msg.display_table_web": "Mostrar lista como tabla (web)", 1860 "msg.normal": "Normal", 1861 "msg.read": "Leer", 1862 "msg.no_instance_required": "No se requiere instancia", 1863 "msg.no_user_required": "No se requiere usuario", 1864 "msg.myaccount": "Mostrar en mi cuenta", 1865 "msg.mycart": "Mostrar en mi carrito", 1866 "msg.home_super": "Mostrar en inicio de superusuario", 1867 "msg.home_instance": "Mostrar en inicio de todas las instancias", 1868 "msg.show_properties": "Mostrar propiedades", 1869 "msg.security" : "Seguridad", 1870 "msg.options" : "Opciones", 1871 "msg.tabs.hidden" : "Ocultar pestañas", 1872 "msg.change_status": "Cambio de estado", 1873 "msg.workflow": "Workflow", 1874 "msg.trigger": "Trigger", 1875 "msg.columnTimestamp": "Columna de fecha", 1876 "msg.columnStatus": "Columna de estado", 1877 "msg.resultType": "Tipo de resultado", 1878 1879 "msg.section": "Sección", 1880 "msg.header": "Cabecera", 1881 "msg.footer": "Pie de página", 1882 "msg.footer.text": "Texto pie de página", 1883 "msg.background": "Fondo", 1884 "msg.secondary": "Secundario", 1885 "msg.card": "Tarjeta", 1886 "msg.template": "Plantilla", 1887 "msg.button": "Botón", 1888 "msg.config": "Config", 1889 "msg.pages": "Páginas", 1890 "msg.page": "Página", 1891 "msg.add.page": "Nueva página", 1892 "msg.add.item": "Nuevo elemento", 1893 "msg.action": "Acción", 1894 "msg.none": "Ninguna", 1895 "msg.instance.entity": "Entidad/Instancia", 1896 "msg.default": "Por defecto", 1897 "msg.template1": "Plantilla1", 1898 "msg.fullImage": "Imagen entera", 1899 "msg.imageTexts": "Imagen y textos", 1900 "msg.carousel": "Carrusel", 1901 "msg.gallery": "GalerÃa", 1902 "msg.preview": "Vista previa", 1903 "msg.classes": "Clases", 1904 "msg.column": "Columna", 1905 "msg.left": "Izquierda",
1906 "msg.right": "Derecha", 1907 "msg.imageText": "Texto en imagen", 1908 "msg.horizontal": "Horizontal", 1909 "msg.enum.option": "Opción", 1910 "msg.restricted": "Restringido", 1911 1912 "msg.select": "Seleccionar", 1913 "msg.select.all": "Seleccionar todos", 1914 "msg.select.search": "Seleccionar o buscar", 1915 "msg.select.media": "Seleccionar media", 1916 "msg.select.target": "Seleccionar objetivo", 1917 "msg.select.entity": "Seleccionar entidad", 1918 "msg.select.instance": "Selecciona una instancia", 1919 "msg.select.instance.last": "Ãltimas seleccionadas", 1920 "msg.select.from": "Seleccionar desde", 1921 "msg.select.addItem": "Añadir nuevo elemento", 1922 1923 "msg.new.copy": "Copiar", 1924 "msg.new.search": "Buscar", 1925 "msg.new.multiple": "Multiples", 1926 "msg.new.showCreated": "Mostrar creados", 1927 "msg.new.hideCreated": "Ocultar creados", 1928 "msg.new.empty.extended": "VacÃo extendido", 1929 "msg.new.locations": "Buscar ubicaciones", 1930 "msg.new.locations.auto": "Buscar ubicaciones auto", 1931 "msg.new.add": "Añadir existentes", 1932 1933 "msg.new.version": "Hay una nueva actualización disponible", 1934 "msg.new.version.desc": "¿Desea actualizar ahora?", 1935 1936 "msg.photos.add": "Añadir fotos", 1937 "msg.photos.google": "Fotos de Google",
1938 "msg.photos.wikipedia": "Fotos de Wikipedia", 1939 1940 "msg.folder": "Sección", 1941 "msg.my_smart": "Agenda", 1942 "msg.new_smart": "Planificar", 1943 1944 "msg.property.type.category": "Sección", 1945 "msg.property.type.text": "Texto", 1946 "msg.property.type.link": "VÃnculo", 1947 "msg.property.type.boolean": "Booleano", 1948 "msg.property.type.number": "Número", 1949 "msg.property.type.date": "Fecha", 1950 "msg.property.type.color": "Color", 1951 "msg.property.type.tags": "Tags", 1952 "msg.property.type.list": "Lista", 1953 "msg.property.type.asin": "ASIN", 1954 "msg.property.type.hidden": "Oculto", 1955 1956 "msg.column.default": "Por defecto", 1957 "msg.column.hidden": "Oculto", 1958 "msg.column.unexposed": "No expuesto", 1959 "msg.column.long": "Largo", 1960 "msg.column.html": "Html", 1961 "msg.column.tab": "Nueva pestaña", 1962 "msg.column.calendar": "Calendario", 1963 "msg.column.sort": "Lista ordenable", 1964 "msg.column.updatable": "Actualizable", 1965 "msg.column.display": "Mostrar", 1966 "msg.column.nolabel": "Sin tÃtulo", 1967 "msg.column.required": "Requerido", 1968 "msg.column.readonly": "Solo lectura", 1969 "msg.column.search": "Buscar", 1970 "msg.column.user": "Usuario", 1971 "msg.column.uppercase": "Mayúsculas", 1972 "msg.column.autosave": "Autoguardado", 1973 "msg.column.unique": "Ãnica", 1974 1975 "msg.column.classes" : "Classes", 1976 "msg.column.size": "Tamaño", 1977 "msg.column.default_value": "Default value", 1978 "msg.column.number": "Number", 1979 "msg.column.min": "Min", 1980 "msg.column.max": "Max", 1981 "msg.column.maxlength": "Max length", 1982 "msg.column.minlength": "Min length", 1983 "msg.column.pattern": "Pattern", 1984 "msg.column.condition": "Condición (javascript)", 1985 "msg.column.delimiter": "Delimitador (o row-break)", 1986 "msg.column.buttonStyle": "Estilo del botón", 1987 1988 "msg.group": "Grupo", 1989 "msg.system": "Sistema", 1990 "msg.configuration": "Configuración", 1991 "msg.myEntities": "Mis entidades", 1992 "msg.lists": "Listados", 1993 1994 "msg.preferences": "Info", 1995 "msg.preferences.powered": "Powered by GEO®", 1996 1997 "msg.number.decimal.separator": "punto", 1998 "msg.currency.decimal.separator": "con", 1999 "msg.currency.USD.decimals": "centavos", 2000 "msg.currency.EUR.decimals": "céntimos", 2001 "msg.currency.MXN.decimals": "centavos", 2002 2003 // LOGIN 2004 "msg.login": "Iniciar sesión", 2005 "msg.login.google": "Iniciar sesión con Google", 2006 "msg.login.register": "¿Aún no tiene cuenta?", 2007 "msg.login.resetPwd": "Olvidé mi contraseña", 2008 "msg.login.error": "Datos incorrectos", 2009 "msg.register": "Crear cuenta", 2010 "msg.register.update": "Actualización de cuenta", 2011 "msg.register.update.desc": "Por favor, indique su email y revise las Condiciones de Servicio y Licencias", 2012 "msg.register.exists": "La cuenta ya existe. Por favor, intente restaurar su contraseña.", 2013 "msg.register.exists.validate": "La cuenta ya existe.", 2014 "msg.restore": "Restaurar", 2015 "msg.restore.title": "Crear nueva contraseña", 2016 "msg.restore.body" : "Hola,<br><br>Haz clic en este enlace para crear la contraseña de tu cuenta.<br><br><a href='{0}'>Crear contraseña</a><br><br>Si no has solicitado este cambio, ignora este correo electrónico.<br><br>Gracias", 2017 "msg.restore.sent1": "Por favor, revise su correo.", 2018 "msg.restore.sent2": "Habrá recibido un email con un link donde podrá indicar su contraseña.", 2019 "msg.restore.sent3": "Si no recibe el correo revise que el email sea correcto o espere 5 minutos por favor.", 2020 "msg.verify.title": "Cuenta no verificada", 2021 "msg.verify.desc": "Revise su correo para terminar la verificación de su cuenta por favor", 2022 "msg.verify.error": "La cuenta aun no está verificada", 2023 "msg.verify.btn": "Hecho", 2024 "msg.verify": "Verificar cuenta", 2025 "msg.verify.body" : "Hola,<br><br>Haga clic en este enlace para verificar su cuenta.<br><br><a href='{0}'>Verificar cuenta</a><br><br>Si no solicitó este cambio, ignore este correo electrónico.<br><br>Gracias.", 2026 "msg.disabled.register": "Nuevo usuario no permitido", 2027 "msg.password.new.invalid": "La nueva contraseña es inválida", 2028 "msg.licenses.accept": "He leido y acepto las Condiciones de Servicio y Licencias", 2029 "msg.logout": "Cerrar sessión", 2030 2031 // CONFIRM 2032 "msg.confirm": "¿Está seguro que desea realizar esta operación?", 2033 "msg.confirm.removeInstance": "<span style='color:red'>Alerta!</span> <b>Esta operación va ha eliminar todos los datos relacionados.</b>", 2034 "msg.confirm.removeAll": "<span style='color:red'>Alerta!</span> <b>Esta operación va ha eliminar todos los resultados.</b>", 2035 "msg.confirm.leave": "¿Estás seguro de que quieres salir de esta página?", 2036 2037 "msg.remove.warns.title": "Alerta!", 2038 "msg.remove.warns.to_remove": "Esta operación eliminará:",
2039 "msg.remove.warns.in_use": "Este objeto aún tiene relaciones con:", 2040 2041 // COOKIES 2042 "msg.cookies.title": "PolÃtica de cookies", 2043 "msg.cookies.description": "<p>Usamos cookies para ofrecerle un uso correcto del sitio y de nuestros servicios.</p><p>Puede obtener más información en nuestra <a onclick='$angular.openLicense(\"cookies\", false)'>PolÃtica de cookies</a>.</p><p>Presione el botón ACEPTAR para confirmar que ha leÃdo y aceptado la información.</p>", 2044 2045 // TERMS 2046 "msg.terms.title": "Revisa nuestras Condiciones de Servicio y Licencias", 2047 "msg.terms.description": "Al continuar utilizando este servicio usted está de acuerdo con estos términos.", 2048 "msg.terms.cookies": "PolÃtica de cookies", 2049 "msg.terms.eula": "EULA", 2050 "msg.terms.privacy": "PolÃtica de privacidad", 2051 "msg.terms.terms": "Condiciones de Servicio", 2052 "msg.terms.platform": "Términos y Condiciones de Uso de la Plataforma Fidesur", 2053 2054 // FORM VALIDATIONS 2055 "required": "Este campo es requerido.", 2056 "fields.required": "Campos requeridos.", 2057 "email.required": "Email requerido", 2058 2059 // SERVER MESSAGES 2060 "server.alreadyExists": "ya existe", 2061 "server.entityExists": "El id '{0}' ya existe", 2062 "server.entityNotExists": "El id '{1}' no existe en '{0}'", 2063 "server.entity.allColumnsRequired": "Todas la columnas son requeridas", 2064 "server.entity.incorrectColumn": "Columna incorrecta: {0}", 2065 "server.entity.repeatedColumn": "Columna repetida: {0}", 2066 "server.geoFence.invalid": "Ãrea inválido", 2067 "server.geo.id.required": "Id requerido", 2068 "server.geo.customId.invalid": "Id inválido '{0}'", 2069 "server.geo.hasData": "La entidad tiene datos en '{0}'", 2070 "server.geo.used": "Está siendo utilizado en {0} {1}", 2071 "server.geo.noInstance": "Instancia no seleccionada", 2072 "server.geo.name.required": "El nombre es requerido", 2073 "server.geo.instanceBelongItself": "La instancia no puede pertenecer a si mismo", 2074 "server.geo.instanceContainsItself": "La instancia no puede contenerse a si mismo", 2075 "server.media.typeRequired": "Tipo requerido",
2076 "server.media.noSourceLink": "Link de origen no encontrado", 2077 "server.media.sourceLink.incorrect": "Link de origen incorrecto", 2078 "server.media.sourceLink.noData": "Link de origen no tiene datos", 2079 "server.schedule.timeFrom.invalid": "La fecha inicial es inválida. Formato HH:mm", 2080 "server.schedule.timeTo.invalid": "La fecha final es inválida. Formato HH:mm", 2081 "server.schedule.date.required": "La fecha no puede estar vacÃa", 2082 "server.schedule.cron.invalid": "La expresión cron es inválida: {0}", 2083 "server.noEntities": "Entidades no definidas", 2084 "server.noEntities.found": "Entidades no encontradas", 2085 "server.words.required": "No datos que buscar", 2086 "server.area.required": "El area es requerida", 2087 "server.noPlacesFound": "Lugares no encontrados", 2088 "server.wikiPage.required": "La página de Wikipedia es requerida", 2089 "server.smarts.disabled": "El motor está deshabilitado", 2090 "server.spreadsheet.empty": "La hoja de cálculo no tiene filas", 2091 2092 // APP MESSAGES 2093 "msg.app.title": "GEO", 2094 "msg.app.description": "GEO", 2095 2096 "msg.home": "Inicio", 2097 "msg.settings": "Configuración", 2098 2099 "msg.instances": "Instancias", 2100 "msg.instance": "Instancia", 2101 "msg.subInstance": "SubInstancia", 2102 "msg.belongsTo": "Pertence a", 2103 "msg.contains": "Contiene", 2104 "msg.instance.home": "Inicio", 2105 "msg.instance.showCurrent": "Mostrar instancia actual", 2106 "msg.type.add": "Añadir tipo", 2107 "msg.entities": "Entidades", 2108 "msg.entity": "Entidad", 2109 "msg.entity.name": "Nombre de la entidad", 2110 "msg.entity.type": "Tipo de entidad", 2111 "msg.entity.value": "Entidad", 2112 "msg.users": "Usuarios", 2113 "msg.user": "Usuario", 2114 "msg.user.account": "Mi cuenta", 2115 "msg.user.qr": "Mi código QR", 2116 "msg.user.name": "Nombre del usuario", 2117 "msg.menu": "Menu", 2118 "msg.target": "Acción", 2119 "msg.recents": "Recientes", 2120 "msg.generateQR": "Ver código QR", 2121 2122 "msg.translations": "Traducciones", 2123 "msg.translations.allowedVariables": "Este texto permite variables", 2124 "msg.translations.variables": "variables", 2125 "msg.translations.variables.info.text": "En este texto se permite añadir variables que serán resueltas con el valor que tengan en el momento de mostrar el texto.", 2126 "msg.translations.variables.info.list": "Variables habilitadas:", 2127 "msg.translations.variables.info.sample.title": "Uso de variables", 2128 "msg.translations.variables.info.sample.text": "Cada variable tiene asignado un número. En la parte del texto que queramos que se escriba la variable ponemos el número entre llaves. Ejemplo:", 2129 "msg.translations.variables.info.sample.original.label": "Guardamos el texto:", 2130 "msg.translations.variables.info.sample.original.value": "Hola {0}! Usted ha visitado {1} paÃses!", 2131 "msg.translations.variables.info.sample.result.label": "Se resuelve cómo:", 2132 "msg.translations.variables.info.sample.result.value": "Hola Antonio! Usted ha visitado 15 paÃses!", 2133 "msg.translations.media.description": "Permite sobreescribir el fichero multimedia por otro fichero para un idioma especÃfico.", 2134 2135 "msg.general": "General", 2136 "msg.sourceEntity": "Entidad fuente", 2137 "msg.resultEntities": "Entidades", 2138 "msg.use": "Usar", 2139 "msg.useTypes": "Usar tipos", 2140 "msg.usePriority": "Usar prioridad", 2141 "msg.useProximity": "Usar proximidad", 2142 "msg.usePeople": "Usar gente", 2143 "msg.useDates": "Usar fechas", 2144 "msg.useLocation": "Usar ubicación", 2145 "msg.useLocationInitial": "Usar ubicación inicial", 2146 "msg.useCategories": "Usar categorias", 2147 "msg.useTranslations": "Usar traducciones", 2148 "msg.dateFrom": "Fecha desde", 2149 "msg.dateTo": "Fecha hasta", 2150 "msg.until": "Hasta", 2151 "msg.timeFrom": "Hora desde", 2152 "msg.timeTo": "Hora hasta", 2153 "msg.people": "Gente", 2154 "msg.senior": "Mayores", 2155 "msg.adult": "Adultos", 2156 "msg.teen": "Jóvenes", 2157 "msg.kid": "Niños", 2158 "msg.dates": "Fechas", 2159 "msg.types": "Tipos", 2160 "msg.first_time": "Primera vez", 2161 "msg.been_here": "He estado aquÃ", 2162 "msg.live_here": "Vivo aquÃ", 2163 "msg.numResults": "Número de resultados", 2164 "msg.maxResults": "Max resultados", 2165 "msg.defaultTimeBetween": "Tiempo entre elementos", 2166 "msg.useAverageTime": "Usar tiempo promedio", 2167 "msg.defaultAverageTime": "Duración por defecto", 2168 "msg.includeRestaurants": "Incluir restaurantes", 2169 "msg.useInitialPosition": "Utilizar position inicial", 2170 "msg.maxDays": "Max dÃas", 2171 "msg.defaultMaxDistance": "Max distancia por defecto", 2172 "msg.maxDistance": "Max distancia", 2173 "msg.walking": "Andando", 2174 "msg.driving": "Conduciendo", 2175 "msg.zoom": "Zoom", 2176 "msg.countryCode": "Código paÃs", 2177 "msg.timezone": "Zona horaria", 2178 "msg.doNotPlan": "No planear", 2179 2180 "msg.averageTime": "Tiempo promedio", 2181 "msg.outdoor": "Aire libre", 2182 2183 "msg.info": "Info", 2184 "msg.location": "Ubicación", 2185 "msg.locationList": "Ubicaciones", 2186 "msg.list": "Lista", 2187 "msg.map": "Mapa", 2188 "msg.calendar": "Calendario", 2189 "msg.trivia": "Trivia", 2190 "msg.prize": "Premio", 2191 "msg.form": "Forma", 2192 "msg.buy": "Compra", 2193 "msg.buy.verb": "Comprar", 2194 "msg.buyer": "Comprador", 2195 "msg.identity": "Identidad", 2196 "msg.schedule": "Programar", 2197 "msg.schedules": "Horarios", 2198 "msg.properties": "Propiedades", 2199 "msg.media": "Media", 2200 "msg.media.add": "Añadir media", 2201 "msg.relations": "Relaciones", 2202 "msg.smarter": "Motor inteligente", 2203 "msg.smartRate": "Valores", 2204 2205 "msg.latitude": "Latitud", 2206 "msg.longitude": "Longitud", 2207 "msg.mobile": "Móvil", 2208 "msg.indoorLevel": "Nivel interior", 2209 "msg.extraInfo": "Info extra", 2210 "msg.googlePlaceId": "ID de Google", 2211 "msg.timetables": "Horarios",
2212 "msg.timetable.invalidHours": "Horario inválido", 2213 "msg.website": "Sitio web", 2214 2215 "msg.image": "Imagen", 2216 "msg.audio": "Audio", 2217 "msg.video": "Video", 2218 "msg.others": "Otros", 2219 "msg.images": "Imágenes", 2220 "msg.image.byUrl": "Desde url", 2221 "msg.licenses": "Licencias", 2222 "msg.license": "Licencia", 2223 "msg.author": "Autor", 2224 "msg.sourceLink": "Enlance de origen", 2225 "msg.sourceMediaUrl": "Url de origen", 2226 "msg.dropzone.drop": "Arrastre ficheros aquà o <label class='btn-link'>clic para seleccionar</label>", 2227 "msg.tags.placeholder": "Añadir tags", 2228 "msg.wikipedia": "Wikipedia", 2229 "msg.wikipedia.url": "Url de wikipedia", 2230 "msg.wikipedia.search": "Buscar en Wikipedia", 2231 "msg.wikiPage": "Página Wikipedia", 2232 "msg.google": "Google", 2233 "msg.flickr": "Flickr", 2234 "msg.seeOriginal": "Ver original", 2235 "msg.seeBig": "Ver en grande", 2236 "msg.seeResized": "Ver redimensionado", 2237 "msg.seeThumb": "Ver en pequeño", 2238 "msg.seeOnMap": "Ver en mapa", 2239 2240 "msg.schedule.allDay": "Todo el dÃa", 2241 2242 "msg.searchLocation": "Buscar ubicación", 2243 "msg.searchLocations": "Buscar multiples ubicaciones", 2244 "msg.geofence": "Ãrea", 2245 "msg.geofence.select": "Seleccione área", 2246 "msg.geofence.search": "Busca o dibuja área", 2247 "msg.geofence.radius": "Ãrea por radio", 2248 "msg.geofence.draw": "Dibujar", 2249 "msg.geofence.drawMinimum": "3 puntos mÃnimo", 2250 2251 "msg.locationList.dragToSort": "Arrastre para ordenar", 2252 "msg.locationList.routeUseFirstLocations": "La ruta solo utiliza las 10 primeras ubicaciones", 2253 "msg.locationList.calculateRoute": "Calcular ruta", 2254 "msg.locationList.calculateRouteSort": "Calcular ruta y ordenar", 2255 "msg.locationList.calculateRoute.walking": "Andando", 2256 "msg.locationList.calculateRoute.driving": "Conduciendo", 2257 2258 "msg.columns": "Columnas", 2259 "msg.columns.add": "Añadir columna", 2260 "msg.columns.addEntity": "Añadir entitad", 2261 "msg.columns.default": "Columnas por defecto", 2262 "msg.entity.inner": "Entidades internas", 2263 "msg.instance.add": "Añadir nueva instancia", 2264 2265 "msg.question": "Pregunta", 2266 "msg.answers": "Respuestas", 2267 "msg.answer.correct": "Correcto", 2268 "msg.answerExplanation": "Explicación", 2269 "msg.answers.is_survey": "Es encuesta", 2270 2271 "msg.prize.image_inactive": "Imagen inactiva", 2272 "msg.prize.image_active": "Imagen activa", 2273 2274 "msg.data": "Datos", 2275 "msg.google.data": "Datos de Google",
2276 "msg.wiki.data": "Datos de Wikipedia", 2277 "msg.place.exists": "Este lugar ya existe", 2278 2279 "status.pending": "Por revisar", 2280 "status.working": "Trabajando", 2281 "status.resolved": "Resuelto", 2282 "status.accepted": "Aceptado", 2283 "status.rejected": "Rechazado", 2284 2285 "day.sunday": "Domingo", 2286 "day.monday": "Lunes", 2287 "day.tuesday": "Martes", 2288 "day.wednesday": "Miércoles", 2289 "day.thursday": "Jueves", 2290 "day.friday": "Viernes", 2291 "day.saturday": "Sábado", 2292 2293 "msg.time.format": "Tiempo HH:mm", 2294 "msg.distance.kms": "Distancia Kms", 2295 2296 "msg.move.desc": "Esta operación mueve todos los registros asignados a la actual instancia a la entidad especificada.", 2297 "msg.similars.found": "Encontrados parecidos!", 2298 "msg.similars.found2": "Entidades parecidas encontradas", 2299 "msg.similars.found3": "¿Desea crearlo igualmente?", 2300 2301 "msg.nearbyUsers.title": "Proximidad con otros usuarios", 2302 "msg.nearbyUsers.distance": "Distancia máxima (en metros)", 2303 "msg.nearbyUsers.time": "Diferencia de tiempo máxima (en minutos)", 2304 2305 "msg.tax.includedInPrice": "Precios con impuestos incluidos", 2306 "msg.tax.vat": "Impuesto", 2307 "msg.tax.vat.percent": "Impuesto (%)", 2308 2309 "msg.email.header": "Por favor, NO RESPONDER A ESTE CORREO.\nEste mensaje ha sido generado automáticamente.", 2310 "msg.email.footer": "Este mensaje está dirigido exclusivamente a su destinatario y puede contener información privilegiada o confidencial. Si no es usted el destinatario indicado, queda notificado de que la utilización, divulgación y/o copia sin autorización está prohibida en virtud de la legislación vigente. Si ha recibido este mensaje por error, le rogamos que nos lo comunique inmediatamente por esta misma vÃa y proceda a su destrucción.", 2311 2312 "msg.scheduler.title": "Programar este evento", 2313 "msg.scheduler": "Planificador", 2314 "msg.recurrent": "Recurrente", 2315 "msg.allDay": "Todo el dÃa", 2316 "msg.useDuration" : "Usar duración", 2317 "msg.day.from": "Fecha inicial", 2318 "msg.day.to": "Fecha final", 2319 "msg.starting": "Inicial", 2320 "msg.ending": "Final", 2321 "msg.duration": "Duración", 2322 "msg.blockDates": "Bloquear fechas", 2323 "msg.blockDates.description": "No podrá programar eventos en fechas bloqueadas", 2324 "msg.blockDays": "Bloquear dÃas", 2325 "msg.blockHours": "Bloquear horas", 2326 "msg.generatedDates": "Fechas generadas", 2327 "msg.endDay": "DÃa final", 2328 "msg.endTime": "Hora de finalización", 2329 "msg.repeat": "Repetir", 2330 "msg.minutes": "Minutos", 2331 "msg.newDate": "Nueva fecha", 2332 2333 "msg.timeAndAttendance": "Tiempo y asistencia", 2334 "msg.worked": "Trabajado", 2335 "msg.workedHours": "Horas trabajadas", 2336 "msg.extraHours": "Horas extra", 2337 "msg.attendantsEntity": "Entidad de asistentes", 2338 "msg.workdaysEntity": "Entidad de jornadas", 2339 "msg.accessRecordsEntities": "Entidades de registros de acceso", 2340 "msg.attendantColumn": "Columna asistente", 2341 "msg.dateColumn": "Column fecha", 2342 "msg.numFutureWorkdays": "Núm. jornadas a futuro", 2343 "msg.access.type": "Tipo de acceso", 2344 "msg.access.planned": "Hora planificada", 2345 "msg.access.record": "Hora de registro", 2346 "msg.difference": "Diferencia", 2347 "msg.access.type.in": "Entrada", 2348 "msg.access.type.out": "Salida", 2349 "msg.access.status.registered": "Registrado", 2350 "msg.access.status.unregistered": "No registrado", 2351 "msg.access.status.unplanned": "No planeado", 2352 2353 "msg.action.login": "Iniciar sesión", 2354 "msg.action.logout": "Cerrar sesión", 2355 "msg.action.licenses": "Aceptar licencias", 2356 "msg.action.download": "Descargar", 2357 "msg.action.location": "Localizar", 2358 "msg.action.prize": "Ganar premio", 2359 "msg.action.qr": "Leer QR", 2360 "msg.action.details": "Ver detalles", 2361 "msg.action.favorite": "Marcar favorito", 2362 "msg.action.checkin": "Registrarse", 2363 "msg.action.rate": "Valorar", 2364 "msg.action.comment": "Comentar", 2365 "msg.action.play_audio": "Reproducir audio", 2366 "msg.action.play_video": "Reproducir video", 2367 "msg.action.share_media": "Compartir medios", 2368 "msg.action.smart": "Sistema experto", 2369 "msg.action.smart_create": "Sistema experto: Crear", 2370 "msg.action.smart_add": "Sistema experto: Añadir", 2371 "msg.action.smart_remove": "Sistema experto: Eliminar", 2372 "msg.action.smart_move": "Sistema experto: Mover", 2373 "msg.action.smart_move_to_day": "Sistema experto: Mover de dÃa", 2374 "msg.action.trivia_answer": "Trivia: Responder pregunta", 2375 "msg.action.trivia_results": "Trivia: Ver resultados", 2376 "msg.action.survey": "Rellenar encuesta", 2377 "msg.action.book": "Reservar", 2378 "msg.action.buy": "Comprar orden", 2379 2380 "msg.safeemployee": "Safe Employee", 2381 2382 "msg.hide_media": "Ocultar media", 2383 "msg.calendar_date": "Fecha para el calendario", 2384 2385 "msg.scheduler.minutely": "Por minutos", 2386 "msg.scheduler.hourly": "Por horas", 2387 "msg.scheduler.daily": "Diario", 2388 "msg.scheduler.weekly": "Semanal", 2389 "msg.scheduler.monthly": "Mensual", 2390 "msg.scheduler.yearly": "Anual", 2391 "msg.scheduler.advanced": "Avanzado", 2392 "msg.scheduler.every": "Cada", 2393 "msg.scheduler.on": "en el", 2394 "msg.scheduler.onThe": "En el", 2395 "msg.scheduler.at": "a las", 2396 "msg.scheduler.of": "de", 2397 "msg.scheduler.and": "y", 2398 "msg.scheduler.second": "segundo", 2399 "msg.scheduler.seconds": "segundo(s)", 2400 "msg.scheduler.minute": "minuto", 2401 "msg.scheduler.minutes": "minuto(s)", 2402 "msg.scheduler.hour": "hora", 2403 "msg.scheduler.hours": "hora(s)", 2404 "msg.scheduler.day": "dÃa", 2405 "msg.scheduler.days": "dÃa(s)", 2406 "msg.scheduler.month": "mes", 2407 "msg.scheduler.months": "mes(es)", 2408 "msg.scheduler.weekDay": "dÃa de la semana (Lunes a Viernes)", 2409 "msg.scheduler.dayOfWeek.MON": "Lunes", 2410 "msg.scheduler.dayOfWeek.TUE": "Martes", 2411 "msg.scheduler.dayOfWeek.WED": "Miércoles", 2412 "msg.scheduler.dayOfWeek.THU": "Jueves", 2413 "msg.scheduler.dayOfWeek.FRI": "Viernes", 2414 "msg.scheduler.dayOfWeek.SAT": "Sábado", 2415 "msg.scheduler.dayOfWeek.SUN": "Domingo", 2416 "msg.scheduler.cronExpression": "Expresion cron",
2417 "msg.scheduler.cronExpressionDetails": "Puede encontrar más detalles sobre como crear estas expresiones", 2418 "msg.scheduler.here": "aquÃ", 2419 "msg.scheduler.monthDay.1W": "Primer dÃa de la semana", 2420 "msg.scheduler.monthDay.LW": "Ãltimo dÃa de la semana", 2421 "msg.scheduler.monthDay.L": "Ãltimo dÃa", 2422 "msg.scheduler.monthWeek.#1": "Primer", 2423 "msg.scheduler.monthWeek.#2": "Segundo", 2424 "msg.scheduler.monthWeek.#3": "Tercero", 2425 "msg.scheduler.monthWeek.#4": "Cuarto", 2426 "msg.scheduler.monthWeek.#5": "Quinto", 2427 "msg.scheduler.monthWeek.L": "Ãltimo", 2428 "msg.scheduler.month.1": "Enero", 2429 "msg.scheduler.month.2": "Febrero", 2430 "msg.scheduler.month.3": "Marzo", 2431 "msg.scheduler.month.4": "Abril", 2432 "msg.scheduler.month.5": "Mayo", 2433 "msg.scheduler.month.6": "Junio", 2434 "msg.scheduler.month.7": "Julio", 2435 "msg.scheduler.month.8": "Agosto", 2436 "msg.scheduler.month.9": "Septiembre", 2437 "msg.scheduler.month.10": "Octubre", 2438 "msg.scheduler.month.11": "Noviembre", 2439 "msg.scheduler.month.12": "Diciembre", 2440 2441 // FRONT END MESSAGES 2442 "msg.web.whatDo": "¿Qué hacer?", 2443 "msg.web.know": "Conoce", 2444 "msg.web.knowMore": "Conoce más", 2445 "msg.web.destinations": "Destinos", 2446 "msg.web.seeAll": "Ver todos", 2447 "msg.web.seeMore": "Ver más", 2448 "msg.web.select": "¿Dónde quiere ir?", 2449 "msg.web.recommendations": "¿Quieres recomendaciones personalizadas?", 2450 "msg.web.discover": "Descubre nuestros destinos", 2451 "msg.web.filters": "Filtros", 2452 2453 "msg.web.cart": "Carrito de compra", 2454 "msg.web.cart.empty": "Su carrito está vacÃo", 2455 "msg.web.cart.checkout": "Pagar", 2456 "msg.web.cart.validateCard": "Validar tarjeta", 2457 "msg.web.cart.finish": "Finalizar pago", 2458 "msg.web.cart.continue": "Continuar comprando", 2459 "msg.web.cart.done.desc": "Su pedido ha sido procesado correctamente.", 2460 "msg.web.cart.contact": "Contacto", 2461 "msg.web.cart.identity.guest": "Tramitar compra como invitado", 2462 "msg.web.cart.identity.user": "Tramitar compra con su cuenta", 2463 2464 "msg.web.plan": "Crear agenda", 2465 "msg.web.plan.new": "Nuevo", 2466 "msg.web.plan.people": "¿Quién viaja?", 2467 "msg.web.plan.types": "¿Lo visitó anteriormente?", 2468 "msg.web.plan.location": "Ubicación", 2469 "msg.web.plan.categories": "Preferencias", 2470 "msg.web.plan.dates": "Fechas", 2471 "msg.web.plan.results": "Ver resultados", 2472 2473 "msg.web.agenda": "Mi Agenda", 2474 "msg.web.agenda.open": "Abierto", 2475 "msg.web.agenda.duration": "Duración", 2476 "msg.web.agenda.noResults": "No se han encontrado resultados", 2477 2478 "msg.web.footer": "Powered by GEO®" 2479 } 2480 2481 } 2482 2483} 2484 2485//// File constants.js //// 2486var $constants = {}; 2487 2488// TODO save data in database? 2489$constants.clean = function() { 2490 $constants.entityList = {}; 2491 $constants.data = {}; // getData (min) 2492 $constants.dataRaw = {}; // getDataRaw (all) 2493 $constants.names = {}; 2494 $constants.categoryList = {}; 2495 $constants.entities = null; // getEntities 2496}; 2497$constants.clean(); // init 2498 2499$constants.removeFromCache = function(entity, entityId) { 2500 if (entity == 'entity') { 2501 delete $entity.metas[entityId]; 2502 } else if (entity == 'category') { 2503 // TODO 2504 } 2505 delete $constants.names[entityId]; 2506 delete $constants.data[entityId]; 2507 delete $constants.dataRaw[entityId]; 2508}; 2509 2510 2511// Constants 2512$constants.blank = "--blank--"; 2513 2514$constants.formatDay = 'dd MMM yyyy'; 2515$constants.formatDayTime = 'dd/MM/yyyy - HH:mm'; 2516 2517$constants.noIds = ['new', 'multiple', 'multiple-locations', 'auto']; 2518 2519$constants.languages = ['en', 'es']; // , 'fr' 2520 2521$constants.productList = ["safeemployee", "time-and-attendance", "microsoft-accounts"]; 2522 2523//$constants.templateList = { 2524// 'default': "msg.default" 2525//}; 2526 2527$constants.daysList = { 2528 0: "day.sunday", 2529 1: "day.monday", 2530 2: "day.tuesday", 2531 3: "day.wednesday", 2532 4: "day.thursday", 2533 5: "day.friday", 2534 6: "day.saturday" 2535}; 2536 2537$constants.enabledList = { 2538 'true': "msg.yes", 2539 'false': "msg.no" 2540}; 2541 2542$constants.rolesList = { 2543 'super': "role.super", 2544 'admin': "role.admin", 2545 'coordinator': "role.coordinator", 2546 'basic': "role.basic" 2547}; 2548 2549$constants.rolesList2 = { 2550 'super': "role.super", 2551 'admin': "role.admin", 2552 'coordinator': "role.coordinator" 2553}; 2554 2555$constants.uses = { 2556 100: "100%", 2557 75: "75%", 2558 50: "50%", 2559 25: "25%", 2560 0: "msg.notUsed" 2561}; 2562 2563$constants.ratings = { 2564 "100": "100%", 2565 "75": "75%", 2566 "50": "50%", 2567 "25": "25%", 2568 "0": "0%", 2569 "-": "msg.forbidden" 2570}; 2571 2572$constants.menuTargets = { 2573 'folder': 'msg.section', 2574 'entity': 'msg.entity.type', 2575 'instance': 'msg.instance', 2576 'my_smart': 'msg.my_smart', 2577 'new_smart': 'msg.new_smart', 2578 'my_account': 'msg.user.account', 2579 'my_qr': 'msg.user.qr', 2580 'link': 'msg.link' 2581}; 2582 2583// home item types
2584$constants.itemTypes = { 2585 'default': 'Full text', 2586 'full_image': 'Full image', 2587 'column': 'Vertical image/text', 2588 'preview': 'Preview', 2589 'carousel': 'Carousel', 2590 'preview-carousel': 'Preview carousel', 2591 'gallery': 'Gallery', 2592 'form': 'Form', 2593 'formview': 'Formview', 2594 'video': 'Video', 2595 'youtube': 'Youtube', 2596 'instagram': 'Instagram', 2597 'pure_html': 'Pure HTML', 2598 'dashboard': 'Dashboard', 2599 'empty': 'Empty' 2600}; 2601 2602$constants.userActions = { 2603 'login': 'msg.action.login', 2604 'logout': 'msg.action.logout', 2605 'licenses': 'msg.action.licenses', 2606 'download': 'msg.action.download', 2607 'location': 'msg.action.location', 2608 'prize': 'msg.action.prize', 2609 'qr': 'msg.action.qr', 2610 'details': 'msg.action.details', 2611 'favorite': 'msg.action.favorite', 2612 'checkin': 'msg.action.checkin', 2613 'rate': 'msg.action.rate', 2614 'comment': 'msg.action.comment', 2615 'play_audio': 'msg.action.play_audio', 2616 'share_media': 'msg.action.share_media', 2617 'smart': 'msg.action.smart', 2618 'smart_create': 'msg.action.smart_create', 2619 'smart_add': 'msg.action.smart_add', 2620 'smart_remove': 'msg.action.smart_remove', 2621 'smart_move': 'msg.action.smart_move', 2622 'smart_move_to_day': 'msg.action.smart_move_to_day', 2623 'trivia_answer': 'msg.action.trivia_answer', 2624 'trivia_results': 'msg.action.trivia_results', 2625 'survey': 'msg.action.survey', 2626 'book': 'msg.action.book', 2627 'cart': 'msg.action.buy', 2628 'buy': 'msg.action.buy' 2629}; 2630 2631// home item actions 2632$constants.itemActions = { 2633 'entity': 'msg.instance.entity', 2634 'link': 'msg.link', 2635 'my_smart': 'msg.my_smart', 2636 'new_smart': 'msg.new_smart' 2637}; 2638$constants.itemAlignment = { 2639 'left': 'left', 2640 'center': 'center', 2641 'right': 'right' 2642}; 2643 2644$constants.entityTypes = { 2645 "entity": "msg.app_object", 2646 "listing": "msg.listing", 2647 "system": "msg.system" 2648}; 2649 2650// custom inner objects 2651$constants.bindingList = { 2652 "geo_user": "msg.user", 2653 "geo_location": "msg.location", 2654 "geo_fence": "msg.geofence", 2655 "geo_schedule": "msg.schedule", 2656 "geo_trivia": "msg.trivia", 2657 "geo_prize": "msg.prize", 2658 "geo_form": "msg.form", 2659 "geo_buy": "msg.buy", 2660 "geo_calendar": "msg.calendar" 2661}; 2662 2663// entity checks 2664$constants.entityOptions = [ 2665 'create_simple', 'attach_documents', 'show_properties', 'show_key_values', 'hide_media', 'display_table', 'display_table_web', 2666 'home_super', 'home_instance', 'auto_location', 'duplicate_copy', 2667 'one_item', 'readonly', 'modeler', 'lazyformulas' ]; 2668 2669$constants.entitySecurity = [ 2670 'read', 'create', 'update', 'delete', 'no_instance_required', 'no_user_required', 'myaccount', 'mycart' ]; 2671 2672$constants.editTabs = [ 2673 'geo-admin', 'geo-buy', 'geo-location', 'geo-schedule', 'geo-trivia', 'geo-prize', 'geo-categories', 2674 'geo-smart-rate', 'geo-translations', 'geo-actions' ]; 2675 2676$constants.inheritances = [ 'no_instance', 'current', 'children', 'parents', 'parents_children', 'all_related_instances' ]; 2677 2678// column checks 2679$constants.columnChecks = [ 2680 'default', 'tab', 'display', 'search', 2681 'autosave', 'long', 'nolabel', 'unique', 2682 'required', 'readonly', 'updatable', 'hidden', 'unexposed', 2683 'html', 'uppercase', 'calendar', 'sort', 'lazyformula', 2684 'user', 'super', 'admin', 'admincreate' ]; 2685 2686$constants.columnChecksValue = [ 2687 'classes', 'size', 'default_value', 'minlength', 'maxlength', 'pattern', 'min', 'max', 'condition' ]; 2688 2689$constants.columnTypeList1 = { 2690 "string":"format_bold", 2691 "string_list":"format_size", 2692 "text":"translate", 2693 "number":"numbers", 2694 "boolean":"check_box", 2695 "boolean_int":"check_box", 2696 "enum_list":"library_add_check", 2697 "enum":"radio_button_checked", 2698 "select":"filter_list", 2699 "date":"event", 2700 "time":"access_time", 2701 "datetime":"update", 2702 "money":"attach_money", 2703 "percentage":"looks_5", 2704 "email":"email", 2705 "phone":"phone", 2706 "password":"password", 2707 "password_raw":"password", 2708 "color":"format_color_fill", 2709 "cron":"edit_calendar", 2710 "json":"code", 2711 "css":"code", 2712 "image":"image", 2713 "video":"play_circle", 2714 "audio":"audiotrack", 2715 "document":"upload_file", 2716 "any":"help_center", 2717}; 2718$constants.columnTypeList2 = { 2719 "entity":"description", 2720 "inner_entity":"description", 2721 "relation_entity":"description", 2722 "any_entity":"description", 2723 2724 "list":"library_books", 2725 "inner_entity_list":"library_books", 2726 "relation":"library_books", 2727 "any_entity_list":"library_books", 2728 2729 "formula":"calculate", 2730 "table":"grid_on", 2731}; 2732$constants.columnTypeList3 = { 2733 "group":"group_work", 2734 "button":"smart_button", 2735 "link":"link", 2736 "map":"place", 2737 "chart":"bar_chart", 2738 "categories":"list", 2739 "geo_schedule":"date_range", 2740 "geo_properties":"notes", 2741 "message":"title", 2742 "h1":"title", 2743 "h2":"title", 2744 "h3":"title", 2745 "h4":"title", 2746 "h5":"title", 2747 "blank":"check_box_outline_blank", 2748}; 2749$constants.columnTypeListForm = { 2750 "ui_image":"collections", 2751 "ui_video":"video_library", 2752 "ui_audio":"library_music", 2753 "ui_document":"content_copy", 2754 "ui_relation":"library_books", 2755 "timetables":"date_range", 2756// "schedules":"date_range", 2757 "booking":"event", 2758 "buy":"shopping_cart",
2759}; 2760 2761$constants.propertyTypes = { 2762 'section': 'msg.section', 2763 'string': 'msg.property.type.text', 2764 'link': 'msg.property.type.link', 2765 'boolean': 'msg.property.type.boolean', 2766 'number': 'msg.property.type.number', 2767 'color': 'msg.property.type.color', 2768 'asin': 'msg.property.type.asin' 2769}; 2770 2771$constants.buttonActionList = { 2772 "save": "msg.save", 2773 "reset": "msg.reset", 2774 "back": "msg.back", 2775 "link": "msg.link", 2776 "set_value": "msg.set_value", 2777 "move": "msg.move", 2778 "copy": "msg.copy", 2779 "copy_to_column": "msg.copy_to_column", 2780 "download": "msg.download", 2781 "print": "msg.print", 2782 "datetime": "msg.datetime", 2783 "smarter": "msg.smarter", 2784 "notify": "msg.notify", 2785 "sync": "msg.sync", 2786 "change_status": "msg.change_status", 2787 "trigger": "msg.trigger", 2788 "actions": "msg.multiActions" 2789}; 2790 2791$constants.getEntityList = function(type, search, add, omitInstances, limit, query, addEmpty) { 2792 2793 if ($utils.isBlank(type)) { 2794 return; 2795 } 2796 if (typeof type != 'string') { 2797 $angular.log("[getEntityList] " + type + " is not string") 2798 return; 2799 } 2800 2801 if (type === "entity" && $instance.current && $instance.current.entityList) { 2802 var isInstance = $angular.contentScope && $angular.contentScope.entity === 'instance'; 2803 if (!isInstance || !$user.isSuper()) { 2804 var list = $instance.current.entityList; 2805 if (search) { 2806 list = list.filter(function(a) { 2807 var name = $entity.displayColumn(a); 2808 return name && name.toLowerCase().contains(search); 2809 }); 2810 } 2811 list.sort(function(a, b) { 2812 var n1 = $entity.displayColumn(a); 2813 var n2 = $entity.displayColumn(b); 2814 if (n1 < n2) { 2815 return -1; 2816 } 2817 if (n1 > n2) { 2818 return 1; 2819 } 2820 return 0; 2821 }); 2822 $constants.entityList[type] = list; 2823 return; 2824 } 2825 } 2826 2827 var index = 0; 2828 var loading = null; 2829 if (add && $constants.entityList[type]) { 2830 index = $constants.entityList[type].length - 1; 2831 loading = 'generic'; 2832 } 2833 if (limit === undefined || limit === null) { 2834 limit = 250; 2835 } 2836 var paramSearch = ""; 2837 if (!$utils.isBlank(search)) { 2838 paramSearch = "&_q=" + $utils.removeDiacritics(search.toLowerCase()); 2839 } 2840 if (omitInstances) { 2841 paramSearch += "&_omit_instances=true"; 2842 } 2843 if (query) { 2844 paramSearch += "&" + query; 2845 } 2846 var url; 2847 if (!$constants.isWeb) { 2848 url = contextPath + "/api/geo/" + type + "/a/light.json?_limit=" + limit + "&_index=" + index + paramSearch; 2849 } else { 2850 url = contextPath + "/www/geo/" + type + "/a/light.json?_limit=" + limit + "&_index=" + index + paramSearch; 2851 } 2852 return $rest.get({url: url, loading: loading}).then(function(list) { 2853 2854 for (var k in list) { 2855 var item = list[k]; 2856 $constants.names[item.id] = $constants.getEntityDesc(type, item); 2857 } 2858 2859 if (add && $constants.entityList[type]) { 2860 $constants.entityList[type].pop(); 2861 $constants.entityList[type] = $constants.entityList[type].concat(list); 2862 } else { 2863 $constants.entityList[type] = list; 2864 if (addEmpty && $utils.isBlank(search)) { 2865 $constants.entityList[type].unshift({id: $constants.blank, name: $constants.blank}); 2866 } 2867 } 2868 if (list.length === 50) { 2869 $constants.entityList[type].push({id: null, name: '...'}); 2870 } 2871 return $constants.entityList[type]; 2872 2873 }, function(o) { 2874 var status = 0; 2875 if (o && o.response && o.response.status) { 2876 status = o.response.status; 2877 } 2878 if (status != 401 && status != 403) { 2879 //$init.logError('Failed load entities ' + type + ' - status ' + status); 2880 } 2881 2882 if (status > 500) { 2883 // can be deploying -> retry 2884 $constants.getEntityList(type, search, add, omitInstances, limit, query, addEmpty); 2885 } 2886 }); 2887}; 2888 2889$constants.getDataListMin = function(entity, query, index, limit, omitInstances) { 2890 var paramSearch = ""; 2891 if (query) { 2892 paramSearch += "&" + query; 2893 } 2894 if (omitInstances) { 2895 paramSearch += "&_omit_instances=true"; 2896 } 2897 var url; 2898 if (!$constants.isWeb) { 2899 url = contextPath + "/api/geo/" + entity + "/a/light.json?_limit=" + limit + "&_index=" + index + paramSearch; 2900 } else { 2901 url = contextPath + "/www/geo/" + entity + "/a/light.json?_limit=" + limit + "&_index=" + index + paramSearch; 2902 } 2903 return $rest.get({ 2904 url: url 2905 }).then(function(list) { 2906 list.forEach(function(o) { 2907 $constants.data[o.id] = o; 2908 }); 2909 return list; 2910 }); 2911}; 2912 2913$constants.getEntityDesc = function(entity, item) { 2914 2915 if ($utils.isBlank(item)) { 2916 return ""; // no warning 2917 } 2918 var $translate = $angular.get("$translate"); 2919 if (item.name === "...") { 2920 return '<em>-- ' + $translate.instant("msg.showMoreOptions") + ' --</em>'; 2921 } 2922 2923 if (typeof item != 'string') { 2924 2925 if ($utils.isArray(item)) { 2926 var result = []; 2927 for (var k in item) { 2928 var r = $entity.displayColumn(item[k]); 2929 if (!$utils.isBlank(r)) { 2930 result.push(r); 2931 } 2932 } 2933 return $utils.join(result, ", "); 2934 } 2935 2936 if (item.id) { 2937 var val = $entity.displayColumn(item); 2938 if (!$utils.isBlank(val)) { 2939 return val; 2940 } 2941 item = item.id; 2942 2943 } else if (item._id) { 2944 item = item._id; 2945 } 2946 if (typeof item == 'number') { 2947 item = "" + item; 2948 } 2949 if (typeof item != 'string') { 2950 console.log('[getEntityDesc] bad arguments: ' + entity, item); 2951 //$angular.log('[getEntityDesc] bad arguments: ' + entity + " - type:" + JSON.stringify(item), item); 2952 //return "bad_arguments"; 2953 return ""; 2954 } 2955 } 2956 if ($utils.isBlank(item)) { 2957 return ""; 2958 } 2959 if ($utils.isBlank(entity)) { 2960 return item; 2961 } 2962 if (item.contains("/")) { 2963 return item + "*"; 2964 } 2965 2966 var value = $constants.names[item]; 2967 if (value) { 2968 //console.log(entity + ":" + item + " => " + value) 2969 return value; 2970 } 2971 2972 var dat = $constants.data[item]; 2973 if (dat) { 2974 value = $entity.displayColumn(dat); 2975 if (!$utils.isBlank(value)) { 2976 $constants.names[item] = value; 2977 return value; 2978 } 2979 } 2980 2981 if (entity === "entity") { 2982 if (item === "entity") { 2983 value = $translate.instant("msg.entity"); 2984 $constants.names[item] = value; 2985 return $utils.parse(value); 2986 } 2987 if (item === "trash") { 2988 value = $translate.instant("msg.trash"); 2989 $constants.names[item] = value; 2990 return value; 2991 } 2992 if (item === "ips") { 2993 value = $translate.instant("msg.ips"); 2994 $constants.names[item] = value; 2995 return value; 2996 } 2997 2998 if (!$instance.hasToRefresh) { 2999 value = $instance.getEntityName(item); 3000 } 3001 if (!$utils.isBlank(value)) { 3002 $constants.names[item] = value; 3003 return $utils.parse(value); 3004 } 3005 } 3006 if (entity === "category") { 3007 value = $instance.getCategoryName(item); 3008 if (!$utils.isBlank(value)) { 3009 $constants.names[item] = value; 3010 return $utils.parse(value); 3011 } 3012 } 3013 if ($constants.names[item] != null) { // multiple requests and empty results 3014 return; 3015 } 3016 3017 // get data by item 3018 $constants.names[item] = ""; 3019 //console.log('getting ' + entity + " - " + item) 3020 var url; 3021 if (!$constants.isWeb) { 3022 url = contextPath + "/api/geo/" + entity + "/" + item + "/name.json"; 3023 } else { 3024 url = contextPath + "/www/geo/" + entity + "/" + item + "/name.json"; 3025 } 3026 $rest.get({url: url, showError: false}).then(function(o) { 3027 //console.log('get ' + entity+"."+item, o) 3028 if ($utils.isBlank(o)) o = item; // "" TODO show id if empty for selects? 3029 $constants.names[item] = o; 3030 3031 }, function(o) { 3032 3033 var status = 0; 3034 if (o && o.response && o.response.status) { 3035 status = o.response.status; 3036 } 3037 3038 if (status > 500) { 3039 // can be deploying -> retry 3040 delete $constants.names[item]; 3041 return undefined; // to avoid in deploys 3042 } 3043 3044 // unknown error -> end 3045 $constants.names[item] = item + " (" + status + ")"; 3046 }); 3047 3048 return undefined; 3049}; 3050 3051$constants.isDisabled = function(entity, item) { 3052 var enabled = $constants.isEnabled(entity, item); 3053 if (enabled === undefined) { 3054 return undefined; 3055 } 3056 return !enabled; 3057}; 3058 3059$constants.isEnabled = function(entity, item) { 3060 if (item === undefined) { 3061 return true; 3062 } 3063 if ($utils.isBlank(entity) || $utils.isBlank(item) || typeof item != 'string') { 3064 //$angular.log('[isEnabled] bad arguments: ' + entity + " - type:" + (typeof item), item); 3065 return false;
3066 } 3067 var dat = $constants.getDataMin(entity, item); 3068 if (dat) { 3069 return !!dat.enabled; 3070 } 3071 return undefined; 3072}; 3073 3074$constants.getEntityListDesc = function(entity, list) { 3075 var cats = []; 3076 if (list) { 3077 for (var key in list) { 3078 var item = $constants.getEntityDesc(entity, list[key]); 3079 if (item == undefined) { 3080 return undefined; 3081 } 3082 if (item) { 3083 cats.push(item); 3084 } 3085 } 3086 } 3087 return $utils.join(cats, ", "); 3088}; 3089 3090$constants.getEntityDescAsPromise = function(entity, item, counter) { 3091 var deferred = $angular.get('$q').defer(); 3092 var entityDesc = $constants.getEntityDesc(entity, item); 3093 if (entityDesc === undefined) { 3094 if (counter === 10) { 3095 return deferred.reject(); 3096 } 3097 var next = counter ? (counter + 1) : 1; 3098 setTimeout(function() { 3099 $constants.getEntityDescAsPromise(entity, item, next).then(function(result) { 3100 deferred.resolve(result); 3101 }); 3102 }, 200); 3103 } else { 3104 deferred.resolve(entityDesc); 3105 } 3106 return deferred.promise; 3107}; 3108 3109$constants.getDefaultColumnRaw = function(entity, id, callback) { 3110 var url = contextPath + "/api/geo/" + entity + "/" + id + "/nameRaw.json"; 3111 $rest.get({url: url, showError: false}).then(function(o) { 3112 callback(o); 3113 }); 3114}; 3115 3116$constants.getCategoryList = function(type, search, add, all) { 3117 if (search == undefined) { 3118 search = ''; 3119 } 3120 var index = 0; 3121 var loading = null; 3122 if (add && $constants.categoryList[type]) { 3123 index = $constants.categoryList[type].length - 1; 3124 loading = 'generic'; 3125 } 3126 var limit = "50"; 3127 if (all) { 3128 limit = "0"; 3129 } 3130 var url; 3131 if (!$constants.isWeb) { 3132 url = contextPath + "/api/geo/category/a/light.json"; 3133 } else { 3134 url = contextPath + "/www/geo/category/a/light.json"; 3135 } 3136 url += "?_limit=" + limit + "&=50&_index=" + index + "&_order=name&_q=" 3137 + $utils.removeDiacritics(search.toLowerCase()) + "&enabled=true&entities=" + type; 3138 $rest.get({url: url, loading: loading}).then(function(list) { 3139 if (add && $constants.categoryList[type]) { 3140 $constants.categoryList[type].pop(); 3141 $constants.categoryList[type] = $constants.categoryList[type].concat(list); 3142 } else { 3143 $constants.categoryList[type] = list; 3144 } 3145 if (list.length == 50) { 3146 $constants.categoryList[type].push({id: null, name: '...'}); 3147 } 3148 }, function(o) { 3149 var status = 0; 3150 if (o && o.response && o.response.status) { 3151 status = o.response.status; 3152 } 3153 //$init.logError('Failed load categories ' + type + " - error " + status); 3154 3155 if (status > 500) { 3156 // can be deploying -> retry 3157 $constants.getCategoryList(type, search, add, all); 3158 } 3159 }); 3160}; 3161 3162$constants.getCategoryListDesc = function(list) { 3163 var cats = []; 3164 if (list) { 3165 if (typeof list == "string") { 3166 return $constants.getEntityDesc('category', list); 3167 } 3168 if (!$utils.isArray(list)) { 3169 return ""; 3170 } 3171 for (var key in list) { 3172 var item = $constants.getEntityDesc('category', list[key]); 3173 if (item == undefined) { 3174 return undefined; 3175 } 3176 if (item && item != list[key]) { 3177 cats.push(item); 3178 } 3179 } 3180 } 3181 return $utils.join(cats, ", "); 3182}; 3183 3184//$constants.getEntities = function() { 3185// if ($constants.entities != null) { 3186// return $constants.entities; 3187// } 3188// if ($instance.getId() != null) { 3189// var list = $utils.clone($instance.getEntityList()); 3190// list.unshift({id: 'entity', name: $angular.get("$translate").instant("msg.entity")}); 3191// $constants.entities = list; 3192// return $constants.entities; 3193// } 3194// $constants.entities = []; 3195// var url = contextPath + "/api/geo/entity/a/light.json"; 3196// $rest.get({url: url}).then(function(list) { 3197// var list = $utils.cloneList(list); 3198// list.unshift({id: 'entity', name: $angular.get("$translate").instant("msg.entity")}); 3199// $constants.entities = list; 3200// }, function(o) { 3201// 3202// var status = 0; 3203// if (o && o.response && o.response.status) { 3204// status = o.response.status; 3205// } 3206// //$init.logError('Failed load entities for columns - error ' + status); 3207// 3208// if (status > 500) { 3209// // can be deploying -> retry 3210// $constants.getEntities(); 3211// } 3212// }); 3213// return $constants.entities; 3214//}; 3215 3216$constants.getDataMin = function(entity, id, callback) { 3217 var o = $constants.data[id]; 3218 if (o) { 3219 if (o.id == null) { 3220 return null; 3221 } 3222 if (callback) { 3223 callback(o); 3224 } 3225 return o; 3226 } 3227 3228 $constants.data[id] = {}; // to avoid multiple requests 3229 3230 //console.log('getting entity ' + entity + " " + id); 3231 var url; 3232 if (!$constants.isWeb) { 3233 url = contextPath + '/api/geo/'+entity+'/' + id + '/min.json'; 3234 } else { 3235 url = contextPath + '/www/geo/'+entity+'/' + id + '/min.json'; 3236 } 3237 if ($instance.current) { 3238 url += '?geo_instance='+$instance.getId(); 3239 } 3240 $rest.get({ 3241 url: url, 3242 showError: false 3243 }).then(function(o) { 3244 $constants.data[o.id] = o; 3245 if (callback) { 3246 callback(o); 3247 } 3248 }, function(o) { 3249 var status = 0; 3250 if (o && o.response && o.response.status) { 3251 status = o.response.status; 3252 } 3253 if ($constants.names[id] == null) { 3254 $constants.names[id] = id + " (" + status + ")"; 3255 } 3256 if (callback) { 3257 callback(null); 3258 } 3259 }); 3260 return null; 3261}; 3262 3263$constants.getDataRaw = function(entity, id, callback) { 3264 var o = $constants.dataRaw[id]; 3265 if (o) { 3266 if (o.id == null) { 3267 return null; 3268 } 3269 if (callback) { 3270 callback(o); 3271 } 3272 return o; 3273 } 3274 3275 $constants.dataRaw[id] = {}; // to avoid multiple requests 3276 3277 //console.log('getting entity ' + entity); 3278 var url; 3279 if (!$constants.isWeb) { 3280 url = contextPath + '/api/geo/'+entity+'/' + id + '.json'; 3281 } else { 3282 url = contextPath + '/www/geo/'+entity+'/' + id + '.json'; 3283 } 3284 if ($instance.current) { 3285 url += '?geo_instance='+$instance.getId(); 3286 } 3287 $rest.get({ 3288 url: url, 3289 showError: false 3290 }).then(function(o) { 3291 $constants.dataRaw[o.id] = o; 3292 if (callback) { 3293 callback(o); 3294 } 3295 }); 3296 return null; 3297}; 3298 3299//// File rest.js //// 3300var $rest = {}; 3301 3302$rest.fetchAPI = false; // TODO bug safari with cookies 3303//console.log('fetchAPI: ' + $rest.fetchAPI) 3304 3305$rest.version = appVersion; 3306 3307$rest.get = function(params) { 3308 params = $.extend(params, { method:"GET" }); 3309 return $rest.request(params); 3310}; 3311 3312$rest.post = function(params) { 3313 params = $.extend(params, { method:"POST" }); 3314 return $rest.request(params); 3315}; 3316 3317$rest.put = function(params) { 3318 params = $.extend(params, { method:"PUT" }); 3319 return $rest.request(params); 3320}; 3321 3322$rest.remove = function(params) { 3323 params = $.extend(params, { method:"DELETE" }); 3324 return $rest.request(params); 3325}; 3326 3327$rest.options = function(params) { 3328 params = $.extend(params, { method:"OPTIONS" });
3329 return $rest.request(params); 3330}; 3331 3332$rest.request = function(params) { 3333 3334 if (params == null) { 3335 params = {}; 3336 } 3337 if (params.skipHideLoading) { 3338 $angular.rootScope.skipHideLoading = true; 3339 } 3340 3341 var defer = $angular.get("$q").defer(); 3342 params.defer = defer; 3343 3344 if (params.confirmTitle || params.confirmText) { 3345 3346 // with confirm panel 3347 $rest.openConfirmPanel(params.confirmTitle, params.confirmText, 3348 function() { $rest.execute(params); }, params.cancelFunction); 3349 3350 } else { 3351 // without confirm panel 3352 $rest.execute(params); 3353 } 3354 3355 return defer.promise; 3356}; 3357 3358$rest.requests = new Array(); 3359 3360$rest.execute = function(params) { 3361 3362 if (params.method == undefined || params.method == "") { 3363 throw "The parameter 'method' is required."; 3364 } 3365 if (params.url == undefined || params.url == "") { 3366 throw "The parameter 'url' is required."; 3367 } 3368 if (params.showError == undefined) { 3369 params.showError = true; 3370 } 3371 3372 // control multiple same request TODO can generate no responses... 3373 if (!$utils.isTrue(params.force)) { 3374 if ($rest.requests.indexOf(params.url) != -1) { 3375 return; 3376 } 3377 $rest.requests.push(params.url); 3378 } 3379 3380 var headers = null; 3381 var data = null; 3382 if (params.noContentType) { 3383 // nothing 3384 headers = params.headers; 3385 3386 } else if (params.contentType == "urlencoded") { 3387 // urlencoded 3388 headers = { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' }; 3389 if (params.data) { 3390 data = $.param(params.data); 3391 } else if (params.form) { 3392 data = $(params.form).serialize(); 3393 } 3394 3395 } else { 3396 // default json 3397 headers = { 'Content-Type': 'application/javascript' }; 3398 if (params.data) { 3399 data = params.data; 3400 } else if (params.form) { 3401 data = $utils.serializeFormJSON($(params.form)); 3402 } 3403 3404 if (params.method == "POST" || params.method == "PUT") { 3405 if ($angular.contentScope && $angular.contentScope.model) { 3406 var model = $angular.contentScope.model; 3407 if (model.entity && model.id && model.sys_updated) { 3408 if (data == null) { 3409 data = {}; 3410 } 3411 data['_sys_updated'] = model.entity + "#" + model.id + "#" + model.sys_updated; 3412 if (data['sys_updated'] != null) { 3413 delete data['sys_updated']; 3414 } 3415 } 3416 } 3417 } 3418 } 3419 if (headers == null) { 3420 headers = {}; 3421 } 3422 if (params.instance) { 3423 headers['From'] = params.instance; 3424 } else if ($instance.current != null) { 3425 headers['From'] = $instance.getId(); 3426 } 3427 //headers['ALLOW-FROM'] = "www"; 3428 headers['ALLOW-FROM'] = ""+window.location.href; 3429 3430 if (params.loading || params.skipHideLoading) { 3431 $utils.showLoading(params.loading); 3432 } 3433 3434 if (!$rest.fetchAPI) { 3435 var configHttp = { 3436 method : params.method, 3437 url : params.url, 3438 data : data, 3439 headers : headers 3440 }; 3441 if (params.responseType) { 3442 configHttp.responseType = params.responseType; 3443 } 3444 $angular.get("$http")(configHttp).then(function(response) { 3445 $rest.processResult(params, response); 3446 }, function(response) { 3447 $rest.processResult(params, response); 3448 }); 3449 return; 3450 } 3451 3452 if (data && typeof data != 'string') { 3453 data = angular.toJson(data); 3454 } 3455 3456 //console.log(params.url, data) 3457 fetch(params.url, { 3458 method: params.method, 3459 headers: headers, 3460 body: data 3461 }).then(function(response) { 3462 $rest.processData(params, response); 3463 }).catch(function(e) { 3464 //console.log('Error get data ' + params.url, e); 3465 $rest.processResult(params, { status:0 }); 3466 }); 3467 3468}; 3469 3470$rest.processData = function(params, response) { 3471 3472 if (response.status > 0) { 3473 var contentType = $rest.getHeader(response, "content-type"); 3474 if (contentType == 'application/json') { 3475 response.json().then(function(data) { 3476 response.data = data; // save in response 3477 $rest.processResult(params, response); 3478 }).catch(function() { 3479 $rest.processResult(params, response); 3480 }); 3481 } else { 3482 response.text().then(function(data) { 3483 response.data = data; // save in response 3484 $rest.processResult(params, response); 3485 }).catch(function() { 3486 $rest.processResult(params, response); 3487 }); 3488 } 3489 return; 3490 } 3491 3492 $rest.processResult(params, response); 3493} 3494 3495$rest.processResult = function(params, response) { 3496 3497 if (response == null || response.status == null) { 3498 response = { status:0 }; 3499 } 3500 3501 var data = response.data; 3502 //console.log('> ' + response.status + " " + params.url, data) 3503 3504 if (data && data._logs) { 3505 //$angular.consoleScope.consoleList = ""; // clear logs
3506 $angular.consoleScope.addLog(data._logs); 3507 delete data._logs; 3508 } 3509 3510 if (params.skipHideLoading) { 3511 $angular.rootScope.skipHideLoading = false; // to skip not found location pages after loaded 3512 } 3513 if (params.loading || params.skipHideLoading) { 3514 $utils.hideLoading(params.loading); 3515 } 3516 3517 var v1 = $rest.version; 3518 var v2 = $rest.getHeader(response, "version"); 3519 if (!$utils.isBlank(v2) && v2 > v1) { 3520 console.log('new version: ' + v1 + " -> " + v2) 3521 $rest.version = v2; 3522 3523 $angular.get("$timeout")(function() { 3524 if ('serviceWorker' in navigator && navigator.serviceWorker.controller) { 3525 navigator.serviceWorker.controller.postMessage({key: 'new_version'}) 3526 } 3527 console.log('show new version panel: ' + $rest.showNewVersion) 3528 if ($rest.showNewVersion) { 3529 setTimeout(function() { 3530 $rest.openConfirmPanel("msg.new.version", "msg.new.version.desc", function() { 3531 window.location.reload(); 3532 }); 3533 }, 1000); // TODO wait to precache 3534 } 3535 }, 1000); 3536 } 3537 3538 if (!$utils.isTrue(params.force)) { 3539 // remove the doble submit control 3540 $rest.requests.splice($rest.requests.indexOf(params.url), 1); 3541 } 3542 3543 // switch http codes 3544 switch(response.status) { 3545 3546 // success 3547 case 100: case 101: case 102: 3548 case 200: case 201: case 202: case 203: case 204: 3549 case 205: case 206: case 207: 3550 3551 if (params.successMessage != null) { 3552 $utils.floatingMsg(params.successMessage); 3553 } 3554 3555 if (params.fullResponse) { 3556 params.defer.resolve(response); 3557 } else { 3558 var location = $rest.getHeader(response, "location"); 3559 params.defer.resolve(data, location); 3560 } 3561 break; 3562 3563 case 401: 3564 var path = "" + $angular.get("$location").path(); // path is not string??? 3565 var isLoginPage = path.contains('/login'); 3566 if (!isLoginPage && params.showError) { 3567 $angular.tmpPath = path; 3568 $angular.goLogin(); 3569 return; 3570 } 3571 params.defer.reject({msg:'Authentication required', response:response}); 3572 break; 3573 3574 case 403: 3575 var msg = $rest.showError(params, data, $angular.get("$translate").instant("msg.accessDenied")); 3576 params.defer.reject({msg:msg, response:response}); 3577 break; 3578 3579 case 404: 3580 var msg = $rest.showError(params, data, $angular.get("$translate").instant("msg.notFound")); 3581 params.defer.reject({msg:msg, response:response}); 3582 break; 3583 3584 case 0: 3585 case -1: 3586 case null: 3587 case undefined: 3588 var msg = $rest.showError(params, data, $angular.get("$translate").instant("msg.error.noConnection")); 3589 params.defer.reject({msg:msg, response:response}); 3590 break; 3591 3592 // error 3593 default: 3594 var msg = $rest.showError(params, data, null); 3595 params.defer.reject({msg:msg, response:response}); 3596 } 3597 3598}; 3599 3600$rest.getHeader = function(response, header) { 3601 if (response.headers) { 3602 if ($rest.fetchAPI) { 3603 // TODO for .. of error in old versions 3604 var it = response.headers.entries(); 3605 var result = it.next(); 3606 while (!result.done) { 3607 var pair = result.value; 3608 //console.log(pair[0] + " = " + pair[1]) 3609 if (pair[0] === header) { 3610 return pair[1]; 3611 } 3612 result = it.next(); 3613 } 3614 } else { 3615 return response.headers(header); 3616 } 3617 } 3618 return null; 3619}; 3620 3621$rest.showError = function(params, data, defMsg) { 3622 3623 if (data && !$utils.isBlank(data.message)) { 3624 data = $angular.get("$translate").instant(data.message); 3625 } 3626 3627 if (data) { 3628 if (typeof data == "string") { 3629 if (data.contains("502 Bad Gateway")) { 3630 data = $angular.get("$translate").instant("msg.error.502"); 3631 3632 } else if (data.indexOf('<html') != -1) { 3633 $angular.log("Request error: " + params.url + " : " + data); 3634 data = null; 3635 } 3636 } else { 3637 console.log(JSON.stringify(data)); 3638 data = null; 3639 } 3640 } 3641 3642 if (params.showError) { 3643 var msg = ""; 3644 if (!$utils.isBlank(defMsg)) { 3645 msg = defMsg; 3646 } 3647 if (data != null) { 3648 if (msg != "") { 3649 msg += "<br><small>" + data + "</small>"; 3650 } else { 3651 msg = data; 3652 } 3653 } 3654 if ($utils.isBlank(msg)) { 3655 msg = $angular.get("$translate").instant("msg.error"); 3656 } 3657 if (params.skipHideLoading) { 3658 $utils.showAlert(msg); 3659 } else { 3660 $utils.floatingError(msg); 3661 } 3662 } 3663 3664 return data; 3665}; 3666 3667$rest.openConfirmPanel = function(title, text, successFunction, cancelFunction) { 3668 var $translate = $angular.get("$translate"); 3669 $angular.openModal("panel-confirm", { 3670 title: $translate.instant(title), 3671 text: $translate.instant(text), 3672 successFunction: successFunction, 3673 cancelFunction: cancelFunction 3674 }); 3675}; 3676 3677$rest.getFileName = function(response) { 3678 var disposition = $rest.getHeader(response, 'Content-Disposition'); 3679 if (disposition && disposition.indexOf('attachment') !== -1) { 3680 var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; 3681 var matches = filenameRegex.exec(disposition); 3682 if (matches != null && matches[1]) { 3683 return matches[1].replace(/['"]/g, ''); 3684 } 3685 } 3686 return null; 3687}; 3688 3689//// File events.js //// 3690 3691 3692var $events = {}; 3693 3694//$events.lastScrolls = []; 3695 3696$events.refresh = function(resetBacks) { 3697 3698 $angular.get("$timeout")(function() { 3699 3700 // left menu 3701 if (!$constants.isWeb) { 3702 $('#menuToggle').unbind('click').on('click', function() { 3703 $events.toggleMenu(); 3704 }); 3705 } else { 3706 $('#menuToggle, #menu .menu-close, #menu .menu-background, #menu a').unbind('click').on('click', function(){ 3707 $events.toggleMenu(); 3708 }); 3709 } 3710 3711 // esc close panels 3712 $events.manageEsc(); 3713 3714 // reset scroll 3715 window.scrollTo(0, 0); 3716 setTimeout(function() { 3717 window.scrollTo(0, 0); 3718 3719 if ($angular.isBackNavigation) { 3720 $angular.isBackNavigation = false; 3721 var name = window.location.href; 3722 var pos = $angular.positions[name]; 3723 if (pos && pos > 0) { 3724 $events.scrollIfReady(pos, 0); 3725 } 3726 } 3727 }, 100); 3728 3729 }); 3730 3731}; 3732$events.scrollIfReady = function(pos, num) { 3733 if ($angular.ready) { 3734 window.scrollTo(0, pos); 3735 3736 var $window = $angular.get("$window"); 3737 var diff = Math.abs($window.pageYOffset - pos); 3738 //console.log("scrollTo: " + pos + " diff:"+diff); 3739 if (diff < 20) { 3740 return; 3741 } 3742 } 3743 if (num == 20) { 3744 return; 3745 } 3746 setTimeout(function() { 3747 $events.scrollIfReady(pos, num+1); 3748 }, 50); 3749}; 3750 3751//$events.removeLastScroll = function() { 3752// var page = $angular.get('$location').path(); 3753// if ($utils.isBlank(page)) { 3754// return; 3755// } 3756// //console.log('remove scroll ' + page) 3757// $events.lastScrolls[page] = 0; 3758//}; 3759// 3760//$events.manageLastScroll = function() { 3761// 3762// var page = $angular.get('$location').path(); 3763// if ($utils.isBlank(page)) { 3764// return; 3765// } 3766// 3767// var ls = $events.lastScrolls[page]; 3768// if (ls == null) { 3769// ls = 0;
3770// } 3771// //console.log('setting: ' + page + ": " + ls) 3772//// window.scrollTo(0, ls); 3773//// setTimeout(function() { 3774//// window.scrollTo(0, ls); 3775//// }, 100); 3776//// setTimeout(function() { 3777//// window.scrollTo(0, ls); 3778//// }, 150); // masonry has timeout 120 3779//// setTimeout(function() { 3780//// window.scrollTo(0, ls); 3781//// }, 300); // sometimes is taking more time to load 3782//// if (!$constants.isWeb) { 3783//// setTimeout(function() { 3784//// window.scrollTo(0, ls); 3785//// }, 500); // sometimes is taking more time to load 3786//// } 3787// 3788// $events.updateLastScroll(); 3789//}; 3790// 3791//$events.updateLastScroll = function() { 3792// 3793// var page = $angular.get('$location').path(); 3794// if ($utils.isBlank(page)) { 3795// return; 3796// } 3797// 3798// var ww = $angular.get('$window'); 3799// angular.element(window).on('scroll', function(event){ 3800// $events.lastScrolls[page] = ww.pageYOffset; 3801// //console.log(page + ": " + ww.pageYOffset) 3802// }); 3803// 3804// // reset scrolls 3805// if ($angular.currentRoute == "web-home") { 3806// $events.lastScrolls = []; 3807// } 3808// 3809//}; 3810 3811$events.back = function() { 3812 // TODO control no exit 3813 if (window.history.length > 0) { 3814 window.history.back(); 3815 return; 3816 } 3817 $angular.goHome(); 3818}; 3819 3820$events.toggleMenu = function() { 3821 $('#menuToggle').toggleClass('active'); 3822 $('body').toggleClass('body-push-toleft'); 3823 $('#menu').toggleClass('menu-open'); 3824 3825 if (!$constants.isWeb) { 3826 $storageService.put("_menu_open", $('#menu').hasClass("menu-open")); 3827 } 3828}; 3829 3830$events.toggleCartAsMenu = function() { 3831 $('#cartAsMenuToggle').toggleClass('active'); 3832 $('body').toggleClass('body-push-toright'); 3833 $('#cartAsMenu').toggleClass('menu-open'); 3834}; 3835 3836$events.manageEsc = function() { 3837 $(document).unbind('keyup').keyup(function(e) { 3838 if (e.keyCode == 27) { 3839 $events.closeAll(true); 3840 } 3841 }); 3842}; 3843 3844$events.closeAll = function(isUser) { 3845 var scopes = [$angular.contentScope, $angular.rootScope]; 3846 for (var k in scopes) { 3847 var scope = scopes[k]; 3848 if (scope && scope.$$phase) { // controlling digest in progress 3849 setTimeout(function() { 3850 $events.closeAll(isUser); 3851 }, 250); 3852 return; 3853 } 3854 } 3855 if ($(".modal").length > 0) { 3856 $(".modal .close").click(); 3857 } 3858 if ($(".dropdown.open").length > 0) { 3859 $(".dropdown.open > .dropdown-toggle").click(); 3860 } 3861 if ($(".dropdown.show").length > 0) { 3862 $(".dropdown.show > .dropdown-toggle").click(); 3863 } 3864 if ($constants.isWeb) { 3865 if ($("#menu").hasClass("menu-open")) { 3866 $('#menuToggle').click(); 3867 } 3868 } 3869 if ($("#cartAsMenu").hasClass("menu-open")) { 3870 $('#cartAsMenuToggle').click(); 3871 } 3872 if ($("#searchForm button.closeSearch").is(":visible")) { 3873 $("#searchForm button.closeSearch").click(); 3874 } 3875 if ($("#images-fullscreen").is(":visible")) { 3876 $("#images-fullscreen .close").click(); 3877 } 3878 if (isUser) { 3879 if ($(".alert.floating-msg").length > 0) { 3880 $(".alert.floating-msg .close").click(); 3881 } 3882 if ($("#search button.closeSearch").is(":visible")) { 3883 $("#search button.closeSearch").click(); 3884 } 3885 if ($("#console").length > 0) { 3886 $("#console").click(); 3887 } 3888 } 3889}; 3890 3891//// File cart.js //// 3892var $cart = {}; 3893var cartInitialized = false; 3894var cartInitializedCallbacks = []; 3895 3896$cart.initCart = function() { 3897 cartInitialized = false; 3898 $angular.rootScope.cart = null; 3899 if ($constants.isWeb && $instance.hasCart()) { 3900 var anonymousCartId = $cart.getAnonymousCartId(); 3901 var url = contextPath + '/www/cart.json'; 3902 if (anonymousCartId) { 3903 url = contextPath + '/www/cart/' + anonymousCartId + '.json'; 3904 } 3905 var initializedCart = function(o) { 3906 $angular.rootScope.cart = o ? o : {}; 3907 cartInitialized = true; 3908 cartInitializedCallbacks.forEach(function(callback) { 3909 callback(); 3910 }); 3911 cartInitializedCallbacks = []; 3912 $angular.apply($angular.rootScope); 3913 }; 3914 if ($user.isLogged() || $cart.isAllowedAnonymous() || !$cart.isUserRequiredToAddCart()) { 3915 $rest.get({ 3916 url: url, 3917 showError: false 3918 }).then(function(o) { 3919 if (!o || $user.isLogged()) { 3920 $cart.setAnonymousCartId(null); 3921 } 3922 initializedCart(o); 3923 }).catch(function() { 3924 $cart.setAnonymousCartId(null); 3925 initializedCart(null); 3926 }); 3927 } else { 3928 initializedCart(null); 3929 } 3930 } else { 3931 //$angular.log('No instance cart enabled'); 3932 } 3933}; 3934 3935$cart.doWhenCartWasInitialized = function(callback) { 3936 if (cartInitialized) { 3937 callback(); 3938 } else { 3939 cartInitializedCallbacks.push(callback); 3940 } 3941}; 3942 3943$cart.hasItems = function() { 3944 return $cart.getItemsQuantity() > 0; 3945} 3946
3947$cart.getItemsQuantity = function() { 3948 var cart = $cart.get(); 3949 var num = 0; 3950 if (cart) { 3951 for (var i in cart.items) { 3952 var item = cart.items[i]; 3953 num += item.quantity; 3954 } 3955 } 3956 return num; 3957}; 3958 3959$cart.getTotalAmount = function() { 3960 var cart = $cart.get(); 3961 return cart ? cart.amount : null; 3962}; 3963 3964$cart.getItems = function() { 3965 var cart = $cart.get(); 3966 return cart ? cart.items : null; 3967}; 3968 3969$cart.buy = function(e, item) { 3970 $utils.preventDefault(e); 3971 if ($user.isLogged() || !$cart.isUserRequiredToAddCart()) { 3972 3973 var formEntity = item.geo_buy ? item.geo_buy.form_entity : null; 3974 if (formEntity && $entity.isGeoForm(formEntity) && $entity.isPermitted(formEntity, 'create')) { 3975 // open popup to show extra data 3976 $angular.openModal('panel-buy', { 3977 item: item, 3978 cartItem: $cart.getCartItem(item.entity, item.id), 3979 size: item.geo_buy.form_entity ? 'xl' : null 3980 }); 3981 } else { 3982 // add directly to cart 3983 var cartItem = $cart.getCartItem(item.entity, item.id); 3984 if (cartItem == null) { 3985 cartItem = {quantity: 0, extraData: {}}; 3986 } 3987 var hasStock = $cart.hasStock(item, cartItem.quantity); 3988 if (hasStock) { 3989 cartItem.quantity++; 3990 $cart.addItem(item.entity, item.id, cartItem); 3991 } 3992 if (!$angular.element("#cartAsMenu").hasClass("menu-open")) { 3993 $events.toggleCartAsMenu(); 3994 } 3995 } 3996 3997 } else { 3998 $user.openLoginAsPanel(function() { 3999 $cart.buy(e, item); 4000 }); 4001 } 4002}; 4003 4004$cart.getProductPrice = function(item) { 4005 4006 var o = item; 4007 if (item && item.id && item.entity) { 4008 item = item.geo_buy; 4009 } 4010 if (item == null) { 4011 return ""; 4012 } 4013 if ($utils.isTrue(item.free)) { 4014 return '<b>' + $utils.parseGeoTranslation('free', $instance.current, 'msg.free', 'geo_buy') + '</b>'; 4015 } 4016 4017 if (!$cart.hasStock(o)) { 4018 return '<b>' + $utils.parseGeoTranslation('stock_exceeded', $instance.current, 'msg.stock.exceeded', 'geo_buy') + '</b>'; 4019 } 4020 4021 var priceToPrint = $utils.printCurrency($utils.addTaxes(item.price, item.tax)); 4022 if (!item.discount || isNaN(item.discount) || Number(item.discount) === 0) { 4023 return '<b>' + priceToPrint + '</b>'; 4024 } 4025 var newPriceToPrint = $utils.printCurrency($utils.addTaxes(item.price - item.discount, item.tax)); 4026 return '<b class="small tach">' + priceToPrint + '</b>' + ' <b>' + newPriceToPrint + '</b>'; 4027}; 4028 4029$cart.getItemAmount = function(item, currency) { 4030 if (item == null) { 4031 return ""; 4032 } 4033 if ($utils.isTrue(item.free)) { 4034 return "<b>" + $utils.parseGeoTranslation('free', $instance.current, 'msg.free', 'geo_buy') + "</b>"; 4035 } 4036 return $utils.printCurrency(item.amount, currency); 4037}; 4038 4039$cart.externalPaymentScripts = {}; 4040 4041$cart.get = function() { 4042 return $angular.rootScope.cart; 4043}; 4044 4045$cart.reset = function() { 4046 $angular.rootScope.cart = {}; 4047 $cart.setAnonymousCartId(null); 4048 $cart.save(); 4049}; 4050$cart.resetRaw = function() { 4051 $angular.rootScope.cart = {}; 4052 $cart.setAnonymousCartId(null); 4053}; 4054 4055$cart.save = function() { 4056 var url = contextPath + '/www/cart.json'; 4057 if (!$user.isLogged()) { 4058 var anonymousCartId = $cart.getAnonymousCartId(); 4059 if (anonymousCartId) { 4060 url = contextPath + '/www/cart/' + anonymousCartId + '.json'; 4061 } 4062 } 4063 $rest.put({ 4064 url: url, 4065 data: $angular.rootScope.cart, 4066 force: true 4067 }).then(function(o) { 4068 $angular.rootScope.cart = o ? o : {}; 4069 var id = o == null || $user.isLogged() ? null : o.id; 4070 $cart.setAnonymousCartId(id); 4071 $angular.apply($angular.rootScope); 4072 }); 4073}; 4074 4075$cart.pay = function(data) { 4076 var cart = $cart.get(); 4077 return $rest.post({ 4078 url: contextPath + '/www/cart/' + cart.id + '/pay.json', 4079 data: data, 4080 loading: 'generic' 4081 }); 4082}; 4083 4084$cart.complete = function(data) { 4085 var cart = $cart.get(); 4086 return $rest.post({ 4087 url: contextPath + '/www/cart/' + cart.id + '/complete.json', 4088 data: data, 4089 loading: 'generic', 4090 showError: false 4091 }).then(function(order) { 4092 $cart.reset(); 4093 return order; 4094 }).catch(function() { 4095 return null; 4096 }); 4097}; 4098 4099$cart.getCartItem = function(productEntity, productId) { 4100 var cart = $cart.get(); 4101 if (cart && cart.items) { 4102 for (var i in cart.items) { 4103 var cartItem = cart.items[i]; 4104 if (cartItem.product.entity === productEntity && cartItem.product.entity_id === productId) { 4105 return cartItem; 4106 } 4107 } 4108 } 4109 return null; 4110}; 4111 4112$cart.addItem = function(productEntity, productId, data) { 4113 var cartItem = $cart.getCartItem(productEntity, productId); 4114 if (cartItem) { 4115 cartItem.quantity = data.quantity; 4116 cartItem.extra_data = data.extraData; 4117 } else { 4118 var cart = $cart.get(); 4119 if (!cart) { 4120 cart = {}; 4121 $angular.rootScope.cart = cart; 4122 } 4123 if (!cart.items) { 4124 cart.items = []; 4125 } 4126 cart.items.push({ 4127 product: { 4128 entity: productEntity, 4129 entity_id: productId 4130 }, 4131 quantity: data.quantity, 4132 extra_data: data.extraData 4133 }); 4134 } 4135 $cart.save(); 4136}; 4137 4138$cart.removeItem = function(cartItem) { 4139 var cart = $cart.get(); 4140 if (cart && cart.items) { 4141 cart.items = cart.items.filter(function(item) { 4142 return item.product.entity !== cartItem.product.entity || 4143 item.product.entity_id !== cartItem.product.entity_id; 4144 }); 4145 $cart.save(); 4146 } 4147}; 4148 4149$cart.setDeliveryMethod = function(deliveryMethod) { 4150 var cart = $cart.get(); 4151 if (cart) { 4152 cart.delivery_method = deliveryMethod; 4153 $cart.save(); 4154 } 4155}; 4156 4157$cart.isDeliveryMethodType = function(type) { 4158 var cart = $cart.get(); 4159 if (cart && cart.delivery_method) { 4160 return cart.delivery_method.type === type; 4161 } 4162 return !type; 4163}; 4164
4165$cart.getDeliveryMethodBooking = function() { 4166 var cart = $cart.get(); 4167 return cart && cart.delivery_method ? cart.delivery_method.booking : null; 4168}; 4169 4170$cart.setDeliveryMethodBooking = function(booking) { 4171 var cart = $cart.get(); 4172 if (cart && cart.delivery_method) { 4173 cart.delivery_method.booking = booking; 4174 $cart.save(); 4175 } 4176}; 4177 4178$cart.getDeliveryMethodExtraData = function() { 4179 var cart = $cart.get(); 4180 return cart && cart.delivery_method ? cart.delivery_method.extra_data : null; 4181}; 4182 4183$cart.setDeliveryMethodExtraData = function(entity, extraData) { 4184 var cart = $cart.get(); 4185 if (cart && cart.delivery_method) { 4186 cart.delivery_method.extra_data_entity = entity; 4187 cart.delivery_method.extra_data = extraData; 4188 $cart.save(); 4189 } 4190}; 4191 4192$cart.hasEmail = function() { 4193 var cart = $cart.get(); 4194 return cart && $utils.isEmail(cart.email); 4195}; 4196 4197$cart.setEmail = function(email) { 4198 var cart = $cart.get(); 4199 if (cart) { 4200 cart.email = email; 4201 $cart.save(); 4202 } 4203}; 4204 4205$cart.isCartItem = function(item, force) { 4206 if (item == null) { 4207 return false; 4208 } 4209 if (!$utils.isTrue(force) && ($entity.isGeoSchedule(item.entity) || !$instance.hasCart())) { 4210 return false; 4211 } 4212 if (!$entity.isGeoBuy(item.entity)) { 4213 return false; 4214 } 4215 if (item.geo_buy) { 4216 item = item.geo_buy; 4217 } 4218 return !$utils.isTrue($instance.parse(item.disabled)) && ($utils.isTrue(item.free) || item.price > 0); 4219}; 4220 4221$cart.getStock = function(item) { 4222 if (item.geo_buy) { 4223 item = item.geo_buy; 4224 } 4225 var stock = item.places; 4226 if (isNaN(stock)) { 4227 return null; 4228 } 4229 if (item.purchases) { 4230 var p = $instance.parse(item.purchases); 4231 if (typeof p == 'number') { 4232 stock -= p; 4233 } 4234 } 4235 return stock; 4236}; 4237 4238$cart.hasStock = function(o, extra) { 4239 var quantity = 1; 4240 if (extra) { 4241 quantity += extra; 4242 } 4243 var stock = $cart.getStock(o); 4244 //console.log('stock:'+stock + " vs quantity:"+quantity) 4245 return stock == null || stock >= quantity; 4246}; 4247 4248$cart.isUserRequiredToAddCart = function() { 4249 return $instance.current && $instance.current.geo_buy && $utils.isTrue($instance.current.geo_buy.user_required_to_add_cart); 4250}; 4251 4252$cart.isAllowedAnonymous = function() { 4253 return $instance.current && $instance.current.geo_buy && $utils.isTrue($instance.current.geo_buy.allowed_anonymous); 4254}; 4255 4256$cart.getAnonymousCartIdKey = function() { 4257 var instanceId = $instance.getId(); 4258 if (instanceId) { 4259 return '_geo_anonymous_cart_' + instanceId + '_'; 4260 } 4261 return null; 4262}; 4263 4264$cart.getAnonymousCartId = function() { 4265 var key = $cart.getAnonymousCartIdKey(); 4266 if (key) { 4267 return $storageService.get(key); 4268 } 4269 return null; 4270}; 4271 4272$cart.setAnonymousCartId = function(id) { 4273 var key = $cart.getAnonymousCartIdKey(); 4274 if (key) { 4275 if (id) { 4276 $storageService.put(key, id); 4277 } else { 4278 $storageService.remove(key); 4279 } 4280 } 4281}; 4282 4283//// File media.js //// 4284 4285 4286var $media = {}; 4287 4288$media.medias = {}; 4289 4290/* 4291// problem passing img element in init function 4292$media.init = function(img, elem, mediaId) { 4293 img.onload = function() { 4294 $angular.onLoadImg(img); 4295 }; 4296 img.onerror = function() { 4297 img.style.display='none'; 4298 }; 4299 if (elem != null) { 4300 var alt = $entity.displayColumn(elem); 4301 if (!$utils.isBlank(alt)) { 4302 $(img).prop("alt", alt); 4303 } 4304 if ($utils.isBlank(mediaId)) { 4305 mediaId = elem.geo_image; 4306 } 4307 } 4308 var url = $media.getMediaUrl(mediaId); 4309 if ($utils.isBlank(url)) { 4310 img.style.display='none'; 4311 return; 4312 } 4313 console.log("Loading media: " + url); 4314 $(img).prop("src", url); 4315}; 4316*/ 4317 4318$media.getMediaInfo = function(mediaId) { 4319 var media = $media.medias[mediaId]; 4320 if (media) { 4321 return media; 4322 } 4323 $rest.get({ 4324 url: contextPath + ($constants.isWeb ? '/www/media/' : "/api/media/") + mediaId + '/info.json', 4325 showError: false 4326 }).then(function(o) { 4327 $media.medias[mediaId] = o ? o : {}; 4328 }, function() { 4329 $media.medias[mediaId] = {}; 4330 }); 4331 return undefined; 4332}; 4333 4334$media.getMediaAlt = function(mediaId) { 4335 var media = $media.getMediaInfo(mediaId); 4336 if (media === undefined) { 4337 return undefined; 4338 } 4339 if (media) { 4340 if (media.description && !$utils.isBlank(media.description)) { 4341 return media.description; 4342 } 4343 if (media.name && !$utils.isBlank(media.name)) { 4344 return media.name; 4345 } 4346 } 4347 return ''; 4348}; 4349 4350$media.getMediaUrl = function(item, extension) { 4351 if (item && item.extension === 'youtube') { 4352 return item.source_media_url; 4353 } 4354 var id = item; 4355 if (id) { 4356 if (id.image) { 4357 id = id.image; 4358 } else if (id.id) { 4359 id = id.id; 4360 } 4361 } 4362 if ($utils.isBlank(id)) { 4363 return ""; 4364 } 4365 if (typeof id == 'string' && id.startsWith('http')) { 4366 return id; 4367 } 4368 if (extension == null) { 4369 extension = $angular.rootScope.imgExtension; 4370 } 4371 var url = $angular.rootScope.rootPath + ($constants.isWeb ? 'www' : 'api'); 4372 return url + "/media/" + id + "." + extension + "?_l=" + $locale.language; 4373}; 4374 4375$media.getMediaName = function(item) { 4376 if (item && item.name) { 4377 return item.name; 4378 } 4379 return item; 4380}; 4381 4382$media.isYoutube = function(item) { 4383 if (typeof item == 'string') { 4384 return item.contains("youtube.com"); 4385 } 4386 return item && item.extension === 'youtube'; 4387} 4388 4389$media.getItemMediaUrl = function(entity, id) { 4390 return $angular.rootScope.rootPath + "www/geo/" + entity + "/" + id + "/media." + $angular.rootScope.imgExtension + "?_l=" + $locale.language; 4391}; 4392 4393$media.openMedia = function(e, entity, id, type, column) { 4394 $utils.preventDefault(e); 4395 setTimeout(function() { 4396 $angular.openModal("panel-add-media", {entity: entity, id: id, type: type, column: column, size: 'xl'}); 4397 }, 100); 4398}; 4399 4400//// File user.js //// 4401var $user = {}; 4402 4403$user.isInit = false; 4404 4405// vars TODO 4406$user.current = null; 4407//$user.isLogged = false; 4408//$user.isSuper = false; 4409//$user.isAdmin = false; 4410//$user.isBasicUser = false; 4411//$user.isLogged = false; 4412 4413$user.isLogged = function() { 4414 return $user.current != null; 4415}; 4416 4417$user.showConsole = function() { 4418 return $user.current && $utils.isTrue($user.current.console); 4419}; 4420 4421$user.set = function(callback) { 4422 4423 $rest.get({ 4424 url: contextPath + "/api/logged.json", 4425 showError: false 4426 }).then(function(o) { 4427 //console.log("user logged in", o); 4428 $user.current = o; 4429 $angular.apply($angular.rootScope); 4430 4431 $cart.initCart(); 4432 4433 if (callback) { 4434 callback(); 4435 return; 4436 } 4437 4438 if (!$utils.isBlank($angular.tmpPath)) { 4439 var path = $angular.tmpPath; 4440 $angular.tmpPath = null; 4441 $angular.get("$location").path(path).replace(); 4442 return; 4443 } 4444 4445 $angular.goHome(); 4446 4447 }, function() { 4448 $user.current = null; 4449 if (callback) { 4450 callback(); 4451 } 4452 }); 4453 4454}; 4455 4456$user.getRoleDesc = function() { 4457 if ($user.current) { 4458 var key = $constants.rolesList[$user.current.role]; 4459 if (key) { 4460 return key; 4461 } 4462 } 4463 return "unknown"; 4464}; 4465 4466$user.isInstanceAllowed = function(i) { 4467 if ($user.isSuper()) { 4468 return true; 4469 } 4470 var u = $user.current; 4471 if (u && u.instances_allowed) { 4472 return u.instances_allowed.includes(i); 4473 } 4474 return false; 4475}; 4476 4477$user.hasInstancesAllowed = function() { 4478 var u = $user.current; 4479 return u && u.instances_allowed && u.instances_allowed.length > 0;
4480}; 4481 4482$user.isSuper = function() { 4483 return $user.hasRole('super'); 4484}; 4485$user.isAdmin = function() { 4486 return $user.hasRole('admin') || $user.isSuper(); 4487}; 4488$user.isCoordinator = function() { 4489 return $user.hasRole('coordinator'); 4490}; 4491$user.isBasicUser = function() { 4492 return $user.hasRole('basic'); 4493}; 4494$user.isPublic = function() { 4495 return $user.hasRole('public'); 4496}; 4497$user.isModeler = function() { 4498 return $user.isSuper() || ($user.current && $user.current.modeler); 4499}; 4500 4501$user.hasRole = function(role) { 4502 return $user.current && $user.current.role === role; 4503}; 4504 4505$user.openLoginAsPanel = function(callback) { 4506 $angular.openModal('panel-login').then(callback); 4507}; 4508 4509$user.isAllowed = function(entity) { 4510 if ($user.isAdmin()) { 4511 return true; 4512 } 4513 if ($user.isCoordinator()) { 4514 return (entity != null && entity.type == 'entity'); 4515 } 4516 return false; 4517}; 4518 4519//// File cookies.js //// 4520var $cookiesService = {}; 4521 4522//The object may have following properties: 4523//- path - {string} - The cookie will be available only for this path and its sub-paths. By default, this is the URL that appears in your <base> tag. 4524//- domain - {string} - The cookie will be available only for this domain and its sub-domains. For security reasons the user agent will not accept the cookie if the current domain is not a sub-domain of this domain or equal to it. 4525//- expires - {string|Date} - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT" or a Date object indicating the exact date/time this cookie will expire. 4526//- secure - {boolean} - If true, then the cookie will only be available through a secured connection. 4527//Note: By default, the address that appears in your <base> tag will be used as the path. This is important so that cookies will be visible for all routes when html5mode is enabled. 4528 4529$cookiesService.get = function(key) { 4530 if (document.cookie != null) { 4531 var nameEQ = key + "="; 4532 var ca = document.cookie.split(';'); 4533 for (var i = 0; i < ca.length; i++) { 4534 var c = ca[i]; 4535 while (c.charAt(0) === ' ') c = c.substring(1); // eliminar espacios 4536 if (c.indexOf(nameEQ) === 0) { 4537 return decodeURIComponent(c.substring(nameEQ.length)); 4538 } 4539 } 4540 } 4541 return null; 4542}; 4543 4544 4545$cookiesService.put = function(key, value, days) { 4546 if (value == null) { 4547 value = ""; 4548 } 4549 if (days == null) { 4550 days = 0; 4551 } 4552 var seconds = days*24*60*60; 4553 var path = contextPath == "" ? "/" : contextPath; 4554 var secure = "; Secure; SameSite=Strict"; 4555 var c = key + "=" + value + "; Max-Age=" + seconds + "; Path=" + path + secure; 4556 document.cookie = c; 4557 //console.log(c) 4558}; 4559 4560$cookiesService.remove = function(key) { 4561 $cookiesService.put(key, "", 0); 4562}; 4563 4564var $storageService = {}; 4565 4566$storageService.get = function(key) { 4567 try { 4568 var $window = $angular.get("$window"); 4569 var value = $window.localStorage[key]; 4570 //console.log("get " + key + " : " + value) 4571 return value; 4572 } catch (e) { 4573 return $cookiesService.get(key); 4574 } 4575}; 4576 4577$storageService.put = function(key, value) { 4578 try { 4579 var $window = $angular.get("$window"); 4580 $window.localStorage[key] = value; 4581 //console.log("put " + key + " : " + value) 4582 } catch (e) { 4583 $cookiesService.put(key, value, 7); 4584 } 4585}; 4586 4587$storageService.remove = function(key) { 4588 try { 4589 var $window = $angular.get("$window"); 4590 $window.localStorage.removeItem(key); 4591 //console.log("remove " + key) 4592 } catch (e) { 4593 $cookiesService.remove(key); 4594 } 4595}; 4596 4597var $sessionService = {}; 4598 4599$sessionService.get = function(key) { 4600 try { 4601 var $window = $angular.get("$window"); 4602 var value = $window.sessionStorage[key]; 4603 //console.log("get " + key + " : " + value) 4604 return value; 4605 } catch (e) { 4606 return $cookiesService.get(key); 4607 } 4608}; 4609 4610$sessionService.put = function(key, value) { 4611 try { 4612 var $window = $angular.get("$window"); 4613 $window.sessionStorage[key] = value; 4614 //console.log("put " + key + " : " + value) 4615 } catch (e) { 4616 $cookiesService.put(key, value, 30); 4617 } 4618}; 4619 4620$sessionService.remove = function(key) { 4621 try { 4622 var $window = $angular.get("$window"); 4623 $window.sessionStorage.removeItem(key); 4624 //console.log("remove " + key) 4625 } catch (e) { 4626 $cookiesService.remove(key); 4627 } 4628}; 4629 4630 4631//// File paginate.js //// 4632 4633 4634var $paginate = {}; 4635var $paginator; 4636 4637$paginate.init = function(element, options) { 4638 $paginator = new $paginate.instance(element, options); 4639 4640 if ($angular.contentScope) { 4641 $angular.contentScope.$paginator = $paginator; 4642 } 4643 4644 if (options.noLoad) { 4645 // no init list; 4646 return; 4647 } 4648 // init list 4649 $paginator.updateList(); 4650 4651 return $paginator; 4652}; 4653 4654$paginate.instance = function(element, options) { 4655 4656 if (element == undefined) { 4657 throw "The element is required."; 4658 } 4659 if (options == undefined) { 4660 throw "The argument 'options' is required."; 4661 } 4662 if (options.path == undefined) { 4663 throw "The parameter 'path' is required."; 4664 } 4665 4666 var self = this; 4667 4668 var _defaults = { 4669 numPerPage: 100, 4670 list: "list", 4671 scope: $angular.contentScope, 4672 sce: $angular.get("$sce"), 4673 indexMin: null, 4674 indexMax: null 4675 } 4676 4677 /* Public attributes */ 4678 this._settings = $.extend( {}, _defaults, options ); 4679 this._element = $(element); 4680 4681 var limit = getParamNumber("_limit"); 4682 if (limit > 0) { 4683 this._settings.numPerPage = Number(limit); 4684 } 4685 4686 if (this._settings.queryString == null) { 4687 this._settings.queryString = getQueryString(window.location.href); 4688 } 4689 4690 // fix urls params 4691 this._settings.queryString = removeParam(this._settings.queryString, "_limit"); 4692 if (this._settings.numPerPage > 0) { 4693 this._settings.queryString = addParam(this._settings.queryString, "_limit", this._settings.numPerPage); 4694 } 4695 4696 var index = getParamNumber("_index", this._settings.queryString); 4697 this._settings.queryString = removeParam(this._settings.queryString, "_index"); 4698 this._settings.queryString = addParam(this._settings.queryString, "_index", index); 4699 4700 // add extra params 4701 if (options.params) { 4702 for (var key in options.params) { 4703 var value = options.params[key]; 4704 if (!this._settings.queryString.contains(key)) { 4705 this._settings.queryString = addParam(this._settings.queryString, key, value); 4706 } 4707 } 4708 } 4709 4710 // Prev 4711 this._settings.scope.loadPrev = function(e, addAfter, addBefore) { 4712 $utils.preventDefault(e); 4713 4714 $("#load-prev a.btn").blur(); 4715 if (addAfter == null) addAfter = false; 4716 if (addBefore == null) addBefore = true; 4717 $paginator.updateList(getPrevQueryString(), true, addAfter, addBefore); 4718 }; 4719 4720 // More 4721 this._settings.scope.loadMore = function(e, addAfter, addBefore) { 4722 $utils.preventDefault(e); 4723 4724 $("#load-more a.btn").blur(); 4725 if (addAfter == null) addAfter = true; 4726 if (addBefore == null) addBefore = false; 4727 $paginator.updateList(getNextQueryString(), true, addAfter, addBefore); 4728 }; 4729 4730 /* Public methods */ 4731 this.getQueryStringAll = function(params, withoutPaginationParams) { 4732 var qs = self._settings.queryString; 4733 qs = removeParam(qs, "_limit"); 4734 if (withoutPaginationParams) { 4735 qs = removeParam(qs, "_paginate"); 4736 qs = removeParam(qs, "_index"); 4737 qs = removeParam(qs, "suffix"); 4738 } else { 4739 qs = addParam(qs, "_paginate", "false"); 4740 var id = $instance.getId(); 4741 if (!$utils.isBlank(id)) { 4742 qs = addParam(qs, "geo_instance", id); 4743 } 4744 } 4745 if (params) { 4746 for (var key in params) { 4747 var param = params[key]; 4748 qs = addParam(qs, param.key, param.value); 4749 } 4750 } 4751 return qs; 4752 }; 4753 4754 this.refreshList = function(force) { 4755 var qs = self._settings.queryString; 4756 qs = removeParam(qs, "_index"); 4757 qs = addParam(qs, "_index", "0"); 4758 this.updateList(qs, force); 4759 }; 4760 4761 this.firstTime = true; 4762 this.requesting = 0; 4763 4764 this.updateList = function(queryString, force, addAfter, addBefore) { 4765 4766 if (!$utils.isTrue(force) && self._settings.queryString == queryString) { 4767 return; 4768 } 4769 4770 if (queryString == undefined) { 4771 queryString = self._settings.queryString; 4772 } 4773 4774 if ($user.isSuper()) { 4775 queryString = removeParam(queryString, "suffix"); 4776 queryString = addParam(queryString, "suffix", "true"); 4777 } 4778 4779 var index = getParamNumber('_index', queryString); 4780 if (index == 0) { 4781 // reset range 4782 self._settings.indexMin = null; 4783 self._settings.indexMax = null; 4784 } 4785 4786 var url = contextPath + "/"+this._settings.path+".json" + queryString; 4787 //console.log(url) 4788 self._settings.queryString = queryString; 4789 4790 if (this.firstTime) { 4791 this.firstTime = false; 4792 } else { 4793 // update current url for backs 4794 var params = queryStringToJSON(queryString); 4795 if (self._settings.numPerPage == 100) { 4796 delete params._limit; 4797 } 4798 delete params.suffix; 4799 //if (params._index == "0") { 4800 delete params._index; 4801 //} 4802 //console.dir(params) 4803 $angular.get("$location").search(params).replace(); 4804 } 4805 4806 self.requesting++; 4807 var tmp = self.requesting; 4808 4809 //var time = new Date().getTime(); 4810 //console.log("1. " + url) 4811 $rest.get({ 4812 skipHideLoading: true, 4813// loading: loading, 4814 url: url 4815 }).then(function(data) { 4816 4817 if (self.requesting != tmp) { 4818 console.log('skipping ' + url + " requesting:" + self.requesting + " tmp:"
4818+ tmp) 4819 return; 4820 } 4821 4822 //console.log("2. " + url) 4823 if (data && self._settings.scope.collapsed) { 4824 4825 var l = []; 4826 var list = data[self._settings.list]; 4827 if (list) { 4828 var colName = $entity.getDefaultColumnName($angular.contentScope.entity); 4829 var last = {}; 4830 for (var i=0; i<list.length; i++) { 4831 var item = list[i]; 4832 var name = item[colName]; 4833 if (last[name] == null) { 4834 l.push(item); 4835 last[name] = item; 4836 last[name]._num = 0; 4837 } 4838 last[name]._num++; 4839 } 4840 } 4841 data[self._settings.list] = l; 4842 //console.log('is error!!! from '+ list.length + " to " + l.length) 4843 } 4844 4845 if (addAfter) { 4846 4847 // Append 4848 self._settings.scope.model[self._settings.list] = self._settings.scope.model[self._settings.list] 4849 .concat(data[self._settings.list]); 4850 4851 } else if (addBefore) { 4852 4853 // Where the page is currently: 4854 var firstMsg = $('.list-row:first'); 4855 var firstMsgId = firstMsg.attr("id"); 4856 var offset = firstMsg.offset(); 4857 if (offset && offset.top) { 4858 var curOffset = offset.top - $(document).scrollTop(); 4859 //console.log("top:"+offset.top + " - scrollTop:"+$(document).scrollTop()) 4860 4861 // Prepend 4862 self._settings.scope.model[self._settings.list] = data[self._settings.list] 4863 .concat(self._settings.scope.model[self._settings.list]); 4864 4865 $angular.apply(self._settings.scope, function() { 4866 // Offset to previous first message minus original offset/scroll 4867 firstMsg = $('#'+firstMsgId); 4868 //console.log("top:"+offset.top + " - curOffset:"+curOffset); 4869 $(document).scrollTop(offset.top-curOffset); 4870 }); 4871 } 4872 4873 } else { 4874 4875 // full list 4876 self._settings.scope.model = data; 4877 4878 // clean cache 4879 if (data.list) { 4880 for (var k in data.list) { 4881 var o = data.list[k] 4882 if (o.id) { 4883 $constants.removeFromCache(null, o.id); 4884 } 4885 } 4886 } 4887 } 4888 4889 var index = getParamNumber('_index', url); 4890 4891 // show pagination data 4892 if (index == 0) { 4893 if (data != null && data.count != null) { 4894 self._settings.numRows = data.count; 4895 } else { 4896 self._settings.numRows = self._settings.scope.model[self._settings.list].length; 4897 } 4898 showPagination(); 4899 } 4900 4901 if (self._settings.indexMin == null || self._settings.indexMin > index) { 4902 self._settings.indexMin = index; 4903 } 4904 if (self._settings.indexMax == null || self._settings.indexMax < index) { 4905 self._settings.indexMax = index; 4906 } 4907 //console.log('min:'+self._settings.indexMin + ' max:'+self._settings.indexMax) 4908 //console.log('prev:'+getPrevIndex() + ' more:'+getNextIndex() + " size:" + self._settings.scope.model[self._settings.list].length) 4909 4910 $angular.apply(self._settings.scope, function() { 4911 if (self._settings.numRows != null && getPrevIndex() >= 0) { 4912 $("#load-prev").removeClass("hidden"); 4913 } else { 4914 $("#load-prev").addClass("hidden"); 4915 } 4916 4917 if (self._settings.numRows != null && getNextIndex() < self._settings.numRows) { 4918 $("#load-more").removeClass("hidden"); 4919 } else { 4920 $("#load-more").addClass("hidden"); 4921 } 4922 //console.log('load more visible ' + $("#load-more").is(":visible") + " - " + $("#load-more").hasClass("hidden") + " - " + $("#load-more").length) 4923 }); 4924 4925 4926 $(window).unbind('scroll').scroll(function() { 4927 4928 if ($(window).scrollTop() + $(window).height() > $(document).height() - 600) { 4929 if ($("#load-more").is(":visible")) { 4930 //console.log('load more') 4931 $(window).unbind('scroll'); 4932 if ($("#load-more a.btn").length > 0) { 4933 $("#load-more a.btn").click(); 4934 } else { 4935 $("#load-more").click(); 4936 } 4937 } 4938 return; 4939 } 4940 4941 if ($(window).scrollTop() == 0) { 4942 if ($("#load-prev").is(":visible")) { 4943 //console.log('load prev') 4944 $(window).unbind('scroll'); 4945 if ($("#load-prev a.btn").length > 0) { 4946 $("#load-prev a.btn").click(); 4947 } else { 4948 $("#load-prev").click(); 4949 } 4950 } 4951 return; 4952 } 4953 }); 4954 4955 if (self._settings.onUpdated) { 4956 self._settings.onUpdated(data); 4957 } 4958 4959 }); 4960 4961 } 4962 4963 function showPagination() { 4964 // show num results 4965 if (self._settings.numRows == null) { 4966 self._settings.numRows = 0; 4967 } 4968 self._settings.scope.pagination_results = $utils.parseNumber(self._settings.numRows); 4969 } 4970 4971 4972 function getPrevQueryString() { 4973 var index = getPrevIndex(); 4974 var queryString = self._settings.queryString; 4975 queryString = removeParam(queryString, "_index"); 4976 queryString = addParam(queryString, "_index", index); 4977 return queryString; 4978 } 4979 function getPrevIndex() { 4980 return self._settings.indexMin - self._settings.numPerPage; 4981 } 4982 4983 function getNextQueryString() { 4984 var index = getNextIndex(); 4985 var queryString = self._settings.queryString; 4986 queryString = removeParam(queryString, "_index"); 4987 queryString = addParam(queryString, "_index", index); 4988 return queryString; 4989 } 4990 function getNextIndex() { 4991 return self._settings.indexMax + self._settings.numPerPage; 4992 } 4993 4994}; 4995 4996// GENERIC METHODS TO MANAGE URL 4997function getQueryString(url) { 4998 if (url == undefined) { 4999 url = window.location.href; 5000 } 5001 var queryString = ""; 5002 var split = url.split("?"); 5003 if (split.length > 1 && split[1] != null) { 5004 queryString = split[1]; 5005 } 5006 queryString = queryString.trim(); 5007 if (queryString.length > 0) { 5008 queryString = "?" + queryString; 5009 } 5010 return queryString; 5011} 5012function getParam(name, url) { 5013 if (url == undefined) { 5014 url = window.location.href; 5015 } 5016 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]"); 5017 var regexS = "[\\?&]"+name+"=([^&#]*)"; 5018 var regex = new RegExp( regexS ); 5019 var results = regex.exec( url ); 5020 if( results == null ) { 5021 return ""; 5022 } else { 5023 return results[1]; 5024 } 5025} 5026function getParamNumber(name, url) { 5027 var value = getParam(name, url); 5028 var orig = value; 5029 if ($utils.isBlank(value)) { 5030 value = 0; 5031 } else { 5032 value = Number(value); 5033 if (isNaN(value)) { 5034 value = 0; 5035 } 5036 } 5037 return value; 5038} 5039function addParam(url, param, value) { 5040 var sep = "&"; 5041 if (url.indexOf("?") == -1) { 5042 sep = "?"; 5043 } 5044 return url + sep + param + "=" + encodeURIComponent(value); 5045} 5046 5047function removeParam(url, param) { 5048 if (!url.contains(param)) { 5049 return url; 5050 } 5051 //console.log('1: remove ' + param + " " + url); 5052 5053 //if (param.contains('$')) { 5054 param = param.replace('\$', '\\$'); 5055 //} 5056 5057 // remove all parameters starting with $ 5058 var regex = new RegExp( "\\&" + param + "=[^&]*&?", "gi"); 5059 var orig; 5060 do { 5061 orig = url; 5062 url = url.replace(regex,'&'); 5063 } while (orig != url); 5064 5065 // remove parameter starting with ? 5066 regex = new RegExp( "\\?" + param + "=[^&]*&?", "gi"); 5067 url = url.replace(regex,'?'); 5068 5069 // remove if ends with ? or & 5070 url = url.replace(/(\?|&)$/,''); 5071 5072 //console.log('2: remove ' + param + " " + url); 5073 return url; 5074} 5075 5076function queryStringToJSON(queryString) { 5077 if (queryString == null) { 5078 queryString = ""; 5079 } else if (queryString.startsWith("?")) { 5080 queryString = queryString.substring(1); 5081 } 5082 var pairs = queryString.split('&'); 5083 var result = {};
5084 pairs.forEach(function(pair) { 5085 pair = pair.split('='); 5086 if (!$utils.isBlank(pair[0])) { 5087 result[pair[0]] = decodeURIComponent(pair[1] || ''); 5088 } 5089 }); 5090 return JSON.parse(JSON.stringify(result)); 5091} 5092 5093//// File instance.js //// 5094 5095 5096var $instance = {}; 5097 5098$instance.current = null; 5099$instance.entities = null; 5100$instance.entityTitles = null; 5101$instance.languages = null; 5102 5103$instance.exists = function() { 5104 return $instance.current != null && $instance.current.name != null; 5105}; 5106 5107$instance.getBaseUrl = function() { 5108 var id = $instance.getId(); 5109 if (id == null && $constants.isWeb) { 5110 id = $instance.getIdToResolveInstance(); 5111 } 5112 if (id != null) { 5113 if (!$constants.isWeb) { 5114 return "admin/i/" + id + "/"; 5115 } 5116 if (!$utils.isBlank(appInstance) && appInstance == id) { 5117 return ""; 5118 } 5119 return "home/" + id + "/"; 5120 } 5121 if ($constants.isWeb) { 5122 console.log("warn: web baseurl to admin (no instance id)"); 5123 } 5124 return "admin/"; 5125}; 5126 5127$instance.exit = function() { 5128 $instance.current = null; 5129 $instance.languages = $constants.languages; 5130 //console.log('exit instance'); 5131}; 5132 5133$instance.hasToRefresh = false; 5134$instance.checkHasToRefresh = function(entity, id) { 5135 if (entity === "instance" || entity === "entity" 5136 || entity === "form" || entity === "category" 5137 || entity === "spreadsheet" || entity === "datamixer" 5138 || entity === "synchronizer" || entity === "notifier") { 5139 $instance.hasToRefresh = true; 5140 5141 if (entity === "instance" && id != null && id == $instance.getId()) { 5142 $instance.resolveInstance(); 5143 } 5144 } 5145}; 5146 5147$instance.resolveInstance = function(callback) { 5148 var id = $instance.getIdToResolveInstance(); 5149 //var path = $angular.get("$location").path(); 5150 5151 if ($instance.current && id == null) { 5152 // exit instance 5153 //console.log('exit instance ' + id + " " + path) 5154 $instance.exit(); 5155 if ($user.isSuper()) { 5156 callback(); 5157 } else { 5158 $user.set(function() { 5159 callback(); 5160 }); 5161 } 5162 return; 5163 } 5164 5165 var hasToRefresh = $instance.hasToRefresh; 5166 $instance.hasToRefresh = false; 5167 5168 if (id == null || (id == $instance.getId() && !hasToRefresh && $instance.exists())) { 5169 // no change 5170 //console.log('no change ' + id + " " + path, $instance.current) 5171 callback(); 5172 return; 5173 } 5174 5175 5176 // load instance id 5177 //console.log('load instance ' + id) 5178 $instance.set(id, callback); 5179}; 5180 5181$instance.getId = function() { 5182 if ($instance.current) { 5183 return $instance.current.id; 5184 } 5185 return null; 5186}; 5187 5188$instance.getIdToResolveInstance = function() { 5189 var path = $angular.get("$location").path(); 5190 if (path) { 5191 if (path.startsWith("/admin/i/") || path.startsWith("/admin/instance/")) { 5192 var split = path.split("/"); 5193 if (split.length > 3) { 5194 var id = split[3]; 5195 if (id.length > 0 && id != 'new') { 5196 return id; 5197 } 5198 } 5199 } 5200 if (path.startsWith("/home/")) { 5201 var split = path.split("/"); 5202 if (split.length > 2) { 5203 var id = split[2]; 5204 if (id.length > 0) { 5205 return id; 5206 } 5207 } 5208 } 5209 } 5210 if (appInstance == "") { 5211 appInstance = null; 5212 } 5213 return appInstance; 5214}; 5215 5216$instance.refresh = function() { 5217 $instance.set($instance.current.id); 5218}; 5219 5220$instance.set = function(instanceId, callback) { 5221 5222 if ($utils.isBlank(instanceId)) { 5223 //$init.logError("instanceId required"); 5224 return; 5225 } 5226 if (callback == null) { 5227 callback = function() {}; 5228 } 5229 5230 var loading = 'generic'; 5231 var oldSkipHideLoading = $angular.rootScope.skipHideLoading; 5232 if (oldSkipHideLoading) { 5233 loading = null; 5234 } 5235 5236 var root = $constants.isWeb ? "/www" : "/api"; 5237 5238 // load instance data 5239 $rest.get({ 5240 url: contextPath + root + "/instance/" + instanceId + "/set.json", 5241 skipHideLoading: !$constants.isWeb,// false for errors in web 5242 instance: instanceId, 5243 loading: loading 5244 }).then(function(o) { 5245 //console.log('set instance', o) 5246 5247 if ($constants.isWeb && $instance.current != null) { 5248 // update instance stylesheet 5249 5250 $("body").fadeOut(200, function() { 5251 $instance.endSet(o, callback, oldSkipHideLoading); 5252 5253 // wait until css is loaded 5254 setTimeout(function() { 5255 $("body").fadeIn(200, function() {}); 5256 }, 250); 5257 }); 5258 return; 5259 } 5260 5261 $instance.endSet(o, callback, oldSkipHideLoading); 5262 5263 }, function(e) { 5264 $instance.current = null; 5265 $angular.rootScope.skipHideLoading = oldSkipHideLoading; 5266 callback(); 5267 5268 if (e.response) { 5269 if (e.response.status == 0) { 5270 setTimeout(function() { 5271 $utils.showNoInternet(); 5272 }, 100); 5273 return; 5274 } 5275 if (e.response.status == 403) { 5276 setTimeout(function() { 5277 $utils.showAccessDenied(); 5278 }, 100); 5279 return; 5280 } 5281 if (e.response.status == 404) { 5282 setTimeout(function() { 5283 $utils.showNotFound(); 5284 }, 100); 5285 return; 5286 } 5287 } 5288 setTimeout(function() { 5289 $utils.showError(); 5290 }, 100); 5291 }); 5292 5293}; 5294 5295$instance.endSet = function(o, callback, oldSkipHideLoading) { 5296 $angular.rootScope.skipHideLoading = oldSkipHideLoading; 5297 $instance.current = o; 5298 $instance.entities = null; 5299 $instance.entityTitles = null; 5300 $cart.initCart(); 5301 if ($instance.isTrackLocation()) { 5302 $angular.get('geolocationService').watchCurrentLocation(); 5303 } 5304 if ($instance.current && $instance.current.name) { 5305 $("html > head > title").html($utils.parse($instance.current.name)); 5306 } 5307 5308 $instance.languages = o.languages; 5309 if ($instance.languages == null || $instance.languages.length == 0) { 5310 $instance.languages = $constants.languages; 5311 } 5312 5313 $instance.mslogin = $utils.isTrue($utils.get($instance.current, "geo_login.mslogin")) 5314 5315 if ($user.isSuper()) { 5316 callback(); 5317 } else { 5318 $user.set(function() { 5319 callback(); 5320 }); 5321 } 5322}; 5323 5324$instance.setCssProperties = function() { 5325 try { 5326 var background = getComputedStyle(document.documentElement).getPropertyValue('--color-background'); 5327 if ($utils.isColorDark(background)) { 5328 $angular.mapStyle = $angular.mapDark; 5329 } 5330 } catch (e) { 5331 console.error(e); 5332 } 5333}; 5334 5335$instance.getEntities = function(type) { 5336 var list = $instance.getEntityList(); 5337 var result = []; 5338 for (var k in list) { 5339 var entity = list[k]; 5340 if (entity.group == type || (type == 'settings' && $utils.isBlank(entity.group))) { 5341 if (!$user.isAllowed(entity)) { 5342 continue; 5343 } 5344 result.push(entity.id); 5345 } 5346 } 5347 return result; 5348}; 5349 5350$instance.getEntityList = function() { 5351 var instance = $instance.current; 5352 if (instance && instance.entityList) { 5353 return instance.entityList; 5354 } 5355 return []; 5356}; 5357 5358$instance.getCategoryName = function(id) { 5359 if ($instance.current && $instance.current.categoryList) { 5360 var list = $instance.current.categoryList; 5361 for (var k in list) { 5362 var cat = list[k]; 5363 if (cat.id == id) { 5364 return $utils.parse(cat.name); 5365 } 5366 } 5367 } 5368 return null; 5369}; 5370 5371// TODO use this instead of constants! 5372$instance.getCategoryList = function(entity) { 5373 var result = []; 5374 if ($instance.current && $instance.current.categoryList) { 5375 var list = $instance.current.categoryList; 5376 for (var k in list) { 5377 var cat = list[k]; 5378 if (cat.entities && cat.entities.indexOf(entity) != -1) { 5379 result.push(cat); 5380 } 5381 } 5382 } 5383 return result; 5384}; 5385 5386$instance.getSubInstances = function() { 5387 var instance = $instance.current; 5388 if (instance && instance.subInstances) { 5389 return instance.subInstances; 5390 } 5391 return []; 5392}; 5393 5394$instance.getSubInstanceName = function(id) { 5395 var list = $instance.getSubInstances(); 5396 for (var k in list) { 5397 var cat = list[k]; 5398 if (cat.id == id) { 5399 return $utils.parse(cat.name); 5400 } 5401 } 5402 return null; 5403}; 5404 5405$instance.getGeoSmarterText = function(key, msg) { 5406 if ($instance.current.geo_smarter == null) { 5407 $instance.current.geo_smarter = {}; 5408 } 5409 var value = $instance.current.geo_smarter[key]; 5410 if ($utils.isBlank(value) && !$utils.isBlank(msg)) { 5411 value = $angular.get("$translate").instant(msg); 5412 } 5413 return value; 5414}; 5415 5416$instance.getGeoJson = function() { 5417 var instance = $instance.current; 5418 if (instance && instance.geo_fence) { 5419 return instance.geo_fence.geo_json; 5420 } 5421 return null; 5422}; 5423 5424$instance.getGeoFence = function() { 5425 var instance = $instance.current; 5426 if (instance && instance.geo_fence) { 5427 return instance.geo_fence; 5428 } 5429 return null; 5430}; 5431 5432$instance.getGeoFenceCenter = function() { 5433 var instance = $instance.current; 5434 if (instance && instance.geo_fence && instance.geo_fence.center_latitude) { 5435 var lat = Number(instance.geo_fence.center_latitude); 5436 var long = Number(instance.geo_fence.center_longitude); 5437 if (lat != 0 && long != 0) { 5438 return new google.maps.LatLng(lat, long); 5439 } 5440 } 5441 return null; 5442}; 5443 5444$instance.getGeoPosition = function() { 5445 var latLng = $instance.getGeoFenceCenter(); 5446 if (latLng) { 5447 return latLng.lat() + ',' + latLng.lng(); 5448 } 5449 var instance = $instance.current; 5450 if (instance && instance.geo_location && instance.geo_location.latitude) { 5451 return instance.geo_location.latitude + ',' + instance.geo_location.longitude; 5452 } 5453 return null; 5454}; 5455 5456$instance.getGeoFenceRadius = function() { 5457 var instance = $instance.current; 5458 if (instance && instance.geo_fence && instance.geo_fence.radius) { 5459 return Number(instance.geo_fence.radius); 5460 } 5461 return null; 5462}; 5463 5464$instance.getGeoFenceZoom = function() { 5465 var instance = $instance.current; 5466 if (instance && instance.geo_fence && instance.geo_fence.default_zoom) { 5467 return Number(instance.geo_fence.default_zoom); 5468 } 5469 return null; 5470}; 5471 5472$instance.getGeoFenceCountryCode = function() { 5473 var instance = $instance.current; 5474 if (instance && instance.geo_fence) { 5475 return instance.geo_fence.country_code; 5476 } 5477 return null; 5478}; 5479 5480$instance.getGeoFenceBounds = function() { 5481 var instance = $instance.current; 5482 if (instance && instance.geo_fence && instance.geo_fence.bounds) { 5483 return instance.geo_fence.bounds; 5484 } 5485 var pos = $instance.getGeoFenceCenter(); 5486 var radius = $instance.getGeoFenceRadius(); 5487 if (pos && radius) {
5488 //console.log(pos.lat() + " " + pos.lng() + " " + radius) 5489// instance.geo_fence.bounds = new google.maps.Circle({radius: radius, center: pos}).getBounds(); 5490 5491 var bounds = new google.maps.LatLngBounds(); 5492 var numPts = 128; 5493 for (var i = 0; i < numPts; i++) { 5494 var loc = google.maps.geometry.spherical.computeOffset(pos, radius, i * 360 / numPts); 5495 bounds.extend(loc); 5496 } 5497 instance.geo_fence.bounds = bounds; 5498 return instance.geo_fence.bounds; 5499 } 5500 return null; 5501}; 5502 5503$instance.getSearchOptions = function() { 5504 var ops = {}; 5505 var bounds = $instance.getGeoFenceBounds(); 5506 if (bounds != null) { 5507 ops.bounds = bounds; 5508 ops.strictBounds = true; 5509 } 5510 var cc = $instance.getGeoFenceCountryCode(); 5511 if (!$utils.isBlank(cc)) { 5512 ops.componentRestrictions = {country: cc}; 5513 } 5514 return ops; 5515}; 5516 5517$instance.getRecents = function() { 5518 var recents = $storageService.get("_recents_admin"); 5519 if ($utils.isBlank(recents)) { 5520 return []; 5521 } 5522 return recents.split("||"); 5523}; 5524$instance.saveInRecents = function() { 5525 var id = $instance.getId(); 5526 if ($utils.isBlank(id)) { 5527 return; 5528 } 5529 var list = $instance.getRecents(); 5530 var index = list.indexOf(id); 5531 if (index == -1 && list.length > 7) { 5532 index = 7; 5533 } 5534 if (index != -1) { 5535 list.splice(index, 1); 5536 } 5537 list.unshift(id); // add first 5538 $instance.saveRecents(list); 5539}; 5540$instance.saveRecents = function(list) { 5541 var recents = $utils.join(list, '||'); 5542 5543 // save in recents TODO control not existing 5544 $storageService.put("_recents_admin", recents); 5545}; 5546$instance.replaceInRecents = function(from, to) { 5547 var list = $instance.getRecents(); 5548 var index = list.indexOf(from); 5549 if (index >= 0) { 5550 list[index] = to; 5551 $instance.saveRecents(list); 5552 } 5553}; 5554 5555$instance.isProperty = function(name) { 5556 if ($instance.current && $instance.current.geo_properties) { 5557 var props = $instance.current.geo_properties; 5558 for (var k in props) { 5559 var prop = props[k]; 5560 if (prop.name == name) { 5561 return prop.value == 'true'; 5562 } 5563 } 5564 } 5565 return false; 5566}; 5567 5568$instance.getEntityName = function(entity) { 5569 var o = $entity.getEntity(entity); 5570 if (o != null) { 5571 var value = $entity.displayColumn(o); 5572 if (value && o.name_extra && !$constants.isWeb && $user.isSuper()) { 5573 value += " (" + o.name_extra + ")"; 5574 } 5575 return value; 5576 } 5577 return null; 5578}; 5579 5580$instance.getEntity = function(entity) { 5581 if ($instance.entities == null) { 5582 $instance.entities = {}; 5583 var l = $instance.getEntityList(); 5584 for (var key in l) { 5585 var o = l[key]; 5586 $instance.entities[o.id] = o; 5587 } 5588 } 5589 return $instance.entities[entity]; 5590}; 5591 5592$instance.hasEntity = function(entity) { 5593 return !!$instance.getEntity(entity); 5594}; 5595 5596$instance.isEntity = function(entity) { 5597 var o = $entity.getEntity(entity); 5598 return o && o.type == "entity"; 5599}; 5600 5601$instance.getColor = function(path, def, def2) { 5602 var c = $utils.get($instance.current, path); 5603 if (c) { 5604 return $utils.getColor(c); 5605 } else if (def2) { 5606 return $instance.getColor(def, def2); 5607 } else { 5608 return def; 5609 } 5610}; 5611 5612$instance.get = function(path, def) { 5613 var c = $utils.get($instance.current, path); 5614 if (c == null) { 5615 c = def; 5616 } 5617 //console.log("get: " + path+"="+c) 5618 return c; 5619}; 5620 5621//function getBoundsByGeoJson(geojson) { 5622// 5623// if (typeof geojson === 'string') { 5624// geojson = JSON.parse(geojson); 5625// } 5626// 5627// var feature = { 5628// type : "Feature", 5629// geometry : geojson 5630// }; 5631// //console.dir(feature) 5632// 5633// var bounds = new google.maps.LatLngBounds(null); 5634// var data = new google.maps.Data(); 5635// data.addGeoJson(feature); 5636// data.forEach(function(feature) { 5637// if (feature && feature.getGeometry()) { 5638// feature.getGeometry().forEachLatLng(function(latLng) { 5639// bounds.extend(latLng); 5640// }); 5641// } 5642// }); 5643// return bounds; 5644//} 5645 5646$instance.isBooking = function(item) { 5647 return item && item.geo_schedule && $entity.isGeoSchedule(item.entity) 5648 && item.geo_schedule.booking && $utils.isTrue(item.geo_schedule.booking.enabled); 5649}; 5650 5651$instance.isShowStock = function() { 5652 return $instance.current && $instance.current.geo_buy && $utils.isTrue($instance.current.geo_buy.show_stock); 5653}; 5654 5655$instance.parse = function(p) { 5656 if (typeof p == 'object' && $instance.current) { 5657 p = p[$instance.current.id]; 5658 } 5659 return p; 5660}; 5661 5662$instance.hasCart = function() { 5663 return $instance.hasGeoBuy() && $instance.current && $instance.current.geo_buy 5664 && !$utils.isTrue($instance.parse($instance.current.geo_buy.disabled)); 5665}; 5666$instance.hasGeoBuy = function() { 5667 if ($instance.current) { 5668 return $utils.isTrue($instance.current.has_geo_buy); 5669 } 5670 return false;
5671}; 5672$instance.hasGeoSchedule = function() { 5673 if ($instance.current) { 5674 return $utils.isTrue($instance.current.has_geo_schedule); 5675 } 5676 return false; 5677}; 5678 5679$instance.hasAgenda = function() { 5680 if ($instance.current == null || $instance.current.geo_smarter == null || $utils.isTrue($instance.current.geo_smarter.disabled)) { 5681 return false; 5682 } 5683 var data = $sessionService.get("agenda_" + $instance.getId()); 5684 if (data == null || $utils.isBlank(data)) { 5685 return false; 5686 } 5687 return true; 5688}; 5689 5690$instance.getAgendaTitle = function() { 5691 return $instance.getGeoSmarterText("title_result", "msg.web.agenda"); 5692}; 5693 5694$instance.isLoginRequired = function(requiredLogged, publicUrl) { 5695 if (!$constants.isWeb) { 5696 // admin 5697 return $utils.isTrue(requiredLogged) && !$user.isLogged(); 5698 5699 } else { 5700 // public 5701 if ($utils.isTrue(publicUrl)) { 5702 return false; 5703 } 5704 var required = $utils.isTrue(requiredLogged) || 5705 ($instance.exists() && $instance.current.geo_login && $utils.isTrue($instance.current.geo_login.required)); 5706 if (required) { 5707 return !$user.isLogged() || $utils.isTrue($user.current.not_allowed); 5708 } 5709 return false; 5710 } 5711}; 5712 5713$instance.isLoginDisabled = function() { 5714 if ($instance.current && $instance.current.geo_login) { 5715 var login = $instance.current.geo_login; 5716 if ($utils.isTrue(login.disabled)) { 5717 return true; 5718 } 5719 } 5720 return false; 5721}; 5722 5723$instance.isSafeemployee = function() { 5724 if ($instance.current && $instance.current.products) { 5725 return $instance.current.products.includes('safeemployee'); 5726 } 5727 return false; 5728}; 5729 5730$instance.isTimeAndAttendance = function() { 5731 return $instance.current && 5732 $instance.current.products && 5733 $instance.current.products.includes('time-and-attendance'); 5734}; 5735 5736$instance.isTimeAndAttendanceTabAllowed = function(entityId) { 5737 return $instance.isTimeAndAttendance() && 5738 (entityId === 'instance' || $instance.isAttendantsEntity(entityId) || $instance.isWorkdaysEntity(entityId)); 5739} 5740 5741$instance.isAttendantsEntity = function(entityId) { 5742 return $instance.current && $instance.current.time_and_attendance && 5743 $instance.current.time_and_attendance.attendants_entity === entityId; 5744}; 5745 5746$instance.isWorkdaysEntity = function(entityId) { 5747 return $instance.current && $instance.current.time_and_attendance && 5748 $instance.current.time_and_attendance.workdays_entity === entityId; 5749}; 5750 5751$instance.isMicrosoftAccounts = function() { 5752 return $instance.current && 5753 $instance.current.products && 5754 $instance.current.products.includes('microsoft-accounts'); 5755}; 5756 5757//$instance.getFormViews = function(entity) { 5758// if ($instance.current && $instance.current.formViews) { 5759// var formViews = $instance.current.formViews[entity]; 5760// return formViews ? formViews : []; 5761// } 5762// return []; 5763//}; 5764//$instance.getWebFormViews = function(entity) { 5765// return $instance.getFormViews(entity).filter(function(form) { 5766// return form.context ? form.context.includes('web') : false; 5767// }); 5768//}; 5769// 5770//$instance.getWebCustomFormViews = function(entity) { 5771// return $instance.getFormViews(entity).filter(function(form) { 5772// return form.context ? form.context.includes('web_custom') : false; 5773// }); 5774//}; 5775// 5776//$instance.getCreateFormViews = function(entity) { 5777// return $instance.getFormViews(entity).filter(function(form) { 5778// return form.context ? form.context.includes('backend_create') : false; 5779// }); 5780//}; 5781// 5782//$instance.getUpdateFormViews = function(entity) { 5783// return $instance.getFormViews(entity).filter(function(form) { 5784// return form.context ? form.context.includes('backend_update') : false; 5785// }); 5786//}; 5787 5788$instance.getSpreadsheets = function(entity, isList, download, upload, group) { 5789 var list = []; 5790 var spreadsheets = null; 5791 if ($instance.current == null) { 5792 if ($angular.contentScope.meta) { 5793 spreadsheets = $angular.contentScope.meta.spreadsheets; 5794 } 5795 } else { 5796 spreadsheets = $instance.current.spreadsheets; 5797 } 5798 if (spreadsheets != null) { 5799 for (var k in spreadsheets) { 5800 var item = spreadsheets[k]; 5801 if (entity && item.entities && !item.entities.includes(entity)) { 5802 continue; 5803 } 5804 if (download && !item.download) { 5805 continue; 5806 } 5807 if (upload && !item.upload) { 5808 continue; 5809 } 5810 if (group && item.show_on_group_home !== group) { 5811 continue; 5812 } 5813 //console.log(item); 5814 if (isList && ($utils.isTrue(item.is_list) || $utils.isTrue(item.bulk_download_allowed))) { 5815 list.push(item); 5816 } else if (!isList && !$utils.isTrue(item.is_list)) { 5817 list.push(item); 5818 } 5819 } 5820 } 5821 return list; 5822}; 5823 5824$instance.getNotifiers = function(entities) { 5825 if (entities && $instance.current && $instance.current.notifiers) { 5826 if(!Array.isArray(entities)) { 5827 entities = [entities]; 5828 } 5829 return $instance.current.notifiers.filter(function(notifier) { 5830 return entities.indexOf(notifier.object_entity) >= 0; 5831 }); 5832 } 5833 return []; 5834}; 5835
5836$instance.getTriggers = function(entity) { 5837 if (entity && $instance.current && $instance.current.triggers) { 5838 return $instance.current.triggers.filter(function(trigger) { 5839 return trigger.events && trigger.events.map(function(event) { 5840 return event.object_entity; 5841 }).indexOf(entity) >= 0; 5842 }); 5843 } 5844 return []; 5845}; 5846 5847$instance.getButtonTriggers = function() { 5848 if ($instance.current && $instance.current.buttonTriggers) { 5849 var entity = $angular.contentScope.entityId; 5850 if ($instance.current.buttonTriggers[entity]) { 5851 return $instance.current.buttonTriggers[entity]; 5852 } 5853 } 5854 return []; 5855}; 5856 5857$instance.getButtonTrigger = function(code) { 5858 if (code) { 5859 var list = $instance.getButtonTriggers(); 5860 if (list) { 5861 for (var k in list) { 5862 if (list[k].code == code) { 5863 return list[k]; 5864 } 5865 } 5866 } 5867 } 5868 return null; 5869}; 5870 5871$instance.getDatamixers = function(group) { 5872 if ($instance.current && $instance.current.datamixers) { 5873 return $instance.current.datamixers.filter(function(datamixer) { 5874 return !group || datamixer.show_on_group_home === group; 5875 }); 5876 } 5877 return []; 5878}; 5879 5880$instance.isPublic = function() { 5881 return $utils.isTrue($utils.get($instance.current, "public")); 5882}; 5883 5884$instance.isTrackLocation = function() { 5885 return $constants.isWeb && $utils.isTrue($utils.get($instance.current, 'track_location')); 5886}; 5887 5888$instance.mslogin = false; 5889$instance.isMslogin = function() { 5890 return $constants.isWeb && $instance.mslogin; 5891}; 5892 5893 5894//// File angular.js //// 5895var $angular = {}; 5896 5897$angular.app = null; 5898$angular.factories = {}; 5899$angular.controllers = {}; 5900$angular.components = {}; 5901$angular.title = ""; 5902$angular.rootScope = {}; 5903$angular.headerScope = {}; 5904$angular.menuScope = {}; 5905$angular.contentScope = {}; 5906$angular.customController = {}; 5907$angular.tz = 0; 5908 5909$angular.starting = false; 5910$angular.load = function() { 5911 if ($angular.starting) { 5912 //$init.log("load already started"); 5913 return; 5914 } 5915 $angular.starting = true; 5916 try { 5917 $init.log("start app"); 5918 startApp(); 5919 $init.log("end app"); 5920 } catch (e) { 5921 $init.logError(e); 5922 } 5923}; 5924 5925$angular.log = function(msg, a, b, c) { 5926 $init.logError(msg); 5927 if (a) console.log('o1', a); 5928 if (b) console.log('o2', b); 5929 if (c) console.log('o3', c); 5930 5931 if ($angular.consoleScope) { 5932 $angular.consoleScope.addLog(msg); 5933 } 5934}; 5935 5936//get angular instance 5937$angular.injector = null; 5938$angular.get = function(name) { 5939 if ($angular.injector == null) { 5940 $angular.injector = angular.element(document.body).injector(); 5941 if ($angular.injector == null) { 5942 return null; 5943 } 5944 } 5945 return $angular.injector.get(name); 5946}; 5947 5948$angular.searchInScope = function(name) { 5949 var elem = null; 5950 $('.ng-scope').each(function(){ 5951 var s = angular.element(this).scope(); 5952 var o = s[name]; 5953 if (o != null) { 5954 elem = o; 5955 return false; // stop looking at the rest 5956 } 5957 }); 5958 return elem; 5959}; 5960 5961$angular.element = function(sel) { 5962 return angular.element(document.querySelectorAll(sel)); 5963}; 5964 5965$angular.apply = function($scope, callback) { 5966 $angular.apply2($scope, callback, 0, 0); 5967}; 5968$angular.apply2 = function($scope, callback, tries1, tries2) { 5969 try { 5970 if ($scope && $scope.$apply) { 5971 if ($scope.$$phase) { // controlling digest in progress 5972 if (tries1 == 10) { 5973 $init.logError("Stop apply due to in progress"); 5974 return; 5975 } 5976 tries1++; 5977 setTimeout(function() { 5978 $angular.apply2($scope, callback, tries1, tries2); 5979 }, 50); 5980 return; 5981 } 5982 $scope.$apply(function() { 5983 //$events.updateLastScroll(); 5984 //console.log('good! ' + tries1 + " " + tries2) 5985 if (callback) { 5986 try { 5987 callback(); 5988 } catch (e) { 5989 $init.logError(e); 5990 } 5991 } 5992 }); 5993 } 5994 } catch (e) { 5995 if (tries2 == 3) { 5996 $init.logError(e); 5997 return; 5998 } 5999 tries2++; 6000 setTimeout(function() { 6001 $angular.apply2($scope, callback, tries1, tries2); 6002 }, 50); 6003 } 6004}; 6005 6006$angular.onLoadImg = function(elem) { 6007 var w = elem.naturalWidth; 6008 var h = elem.naturalHeight; 6009 if (h > w) { 6010 $(elem).addClass("portrait"); 6011 } 6012 $angular.upgradeImg(elem); 6013}; 6014$angular.onLoadImgLandscape = function(elem) {
6015 var w = elem.naturalWidth; 6016 var h = elem.naturalHeight; 6017 var ratio = w / h; 6018 if (ratio < 1.1) { 6019 $(elem).addClass("portrait"); 6020 } 6021 $angular.upgradeImg(elem); 6022}; 6023$angular.upgradeImg = function(elem) { 6024 if (document.body.classList.contains('is-scrolling')) { 6025 setTimeout(function() { 6026 $angular.upgradeImg(elem); 6027 }, 250); 6028 return; 6029 } 6030 var href = $(elem).prop("src"); 6031 if ($utils.isBlank(href)) { 6032 return; 6033 } 6034 if (href.contains("."+$angular.imgExtensionFinal)) { 6035 return; 6036 } 6037 if (href.contains("."+$angular.imgExtensionImg)) { 6038 href = href.replace("."+$angular.imgExtensionImg, "."+$angular.imgExtensionFinal); 6039 $(elem).prop("src", href); 6040 return; 6041 } 6042 if (href.contains("."+$angular.imgExtension)) { 6043 href = href.replace("."+$angular.imgExtension, "."+$angular.imgExtensionImg); 6044 $(elem).prop("src", href); 6045 return; 6046 } 6047}; 6048 6049$angular.start = function() { 6050 angular.bootstrap(document.getElementsByTagName('html')[0], ["myApp"]); 6051}; 6052 6053$angular.init = function() { 6054 6055 // init app 6056 $angular.app = angular.module("myApp", $angular.modules); 6057 6058 $angular.tz = $utils.getTimeZoneOffset(); 6059 $instance.languages = $constants.languages; 6060 //console.dir($angular.tz) 6061 6062 // config requirejs to load js dynamically 6063 require.config({ 6064 baseUrl: contextPath, 6065 urlArgs: function(id, url) { 6066 if (url.indexOf('https') > -1) { 6067 return ''; 6068 } 6069 return url; 6070 }, 6071 waitSeconds: 200, 6072 paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.52.2/min/vs' } 6073 }); 6074 6075 // currencies 6076 $angular.currencies = $i18n.currencies; 6077 6078 $angular.app.config(function($provide, $routeProvider, $locationProvider, 6079 $translateProvider, $controllerProvider, $qProvider, $sceProvider) { 6080 6081 try { 6082 $init.log("start config"); 6083 6084 // $compileProvider.debugInfoEnabled(false); TODO no work 6085 $qProvider.errorOnUnhandledRejections(true); 6086 $sceProvider.enabled(false); // all html is trusted :) 6087 6088 $provide.decorator("$exceptionHandler", function() { 6089 return function(exception, cause) { 6090 $init.logError(exception); 6091 }; 6092 }); 6093 6094 // init route 6095 $angular.prepareRouteProvider($routeProvider); 6096 6097 // to use url without '#' 6098 $locationProvider.html5Mode(true); 6099 6100 // init i18n 6101 var urlLang = getParam("_lang"); 6102 if (!$utils.isBlank(urlLang)) { 6103 // check request param _lang 6104 $locale.language = urlLang; 6105 $cookiesService.put("_language", $locale.language, 90); 6106 } else { 6107 // check cookie 6108 var clang = $cookiesService.get("_language"); 6109 if (!$utils.isBlank(clang)) { 6110 $locale.language = clang; 6111 } 6112 } 6113 $locale.default_lang = "en"; 6114 if ($locale.language == "") { 6115 $locale.language = $locale.default_lang; 6116 } 6117 var availables = { 6118 '*': $locale.default_lang 6119 } 6120 for (var key in $constants.languages) { 6121 var lang = $constants.languages[key]; 6122 availables[lang + '*'] = lang; 6123 } 6124 for (var lng in $i18n.messages) { 6125 $translateProvider.translations(lng, $i18n.messages[lng]); 6126 } 6127 $translateProvider 6128 .useSanitizeValueStrategy('escapeParameters') 6129 .registerAvailableLanguageKeys($constants.languages, availables) 6130 .fallbackLanguage($locale.default_lang) 6131 .preferredLanguage($locale.language); 6132 6133 6134 // improve scroll without blinks 6135 window.addEventListener('wheel', function () { 6136 // do nothing 6137 }, { passive: true }); 6138 6139 // Disable pointer events during scroll to optimize rendering performance 6140 (function() { 6141 var scrollTimeout; 6142 window.addEventListener('scroll', function () { 6143 if (!document.body.classList.contains('is-scrolling')) { 6144 document.body.classList.add('is-scrolling'); 6145 } 6146 clearTimeout(scrollTimeout); 6147 scrollTimeout = setTimeout(function () { 6148 document.body.classList.remove('is-scrolling'); 6149 }, 150); 6150 }, { passive: true }); 6151 })(); 6152 6153 $init.log("end config"); 6154 6155 } catch (e) { 6156 // catch errors manually here 6157 $init.logError(e); 6158 } 6159 6160 }); 6161 6162 if ($angular.modules.indexOf('ngTagsInput') != -1) { 6163 $angular.app.config(function(tagsInputConfigProvider) { 6164 $angular.tagsInputConfigProvider = tagsInputConfigProvider; 6165 }); 6166 } 6167 6168 for (var name in $angular.factories) { 6169 $angular.app.factory(name, $angular.factories[name]); 6170 } 6171 for (var name in $angular.controllers) { 6172 $angular.app.controller(name, $angular.controllers[name]); 6173 } 6174 for (var name in $angular.components) { 6175 $angular.app.component(name, $angular.components[name]); 6176 } 6177 6178 $angular.app.controller('console', function($rootScope, $scope, $sce, $timeout) { 6179 $angular.consoleScope = $scope; 6180 $scope.showConsole = false; 6181 $scope.consoleContent = ""; 6182 $scope.consoleList = ""; 6183 $timeout(function() { 6184 $("#console").removeClass("hidden"); 6185 }); 6186 $scope.addLog = function(o) { 6187 //console.log('log', o) 6188 if (o == null) { 6189 return; 6190 } 6191 if (!$user.showConsole()) { 6192 return; 6193 } 6194 var show = false; 6195 if (typeof o == 'string') { 6196// var date = new Date().getTime(); 6197// var msg = $utils.parseDateTotal(date) + ' ERROR ' + o; 6198 var msg = o; 6199 console.warn(msg); 6200 $scope.consoleList = '<li class="WARN">' + msg + "</li>" + $scope.consoleList; 6201 show = true; 6202 } 6203 if ($utils.isArray(o)) { 6204 for (var x in o.reverse()) { 6205 var item = o[x]; 6206 //var date = item.date; //new Date().getTime(); 6207 if ($scope.consoleList.contains(item.msg)) { 6208 continue; 6209 } 6210 //var msg = $utils.parseDateTotal(date) + ' ' + item.level + ' ' + item.msg; 6211 var msg = item.msg; 6212 console.warn(msg); 6213 $scope.consoleList = '<li class="' + item.level + '">' + msg + "</li>" + $scope.consoleList; 6214 if (item.level != 'INFO') { 6215 show = true; 6216 } 6217 } 6218 } 6219 $scope.consoleContent = $sce.trustAsHtml( 6220 '<span class="close material-icons" onclick="$angular.clearConsole()">close</span> ' 6221 + '<div class="panel panel-default"><div class="panel-body"><ul>' + $scope.consoleList + '</ul></div></div>'); 6222 if (!$scope.showConsole) { 6223 $scope.showConsole = true; 6224 $angular.apply($scope, function() { 6225 $("#console").click(); 6226 }); 6227 } 6228 }; 6229 }); 6230 $angular.clearConsole = function() { 6231 // $("#console").click(); 6232 $angular.consoleScope.showConsole = false; 6233 $angular.consoleScope.consoleContent = ""; 6234 $angular.consoleScope.consoleList = ""; // clear logs 6235 $angular.apply($angular.consoleScope); 6236 }; 6237 6238 $angular.app.directive('iframeSrc', function() { 6239 return { 6240 link: function(scope, element, attrs) { 6241 //console.log('iframeSrc ' + attrs.iframeSrc) 6242 element[0].src = $angular.get('$sce').trustAsResourceUrl(attrs.iframeSrc); 6243 } 6244 }; 6245 }); 6246 6247 $angular.app.directive("autopath", function() { 6248 return { 6249 restrict: 'A', 6250 require: 'ngModel', 6251 scope: { entity: '@', innerEntity: '@', autopath: '=' }, 6252 link: function(scope, element, iAttrs, ngModelCtrl) { 6253 var _auto = null; 6254 var _source = null; 6255 element.bind('focus', function() { 6256 var source; 6257 if (scope.autopath === false) { 6258 source = []; 6259 } else if ($utils.isArray(scope.autopath)) { 6260 source = scope.autopath; 6261 } else { 6262 source = contextPath + "/api/autopath.json?entity=" + scope.entity; 6263 var innerEntity = scope.innerEntity; 6264 if (innerEntity) { 6265 source += "&innerEntity=" + innerEntity; 6266 } 6267 } 6268 if (source !== _source) { 6269 _source = source; 6270 _auto = element.autocomplete({ 6271 classes: { "ui-autocomplete": "zoom" }, 6272 minLength: 0, 6273 source: source, 6274 select: function(event, ui) { 6275 ngModelCtrl.$setViewValue(ui.item.value); 6276 } 6277 });
6278 } 6279 6280 // force key down to open 6281 var e = jQuery.Event("keydown"); 6282 e.which = 40; 6283 _auto.trigger(e); 6284 }); 6285 } 6286 } 6287 }); 6288 6289 $angular.app.directive("autoclasses", function() { 6290 return { 6291 restrict: 'A', 6292 require: 'ngModel', 6293 link: function(scope, element, iAttrs) { 6294 element.autocomplete({ 6295 classes: { "ui-autocomplete": "zoom" }, 6296 minLength: 0, 6297 source: function(request, response) { 6298 response(["group-bar", "group-card", "button-centered"]); 6299 } 6300 }).focus(function() { 6301 $(this).autocomplete("search"); 6302 }); 6303 } 6304 } 6305 }); 6306 6307 $angular.app.directive("extSubmit", ['$timeout', function($timeout) { 6308 return { 6309 link: function($scope, $el, $attr) { 6310 $scope.$on('makeSubmit', function(event, data) { 6311 if (data.formName === $attr.name) { 6312 $timeout(function() { 6313 $el.triggerHandler('submit'); 6314 }, 0, false); 6315 } 6316 }) 6317 } 6318 }; 6319 }]); 6320 6321 // ui-select - refresh-on-active 6322 $angular.app.directive('refreshOnActive', function() { 6323 return { 6324 restrict: 'A', 6325 link: refreshOnActiveLink, 6326 scope: { 6327 refreshOnActive: '=', 6328 refresh: '@' 6329 } 6330 } 6331 6332 function refreshOnActiveLink(scope, element) { 6333 if (!scope.refreshOnActive === true) { 6334 return; 6335 } 6336 var storedFunction = scope.$parent.$select.refresh; 6337 scope.$parent.$select.refresh = function() { }; 6338 6339 var element = angular.element(element).closest('.ui-select-container'); 6340 var fn = function() { 6341 scope.$parent.$select.refresh = function() { 6342 storedFunction(scope.refresh); 6343 }; 6344 scope.$parent.$select.refresh.call(); 6345 element.unbind('click', fn); 6346 }; 6347 element.bind('click', fn); 6348 } 6349 }); 6350 6351 $angular.app.directive('inputNumber', function() { 6352 return { 6353 require: 'ngModel', 6354 link: function(scope, element, attrs, ngModel) { 6355 ngModel.$formatters.push(function(value) { 6356 if (value) { 6357 if (typeof value == 'number') { 6358 return value; 6359 } 6360 if ($utils.isArray(value) && value.length == 1) { 6361 value = value[0]; 6362 } 6363 if (typeof value == 'number') { 6364 return value; 6365 } 6366 if (typeof value == 'string') { 6367 return parseFloat(value); 6368 } 6369 $angular.log("Not number: " + JSON.stringify(value)); 6370 return null; 6371 } 6372 return value; 6373 }); 6374 } 6375 }; 6376 }); 6377 6378 $angular.app.directive('inputDatetime', function() { 6379 return { 6380 require: 'ngModel', 6381 link: function(scope, element, attrs, ngModel) { 6382 ngModel.$parsers.push(function(value) { 6383 //console.log('datetime parse', value) OUT 6384 if (value == null) { 6385 return null; 6386 } 6387 var val = value.getTime(); 6388 return val; 6389 }); 6390 ngModel.$formatters.push(function(value) { 6391 //console.log('datetime format', value) IN 6392 if (value == null) { 6393 return null; 6394 } 6395 var d = $utils.toDate(value); 6396 if (d != null) { 6397 d.setSeconds(0,0); 6398 } 6399 return d; 6400 }); 6401 } 6402 }; 6403 }); 6404 $angular.app.directive('inputDate', function() { 6405 return { 6406 require: 'ngModel', 6407 link: function(scope, element, attrs, ngModel) { 6408 ngModel.$parsers.push(function(value) { 6409 return $utils.toISODay(value); 6410 }); 6411 ngModel.$formatters.push(function(value) { 6412 return $utils.parseDay(value); 6413 }); 6414 } 6415 }; 6416 }); 6417 6418 $angular.app.directive('restrictTo', function() { 6419 return { 6420 restrict: 'A', 6421 link: function(scope, element, attrs) { 6422 var re = RegExp(attrs.restrictTo); 6423 var exclude = /Backspace|Enter|Tab|Delete|Del|ArrowUp|Up|ArrowDown|Down|ArrowLeft|Left|ArrowRight|Right/; 6424 6425 element[0].addEventListener('keydown', function(event) { 6426 if (!exclude.test(event.key) && !re.test(event.key)) { 6427 event.preventDefault(); 6428 } 6429 }); 6430 } 6431 } 6432 }); 6433 6434 $angular.app.directive("ngUploadChange", function() { 6435 return { 6436 scope: { 6437 ngUploadChange: "&" 6438 }, 6439 link: function($scope, $element) { 6440 $element.on("change", function(event) { 6441 $angular.apply($scope, function() { 6442 $scope.ngUploadChange({ $event: event }); 6443 });
6444 }) 6445 $scope.$on("$destroy", function() { 6446 $element.off(); 6447 }); 6448 } 6449 } 6450 }); 6451 6452 $angular.app.directive("monacoEditor", function() { 6453 return { 6454 restrict: 'E', 6455 scope: { 6456 code: '=', 6457 language: '@', 6458 theme: '@' 6459 }, 6460 link: function (scope, element) { 6461 6462 require(["vs/editor/editor.main"], function () { 6463 //console.log('Loaded monaco', monaco) 6464 6465 var editor = monaco.editor.create(element[0], { 6466 value: scope.code || '', 6467 language: scope.language, 6468 theme: "vs-dark", 6469 automaticLayout: true 6470 }); 6471 6472 // Update model on editor change 6473 editor.onDidChangeModelContent(function() { 6474 scope.$apply(function() { 6475 scope.code = editor.getValue(); 6476 }); 6477 }); 6478 6479 // Watch for external changes to `code` 6480 scope.$watch('code', function(newValue) { 6481 if (newValue !== editor.getValue()) { 6482 editor.setValue(newValue || ''); 6483 } 6484 }); 6485 6486 }); 6487 } 6488 }; 6489 }); 6490 6491 $angular.app.directive('encryptedField', function() { 6492 return { 6493 restrict: 'E', 6494 scope: { 6495 model: '=', 6496 field: '=' 6497 }, 6498 template: ` 6499 <input type="{{inputType}}" 6500 ng-model="inputValue" 6501 ng-change="handleChange()" 6502 class="form-control" /> 6503 `, 6504 link: function(scope) { 6505 const ENCRYPTED_PREFIX = '{enc}'; 6506 const MASK = '****************'; 6507 6508 const originalValue = scope.model != null ? scope.model[scope.field] : null; 6509 const isEncrypted = originalValue && originalValue.startsWith(ENCRYPTED_PREFIX); 6510 6511 scope.inputType = isEncrypted ? 'password' : 'text'; 6512 scope.inputValue = isEncrypted ? MASK : ''; 6513 6514 let wasModified = false; 6515 scope.handleChange = function() { 6516 if (isEncrypted && !wasModified && scope.inputValue !== MASK) { 6517 scope.inputValue = ''; // limpiar si se modifica cualquier carácter 6518 scope.inputType = 'text'; // mostrar texto plano 6519 wasModified = true; 6520 } 6521 scope.model[scope.field] = scope.inputValue; 6522 }; 6523 } 6524 }; 6525 }); 6526 6527 6528 6529 $angular.app.animation('.reveal-animation', function() { 6530 return { 6531 enter: function(element, done) { 6532 element.css('display', 'none'); 6533 element.fadeIn(200, done); 6534 //element.show(); 6535 return function() { 6536 element.stop(); 6537 } 6538 }, 6539 leave: function(element, done) { 6540 element.hide();//fadeOut(500, done) 6541 element.remove(); 6542 return function() { 6543 element.stop(); 6544 } 6545 } 6546 } 6547 }); 6548 6549} 6550 6551$angular.prepareComponent = function(self, $scope, $timeout) { 6552 6553 // to access root scope vars 6554 var rs = $angular.rootScope; 6555 for (var k in rs) { 6556 if (k.startsWith("$")) { 6557 continue; 6558 } 6559 $scope[k] = rs[k]; 6560 //console.log(k, $scope[k]) 6561 } 6562 $scope.$utils = $utils; 6563 $scope.$angular = $angular; 6564 $scope.$constants = $constants; 6565 $scope.$user = $user; 6566 $scope.$entity = $entity; 6567 $scope.$instance = $instance; 6568 $scope.$locale = $locale; 6569 $scope.$events = $events; 6570 $scope.$media = $media; 6571 $scope.$cart = $cart; 6572 6573 $timeout(function() { 6574 $scope.refresh(); 6575 }); 6576 6577 return self; 6578} 6579 6580$angular.initRootScope = function($rootScope, $location, $window, $timeout, isWeb) { 6581 6582 $angular.rootScope = $rootScope; 6583 6584 // constants 6585 $constants.isDev = location.host.indexOf('localhost') !== -1; 6586 $constants.isWeb = isWeb; 6587 $constants.isPro = isPro; 6588 $constants.isCustomDomain = isCustomDomain; 6589 6590 $angular.rootScope.$utils = $utils; 6591 $angular.rootScope.$angular = $angular; 6592 $angular.rootScope.$constants = $constants; 6593 $angular.rootScope.$user = $user; 6594 $angular.rootScope.$entity = $entity; 6595 $angular.rootScope.$instance = $instance; 6596 $angular.rootScope.$locale = $locale; 6597 $angular.rootScope.$events = $events; 6598 $angular.rootScope.$media = $media; 6599 if (typeof $cart != 'undefined') { 6600 $angular.rootScope.$cart = $cart; 6601 } 6602 6603 $angular.rootScope.contextPath = contextPath; 6604 $angular.rootScope.rootPath = rootPath; 6605 6606 $angular.initMap();
6607 $angular.initServiceWorker(); 6608 6609 // TODO improve image load 6610 $rootScope.imgExtension = "thumb"; 6611 $rootScope.imgExtensionImg = "img"; 6612 $rootScope.imgExtensionFinal = "big"; 6613 6614 $angular.imgExtension = $rootScope.imgExtension; 6615 $angular.imgExtensionImg = $rootScope.imgExtensionImg; 6616 $angular.imgExtensionFinal = $rootScope.imgExtensionFinal; 6617 6618 // init firebase 6619 if (typeof firebase != 'undefined') { 6620 firebase.initializeApp({ 6621 apiKey: "AIzaSyDiSBSk5BN9XX1uILUQ6KiEylso1xKr4DA", 6622 authDomain: "geo-we.firebaseapp.com", 6623 databaseURL: "https://geo-we.firebaseio.com", 6624 projectId: "geo-we", 6625 storageBucket: "geo-we.appspot.com", 6626 messagingSenderId: "372903613421", 6627 appId: "1:372903613421:web:08c3174e8c857f08" 6628 }); 6629 } 6630 6631// $rootScope.$on('$translateChangeSuccess', function() { 6632// }); 6633 6634 $rootScope.$on('$routeChangeError', function(event, next, previous, error) { 6635 $angular.log(error); 6636 }); 6637 6638 $angular.isBackNavigation = false; 6639 $window.addEventListener('popstate', function() { 6640 $angular.isBackNavigation = true; 6641 //console.log('is back navigation') 6642 }); 6643 $angular.positions = {}; 6644 $rootScope.$on('$locationChangeStart', function(a,b,c) { 6645 var name = c; 6646 var pos = $window.pageYOffset; 6647 $angular.positions[name] = pos; 6648 $angular.ready = false; 6649 //console.log("save: " + name + " = " + pos); 6650 }); 6651 6652 $angular.openLicense = function(key, showButtons) { 6653 $angular.openModal("panel-licenses", { key:key, showButtons:showButtons, size:'lg' }); 6654 }; 6655 6656 $rootScope.getCurrentPath = function() { 6657 return contextPath + $angular.get('$location').path(); 6658 }; 6659 6660 // fullscreen 6661 $rootScope.clickImage = function(e, list, index) { 6662 $utils.preventDefault(e); 6663 // if (typeof index != 'number' && index.$parent) { 6664 // index = index.$parent.carousel.getCurrentIndex(); 6665 // } 6666 $rootScope.fsList = list; 6667 $rootScope.fsIndex = index; 6668 $rootScope.fsShow = true; 6669 }; 6670 $rootScope.closeImages = function() { 6671 $rootScope.fsShow = false; 6672 $rootScope.fsList = []; 6673 $rootScope.fsIndex = 0; 6674 }; 6675 6676 $angular.rootScope.debounceOptions = { 6677 updateOn: 'default blur', 6678 debounce: { 6679 blur: 0, 6680 '*': 1000 6681 } 6682 }; 6683 6684 // keep last wiki search 6685 $angular.rootScope.wikiPages = []; 6686 6687 // youtube config 6688 $angular.rootScope.youtubeVars = { 6689 autoplay: 0, 6690 playsinline: 0, 6691 rel: 0, 6692 showinfo: 0, 6693 enablejsapi: 1 6694 }; 6695 6696 $angular.rootScope.cronGenConfig = { 6697 use24HourTime: true, 6698 hideAdvancedTab: false 6699 }; 6700 6701 // text editor toolbar 6702 $angular.rootScope.taToolbarHidden = []; 6703 $angular.rootScope.taToolbar = [ 6704 ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'pre', 'quote'], 6705 ['fontColor', 'backgroundColor', 'bold', 'italics', 'underline', 'strikeThrough', 'ul', 'ol', 'redo', 'undo', 'clear'], 6706 ['justifyLeft', 'justifyCenter', 'justifyRight', 'indent', 'outdent'], 6707 ['html', 'insertImage', 'geoInsertImage', 'insertLink', 'insertVideo', 'wordcount', 'charcount'], 6708 ['wikipedia'] 6709 ]; 6710 $angular.rootScope.tinymceOptions = { 6711 min_height: 0, 6712 max_height: 400, 6713 autoresize_bottom_margin: 0, 6714 setup: function(editor) { 6715 editor.on("init", function() { 6716 editor._element = $(editor.container); 6717 editor._header = editor._element.find(".tox-editor-header"); 6718 editor._footer = editor._element.find(".tox-statusbar"); 6719 editor._header.hide(); 6720 editor._footer.hide(); 6721 }); 6722 editor.on('focus', function() { 6723 editor._element.addClass("focus"); 6724 editor._header.slideDown('fast'); 6725 editor._footer.slideDown('fast'); 6726 }); 6727 editor.on('blur', function() { 6728 editor._element.removeClass("focus"); 6729 editor._header.slideUp('fast'); 6730 editor._footer.slideUp('fast'); 6731 }); 6732 6733 editor.ui.registry.addButton('wiki', { 6734// icon: 'insert-time', 6735 tooltip: 'Wikipedia', 6736 text: 'W', 6737 onAction: function(_) { 6738 $angular.openModal("panel-wikipedia", { 6739 size: 'xl', 6740 editor: editor 6741 }); 6742 } 6743 }); 6744 }, 6745 //menubar:false, 6746 //statusbar: false, 6747 plugins: [ 6748 'autoresize advlist autolink link image lists charmap print preview hr anchor pagebreak', 6749 'searchreplace wordcount visualblocks visualchars code fullscreen insertdatetime media nonbreaking', 6750 'table emoticons template paste' // help 6751 ],
6752 toolbar: 'fullscreen code wiki | undo redo | bold italic underline strikethrough removeformat | ' 6753 + 'alignleft aligncenter alignright alignjustify | outdent indent | numlist bullist | forecolor backcolor | ' 6754 + 'image media link | charmap emoticons | fontselect fontsizeselect formatselect', 6755 quickbars_selection_toolbar: 'bold italic | quicklink h2 h3 blockquote quickimage quicktable', 6756 automatic_uploads: true, 6757 image_caption: true, 6758 relative_urls: false, 6759 remove_script_host: false, 6760 convert_urls: false, 6761 images_reuse_filename: true, 6762 valid_elements: '+*[*]', 6763 paste_enable_default_filters: false, 6764 paste_remove_styles_if_webkit: false, 6765 paste_webkit_styles: 'all', 6766 paste_retain_style_properties: 'all', 6767 images_upload_handler: function(blobInfo, success, failure, progress) { 6768 6769 if (!(blobInfo.blob() instanceof File)) { 6770 //console.log('image upload canceled due to it is not file'); 6771 //failure('canceled due to it is not file'); 6772 return; 6773 } 6774 6775 var xhr = new XMLHttpRequest(); 6776 xhr.withCredentials = false; 6777 6778 var url = 'api/geo/' + $angular.contentScope.entity + '/' + $angular.contentScope.entityId + '/createImage.json'; 6779 6780 xhr.open('POST', url); 6781 xhr.upload.onprogress = function(e) { 6782 progress(e.loaded / e.total * 100); 6783 }; 6784 xhr.onerror = function() { 6785 failure('Image upload failed. Code: ' + xhr.status); 6786 }; 6787 xhr.onload = function() { 6788 if (xhr.status != 200) { 6789 failure('Error: ' + xhr.status, { remove: true }); 6790 return; 6791 } 6792 var json = JSON.parse(xhr.responseText); 6793 if (!json || typeof json.location != 'string') { 6794 failure('Invalid JSON: ' + xhr.responseText); 6795 return; 6796 } 6797 console.log('location: ' + json.location); 6798 success(json.location); 6799 6800 setTimeout(function() { 6801 delete $angular.contentScope.model.sys_updated; 6802 $angular.contentScope.refreshMedia(); 6803 }, 1000); 6804 }; 6805 6806 var formData = new FormData(); 6807 formData.append('file', blobInfo.blob(), blobInfo.filename()); 6808 xhr.send(formData); 6809 } 6810 }; 6811 6812 if (typeof Dropzone != 'undefined') { 6813 // Dropzone - http://www.dropzonejs.com 6814 Dropzone.autoDiscover = false; 6815 $angular.rootScope.dzOptions = { 6816 paramName: 'file', 6817 parallelUploads: 1, 6818 //acceptedFiles : 'image/*', 6819 //addRemoveLinks : true, 6820 timeout: 900000, // ms 6821 maxFilesize: '500' // MB 6822 }; 6823 $angular.rootScope.getDzOptions = function() { 6824 $angular.rootScope.dzOptions.dictDefaultMessage = $angular.get("$translate").instant("msg.dropzone.drop"); 6825 return $angular.rootScope.dzOptions; 6826 } 6827 $angular.rootScope.dzMethods = {}; 6828 $angular.rootScope.dzCallbacks = { 6829 'sending': function(file, xhr, formData) { 6830 if ($angular.contentScope.dropzoneSending) { 6831 $angular.contentScope.dropzoneSending(file, xhr, formData); 6832 } 6833 }, 6834 'addedfile': function(file) { 6835 if ($angular.contentScope.dropzoneAddedFile) { 6836 $angular.contentScope.dropzoneAddedFile(file); 6837 } 6838 }, 6839 'removedfile': function(file) { 6840 }, 6841 'success': function(file, data) { 6842 $angular.rootScope.dzMethods.getDropzone().removeFile(file); 6843 6844 if ($angular.contentScope.dropzoneSuccessFile) { 6845 $angular.contentScope.dropzoneSuccessFile(file, data); 6846 } 6847 $utils.floatingMsg($angular.get("$translate").instant("msg.updated")); 6848 }, 6849 'canceled': function(file, response) { 6850 $angular.rootScope.dzMethods.getDropzone().removeFile(file); 6851 6852 if ($angular.contentScope.dropzoneErrorFile) { 6853 $angular.contentScope.dropzoneErrorFile(file, response); 6854 } 6855 6856 var msg = ""; 6857 if (response && response.message) { 6858 msg = response.message; 6859 } else { 6860 msg = $angular.get("$translate").instant("msg.error"); 6861 } 6862 $utils.floatingError(msg); 6863 }, 6864 'error': function(file, response) { 6865 console.log('error') 6866 $angular.rootScope.dzMethods.getDropzone().removeFile(file); 6867 6868 if ($angular.contentScope.dropzoneErrorFile) { 6869 $angular.contentScope.dropzoneErrorFile(file, response); 6870 } 6871 6872 var msg = ""; 6873 if (response && response.message) { 6874 msg = response.message; 6875 } else { 6876 msg = $angular.get("$translate").instant("msg.error"); 6877 } 6878 $utils.floatingError(msg); 6879 }, 6880 'queuecomplete': function() { 6881 if ($angular.contentScope.dropzoneCallback) { 6882 $angular.contentScope.dropzoneCallback(); 6883 } 6884 } 6885 }; 6886 } 6887 6888 // columns methods 6889 $rootScope.selectComboItem = function(entity, model, columnName, $select, isCategories) { 6890 var item = $select.selected; 6891 if (item != null) { 6892 if ($utils.isArray(item) && item.length > 0) { 6893 item = item[0]; 6894 } 6895 if (item.name == "..." && item.id == null) { 6896 // load more data 6897 if (isCategories) { 6898 $constants.getCategoryList(entity, $select.search, true); 6899 } else { 6900 $constants.getEntityList(entity, $select.search, true); 6901 } 6902 model[columnName] = null; 6903 return; 6904 } 6905 if (item._id) { 6906 item = item._id; 6907 } 6908 if (item.id) { 6909 item = item.id; 6910 } 6911 } 6912 model[columnName] = item; 6913 $select.close(); 6914 }; 6915 $rootScope.addComboItem = function(entity, model, columnName, $select, isCategories) { 6916 var item = $select ? $select.selected : null; 6917 if (item == null || model == null) { 6918 return; 6919 } 6920 if ($utils.isArray(item) && item.length > 0) { 6921 item = item[0]; 6922 } 6923 if (item.name == "..." && item.id == null) { 6924 // load more data 6925 if (isCategories) { 6926 $constants.getCategoryList(entity, $select.search, true); 6927 } else { 6928 $constants.getEntityList(entity, $select.search, true); 6929 } 6930 return; 6931 } 6932 if (model[columnName] == null) { 6933 model[columnName] = []; 6934 } 6935 if (item._id) { 6936 item = item._id; 6937 } 6938 if (item.id) { 6939 item = item.id; 6940 } 6941 if (model[columnName].indexOf(item) != -1) { 6942 $utils.floatingError($angular.get("$translate").instant("msg.exists")); 6943 return; 6944 } 6945 if (!$utils.isArray(model[columnName])) { 6946 $angular.log('addComboItem: trying to add value to ' + (typeof model[columnName])) 6947 } else { 6948 model[columnName].push(item); 6949 } 6950 6951 try { 6952 $select.close(); 6953 } catch (e) { 6954 } 6955 }; 6956 $rootScope.addComboAnyEntity = function(model, columnName, entity, entityId) { 6957 if (model[columnName] == null) { 6958 model[columnName] = []; 6959 } 6960 if (!$utils.isArray(model[columnName])) { 6961 return; 6962 } 6963 var item = { entity: entity, entity_id: entityId }; 6964 model[columnName].push(item); 6965 }; 6966 $rootScope.addToCombo = function(model, columnName, $select) { 6967 var item = $select ? $select.selected : null; 6968 if (item == null || model == null) { 6969 return; 6970 } 6971 if (model[columnName] == null) { 6972 model[columnName] = []; 6973 } 6974 if (!$utils.isArray(model[columnName])) { 6975 return; 6976 } 6977 model[columnName].push(item); 6978 }; 6979 $rootScope.parseComboItem = function(item) { 6980 if (item._id) { 6981 item = item._id; 6982 } 6983 if (item.id) { 6984 item = item.id; 6985 } 6986 return item; 6987 }; 6988 $rootScope.removeComboItem = function(e, model, columnName, item) { 6989 $utils.preventDefault(e); 6990 var orig = item; 6991 if (item._id) { 6992 item = item._id; 6993 } 6994 if (item.id) { 6995 item = item.id; 6996 } 6997 var list = model[columnName]; 6998 if (list) { 6999 if (!$utils.isArray(list)) { 7000 list = []; 7001 model[columnName] = list; 7002 } 7003 for (var key in list) { 7004 var itemList = list[key]; 7005 if (itemList == item || itemList == orig) { 7006 list.splice(key, 1); 7007 break; 7008 } 7009 } 7010 } 7011 }; 7012 $rootScope.cloneComboItem = function(e, model, column, item, opts) { 7013 $utils.preventDefault(e); 7014 if (model[column.name] == null) { 7015 model[column.name] = []; 7016 } 7017 if (!$utils.isArray(model[column.name])) { 7018 $angular.log('cloneComboItem: trying to add value to ' + (typeof model[column.name])) 7019 return; 7020 } 7021 7022 $rest.post({ 7023 loading: "generic",
7024 url: contextPath + "/api/geo-new/" + column.param + "/" + item + "/copy.json", 7025 data: { copyToEntity: column.param } 7026 }).then(function(o) { 7027 model[column.name].push(o.id); 7028 $utils.autoSave(model, column, opts.extra); 7029 }); 7030 }; 7031 $rootScope.getColumnList = function(model, column) { 7032 if (model && column && column.column) { 7033 var l = model[column.column]; 7034 if (l && $utils.isArray(l)) { 7035 return l; 7036 } 7037 } 7038 return []; 7039 }; 7040 $rootScope.initTags = function(model, column) { 7041 var value = model[column]; 7042 if ($utils.isArray(value)) { 7043 return value; 7044 } 7045 if (value && typeof value == 'string') { 7046 model[column] = value.split(","); 7047 return model[column]; 7048 } 7049 model[column] = []; 7050 return model[column]; 7051 }; 7052 $rootScope.getEntityFromFormula = function(formula) { 7053 var split = formula.split("(")[1].split(","); 7054 if (formula.contains('custom_relation') && split.length > 1) { 7055 return split[1]; 7056 } 7057 var result = split[0]; 7058 //console.log(formula + " -> " + result) 7059 return result; 7060 }; 7061 $rootScope.removeFormulaRelation = function(e, formula, list, item) { 7062 $utils.preventDefault(e); 7063 7064 var path = contextPath + "/api/geo/" + item.entity + "/" + item.id + ".json?force=true"; 7065 $rest.remove({ 7066 url: path, 7067 loading: "generic", 7068 confirmTitle: $angular.get("$translate").instant("msg.remove"), 7069 successMessage: $angular.get("$translate").instant('msg.removed') 7070 }).then(function(o) { 7071 $angular.contentScope.refresh(); 7072 }); 7073 }; 7074 7075 $rootScope.validateTranslate = function(model, name) { 7076 var value = model[name]; 7077 if ($utils.isObject(value)) { 7078 if (value[$locale.language]) { 7079 value = value[$locale.language]; 7080 } else { 7081 var keys = $utils.keys(value); 7082 if (keys.length > 0) { 7083 value = value[keys[0]]; 7084 } 7085 } 7086 model[name] = value; 7087 } 7088 return true; 7089 }; 7090 $rootScope.parseTranslate = function(o) { 7091 if (typeof o == 'string') { 7092 var val = o; 7093 o = {}; 7094 o[$instance.languages[0]] = val; 7095 } 7096 return o; 7097 }; 7098 $rootScope.parseLangs = function(o, name) { 7099 o[name] = $rootScope.parseTranslate(o[name]); 7100 }; 7101 $rootScope.getColumnLang = function(model) { 7102 var o = { 7103 lang : $instance.languages[0], 7104 languages : $utils.cloneList($instance.languages) 7105 }; 7106 if (model && typeof model == 'object') { 7107 var hasData = !$utils.isBlank(model[o.lang]); 7108 for (var k in model) { 7109 if (!o.languages.includes(k)) { 7110 o.languages.push(k); 7111 } 7112 if (!hasData && !$utils.isBlank(model[k])) { 7113 o.lang = k; 7114 hasData = true; 7115 } 7116 } 7117 } 7118 return o; 7119 }; 7120 $rootScope.gtranslate = function(model, key, lang, html) { 7121 if (model && model[key]) { 7122 var text = model[key][lang]; 7123 if ($utils.isBlank(text)) { 7124 return; 7125 } 7126 //console.log(text) 7127 $angular.openModal("panel-translate", { 7128 size: 'xl', 7129 lang:lang, 7130 text:text, 7131 html:html, 7132 successFunction: function(o) { 7133 model[key][o.lang] = o.text; 7134 } 7135 }); 7136 } 7137 }; 7138 7139 $rootScope.openAddEntityModal = function(entity, model, column, isList) { 7140 $angular.openModalLocal("panel-add-entity", { 7141 entity: entity, 7142 size: 'xl' 7143 }).then(function(createdObject) { 7144 if (model) { 7145 if (isList) { 7146 if (model[column] == null || !$utils.isArray(model[column])) { 7147 model[column] = []; 7148 } 7149 if (!model[column].includes(createdObject.id)) { 7150 model[column].push(createdObject.id); 7151 } 7152 } else { 7153 model[column] = createdObject.id; 7154 } 7155 } 7156 if ($angular.contentScope.submitGeoEdit) { 7157 $angular.contentScope.submitGeoEdit(); 7158 } 7159 }); 7160 }; 7161 7162 $rootScope.columnButtonHref = function(column, model) { 7163 if (column && model) { 7164 if (column.type === 'link' || (column.type === 'button' && column.action === 'link')) { 7165 var link = column.link; 7166 if ($utils.isBlank(link)) { 7167 // check value 7168 link = model[column.name]; 7169 if ($utils.isBlank(link)) { 7170 return ""; 7171 } 7172 } 7173 if (link.startsWith('/')) { 7174 link = link.substring(1); 7175 } 7176 link = $entity.parseQuery(link, model); 7177 7178 if (!link.startsWith("http") && !$constants.isCustomDomain) { 7179 if (!link.startsWith("home") && !link.startsWith("admin")) { 7180 link = $instance.getBaseUrl() + link; 7181 } 7182 } 7183 return link; 7184 } 7185 } 7186 return ""; 7187 }; 7188 7189 $rootScope.isColumnLinkBlank = function(column, model) { 7190 var link = $rootScope.columnButtonHref(column, model); 7191 return link && link.startsWith('http'); 7192 }; 7193 7194 $angular.searchRootModel = function() { 7195 if ($("div.panel-add-entity.show").length > 0) { // panel-add-entity 7196 return $angular.panelAddEntityScope.model; 7197 } 7198 if ($angular.contentScope.webFormItem) { // web-home 7199 var item = $angular.contentScope.webFormItem; 7200 if (item.type == 'formview') { 7201 return item.form.data; 7202 } 7203 return item.model; 7204 } 7205 if ($angular.contentScope.form) { // web-item 7206 return $angular.contentScope.form.data; 7207 } 7208 if ($angular.contentScope.geoForm) { // geo-new, geo-edit 7209 return $angular.contentScope.geoForm.data; 7210 } 7211 if ($angular.contentScope.model) { // others 7212 return $angular.contentScope.model; 7213 } 7214 $angular.log('Root model not found'); 7215 return null; 7216 }; 7217 7218 $angular.searchFormView = function() { 7219 if ($("div.panel-add-entity.show").length > 0) { // panel-add-entity 7220 return $angular.panelAddEntityScope.geoForm; 7221 } 7222 if ($angular.contentScope.webFormItem) { // web-home 7223 var item = $angular.contentScope.webFormItem; 7224 if (item.type == 'formview') { 7225 return item.form; 7226 } 7227 return null; 7228 } 7229 if ($angular.contentScope.form) { // web-item 7230 return $angular.contentScope.form; 7231 } 7232 if ($angular.contentScope.geoForm) { // geo-new, geo-edit 7233 return $angular.contentScope.geoForm; 7234 } 7235 return null; 7236 }; 7237 7238 $rootScope.pushButton = function(column, model, saved, actions, index) { 7239 7240 if (saved == null && actions == null) { 7241 console.log('pushButton start'); 7242 } 7243 7244 // entity required 7245 var root = $angular.searchRootModel(); 7246 var entity = model.entity; 7247 if (entity == null && root) { 7248 entity = root.entity; 7249 } 7250 if (model.id == null && root.id) {
7251 model.id = root.id; // set id 7252 } 7253 if (entity == null) { 7254 $angular.buttonError(root, column, model, 'Button: entity not found'); 7255 return; 7256 } 7257 7258 var callbackNext = function() { 7259 setTimeout(function() { 7260 // show only if no floating showing 7261 console.log('pushButton done'); 7262 if ($("div.floating-msg").length > 0) { 7263 return; 7264 } 7265 $utils.floatingMsg($angular.get("$translate").instant('msg.done')); 7266 }, 500); 7267 }; 7268 if (actions != null) { 7269 if (index == actions.length) { 7270 callbackNext(); 7271 return; // end multi actions 7272 } 7273 var path = actions[index]; 7274 column = $entity.getColumn(entity, path); 7275 if (column == null) { 7276 $angular.buttonError(column, model, 'Button: action not found: ' + path); 7277 return; 7278 } 7279 callbackNext = function() { 7280 $rootScope.pushButton(column, model, saved, actions, index+1); 7281 } 7282 } 7283 if (column == null || model == null) { 7284 $angular.buttonError(root, column, model, "Button: column/model not found"); 7285 return; 7286 } 7287 var path = column.name; 7288 if (column.path != null) { 7289 path = column.path; 7290 } 7291 if ($utils.isBlank(path)) { 7292 $angular.buttonError(root, column, model, "Button: path not found"); 7293 return; 7294 } 7295 var action = column.action; 7296 if ($utils.isBlank(action)) { 7297 $angular.buttonError(root, column, model, "Action required"); 7298 return; 7299 } 7300 7301 if (action === 'save' || (column.pre_save && saved == null)) { 7302 7303 console.log('pushButton action: ' + action + " (saving)"); 7304 7305 // prepare callback after save 7306 var callback = null; 7307 if (action != 'save' || (actions != null && index < actions.length)) { 7308 // has pending actions after save 7309 callback = function(callbackPostSave) { 7310 console.log('pushButton action: ' + action + " (postSave)"); 7311 if (action != 'save') { 7312 // has the column action pending 7313 $rootScope.pushButton(column, model, true, actions, index); 7314 return; 7315 } 7316 if (actions != null && index < actions.length) { 7317 // has pending actions 7318 callbackNext(); 7319 return; 7320 } 7321 if (callbackPostSave) { 7322 callbackPostSave(); 7323 return; 7324 } 7325 callbackNext(); 7326 } 7327 } 7328 7329 if ($("div.panel-add-entity.show").length > 0) { // panel-add-entity 7330 $angular.panelAddEntityScope.save(callback); 7331 7332 } else if ($angular.contentScope.saveForm) { 7333 $angular.contentScope.saveForm(callback); // web-home, web-item 7334 7335 } else if ($angular.contentScope.submitGeoEdit) { 7336 $angular.contentScope.submitGeoEdit(false, callback); // geo-edit 7337 7338 } else if ($angular.contentScope.createRaw) { 7339 $angular.contentScope.createRaw(false, callback); // geo-new 7340 7341 } else { 7342 $angular.buttonError(root, column, model, 'No save function found') 7343 } 7344 return; 7345 } 7346 7347 console.log('pushButton action: ' + action); 7348 7349 if (action === 'actions') { 7350 var actions = column.options; 7351 if (actions == null) { 7352 $angular.buttonError(root, column, model, 'No actions found'); 7353 return; 7354 } 7355 // start action index 0 7356 $rootScope.pushButton(column, model, saved, actions, 0); 7357 return; 7358 } 7359 7360 if (column.action === 'link') { 7361 var link = $rootScope.columnButtonHref(column, model); 7362 if (!$utils.isBlank(link)) { 7363 7364 var openNew = link.startsWith("http"); 7365 if (!openNew) { 7366 if (link.contains("admin/") && $constants.isWeb) { 7367 openNew = true; 7368 } else if (link.contains("home/") && !$constants.isWeb) { 7369 openNew = true; 7370 } 7371 } 7372 console.log("pushButton: going to " + link); 7373 if (openNew) { 7374 const enlace = document.createElement("a"); 7375 enlace.href = link; 7376 enlace.target = "_blank"; 7377 enlace.rel = "noopener noreferrer"; // seguridad adicional 7378 enlace.click(); 7379 //window.open(link, '_blank'); // deberia funcionar si se ejecuta dentro de onclick 7380 //window.location.href = link; 7381 } else { 7382 var $location = $angular.get("$location"); 7383 7384 var parts = link.split('?'); 7385 var path = parts[0]; 7386 $location.path(path);
7387 7388 if (parts.length > 1) { 7389 var params = {}; 7390 var queryString = parts[1]; 7391 queryString.split('&').forEach(function(pair) { 7392 const [key, value] = pair.split('='); 7393 params[key] = value; 7394 }); 7395 $location.search(params); 7396 } 7397 } 7398 } 7399 callbackNext(); 7400 return; 7401 } 7402 7403 if (column.action === 'back') { 7404 $events.back(); 7405 callbackNext(); 7406 return; 7407 } 7408 7409 if (column.action === 'reset') { 7410 if ($angular.contentScope && $angular.contentScope.resetForm) { 7411 $angular.contentScope.resetForm(); 7412 } else { 7413 $angular.buttonError(root, column, model, 'No reset function found') 7414 } 7415 callbackNext(); 7416 return; 7417 } 7418 7419 // entityId required 7420 var id = model.id; 7421 if (id == null && root) { 7422 id = root.id; 7423 } 7424 if (id == null) { 7425 $angular.buttonError(root, column, model, 'Button: entity id not found'); 7426 return; 7427 } 7428 7429 if (column.action === 'download') { 7430 if (column.spreadsheet == null) { 7431 $angular.buttonError(root, column, model, 'missing spreadsheet to download') 7432 return; 7433 } 7434 7435 var url = contextPath + "/api/geo/" + entity + "/" + id 7436 + "/download.xlsx?geo_instance=" + $instance.getId() + "&_tz=-120&spreadsheet=" + column.spreadsheet; 7437 var alink = document.createElement('a'); 7438 alink.href = url; 7439 alink.download = entity + "#" + id + ".xlsx"; 7440 alink.target = "_blank"; 7441 document.body.appendChild(alink); 7442 alink.click(); 7443 document.body.removeChild(alink); 7444 7445 callbackNext(); 7446 return; 7447 } 7448 7449 if (column.action === 'print') { 7450 if (column.spreadsheet == null) { 7451 $angular.buttonError(root, column, model, 'missing spreadsheet to print') 7452 return; 7453 } 7454 7455 var fileUrl = contextPath + "/api/geo/" + entity + "/" + id 7456 + "/download.xlsx?__keep=true&geo_instance=" + $instance.getId() + "&_tz=-120&spreadsheet=" + column.spreadsheet; 7457 7458 var num = column.number; 7459 if (num == null || num < 1) { 7460 num = 1; 7461 } 7462 $utils.printUrl(fileUrl, num); 7463 callbackNext(); 7464 return; 7465 } 7466 7467 if (column.action === 'move') { 7468 if (column.param == null) { 7469 $angular.buttonError(root, column, model, 'button: error action -> data required (move)'); 7470 return; 7471 } 7472 $rest.post({ 7473 loading: "generic", 7474 url: contextPath + "/api/geo/" + entity + "/" + id + "/move.json", 7475 data: { 7476 target: column.param 7477 }, 7478 confirmTitle: column._label 7479 }).then(function(o) { 7480 o.entity = o.target; 7481 var url = $angular.rootScope.getItemLinkBy(o); 7482 console.log('going to ' + url, o) 7483 $angular.get("$location").path(url).search({}).replace(); 7484 callbackNext(); 7485 }); 7486 return; 7487 } 7488 7489 if (column.action === 'copy' || column.action === 'copy_to_column') { 7490 if (column._label == null || column.param == null) { 7491 $angular.buttonError(root, column, model, 'button: error action -> data required (copy)'); 7492 return; 7493 } 7494 var data = { 7495 copyToEntity: column.param 7496 }; 7497 if (column.action === 'copy_to_column') { 7498 data.copyToColumn = column.column; 7499 } 7500 $rest.post({ 7501 loading: "generic", 7502 url: contextPath + "/api/geo-new/" + entity + "/" + id + "/copy.json", 7503 data: data, 7504 confirmTitle: column._label 7505 }).then(function(o) { 7506 if (column.action === 'copy') { 7507 var url = $angular.rootScope.getItemLinkBy(o); 7508 $angular.get("$location").path(url).search({}); 7509 } else { 7510 if ($angular.contentScope && $angular.contentScope.refresh) { 7511 $angular.contentScope.refresh(); 7512 } 7513 } 7514 callbackNext(); 7515 }); 7516 return; 7517 } 7518 7519 // server request 7520 $rest.post({ 7521 loading: "generic", 7522 url: contextPath + "/api/geo/" + entity + "/" + id + "/pushButton.json", 7523 data: { 7524 column:column 7525 } 7526 }).then(function() { 7527 if ($angular.contentScope && $angular.contentScope.refresh) { 7528 $angular.contentScope.refresh(callbackNext); 7529 } else { 7530 callbackNext(); 7531 } 7532 }); 7533 } 7534 7535 $angular.buttonError = function(root, column, model, msg) { 7536 $angular.log(msg); 7537 console.log('root', root); 7538 console.log('column', column); 7539 console.log('model', model); 7540 $utils.floatingError($angular.get("$translate").instant('msg.error')); 7541 }; 7542 7543 $rootScope.openAdmin = function() { 7544 window.location.href = contextPath + "/admin"; 7545 }; 7546 7547 $rootScope.carouselNext = function(e, o) { 7548 $utils.preventDefault(e); 7549 var c = searchCarousel(o); 7550 if (c) { 7551 c.next(); 7552 } 7553 }; 7554 $rootScope.carouselPrev = function(e, o) { 7555 $utils.preventDefault(e); 7556 var c = searchCarousel(o); 7557 if (c) { 7558 c.prev(); 7559 } 7560 }; 7561 function searchCarousel(o) { 7562 if (o.carousel) { 7563 return o.carousel; 7564 } 7565 if (o.$$childHead && o.$$childHead.carousel) { 7566 return o.$$childHead.carousel; 7567 } 7568 var i=0; 7569 var o2 = o; 7570 while (o2.$parent != null) { 7571 o2 = o2.$parent; 7572 if (o2.carousel) { 7573 return o2.carousel; 7574 } 7575 i++; 7576 if (i == 5) { 7577 break; 7578 } 7579 } 7580 console.log('not found carousel', o); 7581 return null; 7582 } 7583 7584 // methods to add/remove items 7585 $rootScope.addList = function(o, field) { 7586 var list = o[field]; 7587 if (list == null) { 7588 list = []; 7589 o[field] = list; 7590 } 7591 list.push(""); 7592 }; 7593 $rootScope.removeList = function(o, field, index) { 7594 var list = o[field]; 7595 if (list != null) { 7596 list.splice(index, 1); 7597 } 7598 }; 7599 $rootScope.editJson = function() { 7600 $angular.openModal('panel-edit-json', { 7601 json: $angular.contentScope.model, 7602 size: 'lg', 7603 successFunction: function(json) { 7604 $angular.contentScope.model = json; 7605 } 7606 }); 7607 }; 7608 $rootScope.viewJson = function() { 7609 $angular.openModal("panel-json", { json:$angular.contentScope.model, size:'xl' }); 7610 }; 7611 7612 return true; 7613}; 7614 7615$angular.goHome = function() { 7616 if ($instance.current && $constants.isWeb) { 7617 var o = $instance.current.geo_web; 7618 if (o && o.menu && o.menu.length > 0) { 7619 $angular.apply($angular.rootScope, function() { 7620 $angular.get("$location").path($instance.getBaseUrl() + "p/" + o.menu[0].id).search({}).replace(); 7621 }); 7622 return; 7623 } 7624 } 7625 7626 var path; 7627 if (!$constants.isWeb) { 7628 path = "/admin"; 7629 } else { 7630 path = "/home"; 7631 } 7632 $angular.apply($angular.rootScope, function() { 7633 $angular.get("$location").path(path).search({}).replace(); 7634 }); 7635}; 7636 7637$angular.goLogin = function() { 7638 if ($instance.isMslogin()) { 7639 7640 // FIXME 00000 do it at backend 7641 var accessToken = $cookiesService.get("ms_access_token"); 7642 if (accessToken != null) { 7643 7644 var form = '<form>';
7645 form += '\n<input name="username" value="ms#'+accessToken+'" />'; 7646 form += '\n<input name="password" value="ms" />'; 7647 form += '\n<input name="_remember_me" value="true" />'; 7648 form += '\n</form>'; 7649 7650 $rest.post({ 7651 loading: "generic", 7652 url: contextPath + "/log-in", 7653 contentType: "urlencoded", 7654 form: form, 7655 showError: false 7656 }).then(function() { 7657 // ok 7658 window.location.href = contextPath + $angular.tmpPath; 7659 7660 }).catch(function(e) { 7661 $utils.floatingError($angular.get("$translate").instant("msg.login.error")); 7662 $cookiesService.remove("ms_access_token"); 7663 7664 $angular.goLogin(); 7665 //window.location.href = contextPath + "/admin"; 7666 }); 7667 return; 7668 } 7669 7670 // FIXME 00000 remove instance cookie 7671 $cookiesService.put("instance", $instance.getId(), 1); 7672 window.location.href = "ms/a/login.go"; 7673 return; 7674 } 7675 var path; 7676 if (!$constants.isWeb) { 7677 path = "/admin/login"; 7678 } else { 7679 path = $instance.getBaseUrl() + "login"; 7680 } 7681 $angular.apply($angular.rootScope, function() { 7682 $angular.get("$location").path(path).replace(); 7683 }); 7684}; 7685 7686$angular.changeLanguage = function(e, lang) { 7687 $events.closeAll(); 7688 $utils.preventDefault(e); 7689 7690 //console.log('* ' + $locale.language + " -> " + lang) 7691 if ($locale.language == lang) { 7692 return; 7693 } 7694 7695 // apply texts and content 7696 $angular.get("$translate").use(lang); 7697 $cookiesService.put("_language", lang, 90); 7698 7699 setTimeout(function() { 7700 $locale.language = lang; // save last user selection 7701 $constants.clean(); 7702 $angular.get("$route").reload(); // force full reload 7703 }, 60); 7704 7705 // close menu if needed 7706 setTimeout(function() { 7707 if ($angular.element("#menu").hasClass("menu-open")) { 7708 $events.toggleMenu(); 7709 } 7710 if ($angular.element("#cartAsMenu").hasClass("menu-open")) { 7711 $events.toggleCartAsMenu(); 7712 } 7713 }, 100); 7714 7715}; 7716 7717//select methods 7718$angular.addComboItem = function(e, model, columnName, item) { 7719 $utils.preventDefault(e); 7720 //console.dir(item) 7721 if (item == null || model == null) { 7722 return; 7723 } 7724 if ($utils.isArray(item) && item.length > 0) { 7725 item = item[0]; 7726 } 7727 if (model[columnName] == null) { 7728 model[columnName] = []; 7729 } 7730 if (item._id) { 7731 item = item._id; 7732 } 7733 if (item.id) { 7734 item = item.id; 7735 } 7736 if (!$utils.isArray(model[columnName])) { 7737 model[columnName] = []; 7738 } 7739 if (model[columnName].indexOf(item) != -1) { 7740 $utils.floatingError($angular.get("$translate").instant("msg.exists")); 7741 return; 7742 } 7743 model[columnName].push(item); 7744 $utils.floatingWarn($angular.get("$translate").instant("msg.added")); 7745}; 7746$angular.removeComboItem = function(e, model, columnName, item) { 7747 $utils.preventDefault(e); 7748 if (item._id) { 7749 item = item._id; 7750 } 7751 if (item.id) { 7752 item = item.id; 7753 } 7754 var list = model[columnName]; 7755 if (list) { 7756 if (!$utils.isArray(list)) { 7757 list = []; 7758 model[columnName] = list; 7759 } 7760 for (var key in list) { 7761 var itemList = list[key]; 7762 if (itemList == item) { 7763 list.splice(key, 1); 7764 break; 7765 } 7766 } 7767 } 7768}; 7769 7770//back button 7771window.onpopstate = function(e) { 7772 // force load page 7773 $angular.apply($angular.rootScope); 7774}; 7775 7776$angular.openModalLocal = function(name, params) { 7777 var _modal = $angular.get("$uibModal").open({ 7778 templateUrl: name + ".html", 7779 controller: name, 7780 windowTopClass: name, 7781 size: params ? params.size : null, 7782 resolve: { 7783 params: function() { 7784 return params; 7785 } 7786 } 7787 }); 7788 _modal.opened.then(function() { 7789 }); 7790 _modal.closed.then(function() { 7791 }); 7792 return _modal.result; 7793}; 7794 7795$angular.openModal = function(name, params) { 7796 return $angular.openModalLocal(name, params); 7797}; 7798 7799$angular.currentRoute = ""; 7800$angular.resolveRoute = function(name, requiredLogged, publicUrl) { 7801 var controller = name; 7802 return { 7803 controller: controller, 7804 templateUrl: name + ".html", 7805 reloadOnSearch: false, 7806 resolve: { 7807 load: function($q, $rootScope) { 7808 return $angular.resolveRoutePage($q, $rootScope, name, controller, requiredLogged, publicUrl); 7809 } 7810 } 7811 } 7812}; 7813 7814$angular.resolveRoutePage = function($q, $rootScope, name, controller, requiredLogged, publicUrl) { 7815 // remove window events 7816 $(window).unbind(); 7817 7818 // close panels 7819 $events.closeAll(); 7820 if ($rootScope.closeSearch) { 7821 $rootScope.closeSearch(true); 7822 } 7823 7824 if (!$utils.isBlank($rest.version) && $rest.version !== appVersion) { 7825 // version changed -> reload 7826 console.log('reloading ' + appVersion + " -> " + $rest.version); 7827 window.location.reload(); 7828 // continue execution to avoid errors 7829 } 7830 7831 if (typeof gtag != 'undefined') { 7832 var url = $angular.get("$location").path(); 7833 if (gaInstance != "") { 7834 gtag('event', 'page_view', { 7835 page_location: url, 7836 send_to: gaInstance 7837 }); 7838 } 7839 } 7840 7841 var defer = $q.defer(); 7842 7843 $rootScope.skipHideLoading = true; // for resolve instance 7844 7845 // if (controller == "home-instance") { 7846 // // reload instance data 7847 // //console.dir($instance.current) 7848 // $instance.current = null; 7849 // } 7850 var toExecute = function() { 7851 7852 if ($instance.isLoginRequired(requiredLogged, publicUrl)) { 7853 var path = $angular.get("$location").path(); 7854 var isLoginPage = path.contains('/login'); 7855 if (!isLoginPage) { 7856 // save path to resend after login 7857 $angular.tmpPath = path; 7858 $angular.goLogin(); 7859 return; 7860 } 7861 } 7862 7863 // set the current page class in body 7864 $angular.currentRoute = controller; 7865 7866 // set instance properties 7867 $instance.setCssProperties(); 7868 7869 defer.resolve(); 7870 7871 $angular.apply($rootScope, function() { 7872 $angular.pageReady(); 7873 }); 7874 }; 7875 7876 if (!$user.isInit) { 7877 $user.isInit = true; 7878 var callback = toExecute; 7879 toExecute = function() { 7880 $user.set(callback); 7881 }; 7882 } 7883 7884 $instance.resolveInstance(toExecute); 7885 7886 return defer.promise; 7887 7888}; 7889 7890$angular.pageReady = function() { 7891 setTimeout(function() { 7892 $angular.pageReady2(); 7893 }, 250); 7894}; 7895$angular.pageReady2 = function() { 7896 if (!$("#header").hasClass('hidden')) { 7897 return; 7898 } 7899 7900 if (!$angular.rootScope.skipHideLoading) { 7901 $utils.hideLoading(); 7902 } 7903 $("#init-loading").remove(); 7904 $("#oldbrowser").remove(); 7905 $("#header").removeClass("hidden"); 7906 $("#search").removeClass("hidden"); 7907 $("#searchList").removeClass("hidden"); 7908 $("#menu").removeClass("hidden"); 7909 $("#cartAsMenu").removeClass("hidden"); 7910 $("#content").removeClass("hidden"); 7911 $("#footer").removeClass("hidden"); 7912 $init.log("app ready"); 7913} 7914 7915$angular.preparePage = function(params) { 7916 7917 if (params == null) { 7918 params = {}; 7919 } 7920 7921 if ($angular.menuScope) { 7922 $angular.menuScope.selectedPage = ""; 7923 } 7924 7925 $events.refresh(params.resetBacks); 7926 7927 if (params.title && params.title != null) { 7928 $angular.setTitle(params.title); 7929 } else { 7930 $angular.setTitle(""); 7931 } 7932 7933 if ($angular.headerScope) { 7934 $angular.headerScope.bar_buttons_right = undefined; 7935 if (params.buttonsRight && params.buttonsRight != null) { 7936 $angular.headerScope.bar_buttons_right = params.buttonsRight; 7937 } 7938 $angular.headerScope.bar_buttons_right_right = undefined; 7939 if (params.buttonsRightRight && params.buttonsRightRight != null) { 7940 $angular.headerScope.bar_buttons_right_right = params.buttonsRightRight; 7941 } 7942 } 7943}; 7944 7945$angular.setTitle = function(title) { 7946 $angular.title = title; 7947}; 7948 7949$angular.mapDark = [ 7950 { elementType: 'geometry', stylers: [{ color: '#242f3e' }] }, 7951 { elementType: 'labels.text.stroke', stylers: [{ color: '#242f3e' }] }, 7952 { elementType: 'labels.text.fill', stylers: [{ color: '#746855' }] }, 7953 { 7954 featureType: 'administrative.locality', 7955 elementType: 'labels.text.fill', 7956 stylers: [{ color: '#d59563' }] 7957 }, 7958 { 7959 featureType: 'poi', 7960 elementType: 'labels.text.fill', 7961 stylers: [{ color: '#d59563' }] 7962 }, 7963 { 7964 featureType: 'poi.park', 7965 elementType: 'geometry', 7966 stylers: [{ color: '#263c3f' }] 7967 }, 7968 { 7969 featureType: 'poi.park', 7970 elementType: 'labels.text.fill', 7971 stylers: [{ color: '#6b9a76' }] 7972 }, 7973 { 7974 featureType: 'road', 7975 elementType: 'geometry', 7976 stylers: [{ color: '#38414e' }] 7977 }, 7978 { 7979 featureType: 'road', 7980 elementType: 'geometry.stroke', 7981 stylers: [{ color: '#212a37' }] 7982 }, 7983 { 7984 featureType: 'road', 7985 elementType: 'labels.text.fill', 7986 stylers: [{ color: '#9ca5b3' }] 7987 }, 7988 { 7989 featureType: 'road.highway', 7990 elementType: 'geometry', 7991 stylers: [{ color: '#746855' }] 7992 }, 7993 { 7994 featureType: 'road.highway', 7995 elementType: 'geometry.stroke', 7996 stylers: [{ color: '#1f2835' }] 7997 }, 7998 { 7999 featureType: 'road.highway', 8000 elementType: 'labels.text.fill', 8001 stylers: [{ color: '#f3d19c' }] 8002 }, 8003 { 8004 featureType: 'transit', 8005 elementType: 'geometry', 8006 stylers: [{ color: '#2f3948' }] 8007 }, 8008 { 8009 featureType: 'transit.station', 8010 elementType: 'labels.text.fill', 8011 stylers: [{ color: '#d59563' }] 8012 }, 8013 { 8014 featureType: 'water', 8015 elementType: 'geometry', 8016 stylers: [{ color: '#17263c' }] 8017 }, 8018 { 8019 featureType: 'water', 8020 elementType: 'labels.text.fill', 8021 stylers: [{ color: '#515c6d' }] 8022 }, 8023 { 8024 featureType: 'water', 8025 elementType: 'labels.text.stroke', 8026 stylers: [{ color: '#17263c' }] 8027 } 8028]; 8029 8030$angular.initComponent = function($scope, initFunction, config) { 8031 if ($scope && $scope.$broadcast) { 8032 $scope.$broadcast(initFunction, config); 8033 } else if ($angular.contentScope && $angular.contentScope.$broadcast) { 8034 $angular.contentScope.$broadcast(initFunction, config); 8035 } else if ($angular.rootScope && $angular.rootScope.$broadcast) { 8036 $angular.rootScope.$broadcast(initFunction, config); 8037 } else { 8038 throw new Error('$broadcast is not defined when execute init function component: ' + initFunction); 8039 } 8040}; 8041 8042$angular.acceptLicense = function(id, email, callback) { 8043 if (id == null) { 8044 id = "a"; 8045 } 8046 $rest.put({ 8047 url: contextPath + "/www/license/"+id+"/accept.json", 8048 data: { email:email }, 8049 loading:"generic" 8050 }).then(function(o) { 8051 callback(); 8052 }); 8053}; 8054 8055$angular.rejectLicense = function(id, email, callback) { 8056 if (id == null) { 8057 id = "a"; 8058 } 8059 $rest.put({ 8060 url: contextPath + "/www/license/"+id+"/reject.json", 8061 data: { email:email }, 8062 loading:"generic" 8063 }).then(function(o) { 8064 callback(); 8065 }); 8066}; 8067 8068$angular.initGA = function() { 8069 if ($constants.isDev) { 8070 return; 8071 } 8072 8073 // Google Tag (gtag.js) - Modern GA4 & Google Ads 8074 if (gaInstance != "") { 8075 window.dataLayer = window.dataLayer || []; 8076 window.gtag = function() { window.dataLayer.push(arguments); }; 8077 window.gtag('js', new Date()); 8078 window.gtag('config', gaInstance); 8079 8080 var script = document.createElement('script'); 8081 script.type = 'text/javascript'; 8082 script.async = true;
8083 script.src = 'https://www.googletagmanager.com/gtag/js?id=' + gaInstance; 8084 document.head.appendChild(script); 8085 } 8086}; 8087 8088// service worker 8089$angular.initServiceWorker = function() { 8090 8091 if ('serviceWorker' in navigator) { 8092 8093 var isActive = false;//!isPro; 8094 8095 // NO use service worker 8096 navigator.serviceWorker.getRegistrations().then(function(registrations) { 8097 registrations.forEach(function(registration) { 8098 if (isActive && registration.scope != null && !registration.scope.includes('/admin')) { 8099 // keep 8100 } else { 8101 // unregister 8102 registration.unregister(); 8103 console.log('End sw ' + registration.scope); 8104 } 8105 }) 8106 }) 8107 8108 if (isActive) { 8109 // use service worker 8110 var url = contextPath + '/static/sw.js'; 8111 var scope = './';//$constants.isWeb ? './' : './admin'; 8112 navigator.serviceWorker.register(url, {scope:scope}).then(function(registration) { 8113 if (registration.waiting) { 8114 registration.waiting.postMessage('SKIP_WAITING'); 8115 } 8116 registration.addEventListener('updatefound', function() { 8117 if (registration.installing) { 8118 registration.installing.addEventListener('statechange', function() { 8119 if (registration.waiting) { 8120 if (navigator.serviceWorker.controller) { 8121 registration.waiting.postMessage('SKIP_WAITING'); 8122 } else { 8123 console.log('Init sw ' + scope); 8124 } 8125 } 8126 }) 8127 } 8128 }) 8129 }, function(error) { 8130 $angular.log('Service worker registration failed', error); 8131 }); 8132 } 8133 } 8134} 8135 8136$angular.mapReady = false; 8137$angular.initMap = function(callback) { 8138 8139 window.gak = window.gak || ""; 8140 if (!window.gak) { 8141 console.warn("Google Maps API key no disponible. Saltando carga."); 8142 if (typeof callback === "function") callback(null); 8143 return; 8144 } 8145 8146 (g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({ 8147 key: window.gak, v: "weekly", libraries: "drawing,places,geometry" //marker 8148 }); 8149 initMap(callback); 8150} 8151async function initMap(callback) { 8152 const { Map } = await google.maps.importLibrary("maps"); 8153 //const { AdvancedMarkerElement, PinElement } = await google.maps.importLibrary("marker"); 8154 $angular.mapReady = true; 8155 if (callback != null) { 8156 callback(); 8157 } 8158 //console.log("map ready") 8159} 8160 8161//// File utils.js //// 8162var $utils = {}; 8163 8164$utils.postSave = function(old, data, isCreate, callbackPushButton, callbackEnd) { 8165 8166// if (old) { 8167// if (old.id == null && data.id) { 8168// old.id = data.id; // set id 8169// } 8170// if (old.sys_updated) { 8171// delete old.sys_updated; // remove sysupdated because now is not fresh 8172// } 8173// } 8174 8175 // remove sysupdated 8176 if ($angular.contentScope && $angular.contentScope.model) { 8177 delete $angular.contentScope.model.sys_updated; // because now is not fresh 8178 } 8179 8180 var callback1 = function() { 8181 var $translate = $angular.get("$translate"); 8182 var message = $utils.getGeoTranslation(isCreate ? 'success_message_on_create' : 'success_message_on_update'); 8183 if (message) { 8184 // panel with msg 8185 $utils.hideLoading(); 8186 $angular.openModal("panel-message", { 8187 text: $translate.instant(message, data) 8188 }).then(function() { 8189 }); 8190 return; 8191 } 8192 8193 // floating 8194 $utils.floatingMsg($translate.instant(isCreate ? 'msg.created' : 'msg.updated')); 8195 }; 8196 8197 var callback2 = function() { 8198 if (callbackEnd) { 8199 callbackEnd(callback1); 8200 return; 8201 } 8202 callback1(); 8203 }; 8204 8205 if (callbackPushButton) { 8206 callbackPushButton(callback2); 8207 return; 8208 } 8209 callback2(); 8210 8211}; 8212 8213$utils.validateForm = function(form, errorMessage) { 8214 if (form && !form.$valid && form.$error) { 8215 var msg = errorMessage; 8216 if (!errorMessage) { 8217 for (var k in form.$error) { 8218 var errors = form.$error[k]; 8219 for (var k2 in errors) { 8220 8221 var cause; 8222 if (k == 'required') { 8223 cause = $angular.get("$translate").instant("msg.required"); 8224 } else {
8225 cause = $angular.get("$translate").instant("msg.invalid"); 8226 } 8227 8228 var field = errors[k2]; 8229 var label; 8230 if (field.$name) { 8231 label = $utils.parseGeoTranslation(field.$name); 8232 } else { 8233 label = field.$$element.parents('.form-group').eq(0).find('.control-label').clone().children().remove().end().text(); 8234 } 8235// var validationValue = field.$$attr[k]; 8236// if ($utils.isTrue(validationValue)) { 8237// validationValue = ''; 8238// } 8239 var msg = label.trim() + " " + cause.toLowerCase(); 8240 $utils.floatingError(msg); 8241 console.log('form validation', k, field); 8242 return false; 8243 } 8244 } 8245 } 8246 } 8247 return true; 8248}; 8249 8250$utils.serializeFormJSON = function(form) { 8251 var o = {}; 8252 var a = form.serializeArray(); 8253 $.each(a, function() { 8254 if (o[this.name]) { 8255 if (!o[this.name].push) { 8256 o[this.name] = [o[this.name]]; 8257 } 8258 o[this.name].push(this.value || ''); 8259 } else { 8260 o[this.name] = this.value || ''; 8261 } 8262 }); 8263 8264 // set boolean to false 8265 $('input:checkbox[value="true"]').each(function() { 8266 if (this.name != "" && o[this.name] == null && !this.checked) { 8267 o[this.name] = "false"; 8268 } 8269 }); 8270 8271 return o; 8272}; 8273 8274$utils.get = function(data, path) { 8275 if (path) { 8276 var split = path.split("."); 8277 for (var k in split) { 8278 if (data == null) { 8279 return null; 8280 } 8281 var key = split[k]; 8282 data = data[key]; 8283 } 8284 } 8285 return data; 8286}; 8287 8288$utils.preventDefault = function(e) { 8289 if (e) { 8290 e.preventDefault(); 8291 e.stopPropagation(); 8292 } 8293}; 8294 8295$utils.isScreenLarge = window.innerWidth >= 992; 8296$utils.isScreenSmall = window.innerWidth <= 768; 8297 8298$utils.isString = function(o) { 8299 return o == null || typeof o == 'string'; 8300}; 8301$utils.isObject = function(o) { 8302 return o != null && typeof o == 'object'; 8303}; 8304$utils.isArray = function(obj) { 8305 return obj && angular.isArray(obj); 8306}; 8307 8308$utils.isLink = function(o) { 8309 if (o && typeof o == 'string') { 8310 return o.startsWith('http'); 8311 } 8312 return false; 8313}; 8314 8315$utils.getColor = function(o, preffix) { 8316 if (!$utils.isBlank(o)) { 8317 if (o.startsWith('#')) { 8318 o = o.substring(1); 8319 } 8320 if (!$utils.isBlank(preffix)) { 8321 o = preffix + o; 8322 } 8323 o = '#' + o; 8324 } 8325 return o; 8326}; 8327$utils.getColorOpaque = function(c) { 8328 if (c && c.startsWith('#')) { 8329 return c + "33"; 8330 } 8331 return c; 8332}; 8333 8334$utils.cleanHtml = function(html) { 8335 var temporalDivElement = document.createElement("div"); 8336 temporalDivElement.innerHTML = html; 8337 return temporalDivElement.textContent || temporalDivElement.innerText || ""; 8338}; 8339 8340$utils.parseToInstagram = function(value) { 8341 // https://www.instagram.com/p/"+item+"/embed 8342 if (value && value.contains('instagram.com/p')) { 8343 // add embed if needed 8344 if (!value.contains('/embed')) { 8345 if (!value.endsWith('/')) { 8346 value += "/"; 8347 } 8348 value += "embed"; 8349 } 8350 } 8351 return value; 8352}; 8353 8354$utils.parseHtml = function(o) { 8355 var val = $utils.parse(o); 8356 return $angular.get('$sce').trustAsHtml(val); 8357} 8358 8359$utils.parse = function(o) { 8360 if (o == null) { 8361 return ""; 8362 } 8363 8364 if (typeof o == 'string') { 8365 return o; 8366 } 8367 8368 if (typeof o == 'number') { 8369// if(Math.round(o) !== o) { -> number of decimals configured in formula 8370// o = o.toFixed(2); 8371// } 8372 return $utils.parseNumber(o); 8373 } 8374 8375 if (o === true) { 8376 return "\u2714"; 8377 } 8378 if (o === false) { 8379 //return "\u2717"; 8380 return "false"; 8381 } 8382 8383 if ($utils.isArray(o)) { 8384 if (o.length == 0) { 8385 return ""; 8386 } 8387 if (o.length === 1) { 8388 return $utils.parse(o[0]); 8389 } 8390 if (typeof o[0] == 'object') { 8391 var list = []; 8392 for (var key in o) { 8393 list.push($utils.parse(o[key])); 8394 } 8395 o = list; 8396 } 8397 return $utils.join(o, ", "); 8398 } 8399 8400 if (typeof o != 'object') { 8401 $angular.log('Unknown type ' + (typeof o) + " with value " + o); 8402 return "" + o; 8403 } 8404 8405 if (o.entity && o.id) { 8406 return $entity.displayColumn(o); 8407 } 8408 8409 //console.log($utils.keys(o)); 8410 var val = o[$locale.language]; 8411 if (!$utils.isBlank(val)) { 8412 return val; 8413 } 8414 for (var key in $instance.languages) { 8415 var lang = $instance.languages[key]; 8416 if (!$utils.isBlank(o[lang])) { 8417 return o[lang]; 8418 } 8419 } 8420 for (var key in o) { 8421 if (!$utils.isBlank(o[key])) { 8422 return o[key]; 8423 } 8424 } 8425 return "";//JSON.stringify(o); 8426}; 8427 8428$utils.columnsMedia = ['image', 'audio', 'video', 'document']; 8429$utils.columnsButton = ['link', 'button']; 8430$utils.columnsMessage = ['blank', 'h1', 'h2', 'h3', 'h4', 'h5', 'message']; 8431$utils.columnsComponent = ['timetables', 'geo_schedule', 'categories', 'booking', 'buy', 'map', 'geo_properties', 8432 'ui_relation', 'ui_image', 'ui_video', 'ui_audio', 'ui_document', 'any', 'group']; 8433
8434$utils.initColumns = function($scope, meta, columns, model, opts, extendedOpts, innerEntity) { 8435 columns = columns == null ? [] : columns; 8436 model = model == null ? {} : model; 8437 opts = angular.extend({}, opts, extendedOpts); 8438 8439 opts.extra = opts.extra == null ? '' : opts.extra; 8440 opts.readonly = opts.readonly == null ? false : opts.readonly; 8441 opts.long = opts.long == null ? false : opts.long; 8442 opts.tab = opts.tab == null ? false : opts.tab; 8443 8444 if (typeof meta == 'string') { 8445 meta = $entity.getEntity(meta); 8446 if (meta == null) { 8447 $angular.log('[initColumns] fatal error: entity not found'); 8448 } 8449 } 8450 8451 if (opts.id == null && model.id) { 8452 opts.id = model.id; 8453 } 8454 8455 var pathToTranslations = 'geo_translations'; 8456 if (innerEntity) { 8457 pathToTranslations += '.inner_entities.' + innerEntity; 8458 } 8459 8460 var ereadonly = !opts.forceWritable && $entity.isReadonly(meta); 8461 8462 var cols = []; 8463 for (var k in columns) { 8464 var column = columns[k]; 8465 if (column == null || column.name == null) { 8466 continue; 8467 } 8468 8469 // clone column to avoid changes 8470 column = $utils.clone(column); 8471 columns[k] = column; 8472 8473 if (column.super && !$user.isSuper()) { 8474 continue; 8475 } 8476 if (column.admin && !$user.isAdmin()) { 8477 continue; 8478 } 8479 if (column.unexposed) { 8480 continue; 8481 } 8482 if (column.hidden && $constants.isWeb) { 8483 continue; 8484 } 8485 if (column.tab && !opts.tab) { 8486 continue; 8487 } 8488 if (column.type == 'any' && !$user.isSuper()) { 8489 continue; 8490 } 8491 if (column.type == 'section') { 8492 column.type = 'h3'; 8493 } 8494 8495 var isButton = $utils.columnsButton.indexOf(column.type) >= 0; 8496 var isMessage = $utils.columnsMessage.indexOf(column.type) >= 0; 8497 var isComponent = $utils.columnsComponent.indexOf(column.type) >= 0; 8498 8499 column._autosave = opts.id && column.autosave; 8500 column._readonly = false; 8501 if (!column._autosave && !isButton && !isMessage && !isComponent) { 8502 column._readonly = ereadonly || column.readonly || opts.readonly || ($constants.isWeb && !column.updatable); 8503 } 8504 8505 var value = model[column.name]; 8506 8507 // check if is array 8508 var isArray = false; 8509 switch (column.type) { 8510 case "image": 8511 case "audio": 8512 case "video": 8513 case "document": 8514 case "formula": 8515 if (column.type == 'formula') { 8516 if (column.formula) { 8517 // formula 8518 isArray = column.formula.contains('relation') && !column.formula.contains('correlation'); 8519 } 8520 if (value == null && column.formula_type == 'boolean') { 8521 value = false; 8522 } 8523 } else { 8524 // media 8525 isArray = $utils.isTrue(column.multiple); 8526 } 8527 if (!isArray) { 8528 break;
8528 // skip check array 8529 } 8530 8531 case "string_list": 8532 case "any_entity_list": 8533 case "list": 8534 case "relation": 8535 case "inner_entity_list": 8536 case "enum_list": 8537 case "ui_relation": 8538 case "ui_image": 8539 case "ui_video": 8540 case "ui_audio": 8541 case "ui_document": 8542 case "map": 8543 case "categories": 8544 case "geo_properties": 8545 if ($utils.isBlank(value)) { 8546 value = []; 8547 } 8548 if (!$utils.isArray(value)) { 8549 var valueIds = (typeof value === 'string') ? value.split(',') : null; 8550 if (valueIds && valueIds.every($utils.isGeoObjectId)) { 8551 value = valueIds; 8552 } else { 8553 value = [value]; 8554 } 8555 } 8556 isArray = true; 8557 break; 8558 } 8559 8560 // check data 8561 switch (column.type) { 8562 case "group": 8563 if (value == null) { 8564 value = {}; 8565 } 8566 break; 8567 case "timetables": 8568 if (value != null && typeof value != 'string') { 8569 value = $utils.getTimeTables(value); 8570 } 8571 break; 8572 case "geo_schedule": 8573 if (value != null && typeof value != 'string') { 8574 value = $utils.printScheduledDates(value, 10); 8575 } 8576 break; 8577 case "booking": 8578 if (!$instance.isBooking(value)) { 8579 continue; 8580 } 8581 break; 8582 case "buy": 8583 if (!$cart.isCartItem(value)) { 8584 continue; 8585 } 8586 break; 8587 case "table": 8588 if (value == null) { 8589 value = []; 8590 } 8591 if ($utils.isArray(value) && column.columns != null && column.columns.length > 2) { 8592 var k1 = column.columns[0].name; 8593 var k2 = column.columns[1].name; 8594 8595 // reset data 8596 $entity.initTable(column); 8597 8598 var doc = {}; 8599 for (var i in value) { 8600 var item = value[i]; 8601 var v1 = item[k1]; 8602 var v2 = item[k2]; 8603 if (doc[v1] == null) { 8604 doc[v1] = {}; 8605 } 8606 delete item[k1]; 8607 delete item[k2]; 8608 doc[v1][v2] = item; 8609 } 8610 8611 value = doc; 8612 //console.log('table', doc); 8613 } 8614 break; 8615 case "button": 8616 column._buttonClass = column.style ? ('btn-' + column.style) : 'btn-primary'; 8617 break; 8618 } 8619 8620 model[column.name] = value; // assign if changed 8621 8622 var hasData = !$utils.isBlank(value); 8623 if (hasData && isArray && value.length == 0) { 8624 hasData = false; 8625 } 8626 //console.log(column.name, column.type, value) 8627 8628 if (!hasData && opts.id == null && (column.type == 'formula' || column.type == 'relation_entity' || column.type == 'relation')) { 8629 continue; // no show in create 8630 } 8631 if (!hasData && isComponent) { 8632 continue; // no show components without data 8633 } 8634 if (column._readonly) { 8635 if (column.required && opts.id == null) { 8636 column._readonly = false; 8637 column.__readonly = true; 8638 } else if (!hasData) { 8639 continue; 8640 } 8641 if (column.type == 'formula' || column.type == 'relation_entity' || column.type == 'relation' || column.type == 'table' 8642 || column.type == 'inner_entity' || column.type == 'inner_entity_list') { 8643 column._readonly = false; 8644 column.__readonly = true; 8645 } 8646 if (column.type === 'list' && column.long) { 8647 column._readonly = false; 8648 column.__readonly = true; 8649 } 8650 } 8651 if (column.type == 'timetables' || column.type == 'geo_schedule' || column.type == 'categories') { 8652 column._readonly = true; 8653 column.html = true; 8654 } 8655 8656 if (column.tab) { 8657 column.long = true; 8658 } 8659 if (column.long || opts.long) { 8660 column.size = 12; 8661 } 8662 if (column.size == null) { 8663 column.size = 4; 8664 } 8665 8666 column._type = column.type; 8667 if (column._readonly) { 8668 column._type = "readonly"; 8669 column.required = false; 8670 } 8671 column._classes = "col-lg-" + column.size + " col-md-12 col-12 " + "form-group column"; 8672 if (meta) { 8673 column._classes += " column-entity-" + meta.id; 8674 } 8675 if (column.type) { 8676 column._classes += " column-type-" + column.type; 8677 } 8678 if (column.name) { 8679 column._classes += " column-name-" + column.name; 8680 } 8681 if (column.required && !column.__readonly) { 8682 column._classes += " column-required"; 8683 } 8684 if (column.classes) { 8685 column._classes += " " + column.classes; 8686 } 8687 8688 if (!column.nolabel && column.name.contains("_$_") && column.label == null) { 8689 column.nolabel = true; 8690 } 8691 8692 if (isMessage && value != null) { 8693 column._label = $utils.parse(value); 8694 } else if (column.nolabel) { 8695 column._label = "";
8696 column._classes += " nolabel"; 8697 } else if (column.label) { 8698 column._label = $utils.parse(column.label); 8699 } else if (column.name) { 8700 column._label = $utils.parseGeoTranslation(column.name, meta, null, pathToTranslations); 8701 } 8702 8703 if (column.type === 'boolean_int' && value === 1) { 8704 value = true; 8705 model[column.name] = value; 8706 } 8707 8708 if (column.calendar) { 8709 column._calendarConfig = { 8710 initialView: 'dayGridMonth', 8711 getItems: function() { 8712 var list = model[column.name]; 8713 return list ? list : []; 8714 }, 8715 onClickEvent: function(event, item) { 8716 var url = $angular.rootScope.getItemLinkBy(item); 8717 window.location.href = url; 8718 }, 8719 convertItemToEvent: function(item) { 8720 var columns = $entity.getCalendarColumns(item.entity); 8721 var start; 8722 var end; 8723 var date = $utils.get(item, columns.date.name); 8724 if (columns.date.type === 'datetime') { 8725 start = date; 8726 end = date; 8727 } else { 8728 if (columns.time) { 8729 var time = $utils.get(item, columns.time.name); 8730 start = date + 'T' + time; 8731 end = date + 'T' + time.substring(0, 2) + ':59'; 8732 } else { 8733 start = date; 8734 end = date; 8735 } 8736 } 8737 8738 var o = { 8739 id: item.id, 8740 start: start, 8741 end: end, 8742 title: $entity.displayColumn(item) 8743 }; 8744 if (item.status) { 8745 o.classNames = ['fc-status-'+item.status]; 8746 } 8747 return o; 8748 } 8749 }; 8750 } 8751 8752 cols.push(column); 8753 } 8754 //console.log(entity, cols) 8755 //console.log(entity, model) 8756 8757 $scope.meta = meta; 8758 $scope.columns = cols; 8759 $scope.model = $angular.contentScope.model; 8760 $scope._model = model; 8761 $scope.opts = opts; 8762 $scope.pathToTranslations = pathToTranslations; 8763 $scope.inner_entity = innerEntity; 8764}; 8765 8766$utils.getGeoTranslation = function(field, o, type) { 8767 8768 if (!type) { 8769 type = 'geo_translations'; 8770 } 8771 if (o == null && $angular.contentScope) { 8772 o = $angular.contentScope.meta; 8773 8774 if (o == null && $angular.contentScope.model) { 8775 o = $angular.contentScope.model.meta; 8776 } 8777 } 8778 if (typeof o == 'string') { 8779 o = $entity.getEntity(o); 8780 } 8781 if (o) { 8782 var v = $utils.get(o, type); 8783 if (v && v[field]) { 8784 return $utils.parse(v[field]); 8785 } 8786 8787 // TODO it can be inside an inner_entity -> search in object 8788 var ies = o.inner_entities; 8789 if (ies) { 8790 for (var k in ies) { 8791 var ie = ies[k]; 8792 var ieo = o[ie.name]; 8793 if (ieo && ieo[field]) { 8794 return $utils.parse(ieo[field]); 8795 } 8796 } 8797 } 8798 8799// // try to fix column 8800// var f = $utils.toKey(field); 8801// v = o[type]; 8802// if (v && v[f]) { 8803// return $utils.parse(v[f]); 8804// } 8805 8806 } 8807 return null; 8808}; 8809 8810$utils.parseGeoTranslation = function(field, o, msgKey, type) { 8811 var value = $utils.getGeoTranslation(field, o, type); 8812 if (!$utils.isBlank(value)) { 8813 return value; 8814 } 8815 if (msgKey == null) { 8816 msgKey = "msg." + field; 8817 msgKey = msgKey.trim(); 8818 } 8819 var $translate = $angular.get("$translate"); 8820 value = $translate.instant(msgKey); 8821 if (!$utils.isBlank(value) && value !== msgKey) { 8822 return value; 8823 } 8824 return $utils.toText(field); 8825}; 8826$utils.parseText = function(field) { 8827 var msgKey = "msg." + field.trim(); 8828 var $translate = $angular.get("$translate"); 8829 var value = $translate.instant(msgKey); 8830 if (!$utils.isBlank(value) && value !== msgKey) { 8831 return value; 8832 } 8833 return $utils.toText(field); 8834}; 8835 8836$utils.columnTypeText = function(type, placeholder, column) { 8837 if ($utils.isBlank(type)) { 8838 if (placeholder == true) { 8839 return "<font color='#777777'>Type</font>"; 8840 } 8841 return ""; 8842 } 8843 8844 var extra = ""; 8845 if (column && column.param) { 8846 extra = " (" + column.param + ")"; 8847 } 8848 8849 var key = "msg.column.type." + type; 8850 var $translate = $angular.get("$translate"); 8851 var value = $translate.instant(key); 8852 if (!$utils.isBlank(value) && value !== key) { 8853 return value + extra; 8854 } 8855 return $utils.toText(type) + extra; 8856}; 8857 8858$utils.length = function(value) { 8859 return $utils.keys(value).length; 8860}; 8861 8862$utils.toText = function(field) { 8863 if (field != null && field.length > 1 && !$utils.isNumeric(field)) { 8864 if (field.match("_")) field = field.replaceAll("_", " "); 8865 if (field.match("-")) field = field.replaceAll("-", " "); 8866 field = field.trim();//.toLowerCase(); -> for text no translated (ex: '1. Solicitud') 8867 if (field.length > 1) { 8868 field = field.substring(0, 1).toUpperCase() + field.substring(1); 8869 } 8870 } 8871 return field; 8872}; 8873 8874$utils.toKey = function(value) { 8875 if (value) { 8876 var key = value.toLowerCase().trim(); 8877 key = key.replace(/[ ]/g, "-"); 8878 key = $utils.removeDiacritics(key); 8879 key = key.replace(/[^\w-]/g, ''); 8880 return key; 8881 } 8882 return ""; 8883}; 8884 8885$utils.isKeyOk = function(key) {
8886 if (key == null || key == "") { 8887 return false; 8888 } 8889 if ($constants.reservedWords.indexOf(key) != -1) { 8890 return false; 8891 } 8892 if (key.startsWith("admin")) { 8893 return false; 8894 } 8895 return true; 8896}; 8897 8898$utils.getLocation = function(item) { 8899 var lat = item.latitude; 8900 if (lat == null) { 8901 lat = 0; 8902 } 8903 var lng = item.longitude; 8904 if (lng == null) { 8905 lng = 0; 8906 } 8907 return lat + "," + lng; 8908}; 8909 8910$utils.getZoom = function(item) { 8911 var zoom = item.zoom; 8912 if (zoom == null) { 8913 zoom = 1; 8914 } else { 8915 zoom = Number(zoom); 8916 } 8917 return zoom; 8918}; 8919 8920//$utils.getValueByPath = function(path) { 8921// var val = $component.data; 8922// var keys = path.split("/"); 8923// for (var index in keys) { 8924// var key = keys[index]; 8925// if (val != null && key.length > 0) { 8926// val = val[key]; 8927// } 8928// } 8929// val = $component.parse(val); 8930// return val; 8931//}; 8932// 8933//$utils.setValueByPath = function(path, value) { 8934// var val = $component.data; 8935// var keys = path.split("/"); 8936// for (var i=0; i<keys.length; i++) { 8937// var key = keys[i]; 8938// if (val != null && key.length > 0) { 8939// if (i == keys.length-1) { 8940// // set value 8941// val[key] = value; 8942// } else { 8943// val = val[key]; 8944// } 8945// } 8946// } 8947//}; 8948 8949$utils.setByPath = function(o, path, value) { 8950 var split = path.split("."); 8951 for (var i in split) { 8952 var key = split[i]; 8953 if (o && key.length > 0) { 8954 if (i == split.length-1) { 8955 // set value 8956 o[key] = value; 8957 } else { 8958 var tmp = o[key]; 8959 if (tmp == null) { 8960 tmp = {}; 8961 o[key] = tmp; 8962 } 8963 o = tmp; 8964 } 8965 } 8966 } 8967}; 8968 8969$utils.getVideoId = function(url) { 8970 var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#\&\?]*).*/; 8971 var match = url.match(regExp); 8972 var videoId = (match && match[7].length == 11) ? match[7] : false; 8973 return videoId; 8974} 8975 8976$utils.isTabLoaded = function(value) { 8977 //console.log('isTabLoaded ' + value); 8978 $angular.contentScope.geoForm = null; // reset geoForm 8979 8980 $angular.get("$timeout")(function() { 8981 8982 // update current url with selected tab 8983 var index = $("#edit-tabs .nav-tabs li a.active").parent().attr("index"); 8984 if (index == "-1") { 8985 return; // ignore 8986 } 8987 if (index && index != "0") { 8988 $angular.get("$location").search({'_tab': index}).replace(); 8989 } else { 8990 $angular.get("$location").search({}).replace(); 8991 } 8992 8993 $angular.contentScope.$broadcast('elastic:adjust'); 8994 setTimeout(function() { 8995 $angular.contentScope.$broadcast('elastic:adjust'); 8996 }, 300); 8997 }); 8998 8999 if ($angular.contentScope.selectedTabs == undefined) { 9000 $angular.contentScope.selectedTabs = []; 9001 } 9002 if ($angular.contentScope.selectedTabs.indexOf(value) != -1) { 9003 return true; 9004 } 9005 $angular.contentScope.selectedTabs.push(value); 9006 return false; 9007}; 9008$utils.isTabSelected = function(value) { 9009 if ($angular.contentScope.selectedTabs == null || $utils.isBlank(value)) { 9010 return false; 9011 } 9012 return $angular.contentScope.selectedTabs.indexOf(value) != -1; 9013}; 9014 9015$utils.cloneList = function(list) { 9016 if (list == null) { 9017 return null; 9018 } 9019 return list.slice(0); 9020}; 9021 9022$utils.getSorted = function(map, field) { 9023 var list = []; 9024 if (map) { 9025 for (var k in map) { 9026 list.push(map[k]); 9027 } 9028 } 9029 list.sort(function(a, b) { 9030 var numA = a[field]; 9031 if (numA == null) numA = 999; 9032 var numB = b[field]; 9033 if (numB == null) numB = 999; 9034 return numA - numB; 9035 }); 9036 return list; 9037}; 9038 9039$utils.imageSize = function(width, height) { 9040 if (width != "" && height != "") { 9041 width = Number(width); 9042 height = Number(height); 9043 var extra = ""; 9044 return "padding-top:" + (height / width) * 100 + "%; " + extra; 9045 } 9046 return ""; 9047}; 9048 9049$utils.parseDateTotal = function(value) { 9050 if (value == null) { 9051 return ""; 9052 } 9053 if ($utils.isArray(value)) { 9054 var list = []; 9055 for (var k in value) { 9056 list.push($utils.parseDateTotal(value[k])); 9057 } 9058 return $utils.join(list, ", "); 9059 } 9060 var isString = typeof value == 'string'; 9061 if ($utils.isNumeric(value)) { 9062 var num = isString ? Number(value) : value; 9063 var d = new Date(num); 9064 if (d.getFullYear() > 1900) { 9065// if ($angular.contentScope && $angular.contentScope.timezone != null && $angular.contentScope.timezone != 0) { 9066// d = new Date(value + $angular.contentScope.timezone + (d.getTimezoneOffset()*60*1000)) 9067// } 9068// if (millis) { 9069// return $utils.fromDate(d, 'yyyy-MM-dd HH:mm:ss:sss'); 9070// } 9071 return $utils.fromDate(d, 'yyyy-MM-dd HH:mm:ss'); 9072 } 9073 } 9074 if (isString && !value.contains('-') && !value.contains(' ')) { 9075 value = value.replace("+0000", ""); 9076 var result = ""; 9077 if (value.length > 7) { 9078 result = value.substring(0, 4) + "-" + value.substring(4, 6) + "-" + value.substring(6, 8); 9079 } 9080 if (value.length > 13) { 9081 result += " " + value.substring(8, 10) + ":" + value.substring(10, 12) + ":" + value.substring(12, 14); 9082 } 9083 return result; 9084 } 9085 return value; 9086}; 9087$utils.fromDate = function(value, format, utc) { 9088 if (value != null && typeof value == 'object') { 9089 var $filter = $angular.get("$filter"); 9090 return $filter('date')(value, format, utc); 9091 } 9092 return null; 9093}; 9094$utils.toDate = function(value) { 9095 if (value) { 9096 if ($utils.isInteger(value)) { 9097 // millis 9098 return new Date(value); 9099 } 9100 if (typeof value == 'string') { 9101 9102 if (value.length == 13 && $utils.isNumeric(value)) { 9103 // millis 9104 return new Date(Number(value)); 9105 } 9106 9107 if (value.length == 10) { 9108 // yyyy-MM-dd 9109 var split = value.split("-"); 9110 if (split.length == 3) { 9111 //return new Date(value); -> this change the day result depending the timezone 9112 return new Date(Number(split[0]), Number(split[1]) - 1, Number(split[2])); 9113 } 9114 9115 // dd/MM/yyyy 9116 split = value.split("/"); 9117 if (split.length == 3) { 9118 return new Date(Number(split[2]), Number(split[1]) - 1, Number(split[0])
9118); 9119 } 9120 } 9121 9122 // dd MMM yyyy 9123 if (value.length == 11) { 9124 var split = value.split(" "); 9125 if (split.length == 3) { 9126 return new Date(value); 9127 } 9128 } 9129 9130 if (value.length == 19) { 9131 // 2020-08-21T00:00:00 9132 var split = value.split("T"); 9133 if (split.length == 2) { 9134 return new Date(value); 9135 } 9136 9137 // 2020-10-02 19:09:53 9138 split = value.split(" "); 9139 if (split.length == 2) { 9140 return new Date(value); 9141 } 9142 } 9143 9144 } 9145 //console.log('unknown date format: ' + value) 9146 } 9147 return null; 9148}; 9149$utils.formatDate = function(value) { 9150 // used to parse form datetimes 9151 if (value && value.length == 19) { 9152 var date = $utils.toDate(value); 9153 if (date) { 9154 return date.getTime(); 9155 } 9156 } 9157 return value; 9158}; 9159$utils.parseDateTime = function(value) { 9160 // used to filter date times 9161 if (value) { 9162 var date = $utils.toDate(value); 9163 if (date) { 9164 return date.getTime(); 9165 } 9166 //console.log('unknown date format: ' + value) 9167 } 9168 return null; 9169}; 9170$utils.parseDay = function(value, format) { 9171 if (value == null || value === "0000-00-00") { 9172 return ""; 9173 } 9174 var d = $utils.toDate(value); 9175 if (d != null) { 9176 if (format == null) { 9177 format = $constants.formatDay; 9178 } 9179 var result = $utils.fromDate(d, format); 9180 //console.log(value + " -> " + d + " -> " + result) 9181 if (result != null) { 9182 return result; 9183 } 9184 } 9185 return value; 9186}; 9187$utils.toISODay = function(day) { 9188 var date = day; 9189 if (day && typeof day === 'string') { 9190 date = new Date(day); 9191 } 9192 var $filter = $angular.get("$filter"); 9193 return $filter('date')(date, 'yyyy-MM-dd'); 9194 // return date.getFullYear() + '-' + (date.getMonth()+1) + '-'; 9195}; 9196 9197$utils.printDayTime = function(dateInMillis) { 9198 return $utils.printDate(dateInMillis, $constants.formatDayTime); 9199}; 9200 9201$utils.printDate = function(dateInMillis, format) { 9202 if (dateInMillis) { 9203 var date = new Date(dateInMillis); 9204 var $filter = $angular.get("$filter"); 9205 return $filter('date')(date, format); 9206 } 9207 return null; 9208}; 9209 9210$utils.getTimeZone = function() { 9211 var timeZone = "" + -(new Date().getTimezoneOffset() / 60); 9212 if (!timeZone.startsWith("-")) { 9213 timeZone = "+" + timeZone; 9214 } 9215 return timeZone; 9216}; 9217$utils.getTimeZoneOffset = function() { 9218 return new Date().getTimezoneOffset(); 9219}; 9220 9221$utils.getTimeTables = function(list) { 9222 if (list == null || list.length == 0) { 9223 return ''; 9224 } 9225 var result = "<table>"; 9226 var $translate = $angular.get("$translate"); 9227 for (var i in list) { 9228 var item = list[i]; 9229 if (item && item.day) { 9230 result += "<tr><td>" + $translate.instant($constants.daysList[item.day]) 9231 + ": </td><td>" + item.time_from + " - " + item.time_to + "</td></tr>"; 9232 } 9233 } 9234 result += "</table>"; 9235 return result; 9236}; 9237 9238$utils.hasValidScheduledDates = function(item) { 9239 var result = $utils.printScheduledDates(item); 9240 return !(result.startsWith("<font color='red'>")); 9241}; 9242 9243$utils.printScheduledDates = function(item, max) { 9244 if (item && item.geo_schedule) { 9245 item = item.geo_schedule; 9246 } 9247 if (item == null || item.dates == null) { 9248 return ''; 9249 } 9250 if (item.geo_scheduled_dates != null) { 9251 return item.geo_scheduled_dates; 9252 } 9253 var dates = item.dates; 9254 var result = ''; 9255 var pastResult; 9256 var num = 0; 9257 9258 var timeZone = $utils.getTimeZone(); 9259 var today = $utils.fromDate(new Date(), 'yyyy-MM-dd', 'UTC' + timeZone); 9260 var time = $utils.fromDate(new Date(), 'HH:mm', 'UTC' + timeZone); 9261 var oneYear = new Date(); 9262 oneYear.setDate(oneYear.getDate() + 365); 9263 9264 if (max == null) { 9265 max = 1; 9266 } 9267 var table = false; 9268 if (max > 1) { 9269 table = true; 9270 } 9271 9272 var currentDay = null; 9273 for (var i in dates) { 9274 var date = dates[i]; 9275 if (date && date.day) { 9276 9277 var allDay = !date.end_day && date.time_from === '00:00' && date.time_to === '23:59'; 9278 var line = '<span class="scheduled_day">' + $utils.parseDay(date.day) + '</span>'; 9279 if (!allDay) { 9280 line += '<span class="scheduled_time">' + date.time_from + '</span>' + '-'; 9281 if (date.end_day) { 9282 line += '<span class="scheduled_day">' + $utils.parseDay(date.end_day) + '</span>'; 9283 } 9284 line += '<span class="scheduled_time">' + date.time_to + '</span>'; 9285 } 9286 9287 if (date.day > oneYear) { 9288 continue; 9289 } 9290 var endDay = date.end_day ? date.end_day : date.day; 9291 if (endDay < today) { 9292 pastResult = line; 9293 continue; 9294 } 9295 if (endDay === today && date.time_to < time) { 9296 pastResult = line; 9297 continue; 9298 } 9299 9300 if (!table && date.day === currentDay && !date.end_day && !allDay) { 9301 result += ' / ' + '<span class="scheduled_time">' + date.time_from + '</span>' + '-' + '<span class="scheduled_time">' + date.time_to + '</span>'; 9302 continue; 9303 } 9304 currentDay = date.day; 9305 9306 if (num === max) { 9307 break; 9308 } 9309 9310 result += line 9311 if (table) { 9312 result += '<br>'; 9313 } else if (allDay) { 9314 break; 9315 } 9316 9317 num++; 9318 } 9319 } 9320 9321 if (table) { 9322 result = num === 0 ? '' : ('<div class="scheduled_dates">' + result + '</div>'); 9323 } else if (num === 0 && pastResult) { 9324 result = "<font color='red'>" + pastResult + "</font>"; 9325 } 9326 9327 item.geo_scheduled_dates = result; 9328 return result; 9329}; 9330 9331$utils.parseTimetables = function(list) { 9332 var result = ""; 9333 if (list) { 9334 var $translate = $angular.get("$translate"); 9335 for (var i in list) { 9336 var item = list[i]; 9337 if (item && item.day) { 9338 if (result != "") { 9339 result += "<br>"; 9340 } 9341 result += $translate.instant($constants.daysList[item.day]) + ": " + item.time_from + " - " + item.time_to; 9342 } 9343 } 9344 } 9345 return result; 9346}; 9347 9348$utils.parseDuration = function(value) { 9349 if (value == null || value < 30000) { 9350 return "-"; 9351 } 9352 var sec_num = Math.round(parseInt(value, 10) / 1000); 9353 var hours = Math.floor(sec_num / 3600); 9354 var minutes = Math.round((sec_num - (hours * 3600)) / 60); 9355 9356 var result = ''; 9357 if (hours > 0) { 9358 result += hours +'h '; 9359 } 9360 //if (minutes > 0) { 9361 if (minutes < 10 && hours > 0) { 9362 result += "0"; 9363 } 9364 result += minutes +'m '; 9365 //} 9366 if (result == '') { 9367 return "-"; 9368 } 9369 return result; 9370}; 9371$utils.parseNumber = function(value) { 9372 if (value != null) { 9373 var miles = ($locale.decimal == ",") ? "." : ","; 9374 var val = value.toString().replace(".", $locale.decimal); 9375 if (value > 999) { 9376 val = val.replace(/\B(?=(\d{3})+(?!\d))/g, miles); 9377 } 9378 return val; 9379 } 9380 return ""; 9381}; 9382//$utils.parseNumber = function(value) { 9383// if (value != null) {
9384// //return value.toLocaleString(); 9385// return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, "."); 9386// } 9387// return ""; 9388//}; 9389//$utils.parseDecimal = function(value) { 9390// if (value != null) { 9391// value = (Math.round(value * 100) / 100).toFixed(2); 9392// var split = value.split("."); 9393// return $utils.parseNumber(split[0]) + "," + split[1]; 9394// } 9395// return ""; 9396//}; 9397$utils.parsePercent = function(value) { 9398 if (value != null) { 9399 return value + "%"; 9400 } 9401 return "0%"; 9402}; 9403 9404$utils.isColorDark = function(color) { 9405 9406 if (color == null || color == "") { 9407 return true; 9408 } 9409 9410 var c = color.toUpperCase(); 9411 if (c.startsWith("#")) { 9412 c = c.substring(1); // strip # 9413 } 9414 var rgb = parseInt(c, 16); // convert rrggbb to decimal 9415 var r = (rgb >> 16) & 0xff; // extract red 9416 var g = (rgb >> 8) & 0xff; // extract green 9417 var b = (rgb >> 0) & 0xff; // extract blue 9418 var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // per ITU-R BT.709 9419 // 255:white / 0:black 9420 //console.log(c + " -> " + luma) 9421 if (luma < 190) { // default: 220 9422 return true; 9423 } else { 9424 return false; 9425 } 9426}; 9427$utils.getColorText = function(color) { 9428 if ($utils.isColorDark(color)) { 9429 return "#ffffff"; 9430 } 9431 return "#000000"; 9432}; 9433 9434$utils.getParameterFromUrl = function(name, url) { 9435 if (url == undefined) { 9436 url = "" + window.location.href; 9437 } 9438 9439 name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); 9440 var regexS = "[\\?&]" + name + "=([^&#]*)"; 9441 var regex = new RegExp(regexS); 9442 var results = regex.exec(url); 9443 if (results == null) { 9444 return ""; 9445 } else { 9446 return results[1]; 9447 } 9448}; 9449 9450$utils.removeFromArray = function(list, value) { 9451 var index = list.indexOf(value); 9452 if (index > -1) { 9453 list.splice(index, 1); 9454 } 9455} 9456 9457$utils.isBlank = function(value) { 9458// if (value == null) return true; 9459 //if ($utils.isNumeric(value)) return false; 9460// if (typeof value == "string") { 9461// return value.trim() == ""; 9462// } 9463// return false; 9464 return value == null || value === ''; // || value == "undefined" || value == "null"; 9465}; 9466 9467$utils.isEmpty = function(value) { 9468 if ($utils.isArray(value)) { 9469 return value.length === 0; 9470 } if ($utils.isObject(value)) { 9471 return Object.keys(value).length === 0; 9472 } 9473 return $utils.isBlank(value); 9474}; 9475 9476$utils.isNotEmpty = function(value) { 9477 return !$utils.isEmpty(value); 9478}; 9479 9480$utils.isTrue = function(value) { 9481 if (value != null) { 9482 return (value === 'true' || value === true || value === 1); 9483 } 9484 return false; 9485} 9486 9487$utils.isNumeric = function(n) { 9488 return !isNaN(parseFloat(n)) && isFinite(n); 9489} 9490 9491$utils.isInteger = function(value) { 9492 return typeof value === "number" && 9493 isFinite(value) && 9494 Math.floor(value) === value; 9495} 9496 9497$utils.toNumber = function(value) { 9498 return Number(value); 9499}; 9500 9501$utils.isId = function(o) { 9502 var re = /^[a-zA-Z0-9 ]+$/; 9503 return !re.test(o); 9504}; 9505 9506$utils.keys = function(obj) { 9507 if (obj != undefined) { 9508 return Object.keys(obj); 9509 } 9510 return []; 9511}; 9512$utils.sortKeys = function(o) { 9513 if (o == null) { 9514 return null; 9515 } 9516 delete o["$$hashKey"]; 9517
9518 // sort object by key 9519 var keys = $utils.keys(o); 9520 keys.sort(); 9521 var a = {}; 9522 for (var i in keys) { 9523 var k = keys[i]; 9524 a[k] = o[k]; 9525 9526 if ($utils.isObject(a[k])) { 9527 a[k] = $utils.sortKeys(a[k]); 9528 } 9529 } 9530 9531 return a; 9532}; 9533 9534$utils.firstkey = function(obj) { 9535 if (obj != undefined) { 9536 var keys = Object.keys(obj); 9537 if (keys.length > 0) { 9538 return keys[0]; 9539 } 9540 } 9541 return ""; 9542}; 9543 9544$utils.keyToName = function(key) { 9545 var name = ""; 9546 if (key != undefined) { 9547 var split = key.split("-"); 9548 for (var index in split) { 9549 if (name != "") { 9550 name += " "; 9551 } 9552 name += $utils.firstUpperCase(split[index]); 9553 } 9554 } 9555 return name; 9556}; 9557 9558$utils.firstUpperCase = function(name) { 9559 if (name != undefined) { 9560 if (name.length < 2) { 9561 return name; 9562 } 9563 return name.substring(0, 1).toUpperCase() + name.substring(1); 9564 } 9565 return ""; 9566}; 9567 9568$utils.join = function(list, separator) { 9569 var value = ""; 9570 if (list) { 9571 if ($utils.isArray(list)) { 9572 for (var key in list) { 9573 var item = list[key]; 9574 if (value != "") { 9575 value += separator; 9576 } 9577 value += item; 9578 } 9579 } else { 9580 for (var key in list) { 9581 var item = list[key]; 9582 if (value != "") { 9583 value += separator; 9584 } 9585 value += key + "=" + item; 9586 } 9587 } 9588 } 9589 return value; 9590}; 9591 9592$utils.parseTags = function(list) { 9593 var value = ""; 9594 if (list) { 9595 for (var key in list) { 9596 var item = list[key]; 9597 if (value != "") { 9598 value += ","; 9599 } 9600 if (item.text) { 9601 item = item.text; 9602 } 9603 value += item; 9604 } 9605 } 9606 return value; 9607}; 9608 9609$utils.getPathBy = function(path, part) { 9610 var i = path.indexOf(part); 9611 return path.substring(0, i) + part; 9612}; 9613 9614$utils.validateAlphanumeric = function(name) { 9615 if (name == null || name.trim() == "") { 9616 throw "value cannot be empty"; 9617 } 9618 var re = /^[a-zA-Z0-9 ]+$/; 9619 if (!re.test(name)) { 9620 throw "'" + name + "' contains invalid characters"; 9621 } 9622 var INVALID_KEYS = ["entity", "test"]; 9623 if (INVALID_KEYS.indexOf(name.toLowerCase()) != -1) { 9624 throw "'" + name + "' is not valid"; 9625 } 9626}; 9627 9628$utils.getRandom = function() { 9629 return (Math.random() * 11 * 10000).toFixed(0); 9630}; 9631 9632$utils.showLoading = function(field) { 9633 if (field && field != "generic") { 9634 field = $(field); 9635 if (field.length > 0) { 9636 // loading in place 9637 if (field.find("label.loading").length == 0) { 9638 9639 // Buttons bootstrap 9640 if (field.find("> span.material-icons").length > 0) { 9641 field.find("> span.material-icons").addClass("d-none").after('<label class="loading"> </label>'); 9642 9643 } else { 9644 field.append('<label class="loading"> </label>'); 9645 } 9646 } 9647 return; 9648 } 9649 } 9650 9651 // generic loading 9652 if ($("#full-loading").length == 0) { 9653 //console.log(new Error('showing loading')) 9654 $("body").append($('<div id="full-loading"></div>')); 9655 $("body").addClass('full-loading'); 9656 } 9657}; 9658 9659$utils.hideLoading = function(field) { 9660 if ($("#full-loading").length > 0) { 9661 //console.log(new Error('hiding loading')) 9662 $("#full-loading").remove(); 9663 $("body").removeClass('full-loading'); 9664 } 9665 if (field && field != "generic" && $(field).length > 0) { 9666 field = $(field); 9667 field.find("label.loading").remove(); 9668 9669 9670 // Buttons bootstrap 9671 if (field.find("span.material-icons").length > 0) { 9672 field.find("span.material-icons").removeClass("d-none"); 9673 } 9674 } 9675}; 9676 9677/** Parse the javascript number to string */ 9678$utils.numberParse = function(value, numDecimals, decimales) { 9679 return value; 9680// TODO for negative values 9681// var miles = ","; 9682// if (decimales == undefined || decimales == "") { 9683// decimales = $locale.decimal; 9684// } 9685// if (decimales == ",") { 9686// miles = "."; 9687// } else { 9688// decimales = "."; 9689// } 9690// if (numDecimals == undefined || numDecimals == "") { 9691// numDecimals = 2; 9692// } 9693// 9694// value = value.toFixed(numDecimals); 9695// 9696// var str = value + ''; 9697// var decimal = str.split(".")[1]; 9698// if (decimal.length == 0) { 9699// decimal = decimales + "00"; 9700// } else if (decimal.length == 1) { 9701// decimal = decimales + decimal+"0"; 9702// } else { 9703// decimal = decimales + decimal; 9704// } 9705// 9706// str = str.split(".")[0]; 9707// 9708// var amount = new String(str); 9709// amount = amount.split("").reverse(); 9710// 9711// var output = ""; 9712// for ( var i = 0; i <= amount.length-1; i++ ){ 9713// output = amount[i] + output; 9714// if ((i+1) % 3 == 0 && (amount.length-1) !== i)output = miles + output; 9715// } 9716// return output + decimal; 9717}; 9718 9719/** Parse the string to javascript number */ 9720$utils.numberFormat = function(valor, decimales) { 9721 9722 var miles = ","; 9723 if (decimales == undefined || decimales == "") { 9724 decimales = $locale.decimal; 9725 } 9726 if (decimales == ",") { 9727 miles = "."; 9728 } 9729 9730 // Eliminamos separador de miles 9731 var resultado = valor.replace(miles, ""); 9732 9733 // Reemplazmos el separador de decimles 9734 resultado = resultado.replace(decimales, "."); 9735
9736 // Se convierte en number 9737 resultado = Number(resultado); 9738 9739 return resultado; 9740}; 9741 9742$utils.getAgeFromDate = function(date) { 9743 if (date.length >= 8) { 9744 var fechaIngresada = new Date(date.substring(0, 4), 9745 date.substring(4, 6), date.substring(6, 8)); 9746 var fechaActual = new Date(); 9747 var years = new Date(fechaActual.getTime() - fechaIngresada.getTime()); 9748 var base = new Date(0); 9749 return years.getFullYear() - base.getFullYear(); 9750 } 9751 return -1; 9752}; 9753 9754$utils.lowerCase = function(name) { 9755 return name.toLowerCase(); 9756}; 9757 9758$utils.upperCase = function(name) { 9759 return name.toUpperCase(); 9760}; 9761 9762//// slash to camel case 9763//$utils.camelCase = function(name) { 9764// return name.toUpperCase(); 9765//}; 9766//// camel to slash case 9767//$utils.slashCase = function(name) { 9768// return name.toUpperCase(); 9769//}; 9770 9771$utils.capitalize = function(string) { 9772 return string.charAt(0).toUpperCase() + string.slice(1); 9773}; 9774 9775$utils.floatingError = function(msg) { 9776 $utils.floatingMsg(msg, {state: 'danger', time: 6000}); 9777}; 9778 9779$utils.floatingWarn = function(msg) { 9780 $utils.floatingMsg(msg, {state: 'info', time: 6000}); 9781}; 9782 9783$utils.floatingMsg = function($msg, options) { 9784 9785 //console.error('showing ' + $msg) 9786 9787 var defaults = { 9788 time: 5000, 9789 afterFunction: null, 9790 state: 'success' 9791 }; 9792 9793 if (options == undefined) { 9794 options = {}; 9795 } 9796 9797 var _settings = $.extend({}, defaults, options); 9798 9799 var $container = $('#fmc'); 9800 if ($container.length == 0) {
9801 $container = $('<div id="fmc"></div>'); 9802 $('body').append($container); 9803 } 9804 9805 // remove old 9806 $("div.floating-msg").remove(); 9807 9808 var $div = $('<div class="alert alert-' + _settings.state + ' floating-msg"></div>'); 9809 $div.append('<span class="close material-icons">close</span> '); 9810 $div.css('display', 'none'); 9811 $div.append($msg); 9812 $container.append($div); 9813 $div.fadeIn("fast"); 9814 9815 var closeFn = function() { 9816 $div.fadeOut("slow", function() { 9817 $div.remove(); 9818 }); 9819 if (_settings.afterFunction != null) { 9820 _settings.afterFunction(); 9821 } 9822 }; 9823 9824 $div.find("span.close").click(closeFn); 9825 9826 setTimeout(closeFn, _settings.time); 9827}; 9828 9829$utils.closeFloating = function() { 9830 if ($(".alert.floating-msg").length > 0) { 9831 $(".alert.floating-msg .close").click(); 9832 } 9833} 9834 9835$utils.showAlert = function(msg) { 9836 $angular.apply($angular.rootScope, function() { 9837 $("#content > *").remove(); 9838 $("#content").html( 9839 '<div id="messages" class="alert alert-danger"><span class="material-icons">warning</span> <label>' + msg + '</label></div>' 9840 + '<a id="btnBack" href="javascript:void(0)" onclick="$angular.goHome()" class="btn btn-primary">' + $angular.get("$translate").instant("msg.home") + '</a>'); 9841 }); 9842}; 9843$utils.showAccessDenied = function() { 9844 $utils.showAlert($angular.get("$translate").instant("msg.accessDenied")); 9845}; 9846$utils.showNotFound = function() { 9847 $utils.showAlert($angular.get("$translate").instant("msg.notFound")); 9848}; 9849$utils.showNoInternet = function() { 9850 $utils.showAlert($angular.get("$translate").instant("msg.error.noConnection")); 9851}; 9852$utils.showError = function() { 9853 $utils.showAlert($angular.get("$translate").instant("msg.error")); 9854}; 9855 9856 9857$utils.dataURItoBlob = function(dataURI) { 9858 // convert base64 to raw binary data held in a string 9859 // doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this 9860 var byteString = atob(dataURI.split(',')[1]); 9861 9862 // separate out the mime component 9863 var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; 9864 9865 // write the bytes of the string to an ArrayBuffer 9866 var ab = new ArrayBuffer(byteString.length); 9867 var ia = new Uint8Array(ab); 9868 for (var i = 0; i < byteString.length; i++) { 9869 ia[i] = byteString.charCodeAt(i); 9870 } 9871 9872 //Old Code 9873 //write the ArrayBuffer to a blob, and you're done 9874 //var bb = new BlobBuilder(); 9875 //bb.append(ab); 9876 //return bb.getBlob(mimeString); 9877 9878 //New Code 9879 return new Blob([ab], {type: mimeString}); 9880}; 9881 9882$utils.defaultDiacriticsRemovalMap = [ 9883 { 9884 'base': 'A', 9885 'letters': '\u0041\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F' 9886 }, 9887 {'base': 'AA', 'letters': '\uA732'}, 9888 {'base': 'AE', 'letters': '\u00C6\u01FC\u01E2'}, 9889 {'base': 'AO', 'letters': '\uA734'}, 9890 {'base': 'AU', 'letters': '\uA736'}, 9891 {'base': 'AV', 'letters': '\uA738\uA73A'}, 9892 {'base': 'AY', 'letters': '\uA73C'}, 9893 {'base': 'B', 'letters': '\u0042\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0182\u0181'}, 9894 {'base': 'C', 'letters': '\u0043\u24B8\uFF23\u0106\u0108\u010A\u010C\u00C7\u1E08\u0187\u023B\uA73E'}, 9895 { 9896 'base': 'D', 9897 'letters': '\u0044\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018B\u018A\u0189\uA779\u00D0' 9898 }, 9899 {'base': 'DZ', 'letters': '\u01F1\u01C4'}, 9900 {'base': 'Dz', 'letters': '\u01F2\u01C5'}, 9901 { 9902 'base': 'E', 9903 'letters': '\u0045\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E' 9904 }, 9905 {'base': 'F', 'letters': '\u0046\u24BB\uFF26\u1E1E\u0191\uA77B'}, 9906 { 9907 'base': 'G', 9908 'letters': '\u0047\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E' 9909 }, 9910 {'base': 'H', 'letters': '\u0048\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D'}, 9911 { 9912 'base': 'I', 9913 'letters': '\u0049\u24BE\uFF29\u00CC\u00CD\u00CE\u0128\u012A\u012C\u0130\u00CF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197' 9914 }, 9915 {'base': 'J', 'letters': '\u004A\u24BF\uFF2A\u0134\u0248'}, 9916 {'base': 'K', 'letters': '\u004B\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2'}, 9917 { 9918 'base': 'L', 9919 'letters': '\u004C\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u014
99191\u023D\u2C62\u2C60\uA748\uA746\uA780' 9920 }, 9921 {'base': 'LJ', 'letters': '\u01C7'}, 9922 {'base': 'Lj', 'letters': '\u01C8'}, 9923 {'base': 'M', 'letters': '\u004D\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C'}, 9924 { 9925 'base': 'N', 9926 'letters': '\u004E\u24C3\uFF2E\u01F8\u0143\u00D1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u0220\u019D\uA790\uA7A4' 9927 }, 9928 {'base': 'NJ', 'letters': '\u01CA'}, 9929 {'base': 'Nj', 'letters': '\u01CB'}, 9930 { 9931 'base': 'O', 9932 'letters': '\u004F\u24C4\uFF2F\u00D2\u00D3\u00D4\u1ED2\u1ED0\u1ED6\u1ED4\u00D5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\u00D6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\u00D8\u01FE\u0186\u019F\uA74A\uA74C' 9933 }, 9934 {'base': 'OI', 'letters': '\u01A2'}, 9935 {'base': 'OO', 'letters': '\uA74E'}, 9936 {'base': 'OU', 'letters': '\u0222'}, 9937 {'base': 'OE', 'letters': '\u008C\u0152'}, 9938 {'base': 'oe', 'letters': '\u009C\u0153'}, 9939 {'base': 'P', 'letters': '\u0050\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754'}, 9940 {'base': 'Q', 'letters': '\u0051\u24C6\uFF31\uA756\uA758\u024A'}, 9941 { 9942 'base': 'R', 9943 'letters': '\u0052\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782' 9944 }, 9945 { 9946 'base': 'S', 9947 'letters': '\u0053\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784' 9948 }, 9949 { 9950 'base': 'T', 9951 'letters': '\u0054\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786' 9952 }, 9953 {'base': 'TZ', 'letters': '\uA728'}, 9954 { 9955 'base': 'U', 9956 'letters': '\u0055\u24CA\uFF35\u00D9\u00DA\u00DB\u0168\u1E78\u016A\u1E7A\u016C\u00DC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244' 9957 }, 9958 {'base': 'V', 'letters': '\u0056\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245'}, 9959 {'base': 'VY', 'letters': '\uA760'}, 9960 {'base': 'W', 'letters': '\u0057\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72'}, 9961 {'base': 'X', 'letters': '\u0058\u24CD\uFF38\u1E8A\u1E8C'}, 9962 { 9963 'base': 'Y', 9964 'letters': '\u0059\u24CE\uFF39\u1EF2\u00DD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE' 9965 }, 9966 {'base': 'Z', 'letters': '\u005A\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762'}, 9967 { 9968 'base': 'a', 9969 'letters': '\u0061\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250' 9970 }, 9971 {'base': 'aa', 'letters': '\uA733'}, 9972 {'base': 'ae', 'letters': '\u00E6\u01FD\u01E3'}, 9973 {'base': 'ao', 'letters': '\uA735'}, 9974 {'base': 'au', 'letters': '\uA737'}, 9975 {'base': 'av', 'letters': '\uA739\uA73B'}, 9976 {'base': 'ay', 'letters': '\uA73D'}, 9977 {'base': 'b', 'letters': '\u0062\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253'}, 9978 {'base': 'c', 'letters': '\u0063\u24D2\uFF43\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184'}, 9979 {'base': 'd', 'letters': '\u0064\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\uA77A'}, 9980 {'base': 'dz', 'letters': '\u01F3\u01C6'}, 9981 { 9982 'base': 'e', 9983 'letters': '\u0065\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u025B\u01DD' 9984 }, 9985 {'base': 'f', 'letters': '\u0066\u24D5\uFF46\u1E1F\u0192\uA77C'}, 9986 { 9987 'base': 'g', 9988 'letters': '\u0067\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\u1D79\uA77F' 9989 }, 9990 { 9991 'base': 'h', 9992 'letters': '\u0068\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265' 9993 }, 9994 {'base': 'hv', 'letters': '\u0195'}, 9995 { 9996 'base': 'i', 9997 'letters': '\u0069\u24D8\uFF49\u00EC\u00ED\u00EE\u0129\u012B\u012D\u00EF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131' 9998 }, 9999 {'base': 'j', 'letters': '\u006A\u24D9\uFF4A\u0135\u01F0\u0249'}, 10000 {'base': 'k', 'letters': '\u006B\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3'}, 10001 { 10002 'base': 'l', 10003 'letters': '\u006C\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747' 10004 }, 10005 {'base': 'lj', 'letters': '\u01C9'}, 10006 {'base': 'm', 'letters': '\u006D\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F'}, 10007 { 10008 'base': 'n', 10009 'letters': '\u006E\u24DD\uFF4E\u01F9\u0144\u00F1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5' 10010 }, 10011 {'base': 'nj', 'letters': '\u01CC'}, 10012 { 10013 'base': 'o',
10014 'letters': '\u006F\u24DE\uFF4F\u00F2\u00F3\u00F4\u1ED3\u1ED1\u1ED7\u1ED5\u00F5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\u00F6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\u00F8\u01FF\u0254\uA74B\uA74D\u0275' 10015 }, 10016 {'base': 'oi', 'letters': '\u01A3'}, 10017 {'base': 'ou', 'letters': '\u0223'}, 10018 {'base': 'oo', 'letters': '\uA74F'}, 10019 {'base': 'p', 'letters': '\u0070\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755'}, 10020 {'base': 'q', 'letters': '\u0071\u24E0\uFF51\u024B\uA757\uA759'}, 10021 { 10022 'base': 'r', 10023 'letters': '\u0072\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783' 10024 }, 10025 { 10026 'base': 's', 10027 'letters': '\u0073\u24E2\uFF53\u00DF\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B' 10028 }, 10029 { 10030 'base': 't', 10031 'letters': '\u0074\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787' 10032 }, 10033 {'base': 'tz', 'letters': '\uA729'}, 10034 { 10035 'base': 'u', 10036 'letters': '\u0075\u24E4\uFF55\u00F9\u00FA\u00FB\u0169\u1E79\u016B\u1E7B\u016D\u00FC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289' 10037 }, 10038 {'base': 'v', 'letters': '\u0076\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C'}, 10039 {'base': 'vy', 'letters': '\uA761'}, 10040 {'base': 'w', 'letters': '\u0077\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73'}, 10041 {'base': 'x', 'letters': '\u0078\u24E7\uFF58\u1E8B\u1E8D'}, 10042 { 10043 'base': 'y', 10044 'letters': '\u0079\u24E8\uFF59\u1EF3\u00FD\u0177\u1EF9\u0233\u1E8F\u00FF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF' 10045 }, 10046 {'base': 'z', 'letters': '\u007A\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763'} 10047]; 10048 10049$utils.diacriticsMap = {}; 10050for (var i = 0; i < $utils.defaultDiacriticsRemovalMap.length; i++) { 10051 var letters = $utils.defaultDiacriticsRemovalMap[i].letters; 10052 for (var j = 0; j < letters.length; j++) { 10053 $utils.diacriticsMap[letters[j]] = $utils.defaultDiacriticsRemovalMap[i].base; 10054 } 10055} 10056 10057// "what?" version ... http://jsperf.com/diacritics/12 10058$utils.removeDiacritics = function(str) {
10059 return str.replace(/[^\u0000-\u007E]/g, function(a) { 10060 return $utils.diacriticsMap[a] || a; 10061 }); 10062}; 10063 10064$utils.loadFile = function(filetype, filePath) { 10065 10066 var hc = filePath.hashCode(); 10067 $("#f" + hc).remove(); 10068 10069 if (filetype == "js") { 10070 var fileref = document.createElement('script') 10071 fileref.setAttribute("type", "text/javascript") 10072 fileref.setAttribute("src", filePath) 10073 fileref.setAttribute("id", "f" + hc) 10074 document.getElementsByTagName("head")[0].appendChild(fileref) 10075 10076 } else if (filetype == "css") { 10077 var fileref = document.createElement("link") 10078 fileref.setAttribute("rel", "stylesheet") 10079 fileref.setAttribute("type", "text/css") 10080 fileref.setAttribute("href", filePath) 10081 fileref.setAttribute("id", "f" + hc) 10082 document.getElementsByTagName("head")[0].appendChild(fileref) 10083 } 10084}; 10085 10086$utils.isEmail = function(email) { 10087 var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; 10088 return re.test(String(email).toLowerCase()); 10089} 10090 10091$utils.parseToHtml = function(o, name, level) { 10092 if (o == null) { 10093 return ""; 10094 } 10095 if (level == null) { 10096 level = 0; 10097 } 10098 if (name == null) { 10099 name = ""; 10100 } 10101 10102 if ($utils.isArray(o)) { 10103 if (o.length == 0) { 10104 return ""; 10105 } 10106 if (o.length == 1) { 10107 return $utils.parseToHtml(o[0]); 10108 } 10109 10110 var result = ""; 10111 level = 0; // reset with ul 10112 result += "<ul class='list-group'>"; 10113 for (var key in o) { 10114 var item = o[key]; 10115 10116 if (item.entity && item.id) { 10117 10118 var url = $angular.rootScope.getItemLinkBy(item); 10119 result += "<li class='list-group-item table-relation'>"; 10120 result += "<a class='row' href='" + url + "'>"; 10121 var column = $entity.getColumn(item.entity, name); 10122 var cols = $entity.getTableColumns(item.entity, column); 10123 if (cols.length > 1 && column == null) { 10124 cols = [cols[0]]; // just first 10125 } 10126 for (var k in cols) { 10127 var col = cols[k]; 10128 result += "<div class='col-sm col-6'>"; 10129 if (cols.length > 1) { 10130 result += "<small>"+$utils.parseGeoTranslation(col.name, item.entity)+"</small>"; 10131 } 10132 result += "<label>"+$entity.displayColumn(item, col)+"</label></div>"; 10133 } 10134 result += "</a>"; 10135 result += "</li>"; 10136 10137 } else { 10138 result += "<li class='list-group-item'>"; 10139 var val = $utils.parseToHtml(item, name, level); 10140 if (name == 'categories') { 10141 val = $constants.getEntityDesc('category', val); 10142 } 10143 result += val + "</li>"; 10144 } 10145 } 10146 result += "</ul>"; 10147 return result; 10148 } 10149 10150 if (typeof (o) == 'object') { 10151 10152 if (o.entity && o.id) { 10153 var val = $entity.displayColumn(o); 10154 if (val) { 10155 var url = $angular.rootScope.getItemLinkBy(o); 10156 if (url != null) { 10157 return "<a href='" + url + "'>" + val + "</a>"; 10158 } 10159 return val; 10160 } 10161 } 10162 10163 if (o.day != null && o.time_from != null && o.time_to != null) { 10164 return o.day + " " + o.time_from + "-" + o.time_to; 10165 } 10166 10167 var otmp = {}; 10168 for (var key in o) { 10169 var val = o[key]; 10170 if (val == null || key == '$$hashKey') { 10171 continue; 10172 } 10173 10174 var lev = level; 10175 if (typeof (val) == 'object') { 10176 lev++; 10177 } 10178 10179 var text = $utils.toText(key); 10180 10181 switch (key) { 10182 case "id": 10183 continue; 10184 10185 case "entity": 10186 case "entityType": 10187 case "entityId": 10188 case "entity_id": 10189 var ent = o.entity != null ? o.entity : o.entityType; 10190 var eid = o.entityId != null ? o.entityId : o.entity_id; 10191 if (ent != null || eid != null) { 10192 text = "Entity"; 10193 var url = $angular.rootScope.getItemLink(ent, eid); 10194 val = "<a href='" + url + "'>" + $constants.getEntityDesc(ent, eid) + "</a>"; 10195 } 10196 break; 10197 10198 case "action": 10199 case "value": 10200 if (o.action && o.value) { 10201 var userAction = $constants.userActions[o.action]; 10202 if (userAction) { 10203 userAction = $angular.get("$translate").instant(userAction); 10204 } else { 10205 userAction = o.action; 10206 } 10207 text = "Action"; 10208 val = $utils.parseToHtml(o.value, 'action', lev + 1); 10209 } 10210 break; 10211 10212 case "geo_location": 10213 case "latitude": 10214 case "longitude": 10215 var tmp = o; 10216 if (tmp.geo_location) { 10217 tmp = tmp.geo_location; 10218 } 10219 if (tmp.latitude && tmp.longitude) { 10220 var loc = tmp.latitude + "," + tmp.longitude; 10221 var url = "https://www.google.com/maps/search/?api=1&query=" + loc; 10222 text = "Location"; 10223 val = "<a href='" + url + "' target='_blank'>" + loc + "</a>"; 10224 } 10225 break; 10226 10227 case "device": 10228 val = "<a href='" + $instance.getBaseUrl() + "device/" + val + "'>" + $constants.getEntityDesc('device', val) + "</a>"; 10229 break; 10230 10231 case "instance": 10232 val = "<a href='" + $instance.getBaseUrl() + "instance/" + val + "'>" + $constants.getEntityDesc('instance', val) + "</a> "; 10233 break; 10234 10235 case "date": 10236 val = $utils.parseDateTotal(val); 10237 break; 10238 10239 default: 10240 var value = $utils.parseToHtml(val, key, lev); 10241 if (!$utils.isBlank(value)) { 10242 val = value; 10243 } 10244 break; 10245 } 10246 otmp[text] = val; 10247 } 10248 10249 var result = ""; 10250 for (var key in otmp) { 10251 result = $utils.addBrIfNeeded(result); 10252 result += key + ": " + otmp[key] + " "; 10253 } 10254 return "<div class='action-" + level + "'>" + result + "</div>"; 10255 } 10256 10257 if (typeof o == 'string') { 10258 10259 if (o.startsWith('http')) { 10260 return "<a href='" + o + "' target='_blank'>" + o + "</a>"; 10261 } 10262 10263 if ($utils.isEmail(o)) { 10264 var url = $angular.rootScope.getItemLink('user', o); 10265 return "<a href='" + url + "'>" + o + "</a>"; 10266 } 10267 10268 var split = o.split('#|#'); 10269 if (split.length === 2) { 10270 var url = $angular.rootScope.getItemLink(split[0], split[1]); 10271 return "<a href='" + url + "'>" + split[0] + ":" + split[1] + "</a>"; 10272 } 10273 } 10274 10275 return o; 10276}; 10277 10278$utils.addBrIfNeeded = function(result) { 10279 result = result.trim(); 10280 if (result.length > 8) { 10281 //console.log(result.endsWith('</div>') + " -> " + result.substring(result.length-8), result.length) 10282 if (!result.endsWith('</div>')) { 10283 result += "<br>"; 10284 } 10285 } 10286 return result; 10287}; 10288 10289$utils.printCurrency = function(price, currency) { 10290 if (!price || isNaN(price)) { 10291 price = 0; 10292 } 10293 if (!currency && $instance.current && $instance.current.geo_buy) { 10294 currency = $instance.current.geo_buy.currency; 10295 } 10296 var config = null; 10297 if ($angular.currencies && currency) { 10298 config = $angular.currencies[currency]; 10299 } 10300 if (config == null) { 10301 if (currency == null) { 10302 currency = ""; 10303 } 10304 config = { 10305 decimalDigits: 2, 10306 symbolAfterNumber: true, 10307 symbol: currency 10308 }; 10309 } 10310 10311 var isNegative = price < 0; 10312 if (isNegative) { 10313 price = -price; 10314 } 10315 10316 var print = config.symbolAfterNumber ? '' : config.symbol; 10317 print += $utils.parseNumber(Number(price).toFixed(config.decimalDigits)); 10318 print += config.symbolAfterNumber ? ' ' + config.symbol : ''; 10319 10320 if (isNegative) { 10321 print = "-" + print; 10322 } 10323 10324 return print; 10325}; 10326 10327$utils.addTaxes = function(price, tax) { 10328 if (!price || isNaN(price)) { 10329 price = 0; 10330 } 10331 price = Number(price); 10332 if (!tax || isNaN(tax)) { 10333 return price; 10334 } 10335 tax = Number(tax); 10336 if (price !== 0 && 10337 tax !== 0 && 10338 $instance.current && 10339 $instance.current.geo_buy && 10340 $utils.isTrue($instance.current.geo_buy.show_prices_with_taxes)) { 10341 return (price * tax / 100) + price; 10342 } 10343 return price; 10344}; 10345 10346$utils.getWithRetries = function(getter, retries, waitTime, attempt) { 10347 if (!retries) { 10348 retries = 5; 10349 } 10350 if (!waitTime) { 10351 waitTime = 300; 10352 } 10353 if (!attempt) { 10354 attempt = 0; 10355 } 10356 return new Promise(function(resolve) { 10357 if (attempt > retries) { 10358 resolve(null); 10359 } else { 10360 var result = getter(); 10361 if (result === undefined) { 10362 setTimeout(function() { 10363 $utils.getWithRetries(getter, retries, waitTime, ++attempt).then(function(result) { 10364 resolve(result); 10365 }) 10366 }, waitTime); 10367 } else { 10368 resolve(result); 10369 } 10370 } 10371 }); 10372}; 10373 10374$utils.prepareMapImages = function(entity, map) { 10375 if ($entity.isGeoLocation(entity) && $instance.hasEntity('mapimage')) { 10376 $rest.get({ 10377 url: contextPath + "/api/geo/mapimage.json" 10378 }).then(function(response) { 10379 Promise.all(response.list.map(function(item) { 10380 return $rest.get({ 10381 url: contextPath + "/api/geo/mapimage/" + item.id + ".json" 10382 }); 10383 })).then(function(mapImages) { 10384 if (mapImages && mapImages.length > 0) { 10385 var overlays = [];
10386 mapImages.forEach(function(mapImage) { 10387 var bounds = new google.maps.LatLngBounds( 10388 new google.maps.LatLng(mapImage.south_west.latitude, mapImage.south_west.longitude), 10389 new google.maps.LatLng(mapImage.north_east.latitude, mapImage.north_east.longitude) 10390 ); 10391 var image = contextPath + '/www/media/' + mapImage.map + '.io'; 10392 var overlay = $utils.prepareMapImageOverlay(bounds, image); 10393 10394 $utils.addMapButton(map, $utils.parse(mapImage.name), function() { 10395 overlays.forEach(function(iter) { 10396 if (iter === overlay) { 10397 iter.show(map); 10398 map.fitBounds(bounds); 10399 } else { 10400 iter.hide(); 10401 } 10402 }); 10403 }); 10404 10405 overlays.push(overlay); 10406 }); 10407 $utils.addMapButton(map, $angular.get("$translate").instant('msg.normal'), function() { 10408 overlays.forEach(function(overlay) { 10409 overlay.hide(); 10410 }); 10411 }); 10412 } 10413 }); 10414 }); 10415 } 10416}; 10417 10418$utils.addMapButton = function(map, text, onClick) { 10419 var button = document.createElement('button'); 10420 button.textContent = text; 10421 button.classList.add('btn', 'btn-primary'); 10422 button.addEventListener('click', onClick); 10423 map.controls[google.maps.ControlPosition.TOP_RIGHT].push(button); 10424}; 10425 10426$utils.prepareMapImageOverlay = function(bounds, image) { 10427 var overlayView = new google.maps.OverlayView(); 10428 var div; 10429 10430 overlayView.onAdd = function() { 10431 div = document.createElement('div'); 10432 div.style.borderStyle = 'none'; 10433 div.style.borderWidth = '0px'; 10434 div.style.position = 'absolute'; 10435 10436 var img = document.createElement('img'); 10437 img.src = image; 10438 img.style.width = '100%'; 10439 img.style.height = '100%'; 10440 img.style.position = 'absolute'; 10441 div.appendChild(img); 10442 10443 var panes = overlayView.getPanes(); 10444 panes.overlayLayer.appendChild(div); 10445 }; 10446 10447 overlayView.draw = function() { 10448 var overlayProjection = overlayView.getProjection(); 10449 var sw = overlayProjection.fromLatLngToDivPixel(
10450 bounds.getSouthWest() 10451 ); 10452 var ne = overlayProjection.fromLatLngToDivPixel( 10453 bounds.getNorthEast() 10454 ); 10455 if (div) { 10456 div.style.left = sw.x + 'px'; 10457 div.style.top = ne.y + 'px'; 10458 div.style.width = ne.x - sw.x + 'px'; 10459 div.style.height = sw.y - ne.y + 'px'; 10460 } 10461 }; 10462 10463 overlayView.onRemove = function() { 10464 if (div) { 10465 div.parentNode.removeChild(div); 10466 div = null; 10467 } 10468 }; 10469 10470 return { 10471 hide: function() { 10472 overlayView.setMap(null); 10473 }, 10474 show: function(map) { 10475 overlayView.setMap(map); 10476 } 10477 }; 10478}; 10479 10480$utils.toggleItemOnList = function(obj, listName, item) { 10481 var list = obj[listName]; 10482 if (!$utils.isArray(list)) { 10483 list = []; 10484 obj[listName] = list; 10485 } 10486 var index = list.indexOf(item); 10487 if (index < 0) { 10488 list.push(item); 10489 } else { 10490 list.splice(index, 1); 10491 } 10492}; 10493 10494$utils.isEqual = function(object1, object2) { 10495 var keys1 = Object.keys(object1).filter(function(key) { 10496 return key !== '$$hashKey'; 10497 }); 10498 var keys2 = Object.keys(object2).filter(function(key) { 10499 return key !== '$$hashKey'; 10500 }); 10501 if (keys1.length !== keys2.length) { 10502 return false; 10503 } 10504 for (var key in object1) { 10505 if (key !== '$$hashKey' && object1[key] !== object2[key]) { 10506 return false; 10507 } 10508 } 10509 return true; 10510}; 10511 10512$utils.clone = function(o) { 10513 if (o == null) { 10514 return null; 10515 } 10516 if ($utils.isArray(o)) { 10517 return o.map(function(prop) { 10518 return $utils.clone(prop); 10519 }).filter(function(prop) { 10520 return prop !== undefined && prop !== null; 10521 }); 10522 } 10523 if (typeof o == 'object') { 10524 var result = {}; 10525 var keys = Object.keys(o); 10526 for (var k in keys) { 10527 var key = keys[k]; 10528 if (key == null || (typeof key == 'string' && key.startsWith('$'))) { 10529 continue; 10530 } 10531 var cloned = $utils.clone(o[key]); 10532 if (cloned !== undefined && cloned !== null) { 10533 result[key] = cloned; 10534 } 10535 } 10536 return result; 10537 } 10538 return o; 10539}; 10540 10541$utils.openNextUploadFile = function(e) { 10542 $utils.preventDefault(e); 10543 $(e.target).next('input[type="file"]').trigger('click'); 10544} 10545 10546$utils.addFileOnModel = function($scope, files, model, column, isMultiple) { 10547 if (files.length === 0) { 10548 return; 10549 } 10550 var file = files[0]; 10551 var reader = new FileReader(); 10552 reader.onload = function(event) { 10553 var base64 = file.name + ';' + event.target.result; 10554 if (isMultiple) { 10555 if (model[column]) { 10556 model[column].push(base64); 10557 } else { 10558 model[column] = [base64]; 10559 } 10560 } else { 10561 model[column] = base64; 10562 } 10563 $angular.apply($scope); 10564 }; 10565 reader.readAsDataURL(file); 10566} 10567 10568$utils.autoSave = function(model, column, pathPrefix) { 10569 if (!column._autosave) { 10570 return; 10571 } 10572 10573 var root = $angular.searchRootModel(); 10574 if (root == null) { 10575 //$angular.buttonError(root, column, model, 'AutoSave: root not found'); 10576 console.log('AutoSave: root not found'); 10577 return; 10578 } 10579 10580 var form = $angular.searchFormView(); 10581 var formId; 10582 if (form && form.form) { 10583 formId = form.form.id; 10584 } 10585 10586 var value = model[column.name]; 10587 var path = column.path; 10588 if (path == null) { 10589 path = column.name; 10590 } 10591 if (path == null) { 10592 $angular.buttonError(root, column, model, 'AutoSave: path not found'); 10593 return; 10594 } 10595 if (pathPrefix) { 10596 path = pathPrefix + path; 10597 } 10598 10599 var entity = root.entity; 10600 var entityId = root.id; 10601 if (entity == null || entityId == null) { 10602 $angular.buttonError(root, column, model, 'AutoSave: entity/id not found'); 10603 return; 10604 } 10605 10606 $angular.get("$timeout")(function() { 10607 var baseUrl = contextPath + '/' + ($constants.isWeb ? 'www' : 'api'); 10608 //console.log('saving ' + path + " = " + value); 10609 $rest.put({ 10610 url: baseUrl + '/geo/' + entity + '/' + entityId + '/value.json', 10611 data: { 10612 path: path, 10613 formId: formId, 10614 value: value 10615 }, 10616 loading: 'generic', 10617 successMessage: $angular.get("$translate").instant('msg.updated') 10618 }).then(function () { 10619 $angular.contentScope.refresh(); 10620 }); 10621 }); 10622} 10623 10624$utils.prepareMediaColumnData = function(column) { 10625 var geoMediaFolder; 10626 var extension; 10627 var editFunction; 10628 var msgUploadKey; 10629 var acceptFileTypes; 10630 switch (column.type) { 10631 case 'image': 10632 geoMediaFolder = 'images'; 10633 extension = 'img'; 10634 editFunction = $angular.contentScope.editImage; 10635 msgUploadKey = 'msg.uploadImage'; 10636 acceptFileTypes = 'image/*'; 10637 break; 10638 case 'audio': 10639 geoMediaFolder = 'audio'; 10640 extension = 'audio'; 10641 editFunction = $angular.contentScope.editAudio; 10642 msgUploadKey = 'msg.uploadAudio'; 10643 acceptFileTypes = 'audio/*'; 10644 break; 10645 case 'video': 10646 geoMediaFolder = 'video'; 10647 extension = 'video'; 10648 editFunction = $angular.contentScope.editVideo; 10649 msgUploadKey = 'msg.uploadVideo'; 10650 acceptFileTypes = 'video/*'; 10651 break; 10652 case 'document': 10653 geoMediaFolder = 'others'; 10654 extension = 'data'; 10655 editFunction = $angular.contentScope.editOther; 10656 msgUploadKey = 'msg.uploadFile'; 10657 acceptFileTypes = '*/*'; 10658 break; 10659 } 10660 return { 10661 geoMediaFolder : geoMediaFolder, 10662 getLinkUrl : function(model, mediaId) { 10663 if (mediaId) { 10664 var base = $constants.isWeb ? 'www' : 'api'; 10665 if (mediaId.extension) { 10666 return base + '/media/' + mediaId.id + '.' + mediaId.extension; 10667 } 10668 if (typeof mediaId === 'string') { 10669 if (extension) { 10670 return base + '/media/' + mediaId + '.' + extension; 10671 } 10672 if (model == null || model.geo_media == null) { 10673 model = $angular.contentScope.model; //$angular.searchRootModel(); 10674 } 10675 if (model && model.geo_media && model.geo_media[geoMediaFolder] && model.geo_media[geoMediaFolder][mediaId]) { 10676 var media = model.geo_media[geoMediaFolder][mediaId]; 10677 return base + '/media/' + mediaId + '.' + media.extension; 10678 } 10679 return base + '/media/' + mediaId + '.img'; 10680 } 10681 } 10682 return null; 10683 }, 10684 getFileName : function(model, mediaId) { 10685 if (mediaId) { 10686 if (mediaId.extension) { 10687 return mediaId.name + '.' + mediaId.extension; 10688 } 10689 if (typeof mediaId === 'string') { 10690 if (model == null || model.geo_media == null) { 10691 model = $angular.contentScope.model; //$angular.searchRootModel(); 10692 } 10693 if (model && model.geo_media && model.geo_media[geoMediaFolder] && model.geo_media[geoMediaFolder][mediaId]) { 10694 var media = model.geo_media[geoMediaFolder][mediaId]; 10695 return media.name + '.' + media.extension; 10696 } 10697 return mediaId; 10698 } 10699 } 10700 return null; 10701 }, 10702 editMedia : function($event, model, mediaId) { 10703 if (model == null || model.geo_media == null) { 10704 model = $angular.contentScope.model; //$angular.searchRootModel(); 10705 } 10706 if (model && model.geo_media && model.geo_media[geoMediaFolder] && model.geo_media[geoMediaFolder][mediaId]) { 10707 var media = model.geo_media[geoMediaFolder][mediaId]; 10708 editFunction($event, media); 10709 } 10710 }, 10711 msgUploadKey: msgUploadKey, 10712 acceptFileTypes: acceptFileTypes 10713 }; 10714} 10715 10716$utils.getColumnClasses = function(obj, column) { 10717 if ($utils.hideColumnByCondition(obj, column)) { 10718 if (column.required) { 10719 column._required = true; 10720 column.required = false;
10721 } 10722 return 'hidden'; 10723 } 10724 if (column._required) { 10725 delete column._required; 10726 column.required = true; 10727 } 10728 if (column._classes) { 10729 return column._classes; 10730 } 10731 return ''; 10732}; 10733 10734$utils.hideColumnByCondition = function(obj, column) { 10735 if (column.condition) { 10736 var value = false; 10737 try { 10738 value = eval(column.condition); // FIXME unsafe-eval 10739 } catch (e) { 10740 if ($constants.isDev) { 10741 console.log("Error eval condition: " + column.condition + " : " + e, e); 10742 } 10743 } 10744 10745 if ($constants.isDev) { 10746 var value2 = false; 10747 try { 10748 value2 = evalExpression(obj, column.condition); 10749 } catch (e) { 10750 console.log("Error eval2 condition: " + column.condition + " : " + e, e); 10751 } 10752 if (value != value2) { 10753 console.log("Error compare evals ("+value+" vs "+value2+") condition: " + column.condition); 10754 } 10755 } 10756 10757 return !value; 10758 } 10759 return false; 10760}; 10761 10762function evalExpression(obj, expr) { 10763 const tokens = tokenize(expr); 10764 const rpn = toRPN(tokens); 10765 return evalRPN(obj, rpn); 10766} 10767 10768function tokenize(expr) { 10769 const regex = /(===|!==|>=|<=|==|!=|&&|\|\||>|<|\(|\)|"(?:[^"\\]|\\.)*"|[a-zA-Z_][a-zA-Z0-9_.]*|\d+|true|false)/g; 10770 const tokens = expr.match(regex); 10771 return tokens ? tokens.map(t => t.trim()) : []; 10772} 10773 10774function toRPN(tokens) { 10775 const output = []; 10776 const stack = []; 10777 10778 for (const token of tokens) { 10779 if (token === "(") { 10780 stack.push(token); 10781 } else if (token === ")") { 10782 while (stack.length && stack[stack.length - 1] !== "(") { 10783 output.push(stack.pop()); 10784 } 10785 stack.pop(); // remove "(" 10786 } else if (precedence[token]) { 10787 while ( 10788 stack.length && 10789 precedence[stack[stack.length - 1]] >= precedence[token] 10790 ) { 10791 output.push(stack.pop()); 10792 } 10793 stack.push(token); 10794 } else { 10795 output.push(token); 10796 } 10797 } 10798 10799 while (stack.length) { 10800 output.push(stack.pop()); 10801 } 10802 10803 return output; 10804} 10805 10806const precedence = { 10807 "||": 1, 10808 "&&": 2, 10809 "==": 3, 10810 "!=": 3, 10811 "===": 3, 10812 "!==": 3, 10813 ">": 4, 10814 "<": 4, 10815 ">=": 4, 10816 "<=": 4 10817}; 10818 10819function evalRPN(obj, rpn) { 10820 const stack = []; 10821 10822 for (const token of rpn) { 10823 if (ops[token]) { 10824 const b = stack.pop(); 10825 const a = stack.pop(); 10826 stack.push(ops[token](a, b)); 10827 } else { 10828 // operand 10829 if (token.startsWith("obj.")) { 10830 stack.push(getDeep(obj, token.substring(4))); 10831 } else if (/^[a-zA-Z_]/.test(token)) { 10832 stack.push(getDeep(obj, token)); 10833 } else { 10834 stack.push(parseValue(token)); 10835 } 10836 } 10837 } 10838 10839 return stack.pop(); 10840} 10841 10842const ops = { 10843 "===": (a, b) => a === b, 10844 "!==": (a, b) => a !== b, 10845 "==": (a, b) => a == b, 10846 "!=": (a, b) => a != b, 10847 ">": (a, b) => a > b, 10848 "<": (a, b) => a < b, 10849 ">=": (a, b) => a >= b, 10850 "<=": (a, b) => a <= b, 10851 "&&": (a, b) => a && b, 10852 "||": (a, b) => a || b 10853}; 10854 10855function getDeep(obj, path) { 10856 return path.split('.').reduce((o, k) => o?.[k], obj); 10857} 10858 10859function parseValue(raw) { 10860 try { 10861 return JSON.parse(raw); 10862 } catch { 10863 return raw.replace(/^"|"$/g, ""); 10864 } 10865} 10866 10867 10868 10869//$utils.setModel = function(m, o) { 10870// if (m == null) { 10871// return o; 10872// } 10873// 10874// // clean instance 10875// for (var k in m) { 10876// if ($utils.isObject(m[k]) && !$utils.isArray(m[k]) && !k.startsWith("geo_")) { 10877// m[k] = $utils.setModel(m[k], {}); 10878// } else { 10879// m[k] = null; // delete no work 10880// } 10881// } 10882// 10883// // copy data 10884// for (var k in o) { 10885// if ($utils.isObject(o[k]) && !$utils.isArray(o[k])) { 10886// m[k] = $utils.setModel(m[k], o[k]); 10887// } else { 10888// m[k] = o[k]; 10889// } 10890// } 10891// return m; 10892//}; 10893 10894$utils.setFormviews = function(m, o) { 10895 if (o._formviews == null) o._formviews = []; 10896 if (m == null) { 10897 m = o._formviews; 10898 } else { 10899 // update only data 10900 for (var k in m) { 10901 var fv = m[k]; 10902 var fvo = o._formviews[k]; 10903 fv.data = fvo.data;//$utils.setModel(fv.data, fvo.data); 10904 } 10905 } 10906 delete o._formviews; 10907 return m; 10908}; 10909 10910$utils.printBoolean = function(value, isHtml) { 10911 var isTrue = $utils.isTrue(value); 10912 if (isHtml) { 10913 if (isTrue) { 10914 return '<span class="material-icons">done</span>'; 10915 } 10916 return '<span class="material-icons">clear</span>'; 10917 } 10918 if (isTrue) { 10919 return "\u2714"; 10920 } 10921 return "";//"\u2717"; 10922}; 10923 10924$utils.tryToTranslate = function($translate, keys, params) { 10925 for (var iter = 0; iter < keys.length; iter++) { 10926 var key = keys[iter]; 10927 var text = $translate.instant(key, params); 10928 if (text !== key) { 10929 return text; 10930 } 10931 } 10932 return null; 10933}; 10934 10935$utils.goToGeoObject = function(entity, id, preserveQueryString) { 10936 var href = $angular.rootScope.getItemLink(entity, id); 10937 if (preserveQueryString) { 10938 href += window.location.search; 10939 } 10940 window.location.href = href; 10941}; 10942 10943$utils.printHtml = function (html, test) { 10944 if (test) { 10945 window.open().document.write(html); 10946 return; 10947 } 10948 var hiddenFrame = $('<iframe style="visibility: hidden"></iframe>').appendTo('body')[0]; 10949 hiddenFrame.contentWindow.printAndRemove = function () { 10950 hiddenFrame.contentWindow.print(); 10951 setTimeout(function() { 10952 $(hiddenFrame).remove(); 10953 }, 3000); 10954 }; 10955 var htmlContent = "<html><body onload='printAndRemove();'>" + html + "</body></html>"; 10956 var doc = hiddenFrame.contentWindow.document.open("text/html", "replace"); 10957 doc.write(htmlContent); 10958 doc.close(); 10959}; 10960 10961$utils.printUrl = function (url, num) { 10962 console.log(url); 10963 10964 $utils.showLoading(); 10965// setTimeout(function() { 10966// }, 3000); 10967 10968 var hiddenFrame = $('<iframe style="visibility: hidden"></iframe>').appendTo('body')[0]; 10969 hiddenFrame.contentWindow.printAndRemove = async () => { 10970 const canvas = hiddenFrame.contentDocument.getElementById('pdf-canvas'); 10971 const ctx = canvas.getContext('2d'); 10972 const pdf = await hiddenFrame.contentWindow.pdfjsLib.getDocument(url).promise; 10973 const page = await pdf.getPage(1); // Obtén la primera página del PDF 10974 const viewport = page.getViewport({ scale: 1 }); 10975 canvas.width = viewport.width; 10976 canvas.height = viewport.height; 10977 const renderContext = { 10978 canvasContext: ctx, 10979 viewport: viewport 10980 }; 10981 await page.render(renderContext).promise; 10982 $utils.hideLoading(); 10983 hiddenFrame.contentWindow.print(); 10984 $utils.hideLoading(); 10985 10986 //for (var i=0; i<num; i++) { } 10987 if (num > 1) { 10988 num--; 10989 $rest.openConfirmPanel("msg.print.next", "", function() { 10990 $utils.printUrl(url, num); 10991 }, function() {}); 10992 } 10993 }; 10994 10995 var htmlContent = 10996 "<html>" 10997 + "<head>" 10998 + "<style>@media print { @page { margin: 0; } body { margin: 0; } ::-webkit-scrollbar { display: none; } }</style>" 10999 + "<script src='https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.16.105/pdf.min.js'></script>" 11000 + "</head>" 11001 + "<body onload='printAndRemove();'>
11001<canvas id='pdf-canvas'></canvas></body>" 11002 + "</html>"; 11003 11004 var doc = hiddenFrame.contentWindow.document.open("text/html", "replace"); 11005 doc.write(htmlContent); 11006 doc.close(); 11007 11008}; 11009 11010$utils.contains = function(array, item) { 11011 return $utils.isArray(array) && array.indexOf(item) > -1; 11012}; 11013 11014$utils.validateEnabledObject = function(entity, id) { 11015 var defer = $angular.get('$q').defer(); 11016 if (id) { 11017 $constants.getDataMin(entity, id, function(obj) { 11018 if (!obj) { 11019 defer.reject('notFound'); 11020 } else if (!obj.enabled) { 11021 defer.reject('disabled'); 11022 } else { 11023 defer.resolve(true); 11024 } 11025 }); 11026 } else { 11027 defer.reject('empty'); 11028 } 11029 return defer.promise; 11030}; 11031 11032$utils.pushDistinct = function(obj, attrName, item) { 11033 if (obj && attrName && item) { 11034 var list = obj[attrName]; 11035 if (!list) { 11036 list = []; 11037 obj[attrName] = list; 11038 } 11039 if ($utils.isArray(list)) { 11040 if ($utils.isObject(item)) { 11041 var contains = list.find(function(i) { 11042 return $utils.isEqual(item, i); 11043 }); 11044 if (!contains) { 11045 list.push($utils.clone(item)); 11046 } 11047 } else if (!list.includes(item)) { 11048 list.push(item); 11049 } 11050 } 11051 } 11052}; 11053 11054$utils.isFormula = function(text) { 11055 return true; 11056// if (!text) { 11057// return false; 11058// } 11059// return /^[a-z\d_]+\(.*\)$/g.test(text.trim()); 11060}; 11061 11062$utils.array_move = function(arr, old_index, new_index) { 11063 if (new_index >= arr.length) { 11064 var k = new_index - arr.length + 1; 11065 while (k--) { 11066 arr.push(undefined); 11067 } 11068 } 11069 arr.splice(new_index, 0, arr.splice(old_index, 1)[0]); 11070}; 11071 11072$utils.isGeoObjectId = function(id) { 11073 return id && /^[0-9a-f]{24}$/.test(id); 11074}; 11075 11076$utils.deepEquals = function(o1, o2) { 11077 if ($utils.isArray(o1) && $utils.isArray(o2)) { 11078 if (o1.length !== o2.length) { 11079 return false; 11080 } 11081 for (var iter = 0; iter < o1.length; iter++) { 11082 if (!$utils.deepEquals(o1[iter], o2[iter])) { 11083 return false; 11084 } 11085 } 11086 return true; 11087 } else if ($utils.isObject(o1) && $utils.isObject(o2)) { 11088 var keys1 = Object.keys(o1); 11089 var keys2 = Object.keys(o2); 11090 if (keys1.length !== keys2.length) { 11091 return false; 11092 } 11093 for (var iterKey = 0; iterKey < keys1.length; iterKey++) { 11094 var key = keys1[iterKey]; 11095 if (keys2.indexOf(key) < 0) { 11096 return false; 11097 } 11098 if (!$utils.deepEquals(o1[key], o2[key])) { 11099 return false; 11100 } 11101 } 11102 return true; 11103 } else { 11104 return o1 === o2; 11105 } 11106}; 11107 11108//// File entity.js //// 11109var $entity = {}; 11110 11111$entity.isAppObject = function(entity) { 11112 var meta = $entity.getEntity(entity); 11113 return meta != null && meta.type === "entity"; 11114}; 11115 11116$entity.isCustomId = function(entity) { 11117 var meta = $entity.getEntity(entity); 11118 return meta != null && $utils.isTrue(meta.custom_id); 11119}; 11120 11121$entity.isCreateSimple = function(entity) { 11122 var meta = $entity.getEntity(entity); 11123 return meta && meta.options && $utils.isTrue(meta.options.create_simple); 11124}; 11125$entity.isAttachDocuments = function(entity) { 11126 var meta = $entity.getEntity(entity); 11127 return meta && meta.options && $utils.isTrue(meta.options.attach_documents); 11128}; 11129$entity.isDisplayTable = function(entity) { 11130 var meta = $entity.getEntity(entity); 11131 return meta && meta.options && $utils.isTrue(meta.options.display_table) && !$utils.isScreenSmall; 11132}; 11133$entity.isDisplayTableWeb = function(entity) { 11134 var meta = $entity.getEntity(entity); 11135 return meta && meta.options && $utils.isTrue(meta.options.display_table_web); 11136}; 11137$entity.isHideMedia = function(entity) { 11138 var meta = $entity.getEntity(entity); 11139 return meta && meta.options && $utils.isTrue(meta.options.hide_media); 11140}; 11141$entity.isShowProperties = function(entity) { 11142 var meta = $entity.getEntity(entity); 11143 return meta && meta.options && $utils.isTrue(meta.options.show_properties); 11144}; 11145$entity.isShowKeyValues = function(entity) { 11146 var meta = $entity.getEntity(entity); 11147 return meta && meta.options && $utils.isTrue(meta.options.show_key_values); 11148}; 11149$entity.isReadonly = function(entity) { 11150 var meta = $entity.getEntity(entity); 11151 return meta && meta.options && $utils.isTrue(meta.options.readonly); 11152}; 11153$entity.isOneItem = function(entity) { 11154 var meta = $entity.getEntity(entity); 11155 return meta && meta.options && $utils.isTrue(meta.options.one_item); 11156}; 11157$entity.isAutoLocation = function(entity) { 11158 var meta = $entity.getEntity(entity); 11159 return meta && meta.options && $utils.isTrue(meta.options.auto_location); 11160}; 11161$entity.isModeler = function(entity) { 11162 var meta = $entity.getEntity(entity); 11163 return meta && meta.options && $utils.isTrue(meta.options.modeler); 11164}; 11165 11166$entity.isTabVisible = function(entity, value) { 11167 var meta = $entity.getEntity(entity); 11168 var hidden = meta && meta.tabs && $utils.isTrue(meta.tabs[value]); 11169 return !hidden; 11170}; 11171 11172$entity.getCalendarColumns = function(entity) { 11173 var getColumn = function(by) { 11174 if (by === 'sys.created' || by === 'sys.updated') { 11175 return { name: by, type: 'datetime' }; 11176 } 11177 return $entity.getColumn(entity, by); 11178 }; 11179 var dateColumn; 11180 var timeColumn; 11181 var meta = $entity.getEntity(entity); 11182 var calendarDate = meta ? meta.calendar_date : null; 11183 var isGeoSchedule = $entity.isGeoSchedule(entity); 11184 if (calendarDate === 'geo_schedule') { 11185 isGeoSchedule = true; 11186 } else if (calendarDate) { 11187 isGeoSchedule = false;
11188 var parts = calendarDate.split(','); 11189 for (var i = 0; i < parts.length; i++) { 11190 var column = getColumn(parts[i]); 11191 var type = $entity.getColumnType(column); 11192 if (type === 'datetime') { 11193 return { date: column }; 11194 } 11195// if (type === 'formula') { 11196// return { date: column }; 11197// } 11198 if (type === 'date' && !dateColumn) { 11199 dateColumn = column; 11200 } 11201 if (type === 'time' && !timeColumn) { 11202 timeColumn = column; 11203 } 11204 if (dateColumn && timeColumn) { 11205 return { date: dateColumn, time: timeColumn }; 11206 } 11207 } 11208 } 11209 return { date: dateColumn ? dateColumn : getColumn('sys.created'), geoSchedule: isGeoSchedule }; 11210}; 11211 11212$entity.hasBinding = function(value, entity) { 11213 var meta = $entity.getEntity(entity); 11214 return meta != null && meta.binding != null && meta.binding.indexOf(value) !== -1; 11215}; 11216 11217$entity.isGeoUser = function(entity) { 11218 return $entity.hasBinding("geo_user", entity); 11219}; 11220$entity.isGeoLocation = function(entity) { 11221 return $entity.hasBinding("geo_location", entity) || $entity.hasBinding("geo_fence", entity); 11222}; 11223$entity.isGeoSchedule = function(entity) { 11224 var meta = $entity.getEntity(entity); 11225 if (meta && meta.id === 'instance') { 11226 return $instance.hasGeoSchedule(); 11227 } 11228 return $entity.hasBinding("geo_schedule", entity); 11229}; 11230$entity.isGeoTrivia = function(entity) { 11231 return $entity.hasBinding("geo_trivia", entity); 11232}; 11233$entity.isGeoPrize = function(entity) { 11234 return $entity.hasBinding("geo_prize", entity); 11235}; 11236$entity.isGeoForm = function(entity) { 11237 return $entity.hasBinding("geo_form", entity); 11238}; 11239$entity.isGeoBuy = function(entity) { 11240 var meta = $entity.getEntity(entity); 11241 if (meta && meta.id === 'instance') { 11242 return $instance.hasGeoBuy(); 11243 } 11244 return $entity.hasBinding("geo_buy", entity); 11245}; 11246$entity.isGeoSmartRate = function(entity) { 11247 if ($instance.current && $instance.current.geo_smarter) { 11248 var meta = $entity.getEntity(entity); 11249 var smarter = $instance.current.geo_smarter; 11250 if (meta && smarter.entities && !$utils.isTrue(smarter.disabled)) { 11251 return smarter.entities.indexOf(meta.id) !== -1; 11252 } 11253 } 11254 return false; 11255}; 11256$entity.isGeoCalendar = function(entity) { 11257 return $entity.hasBinding("geo_calendar", entity); 11258}; 11259 11260$entity.getColumnsTranslations = function(entity, model) { 11261 var columns = []; 11262 var meta = $entity.getEntity(entity); 11263 if (meta) { 11264 $entity.addColumnsTextTranslations(columns, meta.columns, meta, model); 11265 11266 if ($entity.isGeoLocation(entity)) { 11267 columns.push({name: 'address', type: 'geo_location'}); 11268 columns.push({name: 'hint', type: 'geo_location'}); 11269 } 11270 if ($entity.isGeoTrivia(entity)) { 11271 columns.push({name: 'question', type: 'geo_trivia'}); 11272 columns.push({name: 'answer_explanation', type: 'geo_trivia'}); 11273 } 11274 if ($entity.isGeoPrize(entity)) { 11275 columns.push({name: 'hint', type: 'geo_prize'}); 11276 } 11277 if (meta.id === 'instance') { 11278 columns.push({name: 'title', type: 'geo_login'}); 11279 } 11280 } 11281 return columns; 11282}; 11283 11284$entity.addColumnsTextTranslations = function(translations, columns, meta, model, type) { 11285 if (columns) { 11286 columns.forEach(function (col) { 11287 if (col.type === 'text') { 11288 translations.push({ 11289 name: col.name, 11290 html: col.html, 11291 type: type ? type : 'text', 11292 key: type ? type + '.' + col.name : undefined, 11293 getValue: function() { 11294 return $utils.get(model, type.replaceAll('[', '.').replaceAll(']', '') + '.' + col.name); 11295 } 11296 }); 11297 } else if (col.type === 'inner_entity') { 11298 if (meta && meta.inner_entities) { 11299 var inner = meta.inner_entities.filter(function(it) { 11300 return it.name === col.inner_entity; 11301 })[0] || {}; 11302 $entity.addColumnsTextTranslations(translations, inner.columns, meta, model, (type ? type + '.' : '') + col.name); 11303 } 11304 } else if (col.type === 'inner_entity_list') { 11305 var path = (type ? type + '.' : '') + col.name; 11306 var data = $utils.get(model, path); 11307 if (meta && meta.inner_entities && data && data.length > 0) { 11308 var innerColumns = (meta.inner_entities.filter(function(it) { 11309 return it.name === col.inner_entity; 11310 })[0] || {}).columns; 11311 for (var iter = 0; iter < data.length; iter++) { 11312 $entity.addColumnsTextTranslations(translations, innerColumns, meta, model, path + '[' + iter + ']'); 11313 } 11314 } 11315 } 11316 }); 11317 } 11318} 11319 11320$entity.isItemValid = function(entity, item) { 11321 return !$entity.isGeoSchedule(entity) || $utils.hasValidScheduledDates(item); 11322}; 11323 11324//inner entities 11325$entity.getColumnsInner = function(entity, column) { 11326 var meta = $entity.getEntity(entity); 11327 if (meta == null) { 11328 return []; 11329 } 11330 if (meta.columnsInnerEntity == null) { 11331 meta.columnsInnerEntity = {}; 11332 } 11333 if (meta.columnsInnerEntity[column.name] == null) { 11334 if (meta.inner_entities) { 11335 for (var k in meta.inner_entities) { 11336 var inner = meta.inner_entities[k]; 11337 if (inner.name === column.inner_entity) { 11338 meta.columnsInnerEntity[column.name] = inner.columns; 11339 break; 11340 } 11341 } 11342 } 11343 } 11344 return meta.columnsInnerEntity[column.name]; 11345}; 11346 11347$entity.getColumnData = function(model, column) { 11348 if (model[column.name] == null && column.type === 'inner_entity') { 11349 model[column.name] = {}; 11350 } 11351 return model[column.name]; 11352}; 11353$entity.addColumnItem = function(model, column, withId, data) { 11354 if (!$utils.isArray(model[column])) { 11355 model[column] = []; 11356 } 11357 var item = data ? data : {}; 11358 if (withId && !item.id) { 11359 item.id = '' + Date.now(); 11360 } 11361 model[column].push(item); 11362 return item; 11363}; 11364$entity.removeColumnItem = function(model, column, index) { 11365 if (!$utils.isArray(model[column])) { 11366 model[column] = []; 11367 } else { 11368 model[column].splice(index, 1); 11369 } 11370}; 11371 11372$entity.displayColumnData = function(entity, id, column) { 11373 if (id == null) { 11374 return null; 11375 } 11376 if (typeof id != 'string') { 11377 return $entity.displayColumn(id, column); 11378 } 11379 if (column && column.default) { 11380 var value = $constants.names[id]; 11381 if (value) { 11382 return value; 11383 } 11384 } 11385 //console.log("getting " + entity + " " + id) 11386 var data = $constants.getDataMin(entity, id); 11387 return $entity.displayColumn(data, column); 11388} 11389 11390$entity.displayColumnHtml = function(model, column, fullHtml) { 11391 return $entity.displayColumn(model, column, true, fullHtml); 11392}; 11393 11394$entity.displayColumnTable = function(o) { 11395 if (o == null) { 11396 return null; 11397 } 11398 if (o.entity) { 11399 return $entity.displayColumn(o); 11400 } 11401 if (o.name) { 11402 return $utils.parseGeoTranslation(o.name); 11403 } 11404 return null; 11405}; 11406 11407$entity.displayColumn = function(model, column, isHtml, fullHtml) { 11408 11409 if (model == null) { 11410 return null; 11411 } 11412 if (column == null) { 11413 if (model._meta) { // for trash 11414 column = $entity.getDefaultColumn(model._meta); 11415 } 11416 if (column == null && model.entity && model.entity != 'entity') { 11417 column = $entity.getDefaultColumn(model.entity); 11418 } 11419 if ($constants.isWeb && column != null && $utils.isTrue(column.hidden)) { 11420 return ""; 11421 } 11422 } 11423 if (isHtml == null) isHtml = false;
11424 if (!isHtml || fullHtml == null) fullHtml = false; 11425 11426 var value = $entity._displayColumn(model, column, fullHtml); 11427 11428 if (!fullHtml && (column == null || column.default) && value && model.id) { 11429 $constants.names[model.id] = value; 11430 } 11431 11432 if (typeof value == 'string') { 11433 var colHtml = column && column.html; 11434 if (!colHtml && isHtml) { 11435 value = value.replace(/\n/g, "<br>"); 11436 } else if (colHtml && !isHtml) { 11437 value = $utils.cleanHtml(value); 11438 } 11439// if (!isHtml && value.length > 30) { 11440// value = value.substring(0,29)+"..."; 11441// } 11442 } 11443 11444 return value; 11445}; 11446 11447$entity._displayColumn = function(model, column, isHtml) { 11448 11449 if (column == null) { 11450 if (model.id && $constants.names[model.id]) { 11451 return $constants.names[model.id]; 11452 } 11453 if ($constants.isWeb && model.name_web) { 11454 return $utils.parse(model.name_web); 11455 } 11456 if (model.name) { // for entity and others 11457 return $utils.parse(model.name); 11458 } 11459 return null; 11460 } 11461 11462// if ($constants.isWeb && $utils.isTrue(column.hidden)) { // TODO if is default column is a problem 11463// return ""; 11464// } 11465 11466 if (column.default && model.id && $constants.names[model.id] && !isHtml) { 11467 return $constants.names[model.id]; 11468 } 11469 11470 if (column.name == 'categories' || column.type == 'categories') { 11471 return $constants.getCategoryListDesc(model[column.name]); 11472 } 11473 11474 var type = column.type; 11475 if (type === 'formula' && column.formula_type) { 11476 type = column.formula_type; 11477 } 11478 11479 var o = null; 11480 if (column.name) { 11481 o = model[column.name]; 11482 } 11483 if (o == null) { 11484 if (type === 'boolean' || type === 'boolean_int') { 11485 o = false; 11486 } else { 11487 return ""; 11488 } 11489 } 11490 //console.log(column.name, type, o) 11491 11492 if (type === 'aggregation') { 11493 if ($utils.isArray(o) && o.length > 0) { 11494 11495 var f = column.aggregation_formula ? column.aggregation_formula : column.formula; 11496 if (f == null) { 11497 f = ""; 11498 } 11499 f = f.trim().split("(")[1].split(")")[0]; 11500 var split = f.split(","); 11501 var e = split[0].trim(); 11502 var g = split[1].trim(); 11503 var col = $entity.getColumn(e, g); 11504 var query = null; 11505 if (split.length > 3) { 11506 query = ""; 11507 for (var i=3; i<split.length; i++) { 11508 query += "&" + split[i].trim(); 11509 } 11510 //console.log("query", query) 11511 } 11512 11513 var list = []; 11514 for (var key in o) { 11515 var item = o[key]; 11516 item = $utils.clone(item); 11517 11518 if (item.id == null) { 11519 item.id = "-"; 11520 } else { 11521 if ($utils.isArray(item.id) && item.id.length > 0) { 11522 item.id = item.id[0]; 11523 } 11524 if (col && col.param) { 11525 item.id = $entity.displayColumnData(col.param, item.id); 11526 } else { 11527 //item.id = $utils.toText(item.id); TODO comented to keep original text 11528 } 11529 } 11530 11531 for (var k in item) { 11532 var v = item[k]; 11533 if (v != null && k.contains("_")) { 11534 var cn = k.split("_")[1]; 11535 var co = $entity.getColumn(e, cn); 11536 if (co && (co.type === 'money' || co.formula_type === 'money')) { 11537 item[k] = $utils.printCurrency(v, co.currency); 11538 continue; 11539 } 11540 if (co && (co.type === 'percentage' || co.formula_type === 'percentage')) { 11541 item[k] = $utils.parseNumber(Number(v).toFixed(2)) + '%'; 11542 continue; 11543 } 11544 } 11545 item[k] = $utils.parse(v); 11546 } 11547 list.push(item); 11548 } 11549 11550 // sort by id 11551 list.sort(function(a, b) { 11552 var y = a.id; 11553 var x = b.id; 11554 if (x > y) { 11555 return -1; 11556 } 11557 if (y > x) { 11558 return 1; 11559 } 11560 return 0; 11561 }); 11562 11563 if (isHtml) { 11564 var result = ""; 11565 result += "<ul class='list-group'>"; 11566 11567 for (var key in list) { 11568 var item = list[key]; 11569 var isOneValue = $utils.keys(item).length < 3; 11570 11571 var li = "<div class='row'>"; 11572 for (var k in item) { 11573 var v = item[k]; 11574 if (k == 'id' && v == '-') { 11575 continue; 11576 } 11577 11578 if (isOneValue) { 11579 li += "<div class='col-12'>"; 11580 } else { 11581 li += "<div class='col-sm col-6'>"; 11582 } 11583 11584 if (k == 'id') { 11585 li += "<small>"+v+"</small>"; 11586 } else if (isOneValue) { 11587 li += "<label>"+v+"</label>"; 11588 } else { 11589 li += "<small>"+k+"</small><br><label>"+v+"</label>"; 11590 } 11591 li += "</div>"; 11592 } 11593 li += "</div>"; 11594 11595 if (e && g) { 11596 var link; 11597 if (item.id != '-') { 11598 link = $instance.getBaseUrl() + e + "?" + g + "=" + item.id; 11599 } else { 11600 link = $instance.getBaseUrl() + e + "?" + g + ":$exists=false"; 11601 } 11602 link += $entity.parseQuery(query, model); 11603 //console.log("link", link) 11604 li = "<a href='"+link+"'>" + li + "</a>"; 11605 } 11606 result += "<li class='list-group-item table-relation'>" + li + "</li>"; 11607 } 11608 result += "</ul>"; 11609 return result; 11610 } 11611 11612 var result = []; 11613 for (var key in list) { 11614 var item = list[key]; 11615 11616 var txt = ""; 11617 var isOneValue = $utils.keys(item).length < 3; 11618 for (var k in item) { 11619 var v = item[k]; 11620 if (k == 'id' && v == '-') { 11621 continue; 11622 } 11623 if (txt.length > 0) { 11624 txt += ": "; 11625 } 11626 if (k == 'id' || isOneValue) { 11627 txt += v; 11628 } else { 11629 txt += k+":"+v + " "; 11630 } 11631 } 11632 result.push(txt); 11633 } 11634 return $utils.join(result, ", "); 11635 } 11636 } 11637 11638 if (type === 'datetime') { 11639 return $utils.parseDateTotal(o); 11640 } 11641 if (type === 'date') { 11642 return $utils.parseDay(o); 11643 } 11644 if (type === 'money') { 11645 return $utils.printCurrency(o, column.currency); 11646 } 11647 if (type === 'percentage') { 11648 return $utils.parseNumber(Number(o).toFixed(2)) + '%'; 11649 } 11650 if (type === 'boolean' || type === 'boolean_int') { 11651 if (Array.isArray(o)) { 11652 return o.reduce(function (a, b) { 11653 return a + $utils.printBoolean(b, isHtml); 11654 }, ''); 11655 } 11656 return $utils.printBoolean(o, isHtml); 11657 } 11658 if (type === 'entity') { 11659 var e = column.param; 11660 if (o && o.entity) { 11661 e = o.entity; 11662 } 11663 var entityDesc = $constants.getEntityDesc(e, o); 11664 if (entityDesc && isHtml && !$constants.isWeb && e) { 11665 var url = $angular.rootScope.getItemLink(e, o); 11666 return '<a href="' + url + '">' + entityDesc + '</a>'; 11667 } 11668 return entityDesc; 11669 } 11670 if (type === 'any_entity') { 11671 if ($utils.isArray(o)) { 11672 type = "any_entity_list"; 11673 } else { 11674 if (o.entity && o.entity_id) { 11675 var entityDesc = $constants.getEntityDesc(o.entity, o.entity_id); 11676 if (entityDesc && isHtml && !$constants.isWeb) { 11677 var url = $angular.rootScope.getItemLink(o.entity, o.entity_id); 11678 return '<a href="' + url + '">' + entityDesc + '</a>'; 11679 } 11680 return entityDesc; 11681 } 11682 return null; 11683 } 11684 } 11685 if (type === 'any_entity_list') { 11686 11687 if (isHtml && !$constants.isWeb) { 11688 var ul = "<ul class='list-group'>"; 11689 for (var k in o) { 11690 var item = o[k]; 11691 if ($utils.isArray(item) && item.length > 0) { 11692 item = item[0]; 11693 } 11694 var text = $constants.getEntityDesc(item.entity, item.entity_id); 11695 var url = $angular.rootScope.getItemLink(item.entity, item.entity_id); 11696 ul += "<li class='list-group-item table-relation'>"; 11697 ul += "<a class='row' href='" + url + "'>
11697" + text + "</a></li>"; 11698 } 11699 ul += "</ul>"; 11700 return ul; 11701 //return $utils.parseToHtml(o, column.name); 11702 } 11703 11704 var result = []; 11705 for (var k in o) { 11706 var item = o[k]; 11707 result.push($constants.getEntityDesc(item.entity, item.entity_id)); 11708 } 11709 return $utils.join(result, ", "); 11710 } 11711 if (type === 'list') { 11712 11713 var e = column.param; 11714 if (o && o.entity) { 11715 e = o.entity; 11716 } 11717 11718 if (isHtml && !$constants.isWeb) { 11719 var ul = "<ul class='list-group'>"; 11720 for (var k in o) { 11721 var item = o[k]; 11722 if ($utils.isArray(item) && item.length > 0) { 11723 item = item[0]; 11724 } 11725 var text, url; 11726 if (typeof item == 'string') { 11727 text = $constants.getEntityDesc(e, item); 11728 url = $angular.rootScope.getItemLink(e, item); 11729 } else { 11730 text = $entity.displayColumn(item); 11731 url = $angular.rootScope.getItemLinkBy(item); 11732 } 11733 ul += "<li class='list-group-item table-relation'>"; 11734 ul += "<a class='row' href='" + url + "'>" + text + "</a></li>"; 11735 } 11736 ul += "</ul>"; 11737 return ul; 11738 //return $utils.parseToHtml(o, column.name); 11739 } 11740 11741 var result = []; 11742 for (var k in o) { 11743 var item = o[k]; 11744 if ($utils.isArray(item) && item.length > 0) { 11745 item = item[0]; 11746 } 11747 if (typeof item == 'string') { 11748 result.push($constants.getEntityDesc(e, item)); 11749 } else { 11750 result.push($entity.displayColumn(item)); 11751 } 11752 } 11753 if (result.some(function(val) { 11754 return val === undefined; 11755 })) { 11756 return undefined; 11757 } 11758 return $utils.join(result, ", "); 11759 } 11760 if (type === 'select' || type === 'enum' || type === 'enum_list') { 11761 if (Array.isArray(o)) { 11762 o = o.map(function(item) { 11763 return $utils.parseGeoTranslation(item, null, null, 'geo_translations.' + column.name + '$options'); 11764 }); 11765 } else { 11766 o = $utils.parseGeoTranslation(o, null, null, 'geo_translations.' + column.name + '$options'); 11767 } 11768 } 11769 if (type === 'json') { 11770 try { 11771 o = angular.toJson(angular.fromJson(o), 2); // pretty print 11772 } catch (e) {} 11773 if (isHtml) { 11774 o = '<div class="code-readonly"><pre><code>' + o + '</code></pre></div>'; 11775 } 11776 return o; 11777 } 11778 if (type === 'image' || type === 'audio' || type === 'video' || type === 'document') { 11779 var isMultiple = !!column.multiple; 11780 if (!Array.isArray(o)) { 11781 o = [o]; 11782 } 11783 11784 var mediaTmp = $utils.prepareMediaColumnData(column); 11785 var result = o.map(function(mediaId) { 11786 var text = mediaTmp.getFileName(model, mediaId); 11787 if (isHtml) { 11788 text = '<a target="_blank" href="' + mediaTmp.getLinkUrl(model, mediaId) + '">
11788' + text + '</a>'; 11789 if (isMultiple) { 11790 text = '<li>' + text + '</li>'; 11791 } 11792 } 11793 return text; 11794 }).join(isHtml ? '' : ','); 11795 11796 if (isHtml && isMultiple) { 11797 result = '<ul class="list-unstyled">' + result + '</ul>'; 11798 } 11799 return result; 11800 } 11801 if (type === 'text') { 11802 o = $utils.parse(o); 11803 } 11804 if (isHtml) { 11805 o = $utils.parseToHtml(o); 11806 } 11807 o = $utils.parse(o); 11808 //console.log(column.name + " -> " + o + " - " + (typeof o)) 11809 return o; 11810}; 11811 11812$entity.getColumnByPath = function(entity, innerEntity, path, prePath) { 11813 var meta; 11814 if (innerEntity) { 11815 meta = $entity.getInnerEntity(entity, innerEntity); 11816 } else { 11817 meta = $entity.getEntity(entity); 11818 } 11819 var parts = path; 11820 if (typeof path === 'string') { 11821 parts = path.split('.'); 11822 } 11823 var colName = parts[0]; 11824 var column = meta.columns.find(function(col) { 11825 return col.name === colName; 11826 }); 11827 if (!column) { 11828 return null; 11829 } 11830 var pathToColumn = (prePath ? prePath + "." : "") + colName; 11831 parts.splice(0, 1); 11832 if (parts.length === 0) { 11833 return { 11834 entity: entity, 11835 innerEntity: innerEntity, 11836 column: column, 11837 pathToColumn: pathToColumn 11838 }; 11839 } 11840 var type = column.type; 11841 if ((type === 'entity' || type === 'list' || type === 'relation_entity' || type === 'relation') && column.param) { 11842 return $entity.getColumnByPath(column.param, null, parts); 11843 } 11844 if ((type === 'inner_entity' || type === 'inner_entity_list') && column.inner_entity) { 11845 return $entity.getColumnByPath(entity, column.inner_entity, parts, pathToColumn); 11846 } 11847 if (type === 'formula') { 11848 var formula = column.formula; 11849 if (formula != null && formula.trim().startsWith("relation")) { 11850 var relationEntity = formula.substring(formula.indexOf("(")+1); 11851 relationEntity = relationEntity.substring(0, relationEntity.indexOf(",")).trim(); 11852 return $entity.getColumnByPath(relationEntity, null, parts); 11853 } 11854 } 11855 return null; 11856}; 11857 11858$entity.hasColumn = function(entity, path) { 11859 return $entity.getColumn(entity, path) != null; 11860}; 11861 11862$entity.getColumn = function(entity, path) { 11863 var meta = $entity.getEntity(entity); 11864 if (meta == null) { 11865 return null; 11866 } 11867 11868 // check if is formview 11869 var form = $angular.searchFormView(); 11870 if (form && form.form) { 11871 form = form.form; 11872 } 11873 if (form && form.id) { 11874 if (form.root_entity != entity) { 11875 console.log('Differents formview entity: ' + entity + " vs " + form.root_entity);//, meta, form); 11876 } else { 11877 // search in formview columns 11878 if (meta._formsMap == null) { 11879 meta._formsMap = {}; 11880 } 11881 if (meta._formsMap[form.id] == null) { 11882 meta._formsMap[form.id] = {}; 11883 $entity.loadColumnsMap(entity, form.columns, meta._formsMap[form.id]); 11884 } 11885 var c = meta._formsMap[form.id][path]; 11886 if (c != null) { 11887 return c; 11888 } 11889 } 11890 } 11891 11892 // search in entity columns 11893 if (meta._columnsMap == null) { 11894 meta._columnsMap = {}; 11895 $entity.loadColumnsMap(entity, meta.columns, meta._columnsMap); 11896 } 11897 var column = meta._columnsMap[path]; 11898 if (column) { 11899 return column; 11900 } 11901 11902 if (path == "*" || path == "_id") { 11903 return meta.columns[0]; 11904 } 11905 if (path.startsWith("_") || path.startsWith("geo_")) { 11906 // no warn 11907 } else { 11908// $angular.log('Column not found: ' + entity + "#" + path, meta, form); 11909 console.log('Column not found: ' + entity + "#" + path, meta, form); 11910 } 11911 return null; 11912}; 11913 11914$entity.loadColumnsMap = function(entity, columns, columnsMap, path) { 11915 if (columns) { 11916 if (path == null) { 11917 path = ""; 11918 } 11919 for (var k in columns) { 11920 11921 var column = columns[k]; 11922 var cpath = column.path; 11923 if (column.type == null && cpath != null) { 11924 // search column in entity 11925 column = $entity.getColumn(entity, cpath); 11926 } 11927 if (column == null || column.type == null) { 11928 continue; 11929 } 11930 11931 var name = column.name; 11932 if (column.type == 'group') { 11933 var cols = column.columns; 11934 $entity.loadColumnsMap(entity, cols, columnsMap, path); 11935 11936// } else if (column.type == 'relation' || column.type == 'relation_entity') { 11937// var ent = column.param; 11938// var cols = column.columns; 11939// 11940 } else if (column.type == 'inner_entity' || column.type == 'inner_entity_list') { 11941 var cols = $entity.getInnerEntityColumns(entity, column); 11942 $entity.loadColumnsMap(entity, cols, columnsMap, path + name + "."); 11943 11944 } else { 11945 11946 // save column in map 11947 if (cpath != null) { 11948 columnsMap[cpath] = column; 11949 } else if (name != null) { 11950 columnsMap[path + name] = column; 11951 } 11952 } 11953 } 11954 } 11955}; 11956 11957$entity.getColumnType = function(col) { 11958 if (col.type == 'formula' && col.formula_type) { 11959 return col.formula_type; 11960 } 11961 return col.type; 11962}; 11963 11964$entity.getDefaultColumnName = function(entity) { 11965 var col = $entity.getDefaultColumn(entity); 11966 if (col == null) { 11967 return 'name'; 11968 } 11969 return col.name; 11970}; 11971$entity.getDefaultColumn = function(entity) { 11972 var meta = $entity.getEntity(entity); 11973 if (meta) { 11974 if (meta._col_name == null) { 11975 var cols = $entity.getColumnsBy(meta, 'default'); 11976 if (cols.length == 0) { 11977 $angular.log("No default column configured in '" + meta.id + "'"); 11978 return null; 11979 } 11980 meta._col_name = cols[0]; 11981 } 11982 return meta._col_name; 11983 } 11984 return null; 11985}; 11986$entity.getDefaultSort = function(entity) { 11987 var meta = $entity.getEntity(entity); 11988 if (meta) { 11989 return meta.order; 11990 } 11991 return null; 11992}; 11993$entity.getTabColumns = function(entity) { 11994 return $entity.getColumnsBy(entity, 'tab'); 11995}; 11996$entity.getSearchColumns = function(entity) { 11997 return $entity.getColumnsBy(entity, 'search'); 11998}; 11999$entity.getDisplayColumns = function(entity) { 12000 return $entity.getColumnsBy(entity, 'display'); 12001}; 12002 12003$entity.getColumnsBy = function(entity, check) { 12004 var meta = $entity.getEntity(entity); 12005 if (meta == null || meta.columns == null) { 12006 return []; 12007 } 12008 if (meta.checkColumns == null) { 12009 meta.checkColumns = {}; 12010 } 12011 var entityCheck = meta.id + "#" + check; 12012 if (meta.checkColumns[entityCheck] == null) { 12013 var list = []; 12014 for (var key in meta.columns) { 12015 var column = meta.columns[key]; 12016 if ($utils.isTrue(column[check])) { 12017 if (check == 'display' && $constants.isWeb && $utils.isTrue(column.hidden)) { 12018 // no display 12019 } else { 12020 list.push(column); 12021 } 12022 } 12023 if (column.isEntity == null) { // used for search columns 12024 column.isEntity = (column.type === 'entity' || column.type === 'list'); 12025 } 12026 } 12027 meta.checkColumns[entityCheck] = list; 12028 } 12029 return meta.checkColumns[entityCheck]; 12030}; 12031 12032$entity.getTableColumns = function(entity, col) { 12033 if (col && !col.long) { 12034 // return default 12035 var def = $entity.getDefaultColumn(entity); 12036 if (def) { 12037 return [ def ]; 12038 } 12039 return []; 12040 } 12041 var meta = $entity.getEntity(entity); 12042 if (meta == null || meta.columns == null) { 12043 return []; 12044 } 12045 if (meta.checkColumns == null) { 12046 meta.checkColumns = {}; 12047 } 12048 var entityCheck = entity + "#table"; 12049 if (meta.checkColumns[entityCheck] == null) { 12050 var list = $entity.getDisplayColumns(entity).slice(); // clone list 12051 var def = $entity.getDefaultColumn(entity); 12052 //if (def && !list.includes(def)) { -> sometimes no work 12053 if (def != null) { 12054 var found = false;
12055 for (var i in list) { 12056 var item = list[i]; 12057 if (def.name == item.name) { 12058 found = true; 12059 break; 12060 } 12061 } 12062 if (!found) { 12063 list.unshift(def); 12064 } 12065 } 12066 meta.checkColumns[entityCheck] = list; 12067 } 12068 return meta.checkColumns[entityCheck]; 12069}; 12070 12071$entity.metas = {}; 12072$entity.getEntityForce = function(entity, callback) { 12073 var o = $entity.getEntity(entity, true); 12074 if (o) { 12075 o = $utils.clone(o); 12076 callback(o); 12077 return; 12078 } 12079 //console.log('getting entity ' + entity); 12080 var url; 12081 if (!$constants.isWeb) { 12082 url = contextPath + '/api/geo/entity/' + entity + '.json'; 12083 } else { 12084 url = contextPath + '/www/geo/entity/' + entity + '.json'; 12085 } 12086 if ($instance.current) { 12087 url += '?geo_instance='+$instance.getId(); 12088 } 12089 $rest.get({ 12090 url: url, 12091 force: true, 12092 showError: false 12093 }).then(function(o) { 12094 //console.log('got entity ' + entity, o); 12095 $entity.metas[entity] = o; 12096 o = $utils.clone(o); 12097 callback(o); 12098 }); 12099}; 12100 12101$entity.getEntity = function(entity, nowarn) { 12102 if ($utils.isBlank(entity)) { 12103 //console.log('entity empty'); 12104 return null; 12105 } 12106 if (typeof entity != 'string') { 12107 return entity; 12108 } 12109 if (entity == 'trash') { 12110 return { id: entity, name:entity, columns:[{name:'name', default:true}] }; 12111 } 12112 12113 // check current scope to get fresh data 12114 if ($angular.contentScope) { 12115 var o = $angular.contentScope.meta; 12116 if (o == null && $angular.contentScope.model) { 12117 o = $angular.contentScope.model.meta; 12118 } 12119 if (o && (o.id == entity)) { 12120 if (o.id == entity) { 12121 $entity.metas[entity] = o; 12122 } 12123 return o; 12124 } 12125 } 12126 12127 if (!$instance.hasToRefresh) { 12128 // check instance entities 12129 var o = $instance.getEntity(entity); 12130 if (o) { 12131 $entity.metas[entity] = o; 12132 return o; 12133 } 12134 } 12135 12136 // check in local cache 12137 if ($entity.metas[entity]) { 12138 return $entity.metas[entity]; 12139 } 12140 12141 if (nowarn != true) { 12142 var sc = $angular.contentScope; 12143 if (sc) { 12144 if (sc.__entities == null) { 12145 sc.__entities = {}; 12146 } 12147 var now = Date.now(); 12148 var last = sc.__entities[entity]; 12149 if (last && (now - last) < 1000) { 12150 return null; // only warn one time 12151 } 12152 sc.__entities[entity] = now; 12153 } 12154 //console.log('load entity ' + entity); 12155 $entity.getEntityForce(entity, function(){}); // force load entity 12156 } 12157 return null; 12158}; 12159 12160$entity.getInnerEntity = function(entityId, innerEntityId) { 12161 var entity = $entity.getEntity(entityId); 12162 if (entity) { 12163 if ($utils.isObject(innerEntityId) && innerEntityId.name) { 12164 innerEntityId = innerEntityId.name; 12165 } 12166 var map = entity.inner_entities_map; 12167 if (map == null) { 12168 entity.inner_entities_map = {}; 12169 } 12170 var ie = entity.inner_entities_map[innerEntityId]; 12171 if (ie == null && entity.inner_entities) { 12172 ie = entity.inner_entities.filter(function(innerEntity) { 12173 return innerEntityId === innerEntity.name; 12174 })[0] || null; 12175 entity.inner_entities_map[innerEntityId] = ie; 12176 } 12177 return ie; 12178 } 12179 return null; 12180}; 12181 12182$entity.getInnerEntityColumns = function(entityId, column) { 12183 if (column.columns && column.columns.length > 0) { 12184 return column.columns; 12185 } 12186 var innerEntityId = column.inner_entity; 12187 var innerEntity = $entity.getInnerEntity(entityId, innerEntityId); 12188 return innerEntity ? innerEntity.columns : []; 12189}; 12190 12191$entity.getTableList = function(o, field, column) { 12192 12193 if (column.type == 'entity') { 12194 12195 // parse column.query 12196 var query = $entity.parseQuery(column.query, $angular.contentScope.model); 12197 //console.log(column.param + " - " + query) 12198 12199 $constants.getDataListMin(column.param, query, 0, 250).then(function(list){ 12200 o[field] = list; 12201 }); 12202 return; 12203 } 12204 12205 var name = ""; 12206 if (column.type == 'message') { 12207 name = $utils.parseGeoTranslation(column.name); 12208 } 12209 o[field] = [{ 12210 name:name 12211 }]; 12212}; 12213 12214$entity.initTable = function(column) { 12215 //console.log('init table', column) 12216 delete column.columnX; 12217 delete column.columnY; 12218 delete column.columnsValue; 12219 delete column.tableListX; 12220 delete column.tableListY; 12221 12222 var columns = column.columns; 12223 if (columns && columns.length > 2) { 12224 12225 column.columnX = columns[0]; 12226 $entity.getTableList(column, 'tableListX', column.columnX); 12227 12228 column.columnY = columns[1]; 12229 $entity.getTableList(column, 'tableListY', column.columnY); 12230 12231 var cols = []; 12232 for (var i=2; i<columns.length; i++) { 12233 cols.push(columns[i]); 12234 } 12235 column.columnsValue = cols; 12236 } 12237 12238}; 12239 12240$entity.cleanTable = function(column, model) { 12241 if (model == null || column == null || column.tableListX == null || column.tableListY == null) { 12242 return; 12243 } 12244 var doc = model[column.name]; 12245 if (doc == null) { 12246 return; 12247 } 12248 12249 var idsx = []; 12250 for (var x in column.tableListX) { 12251 var itemx = column.tableListX[x]; 12252 if (itemx.id) { 12253 idsx.push(itemx.id); 12254 } else { 12255 idsx.push("undefined"); 12256 } 12257 } 12258 //console.log(idsx) 12259 12260 var idsy = []; 12261 for (var y in column.tableListY) { 12262 var itemy = column.tableListY[y]; 12263 idsy.push(itemy.id); 12264 } 12265 //console.log(idsy) 12266 12267 for (var x in doc) { 12268 if (x != null && !idsx.includes(x)) { 12269 delete doc[x]; 12270 continue; 12271 } 12272 var item = doc[x]; 12273 for (var y in item) { 12274 if (!idsy.includes(y)) { 12275 delete item[y]; 12276 } 12277 } 12278 } 12279 12280 // fill new values 12281 for (var k in column.tableListX) { 12282 var v1 = column.tableListX[k].id; 12283 if (doc[v1] == null) { 12284 doc[v1] = {}; 12285 //console.log('new v1: ' + v1) 12286 } 12287 for (var k2 in column.tableListY) { 12288 var v2 = column.tableListY[k2].id; 12289 if (doc[v1][v2] == null) { 12290 doc[v1][v2] = {}; 12291 //console.log('new v2: ' + v1 + " - " + v2) 12292 } 12293 } 12294 } 12295}; 12296 12297$entity.isPermitted = function(entityId, permission) { 12298 var entity = $entity.getEntity(entityId); 12299 return entity && entity.security && $utils.isTrue(entity.security[permission]); 12300}; 12301 12302$entity.registerCustomEntity = function(entityId, entity) { 12303 $entity.metas[entityId] = entity; 12304}; 12305 12306$entity.parseQuery = function(link, model) { 12307 if (link == null) { 12308 link = ""; 12309 } 12310 if (model == null) { 12311 model = {}; 12312 } 12313 while (link.contains('{')) { 12314 var orig = link; 12315 var index = link.indexOf('{'); 12316 var prefix = link.substring(0, index); 12317 link = link.substring(index + 1); 12318 if (!link.contains('}')) { 12319 break; 12320 } 12321 index = link.indexOf('}'); 12322 var col = link.substring(0, index).trim(); 12323 var suffix = link.substring(index + 1); 12324 var value = model[col]; 12325 if (value == null) { 12326 if (col == '_id') { 12327 value = model['id']; 12328 } else if (col == '$instance') { 12329 value = $instance.getId(); 12330 } 12331 if (value == null) { 12332 // search in root 12333 var root = $angular.searchRootModel(); 12334 if (root) { 12335 value = root[col]; 12336 } 12337 } 12338 } 12339 if (value == null) { 12340 value = "";
12341 console.log("var not found " + col + " from " + orig) 12342 } 12343 //console.log(col + "=" + value) 12344 link = prefix + value + suffix; 12345 if (orig === link) { 12346 break; 12347 } 12348 } 12349 return link; 12350}; 12351 12352 12353//// File web-agenda.js //// 12354 12355(function() { 12356 12357 var $agenda = {}; 12358 $agenda.selected = null; 12359 12360 $angular.controllers['web-agenda'] = function($rootScope, $scope, $routeParams, $translate, $uibModal, $window, $document, $location, $timeout) { 12361 $angular.preparePage({ buttonsRight:"web-agenda-buttons.html" }); 12362 $angular.contentScope = $scope; 12363 12364 $scope.title = ""; 12365 $scope.setTitle = function() { 12366 $scope.title = $instance.getGeoSmarterText("title_result", "msg.web.agenda"); 12367 }; 12368 $scope.setTitle(); 12369 12370 var data = $sessionService.get("agenda_"+$instance.getId()); 12371 if (data == null || $utils.isBlank(data)) { 12372 $scope.days = []; 12373 } else { 12374 $scope.days = JSON.parse(data); 12375 } 12376 //console.dir($scope.days) 12377 $scope.model = {}; 12378 12379 $scope.activeDay = 0; 12380 if ($agenda.selected != null) { 12381 for (var i=0; i<$scope.days.length; i++) { 12382 var day = $scope.days[i]; 12383 if (day.date == $agenda.selected.date) { 12384 $scope.activeDay = i; 12385 } 12386 } 12387 } 12388 //console.log($scope.activeDay) 12389 12390 $scope.selectDay = function(index) { 12391 $scope.activeDay = index; 12392 $scope.model = $scope.days[index]; 12393 if ($scope.showMap) { 12394 $angular.apply($scope, function() { 12395 initGeoIndexMap(); 12396 }); 12397 } 12398 }; 12399 $scope.selectDay($scope.activeDay); 12400 12401 12402 // map 12403 $scope.showMap = false; 12404 if ($utils.isTrue($routeParams.__map)) { 12405 $scope.showMap = true; 12406 $angular.apply($scope, function() { 12407 initGeoIndexMap(); 12408 }); 12409 } 12410 $scope.showOrHideMap = function() { 12411 $scope.showMap = !$scope.showMap; 12412 12413 if ($scope.showMap) { 12414 $location.search({'__map':"true"}).replace(); 12415 } else { 12416 $location.search({}).replace(); 12417 } 12418 12419 if ($scope.showMap) { 12420 $angular.apply($scope, function() { 12421 initGeoIndexMap(); 12422 }); 12423 } 12424 }; 12425 12426 var map; 12427 var infoWindow; 12428 var markers = {}; 12429 var _tmp = 0; 12430 function initGeoIndexMap() { 12431 12432 window.scrollTo(0, 0); 12433 12434 markers = {}; 12435 _tmp = 0; 12436 infoWindow = new google.maps.InfoWindow({ maxWidth: 230, maxHeight: 230 }); 12437 12438 var mapOptions = { 12439 mapId : "GEO_AGENDA", 12440 streetViewControl : false, panControl : false, 12441 mapTypeId : google.maps.MapTypeId.ROADMAP, 12442 disableDefaultUI: false, zoomControl: true 12443 }; 12444 12445 var gf = $instance.getGeoFence(); 12446 if (gf && gf.center_latitude) { 12447 var lat = Number(gf.center_latitude); 12448 var lng = Number(gf.center_longitude); 12449 var pos = new google.maps.LatLng(lat, lng); 12450 var zoom = 12; 12451 if (gf.default_zoom) { 12452 zoom = Number(gf.default_zoom); 12453 } 12454 mapOptions.center = pos; 12455 mapOptions.zoom = zoom; 12456 } else { 12457 mapOptions.center = new google.maps.LatLng(0, 0); 12458 mapOptions.zoom = 3; 12459 } 12460 map = new google.maps.Map(document.getElementById('web-agenda-map'), mapOptions); 12461 google.maps.event.addListener(map, 'zoom_changed', function() { 12462 if (this.getZoom() > 17.5 && this.initialZoom == true) { 12463 this.setZoom(17.5); 12464 this.initialZoom = false;
12465 } 12466 }); 12467 12468 var bounds = new google.maps.LatLngBounds(null); 12469 var num = 0; 12470 for (var id in markers) { 12471 var m = markers[id]; 12472 m.setMap(null); 12473 } 12474 markers = {}; 12475 12476 for (var k in $scope.model.list) { 12477 var item = $scope.model.list[k]; 12478 console.dir(item) 12479 if (markers[item.object.id]) { 12480 continue; // exists 12481 } 12482 // add new 12483 if (item.latitude == null || item.longitude == null) { 12484 continue; 12485 } 12486 var pos = new google.maps.LatLng(item.latitude, item.longitude); 12487 var marker = new google.maps.Marker({ 12488 position : pos, 12489 map : map, clickable : true 12490 }); 12491 markers[item.object.id] = marker; 12492 12493 google.maps.event.addListener(marker, 'click', (function(plc, mark) { return function() { 12494 var href = $rootScope.getItemLinkBy(plc.object); 12495 var content = "<div class='infowindow'><a href='"+ href +"' class='bold'>" + $entity.displayColumn(plc.object) + "</a><br>"; 12496 content += "<label style='margin-top:5px; font-size: 14px;'>" + $utils.parse(plc.address + "</label></div>"); 12497 infoWindow.setContent(content); 12498 infoWindow.open(map, mark); 12499 }; })(item, marker)); 12500 12501 bounds.extend(pos); 12502 num++; 12503 } 12504 12505 if (num > 0 && map) { 12506 map.initialZoom = true; 12507 map.fitBounds(bounds); 12508 } 12509 } 12510 12511 } 12512 12513})(); 12514 12515//// File web-booking.js //// 12516(function() { 12517 12518 $angular.controllers['web-booking'] = function($rootScope, $scope, $routeParams, $translate) { 12519 $angular.preparePage({buttonsRight: "web-booking-buttons.html"}); 12520 $angular.contentScope = $scope; 12521 12522 $scope.title = ""; 12523 $scope.setTitle = function() { 12524 $scope.title = $translate.instant('msg.booking') + ' ' + $scope.model.id; 12525 }; 12526 12527 function loadBooking() { 12528 $rest.get({ 12529 skipHideLoading: true, 12530 loading: "generic", 12531 url: contextPath + "/www/booking/" + $routeParams.id + ".json" 12532 }).then(function(o) { 12533 $scope.model = o; 12534 $scope.setTitle(); 12535 $rest.get({ 12536 skipHideLoading: true, 12537 loading: "generic", 12538 url: contextPath + "/www/booking/a/columns.json?entity=" + o.object.entity + "&entityId=" + o.object.entity_id 12539 }).then(function(bookingEntity) { 12540 $scope.extraDataEntity = bookingEntity; 12541 12542 $angular.apply($scope, function() { 12543 $angular.ready = true; 12544 }); 12545 }); 12546 }); 12547 } 12548 12549 loadBooking(); 12550 12551 $scope.cancelBooking = function() { 12552 $rest.remove({ 12553 url: contextPath + "/www/booking/" + $scope.model.id + ".json", 12554 confirmTitle: 'msg.booking.cancel.confirm.title', 12555 confirmText: 'msg.booking.cancel.confirm.text', 12556 loading: "generic" 12557 }).then(loadBooking); 12558 }; 12559 12560 $scope.buildAddToGoogleCalendarLink = function() { 12561 var booking = $scope.model; 12562 var day = booking.day.replaceAll('-', ''); 12563 var timeFrom = booking.time.replace(':', ''); 12564 var timeTo = booking.end_time ? booking.end_time.replace(':', '') : ''; 12565 return 'https://www.google.com/calendar/render' + 12566 '?action=TEMPLATE' + 12567 '&text=' + encodeURIComponent($constants.getEntityDesc(booking.object.entity, booking.object.entity_id)) + 12568 '&dates=' + day + 'T' + timeFrom + '00/' + day + 'T' + timeTo + '00'; 12569 }; 12570 12571 $scope.buildAddToOutlookCalendarLink = function() { 12572 var booking = $scope.model; 12573 return 'https://outlook.live.com/calendar/0/deeplink/compose' + 12574 '?path=/calendar/action/compose' + 12575 '&rru=addevent' + 12576 '&startdt=' + booking.day + 'T' + booking.time + ':00' + 12577 (booking.end_time ? '&enddt=' + booking.day + 'T' + booking.end_time + ':00' : '') + 12578 '&subject=' + encodeURIComponent($constants.getEntityDesc(booking.object.entity, booking.object.entity_id)); 12579 }; 12580 } 12581})(); 12582 12583//// File web-cart.js //// 12584(function() { 12585 12586 $angular.controllers['web-cart'] = function($rootScope, $scope, $routeParams, $translate, $location, $timeout) { 12587 $angular.preparePage({buttonsRight: "web-cart-buttons.html"}); 12588 $angular.contentScope = $scope; 12589 12590 $scope.showNext = false; 12591 $scope.title = ""; 12592 12593 $scope.setTitle = function() { 12594 if ($scope.step === 1) { 12595 $scope.title = $translate.instant("msg.web.cart"); 12596 } else if ($scope.step === 2) { 12597 $scope.title = $translate.instant("msg.buyer"); 12598 } else if ($scope.step === 3) { 12599 $scope.title = $translate.instant("msg.delivery"); 12600 } else if ($scope.step === 4) { 12601 $scope.title = $translate.instant("msg.identity"); 12602 } else if ($scope.step === 5) { 12603 $scope.title = $translate.instant("msg.pay.mode"); 12604 } 12605 }; 12606 12607 if ($angular.currencies && $instance.current && $instance.current.geo_buy) { 12608 $scope.currencyConfig = $angular.currencies[$instance.current.geo_buy.currency]; 12609 } 12610 12611 $scope.checkout = function() { 12612 if ($scope.validateCheckout) { 12613 $scope.validateCheckout(); 12614 } else { 12615 goToStep($scope.step + 1); 12616 } 12617 }; 12618 $scope.back = function() { 12619 goToStep($scope.step - 1, true); 12620 }; 12621 12622 function goToStep(step, goBack) { 12623 //console.log('going to step ' + step) 12624 12625 $scope.isDirectPay = false;
12626 if ($rootScope.cart == null || $rootScope.cart.items == null || $rootScope.cart.items.length == 0) { 12627 step = 1; 12628 } else { 12629 var extra = $rootScope.cart.items[0].extra_data; 12630 $scope.isDirectPay = extra != null && extra.directPay == true; 12631 if ($scope.isDirectPay && step < 2) { 12632 step = 2; 12633 } 12634 } 12635 12636 if (step === 5) { 12637 // force start again 12638 $scope.payment_id = null; 12639 } 12640 12641 if (step === 6) { 12642 // start payment if needed 12643 if ($scope.payment_id == null) { 12644 12645 $scope.startPayment(); 12646 return; 12647 } 12648 goToStep(7); 12649 return; 12650 } 12651 12652 if (step === 7) { 12653 // end 12654 console.log('cart', $rootScope.cart); 12655 12656 if ($scope.payment_id == null) { 12657 if ($rootScope.cart && $rootScope.cart.payment) { 12658 $scope.payment_id = $rootScope.cart.payment; 12659 } 12660 } 12661 if ($scope.payment_id != null) { 12662 finishPayment(); 12663 return; 12664 } 12665 goToStep(5); 12666 return; 12667 } 12668 12669 isValidStep(step, function(ok) { 12670 //console.log('step is valid: ' + ok) 12671 if (ok || step === 5) { 12672 // step is valid: show it 12673 $scope.step = step; 12674 $scope.setTitle(); 12675 prepareStep(); 12676 return; 12677 } 12678 12679 // try next 12680 var tryStep = goBack ? (step - 1) : (step + 1); 12681 goToStep(tryStep, goBack); 12682 }); 12683 } 12684 12685 $scope.choosePaymentMethod = function(methodName) { 12686 $scope.selectedPaymentMethod = methodName; 12687 if (methodName === 'braintree' || methodName === 'ath_movil_business' || methodName === 'paypal' || methodName === 'ath_movil_business') { 12688 $scope.choosePayment = false; 12689 $scope.startPayment(); 12690 return; 12691 } 12692 $scope.showNext = true; 12693 }; 12694 12695 $scope.startPayment = function() { 12696 var methodName = $scope.selectedPaymentMethod; 12697 12698 if (methodName === 'braintree') { 12699 prepareExternalPayment('https://js.braintreegateway.com/web/dropin/1.22.1/js/dropin.min.js', prepareBraintreePayment); 12700 12701 } else if (methodName === 'stripe') { 12702 prepareExternalPayment('https://js.stripe.com/v3/', prepareStripePayment); 12703 12704 } else if (methodName === 'paypal') { 12705 prepareExternalPayment(function(data) { 12706 return 'https://www.paypal.com/sdk/js?client-id=' + data.client_id; 12707 }, preparePaypalPayment); 12708 12709 } else if (methodName === 'ath_movil_business') { 12710 prepareExternalPayment('https://www.athmovil.com/api/js/v3/athmovilV3.js', prepareAthMovilBusinessPayment, true); 12711 12712 } else if (methodName === 'cybersource' || methodName === 'authorize_net' || methodName === 'pharos') { 12713 prepareExternalPayment(null, prepareRedirectPayment); 12714 12715 } else if (methodName === 'fake_payment') { 12716 prepareExternalPayment(null, prepareFakePayment); 12717 12718 } else { 12719 console.log('Unknown payment method: ' + methodName); 12720 goToStep(5); 12721 } 12722 }; 12723 12724 $scope.chooseDeliveryMethod = function(method, force) { 12725 var deliveryMethodChanged = !$cart.isDeliveryMethodType(method ? method.name : null); 12726 if (force || deliveryMethodChanged) { 12727 $scope.validateCheckout = null; 12728 if (method) { 12729 if (deliveryMethodChanged) { 12730 $cart.setDeliveryMethod({ 12731 type: method.name, 12732 price: $scope.getDeliveryMethodPrice(method) 12733 }); 12734 } 12735 if (method.entity) { 12736 if (method.entityId) { 12737 prepareDeliveryMethodBooking(method); 12738 } else { 12739 prepareDeliveryMethodForm(method); 12740 } 12741 } else { 12742 $scope.showNext = true; 12743 } 12744 } else { 12745 $cart.setDeliveryMethod(null); 12746 $scope.showNext = false; 12747 } 12748 } 12749 } 12750 12751 $scope.getDeliveryMethodPrice = function(method) { 12752 return method.price && !isNaN(method.price) ? Number(method.price) : null; 12753 }; 12754 12755 function prepareExternalPayment(scriptUrl, callback, loadScriptAfterCallback) { 12756 $cart.pay({ 12757 payment_method: $scope.selectedPaymentMethod, 12758 location: $location.absUrl() 12759 }).then(function(o) { 12760 var methodName = $scope.selectedPaymentMethod; 12761 var script = $cart.externalPaymentScripts[methodName]; 12762 var paymentMethodData = o.data; 12763 $scope.payment_id = o.payment_id; 12764 var runCallback = true; 12765 if (loadScriptAfterCallback) { 12766 callback(paymentMethodData, null); 12767 runCallback = false;
12768 } 12769 if (scriptUrl != null && script == null) { 12770 if (typeof scriptUrl === 'function') { 12771 scriptUrl = scriptUrl(paymentMethodData); 12772 } 12773 require([scriptUrl], function(dropin) { 12774 $cart.externalPaymentScripts[methodName] = dropin; 12775 $utils.hideLoading(); 12776 if (runCallback) { 12777 callback(paymentMethodData, dropin); 12778 } 12779 }); 12780 } else { 12781 $utils.hideLoading(); 12782 if (runCallback) { 12783 callback(paymentMethodData, script); 12784 } 12785 } 12786 }); 12787 } 12788 12789 var payInstance; 12790 function prepareBraintreePayment(data, braintree) { 12791 braintree.create({ 12792 authorization: data.client_token, 12793 container: '#external-payment-container' 12794 }, function(createErr, instance) { 12795 payInstance = instance; 12796 if (payInstance == null) { 12797 $utils.floatingError($translate.instant("msg.error")); 12798 return; 12799 } 12800 $scope.showValidateBtn = true; 12801 $angular.apply($scope); 12802 }); 12803 } 12804 12805 function prepareStripePayment(data) { 12806 var stripe = Stripe(data.publishable_key); 12807 stripe.redirectToCheckout({ 12808 sessionId: data.session_id 12809 }); 12810 showLoading(); 12811 } 12812 12813 function preparePaypalPayment(data) { 12814 paypal.Buttons({ 12815 createOrder: function() { 12816 return Promise.resolve(data.order_id); 12817 }, 12818 onApprove: function() { 12819 $scope.checkout(); 12820 } 12821 }).render('#external-payment-container'); 12822 } 12823 12824 function prepareAthMovilBusinessPayment(data) { 12825 var $external = $('#external-payment-container'); 12826 $external.empty(); 12827 $external.append('<div style="width: 100px;"><div id="ATHMovil_Checkout_Button"></div></div>'); 12828 window.ATHM_Checkout = { 12829 env: data.environment, 12830 publicToken: data.public_key, 12831 theme: 'btn', 12832 lang: $locale.language, 12833 total: $cart.getTotalAmount(), 12834 onCompletedPayment: function(response) { 12835 if (response.status === 'completed') { 12836 $scope.externalPaymentData.athMovilBusinessReferenceNumber = response.referenceNumber; 12837 $scope.checkout(); 12838 } 12839 }, 12840 onCancelledPayment: function() { 12841 $location.reload(); 12842 }, 12843 onExpiredPayment: function() { 12844 $location.reload(); 12845 } 12846 } 12847 } 12848 12849 function prepareFakePayment(data) { 12850 $scope.checkout(); 12851 } 12852 12853 function prepareRedirectPayment(data) { 12854 12855 // test cybersource 12856// var url = contextPath + "/ms/a/paid.go"; 12857// $rest.post({ 12858// loading: "generic", 12859// url: url, 12860// data: { 12861// req_reference_number:data.reference_number, 12862// transaction_id: '12345678', reason_code:'100' 12863// } 12864// }).then(function() { 12865// window.location.href = url; 12866// }).catch(function(e) { 12867// console.log('error', e) 12868// goToStep(5); 12869// }); 12870 12871 var url = data.redirect_url; 12872 delete data.redirect_url; 12873 var form = '<form method="post" action="' + url + '" class="hidden">'; 12874 for (var k in data) { 12875 form += '\n<input name="' + k + '" value="' + data[k] + '" />'; 12876 } 12877 form += '\n</form>'; 12878 //console.log(form) 12879 submitPaymentForm(form); 12880 } 12881 12882 function submitPaymentForm(form) { 12883 var $form = $(form); 12884 var $external = $('#external-payment-container'); 12885 $external.empty(); 12886 $external.append($form); 12887 $form.submit(); 12888 showLoading(); 12889 } 12890 12891 function showLoading() { 12892 $scope.payment_id = null; // important to wait for payment 12893 $utils.showLoading(); 12894 setTimeout(function() { 12895 $utils.hideLoading(); 12896 }, 3000); 12897 } 12898 12899// function showPaymentButton(onClick) { 12900// var $external = $('#external-payment-container'); 12901// $external.empty(); 12902// var $button = $('<button class="btn btn-primary">' + $translate.instant('msg.goToPay') + '</button>'); 12903// $external.append($button); 12904// $button.click(onClick); 12905// } 12906 12907 $scope.validateCard = function() { 12908 if ($scope.selectedPaymentMethod === 'braintree') { 12909 payInstance.requestPaymentMethod(function(err, p) { 12910 if (p == null) { 12911 $utils.floatingError($translate.instant("msg.error")); 12912 return; 12913 } 12914 $scope.externalPaymentData.braintreeNonce = p.nonce; 12915 $scope.showValidateBtn = false; 12916 $scope.showNext = true; 12917 $angular.apply($scope); 12918 }); 12919 return; 12920 } 12921 $scope.showValidateBtn = false;
12922 $scope.showNext = true; 12923 $angular.apply($scope); 12924 }; 12925 12926 function finishPayment() { 12927 $cart.complete({ 12928 payment_id: $scope.payment_id, 12929 data: $scope.externalPaymentData 12930 }).then(function(order) { 12931 if (order == null) { 12932 $angular.log('Payment 4 failed'); 12933 $utils.showAlert($translate.instant("msg.payment.failed")); 12934 return; 12935 } 12936 $angular.log('Payment 4 done'); 12937 $location.path($instance.getBaseUrl() + 'order/' + order.id).search({isNew: true, code: order.code}); 12938 }); 12939 } 12940 12941 $scope.availableDeliveryMethods = []; 12942 if ($instance.current && $instance.current.geo_buy && $instance.current.geo_buy.delivery_methods) { 12943 $scope.availableDeliveryMethods = $instance.current.geo_buy.delivery_methods.filter(function(method) { 12944 return !!method.name; 12945 }); 12946 } 12947 12948 function prepareStep() { 12949 if ($scope.step === 1) { 12950 $scope.showNext = true; 12951 } 12952 if ($scope.step > 1) { 12953 $rest.get({ 12954 skipHideLoading: true, 12955 loading: "generic", 12956 url: contextPath + "/www/user/a/mycart.json" 12957 }).then(function(o) { 12958 $scope.user = o; 12959 }); 12960 } 12961 if ($scope.step === 2) { 12962 $scope.showNext = true; 12963 return; 12964 } 12965 if ($scope.step === 3) { 12966 if ($scope.availableDeliveryMethods.length === 0) { 12967 $cart.setDeliveryMethod(null); 12968 $scope.checkout(); 12969 } else if ($scope.availableDeliveryMethods.length === 1) { 12970 $scope.chooseDeliveryMethod($scope.availableDeliveryMethods[0], true); 12971 } else { 12972 $scope.chooseDeliveryMethod($scope.availableDeliveryMethods.filter(function(method) { 12973 return $cart.isDeliveryMethodType(method.name); 12974 })[0] || null, true); 12975 } 12976 return; 12977 } 12978 if ($scope.step === 4) { 12979 $scope.identity = { 12980 checkoutAs: $cart.isAllowedAnonymous() && $cart.hasEmail() ? 'guest' : 'user' 12981 }; 12982 $scope.showNext = isIdentityReadyToContinue(); 12983 return; 12984 } 12985 if ($scope.step === 5) { 12986 if ($instance.current && $instance.current.geo_buy && $utils.isTrue($instance.current.geo_buy.disabled_payment)) { 12987 $scope.checkout(); 12988 return; 12989 } 12990 12991 $rest.get({ 12992 skipHideLoading: true, 12993 url: contextPath + "/www/payment-methods.json", 12994 loading: "generic" 12995 }).then(function(o) { 12996 $scope.choosePayment = true; 12997 $scope.availablePaymentMethods = o.methods; 12998 $scope.externalPaymentData = {}; 12999 13000 if ($scope.availablePaymentMethods.length === 1) { 13001 $scope.choosePaymentMethod($scope.availablePaymentMethods[0]); 13002 } 13003 }); 13004 } 13005 } 13006 13007 function prepareDeliveryMethodBooking(method) { 13008 $rest.get({ 13009 url: contextPath + '/www/geo/' + method.entity + '/' + method.entityId + '.json', 13010 loading: 'generic' 13011 }).then(function(geoObject) { 13012 if (geoObject.geo_schedule && geoObject.geo_schedule.booking && geoObject.geo_schedule.booking.enabled) { 13013 method.bookingConfig = { 13014 geoObject: geoObject, 13015 model: $cart.getDeliveryMethodBooking() 13016 }; 13017 } else { 13018 $scope.showNext = true; 13019 } 13020 }); 13021 } 13022 13023 $scope.onChangeDeliveryMethodBooking = function(booking, isReady) { 13024 $scope.showNext = isReady; 13025 $cart.setDeliveryMethodBooking(booking); 13026 }; 13027 13028 function prepareDeliveryMethodForm(method) { 13029 var formEntity = method.entity; 13030 if ($entity.isGeoForm(formEntity) && $entity.isPermitted(formEntity, 'create')) { 13031 var entity = $entity.getEntity(formEntity); 13032 if (entity) { 13033 $scope.validateCheckout = function() { 13034 $scope.$broadcast('validateDeliveryMethodExtraData'); 13035 }; 13036 method.formConfig = { 13037 entity: entity, 13038 model: $cart.getDeliveryMethodExtraData(), 13039 onSubmit: function(formModel) { 13040 $cart.setDeliveryMethodExtraData(formEntity, formModel); 13041 $scope.validateCheckout = null; 13042 $scope.checkout(); 13043 } 13044 }; 13045 } 13046 } 13047 $scope.showNext = true; 13048 } 13049 13050 $scope.onChangeIdentity = function() { 13051 if ($user.isLogged()) { 13052 $cart.doWhenCartWasInitialized(function() { 13053 $scope.checkout(); 13054 }); 13055 } else { 13056 $cart.save(); 13057 $scope.showNext = isIdentityReadyToContinue(); 13058 } 13059 }; 13060 13061 function isIdentityReadyToContinue() { 13062 return $cart.hasEmail() && $scope.identity.checkoutAs === 'guest'; 13063 } 13064 13065 function isValidStep(step, callback) { 13066 if (step === 1) { 13067 callback(true); 13068 return; 13069 } 13070 if (step === 2) { 13071 if ($scope.user) { 13072 callback($scope.user.users_meta.length > 0 || $scope.user.users.length > 0); 13073 } else if ($user.isLogged()) { 13074 isUserDataStepValid(callback); 13075 } else { 13076 callback(false); 13077 } 13078 return; 13079 } 13080 if (step === 3) { 13081 callback($scope.availableDeliveryMethods.length > 0); 13082 return; 13083 } 13084 if (step === 4) { 13085 callback(!$user.isLogged()); 13086 return; 13087 } 13088 if (step === 5) { 13089 callback(($instance.current && $instance.current.geo_buy && $utils.isTrue($instance.current.geo_buy.disabled_payment)) 13090 || $cart.getTotalAmount() > 0); 13091 return; 13092 } 13093 $angular.goHome(); 13094 } 13095 13096 function isUserDataStepValid(callback) { 13097 $rest.get({ 13098 skipHideLoading: true, 13099 loading: "generic", 13100 url: contextPath + "/www/user/a/mycart.json" 13101 }).then(function(o) { 13102 callback(o.users_meta.length > 0 || o.users.length > 0); 13103 }); 13104 } 13105 13106 $cart.doWhenCartWasInitialized(function() { 13107
13108 if ($routeParams.entity && $routeParams.entityId) { 13109 13110 // clean cart 13111 $cart.resetRaw(); 13112 13113 // check if is booking 13114 if ($routeParams.entity == 'booking') { 13115 13116 // load booking 13117 var url = contextPath + '/www/booking/' + $routeParams.entityId + '.json'; 13118 $rest.get({ 13119 skipHideLoading: true, 13120 url: url, 13121 loading: 'generic' 13122 }).then(function(o) { 13123 13124 // load item 13125 var url2 = contextPath + '/www/geo/' + o.object.entity + '/' + o.object.entity_id + '.json'; 13126 $rest.get({ 13127 skipHideLoading: true, 13128 url: url2, 13129 loading: 'generic' 13130 }).then(function(item) { 13131 $cart.addItem(item.entity, item.id, { quantity: 1, extraData: { booking:o.id, directPay:true }}); 13132 goToStep(2); 13133 }); 13134 }); 13135 return; 13136 } 13137 13138 // get cart item 13139 var url = contextPath + '/www/geo/' + $routeParams.entity + '/' + $routeParams.entityId + '.json'; 13140 $rest.get({ 13141 skipHideLoading: true, 13142 url: url, 13143 loading: 'generic' 13144 }).then(function(item) { 13145 if (!$cart.isCartItem(item, true)) { 13146 console.log('no cart item', item); 13147 } else { 13148 var hasStock = $cart.hasStock(item); 13149 if (!hasStock) { 13150 console.log('no stock', item); 13151 } else { 13152 $cart.addItem(item.entity, item.id, { quantity: 1, extraData: { directPay:true }}); 13153 } 13154 } 13155 goToStep(2); 13156 }); 13157 return; 13158 } 13159 13160 var successPayment = $location.search().success_payment; 13161 if (!$utils.isBlank(successPayment)) { 13162 // success 13163 $scope.payment_id = successPayment; 13164 $scope.step = 6; 13165 $scope.checkout(); 13166 return; 13167 } 13168 13169 var failedPayment = $utils.isTrue($location.search().failed_payment); 13170 if (failedPayment) { 13171 // failed 13172 $utils.showAlert($translate.instant("msg.payment.failed")); 13173 return; 13174 } 13175 13176 // step 13177 var step = 1; 13178 if (!$utils.isBlank($location.search().step)) { 13179 step = Number($location.search().step); 13180 if (isNaN($location.search().step)) { 13181 console.log('error getting step ' + $location.search().step) 13182 step = 1; 13183 } 13184 var search = $location.search(); 13185 delete search.step; 13186 $location.search(search).replace(); 13187 } 13188 goToStep(step); 13189 }); 13190 } 13191})(); 13192 13193//// File web-plan.js //// 13194(function() { 13195 13196 13197 $angular.controllers['web-plan'] = function($rootScope, $scope, $routeParams, $translate, $uibModal, $window, $document, $location, $timeout) { 13198 $angular.preparePage({buttonsRight:"web-plan-buttons.html"}); 13199 $angular.contentScope = $scope; 13200 13201 $scope.title = ""; 13202 $scope.setTitle = function() { 13203 $scope.title = $instance.getGeoSmarterText("title_plan", "msg.web.plan"); 13204 }; 13205 $scope.setTitle(); 13206 13207 //var page = $location.path(); 13208 //$events.lastScrolls[page] = 0; 13209 13210 if ($instance.current.geo_smarter == null) { 13211 $instance.current.geo_smarter = {}; 13212 } 13213 if ($utils.isTrue($instance.current.geo_smarter.disabled)) { 13214 $utils.showAccessDenied(); 13215 return; 13216 } 13217 if ($instance.current.geo_smarter.types == null) { 13218 $instance.current.geo_smarter.types = []; 13219 } 13220 if ($instance.current.geo_smarter.people == null) { 13221 $instance.current.geo_smarter.people = []; 13222 } 13223 if ($instance.current.geo_smarter.categories == null) { 13224 $instance.current.geo_smarter.categories = []; 13225 } 13226 if ($instance.current.subInstances == null) { 13227 $instance.current.subInstances = []; 13228 } 13229 13230 $scope.model = { 13231 date_from: $utils.fromDate(new Date(), $constants.formatDay), 13232 date_to: $utils.fromDate(new Date(), $constants.formatDay), 13233 people: {}, 13234 types: [], 13235 instances: [], 13236 categories: [] 13237 }; 13238 $scope.other = { 13239 showAll : false 13240 }; 13241 13242 if ($instance.current.geo_smarter.types.length > 0) { 13243 $scope.model.types.push($instance.current.geo_smarter.types[0]); 13244 } 13245 13246 $scope.selectAll = function(list) { 13247 list.splice(0, list.length); 13248 }; 13249 $scope.clickChip = function(list, item, noMultiple) { 13250 if (list.indexOf(item) == -1) { 13251 if (noMultiple) { 13252 while(list.length > 0) { 13253 list.pop(); 13254 } 13255 } 13256 list.push(item); 13257 } else { 13258 $utils.removeFromArray(list, item); 13259 } 13260 }; 13261 13262 $scope.clickPerson = function(type) { 13263 var people = $scope.model.people; 13264 if (people[type] == null) { 13265 people[type] = 0; 13266 } 13267 people[type]++; 13268 $angular.apply($scope); 13269 }; 13270 $scope.removePerson = function(e, type) { 13271 $utils.preventDefault(e); 13272 var people = $scope.model.people; 13273 people[type]--; 13274 $angular.apply($scope); 13275 }; 13276 $scope.getNumber = function(value) { 13277 if (value) { 13278 return value; 13279 } 13280 return 0; 13281 } 13282 13283 $scope.finish = function() { 13284 13285 var model = JSON.parse(JSON.stringify($scope.model)); 13286 if ($scope.model.types.length > 0) { 13287 model.type = $scope.model.types[0]; 13288 } 13289 delete model.types; 13290 //console.dir(model) 13291 13292 $rest.post({ 13293 url: contextPath + "/www/smarter.json", 13294 data: model, 13295 loading: "generic" 13296 }).then(function(data) { 13297 if (data == null || data.length == 0) { 13298 var txt = $translate.instant("msg.web.agenda.noResults"); 13299 $utils.floatingError(txt); 13300 return; 13301 } 13302 //console.dir(data) 13303 13304 // save data 13305 $sessionService.put("agenda_"+$instance.getId(), JSON.stringify(data)); 13306 13307 $location.path($instance.getBaseUrl() + "agenda").replace(); 13308 }); 13309 13310 }; 13311 13312 } 13313 13314})(); 13315 13316//// File web-user.js //// 13317(function() { 13318 13319 13320 $angular.controllers['web-user'] = function($rootScope, $scope, $translate, $location) { 13321 $angular.preparePage(); 13322 $angular.contentScope = $scope; 13323 13324 $scope.title = ""; 13325 $scope.setTitle = function() { 13326 $scope.title = $translate.instant("msg.user.account"); 13327 }; 13328 $scope.setTitle(); 13329 13330 $scope.model = {}; 13331 $scope.showEdit = true; 13332 $rest.get({ 13333 skipHideLoading: true, 13334 loading: "generic", 13335 url: contextPath + "/www/user/a/myaccount.json" 13336 }).then(function(o) { 13337 $scope.model = o; 13338 13339 $angular.apply($scope, function() { 13340 $angular.ready = true; 13341 }); 13342 }); 13343 13344 } 13345 13346})(); 13347 13348//// File web-home.js //// 13349(function() { 13350 13351 13352 $angular.controllers['web-home'] = function($rootScope, $scope, $routeParam
13352s, $translate, $window, $location, geolocationService, $timeout) { 13353 $angular.preparePage({ resetBacks:true, buttonsRight:"web-home-buttons.html" }); 13354 $angular.contentScope = $scope; 13355 13356 if ($instance.current == null) { 13357 $angular.log('no instance'); 13358 return; 13359 } 13360 13361 function initHome() { 13362 13363 var id = $routeParams.id; 13364 if ($utils.isBlank(id)) { 13365 // get first page 13366 var o = $instance.current.geo_web; 13367 if (o && o.menu && o.menu.length > 0) { 13368 id = o.menu[0].id; 13369 $location.path($instance.getBaseUrl() + "p/" + id).search({}).replace(); 13370 return; 13371 } 13372 } 13373 if ($utils.isBlank(id)) { 13374 $angular.log('no page id found'); 13375 return; 13376 } 13377 13378 $angular.menuScope.selectedPage = 'home-' + id; 13379 $scope.page = null; 13380 $rest.get({ 13381 skipHideLoading: true, 13382 loading: "generic", 13383 url: contextPath + "/www/instance/"+$instance.current.id+"/home.json?page=" + id 13384 }).then(function(o) { 13385 $scope.page = o; 13386 parseItems(); 13387 13388 $angular.apply($scope, function() { 13389 var url = window.location.href; 13390 if (url.contains("#")) { 13391 var id = url.split("#")[1]; 13392 if (!$utils.isBlank(id)) { 13393 var el = document.getElementById(id); 13394 if (el !== null) { 13395 el.scrollIntoView(); 13396 return; 13397 } 13398 } 13399 } 13400 $angular.ready = true; 13401 }); 13402 }); 13403 } 13404 13405 function parseItems() { 13406 var items = []; 13407 var requestGeoLocation = false; 13408 if ($scope.page.items) { 13409 var slides = []; 13410 var gallery = []; 13411 for (var k in $scope.page.items) { 13412 var item = $scope.page.items[k]; 13413 if ($utils.isTrue(item.hidden)) { 13414 continue; 13415 } 13416 loadData(item); 13417 13418 if (item.classes == null) { 13419 item.classes = ""; 13420 } 13421 if (item.type != 'carousel' && item.type != 'preview-carousel' && item.type != 'gallery') { 13422 if (!item.classes.contains("col-")) { 13423 if (item.type == 'column') { 13424 item.classes += " col-sm-4"; 13425 } else { 13426 item.classes += " col-12"; 13427 } 13428 } 13429 } 13430 if (!$utils.isBlank(item.alignment)) { 13431 item.classes += " align-" + item.alignment; 13432 } 13433 13434 // check carousel 13435 if (item.type == 'carousel') { 13436 slides.push(item); 13437 continue; 13438 } 13439 if (slides.length > 0) { 13440 items.push({ 13441 type: 'carousel', 13442 classes: "col-12", 13443 list: slides 13444 }); 13445 slides = []; 13446 } 13447 13448 // check gallery 13449 if (item.type == 'gallery') { 13450 gallery.push(item); 13451 continue; 13452 } 13453 if (gallery.length > 0) { 13454 items.push({ 13455 type: 'gallery', 13456 classes: "col-12", 13457 list: gallery 13458 }); 13459 gallery = []; 13460 } 13461 13462 // TODO remove title / horizontal 13463 if ($utils.isBlank(item.type) || item.type == 'title' || item.type == 'horizontal') { 13464 item.type = 'default'; 13465 } 13466 13467 // normal item 13468 items.push(item); 13469 } 13470 13471 if (slides.length > 0) { 13472 items.push({ 13473 type: 'carousel', 13474 classes: "col-12", 13475 list: slides 13476 }); 13477 } 13478 if (gallery.length > 0) { 13479 items.push({ 13480 type: 'gallery', 13481 classes: "col-12", 13482 list: gallery 13483 }); 13484 } 13485 13486 if ((item.type === 'form' || item.type === 'formview') && item.entity && $entity.isAutoLocation(item.entity)) { 13487 requestGeoLocation = true; 13488 } 13489 } 13490 13491 if (requestGeoLocation) { 13492 geolocationService.getCurrentLocation().then(function(location) { 13493 $scope.currentGeoLocation = location; 13494 }); 13495 } 13496 13497 $scope.page.itemList = items; 13498 } 13499 13500 var webForm = null; 13501 var webFormCallback = null; 13502 $scope.webFormItem = null; 13503 $scope.initForm = function(form, item) { 13504 webForm = form; 13505 $scope.webFormItem = item; 13506 } 13507 $scope.saveForm = function(callback) { 13508 webFormCallback = callback; 13509 setTimeout(function(){ 13510 $("#webForm")[0].requestSubmit(); // to validate form 13511 }, 100); 13512 } 13513 $scope.submitForm = function(e) { 13514 $utils.preventDefault(e); 13515 13516 if (!$utils.validateForm(webForm.webForm)) { 13517 return; 13518 } 13519 13520 var item = $scope.webFormItem; 13521 var model = item.model; 13522 var isCreate = item.model.id == null; 13523 13524 if (item.type == 'formview') { 13525 isCreate = item.form.data.id == null; 13526 model = { 13527 id: item.form.data.id, 13528 formId : item.form.form.id, 13529 data: item.form.data 13530 }; 13531 } 13532 13533 if ($scope.currentGeoLocation) { 13534 model.geo_location = { 13535 latitude: $scope.currentGeoLocation.latitude, 13536 longitude: $scope.currentGeoLocation.longitude 13537 }; 13538 } 13539 13540 $rest.post({ 13541 url: contextPath + "/www/geo/" + item.entity + ".json", 13542 data: model, 13543 loading: "generic" 13544 }).then(function(data) { 13545 13546 if (isCreate && item.form != null) { 13547 if (item.type == 'formview') { 13548 item.form.data.id = data.id; 13549 } else { 13550 item.form.model.id = data.id; 13551 } 13552 }
13553 $utils.postSave(model, data, isCreate, webFormCallback, function(callback) { 13554 13555 if (!$utils.isBlank(item.link)) { 13556 var url = item.link; 13557 if (url.contains('geodesignlabs.com/admin')) { 13558 13559 } else if (url.contains('geodesignlabs.com/') && !url.contains('/media')) { 13560 url = url.split('geodesignlabs.com/')[1]; 13561 } 13562 url = $entity.parseQuery(url, data); 13563 $location.path(url); 13564 13565 if (callback) { 13566 callback(); 13567 } 13568 return; 13569 } 13570 13571 // reload data 13572 loadForm(item, data); 13573 13574 if (callback) { 13575 callback(); 13576 } 13577 }); 13578 }); 13579 }; 13580 13581 $scope.refreshForm = function() { 13582 refreshForm(); 13583 }; 13584 function refreshForm() { 13585 loadForm($scope.webFormItem, { id:$scope.webFormItem.model.id }); 13586 } 13587 13588 $scope.resetForm = function() { 13589 // reload with new 13590 loadForm($scope.webFormItem); 13591 }; 13592 13593 $scope.openUploadFile = function(e) { 13594 $utils.preventDefault(e); 13595 $('#webFormAttachments input[type="file"]').trigger('click'); 13596 }; 13597 13598 $scope.uploadFile = function(files) { 13599 if (files.length === 0) { 13600 return; 13601 } 13602 var file = files[0]; 13603 var reader = new FileReader(); 13604 reader.onload = function(event) { 13605 $rest.post({ 13606 url: contextPath + '/www/media/a/createBase64.json', 13607 data: { 13608 fileBase64: event.target.result.split(',')[1], 13609 fileName: file.name, 13610 entity: $scope.webFormItem.entity, 13611 entityId: $scope.webFormItem.model.id 13612 }, 13613 loading: 'generic', 13614 successMessage: $translate.instant('msg.saved') 13615 }).then(function() { 13616 refreshForm(); 13617 }); 13618 }; 13619 reader.readAsDataURL(file); 13620 }; 13621 13622 $scope.removeFile = function(item, item2) { 13623 $rest.remove({ 13624 url: contextPath + '/www/media/' + item.id + '.json', 13625 loading: 'generic', 13626 confirmTitle: $translate.instant('msg.remove'), 13627 successMessage: $translate.instant('msg.removed') 13628 }).then(function() { 13629 refreshForm(); 13630 }); 13631 }; 13632 13633 function loadForm(item, data) { 13634 var url; 13635 if (data && data.id) { 13636 url = contextPath + '/www/geo/' + item.entity + '/' + data.id + '/edit.json'; 13637 } else { 13638 url = contextPath + "/www/geo/" + item.entity + "/new.json"; 13639 $scope.isNew = true; 13640 } 13641 if (item.type == 'formview') { 13642 url += "?form=" + item.formview; 13643 } 13644 $rest.get({ 13645 skipHideLoading: true, 13646 url: url, 13647 loading: 'generic' 13648 }).then(function(o) { 13649 13650 $entity.getEntityForce(o.entity, function(meta) { 13651 if (meta.id === "user") { 13652 meta.columns = []; // FIXME user no columns??? 13653 } 13654 item.meta = meta; // needed for translations 13655 item.model = o;//$utils.setModel(item.model, o); 13656 13657 if (item.type == 'formview') { 13658 item.formviews = $utils.setFormviews(item.formviews, o); 13659 for (var k in item.formviews) { 13660 var fv = item.formviews[k]; 13661 if (fv.form.id == item.formview) { 13662 item.form = fv; 13663 } 13664 } 13665 } 13666 13667 // auto fill url params 13668 var search = $location.search(); 13669 if (search) { 13670 for (var k in search) { 13671 var svalue = search[k]; 13672 if (!$utils.isBlank(svalue)) { 13673 //console.log(k, svalue) 13674 var column = $entity.getColumn(item.entity, k); 13675 if (column != null) { 13676 //console.log(column); 13677 if (item.form != null) { 13678 item.form.data[k] = svalue; 13679 } else { 13680 item.model[k] = svalue; 13681 } 13682// delete search[k]; 13683// $location.search(search).replace(); 13684 } 13685 } 13686 } 13687 } 13688 13689 // keep last scroll 13690 var scroll = $window.pageYOffset; 13691 $angular.apply($scope, function() { 13692 window.scrollTo(0, scroll); 13693 }); 13694 }); 13695 }); 13696 } 13697 13698 function loadData(item) { 13699 13700 if (item.type == 'form' || item.type == 'formview') { 13701 loadForm(item); 13702 return; 13703 } 13704 13705 if (item.action != 'entity' || $utils.isBlank(item.entity)) { 13706 return; 13707 } 13708 13709 $entity.getEntityForce(item.entity, function(meta) { 13710 //console.log(item.entity + " -> " + meta.id, meta) 13711 var limit = 2; 13712 if (item.type == 'preview' || item.type == 'preview-carousel') { 13713 if (item.preview == null) { 13714 item.preview = 4; 13715 } else { 13716 item.preview = Number(item.preview); 13717 } 13718 item.limit = item.preview + 1; 13719 limit = item.limit; 13720 } 13721 var url = contextPath + "/www/geo/" + item.entity + ".json?_limit=" + limit; 13722 if (item.instance) { 13723 url += "&instances=" + item.instance; 13724 } 13725 if (item.categories && item.categories.length > 0) { 13726 url += '&categories:in=' + $utils.join(item.categories,","); 13727 } 13728 if (item.query) { 13729 url += '&' + item.query; 13730 } 13731 item.entity = meta.id; 13732 $rest.get({ 13733 url: url, 13734 force: true 13735 }).then(function(o) { 13736 item.data = o.list; 13737 }); 13738 }); 13739 13740 } 13741 13742 $scope.hasAgenda = function() { 13743 return !$utils.isBlank($sessionService.get("agenda_"+$instance.getId())); 13744 }; 13745 13746 $scope.hasText = function(item) { 13747 return !$utils.isBlank($utils.parse(item.title)) 13748 || !$utils.isBlank($utils.parse(item.description)); 13749 }; 13750 13751 $scope.hasButtonText = function(item) { 13752 return !$utils.isBlank($utils.parse(item.button)); 13753 }; 13754 13755 $scope.hasAction = function(item) { 13756 if ($utils.isBlank(item.action)) { 13757 return false;
13758 } 13759 if (item.action == 'entity') { 13760 if (!$utils.isBlank(item.entity)) { 13761 if ($entity.isGeoForm(item.entity) && item.type != 'preview' && item.type != 'preview-carousel') { 13762 return true; 13763 } 13764 if (item.type == 'preview' || item.type == 'preview-carousel') { 13765 return item.data && item.data.length > item.preview; 13766 } 13767 return item.data && item.data.length > 0; 13768 } 13769 if ($utils.isBlank(item.instance)) { 13770 return false; 13771 } 13772 } 13773 if (item.action == 'link') { 13774 return !$utils.isBlank(item.link); 13775 } 13776 return true; 13777 }; 13778 13779 $scope.getButtonText = function(item) { 13780 var text = $utils.parse(item.button); 13781 if (!$utils.isBlank(text)) { 13782 return text; 13783 } 13784 if (item.action == 'entity') { 13785 return $translate.instant("msg.web.seeAll"); 13786 } 13787 return $translate.instant("msg.go"); 13788 }; 13789 13790 // styles 13791 $scope.getStyleItem = function(item) { 13792 if (!$utils.isBlank(item.background)) { 13793 return { 'background-color':item.background }; 13794 } 13795 return {}; 13796 }; 13797 $scope.getStyleItemImage = function(item) { 13798 if (!$utils.isBlank(item.image)) { 13799 return { 'background-image':'url('+$rootScope.$media.getMediaUrl(item.image, $angular.imgExtensionFinal)+')' }; 13800 } 13801 return {}; 13802 }; 13803 $scope.getStyleItemText = function(item) { 13804 if (item.type == 'default' || item.type == 'horizontal') { 13805 if (!$utils.isBlank(item.image)) { 13806 return { 'color':'var(--color-image-text)' }; 13807 } 13808 } 13809 if (!$utils.isBlank(item.background)) { 13810 return { 'color':$utils.getColorText(item.background) }; 13811 } 13812 return {}; 13813 }; 13814 $scope.getStyleImage = function(id) { 13815 if ($instance.current) { 13816 var images = $instance.current.geo_images; 13817 if (images) { 13818 var image = images[id]; 13819 if (image && image.width && image.height) { 13820 var value = image.height * 100 / image.width; 13821 return { 'height': value+'%' }; 13822 //,'aspect-ratio': image.width + '/' + image.height 13823 } 13824 } 13825 } 13826 return {}; 13827 }; 13828 13829 // click items 13830 $scope.clickItem = function(e, item, index, carousel) { 13831 $utils.preventDefault(e); 13832 13833 var o = item; 13834 if (index != null && item.list != null) { 13835 item = item.list[index]; 13836 } 13837 //console.log(item) 13838 13839 var url = null; 13840 var params = {}; 13841 if (item.action == 'new_smart') { 13842 url = $instance.getBaseUrl() + "plan"; 13843 13844 } else if (item.action == 'my_smart') { 13845 if ($scope.hasAgenda()) { 13846 url = $instance.getBaseUrl() + "agenda"; 13847 } else { 13848 url = $instance.getBaseUrl() + "plan"; 13849 } 13850 13851 } else if (item.action == 'link' && !$utils.isBlank(item.link)) { 13852 url = item.link; 13853 } 13854 13855 if ($utils.isBlank(url)) { 13856 if (item.entity) { 13857 if (item.data && item.data.length == 1) { 13858 url = $rootScope.getItemLinkBy(item.data[0]); 13859 } else if (item.entity) { 13860 url = $rootScope.getItemLink(item.entity, item.id); 13861 } 13862 if (item.instance) { 13863 params.instances = item.instance; 13864 } 13865 if (item.categories && item.categories.length > 0) { 13866 params['categories:in'] = $utils.join(item.categories,","); 13867 } 13868 if (item.query) { 13869 var o = queryStringToJSON(item.query); 13870 for (var k in o) { 13871 params[k] = o[k]; 13872 } 13873 } 13874 13875 } else if (item.instance) { 13876 url = "home/" + item.instance; 13877 } 13878 } 13879 13880 if (!$utils.isBlank(url)) { 13881 if (typeof url != 'string') { 13882 $angular.log('url is not string: ' + url); 13883 return; 13884 } 13885 if (!$utils.isTrue(item.new_tab)) { 13886 if (url.contains('geodesignlabs.com/admin')) { 13887 13888 } else if (url.contains('geodesignlabs.com/') && !url.contains('/media')) { 13889 url = url.split('geodesignlabs.com/')[1]; 13890 } 13891 } 13892 if (url.startsWith('http')) { 13893 if ($utils.isTrue(item.new_tab)) { 13894 window.open(url); 13895 } else { 13896 window.location.href = url; 13897 } 13898 return; 13899 } 13900 if (url.startsWith('#')) { 13901 var last = window.location.href; 13902 if (last.contains("#")) { 13903 last = last.split("#")[0]; 13904 } 13905 window.location.href = last + url; 13906 return; 13907 } 13908 //console.log(url, params) 13909 $location.path(url).search(params); 13910 return; 13911 } 13912 13913 item = o; // restore original 13914// if (item.image) { 13915// $rootScope.clickImage(null, [item], 0); 13916// return; 13917// } 13918 if (item.type == 'gallery' && index != null) { 13919 // open gallery in fullscreen 13920 $rootScope.clickImage(null, item.list, index); 13921 return; 13922 } 13923 13924 if ((item.type == 'carousel' || item.type == 'preview-carousel') && carousel != null) { 13925 $rootScope.carouselNext(e, carousel); 13926 return; 13927 } 13928 13929 }; 13930 13931 initHome(); 13932 } 13933 13934})(); 13935 13936//// File web-list.js //// 13937(function() { 13938 13939 $angular.controllers['web-list'] = function($rootScope, $scope, $routeParam
13939s, $translate, $uibModal, $window, $document, $location) { 13940 $angular.preparePage({buttonsRight: "web-list-buttons.html"}); 13941 $angular.contentScope = $scope; 13942 $angular.menuScope.selectedPage = ""; 13943 $scope.showMap = false; 13944 13945 $scope.instanceId = $routeParams.instanceId; 13946 $scope.entity = $routeParams.entity; 13947 $scope.model = {}; 13948 $angular.currentRoute += " " + $angular.currentRoute+"-"+$scope.entity; 13949 13950 var subInstance = $routeParams.instances; 13951 $scope.title = ""; 13952 $scope.setTitle = function() { 13953 var title; 13954 if (!$utils.isBlank(subInstance)) { 13955 title = $instance.getSubInstanceName(subInstance); 13956 } 13957 if ($utils.isBlank(title)) { 13958 title = $instance.getEntityName($scope.entity); 13959 } 13960 $scope.title = title; 13961 }; 13962 13963 $entity.getEntityForce($scope.entity, function(o){ 13964 $scope.meta = o; 13965 $scope.setTitle(); 13966 $scope.showMap = $entity.isGeoLocation(o); 13967 13968 if ($scope.showMap) { 13969 $angular.apply($scope, function() { 13970 initGeoIndexMap(); 13971 }); 13972 } 13973 }); 13974 13975 $paginate.init($(".paginate"), { 13976 path: "www/geo/" + $scope.entity, 13977 noLoad: true 13978 }); 13979 13980 function loadData(force, search) { 13981 13982 var qs = $paginator._settings.queryString; 13983 if (qs == null) qs = ""; 13984 qs = removeParam(qs, "_index"); 13985 qs = removeParam(qs, '_q'); 13986 13987 if (!$utils.isBlank(search)) { 13988 search = search.replace("'", ""); // bug angularjs 13989 search = $utils.removeDiacritics(search.trim().toLowerCase()); 13990 } 13991 if (!$utils.isBlank(search)) { 13992 // filter by search 13993 qs = addParam(qs, '_q', search); 13994 } else { 13995 var searchParams = $scope.searchParams; 13996 if (searchParams) { 13997 var text = searchParams.text; 13998 if (text) { 13999 text = text.replace("'", ""); // bug angularjs 14000 text = $utils.removeDiacritics(text.trim().toLowerCase()); 14001 qs = addParam(qs, '_q', text); 14002 } 14003 var likes = searchParams.likes; 14004 Object.keys(likes).forEach(function(likeKey) { 14005 var paramKey = likeKey + ':like'; 14006 qs = removeParam(qs, paramKey); 14007 var paramValue = likes[likeKey]; 14008 if (paramValue && $scope.advancedSearch) { 14009 qs = addParam(qs, paramKey, paramValue); 14010 } 14011 }); 14012 var options = searchParams.options; 14013 Object.keys(options).forEach(function(optionKey) { 14014 var paramKey = optionKey + ':in'; 14015 qs = removeParam(qs, paramKey); 14016 var paramValue = options[optionKey]; 14017 if (paramValue && $scope.advancedSearch) { 14018 qs = addParam(qs, paramKey, paramValue); 14019 } 14020 }); 14021 } 14022 } 14023 $paginator.updateList(qs, force); 14024 refreshMarkers(true); 14025 window.scrollTo(0, 0); 14026 14027 $angular.apply($scope, function() { 14028 $angular.ready = true; 14029 }); 14030 } 14031 14032 // map 14033 $scope.showOrHideMap = function() { 14034 $scope.showMap = !$scope.showMap; 14035 }; 14036 14037 // calendar 14038 $scope.showCalendar = false; 14039 $scope.showOrHideCalendar = function() { 14040 $scope.showCalendar = !$scope.showCalendar; 14041 if ($scope.showCalendar) { 14042 $scope.$broadcast('reloadCalendarComponent'); 14043 } 14044 }; 14045 14046 $scope.calendarConfig = { 14047 initialView: 'dayGridMonth', 14048 getItems: function() { 14049 return $scope.model.list; 14050 }, 14051 onClickEvent: function(event, item) { 14052 window.location.href = $rootScope.getItemLinkBy(item); 14053 }, 14054 convertItemToEvent: function(item) { 14055 if (item.geo_schedule && item.geo_schedule.dates) { 14056 var timeZone = $utils.getTimeZone(); 14057 var today = $utils.fromDate(new Date(), 'yyyy-MM-dd', 'UTC' + timeZone); 14058 var time = $utils.fromDate(new Date(), 'HH:mm', 'UTC' + timeZone); 14059 var oneYear = new Date(); 14060 oneYear.setDate(oneYear.getDate() + 365); 14061 for (var d in item.geo_schedule.dates) { 14062 var date = item.geo_schedule.dates[d]; 14063 if (date && date.day) { 14064 if (date.day > oneYear) { 14065 continue; 14066 } 14067 var endDay = date.end_day ? date.end_day : date.day; 14068 if (endDay < today) { 14069 continue; 14070 } 14071 if (endDay === today && date.time_to < time) { 14072 continue; 14073 } 14074 14075 var o = { 14076 id: item.id, 14077 start: date.day + 'T' + date.time_from + ':00', 14078 end: endDay + 'T' + date.time_to + ':00', 14079 title: $entity.displayColumn(item) 14080 }; 14081 if (item.status) { 14082 o.classNames = ['fc-status-'+item.status]; 14083 } 14084 return o; 14085 } 14086 } 14087 } 14088 return {}; 14089 } 14090 }; 14091 14092 var map; 14093 var infoWindow; 14094 var markers = {}; 14095 var _tmp = 0; 14096 14097 function initGeoIndexMap() { 14098 14099 markers = {}; 14100 _tmp = 0; 14101 infoWindow = new google.maps.InfoWindow({maxWidth: 230, maxHeight: 230}); 14102 14103 var mapOptions = { 14104 mapId : "GEO_LIST", 14105 streetViewControl: false, panControl: false, 14106 mapTypeId: google.maps.MapTypeId.ROADMAP, 14107 disableDefaultUI: false, zoomControl: true 14108 }; 14109 14110 var gf = $instance.getGeoFence(); 14111 if (gf && gf.center_latitude) { 14112 var lat = Number(gf.center_latitude); 14113 var lng = Number(gf.center_longitude); 14114 var pos = new google.maps.LatLng(lat, lng); 14115 var zoom = 12; 14116 if (gf.default_zoom) { 14117 zoom = Number(gf.default_zoom); 14118 } 14119 mapOptions.center = pos; 14120 mapOptions.zoom = zoom; 14121 } else { 14122 mapOptions.center = new google.maps.LatLng(0, 0); 14123 mapOptions.zoom = 3; 14124 } 14125 map = new google.maps.Map(document.getElementById('web-list-map'), mapOptions); 14126 //google.maps.event.addListenerOnce(map, 'idle', function(){}); 14127 //google.maps.event.addListener(map, "click", function(event) {});
14128 //google.maps.event.addListener(map, "zoom_changed", function(event) {}); 14129// google.maps.event.addListener(map, "bounds_changed", function(event) { 14130// _tmp++; 14131// var val = _tmp; 14132// setTimeout(function(){ 14133// if (val == _tmp) { 14134// refreshMarkers(); 14135// } 14136// }, 250); 14137// }); 14138 14139 google.maps.event.addListener(map, 'zoom_changed', function() { 14140 if (this.getZoom() > 17.5 && this.initialZoom) { 14141 this.setZoom(17.5); 14142 this.initialZoom = false; 14143 } 14144 }); 14145 14146 refreshMarkers(true); 14147 $utils.prepareMapImages($scope.entity, map); 14148 } 14149 14150 function refreshMarkers(clean) { 14151 14152 if (clean == null) { 14153 clean = false; 14154 } 14155 14156 var qs = $paginator._settings.queryString; 14157 qs = removeParam(qs, "_order"); 14158 qs = removeParam(qs, "_limit"); 14159 qs = removeParam(qs, "_paginate"); 14160 qs = addParam(qs, "_limit", 1000); 14161// var b = map.getBounds(); 14162// if (b && b.ma && b.fa) { 14163// qs = addParam(qs, "geo_location.latitude:$gt", b.ma.j); 14164// qs = addParam(qs, "geo_location.longitude:$gt", b.fa.j); 14165// qs = addParam(qs, "geo_location.latitude:$lt", b.ma.l); 14166// qs = addParam(qs, "geo_location.longitude:$lt", b.fa.l); 14167// } 14168 var url = contextPath + "/www/geo/" + $angular.contentScope.entity + "/a/map.json" + qs; 14169 $rest.get({ 14170 //loading: "generic", 14171 url: url 14172 }).then(function(data) { 14173 14174 var bounds = new google.maps.LatLngBounds(null); 14175 var num = 0; 14176 14177 if (clean) { 14178 for (var id in markers) { 14179 var m = markers[id]; 14180 m.setMap(null); 14181 } 14182 markers = {}; 14183 } 14184 14185 for (var k in data.list) { 14186 var item = data.list[k]; 14187 if (markers[item.id]) { 14188 continue; // exists 14189 } 14190 // add new 14191 var loc = item.geo_location; 14192 if (loc == null || loc.latitude == null || loc.longitude == null) { 14193 continue; 14194 } 14195 var pos = new google.maps.LatLng(loc.latitude, loc.longitude); 14196 var marker = new google.maps.Marker({ 14197 position: pos, 14198 map: map, clickable: true 14199 }); 14200 markers[item.id] = marker; 14201 14202 google.maps.event.addListener(marker, 'click', (function(plc, mark) { 14203 return function() { 14204 var href = $rootScope.getItemLinkBy(plc); 14205 var content = "<div class='infowindow'><a href='" + href + "' class='bold'>" + $entity.displayColumn(plc) + "</a><br>"; 14206 content += "<label style='margin-top:5px; font-size: 14px;'>" + $utils.parse(plc.geo_location.address + "</label></div>"); 14207 infoWindow.setContent(content); 14208 infoWindow.open(map, mark); 14209 }; 14210 })(item, marker)); 14211 14212 bounds.extend(pos); 14213 num++; 14214 } 14215 14216 if (num > 0 && map) { 14217 map.initialZoom = true; 14218 map.fitBounds(bounds); 14219 } 14220 14221 }); 14222 } 14223 14224 $scope.searchParams = { 14225 text: $routeParams._q, 14226 likes: {}, 14227 options: {} 14228 }; 14229 $scope.advancedSearch = true; //false; 14230 $scope.searchOptions = {}; 14231 $scope.searchOptionsSelected = {}; 14232 14233 $scope.applySearch = function() { 14234 loadData(true); 14235 }; 14236 14237 $scope.modifySearchColumnOption = function(column, itemId, $event) { 14238 if ($event) { 14239 $event.preventDefault(); 14240 } 14241 var columnElement = $scope.searchOptionsSelected[column.name]; 14242 if (!columnElement) { 14243 columnElement = { 14244 options: {}, 14245 text: null 14246 }; 14247 $scope.searchOptionsSelected[column.name] = columnElement; 14248 } 14249 var options = columnElement.options; 14250 14251 var option = options[itemId]; 14252 if (!option) { 14253 option = { 14254 checked: false 14255 }; 14256 options[itemId] = option; 14257 } 14258 option.checked = !option.checked; 14259 14260 var availableOptions = $scope.searchOptions[column.param]; 14261 if (availableOptions == null) { 14262 availableOptions = []; 14263 } 14264 var checkedOptions = Object.keys(options) 14265 .filter(function(key) { 14266 return options[key].checked; 14267 }); 14268 $scope.searchParams.options[column.name] = checkedOptions.join(','); 14269 columnElement.text = checkedOptions 14270 .map(function(key) { 14271 return availableOptions.filter(function(op) { 14272 return op.id === key; 14273 })[0] || null; 14274 }) 14275 .filter(function(op) { 14276 return !!op; 14277 }) 14278 .map(function(op) { 14279 return $entity.displayColumn(op); 14280 }) 14281 .join(', '); 14282 }; 14283 14284 function selectEntityFilterByParams(col) {
14285 var paramValue = $routeParams[col.name + ':in']; 14286 if (typeof paramValue == 'string') { 14287 paramValue.split(',').forEach(function(id) { 14288 $scope.modifySearchColumnOption(col, id); 14289 }); 14290 $scope.advancedSearch = true; 14291 } 14292 } 14293 14294 var searchColumns = [];//$utils.cloneList($entity.getSearchColumns($scope.entity)); 14295 var searchOptionsPromises = {}; 14296 $entity.getSearchColumns($scope.entity).forEach(function(col) { 14297 14298 if (col.isEntity) { 14299 searchColumns.push(col); 14300 if ($scope.searchOptions[col.param]) { 14301 selectEntityFilterByParams(col); 14302 } else { 14303 if (!searchOptionsPromises[col.param]) { 14304 var prom = $constants.getEntityList(col.param, null, null, null, 250); 14305 if (prom) { 14306 searchOptionsPromises[col.param] = prom.then(function(result) { 14307 $scope.searchOptions[col.param] = result; 14308 }); 14309 } 14310 } 14311 if (searchOptionsPromises[col.param]) { 14312 searchOptionsPromises[col.param].then(function() { 14313 selectEntityFilterByParams(col); 14314 }); 14315 } 14316 } 14317 } else { 14318 searchColumns.push(col); 14319 var paramValue = $routeParams[col.name + ':like']; 14320 if (paramValue) { 14321 $scope.searchParams.likes[col.name] = paramValue; 14322 $scope.advancedSearch = true; 14323 } 14324 } 14325 }); 14326 var categoryList = $instance.getCategoryList($scope.entity); 14327 if (categoryList && categoryList.length > 0) { 14328 var categoriesColumn = { 14329 name: 'categories', 14330 isEntity: true, 14331 param: '__categories__' 14332 }; 14333 searchColumns.push(categoriesColumn); 14334 $scope.searchOptions[categoriesColumn.param] = categoryList; 14335 selectEntityFilterByParams(categoriesColumn); 14336 } 14337 $scope.searchColumns = searchColumns; 14338 14339 $scope.resetSearch = function() { 14340 14341 // remove url params 14342 var qs = $paginator._settings.queryString; 14343 if (qs == null) qs = ""; 14344 qs = removeParam(qs, "_index"); 14345 qs = removeParam(qs, '_q'); 14346 14347 var searchParams = $scope.searchParams; 14348 var likes = searchParams.likes; 14349 Object.keys(likes).forEach(function(likeKey) { 14350 var paramKey = likeKey + ':like'; 14351 qs = removeParam(qs, paramKey); 14352 }); 14353 var options = searchParams.options; 14354 Object.keys(options).forEach(function(optionKey) { 14355 var paramKey = optionKey + ':in'; 14356 qs = removeParam(qs, paramKey); 14357 }); 14358 14359 // reset filter 14360 searchParams.text = ''; 14361 searchParams.likes = {}; 14362 searchParams.options = {}; 14363 for (var k in $scope.searchOptionsSelected) { 14364 var columnElement = $scope.searchOptionsSelected[k]; 14365 if (columnElement == null) { 14366 continue; 14367 } 14368 columnElement.options = {}; 14369 columnElement.text = null; 14370 } 14371 14372 // update list 14373 console.log(qs) 14374 $paginator.updateList(qs, true); 14375 refreshMarkers(true); 14376 window.scrollTo(0, 0); 14377 }; 14378 14379 loadData(true); 14380 } 14381 14382})(); 14383 14384//// File web-pos.js //// 14385(function() { 14386 14387 $angular.controllers['web-pos'] = function($rootScope, $scope, $translate, $templateCache, $compile, $q) { 14388 $angular.preparePage(); 14389 $angular.contentScope = $scope; 14390 $angular.menuScope.selectedPage = ""; 14391 $rest.showNewVersion = true; 14392 14393 // only for admin/coordinators (new role vendedor?) 14394 $scope.config = $instance.current != null ? $instance.current.geo_pos : null; 14395 if ((!$user.isAdmin() && !$user.isCoordinator()) || $scope.config == null || !$scope.config.enabled) { 14396 $utils.showAccessDenied(); 14397 return; 14398 } 14399 if ($scope.config.orders == null || $scope.config.products == null) { 14400 $utils.showAlert("Missing configuration"); 14401 return; 14402 } 14403 14404 var isDev = location.host.indexOf('localhost') !== -1; 14405 if (!isDev) { 14406 // warn if back button 14407 window.onbeforeunload = function(e) { 14408 return $translate.instant("msg.confirm.leave"); 14409 }; 14410 } 14411 14412 $scope.payTypeList = []; 14413 $entity.getEntityForce($scope.config.orders, function(o){ 14414 $scope.meta = o; 14415 //console.log('meta', o) 14416 o.columns.forEach(function(column) { 14417 if (column.name == 'pay_type') { 14418 $scope.payTypeList = column.options; 14419 return; 14420 } 14421 }); 14422 }); 14423 14424 $scope.filter = { 14425 orders: $storageService.get("_pos_orders"), 14426 search1: null, 14427 search2: null 14428 }; 14429 14430 $scope.platforms = [ 14431 { id: 'local', name: 'Local', icon: 'store', priceField: null } // required 14432 //,{ id: 'uber', name: 'Uber', icon: 'directions_car', priceField: 'price_uber' } 14433 //,{ id: 'rappi', name: 'Rappi', icon: 'moped', priceField: 'price_rappi' } 14434 ]; 14435 14436 $scope.initOrder = function(order) { 14437 parseClients(order); 14438 }; 14439 $scope.showOrders = function(type) { 14440 if (type) { 14441 $scope.filter.orders = type; 14442 } 14443 $scope.showList = true; 14444 $angular.title = $translate.instant("msg.order.list"); 14445 $scope.order = null; 14446 $scope.getOrders(); 14447 }; 14448 $scope.newOrder = function() { 14449 $scope.showList = false; 14450 $angular.title = $translate.instant("msg.order.new"); 14451 14452 $scope.order = { 14453 entity: $scope.config.orders, 14454 items: [], 14455 platform: $scope.platforms[0] // Default a local 14456 }; 14457 refreshTotals(false); 14458 $scope.original = $utils.clone($scope.order); 14459 14460 // refresh products for availability 14461 $scope.getProducts(); 14462 }; 14463 $scope.showOrder = function(item) { 14464 //console.dir(item) 14465 $scope.showList = false; 14466 $angular.title = $translate.instant("msg.order") + " #" + item.code; 14467 14468 item.clients = null; 14469 $scope.order = item; 14470 // Asegurar que exista una plataforma asignada en órdenes previas 14471 if (!$scope.order.platform) { 14472 $scope.order.platform = $scope.platforms[0]; 14473 } 14474 14475 refreshTotals(false); 14476 $scope.original = $utils.clone($scope.order); 14477 14478 // refresh products for availability 14479 $scope.getProducts(); 14480 }; 14481 14482 14483 var flag = 0; 14484 var updating = null; 14485 $scope.update = function(order) { 14486 flag++; 14487 14488 var tmp = order; 14489 if (tmp == null) { 14490 tmp = $scope.order; 14491 } 14492 14493 if (updating != null && updating != tmp) { 14494 updateOrder(updating); 14495 updating = null; 14496 } 14497 14498 if (flag > 100 || order != null) { 14499 flag = 0; 14500 updating = null; 14501 updateOrder(tmp); 14502 return; 14503 } 14504 14505 var flag2 = flag; 14506 updating = tmp; 14507 setTimeout(function() { 14508 if (flag2 == flag && updating == tmp) { 14509 flag = 0; 14510 updating = null; 14511 updateOrder(tmp); 14512 } 14513 }, 750); 14514 14515 }; 14516 14517 function updateOrder(tmp) { 14518 14519 var data = $utils.clone(tmp); 14520 delete data.clients; 14521 14522 var loading = (data.id == null || (data.paid != null && $scope.original != null && $scope.original.paid == null)); 14523 $rest.post({ 14524 url: contextPath + "/api/pos.json", 14525 data: data, 14526 loading: loading ? 'generic' : null 14527 }).then(function(o) { 14528 if (tmp == $scope.order) { 14529 if (tmp.id == null) { 14530 // created 14531 $scope.showOrder(o); 14532 } else { 14533 // updated - save last status 14534 $scope.original = $utils.clone($scope.order); 14535 14536 // refresh products for availability 14537 $scope.getProducts(); 14538 } 14539 } else { 14540 // refresh list 14541 $scope.getOrders(); 14542 } 14543 14544 }).catch(function() { 14545 if (tmp == $scope.order) { 14546 // restore original object 14547 $scope.order = $scope.original; 14548 } else { 14549 // refresh list 14550 $scope.getOrders(); 14551 } 14552 }); 14553 14554 } 14555 $scope.remove = function() { 14556 if ($scope.order.id == null) { 14557 $scope.showOrders(); 14558 return; 14559 } 14560 $rest.remove({ 14561 confirmTitle: $translate.instant("msg.remove") + " #" + $scope.order.code, 14562 url: contextPath + "/api/pos/" + $scope.order.id + ".json?force=true", 14563 //successMessage: $translate.instant("msg.removed") 14564 }).then(function(o) { 14565 //console.log('remove', o) 14566 $scope.showOrders(); 14567 }); 14568 } 14569 14570 $scope.getOrders = function() { 14571 14572 if ($utils.isBlank($scope.filter.orders)) { 14573 $scope.filter.orders = 'all'; 14574 } 14575 14576 var url = contextPath + "/api/pos.json?no-projection=true&_limit=200"; 14577 if ($scope.filter.orders == 'to_pay') { 14578 url += "&paid:$exists=false"; 14579 } else if ($scope.filter.orders == 'to_deliver') { 14580 url += "&paid:$exists=true&delivered:$exists=false"; 14581 } else { 14582 // all 14583 } 14584 $storageService.put("_pos_orders", $scope.filter.orders); 14585 14586 var search = $scope.filter.search1; 14587 if (!$utils.isBlank(search)) { 14588 search = search.replace("'", ""); // bug angularjs 14589 search = $utils.removeDiacritics(search.trim().toLowerCase()); 14590 } 14591 if (!$utils.isBlank(search)) { 14592 url += "&_q=" + search; 14593 } 14594 14595 $rest.get({ 14596 url: url 14597 }).then(function(o) { 14598 $scope.orders = o.list; 14599 }); 14600 } 14601 14602 $scope.getCategories = function() { 14603 $rest.get({ 14604 url: contextPath + "/api/pos/a/categories.json" 14605 }).then(function(o) { 14606 $scope.categories = o.list; 14607 }); 14608 } 14609 14610 var productsMap = {}; 14611 var productsUrl = null; 14612 $scope.getProducts = function(callback) { 14613 14614 var url = contextPath + "/api/pos/a/products.json?_limit=100"; 14615 if ($scope.filter.category != null) { 14616 url += "&categories=" + $scope.filter.category.id + "&"; 14617 } 14618 var search = $scope.filter.search2; 14619 if (!$utils.isBlank(search)) { 14620 search = search.replace("'", ""); // bug angularjs 14621 search = $utils.removeDiacritics(search.trim().toLowerCase()); 14622 } 14623 if (!$utils.isBlank(search)) { 14624 url += "&_q=" + search; 14625 } 14626 14627 if (url == productsUrl && callback == null) { 14628 // skip request 14629 productsUrl = null; 14630 return; 14631 } 14632 productsUrl = url; 14633 14634 $rest.get({ 14635 url: url, 14636 loading: (callback != null) ? 'generic' : null 14637 }).then(function(o) { 14638 $scope.products = o.list; 14639 14640 // save products in cache 14641 o.list.forEach(function(item) { 14642 productsMap[item.id] = item; 14643 14644 var stock = getStock(item); 14645 if (stock > 0 && stock < 3) { 14646 productsUrl = null; // omit skip request 14647 } 14648 }); 14649 14650 if (callback) { 14651 callback(); 14652 } 14653 }); 14654 }; 14655 14656 // products search 14657 $scope.clickCategory = function(category) { 14658 $scope.filter.category = category; 14659 $scope.getProducts(); 14660 } 14661 $scope.cleanSearch1 = function() { 14662 $scope.filter.search1 = ""; 14663 $scope.getOrders(); 14664 } 14665 $scope.cleanSearch2 = function() { 14666 $scope.filter.search2 = ""; 14667 $scope.getProducts(); 14668 } 14669 14670 $scope.addItem = function(product) { 14671 if (!$scope.hasStock(product)) { 14672 return; 14673 } 14674 for (var k in $scope.items) { 14675 var item = $scope.items[k]; 14676 if (item.product && item.product.entity_id == product.id) { 14677 $scope.addQuantity(null, item); 14678 return; 14679 } 14680 } 14681 14682 var priceField = $scope.order.platform && $scope.order.platform.priceField ? $scope.order.platform.priceField : null; 14683 var price = priceField && product[priceField] != null ? product[priceField] : product.geo_buy.price; 14684 14685 $scope.items.push({ 14686 id: '' + Date.now(), // for inner entity list 14687 name: $entity.displayColumn(product), 14688 quantity: 1, 14689 price: price, 14690 tax: product.geo_buy.tax, // TODO 14691 amount: price, 14692 product: { 14693 entity: product.entity, 14694 entity_id: product.id 14695 } 14696 }); 14697 14698 $angular.apply($scope, function() { 14699 if ($scope.items == $scope.order.clients[$scope.order.clients.length-1]) { 14700 // is last scroll down 14701 var objDiv = document.getElementById("preorder-body"); 14702 if (objDiv != null) { 14703 objDiv.scrollTop = objDiv.scrollHeight; 14704 } 14705 } 14706 refreshTotals(true); 14707 }); 14708 14709 }; 14710 $scope.removeItem = function(list, item) { 14711 $utils.removeFromArray(list, item); 14712 if (list.length == 0 && $scope.order.clients.length > 1) { 14713 $utils.removeFromArray($scope.order.clients, list); 14714 $scope.items = $scope.order.clients[0]; 14715 } 14716 refreshTotals(true); 14717 }; 14718 14719 $scope.selectClient = function(client) { 14720 $scope.items = client; 14721 }; 14722 14723 $scope.setPlatform = function(platform) { 14724 if ($scope.order.platform == platform) return; 14725 $scope.order.platform = platform; 14726 14727 // update prices of existing items 14728 var priceField = platform.priceField; 14729 for (var k in $scope.order.items) { 14730 var item = $scope.order.items[k]; 14731 if (item.product) { 14732 var product = productsMap[item.product.entity_id]; 14733 if (product) { 14734 var newPrice = priceField && product[priceField] != null ? product[priceField] : product.geo_buy.price; 14735 item.price = newPrice; 14736 } 14737 } 14738 } 14739 refreshTotals(true); 14740 }; 14741 14742 $scope.addClient = function() { 14743 var list = $scope.order.clients; 14744 if (list.length > 0 && list[list.length - 1].length == 0) { 14745 return; 14746 } 14747 $scope.items = []; 14748 $scope.order.clients.push($scope.items); 14749 }; 14750 $scope.addDiscount = function() { 14751 $angular.openModal("panel-form", { 14752 title: $translate.instant('msg.discount'), 14753 items: [ 14754 { type: 'number', name: 'discount', label: $translate.instant('msg.discount') } 14755 ], 14756 successFunction: function(o) { 14757 if (o.discount > 0) { 14758 $scope.items.push({ 14759 id: '' + Date.now(), // for inner entity list 14760 discount: o.discount 14761 });
14762 refreshTotals(true); 14763 } 14764 return null; 14765 } 14766 }); 14767 }; 14768 $scope.addNote = function() { 14769 $angular.openModal("panel-form", { 14770 title: $translate.instant('msg.note'), 14771 items: [ 14772 { type: 'text', name: 'note', label: $translate.instant('msg.note') } 14773 ], 14774 successFunction: function(o) { 14775 if (!$utils.isBlank(o.note)) { 14776 $scope.items.push({ 14777 id: '' + Date.now(), // for inner entity list 14778 note: o.note 14779 }); 14780 refreshTotals(true); 14781 } 14782 return null; 14783 } 14784 }); 14785 }; 14786 14787 $scope.hasMoreStock = function(item) { 14788 if (item.product) { 14789 var product = productsMap[item.product.entity_id]; 14790 if (product) { 14791 return $scope.hasStock(product); 14792 } 14793 } 14794 return true; 14795 }; 14796 14797 $scope.addQuantity = function(e, item) { 14798 $utils.preventDefault(e); 14799 14800 if (!$scope.hasMoreStock(item)) { 14801 return; 14802 } 14803 14804 if (item.quantity == null) item.quantity = 0; 14805 item.quantity++; 14806 refreshTotals(true); 14807 }; 14808 14809 $scope.removeQuantity = function(e, list, item) { 14810 $utils.preventDefault(e); 14811 14812 if (item.quantity == null || item.quantity === 1) { 14813 $scope.removeItem(list, item); 14814 return; 14815 } 14816 item.quantity--; 14817 refreshTotals(true); 14818 }; 14819 14820 $scope.refreshQuantity = function() { 14821 refreshTotals(true); 14822 }; 14823 14824 function parseClients(order) { 14825 var clients = [[]]; 14826 for (var k in order.items) { 14827 var item = order.items[k]; 14828 if (item.client == null || item.client == 0) { 14829 item.client = 1; 14830 } 14831 var list = clients[item.client-1]; 14832 if (list == null) { 14833 list = []; 14834 clients.push(list); 14835 } 14836 list.push(item); 14837 } 14838 order.clients = clients; 14839 } 14840 14841 function refreshTotals(update) { 14842 14843 if ($scope.order.clients == null) { 14844 // parse items to clients 14845 parseClients($scope.order); 14846 } 14847 14848 if (!update) { 14849 $scope.items = $scope.order.clients[0]; 14850 } 14851 14852 // parse clients to items 14853 var items = []; 14854 $scope.order.clients.forEach(function(list, index) { 14855 list.forEach(function(item) { 14856 item.client = index + 1; 14857 items.push(item); 14858 }); 14859 }); 14860 $scope.order.items = items; 14861 14862 // parse total 14863 var total = 0; 14864 var tax = 0; 14865 for (var k in $scope.order.items) { 14866 var item = $scope.order.items[k]; 14867 if (item.note != null) { 14868 continue; 14869 } 14870 if (item.price) { 14871 var amount = item.price * item.quantity; 14872 item.amount = amount; 14873 total += amount; 14874 } 14875 if (item.discount != null) { 14876 item.amount = -item.discount; 14877 total -= item.discount; 14878 } 14879 if (item.tax) { 14880 tax += (item.tax * item.quantity); 14881 } 14882 } 14883 $scope.order.base = total; 14884 $scope.order.tax = tax; 14885 $scope.order.amount = total + tax; 14886 14887 if (update) { 14888 $scope.update(); 14889 } 14890 } 14891 14892 $scope.showStatus = function(order) { 14893 var list = []; 14894 if (order.paid) { 14895 if (order.payment) { 14896 list.push($translate.instant("msg.paid.web")); 14897 } 14898 if (!$utils.isBlank(order.pay_type)) { 14899 list.push($utils.toText(order.pay_type)); 14900 } 14901 } 14902 if (order.delivery_method != null && !$utils.isBlank(order.delivery_method.type)) { 14903 list.push(order.delivery_method.type); 14904 } 14905 if (order.delivered) { 14906 list.push("<b>" + $translate.instant("msg.delivered") + "</b>"); 14907 } 14908 return $utils.join(list, "<br>"); 14909 } 14910 14911 $scope.hasStock = function(item) { 14912 return getStock(item) > 0; 14913 }; 14914 function getStock(item) { 14915 return item.geo_buy != null ? item.geo_buy.stock : 0; 14916 } 14917 14918 $scope.checkout = function() { 14919 14920 $scope.getProducts(function() { 14921 14922 if ($scope.order == null) { 14923 return; 14924 } 14925 14926 // validate stock 14927 for (var k in $scope.order.items) { 14928 var item = $scope.order.items[k]; 14929 if (item.product) { 14930 var product = productsMap[item.product.entity_id]; 14931 if (getStock(product) < 0) { 14932 $utils.floatingError("No hay suficiente stock de " + $entity.displayColumnHtml(product)); // TODO translate 14933 return; 14934 } 14935 } 14936 } 14937 14938 if ($scope.payTypeList.length > 0) { 14939 $scope.order.pay_type = $scope.payTypeList[0]; 14940 } 14941 $scope.order.paid = new Date().getTime(); 14942
14943 $scope.update(); 14944 }); 14945 14946 14947 }; 14948 $scope.payType = function(e, type) { 14949 $utils.preventDefault(e); 14950 14951 if ($scope.order.pay_type == type) { 14952 $scope.order.pay_type = null; 14953 $scope.order.paid = null; 14954 } else { 14955 $scope.order.pay_type = type; 14956 } 14957 14958 $scope.update(); 14959 }; 14960 $scope.deliver = function(e, order) { 14961 $utils.preventDefault(e); 14962 14963 if (order.delivered) { 14964 order.delivered = null; 14965 } else { 14966 order.delivered = new Date().getTime(); 14967 } 14968 14969 $scope.update(order); 14970 }; 14971 14972 $scope.print = function() { 14973 var template = $templateCache.get("web-pos-print.html"); 14974 var now = new Date().getTime(); 14975 var printScope = angular.extend($rootScope.$new(), { order:$scope.order, now:now }); 14976 var element = $compile($('<div>' + template + '</div>'))(printScope); 14977 $angular.apply(printScope, function() { 14978 try { 14979 var html = element.html(); 14980 $utils.printHtml(html, false); 14981 printScope.$destroy(); // To avoid memory leaks from scope create by $rootScope.$new() 14982 } catch (e) { 14983 $init.logError(e); 14984 } 14985 }) 14986 }; 14987 14988 // init 14989 $scope.showOrders(); 14990 $scope.getCategories(); 14991 14992 } 14993 14994})(); 14995 14996//// File web-orders.js //// 14997(function() { 14998 14999 $angular.controllers['web-orders'] = function($rootScope, $scope, $translate) { 15000 $angular.preparePage(); 15001 $angular.contentScope = $scope; 15002 15003 $scope.title = ""; 15004 $scope.setTitle = function() { 15005 $scope.title = $translate.instant("msg.orders"); 15006 }; 15007 $scope.setTitle(); 15008 15009 $scope.model = { 15010 orders: [] 15011 }; 15012 $rest.get({ 15013 skipHideLoading: true, 15014 loading: "generic", 15015 url: contextPath + "/www/orders.json" 15016 }).then(function(o) { 15017 $scope.model.orders = o.orders; 15018 15019 $angular.apply($scope, function() { 15020 $angular.ready = true; 15021 }); 15022 }); 15023 } 15024})(); 15025 15026//// File web-bookings.js //// 15027(function() { 15028 15029 $angular.controllers['web-bookings'] = function($rootScope, $scope, $translate) { 15030 $angular.preparePage(); 15031 $angular.contentScope = $scope; 15032 15033 $scope.title = ""; 15034 $scope.setTitle = function() { 15035 $scope.title = $translate.instant("msg.bookings"); 15036 }; 15037 $scope.setTitle(); 15038 15039 $scope.model = { 15040 items: [] 15041 }; 15042 $rest.get({ 15043 skipHideLoading: true, 15044 loading: "generic", 15045 url: contextPath + "/www/booking.json" 15046 }).then(function(o) { 15047 $scope.model.items = o.items; 15048 15049 $angular.apply($scope, function() { 15050 $angular.ready = true; 15051 }); 15052 }); 15053 } 15054})(); 15055 15056//// File web-select.js //// 15057(function() { 15058 15059 15060 $angular.controllers['web-select'] = function($rootScope, $scope, $routeParams, $translate, $window, $document, $location) { 15061 $angular.preparePage({ resetBacks:true, buttonsRight:"web-select-buttons.html" }); 15062 $angular.contentScope = $scope; 15063 15064 window.location.href = contextPath + "/admin" 15065 15066 /* 15067 if (!$user.isSuper()) { 15068 window.location.href = contextPath + "/admin" 15069 return; 15070 } 15071 15072 $scope.withDomains = true; 15073 $scope.toggleWithDomains = function() { 15074 $scope.withDomains = !$scope.withDomains; 15075 $scope.refresh(); 15076 } 15077 15078 $scope.list = []; 15079 $scope.refresh = function() { 15080 15081 var url = contextPath + "/www/geo/instance.json?_paginate=false"; 15082 if ($scope.withDomains) { 15083 url += "&has-domain=true"; 15084 } 15085 15086 $rest.get({ 15087 skipHideLoading: true, 15088 loading: "generic", 15089 url: url 15090 }).then(function(o) { 15091 15092 var isDev = location.host.indexOf('localhost') !== -1; 15093 15094 for (var k in o.list) { 15095 var item = o.list[k]; 15096 if (!isDev && $scope.withDomains && item.domains && item.domains.length > 0) { 15097 item.url = "https://" + item.domains[0]; 15098 continue; 15099 } 15100 item.url = "home/" + item.id; 15101 } 15102 15103 $scope.list = o.list; 15104 }); 15105 }; 15106 $scope.refresh(); 15107 */ 15108 15109 } 15110 15111})(); 15112 15113//// File web-order.js //// 15114(function() { 15115 15116 $angular.controllers['web-order'] = function($rootScope, $scope, $routeParams, $translate, $uibModal, $window, $document, $location) { 15117 $angular.preparePage({buttonsRight: "web-order-buttons.html"}); 15118 $angular.contentScope = $scope; 15119 15120 $scope.title = ""; 15121 $scope.setTitle = function() { 15122 $scope.title = $translate.instant("msg.order"); 15123 }; 15124 $scope.setTitle(); 15125 15126 $scope.showIsNewMessage = $location.search().isNew; 15127 $location.search('isNew', null).replace(); 15128 $scope.closeIsNewMessage = function() { 15129 $scope.showIsNewMessage = false;
15130 }; 15131 15132 var pathToOrder = "/www/orders/" + $routeParams.id + ".json"; 15133 if (!$user.isLogged()) { 15134 var code = $location.search().code; 15135 if (code) { 15136 pathToOrder = "/www/orders-public/" + $routeParams.id + ".json?code=" + code; 15137 } else { 15138 $angular.goLogin(); 15139 return; 15140 } 15141 } 15142 $rest.get({ 15143 skipHideLoading: true, 15144 loading: "generic", 15145 url: contextPath + pathToOrder 15146 }).then(function(order) { 15147 $scope.model = order; 15148 15149 var deliveryMethod = order.delivery_method; 15150 if (deliveryMethod && deliveryMethod.extra_data && deliveryMethod.extra_data_entity) { 15151 $scope.deliveryMethodFormEntity = $entity.getEntity(deliveryMethod.extra_data_entity); 15152 } 15153 15154 $angular.apply($scope, function() { 15155 $angular.ready = true; 15156 }); 15157 }); 15158 15159 $scope.clickItem = function($event, item) { 15160 $utils.preventDefault($event); 15161 var url = $angular.rootScope.getItemLinkBy(item.object); 15162 $location.path(url); 15163 }; 15164 } 15165 15166})(); 15167 15168//// File web-item.js //// 15169(function() { 15170 15171 $angular.controllers['web-item'] = function($rootScope, $scope, $sce, $routeParams, $translate, $location, $window, NgMap, geolocationService) { 15172 $angular.preparePage({title: '', buttonsRight: "web-item-buttons.html"}); 15173 $angular.contentScope = $scope; 15174 $angular.menuScope.selectedPage = ""; 15175 $scope.entity = $routeParams.entity; 15176 $scope.entityId = $routeParams.entityId; 15177 $angular.currentRoute += " " + $angular.currentRoute+"-"+$scope.entity; 15178 15179 if ($entity.isGeoUser($scope.entity) && !$user.isLogged()) { 15180 $angular.tmpPath = $location.path(); 15181 $angular.goLogin(); 15182 return; 15183 } 15184 15185 if ($scope.entityId == "new") { 15186 $scope.entityId = null; 15187 $scope.isNew = true; 15188 } 15189 15190 $scope.meta = null; 15191 $scope.model = null; 15192 $scope.isItem = false; 15193 $scope.isForm = false; 15194 $scope.isFormview = false; 15195 15196 // get custom formview id 15197 var search = $location.search(); 15198 if (search && search.form) { 15199 $scope.formId = search.form; 15200 } 15201 15202 // load entity meta 15203 $entity.getEntityForce($scope.entity, function(o){ 15204 $scope.meta = o; 15205 //console.log("meta", $scope.meta) 15206 15207 $scope.haveDocuments = $entity.isAttachDocuments($scope.meta); 15208 if (!$scope.haveDocuments) { 15209 if ($scope.meta && $scope.meta.columns) { 15210 for (var k in $scope.meta.columns) { 15211 var column = $scope.meta.columns[k]; 15212 if (column.type == 'document') { 15213 $scope.haveDocuments = true; 15214 break; 15215 } 15216 } 15217 } 15218 } 15219 15220 if ($entity.isAutoLocation($scope.entity)) { 15221 geolocationService.getCurrentLocation().then(function(location) { 15222 $scope.currentGeoLocation = location; 15223 }); 15224 } 15225 15226 refresh(); 15227 }); 15228 15229 $scope.refresh = function() { 15230 refresh(); 15231 }; 15232 function refresh(callback) { 15233 var url; 15234 if ($utils.isBlank($scope.entityId)) { 15235 url = contextPath + "/www/geo/" + $scope.entity + "/new.json"; 15236 } else { 15237 url = contextPath + '/www/geo/' + $scope.entity + '/' + $scope.entityId + '/edit.json'; 15238 } 15239 if ($scope.formId != null) { 15240 url += "?form=" + $scope.formId; 15241 } 15242 $rest.get({ 15243 skipHideLoading: true, 15244 url: url, 15245 loading: 'generic' 15246 }).then(function(o) { 15247 $scope.model = o; 15248 //console.log("model", $scope.model) 15249 15250 if (!$utils.isBlank($scope.entityId) && $scope.entityId != o.id
15250) { 15251 $scope.entity = o.entity; 15252 $scope.entityId = o.id; 15253 //console.log('updated entity/id ' + o.entity + " " + o.id) 15254 } 15255 15256 $scope.formviews = $utils.setFormviews($scope.formviews, o); 15257 if ($scope.formviews.length > 0) { 15258 for (var k in $scope.formviews) { 15259 var fv = $scope.formviews[k]; 15260 if ($scope.form == null || fv.form.id == $scope.formId) { 15261 $scope.form = fv; 15262 } 15263 } 15264 //console.log($scope.form) 15265 $scope.isFormview = true; 15266 $scope.opts = {}; 15267 $scope.opts.readonly = $scope.form.form.readonly; 15268 15269 } else if ($entity.isGeoForm($scope.entity)) { 15270 $scope.isForm = true; 15271 15272 } else { 15273 $scope.isItem = true; 15274 15275 if (o.geo_media == null) o.geo_media = {}; 15276 if (o.geo_media.images == null) o.geo_media.images = []; 15277 if (o.geo_location == null) o.geo_location = {}; 15278 parseData(o); 15279 $scope.hasShare = navigator.share; 15280 } 15281 15282 // auto fill url params 15283 if ($scope.isForm || $scope.isFormview) { 15284 var search = $location.search(); 15285 if (search) { 15286 for (var k in search) { 15287 var item = search[k]; 15288 //console.log(k, item) 15289 if (!$utils.isBlank(item)) { 15290 if ($entity.getColumn($scope.entity, k) != null) { 15291 if ($scope.form != null) { 15292 $scope.form.data[k] = item; 15293 } else { 15294 $scope.model[k] = item; 15295 } 15296// delete search[k]; 15297// $location.search(search).replace(); 15298 } 15299 } 15300 } 15301 } 15302 15303 NgMap.getMap().then(function (map) { // TODO only return first map - use getMap(id) 15304 if (map.getZoom() > 15) { 15305 map.setZoom(15); 15306 } 15307 }); 15308 } 15309 15310 $angular.apply($scope, function() { 15311 $angular.ready = true; 15312 }); 15313 15314 if (callback) { 15315 callback(); 15316 } 15317 }); 15318 } 15319 15320 var webForm; 15321 var webFormCallback; 15322 $scope.initForm = function(form) { 15323 webForm = form; 15324 } 15325 $scope.saveForm = function(callback) { 15326 webFormCallback = callback; 15327 setTimeout(function(){ 15328 $("#webForm")[0].requestSubmit(); // to validate form 15329 }, 100); 15330 } 15331 $scope.submitForm = function(e) { 15332 $utils.preventDefault(e); 15333 15334 if (!$utils.validateForm(webForm.webForm)) { 15335 return; 15336 } 15337 15338 var model = $scope.model; 15339 var isCreate = $scope.model.id == null; 15340 15341 if ($scope.isFormview) { 15342 isCreate = $scope.form.data.id == null; 15343 model = { 15344 id: $scope.form.data.id, 15345 formId: $scope.form.form.id, 15346 data: $scope.form.data 15347 }; 15348 } 15349 15350 if ($scope.currentGeoLocation) { 15351 model.geo_location = { 15352 latitude: $scope.currentGeoLocation.latitude, 15353 longitude: $scope.currentGeoLocation.longitude 15354 }; 15355 } 15356 15357 $rest.post({ 15358 url: contextPath + "/www/geo/" + $scope.entity + ".json", 15359 data: model, 15360 loading: "generic" 15361 }).then(function(data) { 15362 15363 if (isCreate) { 15364 $scope.entityId = data.id; 15365 if ($scope.isFormview) { 15366 $scope.form.data.id = data.id; 15367 } else { 15368 $scope.model.id = data.id; 15369 } 15370 } 15371 15372 $utils.postSave(model, data, isCreate, webFormCallback, refresh); 15373 }); 15374 }; 15375 15376 $scope.resetForm = function() { 15377 $scope.entityId = null; 15378 refresh(); 15379 }; 15380 15381 // attach documents 15382 $scope.openUploadFile = function(e) { 15383 $utils.preventDefault(e); 15384 $('#webFormAttachments input[type="file"]').trigger('click'); 15385 }; 15386 15387 $scope.uploadFile = function(files) { 15388 if (files.length === 0) { 15389 return; 15390 } 15391 var file = files[0]; 15392 var reader = new FileReader(); 15393 reader.onload = function(event) { 15394 $rest.post({ 15395 url: contextPath + '/www/media/a/createBase64.json', 15396 data: { 15397 fileBase64: event.target.result.split(',')[1], 15398 fileName: file.name, 15399 entity: $scope.entity, 15400 entityId: $scope.entityId 15401 }, 15402 loading: 'generic', 15403 successMessage: $translate.instant('msg.saved') 15404 }).then(function() { 15405 refresh(); 15406 }); 15407 }; 15408 reader.readAsDataURL(file); 15409 }; 15410 15411 $scope.removeFile = function(item) { 15412 $rest.remove({ 15413 url: contextPath + '/www/media/' + item.id + '.json', 15414 loading: 'generic', 15415 confirmTitle: $translate.instant('msg.remove'), 15416 successMessage: $translate.instant('msg.removed') 15417 }).then(function() { 15418 refresh();
15419 }); 15420 }; 15421 15422 15423 // old web-item 15424 var hasYoutube = false; 15425 var hasMedia = false; 15426 var data1 = []; 15427 var dataRight = []; 15428 15429 function parseData(model) { 15430 15431 hasMedia = false; 15432 hasYoutube = false; 15433 data1 = []; 15434 dataRight = []; 15435 15436 // buy 15437 if ($cart.isCartItem(model)) { 15438 addItem({ 15439 force: true, 15440 type: 'buy', 15441 stock: $cart.getStock(model) 15442 }); 15443 } 15444 15445 if ($entity.isGeoLocation($scope.entity)) { 15446 15447 if (model.geo_location == null) { 15448 model.geo_location = {}; 15449 } 15450 15451 // address 15452 if (model.geo_location.address) { 15453 addItem({ 15454 type: 'text', 15455 name: 'address', 15456 label: $translate.instant("msg.address"), 15457 value: $utils.parse(model.geo_location.address), 15458 from: 'geo_location' 15459 }); 15460 } 15461 15462 // map 15463 var lat; 15464 var lng; 15465 var zoom; 15466 var label; 15467 if (model.geo_fence) { 15468 lat = model.geo_fence.center_latitude; 15469 lng = model.geo_fence.center_longitude; 15470 zoom = model.geo_fence.default_zoom; 15471 } 15472 if (!lat || !lng) { 15473 lat = model.geo_location.latitude; 15474 lng = model.geo_location.longitude; 15475 } 15476 if (model.geo_location.address == null) { 15477 label = $translate.instant("msg.address"); 15478 } 15479 if (lat && lng) { 15480 addItem({ 15481 force: true, 15482 label: label, 15483 type: 'map', 15484 latitude: lat, 15485 longitude: lng, 15486 zoom: zoom ? zoom : 15 15487 }); 15488 } 15489 } 15490 15491 // timetables 15492 if ($entity.isGeoLocation($scope.entity) && !$utils.isBlank(model.geo_location.timetables)) { 15493 addItem({ 15494 type: 'html', 15495 name: 'timetables', 15496 label: $utils.parseGeoTranslation('timetables'), 15497 value: getTimeTables(model.geo_location.timetables) 15498 }); 15499 } 15500 15501 // schedule 15502 if ($entity.isGeoSchedule($scope.entity) && model.geo_schedule) { 15503 var geoScheduleBooking = model.geo_schedule.booking; 15504 if (geoScheduleBooking && geoScheduleBooking.enabled) { 15505 addItem({ 15506 type: 'booking', 15507 force: true, 15508 bookableObject: model 15509 }); 15510 } else { 15511 var value = $utils.printScheduledDates(model, 10); 15512 if (!$utils.isBlank(value)) { 15513 addItem({ 15514 type: 'html', 15515 name: 'schedule', 15516 label: $utils.parseGeoTranslation('schedules'), 15517 value: value 15518 }); 15519 } 15520 } 15521 } 15522 15523// // average time TODO with add to agenda?? 15524// if (model.geo_smart_rate && model.geo_smart_rate.average_time > 0) { 15525// addGroup({ 15526// type: 'text', 15527// name: 'average_time', 15528// label: $translate.instant("msg.averageTime"), 15529// value: model.geo_smart_rate.average_time + "m", 15530// from: 'geo_smart_rate' 15531// }); 15532// } 15533 15534 // columns 15535 if ($scope.meta && $scope.meta.columns) { 15536 var columns = $scope.meta.columns; 15537 for (var key in columns) { 15538 var column = columns[key]; 15539 addColumn(model, column); 15540 } 15541 } 15542 15543 // properties 15544 var props = model.geo_properties; 15545 if (props) { 15546 for (var key in props) { 15547 addProperty(model, props[key]); 15548 } 15549 } 15550 15551 // images 15552 if (!hasMedia && !hasYoutube) { 15553 var imageList = $utils.getSorted(model.geo_media.images, '_order_num'); 15554 if (imageList.length > 0) { 15555 addItem({ 15556 force: true, 15557 big: true, 15558 type: 'images', 15559 medias: imageList 15560 }, true); 15561 } 15562 } 15563 15564 if (hasYoutube && (typeof YT == 'undefined')) { 15565 require(["https://www.youtube.com/iframe_api"], function(o) { 15566 parseDataEnd(); 15567 }); 15568 return; 15569 } 15570 parseDataEnd(); 15571 } 15572 15573 function parseDataEnd() { 15574 if (data1.length === 0) { 15575 data1 = dataRight; 15576 dataRight = []; 15577 } 15578 $scope.data = data1; 15579 $scope.dataRight = dataRight; 15580 $angular.apply($scope); 15581 } 15582 15583 function addProperty(model, prop) { 15584 if ($utils.isTrue(prop.hidden)) { 15585 return; 15586 } 15587 if (prop.type == "boolean") { 15588 return; 15589 } 15590 addItem({ 15591 type: "text", 15592 typeColumn: prop.type, 15593 name: prop.name, 15594 label: prop.name,//$utils.parseGeoTranslation(name, model) 15595 value: $utils.parse(prop.value) 15596 }); 15597 } 15598 15599 function addColumn(model, column, innerEntity) { 15600 if (model == null) { 15601 return; 15602 } 15603 if (column.hidden || column.user) { 15604 return; 15605 } 15606 var def = $utils.isTrue(column.default); 15607 if (def) { 15608 return; 15609 } 15610 15611 var name = column.name; 15612 var type = column.type; 15613 var param = column.param; 15614 var html = $utils.isTrue(column.html); 15615 var nolabel = $utils.isTrue(column.nolabel); 15616 var value = model[name]; 15617 15618 var pathToTranslations = 'geo_translations'; 15619 if (innerEntity) { 15620 pathToTranslations += '.inner_entities.' + innerEntity; 15621 } 15622 15623 var item = { 15624 type: (html ? 'html' : 'text'), 15625 name: name, 15626 label: nolabel ? null : $utils.parseGeoTranslation(name, null, null, pathToTranslations), 15627 typeColumn: type 15628 }; 15629 //console.log(type + ' - ' + name) 15630 15631 switch (type) { 15632 15633 case "any": 15634 case "cron": 15635 case "json": 15636 case "css": 15637 return; 15638 15639 case "boolean": 15640 case "boolean_int": 15641 item.type = 'text'; 15642 if ($utils.isTrue(value)) { 15643 item.value = "\u2714"; 15644 //} else { 15645 // item.value = "\u2717"; 15646 } 15647 break; 15648 15649 case "button": 15650 item.click = function(e) { 15651 $angular.log("web item button not implemented"); 15652 } 15653 case "link": 15654 item.type = type; 15655 item.value = $rootScope.columnButtonHref(column, $scope.model); 15656 item.blank = $rootScope.isColumnLinkBlank(column, $scope.model); 15657 item.icon = column.icon ? 'www/media/' + column.icon + '.img' : null; 15658 break; 15659 15660 case "entity": 15661 case "list": 15662 item.value = value; 15663 break; 15664 15665 case "inner_entity": 15666 case "inner_entity_list": 15667 if (!$utils.isBlank(column.inner_entity) && $scope.meta && $scope.meta.inner_entities) { 15668 var columns = $entity.getColumnsInner($scope.entity, column); 15669 if (columns && columns.length > 0) { 15670 15671 if (!$utils.isArray(value)) { 15672 value = [value]; 15673 } 15674 for (var k in value) { 15675 var it = value[k]; 15676 for (var key in columns) { 15677 addColumn(it, columns[key], column.inner_entity); 15678 } 15679 } 15680 } 15681 } 15682 return; 15683 15684 case "tags": 15685 case "string_list": 15686 if (value && $utils.isArray(value)) { 15687 item.value = value.join(", "); 15688 } else { 15689 item.value = value; 15690 } 15691 break; 15692 15693 case "formula": 15694 if (column.formula && column.formula.startsWith('relation')) { 15695 item.type = "list"; 15696 item.value = value; 15697 } else { 15698 item.value = $entity.displayColumn(model, column); 15699 } 15700 break; 15701 15702 case "select": 15703 case "enum": 15704 item.value = $utils.parseGeoTranslation(value, null, null, pathToTranslations + '.' + column.name + '$options'); 15705 break; 15706 15707 case "enum_list": 15708 item.type = 'text_list'; 15709 if (Array.isArray(value)) { 15710 item.value = value.map(function(val) { 15711 return $utils.parseGeoTranslation(val, null, null, pathToTranslations + '.' + column.name + '$options'); 15712 });
15713 } 15714 break; 15715 15716 case "image": 15717 var images = []; 15718 if (value && model.geo_media && model.geo_media.images) { 15719 (Array.isArray(value) ? value : [value]).forEach(function(mediaId) { 15720 var image = mediaId ? model.geo_media.images[mediaId] : null; 15721 if (image) { 15722 images.push(image); 15723 } 15724 }); 15725 } 15726 if (images.length !== 0) { 15727 hasMedia = true; 15728 addItem({ 15729 label: item.label, 15730 force: true, 15731 type: 'images', 15732 medias: images 15733 }); 15734 } 15735 return; 15736 15737 case "audio": 15738 var audios = []; 15739 if (value && model.geo_media && model.geo_media.audio) { 15740 (Array.isArray(value) ? value : [value]).forEach(function(mediaId) { 15741 var audio = mediaId ? model.geo_media.audio[mediaId] : null; 15742 if (audio) { 15743 audios.push({ 15744 name: audio.name ? audio.name : mediaId, 15745 url: 'www/media/' + mediaId + '.audio' 15746 }); 15747 } 15748 }); 15749 } 15750 if (audios.length !== 0) { 15751 hasMedia = true; 15752 addItem({ 15753 label: item.label, 15754 typeColumn: 'audio', 15755 big: audios.length > 1, 15756 type: audios.length === 1 ? 'audio' : 'audio-playlist', 15757 value: audios[0].url, 15758 medias: audios 15759 }); 15760 } 15761 return; 15762 15763 case "video": 15764 var ownVideos = []; 15765 var youtubeVideos = []; 15766 if (value && model.geo_media && model.geo_media.video) { 15767 var videos = []; 15768 if (Array.isArray(value)) { 15769 videos = value; 15770 } else { 15771 videos.push(value); 15772 } 15773 videos.forEach(function(mediaId) { 15774 var video = mediaId ? model.geo_media.video[mediaId] : null; 15775 if (video) { 15776 if (video.extension !== 'youtube') { 15777 ownVideos.push({ 15778 name: video.name ? video.name : mediaId, 15779 url: 'www/media/' + mediaId + '.video' 15780 }); 15781 } else if (video.source_media_url) { 15782 youtubeVideos.push({ 15783 name: video.name ? video.name : video.source_media_url, 15784 url: video.source_media_url 15785 }); 15786 } 15787 } 15788 }); 15789 } 15790 if (ownVideos.length !== 0) { 15791 hasMedia = true; 15792 addItem({ 15793 label: item.label, 15794 typeColumn: 'video', 15795 big: true, 15796 type: ownVideos.length === 1 ? 'video' : 'video-playlist', 15797 value: ownVideos[0].url, 15798 medias: ownVideos 15799 }); 15800 } 15801 if (youtubeVideos.length !== 0) { 15802 hasYoutube = true; 15803 addItem({ 15804 label: item.label, 15805 typeColumn: 'video', 15806 big: true, 15807 type: youtubeVideos.length === 1 ? 'youtube' : 'youtube-playlist', 15808 value: youtubeVideos[0].url, 15809 medias: youtubeVideos 15810 }); 15811 } 15812 return; 15813 15814 case "document": 15815 if (value && model.geo_media && model.geo_media.others) { 15816 var docs = []; 15817 if (Array.isArray(value)) { 15818 docs = value; 15819 } else { 15820 docs.push(value); 15821 } 15822 var ivalue = ""; 15823 docs.forEach(function(mediaId) { 15824 var doc = model.geo_media.others[mediaId]; 15825 if (doc) { 15826 ivalue += '<a target="_blank" href="' + contextPath + '/www/media/' + mediaId + '.' + doc.extension +'">' + 15827 doc.name + '.' + doc.extension + '</a>'; 15828 } 15829 }); 15830 if (ivalue != "") { 15831 item.type = 'html'; 15832 item.value = ivalue; 15833 } 15834 } 15835 break; 15836 15837 case 'chart': 15838 if (column.datamixer) { 15839 addItem({ 15840 big: true, 15841 force: true, 15842 type: 'chart', 15843 datamixer: column.datamixer 15844 }); 15845 } 15846 return; 15847 15848 default: 15849 item.value = $entity.displayColumn(model, column, html); 15850 break; 15851 } 15852 15853 addItem(item); 15854 } 15855 15856 function addItem(item, addToFirst) { 15857 15858 if (item.typeColumn === 'section') { 15859 item.type = "section"; 15860 15861 } else if (item.typeColumn === 'message') { 15862 item.value = item.label; 15863 item.label = null; 15864 15865 } else if (item.typeColumn !== 'video') { 15866 15867 if (item.value && (typeof item.value == 'string') && item.value.startsWith("http")) { 15868 item.type = "link"; 15869 15870 if (item.value.contains("youtube.com")) { 15871 item.type = "youtube"; 15872 item.big = true; 15873 addToFirst = true; 15874 hasYoutube = true; 15875 } 15876 } 15877 15878 if (!$utils.isTrue(item.force) && $utils.isBlank(item.value)) { 15879 return; 15880 } 15881 15882 if (item.typeColumn === 'entity') { 15883 if (typeof item.value == 'string') { 15884 return; // can be instances 15885 } 15886 item.type = 'list'; 15887 item.value = [item.value]; 15888 } 15889 if (item.typeColumn === 'list') { 15890 item.type = 'list'; 15891 } 15892 if (item.type === 'list') { 15893 // validate list 15894 var l = item.value; 15895 var l2 = []; 15896 for (var k in l) { 15897 var o = l[k]; 15898 if ($entity.isItemValid($scope.entity, o)) { 15899 l2.push(o); 15900 //console.log(o); 15901 } 15902 } 15903 if (l2.length === 0) { 15904 return; 15905 } 15906 if (l2.length > 1) { 15907 item.big = true; 15908 } 15909 item.value = l2; 15910 15911 var mapPoints = l2.map(function(listItem) { 15912 var geoLocation = listItem.geo_location; 15913 if (geoLocation != null && !!geoLocation.latitude && !!geoLocation.longitude) { 15914 return { 15915 title: $entity.displayColumn(listItem), 15916 latitude: geoLocation.latitude, 15917 longitude: geoLocation.longitude 15918 }; 15919 } 15920 return null; 15921 }).filter(function(mapPoint) { 15922 return !!mapPoint; 15923 });
15924 if (mapPoints.length > 0) { 15925 addItem({ 15926 force: true, 15927 label: item.label, 15928 type: 'map', 15929 points: mapPoints 15930 }); 15931 } 15932 } 15933 } 15934 15935 if (item.type === "html" || item.type === "text") { 15936 if (item.value && item.value.length > 800) { 15937 item.big = true; 15938 } 15939 } else if (item.type === "boolean" || item.type === "boolean_int") { 15940 if (item.value) { 15941 item.value = "*"; 15942 } else { 15943 item.value = ""; 15944 } 15945 } 15946 15947 var isBig = $utils.isTrue(item.big); 15948 if (isBig || !$utils.isScreenLarge) { 15949 if (addToFirst) { 15950 data1.unshift(item); 15951 } else { 15952 data1.push(item); 15953 } 15954 } else { 15955 if (addToFirst) { 15956 dataRight.unshift(item); 15957 } else { 15958 dataRight.push(item); 15959 } 15960 } 15961 } 15962 15963 function getTimeTables(list) { 15964 var result = "<table>"; 15965 if (list) { 15966 var $translate = $angular.get("$translate"); 15967 for (var i in list) { 15968 var item = list[i]; 15969 if (item && item.day) { 15970 result += "<tr><td>" + $translate.instant($constants.daysList[item.day]) 15971 + ": </td><td>" + item.time_from + " - " + item.time_to + "</td></tr>"; 15972 } 15973 } 15974 } 15975 result += "</table>"; 15976 return result; 15977 } 15978 15979 // share 15980 $scope.share = function() { 15981 var link = "" + window.location.href; 15982 navigator.share({ 15983 title: 'Share', 15984 url: link 15985 }).then(function() { 15986 //console.log('Thanks for sharing!'); 15987 }); 15988 }; 15989 } 15990})(); 15991 15992//// File geolocation.service.js //// 15993(function() { 15994 'use strict'; 15995 15996 $angular.factories['geolocationService'] = function($window, $q) { 15997 var currentPosition; 15998 var watching = false; 15999 var service = {}; 16000 16001 service.watchCurrentLocation = function() { 16002 if (!watching) { 16003 if (!$window.navigator.geolocation) { 16004 console.warn('Geolocation not supported.'); 16005 } else { 16006 $window.navigator.geolocation.watchPosition(function(position) { 16007 watching = true; 16008 currentPosition = position ? position.coords : null; 16009 var geoLocationCookie = currentPosition.latitude + ',' + currentPosition.longitude; 16010 $cookiesService.put('geo_location', geoLocationCookie, 1); 16011 }); 16012 } 16013 } 16014 }; 16015 16016 service.getCurrentLocation = function() { 16017 var deferred = $q.defer(); 16018 16019 if (watching && currentPosition) { 16020 deferred.resolve(currentPosition); 16021 } else { 16022 if (!$window.navigator.geolocation) { 16023 deferred.reject('Geolocation not supported.'); 16024 } else { 16025 $window.navigator.geolocation.getCurrentPosition(function(position) { 16026 currentPosition = position ? position.coords : null; 16027 deferred.resolve(currentPosition); 16028 }, function(err) { 16029 deferred.reject(err); 16030 }); 16031 } 16032 } 16033 return deferred.promise; 16034 }; 16035 16036 return service; 16037 }; 16038})(); 16039 16040//// File preferences.js //// 16041(function() { 16042 16043 16044 $angular.controllers['preferences'] = function($scope, $translate) { 16045 $angular.preparePage(); 16046 $angular.contentScope = $scope; 16047 $angular.menuScope.selectedPage = 'preferences'; 16048 16049// $scope.setTitle = function() { 16050// $angular.setTitle($translate.instant("msg.preferences")); 16051// }; 16052// $scope.setTitle(); 16053 16054 $scope.licenses = []; 16055 16056 var path = "/www/license.json"; 16057 $rest.get({ 16058 skipHideLoading: true, 16059 url: contextPath + path + "?instances="+$instance.getId(), 16060 loading: "generic" 16061 }).then(function(o) { 16062 $scope.licenses = o.list; 16063 }); 16064 16065 } 16066 16067})(); 16068 16069//// File logout.js //// 16070(function() { 16071 16072 $angular.controllers['logout'] = function($rootScope, $scope) { 16073 $angular.preparePage(); 16074 $angular.contentScope = $scope; 16075 16076 $rest.get({ 16077 loading: "generic", 16078 url: contextPath + "/log-out?_r=" + new Date().getTime() 16079 }).then(function() { 16080 $user.current = null; 16081 if (!$constants.isWeb) { 16082 $instance.current = null; 16083 } 16084 16085 if ($instance.isMslogin()) { 16086 $cookiesService.remove("ms_access_token"); 16087 $cookiesService.put("instance", $instance.getId(), 1); 16088 window.location.href = "ms/a/logout.go"; 16089 return; 16090 } 16091 16092 $angular.goHome(); 16093 $cart.initCart(); 16094 }); 16095 } 16096})(); 16097 16098//// File debounce.js //// 16099(function() { 16100 'use strict'; 16101 16102 $angular.factories['debounce'] = function($timeout, $q) { 16103 // The service is actually this function, which we call with the func 16104 // that should be debounced and how long to wait in between calls 16105 return function debounce(func, wait, immediate) { 16106 var timeout; 16107 // Create a deferred object that will be resolved when we need to 16108 // actually call the func 16109 var deferred = $q.defer(); 16110 return function() { 16111 var context = this, args = arguments; 16112 var later = function() { 16113 timeout = null; 16114 if (!immediate) {
16115 deferred.resolve(func.apply(context, args)); 16116 deferred = $q.defer(); 16117 } 16118 }; 16119 var callNow = immediate && !timeout; 16120 if (timeout) { 16121 $timeout.cancel(timeout); 16122 } 16123 timeout = $timeout(later, wait); 16124 if (callNow) { 16125 deferred.resolve(func.apply(context, args)); 16126 deferred = $q.defer(); 16127 } 16128 return deferred.promise; 16129 }; 16130 }; 16131 }; 16132})(); 16133 16134//// File not-found.js //// 16135(function() { 16136 16137 16138 $angular.controllers['not-found'] = function($scope, $location, $translate) { 16139 //$angular.preparePage(); 16140 $angular.contentScope = $scope; 16141 $angular.goHome(); 16142 //$utils.showNotFound(); 16143 } 16144 16145})(); 16146 16147//// File login.js //// 16148(function() { 16149 16150 $angular.controllers['login'] = function($scope) { 16151 $angular.preparePage(); 16152 $angular.contentScope = $scope; 16153 } 16154})(); 16155 16156//// File panel-buy.js //// 16157(function() { 16158 16159 $angular.controllers['panel-buy'] = function($uibModalInstance, $scope, params) { 16160 $scope.item = params.item; 16161 $scope.cartItem = { 16162 quantity: params.cartItem ? params.cartItem.quantity : 1, 16163 extraData: params.cartItem ? params.cartItem.extra_data : {} 16164 }; 16165 $scope.ready = false; 16166 16167 $scope.stock = $cart.getStock($scope.item); 16168 16169 var formEntity = $scope.item.geo_buy.form_entity; 16170 if (formEntity && $entity.isGeoForm(formEntity) && $entity.isPermitted(formEntity, 'create')) { 16171 $scope.extraDataEntity = $entity.getEntity(formEntity); 16172 } else { 16173 $scope.ready = true; 16174 } 16175 16176 $scope.onChangeExtraData = function(extraData, isReady) { 16177 $scope.ready = isReady; 16178 $scope.cartItem.extraData = extraData; 16179 }; 16180 16181 $scope.close = function() { 16182 $uibModalInstance.dismiss('cancel'); 16183 }; 16184 16185 $scope.addQuantity = function(item) { 16186 if ($cart.hasStock(item, $scope.cartItem.quantity)) { 16187 $scope.cartItem.quantity++; 16188 } 16189 }; 16190 16191 $scope.removeQuantity = function() { 16192 if ($scope.cartItem.quantity === 1) { 16193 return; 16194 } 16195 $scope.cartItem.quantity--; 16196 }; 16197 16198 $scope.buy = function() { 16199 $cart.addItem($scope.item.entity, $scope.item.id, $scope.cartItem); 16200 if (!$angular.element("#cartAsMenu").hasClass("menu-open")) { 16201 $events.toggleCartAsMenu(); 16202 } 16203 $scope.close(); 16204 }; 16205 } 16206})(); 16207 16208//// File panel-add-instance.js //// 16209(function() { 16210 16211 16212 $angular.controllers['panel-add-instance'] = function($uibModalInstance, $scope, $translate, $http, params) { 16213 16214 $scope.model = {}; 16215 16216 $scope.close = function() { 16217 $uibModalInstance.dismiss('cancel'); 16218 } 16219 16220 $scope.create = function(form) { 16221 if (!$utils.validateForm(form)) { 16222 return; 16223 } 16224 16225 var id = $instance.current.add_subinstance; 16226 16227 var data = { 16228 name: $scope.model.name, 16229 copyContent: true, 16230 copySystem: true 16231 }; 16232 16233 $rest.post({ 16234 loading: "generic", 16235 url: contextPath + "/api/geo-new/instance/" + id + "/copy.json", 16236 data: data, 16237 successMessage: $angular.get("$translate").instant('msg.created') 16238 }).then(function(o) { 16239 $scope.close(); 16240 $instance.refresh(); 16241 }); 16242 16243 } 16244 16245 } 16246 16247})(); 16248 16249//// File panel-edit-media.js //// 16250(function () { 16251 16252 $angular.controllers['panel-edit-media'] = function ($uibModalInstance, $scope, $translate, $http, params, $timeout) { 16253 var type = params.type; 16254 16255 $timeout(function () { 16256 $scope.model = params.data; 16257 $scope.model.mediaType = type; 16258 $scope.mediaType = type; 16259 $scope.downloadExtension = type; 16260 if (type === 'images') { 16261 $scope.downloadExtension = 'io'; 16262 } else if (type === 'others') { 16263 $scope.downloadExtension = $scope.model.extension; 16264 } 16265 $scope.mediaI18n = {};
16266 $instance.languages.forEach(function(lang) { 16267 $scope.mediaI18n[lang] = 'loading'; 16268 }); 16269 checkMediaI18n(); 16270 loadAppMedia(); 16271 }); 16272 16273 16274 $scope.close = function () { 16275 $uibModalInstance.dismiss(); 16276 } 16277 16278 $scope.saveMediaInfo = function () { 16279 $rest.put({ 16280 url: contextPath + '/api/media/' + $scope.model.id + '.json', 16281 data: $scope.model, 16282 successMessage: $angular.get("$translate").instant('msg.updated') 16283 }).then(function () { 16284 $uibModalInstance.close(); 16285 }); 16286 }; 16287 16288 $scope.uploadTranslation = function(lang) { 16289 $angular.openModal("panel-add-media", { 16290 entity: $angular.contentScope.entity, 16291 id: $angular.contentScope.entityId, 16292 type: type, 16293 size: 'xl', 16294 mediaId: $scope.model.id, 16295 language: lang 16296 }).then(function() { 16297 checkMediaI18n(); 16298 }); 16299 }; 16300 16301 $scope.removeTranslation = function(lang) { 16302 $rest.remove({ 16303 url: contextPath + '/api/media/' + $scope.model.id + '.json?language=' + lang, 16304 loading: "generic", 16305 confirmTitle: $angular.get("$translate").instant("msg.remove"), 16306 successMessage: $angular.get("$translate").instant('msg.removed') 16307 }).then(function() { 16308 checkMediaI18n(); 16309 }); 16310 }; 16311 16312 function checkMediaI18n() { 16313 $scope.rand = Math.random();
16314 $instance.languages.forEach(function(lang) { 16315 $rest.get({ 16316 url: contextPath + '/api/media/' + $scope.model.id + '.json?language=' + lang, 16317 showError: false 16318 }).then(function () { 16319 $scope.mediaI18n[lang] = 'found'; 16320 }).catch(function () { 16321 $scope.mediaI18n[lang] = 'not-found'; 16322 }); 16323 }); 16324 } 16325 16326 function loadAppMedia() { 16327 $rest.get({ 16328 url: contextPath + '/api/media/' + $scope.model.id + '/appMedia.json', 16329 showError: false 16330 }).then(function (o) { 16331 $scope.info = o; 16332 }); 16333 } 16334 } 16335 16336})(); 16337 16338//// File panel-upload.js //// 16339(function() { 16340 16341 $angular.controllers['panel-upload'] = function($uibModalInstance, $scope, $translate, params) { 16342 16343 $scope.close = function() { 16344 $uibModalInstance.dismiss('cancel'); 16345 }; 16346 16347 if (params.type === 'batch') { 16348 16349 var dz = { 16350 options : { 16351 url: contextPath + "/api/batch.json?task="+ $angular.contentScope.taskUpload + "&arg=" + $angular.contentScope.arg3, 16352 paramName : 'file', acceptedFiles : '', autoProcessQueue: true, maxFilesize : '10000', // MB 16353 addRemoveLinks: true, parallelUploads: 1, timeout: 3600000, // ms 16354 dictDefaultMessage : $translate.instant("msg.dropzone.drop") 16355 }, 16356 methods : {}, 16357 callbacks : { 16358 sending : function(file, xhr, formData) {}, 16359 addedfile : function(file) {}, 16360 removedfile : function(file) {}, 16361 success : function(file, data) { 16362 if (data && data._logs) { 16363 $angular.consoleScope.addLog(data._logs); 16364 delete data._logs; 16365 } 16366 $scope.dzMethods.getDropzone().removeFile(file); 16367 $utils.floatingMsg("Uploaded " + file.name); 16368 if (params.successFunction) { 16369 params.successFunction(file, data); 16370 } 16371 }, 16372 error : function(file, response) { 16373 $utils.floatingError((response && response.message) ? response.message : $translate.instant("msg.error")); 16374 }, 16375 queuecomplete : function() { 16376 $uibModalInstance.dismiss('cancel'); 16377 } 16378 } 16379 }; 16380 16381 $scope.getDzOptions = function() { 16382 return dz.options; 16383 } 16384 $scope.dzCallbacks = dz.callbacks; 16385 $scope.dzMethods = dz.methods; 16386 16387 } else if (params.spreadsheet) { 16388 16389 $angular.rootScope.dzOptions.url = 'api/geo/' + $angular.contentScope.entity 16390 + '/a/uploadList.json?spreadsheet=' + params.spreadsheet.id 16391 + '&geo_instance=' + $instance.getId() 16392 + '&preview=' + !params.spreadsheet.no_preview; 16393 $angular.contentScope.dropzoneSuccessFile = function(file, data) { 16394 if (data && data._logs) { 16395 $angular.consoleScope.addLog(data._logs); 16396 delete data._logs; 16397 } 16398 $uibModalInstance.dismiss('cancel'); 16399 if (data.preview) { 16400 showPreview(file, data); 16401 } else { 16402 $angular.contentScope.refresh(); 16403 } 16404 $instance.hasToRefresh = true; 16405 }; 16406 16407 } else { 16408 16409 // generic upload 16410 $angular.rootScope.dzOptions.url = 'api/geo/' + $angular.contentScope.entity 16411 + '/a/uploadList.json?geo_instance=' + $instance.getId(); 16412 $angular.contentScope.dropzoneSuccessFile = function(file, data) { 16413 if (data && data._logs) { 16414 $angular.consoleScope.addLog(data._logs); 16415 delete data._logs; 16416 } 16417 $uibModalInstance.dismiss('cancel'); 16418 $angular.contentScope.refresh(); 16419 $instance.hasToRefresh = true; 16420 }; 16421 16422 } 16423 16424 function showPreview(file, response) { 16425 var meta = $entity.getEntity(response.entity); 16426 $angular.openModalLocal('panel-columns', { 16427 title: 'msg.upload.preview', 16428 meta: meta, 16429 columns: meta.columns, 16430 model: response.preview, 16431 opts: {readonly: true}, 16432 buttons: [ 16433 {result: 'cancel', class: 'btn-default', text: 'msg.cancel'}, 16434 {result: 'execute', class: 'btn-primary', text: 'msg.upload.execute'} 16435 ], 16436 size: 'xl' 16437 }).then(function(result) { 16438 if (result === 'execute') { 16439 saveSpreadsheetFile(file, response.spreadsheet); 16440 } else if (result === 'cancel') { 16441 $angular.contentScope.refresh(); 16442 } 16443 }, function() { 16444 $angular.contentScope.refresh(); 16445 }) 16446 } 16447 16448 function saveSpreadsheetFile(file, spreadsheet) { 16449 var reader = new FileReader(); 16450 reader.onload = function(event) { 16451 var fileData = { 16452 base64: event.target.result, 16453 name: file.name, 16454 type: file.type 16455 }; 16456 $rest.post({ 16457 loading: 'generic', 16458 url: contextPath + '/api/geo/' + $angular.contentScope.entity + '/a/uploadList.json?spreadsheet=' 16459 + spreadsheet + '&geo_instance=' + $instance.getId(), 16460 data: { 16461 fileBase64: fileData 16462 } 16463 }).then(function() { 16464 $angular.contentScope.refresh(); 16465 }, function() { 16466 $angular.contentScope.refresh(); 16467 }); 16468 };
16469 reader.readAsDataURL(file); 16470 } 16471 } 16472})(); 16473 16474//// File panel-add-media.js //// 16475(function() { 16476 16477 16478 $angular.controllers['panel-add-media'] = function($uibModalInstance, $scope, $translate, $http, params, $timeout) { 16479 $scope.close = function() { 16480 $uibModalInstance.dismiss('cancel'); 16481 } 16482 $scope.entity = params.entity; 16483 $scope.entityId = params.id; 16484 $scope.mediaType = params.type; 16485 $scope.images = []; 16486 16487 function closeAndRefresh() { 16488 $uibModalInstance.close(); 16489 if (typeof $angular.contentScope.refreshMedia != 'undefined') { 16490 $angular.contentScope.refreshMedia(); 16491 return; 16492 } 16493 if (typeof $angular.contentScope.refreshForm != 'undefined') { 16494 $angular.contentScope.refreshForm(); 16495 return; 16496 } 16497 if (typeof $angular.contentScope.refresh != 'undefined') { 16498 $angular.contentScope.refresh(); 16499 return; 16500 } 16501 } 16502 16503 // dropzone 16504 $angular.rootScope.dzOptions.url = (!$constants.isWeb ? 'api' : 'www') + '/media.json'; 16505 if ($instance.current) { 16506 $angular.rootScope.dzOptions.headers = { 'From' : $instance.getId() }; 16507 } else { 16508 $angular.rootScope.dzOptions.headers = null; 16509 } 16510 $angular.contentScope.dropzoneSending = function(file, xhr, formData) { 16511 if (params.entity) formData.append('entity', params.entity); 16512 if (params.id) formData.append('entityId', params.id); 16513 if (params.type) formData.append('type', params.type); 16514 if (params.column) formData.append('column', params.column); 16515 if (params.mediaId) formData.append('mediaId', params.mediaId); 16516 if (params.language) formData.append('language', params.language); 16517 }; 16518 $angular.contentScope.dropzoneCallback = function() { 16519 closeAndRefresh(); 16520 }; 16521 16522 setTimeout(function() { 16523 //$("#uploadMedias div.dropzone").click(); 16524 }, 100); 16525 if ($constants.isWeb) { 16526 return; 16527 } 16528 16529 // url 16530 $scope.saveImageUrl = function() { 16531 if ($utils.isBlank($("#imageUrlForm input.url").val())) { 16532 return; 16533 } 16534 16535 $rest.post({ 16536 form: $("#imageUrlForm"), 16537 url: contextPath + '/api/media/a/createUrl.json', 16538 loading: "generic", 16539 successMessage: $angular.get("$translate").instant('msg.saved') 16540 }).then(function(data, url) { 16541 closeAndRefresh(); 16542 }); 16543 }; 16544 16545 // edit images 16546 $scope.removeImage = function(e, item) { 16547 $utils.preventDefault(e); 16548 item.removed = true; 16549 }; 16550 $scope.showImage = function(e, item) { 16551 $utils.preventDefault(e); 16552 $angular.openModalLocal("panel-image", {data: item}); 16553 }; 16554 16555 // save images 16556 $scope.saveImages = function() { 16557 $rest.post({ 16558 form: $("#confirmImages"), 16559 url: contextPath + '/' + (!$constants.isWeb ? 'api' : 'www') + '/media.json', 16560 loading: "generic", 16561 successMessage: $angular.get("$translate").instant('msg.saved') 16562 }).then(function(data, url) { 16563 closeAndRefresh(); 16564 }); 16565 }; 16566 16567 // wikipedia 16568 $scope.wikiPage = null; 16569 $scope.searchWikiPages = function(value) { 16570 //console.log(value) 16571 if ($utils.isBlank(value) || value.length < 3) { 16572 return; 16573 } 16574 $rest.get({ 16575 url : contextPath + '/api/geo-new/'+$angular.contentScope.entity+'/a/searchWikiPages.json?name='+value, 16576 loading : 'generic' 16577 }).then(function(data) { 16578 $scope.wikiPage = null; 16579 $angular.rootScope.wikiPages = data.wikiPages; 16580 }); 16581 }; 16582 $scope.selectWikiPage = function(value) { 16583 $("#imagesWikipediaForm input.name").val(value); 16584 $rest.post({ 16585 form: $("#imagesWikipediaForm"), 16586 url: contextPath + '/api/media/a/imagesWikipedia.json', 16587 loading: "generic" 16588 }).then(function(data, url) { 16589 $scope.morePages = false; 16590 $scope.images = data.list; 16591 }); 16592 }; 16593 16594 // google 16595 $timeout(function() { 16596 if ($("#google-images").length > 0) { 16597 var autocomplete = new google.maps.places.Autocomplete(document.getElementById('google-images'), $instance.getSearchOptions()); 16598 google.maps.event.addListener(autocomplete, 'place_changed', function() { 16599 var place = autocomplete.getPlace(); 16600 if (place == null || place.geometry == null) { 16601 return; 16602 } 16603 var id = place.place_id; 16604 $("#imagesGoogleForm input.name").val(id); 16605 $rest.post({ 16606 form: $("#imagesGoogleForm"), 16607 url: contextPath + '/api/media/a/imagesGoogle.json', 16608 loading: "generic" 16609 }).then(function(data, url) { 16610 $scope.morePages = false;
16611 $scope.images = data.list; 16612 }); 16613 }); 16614 } 16615 }, 500); 16616 16617 // flickr 16618 $scope.getImagesFlickr = function(add) { 16619 var page = ""; 16620 if (add) { 16621 page = ($scope.images.length / 20) + 1; 16622 } 16623 $rest.post({ 16624 form: $("#imagesFlickrForm"), 16625 url: contextPath + '/api/media/a/imagesFlickr.json?page='+page, 16626 loading: "generic" 16627 }).then(function(data, url) { 16628 $scope.morePages = false; 16629 if (add) { 16630 var num = $scope.images.length; 16631 $scope.images = $scope.images.concat(data.list); 16632 if ($scope.images.length == (num+20)) { 16633 $scope.morePages = true; 16634 } 16635 } else { 16636 $scope.images = data.list; 16637 if ($scope.images.length == 20) { 16638 $scope.morePages = true; 16639 } 16640 } 16641 }); 16642 }; 16643 16644 $scope.moreFlickr = function() { 16645 $scope.getImagesFlickr(true); 16646 }; 16647 16648 // youtube url 16649 $scope.saveYoutubeUrl = function(youtubeUrl) { 16650 if ($utils.isBlank(youtubeUrl)) { 16651 return; 16652 } 16653 var data = { 16654 entity: $scope.entity, 16655 entityId: $scope.entityId, 16656 url: youtubeUrl 16657 }; 16658 if (params.mediaId) { 16659 data.mediaId = params.mediaId; 16660 } 16661 if (params.language) { 16662 data.language = params.language; 16663 } 16664 $rest.post({ 16665 url: contextPath + '/api/media/a/createYoutubeUrl.json', 16666 data: data, 16667 loading: "generic", 16668 successMessage: $angular.get("$translate").instant('msg.saved') 16669 }).then(function() { 16670 closeAndRefresh(); 16671 }); 16672 }; 16673 16674 // TTS: https://cloud.ibm.com/apidocs/text-to-speech?code=node#synthesize 16675 $scope.tts = { 16676 entity: $scope.entity, 16677 entityId: $scope.entityId, 16678 language: $locale.language, 16679 voice: "", 16680 text: "" 16681 }; 16682 $scope.saveTTS = function() { 16683 $rest.post({ 16684 url: contextPath + '/api/media/a/createTTS.json', 16685 data: $scope.tts, 16686 loading: "generic", 16687 successMessage: $angular.get("$translate").instant('msg.saved') 16688 }).then(function() { 16689 closeAndRefresh(); 16690 }); 16691 }; 16692 $scope.voices = { 16693 'en': [ 'en-AU-CraigVoice', 'en-AU-MadisonVoice', 'en-GB_CharlotteV3Voice', 'en-GB_JamesV3Voice', 'en-GB_KateVoice', 'en-GB_KateV3Voice', 'en-US_AllisonVoice', 'en-US_AllisonV3Voice', 'en-US_EmilyV3Voice', 'en-US_HenryV3Voice', 'en-US_KevinV3Voice', 'en-US_LisaVoice', 'en-US_LisaV3Voice', 'en-US_MichaelVoice', 'en-US_MichaelV3Voice', 'en-US_OliviaV3Voice' ], 16694 'es': [ 'es-ES_EnriqueVoice', 'es-ES_EnriqueV3Voice', 'es-ES_LauraVoice', 'es-ES_LauraV3Voice', 'es-LA_SofiaVoice', 'es-LA_SofiaV3Voice', 'es-US_SofiaVoice', 'es-US_SofiaV3Voice' ], 16695 'fr': [ 'fr-FR_NicolasV3Voice', 'fr-FR_ReneeVoice', 'fr-FR_ReneeV3Voice' ], 16696 'it': [ 'it-IT_FrancescaVoice', 'it-IT_FrancescaV3Voice' ], 16697 'de': [ 'de-DE_BirgitVoice', 'de-DE_BirgitV3Voice', 'de-DE_DieterVoice', 'de-DE_DieterV3Voice', 'de-DE_ErikaV3Voice' ], 16698 }; 16699 16700 16701 } 16702 16703 $angular.controllers['panel-image'] = function($uibModalInstance, $scope, $translate, $http, params, $timeout) { 16704 $timeout(function() { 16705 $scope.item = params.data; 16706 }); 16707 $scope.close = function() { 16708 $uibModalInstance.dismiss('cancel'); 16709 } 16710 } 16711 16712})(); 16713 16714//// File panel-generic.js //// 16715(function() { 16716 16717 16718 $angular.controllers['panel-generic'] = function($uibModalInstance, $scope, $translate, $http, params, $sce) { 16719 16720 $scope.title = params.title; 16721 $scope.model = params.model; 16722 $scope.content = $sce.trustAsHtml(params.content); 16723 //console.log(params.content) 16724 16725 $scope.close = function() { 16726 $uibModalInstance.dismiss('cancel'); 16727 } 16728 16729 $scope.accept = function() { 16730 var result = params.successFunction($scope.model); 16731 if (result) { 16732 result.then(function() { 16733 $uibModalInstance.dismiss('success'); 16734 }); 16735 } else { 16736 $uibModalInstance.dismiss('success'); 16737 } 16738 }; 16739 16740 } 16741 16742})(); 16743 16744//// File panel-message.js //// 16745(function() { 16746 16747 $angular.controllers['panel-message'] = function($uibModalInstance, $scope, $translate, params) { 16748 $scope.title = $translate.instant(params.title); 16749 $scope.text = $translate.instant(params.text); 16750 16751 $scope.close = function() { 16752 $uibModalInstance.close(); 16753 } 16754 }; 16755})(); 16756 16757//// File panel-select-media-image.js //// 16758(function() { 16759 16760 16761 $angular.controllers['panel-select-media-image'] = function($uibModalInstance, $scope, params) { 16762 16763 $scope.images = params.model && params.model.geo_media && params.model.geo_media.images ? params.model.geo_media.images : null; 16764 $scope.callback = params.callback; 16765 16766 $scope.close = function() { 16767 $uibModalInstance.dismiss('cancel'); 16768 } 16769 16770 $scope.selectImage = function(image) { 16771 $scope.close(); 16772 $scope.callback(image); 16773 } 16774 } 16775})(); 16776 16777//// File panel-query-builder.js //// 16778(function() { 16779 $angular.controllers['panel-query-builder'] = function($uibModalInstance, $scope, params, debounce) { 16780 $scope.filterOperators = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'like', 'exists', 'in', 'nin']; 16781 $scope.orderDirections = [{value: 'asc', label: 'msg.direction.asc'}
16781, {value: 'desc', label: 'msg.direction.desc'}]; 16782 $scope.entity = params.entity; 16783 $scope.innerEntity = params.innerEntity; 16784 $scope.fromEntity = params.fromEntity; 16785 $scope.columns = {}; 16786 $scope.model = parseQuery($scope, params.query); 16787 16788 $scope.$watch('model', debounce(function(data) { 16789 applyFiltersChanges($scope, data.filters); 16790 $scope.query = formatQuery(data); 16791 }, 500), true); 16792 16793 $scope.close = function() { 16794 $uibModalInstance.dismiss(); 16795 }; 16796 16797 $scope.finish = function() { 16798 applyFiltersChanges($scope, $scope.model.filters); 16799 $scope.query = formatQuery($scope.model); 16800 $uibModalInstance.close($scope.query); 16801 }; 16802 16803 $scope.clear = function() { 16804 $scope.model = parseQuery($scope); 16805 prepareDefaults($scope); 16806 }; 16807 16808 $scope.addNewFilter = function() { 16809 var operator = 'eq'; 16810 var multiValue = toMultiValue(null); 16811 var filter = { 16812 operator: operator, 16813 _operator: operator, 16814 multiValue: multiValue, 16815 _multiValue: $utils.clone(multiValue) 16816 }; 16817 addFilterTemplate($scope, filter); 16818 $scope.model.filters.push(filter); 16819 }; 16820 $scope.addNewOrder = function() { 16821 $scope.model.orders.push({ 16822 direction: 'asc' 16823 }); 16824 }; 16825 $scope.addNewProjection = function() { 16826 $scope.model.projections.push({}); 16827 }; 16828 16829 prepareDefaults($scope); 16830 $scope.query = formatQuery($scope.model); 16831 }; 16832 16833 function prepareDefaults($scope) { 16834 if ($scope.model.filters.length === 0) { 16835 $scope.addNewFilter(); 16836 } 16837 if ($scope.model.orders.length === 0) { 16838 $scope.addNewOrder(); 16839 } 16840 if ($scope.model.projections.length === 0) { 16841 $scope.addNewProjection(); 16842 } 16843 } 16844 16845 function parseQuery($scope, query) { 16846 var filters = []; 16847 var limitEnabled = false; 16848 var limit = null; 16849 var orderEnabled = false; 16850 var orders = []; 16851 var projectionEnabled = false; 16852 var projections = []; 16853 if (query) { 16854 query.split("&").forEach(function(param) { 16855 var paramParts = param.split('='); 16856 if (paramParts.length === 2) { 16857 var paramKey = paramParts[0]; 16858 var paramValue = paramParts[1]; 16859 if (paramKey && paramValue) { 16860 if (paramKey === '_limit') { 16861 if ($utils.isNumeric(paramValue)) { 16862 limitEnabled = true; 16863 limit = Number(paramValue); 16864 } 16865 } else if (paramKey === '_order') { 16866 orderEnabled = true; 16867 orders = paramValue.split(',').map(function(orderParam) { 16868 var orderParts = orderParam.split(":"); 16869 return { 16870 path: orderParts[0], 16871 direction: (orderParts.length > 1 && orderParts[1] === 'desc') ? 'desc' : 'asc' 16872 }; 16873 }); 16874 } else if (paramKey === '_projection') { 16875 projectionEnabled = true; 16876 projections = paramValue.split(',').map(function(projectionParam) { 16877 return { 16878 path: projectionParam 16879 }; 16880 }); 16881 } else { 16882 var paramKeyParts = paramKey.split(":"); 16883 var path = paramKeyParts[0]; 16884 var operator = paramKeyParts.length === 1 ? 'eq' : paramKeyParts[1].substring(1); 16885 var multiValue = toMultiValue(paramValue); 16886 var filter = { 16887 path: path, 16888 _path: path, 16889 operator: operator, 16890 _operator: operator, 16891 value: paramValue, 16892 _value: $utils.clone(paramValue), 16893 multiValue: multiValue, 16894 _multiValue: $utils.clone(multiValue) 16895 }; 16896 addFilterTemplate($scope, filter); 16897 filters.push(filter); 16898 } 16899 } 16900 } 16901 }); 16902 } 16903 return { 16904 filters: filters, 16905 limitEnabled: limitEnabled, 16906 limit: limit, 16907 orderEnabled: orderEnabled, 16908 orders: orders, 16909 projectionEnabled: projectionEnabled, 16910 projections: projections 16911 }; 16912 } 16913 16914 function formatQuery(data) { 16915 var params = []; 16916 data.filters.forEach(function(filter) { 16917 if (filter.path && filter.operator && !$utils.isEmpty(filter.value)) { 16918 var operator = ''; 16919 if (filter.operator !== 'eq') { 16920 operator = ':$' + filter.operator; 16921 } 16922 params.push(filter.path + operator + '=' + filter.value); 16923 } 16924 }); 16925 if (data.limitEnabled && $utils.isNumeric(data.limit)) { 16926 params.push('_limit=' + data.limit); 16927 } 16928 if (data.orderEnabled) { 16929 var orders = [];
16930 data.orders.forEach(function(order) { 16931 if (order.path && order.direction) { 16932 orders.push(order.path + (order.direction === 'desc' ? ':desc' : '')); 16933 } 16934 }); 16935 if (orders.length > 0) { 16936 params.push('_order=' + orders.join(',')); 16937 } 16938 } 16939 if (data.projectionEnabled) { 16940 var projections = []; 16941 data.projections.forEach(function(projection) { 16942 if (projection.path) { 16943 projections.push(projection.path); 16944 } 16945 }); 16946 if (projections.length > 0) { 16947 params.push('_projection=' + projections.join(',')); 16948 } 16949 } 16950 if (params.length === 0) { 16951 return null; 16952 } 16953 return params.join('&'); 16954 } 16955 16956 function addFilterTemplate($scope, filter) { 16957 var inOperator = filter.operator === 'in' || filter.operator === 'nin'; 16958 var template = inOperator ? 'multi-text' : 'text'; 16959 var columns = null; 16960 if (filter.operator === 'exists') { 16961 template = 'boolean'; 16962 if (typeof filter.value !== 'boolean') { 16963 filter.value = (filter.value === true || filter.value === 'true'); 16964 } 16965 } else if (filter.path && filter.operator !== 'like') { 16966 var column = getFilterColumn($scope, filter.path); 16967 if (column) { 16968 template = inOperator && column.type !== 'list' ? 'multi-column' : 'column'; 16969 columns = [column]; 16970 } 16971 } 16972 filter.template = template; 16973 filter.columns = columns; 16974 } 16975 16976 function toMultiValue(val) { 16977 if ($utils.isArray(val) && val.length > 0) { 16978 return val.map(function(v) { 16979 return {value: v}; 16980 }); 16981 } 16982 return [{}]; 16983 } 16984 16985 function fromMultiValue(value) { 16986 if ($utils.isArray(value)) { 16987 return value.map(function(val) { 16988 return val.value; 16989 }).filter(function(val) { 16990 return !$utils.isEmpty(val); 16991 }) 16992 } 16993 return null; 16994 } 16995 16996 function applyFiltersChanges($scope, filters) { 16997 filters.forEach(function(filter) { 16998 var changedFromCondition = filter.path !== filter._path || 16999 filter.operator !== filter._operator; 17000 if (changedFromCondition) { 17001 filter._path = filter.path; 17002 filter._operator = filter.operator; 17003 addFilterTemplate($scope, filter); 17004 } 17005 if (!$utils.deepEquals(filter.value, filter._value)) { 17006 filter._value = $utils.clone(filter.value); 17007 filter.multiValue = toMultiValue(filter.value); 17008 filter._multiValue = $utils.clone(filter.multiValue); 17009 } else if (!$utils.deepEquals(filter.multiValue, filter._multiValue)) { 17010 filter._multiValue = $utils.clone(filter.multiValue); 17011 filter.value = fromMultiValue(filter.multiValue); 17012 filter._value = $utils.clone(filter.value); 17013 } 17014 }); 17015 } 17016 17017 function getFilterColumn($scope, filterPath) { 17018 var col = $scope.columns[filterPath]; 17019 if (col) { 17020 return col.column ? col.column[0] : null; 17021 } 17022 col = $entity.getColumnByPath($scope.entity, $scope.innerEntity, filterPath); 17023 if (col) { 17024 col = col.column; 17025 col = { 17026 name: 'value', 17027 type: col.type === 'formula' && col.formula_type ? col.formula_type : col.type, 17028 param: col.param, 17029 currency: col.currency, 17030 nolabel: true 17031 }; 17032 } 17033 $scope.columns[filterPath] = { 17034 column: col ? [col] : null 17035 }; 17036 return col; 17037 } 17038})(); 17039 17040//// File panel-inner-entity-list-item.js //// 17041(function() { 17042 17043 $angular.controllers['panel-inner-entity-list-item'] = function($uibModalInstance, $scope, params) { 17044 $scope.close = function() { 17045 $uibModalInstance.dismiss(); 17046 }; 17047 if (!params.model[params.innerListColumn]) { 17048 params.model[params.innerListColumn] = []; 17049 } 17050 $scope.isNew = params.itemIndex === undefined; 17051 $scope.removeEnabled = params.removeEnabled; 17052 $scope.title = params.title; 17053 if ($scope.isNew) { 17054 $scope.model = params.itemData ? params.itemData : {}; 17055 $scope.itemIndex = params.model[params.innerListColumn].length; 17056 } else { 17057 $scope.model = $utils.clone(params.model[params.innerListColumn][params.itemIndex]); 17058 $scope.itemIndex = params.itemIndex; 17059 } 17060 if (params.onChange) { 17061 $scope.$watch('model', params.onChange, true); 17062 } 17063 17064 $scope.meta = params.meta; 17065 var columns = params.columns; 17066 if (!columns) { 17067 columns = $entity.getInnerEntity(params.meta.id, params.innerEntity).columns; 17068 } 17069 $scope.columns = columns; 17070 $scope.ext = { 17071 extra: params.innerListColumn + '['+$scope.itemIndex+'].' 17072 }; 17073 $scope.ientity = params.innerEntity; 17074
17075 $scope.save = function() { 17076 var item = $utils.clone($scope.model); 17077 if ($scope.isNew) { 17078 $entity.addColumnItem(params.model, params.innerListColumn, true, item); 17079 } else { 17080 params.model[params.innerListColumn][params.itemIndex] = item; 17081 } 17082 17083 $uibModalInstance.close(item); 17084 }; 17085 17086 $scope.remove = function() { 17087 params.model[params.innerListColumn].splice(params.itemIndex, 1); 17088 $uibModalInstance.close(null); 17089 }; 17090 } 17091})(); 17092 17093//// File panel-wikipedia.js //// 17094(function() { 17095 17096 17097 $angular.controllers['panel-wikipedia'] = function($uibModalInstance, $scope, $translate, $http, params) { 17098 17099 $scope.editor = params.editor; 17100 17101 $scope.wikiPage = null; 17102 $scope.value = "";//$scope.editor.html; 17103 $scope.wikiContent = ""; 17104 17105 // FINISH 17106 $scope.accept = function() { 17107 $scope.editor.insertContent($scope.value); 17108 $uibModalInstance.dismiss('success'); 17109 }; 17110 $scope.close = function() { 17111 $uibModalInstance.dismiss('cancel'); 17112 }; 17113 17114 // WIKI SEARCH 17115 $scope.searchWikiPages = function(value) { 17116 //console.log(value) 17117 if ($utils.isBlank(value) || value.length < 3) { 17118 return; 17119 } 17120 $rest.get({ 17121 url : contextPath + '/api/geo-new/'+$angular.contentScope.entity+'/a/searchWikiPages.json?name='+value, 17122 loading : 'generic' 17123 }).then(function(data) { 17124 $scope.wikiPage = null; 17125 $angular.rootScope.wikiPages = data.wikiPages; 17126 }); 17127 }; 17128 $scope.selectWikiPage = function(value) { 17129 if ($utils.isBlank(value)) { 17130 value = null; 17131 } 17132 $scope.wikiPage = value; 17133 }; 17134 $scope.$watch('wikiPage', function(newValue, oldValue) { 17135 //console.log('-> wikiPage: ' + newValue) 17136 $scope.wp = newValue; 17137 if (newValue != oldValue) { 17138 $scope.loadWikiData(); 17139 } 17140 }); 17141 $scope.loadWikiData = function() { 17142 var url = $angular.rootScope.wikiPages[$scope.wikiPage]; 17143 if (url == null) { 17144 $scope.wikiContent = ""; 17145 return; 17146 } 17147 $rest.get({ 17148 url : contextPath + '/api/geo-new/'+$angular.contentScope.entity+'/a/loadWikiHtml.json?name='+url, 17149 loading : 'generic' 17150 }).then(function(data) { 17151 $scope.wikiContent = data.description; 17152 }); 17153 }; 17154 17155 $scope.copySelection = function() { 17156 var txt = getSelectedText(); 17157 if (!$utils.isBlank(txt)) { 17158 var old = $scope.value; 17159 if (!$utils.isBlank(old)) { 17160 old += "<br>"; 17161 } 17162 old += txt; 17163 $scope.value = old; 17164 } 17165 }; 17166 17167 function getSelectedText() { 17168 var text = ""; 17169 17170 if (document.selection && document.selection.createRange) { 17171 var range = document.selection.createRange(); 17172 text = range.htmlText; 17173 17174 } else if (window.getSelection) { 17175 var selection = window.getSelection(); 17176 if (selection.rangeCount > 0) { 17177 var range = selection.getRangeAt(0); 17178 var clonedSelection = range.cloneContents(); 17179 var div = document.createElement('div'); 17180 div.appendChild(clonedSelection); 17181 text = div.innerHTML; 17182 } 17183 } 17184 17185// try { 17186// if (window.getSelection) { 17187// var nNd = document.createElement("any"); 17188// var w = window.getSelection().getRangeAt(0); 17189// w.surroundContents(nNd); 17190// text = nNd.innerHTML; 17191// } else if (document.selection) { 17192// var c = document.selection.createRange(); 17193// text = c.htmlText; 17194// } 17195// } catch (e) { 17196// if (document.selection) { 17197// text = document.selection.createRange(); 17198// } else { 17199// text = window.getSelection(); 17200// } 17201// } 17202 if (text != null) { 17203 text = text.toString().replace(/\[.*?\]/g, ''); 17204 } 17205 17206 // remove selection 17207// if (window.getSelection) { 17208// if (window.getSelection().empty) { // Chrome 17209// window.getSelection().empty(); 17210// } else if (window.getSelection().removeAllRanges) { // Firefox 17211// window.getSelection().removeAllRanges(); 17212// } 17213// } else if (document.selection) { // IE? 17214// document.selection.empty(); 17215// } 17216 17217 return text; 17218 } 17219 17220 } 17221 17222})(); 17223 17224//// File panel-form.js //// 17225(function() { 17226 17227 $angular.controllers['panel-form'] = function($uibModalInstance, $scope, $translate, params, $timeout) { 17228 17229 $scope.title = params.title; 17230 $scope.items = params.items; 17231 17232 // init with default values 17233 $scope.model = {}; 17234 if ($scope.items) { 17235 for (var k in $scope.items) { 17236 var item = $scope.items[k]; 17237 if (item.type == 'radio') { 17238 if (item.selected) { 17239 $scope.model[item.name] = item.value; 17240 } 17241 } else { 17242 $scope.model[item.name] = item.value; 17243 } 17244 } 17245 } 17246 17247 $scope.close = function() { 17248 $uibModalInstance.dismiss('cancel'); 17249 }; 17250 17251 $scope.accept = function() { 17252 var result = params.successFunction($scope.model); 17253 if (result) { 17254 result.then(function() { 17255 $uibModalInstance.dismiss('success'); 17256 }); 17257 } else { 17258 $uibModalInstance.dismiss('success'); 17259 } 17260 }; 17261 17262 $timeout(function() {
17263 $(".panel-form .modal-body .form-control")[0].focus(); 17264 }); 17265 17266 } 17267})(); 17268//// File panel-duration-calculator.js //// 17269(function() { 17270 17271 $angular.controllers['panel-duration-calculator'] = function($uibModalInstance, $scope, params) { 17272 $scope.timeFrom = params.time; 17273 $scope.timeTo = null; 17274 $scope.plusDays = 0; 17275 $scope.duration = params.duration && !isNaN(params.duration) ? Number(params.duration) : 0; 17276 17277 var time = parseTime($scope.timeFrom); 17278 if (time) { 17279 $scope.plusDays = Math.floor($scope.duration / 1440); 17280 var duration = $scope.duration % 1440; 17281 time.hours += Math.floor(duration / 60); 17282 time.minutes += duration % 60; 17283 if (time.minutes > 59) { 17284 time.minutes -= 60; 17285 time.hours++; 17286 } 17287 if (time.hours > 23) { 17288 time.hours -= 24; 17289 } 17290 $scope.timeTo = formatTime(time); 17291 } 17292 17293 $scope.$watch('timeFrom', recalculate); 17294 $scope.$watch('timeTo', recalculate); 17295 $scope.$watch('plusDays', recalculate); 17296 17297 $scope.close = function() { 17298 $uibModalInstance.dismiss('cancel'); 17299 }; 17300 17301 $scope.save = function() { 17302 $uibModalInstance.dismiss('success'); 17303 params.successFunction($scope.duration); 17304 }; 17305 17306 function recalculate() { 17307 var from = parseTime($scope.timeFrom); 17308 var to = parseTime($scope.timeTo); 17309 if (from && to) { 17310 var hours = to.hours - from.hours; 17311 var minutes = to.minutes - from.minutes; 17312 if (minutes < 0) { 17313 minutes += 60; 17314 hours--; 17315 } 17316 if (hours < 0) { 17317 hours += 24; 17318 } 17319 $scope.duration = minutes + (hours * 60) + ($scope.plusDays * 1440); 17320 } 17321 } 17322 } 17323 17324 function parseTime(time) { 17325 if (!time || time.length !== 5) { 17326 return null; 17327 } 17328 var parts = time.split(':'); 17329 if (parts.length !== 2 || isNaN(parts[0]) || isNaN(parts[1])) { 17330 return null; 17331 } 17332 var hour = Number(parts[0]); 17333 var minutes = Number(parts[1]); 17334 if (hour < 0 || hour > 23 || minutes < 0 || minutes > 59) { 17335 return null; 17336 } 17337 return { 17338 hours: hour, 17339 minutes: minutes 17340 } 17341 } 17342 17343 function formatTime(time) { 17344 var text = time.hours < 10 ? '0' : ''; 17345 text += time.hours; 17346 text += ':'; 17347 text += time.minutes < 10 ? '0' : ''; 17348 text += time.minutes; 17349 return text; 17350 } 17351 17352})(); 17353 17354//// File panel-columns.js //// 17355(function() { 17356 17357 $angular.controllers['panel-columns'] = function($uibModalInstance, $scope, $translate, params) { 17358 17359 $scope.close = function() { 17360 $uibModalInstance.dismiss(); 17361 }; 17362 17363 $scope.clickButton = function(result) { 17364 $uibModalInstance.close(result); 17365 }; 17366 17367 $scope.title = params.title; 17368 $scope.meta = params.meta; 17369 $scope.columns = params.columns; 17370 $scope.model = params.model; 17371 $scope.opts = params.opts; 17372 $scope.buttons = params.buttons; 17373 }; 17374})(); 17375 17376//// File panel-translate.js //// 17377(function() { 17378 17379 17380 $angular.controllers['panel-translate'] = function($uibModalInstance, $scope, $translate, $http, params, $sce) { 17381 17382 $scope.url = contextPath + "/api/translate.html?lang=" + params.lang; 17383 17384 $scope.close = function() { 17385 $uibModalInstance.dismiss('cancel'); 17386 }; 17387 17388 $angular.initTranslate = function() { 17389 var text = $sce.trustAsHtml(params.text); 17390 $('#itranslate').contents().find("#translation").html(text); 17391 }; 17392 17393 $scope.accept = function() { 17394 var text; 17395 if (params.html) { 17396 text = $('#itranslate').contents().find("#translation").html(); 17397 } else { 17398 text = $('#itranslate').contents().find("#translation").text(); 17399 } 17400 var lang = $('#itranslate').contents().find("select.goog-te-combo").val(); 17401 17402 if ($utils.isBlank(text)) { 17403 return; 17404 } 17405 17406 $uibModalInstance.dismiss('success'); 17407 params.successFunction({ text:text, lang:lang }); 17408 }; 17409 17410 } 17411 17412})(); 17413 17414//// File panel-formula-builder.js //// 17415(function() { 17416 $angular.controllers['panel-formula-builder'] = function($uibModalInstance, $scope, params, debounce) { 17417 $scope.functions = Object.keys(formulas); 17418 $scope.formulas = formulas; 17419 $scope.entity = params.entity; 17420 $scope.innerEntity = params.innerEntity; 17421 $scope.model = parseFormula(params.formula); 17422 17423 $scope.$watch('model', debounce(function(data) { 17424 $scope.formula = formatFormula(data); 17425 }, 500), true); 17426 17427 $scope.close = function() { 17428 $uibModalInstance.dismiss(); 17429 }; 17430 17431 $scope.finish = function() { 17432 $scope.formula = formatFormula($scope.model); 17433 $uibModalInstance.close($scope.formula); 17434 }; 17435 17436 $scope.clear = function() { 17437 $scope.model = parseFormula(); 17438 prepareDefaults($scope); 17439 }; 17440 17441 $scope.onChangeFunc = function() { 17442 $scope.model.args = prepareArgs($scope.model.args, $scope.model.func); 17443 }; 17444 17445 $scope.buildArgFormula = function(arg) { 17446 $angular.openModalLocal('panel-formula-builder', { 17447 size: 'xl', 17448 entity: $scope.entity, 17449 formula: arg.value 17450 }).then(function(result) { 17451 arg.value = result; 17452 }); 17453 }; 17454 17455 $scope.addArg = function(arg) { 17456 var newArg = $utils.clone(arg); 17457 newArg.value = null; 17458 newArg.optional = true; 17459 $scope.model.args.push(newArg); 17460 }; 17461 17462 prepareDefaults($scope); 17463 $scope.formula = formatFormula($scope.model); 17464 }; 17465 17466 function prepareDefaults($scope) { 17467 17468 } 17469 17470 function parseFormula(value) { 17471 if (value) { 17472 value = value.trim(); 17473 if ($utils.isFormula(value)) { 17474 var indexOfStart = value.indexOf('('); 17475 var func = value.substring(0, indexOfStart); 17476 var data = value.substring(indexOfStart + 1, value.length - 1); 17477 var args = splitArgs(data) 17478 .map(parseArg) 17479 .filter($utils.isNotEmpty); 17480 return { 17481 func: func, 17482 args: prepareArgs(args, func) 17483 }; 17484 } 17485 } 17486 return null; 17487 } 17488 17489 function parseArg(value) { 17490 if (value) { 17491 value = value.trim(); 17492 var type = 'value'; 17493 if ($utils.isFormula(value)) { 17494 type = 'formula'; 17495 } else if (isQuotedString(value)) { 17496 type = 'text'; 17497 value = value.substring(1, value.length - 1); 17498 } 17499 return { 17500 valueType: type, 17501 value: value 17502 }; 17503 } 17504 return null; 17505 } 17506 17507 function isQuotedString(text) { 17508 if (text.length === 0) { 17509 return false;
17510 } 17511 var first = text[0]; 17512 if (first === '"' || first === "'") { 17513 var end = findEndOfString(text, 0, first); 17514 if (end === text.length - 1) { 17515 return true; 17516 } 17517 } 17518 return false; 17519 } 17520 17521 function splitArgs(content) { 17522 var args = []; 17523 var preArg = ''; 17524 var index = 0; 17525 while (index < content.length) { 17526 var character = content[index]; 17527 if (character === '"' || character === "'") { 17528 var endOfString = findEndOfString(content, index, character); 17529 if (endOfString > content.length) { 17530 args.push(preArg + content.substring(index, content.length)); 17531 return args; 17532 } 17533 preArg += content.substring(index, endOfString + 1); 17534 index = endOfString; 17535 } else if (character === '(') { 17536 var endOfParenthesis = findEndOfParenthesis(content, index); 17537 if (endOfParenthesis > content.length) { 17538 args.push(preArg + content.substring(index, content.length)); 17539 return args; 17540 } 17541 preArg += content.substring(index, endOfParenthesis + 1); 17542 index = endOfParenthesis; 17543 } else if (character === ',') { 17544 args.push(preArg); 17545 preArg = ''; 17546 } else { 17547 preArg += character; 17548 } 17549 index++; 17550 } 17551 if (preArg.length > 0) { 17552 args.push(preArg); 17553 } 17554 return args; 17555 } 17556 17557 function findEndOfString(content, start, quote) { 17558 var index = start + 1; 17559 while (index < content.length) { 17560 var character = content[index]; 17561 if (character === quote) { 17562 return index; 17563 } else if (character === '\\') { 17564 index++; 17565 } 17566 index++; 17567 } 17568 return index; 17569 } 17570 17571 function findEndOfParenthesis(content, start) { 17572 var index = start + 1; 17573 var opened = 0; 17574 while (index < content.length) { 17575 var character = content[index]; 17576 if (character === ')') { 17577 if (opened === 0) { 17578 return index; 17579 } 17580 opened--; 17581 } else if (character === '(') { 17582 opened++; 17583 } else if (character === '"' || character === "'") { 17584 index = findEndOfString(content, index, character); 17585 } 17586 index++; 17587 } 17588 return index; 17589 } 17590 17591 function prepareArgs(fromArgs, func) { 17592 if (!fromArgs) { 17593 fromArgs = []; 17594 } 17595 var formula = formulas[func]; 17596 if (!formula) { 17597 return fromArgs; 17598 } 17599 var args = []; 17600 var iterFromArgs = 0; 17601 for (var iter = 0; iter < formula.args.length; iter++) { 17602 var formulaArg = formula.args[iter]; 17603 var fromArg = iterFromArgs < fromArgs.length ? fromArgs[iterFromArgs] : null; 17604 if (formulaArg.multiple) { 17605 var numMultipleArgs = 0; 17606 for (iterFromArgs; iterFromArgs < fromArgs.length; iterFromArgs++) { 17607 var arg = $utils.clone(formulaArg); 17608 arg.value = fromArgs[iterFromArgs].value; 17609 if (formulaArg.min && numMultipleArgs >= formulaArg.min) { 17610 arg.optional = true; 17611 } 17612 args.push(arg); 17613 numMultipleArgs++; 17614 } 17615 if (formulaArg.min) { 17616 for (var i = numMultipleArgs; i < formulaArg.min; i++) { 17617 args.push($utils.clone(formulaArg)); 17618 } 17619 } 17620 } else { 17621 var argument = $utils.clone(formulaArg); 17622 argument.value = fromArg ? fromArg.value : null; 17623 args.push(argument); 17624 iterFromArgs++; 17625 } 17626 } 17627 return args; 17628 } 17629 17630 function formatFormula(data) { 17631 if (data && data.func && formulas[data.func]) { 17632 return data.func + '(' + data.args 17633 .filter(function(arg) { 17634 return $utils.isNotEmpty(arg.value); 17635 }) 17636 .map(function(arg) { 17637 return arg.type === 'text' ? "'" + arg.value + "'" : arg.value; 17638 }) 17639 .join(', ') + ')'; 17640 } 17641 return null; 17642 } 17643 17644 var formulas = { 17645 display: { 17646 args: [{name: 'path'}] 17647 }, 17648 math: { 17649 args: [{name: 'operation', label: 'msg.formula.arg.operation'}, 17650 {name: 'decimals', type: 'number', optional: true, label: 'msg.formula.arg.decimals'}] 17651 }, 17652 string: { 17653 args: [{name: 'path'}] 17654 }, 17655 number: { 17656 args: [{name: 'path'}, 17657 {name: 'decimals', type: 'number', optional: true, label: 'msg.formula.arg.decimals'}] 17658 }, 17659 bool: { 17660 args: [{name: 'path'}] 17661 }, 17662 not: { 17663 args: [{name: 'path'}] 17664 }, 17665 and: { 17666 args: [{name: 'path', multiple: true, min: 1}] 17667 }, 17668 or: { 17669 args: [{name: 'path', multiple: true, min: 1}] 17670 }, 17671 eq: { 17672 args: [{name: 'path'}, 17673 {name: 'path'}] 17674 }, 17675 ne: { 17676 args: [{name: 'path'}, 17677 {name: 'path'}] 17678 }, 17679 gt: { 17680 args: [{name: 'path'}, 17681 {name: 'path'}] 17682 }, 17683 gte: { 17684 args: [{name: 'path'}, 17685 {name: 'path'}] 17686 }, 17687 lt: { 17688 args: [{name: 'path'}, 17689 {name: 'path'}] 17690 }, 17691 lte: { 17692 args: [{name: 'path'}, 17693 {name: 'path'}] 17694 }, 17695 empty: { 17696 args: [{name: 'path'}] 17697 }, 17698 length: { 17699 args: [{name: 'path'}] 17700 }, 17701 replace: { 17702 args: [{name: 'path'}, 17703 {name: 'search text', type: 'text'}, 17704 {name: 'replace by', type: 'text', optional: true}] 17705 }, 17706 substring: { 17707 args: [{name: 'path'}, 17708 {name: 'from index', type: 'number'}, 17709 {name: 'to index', type: 'number'}] 17710 }, 17711 round: { 17712 args: [{name: 'path'}, 17713 {name: 'decimals', type: 'number', optional: true, label: 'msg.formula.arg.decimals'}] 17714 }, 17715 sum: { 17716 args: [{name: 'path'}, 17717 {name: 'decimals', type: 'number', optional: true, label: 'msg.formula.arg.decimals'}] 17718 }, 17719 avg: { 17720 args: [{name: 'path'}, 17721 {name: 'decimals', type: 'number', optional: true, label: 'msg.formula.arg.decimals'}] 17722 }, 17723 if: { 17724 args: [{name: 'condition'}, 17725 {name: 'result'},
17726 {name: 'else', optional: true}] 17727 }, 17728 convert_to_text: { 17729 args: [{name: 'number'}, 17730 {name: 'language', optional: true}, 17731 {name: 'currency', optional: true}] 17732 } 17733 }; 17734})(); 17735 17736//// File panel-column-types.js //// 17737(function() { 17738 17739 17740 $angular.controllers['panel-column-types'] = function($uibModalInstance, $scope, $translate, $http, params) { 17741 17742 $scope.column = params.column; 17743 17744 $scope.key_search = ""; 17745 17746 $scope.close = function() { 17747 $uibModalInstance.dismiss('cancel'); 17748 } 17749 17750 $scope.select = function(type) { 17751 $scope.column.type = type; 17752 $uibModalInstance.dismiss('success'); 17753 }; 17754 17755 $scope.showColumnType = function(type) { 17756 if ($utils.isBlank($scope.key_search)) { 17757 return true; 17758 } 17759 var txt = $utils.columnTypeText(type).toLowerCase(); 17760 return txt.contains($scope.key_search.toLowerCase()); 17761 } 17762 17763 } 17764 17765})(); 17766 17767//// File panel-change-history.js //// 17768(function() { 17769 17770 $angular.controllers['panel-change-history'] = function($uibModalInstance, $scope, params) { 17771 $scope.entity = params.entity; 17772 $scope.entityId = params.entityId; 17773 $scope.changes = []; 17774 $scope.limit = 0; 17775 $scope.index = 0; 17776 17777 $scope.load = function() { 17778 $rest.get({ 17779 skipHideLoading: true, 17780 url: contextPath + '/api/changes.json?entity=' + $scope.entity + '&entity_id=' + $scope.entityId + '&index=' + $scope.index, 17781 loading: 'generic' 17782 }).then(function(o) { 17783 if ($scope.limit == 0) { 17784 $scope.limit = o.list.length; 17785 } 17786 $scope.changes = o.list; 17787 }); 17788 }; 17789 17790 $scope.next = function() { 17791 if ($scope.changes.length === $scope.limit) { 17792 $scope.index += $scope.limit; 17793 $scope.load(); 17794 } 17795 }; 17796 17797 $scope.prev = function() { 17798 if ($scope.index > 0) { 17799 $scope.index = Math.max(0, $scope.index - $scope.limit); 17800 $scope.load(); 17801 } 17802 }; 17803 17804 $scope.load(); 17805 17806 $scope.close = function() { 17807 $uibModalInstance.dismiss('cancel'); 17808 }; 17809 } 17810})(); 17811 17812//// File panel-licenses.js //// 17813(function() { 17814 17815 17816 $angular.controllers['panel-licenses'] = function($uibModalInstance, $rootScope, $scope, $translate, $http, params) { 17817 17818 $scope.key = params.key; 17819 $scope.showButtons = params.showButtons; 17820 17821 $scope.close = function() { 17822 $uibModalInstance.dismiss('cancel'); 17823 } 17824 17825 $scope.model = {}; 17826 $rest.get({ 17827 skipHideLoading: true, 17828 url: contextPath + "/www/license/"+params.key+".json", 17829 loading: "generic" 17830 }).then(function(o) { 17831 $scope.model = o; 17832 }); 17833 17834 $scope.accept = function() { 17835 $angular.acceptLicense(params.key, null, function() { 17836 $utils.floatingMsg($translate.instant("status.accepted")); 17837 $scope.close(); 17838 }); 17839 }; 17840 $scope.reject = function() { 17841 $angular.rejectLicense(params.key, null, function() { 17842 $utils.floatingMsg($translate.instant("status.rejected")); 17843 $scope.close(); 17844 }); 17845 }; 17846 17847 17848 } 17849 17850})(); 17851 17852//// File panel-action-info.js //// 17853(function() { 17854 17855 $angular.controllers['panel-action-info'] = function($uibModalInstance, $scope, params) { 17856 $scope.title = params.title; 17857 $scope.action = params.action; 17858 17859 $scope.close = function() { 17860 $uibModalInstance.dismiss('cancel'); 17861 }; 17862 17863 $scope.buildAddToGoogleCalendarLink = function() { 17864 var action = $scope.action; 17865 var dateFrom = $utils.printDate(action.date, 'yyyyMMddTHHmm'); 17866 var dateTo = $utils.printDate(action.date + 3600000, 'yyyyMMddTHHmm'); 17867 return 'https://www.google.com/calendar/render' + 17868 '?action=TEMPLATE' + 17869 '&text=' + encodeURIComponent($scope.title) + 17870 '&dates=' + dateFrom + '00/' + dateTo + '00'; 17871 }; 17872 17873 $scope.buildAddToOutlookCalendarLink = function() { 17874 var action = $scope.action; 17875 var date = $utils.printDate(action.date, 'yyyy-MM-ddTHH:mm'); 17876 return 'https://outlook.live.com/calendar/0/deeplink/compose' + 17877 '?path=/calendar/action/compose' + 17878 '&rru=addevent' + 17879 '&startdt=' + date + ':00' + 17880 '&subject=' + encodeURIComponent($scope.title); 17881 }; 17882 } 17883})(); 17884 17885//// File panel-add-entity.js //// 17886(function() { 17887 17888 $angular.controllers['panel-add-entity'] = function($uibModalInstance, $scope, $translate, $http, params) { 17889 $scope.close = function() { 17890 $uibModalInstance.dismiss(); 17891 }; 17892 $scope.entity = params.entity; 17893 $scope.model = {}; 17894 $angular.panelAddEntityScope = $scope; 17895 17896 $entity.getEntityForce($scope.entity, function(meta) { 17897 $rest.get({ 17898 skipHideLoading: true, 17899 url: contextPath + "/api/geo-new/" + $scope.entity + "/new.json", 17900 loading: "generic" 17901 }).then(function(o) { 17902 $scope.geoForm = $utils.setFormviews(null, o).find(function(fv) { 17903 return !fv.form.optional; 17904 }); 17905 17906 $scope.opts = {}; 17907 var baseColumns = meta.columns; 17908 if ($scope.geoForm) { 17909 $scope.columns = $scope.geoForm.form.columns; 17910 baseColumns = $scope.geoForm.form.columns; 17911 } else if ($entity.isCreateSimple($scope.entity)) { 17912 $scope.columns = [$entity.getDefaultColumn(meta)]; 17913 } else { 17914 $scope.columns = baseColumns; 17915 } 17916 17917 // auto fill columns 17918 if (baseColumns && $angular.contentScope) { 17919 var pScope = $angular.contentScope; 17920 for (var key in baseColumns) { 17921 var col = baseColumns[key]; 17922 if (col.type === 'entity' && col.param === pScope.entity && pScope.entityId) { 17923 $scope.model[col.name] = pScope.entityId; 17924 col.unexposed = true; // hide relation 17925 17926 } else if (col.type === 'list' && col.param === pScope.entity && pScope.entityId) { 17927 if ($scope.model[col.name] == null) { 17928 $scope.model[col.name] = []; 17929 } 17930 $scope.model[col.name].push(pScope.entityId); 17931 col.unexposed = true; // hide relation 17932 17933 } else if (col.type === 'formula') { 17934 col.unexposed = true; // hide formulas 17935 } 17936 } 17937 } 17938 17939 $scope.meta = meta; 17940 }); 17941 }); 17942 17943 var formCallback;
17944 $scope.save = function(callback) { 17945 var submit = $("#geoAddEntityForm input[type=submit]"); 17946 if (submit.size() > 0) { 17947 formCallback = callback; 17948 setTimeout(function(){ 17949 submit.click(); // to validate form 17950 }, 100); 17951 } 17952 }; 17953 17954 $scope.submit = function(e, form) { 17955 $utils.preventDefault(e); 17956 17957 if (!$utils.validateForm(form)) { 17958 return; 17959 } 17960 17961 var data = $utils.clone($scope.model); 17962 if ($scope.geoForm) { 17963 data = { 17964 formId: $scope.geoForm.form.id, 17965 data: data 17966 } 17967 } 17968 $rest.post({ 17969 loading: "generic", 17970 url: contextPath + "/api/geo-new/" + $scope.entity + ".json", 17971 data: data 17972 }).then(function(createdObject) { 17973 $instance.checkHasToRefresh($scope.entity); 17974 $entity.getEntityForce($scope.entity, function() { 17975 $utils.postSave(data, createdObject, true, formCallback, function(callback) { 17976 $uibModalInstance.close(createdObject); 17977 if (callback) { 17978 callback(); 17979 } 17980 }); 17981 }); 17982 }); 17983 }; 17984 } 17985 17986})(); 17987 17988//// File panel-move.js //// 17989(function() { 17990 17991 $angular.controllers['panel-move'] = function($uibModalInstance, $scope) { 17992 $scope.close = function() { 17993 $uibModalInstance.dismiss('cancel'); 17994 }; 17995 $scope.model = {}; 17996 $scope.move = function(entity) { 17997 if ($utils.isBlank(entity)) { 17998 return; 17999 } 18000 var url; 18001 if ($utils.isBlank($angular.contentScope.entityId)) { 18002 url = contextPath + "/api/geo/" + $angular.contentScope.entity + "/a/move.json" + $paginator.getQueryStringAll() + "&target=" + entity; 18003 } else { 18004 url = contextPath + "/api/geo/" + $angular.contentScope.entity + "/" + $angular.contentScope.entityId + "/move.json?target=" + entity; 18005 } 18006 $rest.put({ 18007 url: url, 18008 loading: "generic", 18009 successMessage: $angular.get("$translate").instant('msg.moved') 18010 }).then(function() { 18011 $uibModalInstance.dismiss('cancel'); 18012 if ($utils.isBlank($angular.contentScope.entityId)) { 18013 $angular.contentScope.refresh(); 18014 } else { 18015 $events.back(); 18016 } 18017 }); 18018 }; 18019 } 18020 18021})(); 18022 18023//// File panel-prompt.js //// 18024(function() { 18025 18026 $angular.controllers['panel-prompt'] = function($uibModalInstance, $scope, $translate, params) { 18027 $scope.title = params.title; 18028 $scope.label = params.label; 18029 18030 $scope.close = function() { 18031 $uibModalInstance.dismiss(); 18032 }; 18033 18034 $scope.accept = function() { 18035 if (params.validate) { 18036 var result = params.validate($scope.value); 18037 if (result !== true) { 18038 if (typeof result === 'string') { 18039 $utils.floatingError($translate.instant(result)); 18040 } 18041 return; 18042 } 18043 } 18044 $uibModalInstance.close($scope.value); 18045 }; 18046 } 18047})(); 18048 18049//// File panel-edit-json.js //// 18050(function() { 18051 18052 $angular.controllers['panel-edit-json'] = function($uibModalInstance, $scope, params) { 18053 if (typeof params.json === 'string') { 18054 $scope.json = params.json; 18055 } else { 18056 $scope.json = angular.toJson(params.json, 2); 18057 } 18058 18059 $scope.close = function() { 18060 $uibModalInstance.dismiss('cancel'); 18061 }; 18062 18063 $scope.finishEdition = function() { 18064 try { 18065 params.successFunction(angular.fromJson($scope.json)); 18066 } catch (e) {
18067 alert('Json invalid'); 18068 console.error(e); 18069 return; 18070 } 18071 $uibModalInstance.dismiss('success'); 18072 }; 18073 } 18074})(); 18075 18076//// File panel-video.js //// 18077(function() { 18078 18079 18080 $angular.controllers['panel-video'] = function($uibModalInstance, $scope, $translate, $http, params) { 18081 18082 $scope.videoUrl = params.video; 18083 18084 $scope.close = function() { 18085 $uibModalInstance.dismiss('cancel'); 18086 } 18087 18088 } 18089 18090})(); 18091 18092//// File panel-login.js //// 18093(function() { 18094 18095 $angular.controllers['panel-login'] = function($uibModalInstance, $scope) { 18096 $scope.close = function() { 18097 $uibModalInstance.dismiss(); 18098 }; 18099 $scope.finish = function() { 18100 $uibModalInstance.close(); 18101 }; 18102 } 18103})(); 18104 18105//// File panel-confirm.js //// 18106(function() { 18107 18108 18109 $angular.controllers['panel-confirm'] = function($uibModalInstance, $scope, $translate, $http, params) { 18110 18111 $scope.title = params.title; 18112 if (params.text && params.text != null) { 18113 $scope.text = params.text; 18114 } else { 18115 $scope.text = $translate.instant("msg.confirm"); 18116 } 18117 18118 $scope.close = function() { 18119 $uibModalInstance.dismiss('cancel'); 18120 18121 if (params.cancelFunction) { 18122 params.cancelFunction(); 18123 } 18124 } 18125 18126 $scope.accept = function() { 18127 $uibModalInstance.dismiss('success'); 18128 params.successFunction(); 18129 } 18130 18131 } 18132 18133})(); 18134 18135//// File panel-json.js //// 18136(function() { 18137 "use strict"; 18138 18139 $angular.controllers['panel-json'] = function($uibModalInstance, $scope, $translate, $http, params, $sce) { 18140 18141 $scope.content = $utils.sortKeys(params.json); 18142 //console.dir(params.content) 18143 18144 $scope.close = function() { 18145 $uibModalInstance.dismiss('cancel'); 18146 } 18147 18148 }; 18149 18150})(); 18151 18152//// File datamixer-user-inputs.component.js //// 18153(function() { 18154 18155 $angular.controllers['datamixer-user-inputs-component'] = function($scope) { 18156 18157 $scope.$on('initDatamixerUserInputsComponent', function(event, config) { 18158 $scope.datamixer = config.model; 18159 $scope.model = { 18160 columns: prepareColumns(), 18161 sample: prepareSample() 18162 } 18163 $scope.$watch('model.sample', onChangeSample, true); 18164 }); 18165 18166 $scope.$on('refreshDatamixerUserInputsComponent', function(event, data) { 18167 $scope.datamixer = data.model; 18168 $scope.model.columns = prepareColumns(); 18169 $scope.model.sample = prepareSample(); 18170 }); 18171 18172 function prepareColumns() { 18173 if ($scope.datamixer.user_inputs && $scope.datamixer.user_inputs.columns) { 18174 return angular.fromJson($scope.datamixer.user_inputs.columns); 18175 } 18176 return []; 18177 } 18178 18179 function prepareSample() { 18180 if ($scope.datamixer.user_inputs && $scope.datamixer.user_inputs.sample_data) { 18181 return angular.fromJson($scope.datamixer.user_inputs.sample_data); 18182 } 18183 return {}; 18184 } 18185 18186 $scope.onChange = function(columns) { 18187 if (!$scope.datamixer.user_inputs) { 18188 $scope.datamixer.user_inputs = {}; 18189 } 18190 $scope.datamixer.user_inputs.columns = angular.toJson(columns); 18191 }; 18192 18193 function onChangeSample(sample) { 18194 if (!$scope.datamixer.user_inputs) { 18195 $scope.datamixer.user_inputs = {}; 18196 } 18197 $scope.datamixer.user_inputs.sample_data = angular.toJson(sample); 18198 } 18199 } 18200})(); 18201 18202//// File booking.component.js //// 18203(function() { 18204 18205 $angular.components['booking'] = { 18206 templateUrl: 'booking.component.html', 18207 bindings: { 18208 geoObject: '<', 18209 model: '<', 18210 hideTitle: '<', 18211 hideBookButton: '<', 18212 onChange: '&' 18213 }, 18214 controller: function($scope, $timeout) { 18215 var self = $angular.prepareComponent(this, $scope, $timeout); 18216 18217 self.$onChanges = function() { 18218 $scope.refresh(); 18219 }; 18220 18221 $scope.refresh = function() { 18222 $scope.geoObject = self.geoObject; 18223 $scope.showTitle = !self.hideTitle; 18224 $scope.showBookButton = !self.hideBookButton; 18225 $scope.onChange = self.onChange; 18226 18227 var booking = self.model; 18228 if (!booking) { 18229 booking = {}; 18230 } 18231 $scope.model = booking; 18232 18233 var scheduleConfig = $scope.geoObject.geo_schedule; 18234 var bookingConfig = scheduleConfig.booking; 18235 18236 $scope.availableDays = $scope.getAvailableDates(scheduleConfig); 18237 18238 if (!$scope.bookingEntityColumns) { 18239 $rest.get({ 18240 skipHideLoading: true, 18241 loading: "generic", 18242 url: contextPath + "/www/booking/a/columns.json?entity=" + $scope.geoObject.entity + "&entity
18242Id=" + $scope.geoObject.id 18243 }).then(function(bookingEntity) { 18244 var bookingEntityColumns = bookingEntity.columns; 18245 $scope.bookingEntityColumns = bookingEntityColumns; 18246 var extra = {}; 18247 if (bookingEntityColumns && bookingEntityColumns.length > 0) { 18248 $scope.extraDataEntity = bookingEntity; 18249 for (var iter = 0; iter < bookingEntityColumns.length; iter++) { 18250 var name = bookingEntityColumns[iter].name; 18251 extra[name] = null; 18252 if (booking.extra_data) { 18253 $scope.geoObject[name] = booking.extra_data[name]; 18254 } 18255 } 18256 } 18257 $scope.extra = extra; 18258 }); 18259 } 18260 18261 $scope.single = bookingConfig.capacity === 1 || bookingConfig.capacity_per_booking === 1; 18262 18263 $scope.booking = { 18264 day: booking ? $utils.parseDay(booking.day) : null, 18265 time: booking ? booking.time : null, 18266 quantity: booking ? booking.quantity : null 18267 }; 18268 18269 $scope.$watch('booking', $scope.validateIfBookingIsReady, true); 18270 $scope.$watch('geoObject', $scope.validateIfBookingIsReady, true); 18271 $scope.validateIfBookingIsReady(); 18272 }; 18273 18274 $scope.getAvailableDates = function(geoSchedule) { 18275 var today = new Date(); 18276 today.setHours(0); 18277 today.setMinutes(0); 18278 today.setSeconds(0); 18279 today.setMilliseconds(0); 18280 18281 var now = today.getTime() - 1; 18282 var list = $scope.getBookingDates(geoSchedule) 18283 .map(function(date) { 18284 return $utils.parseDay(date.day); 18285 }); 18286 return list.filter(function(day, position) { 18287 return list.indexOf(day) === position; 18288 }).filter(function(day) { 18289 return new Date(day).getTime() - now > 0; 18290 }); 18291 }; 18292 18293 $scope.getBookingTimes = function(geoSchedule, day) { 18294 if (day) { 18295 var parseDay = $utils.toISODay(day); 18296 var list = $scope.getBookingDates(geoSchedule) 18297 .filter(function(date) { 18298 return parseDay === date.day; 18299 }) 18300 .map(function(date) { 18301 return date.time_from; 18302 }); 18303 if (list.length == 1) { 18304 $scope.booking.time = list[0]; 18305 } 18306 return list; 18307 } 18308 return []; 18309 } 18310 18311 $scope.getBookingDates = function(geoSchedule) { 18312 if (geoSchedule == null || geoSchedule.dates == null) { 18313 return []; 18314 } 18315 var dates = geoSchedule.dates; 18316 var maxBookings = geoSchedule.booking.max_bookings; 18317 if (maxBookings) { 18318 dates = dates.filter(function(date) { 18319 return date && (!date.num_bookings || date.num_bookings < maxBookings); 18320 }); 18321 } 18322 var capacity = geoSchedule.booking.capacity; 18323 if (capacity) { 18324 dates = dates.filter(function(date) { 18325 return date && (!date.booked || date.booked < capacity); 18326 }); 18327 } 18328 return dates; 18329 } 18330 18331 $scope.validateIfBookingIsReady = function() { 18332 var day = $scope.booking.day; 18333 var time = $scope.booking.time; 18334 var quantity = $scope.single ? 1 : $scope.booking.quantity; 18335 18336 $scope.isReady = !!(day && time && quantity); 18337 $scope.model.entity = $scope.geoObject.entity; 18338 $scope.model.entity_id = $scope.geoObject.id; 18339 $scope.model.day = day ? $utils.toISODay(day) : null; 18340 $scope.model.time = time; 18341 $scope.model.quantity = quantity; 18342 18343 var extraData = {}; 18344 for (var extra in $scope.extra) { 18345 extraData[extra] = $scope.geoObject[extra]; 18346 } 18347 $scope.model.extra_data = extraData; 18348 18349 if ($scope.onChange) { 18350 $scope.onChange({ 18351 booking: $scope.model, 18352 isReady: $scope.isReady 18353 }); 18354 } 18355 }; 18356 18357 $scope.book = function() { 18358 if (!$user.isLogged() && !$instance.isLoginDisabled()) { 18359 $user.openLoginAsPanel(function() { 18360 $scope.book(); 18361 }); 18362 return; 18363 } 18364 var form = $angular.searchInScope("bookingForm"); 18365 if (!$utils.validateForm(form)) { 18366 return; 18367 } 18368 if (!$scope.isReady) { 18369 $utils.floatingError($angular.get("$translate").instant("fields.required")); 18370 return; 18371 } 18372 $rest.post({ 18373 url: contextPath + '/www/booking.json', 18374 data: $scope.model, 18375 loading: 'generic' 18376 }).then(function(o) { 18377 $scope.booking.success = true; 18378 $scope.booking.day = null; 18379 $scope.booking.time = null; 18380 $scope.booking.quantity = null; 18381 18382 if ($entity.isGeoBuy(o.object.entity)) { 18383 $angular.get("$location").path($instance.getBaseUrl() + "booking/" + o.id + "/pay"); 18384 } 18385 }); 18386 }; 18387 } 18388 }; 18389})(); 18390 18391//// File datamixer-processors.component.js //// 18392(function() { 18393 18394 var FUNCTIONS = [ 18395 {name: 'count', from: ['list', 'string']}, 18396 {name: 'sum', from: ['list']}, 18397 {name: 'filter', from: ['list']}, 18398 {name: 'query', from: ['list']}, 18399 {name: 'group', from: ['list']}, 18400 {name: 'sort', from: ['list']}, 18401 {name: 'get', from: ['object', 'list', 'string']}, 18402 {name: 'replace', from: ['list']}, 18403 {name: 'add', from: ['day', 'time', 'object', 'list', 'integer', 'decimal', 'string']}, 18404 {name: 'subtract', from: ['day', 'time', 'object', 'list', 'integer', 'decimal', 'string']}, 18405 {name: 'multiply', from: ['list', 'integer', 'decimal']}, 18406 {name: 'divide', from: ['list', 'integer', 'decimal']}, 18407 {name: 'fetch', from: ['list', 'string']}, 18408 {name: 'clone', from: ['day', 'time', 'object', 'list', 'integer', 'decimal', 'string', 'boolean']}, 18409 {name: 'wrap', from: ['day', 'time', 'object', 'list', 'integer', 'decimal', 'string', 'boolean']}, 18410 {name: 'unwrap', from: ['list']}, 18411 {name: 'formula', from: ['object', 'list']} 18412 ]; 18413 18414 var maxDemoObjects = null; 18415 18416 $angular.controllers['datamixer-processors-component'] = function($scope) { 18417 18418 $scope.$on('initDatamixerProcessorsComponent', function(event, config) { 18419 $scope.model = {}; 18420 $scope.datamixer = config.model; 18421 prepareToEdit(); 18422 $scope.addDataFrom = {}; 18423 }); 18424 18425 $scope.$on('refreshDatamixerProcessorsComponent', function(event, data) { 18426 $scope.datamixer = data.model; 18427 prepareToEdit(); 18428 }); 18429 18430 $scope.printFrom = printFrom; 18431 18432 function prepareToEdit() { 18433 maxDemoObjects = $scope.datamixer.max_demo_objects; 18434 $scope.model.variables = []; 18435 if ($scope.datamixer.user_inputs) { 18436 if ($scope.datamixer.user_inputs.columns) { 18437 var inputs = angular.fromJson($scope.datamixer.user_inputs.columns); 18438 if ($utils.isArray(inputs)) {
18439 inputs.forEach(function(input) { 18440 if (input.name) { 18441 $scope.model.variables.push(input.name); 18442 } 18443 }); 18444 } 18445 } 18446 if ($scope.datamixer.user_inputs.sample_data) { 18447 $scope.model.inputData = angular.fromJson($scope.datamixer.user_inputs.sample_data); 18448 } 18449 } 18450 $scope.model.samples = []; 18451 $scope.model.processors = $scope.datamixer.data_processors ? $scope.datamixer.data_processors.map(function(d) { 18452 if (d.new_var) { 18453 $scope.model.variables.push(d.new_var); 18454 } 18455 return { 18456 id: d.id, 18457 from: d.from, 18458 new_var: d.new_var, 18459 operations: d.operations ? angular.fromJson(d.operations) : [], 18460 built_by_component: d.built_by_component 18461 }; 18462 }) : []; 18463 $scope.model.variables.push('today'); 18464 var numProcessors = $scope.model.processors.length; 18465 prepareSample(0, numProcessors); 18466 } 18467 18468 function prepareToSave() { 18469 $scope.datamixer.data_processors = $scope.model.processors.map(function(d) { 18470 return { 18471 id: d.id, 18472 from: d.from, 18473 new_var: d.new_var, 18474 operations: d.operations ? angular.toJson(d.operations) : null, 18475 built_by_component: d.built_by_component 18476 }; 18477 }); 18478 } 18479 18480 function saveDatamixer() { 18481 prepareToSave(); 18482 $angular.contentScope.submitGeoEdit(); 18483 } 18484 18485 function prepareSample(index, numProcessors) { 18486 if (index >= numProcessors) { 18487 return; 18488 } 18489 var processors = []; 18490 for (var iter = 0; iter < index; iter++) { 18491 processors.push($scope.model.processors[iter]); 18492 } 18493 var processorToSample = $scope.model.processors[index]; 18494 processors.push({ 18495 from: processorToSample.from, 18496 operations: processorToSample.operations, 18497 new_var: '__$sample$__' 18498 }); 18499 getSample(processors, $scope.model.inputData, index).then(function(result) { 18500 $scope.model.samples[index] = result.sample; 18501 prepareSample(index + 1, numProcessors); 18502 }); 18503 } 18504 18505 $scope.addDataFromEntity = function() { 18506 if ($scope.addDataFrom.entity) { 18507 var entityId = $scope.addDataFrom.entity; 18508 $angular.openModalLocal('panel-datamixer-operation', { 18509 model: $scope.model, 18510 size: 'xl', 18511 isNewData: true, 18512 prevProcessors: $scope.model.processors, 18513 from: entityId 18514 }).then(function(result) { 18515 var processor = $entity.addColumnItem($scope.model, 'processors', true, { 18516 from: entityId, 18517 new_var: result.newVar 18518 }); 18519 if (result.operation) { 18520 $entity.addColumnItem(processor, 'operations', false, result.operation); 18521 } 18522 saveDatamixer(); 18523 }); 18524 } 18525 $scope.addDataFrom = {}; 18526 }; 18527 18528 $scope.addDataFromVar = function() { 18529 var variable = $scope.addDataFrom.variable; 18530 if (variable) { 18531 var from = '$' + variable; 18532 $angular.openModalLocal('panel-datamixer-operation', { 18533 model: $scope.model, 18534 size: 'xl', 18535 isNewData: true, 18536 prevProcessors: $scope.model.processors, 18537 from: from 18538 }).then(function(result) { 18539 var processor = $entity.addColumnItem($scope.model, 'processors', true, { 18540 from: from, 18541 new_var: result.newVar 18542 }); 18543 if (result.operation) { 18544 $entity.addColumnItem(processor, 'operations', false, result.operation); 18545 } 18546 saveDatamixer(); 18547 }); 18548 } 18549 $scope.addDataFrom = {}; 18550 }; 18551 18552 $scope.removeData = function(processor, index) { 18553 $rest.openConfirmPanel('msg.datamixer.removeData', null, function() { 18554 $scope.model.processors.splice(index, 1); 18555 saveDatamixer(); 18556 }); 18557 } 18558 18559 $scope.moveDataUp = function(processor, index) { 18560 var aux = $scope.model.processors[index].id; 18561 $scope.model.processors[index].id = $scope.model.processors[index - 1].id; 18562 $scope.model.processors[index - 1].id = aux; 18563 saveDatamixer(); 18564 }; 18565 18566 $scope.moveDataDown = function(processor, index) { 18567 var aux = $scope.model.processors[index].id; 18568 $scope.model.processors[index].id = $scope.model.processors[index + 1].id; 18569 $scope.model.processors[index + 1].id = aux; 18570 saveDatamixer(); 18571 }; 18572 18573 $scope.initDatamixerOperationsList = function(scope, processor) { 18574 initDatamixerOperationsList(scope, $scope.model, processor, saveDatamixer, function() { 18575 var processors = []; 18576 for (var i = 0; i < $scope.model.processors.length; i++) { 18577 var iter = $scope.model.processors[i]; 18578 if (iter.new_var === processor.new_var) { 18579 break; 18580 } 18581 processors.push(iter); 18582 } 18583 return { 18584 prevProcessors: processors, 18585 from: processor.from 18586 }; 18587 }); 18588 }; 18589 } 18590 18591 $angular.controllers['panel-datamixer-operation'] = function($uibModalInstance, $scope, $translate, params) { 18592 $scope.model = params.model; 18593 $scope.prevProcessors = params.prevProcessors; 18594 $scope.from = params.from; 18595 $scope.operation = params.operation ? $utils.clone(params.operation) : {}; 18596 $scope.autoPathFields = []; 18597 $scope.filterOperators = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte']; 18598 $scope.isExpression = $scope.operation && $scope.operation.params && $scope.operation.params.value && (typeof $scope.operation.params.value === 'object'); 18599 18600 $scope.close = function() { 18601 $uibModalInstance.dismiss(); 18602 }; 18603
18604 $scope.save = function() { 18605 if ($scope.operation && $scope.operation.function) { 18606 var operation = $scope.operation; 18607 getSampleOperation(operation).then(function(sampleResult) { 18608 operation.from_type = {type: $scope.fromType}; 18609 operation.result_type = sampleResult.result_type; 18610 saveOperation(operation); 18611 }); 18612 } else { 18613 saveOperation(null); 18614 } 18615 }; 18616 18617 function saveOperation(operation) { 18618 if (params.isNewData) { 18619 $angular.openModal('panel-prompt', { 18620 title: 'msg.datamixer.storeData', 18621 label: 'msg.datamixer.newVariable', 18622 validate: validateNewVar 18623 }).then(function(newVar) { 18624 $uibModalInstance.close({ 18625 newVar: newVar, 18626 operation: operation 18627 }); 18628 }); 18629 } else { 18630 $uibModalInstance.close({ 18631 operation: operation 18632 }); 18633 } 18634 } 18635 18636 function validateNewVar(varName) { 18637 if (!varName) { 18638 return false; 18639 } 18640 if ($scope.model.variables.indexOf(varName) >= 0) { 18641 return 'msg.datamixer.variableAlreadyExists'; 18642 } 18643 if (/^[a-zA-Z0-9_]+$/.test(varName)) { 18644 return true; 18645 } 18646 return 'msg.datamixer.invalidVariableName'; 18647 } 18648 18649 $scope.processData = function() { 18650 getSampleOperation($scope.operation).then(function(result) { 18651 $scope.toData = result.sample; 18652 }); 18653 }; 18654 18655 $scope.getAvailableFunctions = function() { 18656 if ($scope.fromType) { 18657 return FUNCTIONS.filter(function(func) { 18658 return func.from.indexOf($scope.fromType) >= 0; 18659 }).map(function(func) { 18660 return func.name; 18661 }); 18662 } 18663 return []; 18664 }; 18665 18666 $scope.getFunctionText = function(func, fromType) { 18667 var messageKeys = [ 18668 'msg.datamixer.operation.' + func + '.' + fromType, 18669 'msg.datamixer.operation.' + func 18670 ]; 18671 return $utils.tryToTranslate($translate, messageKeys); 18672 }; 18673 18674 function getSampleOperation(operation) { 18675 var processors = $scope.prevProcessors.slice(); 18676 processors.push({ 18677 from: $scope.from, 18678 operations: operation ? [operation] : [], 18679 new_var: '__$sample$__' 18680 }); 18681 return getSample(processors, $scope.model.inputData); 18682 } 18683 18684 function addFieldsForAutoPath(fields, data, prefix) { 18685 if ($utils.isArray(data)) { 18686 data.forEach(function(item) { 18687 addFieldsForAutoPath(fields, item, prefix); 18688 }); 18689 } else if ($utils.isObject(data)) { 18690 $utils.keys(data).forEach(function(key) { 18691 var field = prefix + key; 18692 if (fields.indexOf(field) < 0) { 18693 fields.push(field); 18694 addFieldsForAutoPath(fields, data[key], field + '.'); 18695 } 18696 }); 18697 } 18698 } 18699 getSampleOperation(null).then(function(result) { 18700 $scope.fromData = result.sample; 18701 $scope.fromType = result.result_type.type; 18702 $scope.fromType = !$scope.fromType || $scope.fromType === 'null' ? 'list' : $scope.fromType; 18703 var getSubType = function(t) { 18704 return t.subtype ? getSubType(t.subtype) : t.type; 18705 } 18706 $scope.fromSubType = getSubType(result.result_type); 18707 $scope.fromSubType = !$scope.fromSubType || $scope.fromSubType === 'null' ? 'object' : $scope.fromSubType; 18708 var fields = []; 18709 var data = result.data; 18710 addFieldsForAutoPath(fields, data, ''); 18711 $scope.autoPathFields = fields; 18712 var obj = null; 18713 if ($utils.isArray(data) && data.length > 0) { 18714 obj = data[0]; 18715 } else if ($utils.isObject(data)) { 18716 obj = data; 18717 } 18718 if (obj) { 18719 $scope.fromDataEntity = obj.entity; 18720 } 18721 }); 18722 18723 $scope.buildQuery = function() { 18724 if (!$scope.operation.params) { 18725 $scope.operation.params = {}; 18726 } 18727 $angular.openModalLocal('panel-query-builder', { 18728 size: 'xl', 18729 entity: $scope.fromDataEntity, 18730 query: $scope.operation.params.query 18731 }).then(function(result) { 18732 $scope.operation.params.query = result; 18733 }); 18734 }; 18735 18736 $scope.changeIsExpression = function() { 18737 $scope.isExpression = !$scope.isExpression; 18738 if ($scope.isExpression) { 18739 $scope.operation.params.value = {operations: []}; 18740 } else { 18741 $scope.operation.params.value = null; 18742 } 18743 }; 18744 18745 $scope.initDatamixerOperationsList = function(scope, obj, attribute) { 18746 var processor = obj[attribute]; 18747 if (!processor || typeof processor !== 'object') { 18748 processor = { 18749 operations: [] 18750 }; 18751 obj[attribute] = processor; 18752 } 18753 initDatamixerOperationsList(scope, $scope.model, processor, null, function() { 18754 var processors = $scope.prevProcessors.slice(); 18755 var from = processor.from; 18756 if (from === '$' || from.startsWith('$.')) { 18757 var operations = []; 18758 operations.push({ 18759 function: 'get', 18760 params: { 18761 at: 0 18762 } 18763 }); 18764 if (from.startsWith('$.') && from.length > 2) { 18765 operations.push({ 18766 function: 'get', 18767 params: { 18768 at: from.substring(2) 18769 } 18770 }); 18771 } 18772 var newVar = '__$var' + Math.random() + '$__'; 18773 processors.push({ 18774 from: $scope.from, 18775 operations: operations, 18776 new_var: newVar 18777 }); 18778 from = '$' + newVar; 18779 } 18780 return { 18781 prevProcessors: processors, 18782 from: from 18783 }; 18784 }); 18785 }; 18786 } 18787 18788 function getSample(processors, inputData, index) { 18789 return $rest.put({ 18790 url: contextPath + '/api/dashboard/' + (index ? index : 0) + '/sample.json', 18791 data: { 18792 max_demo_objects: maxDemoObjects, 18793 data_processors: processors, 18794 input: inputData 18795 } 18796 }).then(function(data) { 18797 var sample = data.sample ? angular.toJson(data.sample, 2) : data.sample; 18798 var max = 100000; 18799 if (sample && sample.length > max) { 18800 sample = sample.substring(0, max) + '...'; 18801 } 18802 return { 18803 data: data.sample, 18804 sample: sample, 18805 result_type: data.result_type 18806 }; 18807 }); 18808 } 18809 18810 function printFrom(from) { 18811 var $translate = $angular.get('$translate'); 18812 if (from === '$') { 18813 return $translate.instant('msg.datamixer.fromItem'); 18814 } 18815 if (from.startsWith('$.')) { 18816 return $translate.instant('msg.datamixer.fromItemPath', {from: from.substring(2)}); 18817 } 18818 if (from.startsWith('$')) { 18819 return $translate.instant('msg.datamixer.fromVariable', {from: from.substring(1)}); 18820 } 18821 return $translate.instant('msg.datamixer.fromEntity', {from: $constants.getEntityDesc('entity', from)}); 18822 } 18823 18824 function initDatamixerOperationsList($scope, model, processor, saveDatamixer, prevProcessorsGetter) { 18825 $scope.processor = processor; 18826 $scope.canEditAsJson = !!saveDatamixer; 18827 18828 $scope.printFrom = printFrom; 18829 $scope.printOperation = function(operation) { 18830 var $translate = $angular.get('$translate'); 18831 var params = operation.params; 18832 var func = operation.function; 18833 var messageKeys = []; 18834 var text = '...'; 18835 if (operation.from_type) { 18836 var fromType = operation.from_type.type; 18837 var fromSubtype = operation.from_type.subtype; 18838 if (fromSubtype) { 18839 messageKeys.push('msg.datamixer.operation.' + func + '.' + fromType + '.' + fromSubtype.type + '.params'); 18840 } 18841 messageKeys.push('msg.datamixer.operation.' + func + '.' + fromType + '.params'); 18842 messageKeys.push('msg.datamixer.operation.' + func + '.params'); 18843 if (fromSubtype) { 18844 messageKeys.push('msg.datamixer.operation.' + func + '.' + fromType + '.' + fromSubtype.type); 18845 } 18846 messageKeys.push('msg.datamixer.operation.' + func + '.' + fromType); 18847 messageKeys.push('msg.datamixer.operation.' + func); 18848 var operatorText = (params && params.operator) ? $translate.instant('msg.operator.' + params.operator) : null; 18849 var filterValue = (params && params.value && typeof params.value !== 'object') ? params.value : null; 18850 text = $utils.tryToTranslate($translate, messageKeys, { 18851 params: params, 18852 operator: operatorText, 18853 filterValue: filterValue 18854 }); 18855 if (!text) { 18856 text = $translate.instant('msg.datamixer.operation.invalid', operation); 18857 } 18858 } 18859 text = '<p>
18859' + text + '</p>'; 18860 var innerProcessor = null; 18861 if (params && params.from) { 18862 innerProcessor = params; 18863 } else if (params && params.value && params.value.from) { 18864 innerProcessor = params.value; 18865 } 18866 if (innerProcessor) { 18867 var innerText = '<div class="row mt-2"><div class="col">' + $scope.printFrom(innerProcessor.from) + '</div></div>'; 18868 if (innerProcessor.operations) { 18869 innerText += innerProcessor.operations.map(function(op) { 18870 return '<div class="row ml-2"><div class="col-12"><hr /></div><div class="col">' + $scope.printOperation(op) + '</div></div>'; 18871 }).join(''); 18872 } 18873 text += '<div class="ml-4">' + innerText + '</div>'; 18874 } 18875 return text; 18876 }; 18877 18878 $scope.addOperation = function() { 18879 var prev = prevProcessorsGetter(); 18880 var prevProcessors = prev.prevProcessors; 18881 var processor = $scope.processor; 18882 var from = prev.from; 18883 if (processor.operations) { 18884 var extraProcessor = { 18885 from: from, 18886 operations: processor.operations.slice(), 18887 new_var: '__$var' + Math.random() + '$__' 18888 }; 18889 prevProcessors.push(extraProcessor); 18890 from = '$' + extraProcessor.new_var; 18891 } 18892 $angular.openModalLocal('panel-datamixer-operation', { 18893 model: model, 18894 size: 'xl', 18895 isNewData: false, 18896 prevProcessors: prevProcessors, 18897 from: from 18898 }).then(function(result) { 18899 if (result.operation) { 18900 $entity.addColumnItem(processor, 'operations', false, result.operation); 18901 } 18902 if (saveDatamixer) { 18903 saveDatamixer(); 18904 } 18905 }); 18906 }; 18907 18908 $scope.editOperation = function(index) { 18909 var prev = prevProcessorsGetter(); 18910 var prevProcessors = prev.prevProcessors; 18911 var processor = $scope.processor; 18912 var from = prev.from; 18913 if (processor.operations) { 18914 var extraProcessor = { 18915 from: from, 18916 operations: processor.operations.slice(0, index), 18917 new_var: '__$var' + Math.random() + '$__' 18918 }; 18919 prevProcessors.push(extraProcessor); 18920 from = '$' + extraProcessor.new_var; 18921 } 18922 $angular.openModalLocal('panel-datamixer-operation', { 18923 model: model, 18924 size: 'xl', 18925 isNewData: false, 18926 operation: processor.operations[index], 18927 prevProcessors: prevProcessors, 18928 from: from 18929 }).then(function(result) { 18930 if (result.operation) { 18931 processor.operations[index] = result.operation; 18932 } else { 18933 processor.operations.splice(index, 1); 18934 } 18935 if (saveDatamixer) { 18936 saveDatamixer(); 18937 } 18938 }); 18939 }; 18940 18941 $scope.removeOperation = function(index) { 18942 $rest.openConfirmPanel('msg.datamixer.removeOperation', null, function() { 18943 $scope.processor.operations.splice(index, 1); 18944 if (saveDatamixer) { 18945 saveDatamixer(); 18946 } 18947 }); 18948 }; 18949 18950 $scope.editOperationsAsJson = function() { 18951 var simplifyToEdit = function(data) { 18952 if ($utils.isArray(data)) { 18953 return data.map(simplifyToEdit); 18954 } else if ($utils.isObject(data)) { 18955 var newObj = {}; 18956 for (var key in data) { 18957 if (key !== 'from_type' && key !== 'result_type') { 18958 newObj[key] = simplifyToEdit(data[key]); 18959 } 18960 } 18961 return newObj; 18962 } 18963 return data; 18964 }; 18965 var simpleJson = simplifyToEdit($scope.processor.operations); 18966 $angular.openModal('panel-edit-json', { 18967 json: simpleJson, 18968 size: 'lg', 18969 successFunction: function(json) { 18970 $scope.processor.operations = json; 18971 saveDatamixer(); 18972 } 18973 }); 18974 }; 18975 } 18976})(); 18977 18978//// File geo-users.js //// 18979(function() { 18980 18981 $angular.controllers['geo-users-component'] = function($scope, $element) { 18982 18983 function prepareGeoUsers() { 18984 var $scope = $angular.contentScope; 18985 18986 var fromDate = new Date(); 18987 fromDate.setDate(fromDate.getDate() - 15); 18988 $scope.nearbyUsers = { 18989 list: [], 18990 filter: { 18991 from: $utils.fromDate(fromDate, $constants.formatDay), 18992 to: null, 18993 distance: 100, 18994 time: 60 18995 } 18996 }; 18997 18998 $scope.searchNearbyUsers = function() { 18999 var params = []; 19000 var filter = $scope.nearbyUsers.filter; 19001 if (filter.from) { 19002 params.push('from=' + $utils.toISODay(filter.from)); 19003 } 19004 if (filter.to) { 19005 params.push('to=' + $utils.toISODay(filter.to)); 19006 } 19007 if (filter.distance) { 19008 params.push('maxMetersOfDistance=' + filter.distance); 19009 } 19010 if (filter.time) { 19011 params.push('maxMinutesOfDifference=' + filter.time); 19012 } 19013 $rest.get({ 19014 url: contextPath + '/api/nearby-users/' + $scope.entityId + '.json?' + params.join('&'), 19015 loading: 'generic' 19016 }).then(function(o) { 19017 $scope.nearbyUsers.list = o; 19018 }); 19019 }; 19020 19021 $scope.searchNearbyUsers(); 19022 } 19023 19024 prepareGeoUsers(); 19025 19026 } 19027})(); 19028//// File dashboard.component.js //// 19029(function() { 19030 19031 $angular.components['dashboard'] = { 19032 templateUrl: 'dashboard.component.html', 19033 bindings: { 19034 datamixer: '<', 19035 inputData: '<', 19036 onDatamixerReceived: '&', 19037 onInputDataChanged: '&' 19038 }, 19039 controller: function($scope, $timeout, $translate, $httpParamSerializer, $interval) { 19040 var self = $angular.prepareComponent(this, $scope, $timeout); 19041 19042 self.$onChanges = function() { 19043 $scope.refresh(); 19044 }; 19045 19046 $scope.refresh = function() { 19047 $scope.inputData = self.inputData ? self.inputData : {}; 19048 initDashboard(); 19049 $scope.$watch('inputData', function() { 19050 self.onInputDataChanged({inputData: $scope.inputData}); 19051 initDashboard(); 19052 }, true); 19053 19054 }; 19055 19056 $scope.reload = function() { 19057 lastInputData = null; 19058 initDashboard(); 19059 }; 19060 19061 $interval(function() { 19062 if (!isLoading && $scope.secondsToReload && $scope.secondsToReload > 0) { 19063 $scope.secondsToReload--; 19064 if ($scope.secondsToReload === 0) { 19065 $scope.reload(); 19066 } 19067 } 19068 }, 1000); 19069 19070 var lastInputData = null; 19071 var isLoading = true; 19072 function initDashboard() { 19073 if (lastInputData !== null && $utils.isEqual(lastInputData, $scope.inputData)) { 19074 return; 19075 } 19076 isLoading = true; 19077 var qs = $httpParamSerializer($scope.inputData); 19078 $rest.get({ 19079 url: contextPath + '/api/dashboard/' + self.datamixer + '.json?' + qs, 19080 loading: 'generic' 19081 }).then(function(o) { 19082 $angular.setTitle($utils.parse(o.name)); 19083 $scope.secondsToReload = o.datamixer.reload_every_seconds; 19084 self.onDatamixerReceived({datamixerData: o.datamixer}); 19085 if (o.safeemployee) { 19086 $scope.components = buildSafeemployeeComponents(o.safeemployee); 19087 } else { 19088 $scope.components = o.components; 19089 } 19090 $scope.inputData = o.input ? o.input : {}; 19091 lastInputData = $utils.clone($scope.inputData); 19092 if (o.datamixer.user_inputs && o.datamixer.user_inputs.columns) {
19093 $scope.inputs = angular.fromJson(o.datamixer.user_inputs.columns); 19094 } 19095 isLoading = false; 19096 $scope.componentsDownloadLinks = prepareComponentDownloadLinks(); 19097 }); 19098 } 19099 19100 function prepareComponentDownloadLinks() { 19101 var links = {}; 19102 if ($scope.components == null) { 19103 return links; 19104 } 19105 $scope.components.forEach(function(component) { 19106 if (component.type === 'table') { 19107 var id = self.datamixer + '-' + component.id; 19108 var qs = $httpParamSerializer(self.inputData); 19109 links[component.id] = [{ 19110 icon: 'cloud_download', 19111 href: contextPath + '/api/dashboard/' + id + '/downloadComponent.xlsx?' + qs + '&geo_instance=' + $instance.getId() 19112 }]; 19113 } 19114 }); 19115 return links; 19116 } 19117 19118 function buildSafeemployeeComponents(data) { 19119 return [{ 19120 type: 'counter', 19121 title: $translate.instant('msg.inRisk'), 19122 icon: 'sanitizer', 19123 color: '#C7C41B', 19124 value: data.people_in_risk, 19125 width: 3 19126 }, { 19127 type: 'counter', 19128 title: $translate.instant('msg.suspicious'), 19129 icon: 'local_hospital',
19130 color: '#FFA500', 19131 value: data.people_suspicious, 19132 width: 3 19133 }, { 19134 type: 'counter', 19135 title: $translate.instant('msg.sick'), 19136 icon: 'sick', 19137 color: '#E01B43', 19138 value: data.people_sick, 19139 width: 3 19140 }, { 19141 type: 'counter', 19142 title: $translate.instant('msg.recovered'), 19143 icon: 'thumb_up', 19144 color: '#008000', 19145 value: data.people_recovered, 19146 width: 3 19147 }, { 19148 type: 'map', 19149 title: $translate.instant('msg.dashboard.map.title'), 19150 subtitle: $translate.instant('msg.dashboard.map.description'), 19151 markers: data.locations, 19152 width: 6 19153 }, { 19154 type: 'chart', 19155 title: $translate.instant('msg.dashboard.graph.title'), 19156 subtitle: $translate.instant('msg.dashboard.graph.description'), 19157 chart: buildSafeemployeeChart(data), 19158 width: 6 19159 }]; 19160 } 19161 19162 function buildSafeemployeeChart(data) { 19163 var series = []; 19164 var colors = []; 19165 if (data.people_suspicious != null) { 19166 series.push({ 19167 name: $translate.instant('msg.suspicious'), 19168 data: data.cases_by_date.map(function(x) { 19169 return x.people_suspicious; 19170 }) 19171 }); 19172 colors.push('#FFA500'); 19173 } 19174 if (data.people_sick != null) { 19175 series.push({ 19176 name: $translate.instant('msg.sick'), 19177 data: data.cases_by_date.map(function(x) { 19178 return x.people_sick; 19179 }) 19180 }); 19181 colors.push('#E01B43'); 19182 } 19183 if (data.people_recovered != null) { 19184 series.push({ 19185 name: $translate.instant('msg.recovered'), 19186 data: data.cases_by_date.map(function(x) { 19187 return x.people_recovered; 19188 }) 19189 }); 19190 colors.push('#008000'); 19191 } 19192 return { 19193 chart: { 19194 type: 'bar' 19195 }, 19196 series: series, 19197 colors: colors, 19198 responsive: [{ 19199 breakpoint: 480, 19200 options: { 19201 legend: { 19202 position: 'bottom', 19203 offsetX: -10, 19204 offsetY: 0 19205 } 19206 } 19207 }], 19208 plotOptions: { 19209 bar: { 19210 horizontal: false 19211 } 19212 }, 19213 xaxis: { 19214 type: 'datetime', 19215 categories: data.cases_by_date.map(function(x) { 19216 return x.date; 19217 }) 19218 }, 19219 fill: { 19220 opacity: 1 19221 } 19222 }; 19223 } 19224 } 19225 }; 19226})(); 19227 19228//// File input-radio.js //// 19229(function() { 19230 19231 $angular.components['inputRadio'] = { 19232 templateUrl: "input-radio.html", 19233 bindings: { 19234 key: '@', model: '=', list: '=', changed: '&' 19235 }, 19236 controller: function() { 19237 } 19238 } 19239 19240})(); 19241//// File dashboard-card.component.js //// 19242(function() { 19243 19244 $angular.components['dashboardCard'] = { 19245 templateUrl: 'dashboard-card.component.html', 19246 bindings: { 19247 component: '<', 19248 type: '@', 19249 value: '<', 19250 chart: '<', 19251 markers: '<', 19252 tableColumns: '<', 19253 tableData: '<', 19254 downloadLinks: '<', 19255 hoverIcon: '@' 19256 }, 19257 controller: function($scope, $timeout, $element) { 19258 var self = $angular.prepareComponent(this, $scope, $timeout); 19259 19260 self.$onChanges = function() { 19261 $scope.prepare(); 19262 }; 19263 19264 $scope.refresh = function() { 19265 $scope.$watch('$ctrl.component', $scope.prepare, true); 19266 }; 19267 19268 $scope.prepare = function() { 19269 $scope.downloadLinks = self.downloadLinks ? self.downloadLinks : []; 19270 $scope.component = $utils.clone(self.component); 19271 if (self.type) { 19272 $scope.component.type = self.type; 19273 } 19274 if (!$utils.isBlank(self.value)) { 19275 $scope.component.value = self.value; 19276 } 19277 if (self.markers) { 19278 $scope.component.markers = self.markers; 19279 } 19280 if (self.tableColumns) { 19281 $scope.component.table_columns = self.tableColumns; 19282 } 19283 if (self.tableData) { 19284 $scope.component.data_list = self.tableData; 19285 } 19286 if ($scope.component.type === 'chart') { 19287 var chart = self.chart ? self.chart : $scope.component.chart; 19288 $timeout(function() { 19289 buildChart(chart); 19290 }); 19291 } 19292 $scope.hoverIcon = self.hoverIcon; 19293 }; 19294 19295 $scope.getCardViewStyle = function(component) { 19296 var style = {}; 19297 if (component.color) { 19298 style['border-left'] = '5px solid ' + component.color; 19299 } 19300 return style; 19301 }; 19302 19303 $scope.getCardTitleStyle = function(component) { 19304 var style = {}; 19305 if (component.color) { 19306 style['color'] = component.color; 19307 } 19308 return style; 19309 }; 19310 19311 function buildChart(chart) { 19312 if ($scope.apexChart) { 19313 $scope.apexChart.destroy(); 19314 } 19315 if (!chart || !chart.chart) { 19316 return; 19317 } 19318 var chartParsed = parseChartFunctions(chart); 19319 var $el = $element.find('.dashboard-card-chart'); 19320 $scope.apexChart = new ApexCharts($el[0], chartParsed); 19321 $scope.apexChart.render().catch(function() { 19322 $el.empty().append('<div class="alert alert-warning">Invalid data</div>'); 19323 }); 19324 } 19325 19326 function parseChartFunctions(chart) { 19327 if (chart === null) { 19328 return 0; 19329 } 19330 if ($utils.isArray(chart)) { 19331 return chart.map(function(item) { 19332 return parseChartFunctions(item); 19333 }); 19334 } 19335 if ($utils.isObject(chart)) { 19336 var newObj = {}; 19337 for (var key in chart) { 19338 newObj[key] = parseChartFunctions(chart[key]); 19339 } 19340 return newObj; 19341 } 19342 if (typeof chart === 'string') { 19343 if (chart === '__false__') { 19344 return false;
19345 } 19346 if (chart.trim().startsWith('function(')) { 19347 return new Function('return ' + chart)(); // FIXME unsafe-eval 19348 } 19349 } 19350 return chart; 19351 } 19352 19353 } 19354 }; 19355})(); 19356 19357//// File columns-form.component.js //// 19358(function() { 19359 19360 $angular.components['columnsForm'] = { 19361 templateUrl: 'columns-form.component.html', 19362 bindings: { 19363 entity: '<', 19364 model: '<', 19365 submitEvent: '@', 19366 wrapWithForm: '<', 19367 readonly: '<', 19368 allInOneColumn: '<', 19369 onChange: '&', 19370 onSubmit: '&' 19371 }, 19372 controller: function($scope, $timeout) { 19373 var self = $angular.prepareComponent(this, $scope, $timeout); 19374 19375 self.$onChanges = function() { 19376 $scope.refresh(); 19377 }; 19378 19379 $scope.refresh = function() { 19380 $scope.formSubmitId = 'form-component-' + $utils.getRandom(); 19381 $scope.onChange = self.onChange; 19382 $scope.onSubmit = self.onSubmit; 19383 $scope.wrapWithForm = !!self.wrapWithForm; 19384 19385 var entity = self.entity; 19386 19387 if (self.submitEvent && $scope.wrapWithForm) { 19388 $scope.$on(self.submitEvent, $scope.validateForm); 19389 } 19390 19391 if (!self.model) { 19392 self.model = {}; 19393 } 19394 $scope.model = self.model; 19395 19396 var columns = entity.columns; 19397 var formColumns = []; 19398 $scope.requiredColumns = []; 19399 if (columns) { 19400 formColumns = columns.filter(function(column) { 19401 return !column.hidden && column.updatable; 19402 }); 19403 $scope.requiredColumns = formColumns.filter(function(column) { 19404 return column.required; 19405 }).map(function(column) { 19406 return column.name; 19407 }); 19408 } 19409 19410 $scope.config = { 19411 meta: entity, 19412 columns: formColumns, 19413 model: $scope.model, 19414 opts: { 19415 readonly: self.readonly, 19416 long: self.allInOneColumn 19417 } 19418 }; 19419 19420 $scope.$watch('model', $scope.validateIfFormIsReady, true); 19421 $scope.validateIfFormIsReady(); 19422 }; 19423 19424 $scope.validateIfFormIsReady = function() { 19425 $scope.isReady = $scope.requiredColumns.every(function(required) { 19426 return $scope.model[required]; 19427 }); 19428 if ($scope.onChange) { 19429 $scope.onChange({ 19430 data: $scope.model, 19431 isReady: $scope.isReady 19432 }); 19433 } 19434 }; 19435 19436 $scope.validateForm = function() { 19437 $timeout(function() { 19438 $('#' + $scope.formSubmitId).click(); 19439 }, 0, false); 19440 }; 19441 19442 $scope.submitForm = function() { 19443 if ($scope.onSubmit) { 19444 $scope.onSubmit({ 19445 data: $scope.model, 19446 isReady: $scope.isReady 19447 }); 19448 } 19449 }; 19450 } 19451 }; 19452})(); 19453 19454//// File select-geo.component.js //// 19455(function() { 19456 19457 var LIMIT = 50; 19458 19459 $angular.components['selectGeo'] = { 19460 templateUrl: 'select-geo.component.html', 19461 require: { 19462 ngModelCtrl: 'ngModel' 19463 }, 19464 bindings: { 19465 ngModel: '<', 19466 entity: '<', 19467 query: '<', 19468 allowClear: '<', 19469 emptyOption: '<', 19470 multiple: '<', 19471 linkSelected: '<', 19472 numToShow: '<', 19473 placeholder: '@', 19474 omitInstances: '<', 19475 onChange: '&' 19476 }, 19477 controller: function($scope, $timeout, $translate, $element) { 19478 var self = $angular.prepareComponent(this, $scope, $timeout); 19479 19480 self.$onChanges = function() { 19481 $scope.refresh(); 19482 }; 19483 19484 var scrollBind = false; 19485 $scope.model = {}; 19486 $scope.optionsBySearch = {}; 19487 19488 $scope.refresh = function() { 19489 $scope.entity = self.entity; 19490 $scope.allowClear = $utils.isTrue(self.allowClear); 19491 $scope.omitInstances = $utils.isTrue(self.omitInstances); 19492 $scope.multiple = $utils.isTrue(self.multiple); 19493 $scope.placeholder = self.placeholder ? self.placeholder : $translate.instant('msg.select.search'); 19494 $scope.linked = self.linkSelected === undefined ? !$constants.isWeb : $utils.isTrue(self.linkSelected); 19495 $scope.numToShow = self.numToShow === undefined ? 10 : self.numToShow; 19496 setModels(self.ngModel); 19497 loadOptions(false); 19498 }; 19499 19500 $scope.getName = function(optionId) { 19501 if (!optionId) { 19502 return null; 19503 } 19504 if (optionId === $constants.blank) { 19505 return $constants.blank; 19506 } 19507 return $constants.getEntityDesc(self.entity, optionId); 19508 }; 19509 19510 $scope.isDisabled = function(optionId) { 19511 if (!optionId) { 19512 return null; 19513 } 19514 if (optionId === $constants.blank) { 19515 return false; 19516 } 19517 if (self.entity === 'entity' && $instance.current && $instance.current.entityList) { 19518 var entity = $instance.current.entityList.find(function(entity) { 19519 return entity.id === optionId; 19520 }); 19521 if (entity) { 19522 return entity.enabled !== undefined && !entity.enabled; 19523 } 19524 } 19525 var enabled = $constants.isEnabled(self.entity, optionId); 19526 if (enabled === undefined) { 19527 return undefined; 19528 } 19529 return !enabled; 19530 }; 19531 19532 $scope.searchOptions = function(search) { 19533 $scope.model.search = search; 19534 loadOptions(false); 19535 }; 19536 19537 $scope.onSelect = function($select) { 19538 var itemId = $select.selected; 19539 19540 if ($scope.multiple) { 19541 $scope.model.list.push(itemId); 19542 $scope.model.id = null; 19543 self.ngModelCtrl.$setViewValue($scope.model.list); 19544 } else { 19545 self.ngModelCtrl.$setViewValue(itemId); 19546 } 19547 19548 $select.close(); 19549 self.onChange({ 19550 $select: $select 19551 }); 19552 19553 loadOptions(false); 19554 }; 19555 19556 $scope.removeMultipleSelectedOption = function(e, itemId) { 19557 $utils.preventDefault(e); 19558 $scope.model.list.splice($scope.model.list.indexOf(itemId), 1); 19559 self.ngModelCtrl.$setViewValue($scope.model.list); 19560 loadOptions(false); 19561 } 19562 19563 function setModels(ngModel) { 19564 if ($scope.multiple) { 19565 if ($utils.isArray(ngModel)) { 19566 $scope.model.list = ngModel; 19567 } else if (ngModel) { 19568 $scope.model.list = ngModel.split(','); 19569 } else { 19570 $scope.model.list = []; 19571 } 19572 } else { 19573 $scope.model.id = ngModel; 19574 } 19575 } 19576 19577 function getSearchQuery() { 19578 var params = []; 19579 var search = $scope.model.search; 19580 if (!$utils.isBlank(search)) { 19581 params.push('_q=' + $utils.removeDiacritics(search.toLowerCase())); 19582 } 19583 if (self.query) { 19584 var query = $entity.parseQuery(self.query); 19585 params.push(query); 19586 } 19587 return params.join('&'); 19588 } 19589 19590 function loadOptions(add) { 19591 if ($utils.isBlank(self.entity) || (typeof self.entity != 'string')) { 19592 return; 19593 } 19594 if (self.entity === 'entity' && $instance.getId() != null && (!$scope.omitInstances || !$user.isModeler())) { 19595 // load instance entities 19596 loadAllEntities(); 19597 return; 19598 } 19599 19600 $timeout(function() { 19601 if (!scrollBind) { 19602 scrollBind = true; 19603 var uiSelectChoices = $element[0].querySelector('.select-geo-choices'); 19604 if (uiSelectChoices) { 19605 scrollBind = true; 19606 angular.element(uiSelectChoices).bind('scroll', function() { 19607 onScroll(uiSelectChoices); 19608 }); 19609 } 19610 } 19611 }); 19612 19613 var searchQuery = getSearchQuery(); 19614 var prevSearch = getOptionsBySearch(); 19615 if (!add && prevSearch.loaded) { 19616 $scope.options = prepareOptions(prevSearch); 19617 return; 19618 } 19619 19620 var index = prevSearch.options.length; 19621 $constants.getDataListMin(self.entity, searchQuery, index, LIMIT, $scope.omitInstances).then(function(list) { 19622 var newOptions = list.map(function(item) { 19623 return item._id ? item._id : item.id; 19624 }); 19625 19626 prevSearch.loaded = true; 19627 prevSearch.loadMore = newOptions.length === LIMIT; 19628 if (add) { 19629 prevSearch.options = prevSearch.options.concat(newOptions); 19630 } else { 19631 prevSearch.options = newOptions; 19632 } 19633 19634 $scope.options = prepareOptions(prevSearch); 19635 }); 19636 } 19637 19638 function loadAllEntities() { 19639 var search = $scope.model.search; 19640 if (!!search) { 19641 search = search.toLowerCase(); 19642 } 19643 19644 var list = $utils.clone($instance.getEntityList()); 19645 list.unshift({id: 'entity', name: $angular.get("$translate").instant("msg.entity")}, 19646 {id: 'instance', name: $angular.get("$translate").instant("msg.instance")}); 19647 19648 $scope.options = list.map(function(item) { 19649 return { 19650 id: item._id ? item._id : item.id, 19651 name: $entity.displayColumn(item) 19652 }; 19653 }).filter(function(item) { 19654 return !search || (item.name && item.name.toLowerCase().contains(search)); 19655 }).sort(function(itemA, itemB) { 19656 if (itemA.name < itemB.name) { 19657 return -1; 19658 } 19659 if (itemA.name > itemB.name) { 19660 return 1; 19661 } 19662 return 0; 19663 }).map(function(item) { 19664 return item.id; 19665 }); 19666 } 19667 19668 function prepareOptions(newSearch) { 19669 var options = []; 19670 if ($utils.isTrue(self.emptyOption)) { 19671 options.push($constants.blank); 19672 } 19673 newSearch.options.forEach(function(option) { 19674 options.push(option); 19675 }); 19676 if (self.ngModel && !$scope.multiple && !options.includes(self.ngModel)) { 19677 options.push(self.ngModel); 19678 } 19679 if ($scope.multiple && $scope.model.list) { 19680 return options.filter(function(option) { 19681 return !$scope.model.list.includes(option); 19682 }); 19683 } 19684 return options; 19685 } 19686 19687 function onScroll(uiSelectChoices) { 19688 var remainingHeight = uiSelectChoices.offsetHeight - uiSelectChoices.scrollHeight; 19689 var scrollTop = uiSelectChoices.scrollTop; 19690 var percent = Math.abs((scrollTop / remainingHeight) * 100); 19691 if (percent > 80) { 19692 var prevSearch = getOptionsBySearch(); 19693 if (prevSearch.loaded && prevSearch.loadMore) { 19694 prevSearch.loadMore = false;
19695 loadOptions(true); 19696 } 19697 } 19698 } 19699 19700 function getOptionsBySearch() { 19701 if (!self.entity) { 19702 return { 19703 options: [], 19704 loaded: true, 19705 loadMore: false 19706 }; 19707 } 19708 var entityOptions = $scope.optionsBySearch[self.entity]; 19709 if (!entityOptions) { 19710 entityOptions = {}; 19711 $scope.optionsBySearch[self.entity] = entityOptions; 19712 } 19713 var searchQuery = getSearchQuery(); 19714 var options = entityOptions[searchQuery]; 19715 if (!options) { 19716 options = { 19717 options: [], 19718 loaded: false, 19719 loadMore: false 19720 }; 19721 entityOptions[searchQuery] = options; 19722 } 19723 return options; 19724 } 19725 } 19726 }; 19727})(); 19728 19729//// File calendar.component.js //// 19730(function() { 19731 19732 $angular.components['calendar'] = { 19733 templateUrl: 'calendar.component.html', 19734 bindings: { 19735 config: '<' 19736 }, 19737 controller: function($scope, $timeout, $element) { 19738 var self = $angular.prepareComponent(this, $scope, $timeout); 19739 19740 self.$onChanges = function() { 19741 $scope.refresh(); 19742 }; 19743 19744 $scope.$on('reloadCalendarComponent', reloadEvents); 19745 19746 $scope.refresh = function() { 19747 $scope.config = self.config; 19748 $scope.calendarLanguage = $locale.language; 19749 $scope.events = {}; 19750 $scope.items = {}; 19751 if ($scope.config.lazyLoadingEvents) { 19752 $scope.rangesLoaded = []; 19753 } 19754 19755 setTimeout(loadCalendar, 200); 19756 }; 19757 19758 function loadCalendar() { 19759 if ($scope.config.lazyLoadingEvents) { 19760 createCalendar(function(info) { 19761 var from = info.start.getTime(); 19762 var to = info.end.getTime(); 19763 return getLazyEvents(from, to); 19764 }); 19765 } else if ($scope.config.getItems) { 19766 Promise.all($scope.config.getItems().map(convertToEvent)).then(createCalendar); 19767 } else { 19768 createCalendar(); 19769 } 19770 19771// $angular.rootScope.$watch('language', function(value) { 19772// if ($scope.calendar == null) { 19773// return; 19774// } 19775// if (value !== $scope.calendarLanguage) { 19776// $scope.calendarLanguage = value; 19777// $scope.calendar.setOption('locale', value); 19778// reloadEvents(); 19779// } 19780// }); 19781 } 19782 19783 function createCalendar(eventsProvider) { 19784 19785 var height = "auto"; 19786 var iv = localStorage.getItem("fcDefaultView") || 'dayGridMonth'; 19787 var id = localStorage.getItem("fcDefaultDate") || new Date(); 19788 19789 var timeFormat = { 19790 omitZeroMinute: false, 19791 hour: '2-digit', 19792 minute: '2-digit', 19793 meridiem: false, 19794 hour12: false 19795 }; 19796 var calendarParams = { 19797 headerToolbar: { 19798 left: 'prev,next today', 19799 center: 'title', 19800 right: 'dayGridMonth,customWeek,customDay,listMonth' 19801 }, 19802 views: { 19803 customWeek: { 19804 type: 'dayGridWeek', 19805 buttonText: 'week' 19806 }, 19807 customDay: { 19808 type: 'listDay', 19809 buttonText: 'day' 19810 } 19811 }, 19812 initialView: iv, 19813 initialDate: id, 19814 datesSet: function (dateInfo) { 19815 localStorage.setItem("fcDefaultView", dateInfo.view.type); 19816 localStorage.setItem("fcDefaultDate", dateInfo.startStr); 19817 }, 19818 showNonCurrentDates: $scope.config.hideNonCurrentDates, 19819 locale: $scope.calendarLanguage, 19820 events: eventsProvider, 19821 eventClick: function(info) { 19822 if ($scope.config.onClickEvent) { 19823 var item = $scope.items[info.event.id]; 19824 var event = $scope.events[info.event.id]; 19825 $scope.config.onClickEvent(event, item); 19826 } 19827 }, 19828 eventOrder: "start", 19829 eventDidMount: $scope.config.eventDidMount, 19830 eventMouseEnter: $scope.config.eventMouseEnter, 19831 eventMouseLeave: $scope.config.eventMouseLeave, 19832 slotLabelFormat: timeFormat, 19833 eventTimeFormat: timeFormat, 19834 weekends: true, navLinks: true, weekNumbers: false, height: height, firstDay:1 19835 }; 19836 $scope.calendar = new FullCalendar.Calendar($element[0], calendarParams); 19837 $scope.calendar.render(); 19838 } 19839 19840 function reloadEvents() { 19841 if ($scope.calendar == null) { 19842 return; 19843 } 19844 $scope.events = {}; 19845 $scope.items = {}; 19846 if ($scope.config.lazyLoadingEvents) { 19847 $scope.rangesLoaded = []; 19848 $scope.calendar.refetchEvents(); 19849 } else { 19850 Promise.all($scope.config.getItems().map(convertToEvent)).then(function(events) { 19851 $scope.calendar.getEventSources()[0].remove(); 19852 $scope.calendar.addEventSource(events); 19853 }); 19854 } 19855 } 19856 19857 function getLazyEvents(from, to) { 19858 var cache = !$scope.config.noCache; 19859 var range = cache ? evaluateIfNeedsToLoadMoreItems(from, to) : true; 19860 if (range && $scope.config.buildUrl) { 19861 return $rest.get({ 19862 url: $scope.config.buildUrl(from, to), 19863 loading: 'generic' 19864 }).then(function(o) { 19865 if (cache) { 19866 addRangeAsLoaded(range); 19867 } 19868 var items = $scope.config.getItemsFromResponse ? $scope.config.getItemsFromResponse($scope.calendar, o, from, to) : o; 19869 if (!Array.isArray(items)) { 19870 items = [items]; 19871 } 19872 return Promise.all(items.map(convertToEvent)); 19873 }); 19874 } 19875 return Promise.resolve(Object.values($scope.events)); 19876 } 19877 19878 function convertToEvent(item) { 19879 var event = $scope.config.convertItemToEvent ? $scope.config.convertItemToEvent(item) : item; 19880 if (typeof event.then === 'function') { 19881 return event.then(function(ev) { 19882 return prepareEvent(ev, item); 19883 }); 19884 } 19885 return Promise.resolve(prepareEvent(event, item)); 19886 } 19887 19888 function prepareEvent(event, item) { 19889 if (!event.id) { 19890 event.id = $utils.getRandom() + new Date().getTime(); 19891 } 19892 $scope.items[event.id] = item; 19893 $scope.events[event.id] = event; 19894 return event; 19895 } 19896 19897 function evaluateIfNeedsToLoadMoreItems(from, to) { 19898 var range = {from: from, to: to}; 19899 $scope.rangesLoaded.forEach(function(rangeIter) { 19900 if (range) { 19901 if (rangeIter.from <= range.from && rangeIter.to > range.from && rangeIter.to < range.to) { 19902 range.from = rangeIter.to; 19903 } else if (rangeIter.from > range.from && rangeIter.from < range.to && rangeIter.to >= range.to) { 19904 range.to = rangeIter.from; 19905 } else if (rangeIter.from <= range.from && rangeIter.to >= range.to) { 19906 range = null; 19907 } 19908 } 19909 }); 19910 return range; 19911 } 19912 19913 function addRangeAsLoaded(range) { 19914 var newRanges = []; 19915 var added = null; 19916 $scope.rangesLoaded.forEach(function(rangeIter) { 19917 if (added) { 19918 if (added.to < rangeIter.from) { 19919 newRanges.push(rangeIter); 19920 } else if (added.to < rangeIter.to) { 19921 added.to = rangeIter.to; 19922 } 19923 } else if (range.from < rangeIter.from) { 19924 if (range.to < rangeIter.from) { 19925 added = {from: range.from, to: range.to}; 19926 newRanges.push(added, rangeIter); 19927 } else if (range.to < rangeIter.to) { 19928 added = {from: range.from, to: rangeIter.to}; 19929 newRanges.push(added); 19930 } else { 19931 added = {from: range.from, to: range.to}; 19932 newRanges.push(added); 19933 } 19934 } else if (range.from <= rangeIter.to) { 19935 if (range.to <= rangeIter.to) { 19936 added = rangeIter; 19937 } else { 19938 added = {from: rangeIter.from, to: range.to}; 19939 } 19940 newRanges.push(added); 19941 } else { 19942 newRanges.push(rangeIter); 19943 } 19944 }); 19945 if (!added) { 19946 newRanges.push(range); 19947 } 19948 $scope.rangesLoaded = newRanges; 19949 } 19950 } 19951 }; 19952})(); 19953 19954//// File fidesur-reg.js //// 19955(function() { 19956 19957 $angular.controllers['fidesur-reg-component'] = function($scope, $element) { 19958 19959 $angular.contentScope.submitFidesurReg = function() { 19960 $rest.put({ 19961 url: contextPath + '/api/geo/' + $angular.contentScope.entity + '/' + $angular.contentScope.entityId + '/updateCustom.json', 19962 form: '#fidesurRegForm', 19963 loading: 'generic', 19964 successMessage: $angular.get('$translate').instant('msg.updated') 19965 }).then(function(data, url) { 19966 if ($angular.contentScope.postSubmit) { 19967 $angular.contentScope.postSubmit(); 19968 } 19969 }); 19970 }; 19971
19972 function verifyData() { 19973 var o = $angular.contentScope.model.fidesur_reg; 19974 if (o == null) { 19975 o = {}; 19976 $angular.contentScope.model.fidesur_reg = o; 19977 var props = $angular.contentScope.model.geo_properties; 19978 if (props) { 19979 for (var k in props) { 19980 var prop = props[k]; 19981 if (prop.name == 'Website') { 19982 o.empr_site = prop.value; 19983 } else if (prop.name == 'Phone') { 19984 o.empr_telf_fijo = prop.value; 19985 } 19986 } 19987 } 19988 } 19989 19990 /* add one item for list */ 19991 var btns = $('#fidesurRegForm .btn'); 19992 btns.each(function() { 19993 var btn = $(this); 19994 var click = btn.attr('ng-click'); 19995 if (click && click.startsWith('addList')) { 19996 setTimeout(function() { 19997 btn.click(); 19998 }, 500); 19999 } 20000 }); 20001 20002 } 20003 verifyData(); 20004 20005 $angular.contentScope.getEntidades = function() { 20006 var $scope = $angular.contentScope; 20007 if ($scope.entidades && $scope.entidades.length > 0) { 20008 return $scope.entidades; 20009 } 20010 if ($scope.entidades) { 20011 return null; 20012 } 20013 $scope.entidades = []; 20014 $rest.post({ 20015 url: contextPath + '/api/request.txt', 20016 loading: 'generic', 20017 data: { url : 'https://gaia.inegi.org.mx/wscatgeo/mgee/' } 20018 }).then(function(data) { 20019 $scope.entidades = angular.fromJson(data).datos; 20020 }); 20021 return null; 20022 }; 20023 20024 $angular.contentScope.getMunicipios = function(entidad) { 20025 if (entidad == null) { 20026 return []; 20027 } 20028 var $scope = $angular.contentScope; 20029 if ($scope.municipios && $scope.municipios[entidad] && $scope.municipios[entidad].length > 0) { 20030 return $scope.municipios[entidad]; 20031 } 20032 if ($scope.municipios && $scope.municipios[entidad]) { 20033 return null; 20034 } 20035 if ($scope.municipios == null) { 20036 $scope.municipios = {}; 20037 } 20038 $scope.municipios[entidad] = []; 20039 $rest.post({ 20040 url: contextPath + '/api/request.txt', 20041 loading: 'generic', 20042 data: { url : 'https://gaia.inegi.org.mx/wscatgeo/mgem/' + entidad } 20043 }).then(function(data) { 20044 $scope.municipios[entidad] = angular.fromJson(data).datos; 20045 }); 20046 return null; 20047 }; 20048 20049 $angular.contentScope.getLocalidades = function(entidad, municipio) { 20050 if (entidad == null || municipio == null) { 20051 return []; 20052 } 20053 var $scope = $angular.contentScope; 20054 var key = entidad + '-' + municipio; 20055 if ($scope.localidades && $scope.localidades[key] && $scope.localidades[key].length > 0) { 20056 return $scope.localidades[key]; 20057 } 20058 if ($scope.localidades && $scope.localidades[key]) { 20059 return null; 20060 } 20061 if ($scope.localidades == null) { 20062 $scope.localidades = {}; 20063 } 20064 $scope.localidades[key] = []; 20065 $rest.post({ 20066 url: contextPath + '/api/request.txt', 20067 loading: 'generic', 20068 data: { url : 'https://gaia.inegi.org.mx/wscatgeo/localidades/'+entidad+'/'+municipio } 20069 }).then(function(data) { 20070 $scope.localidades[key] = angular.fromJson(data).datos; 20071 }); 20072 return null; 20073 }; 20074 20075 $angular.contentScope.selectEntidad = function(item) { 20076 var model = $angular.contentScope.model; 20077 if (model == null) { 20078 return; 20079 } 20080 if (item == null) { 20081 model.fidesur_reg.entidad_id = null; 20082 model.fidesur_reg.entidad = null; 20083 model.fidesur_reg.municipio_id = null; 20084 model.fidesur_reg.municipio = null; 20085 model.fidesur_reg.localidad_id = null; 20086 model.fidesur_reg.localidad = null; 20087 return; 20088 } 20089 model.fidesur_reg.entidad_id = item.cve_agee; 20090 model.fidesur_reg.entidad = item.nom_agee; 20091 model.fidesur_reg.municipio_id = null; 20092 model.fidesur_reg.municipio = null; 20093 model.fidesur_reg.localidad_id = null; 20094 model.fidesur_reg.localidad = null; 20095 $angular.contentScope.getMunicipios(model.fidesur_reg.entidad_id); 20096 }; 20097 $angular.contentScope.selectMunicipio = function(item) { 20098 var model = $angular.contentScope.model; 20099 if (model == null) { 20100 return; 20101 } 20102 if (item == null) { 20103 model.fidesur_reg.municipio_id = null; 20104 model.fidesur_reg.municipio = null; 20105 model.fidesur_reg.localidad_id = null; 20106 model.fidesur_reg.localidad = null; 20107 return; 20108 } 20109 model.fidesur_reg.municipio_id = item.cve_agem; 20110 model.fidesur_reg.municipio = item.nom_agem; 20111 model.fidesur_reg.localidad_id = null; 20112 model.fidesur_reg.localidad = null; 20113 $angular.contentScope.getLocalidades(model.fidesur_reg.entidad_id, model.fidesur_reg.municipio_id); 20114 }; 20115 $angular.contentScope.selectLocalidad = function(item) { 20116 var model = $angular.contentScope.model; 20117 if (model == null) { 20118 return; 20119 } 20120 if (item == null) { 20121 model.fidesur_reg.localidad_id = null; 20122 model.fidesur_reg.localidad = null; 20123 return; 20124 } 20125 model.fidesur_reg.localidad_id = item.cve_loc; 20126 model.fidesur_reg.localidad = item.nom_loc; 20127 }; 20128
20129 $angular.contentScope.getCodigoInegi = function() { 20130 /* codigo 00(clave estado)000(municipio)0000(localidad) */ 20131 var o = $angular.contentScope.model.fidesur_reg; 20132 if (o && o.entidad_id) { 20133 var cod = o.entidad_id; 20134 if (o.municipio_id) { 20135 cod += o.municipio_id; 20136 if (o.localidad_id) { 20137 cod += o.localidad_id; 20138 } 20139 } 20140 return cod; 20141 } 20142 return ''; 20143 }; 20144 20145 $angular.contentScope.getTipos = function() { 20146 var o = $angular.contentScope.model.fidesur_reg; 20147 if (o && o.prod_categoria) { 20148 var cat = $angular.contentScope.categories[o.prod_categoria]; 20149 if (cat && cat.tipos) { 20150 return cat.tipos; 20151 } 20152 } 20153 return {}; 20154 }; 20155 $angular.contentScope.getSubtipos = function() { 20156 var o = $angular.contentScope.model.fidesur_reg; 20157 if (o && o.prod_categoria) { 20158 var cat = $angular.contentScope.categories[o.prod_categoria]; 20159 if (cat && cat.tipos) { 20160 var tipo = cat.tipos[o.prod_tipo]; 20161 if (tipo && tipo.subtipos) { 20162 return tipo.subtipos; 20163 } 20164 } 20165 } 20166 return {}; 20167 }; 20168 $angular.contentScope.getCodigoProd = function() { 20169 /* codigo attractivo 000(categoria)A(tipo)00(subtipo)-1(consecutivo) */ 20170 var o = $angular.contentScope.model.fidesur_reg; 20171 if (o && o.prod_categoria) { 20172 var cod = o.prod_categoria; 20173 if (o.prod_tipo) { 20174 cod += '-' + o.prod_tipo; 20175 if (o.prod_subtipo) { 20176 cod += o.prod_subtipo; 20177 } 20178 } 20179 return cod; 20180 } 20181 return ''; 20182 }; 20183 20184 $angular.contentScope.categories = { 20185 'SN' : { name: 'Sitios Naturales', tipos: { 20186 'M': { name: 'Montañas', subtipos: { '1': 'Altiplano', '2': 'Meseta', '3': 'Cerro', '4': 'Ãreas nevadas', '5': 'Bosque de piedras', '6': 'Volcanes' } }, 20187 'P': { name: 'Planicies', subtipos: { '1': 'Desiertos', '2': 'Llanuras', '3': 'Pampas', '4': 'Salinas' } }, 20188 'V': { name: 'Valles', subtipos: { '1': 'Valles' } }, 20189 'C': { name: 'Cañones y quebradas', subtipos: { '1': 'Quebradas', '2': 'Cañones' } }, 20190 'LL': { name: 'Lagos, lagunas, pantanos, presas y esteros', subtipos: { '1': 'Lagos', '2': 'Laguna', '3': 'Pantano', '4': 'Estero', '5': 'Presa' } }, 20191 'R': { name: 'RÃos y arroyos', subtipos: { '1': 'RÃo', '2': 'Arroyo' } }, 20192 'CM': { name: 'CaÃda de agua y manantiales', subtipos: { '1': 'CaÃda de agua y manantiales', '2': 'Manantiales' } }, 20193 'AT': { name: 'Aguas termales y minero-medicinales', subtipos: { '1': 'Aguas termales', '2': 'Aguas minero-medicinales' } }, 20194 'L': { name: 'Litorales', subtipos: { '1': 'Playas', '2': 'BahÃas', '3': 'PenÃnsulas', '4': 'Puntas', '5': 'Islas', '6': 'Caletas', '7': 'Manglares' } }, 20195 'G': { name: 'Grutas, cavernas y cuetas', subtipos: { '1': 'Grutas, cavernas y cuetas', '2': 'Cuevas' } }, 20196 'ANP': { name: 'Ãreas Naturales Protegidas', subtipos: { '1': 'Reservas de la Biósfera', '2': 'Parques Nacionales', '3': 'Parques Nacionales', '4': 'Ãreas de Protección de Recursos Naturales', '5': 'Ãreas de Protección de Flora y Fauna', '6': 'Santuarios' } }, 20197 'O': { name: 'Otros', subtipos: { '1': 'Bosques', '2': 'Selvas', '3': 'Miradores naturales', '4': 'Lugares paleontológicos' } } 20198 } }, 20199 'MHC' : { name: 'Manifestaciones Histórico Culturales', tipos: { 20200 'M': { name: 'Museos', subtipos: { '1': 'Arqueológico / Antropológico', '2': 'Arqueológico / Antropológico', '3': 'Historia natural', '4': 'Arte', '5': 'Historia', '6': 'Otros' } }, 20201 'A': { name: 'Arquitectura y espacios urbanos', subtipos: { '1': 'Iglesia', '2': 'Convento', '3': 'Capilla', '4': 'Casa de valor arquitectónico', '5': 'Casa - Hacienda', '6': 'Palacio o castillo', '7': 'Teatros', '8': 'Biblioteca', '9': 'Molino', '10': 'Edificaciones civiles (fortalezas, escuelas, colegios, etc.)', '11': 'Universidades', '12': 'Otros', '13': 'Plazas', '14': 'Alamedas', '15': 'Paseos', '16': 'Boulevares', '17': 'Malecones', '18': 'Santuarios', '19': 'Miradores', '20': 'Parques y Jardines', '21': 'Glorietas', '22': 'Puerto o embarcadero', '23': 'Obras de ingenierÃa (puentes, estación ferroviaria, etc.)' } }, 20202 'LH': { name: 'Lugares Históricos', subtipos: { '1': 'Casco urbano histórico', '2': 'Edificaciones civiles', '3': 'Edificiacione religiosas', '4': 'Barrios', '5': 'Puertos o embarcaderos', '6': 'Campo santo', '7': 'Campo de batalla', '8': 'Otros', '9': 'Obras de ingenierÃa (puentes, c
20202anales, etc.)' } }, 20203 'R': { name: 'Ruinas y Sitios Arqueológicos', subtipos: { '1': 'Edificaciones', '2': 'Pinturas rupestres', '3': 'Petroglifos', '4': 'Esculturas', '5': 'Geoglifos', '6': 'Sitios funerarios', '7': 'Otros' } }, 20204 'P': { name: 'Pueblos', subtipos: { '1': 'Pueblos históricos', '2': 'Pueblos tradicionales' } } 20205 } }, 20206 'F' : { name: 'Folklore', tipos: { 20207 'MR': { name: 'Manifestaciones religiosas y creencias populares', subtipos: { '1': 'Literatura', '2': 'Leyendas', '3': 'Mitos', '4': 'Ceremonias y costumbres religiosas' } }, 20208 'FM': { name: 'Ferias y mercados', subtipos: { '1': 'Mercados artesanales', '2': 'Tianguis', '3': 'Ferias artesanales' } }, 20209 'MD': { name: 'Música y Danzas', subtipos: { '1': 'Música y Danza' } }, 20210 'A': { name: 'ArtesanÃas y artes', subtipos: { '1': 'AlfarerÃa', '2': 'Cera', '3': 'Cerámica', '4': 'Cueros y pieles', '5': 'Madera / carpinterÃa', '6': 'Instrumentos musicales', '7': 'Metales', '8': 'Máscaras', '9': 'Objetos rituales', '10': 'Papel', '11': 'Piedras', '12': 'Pinturas', '13': 'Tejidos/indumentaria' } }, 20211 'G': { name: 'GastronomÃa', subtipos: { '1': 'Platillos tÃpicos', '2': 'Bebidas tÃpicas', '3': 'Dulces tÃpicos' } } 20212 } }, 20213 'RT' : { name: 'Realizaciones Técnicas, CientÃficas o ArtÃsticas Contemporáneas', tipos: { 20214 'EM': { name: 'Explotaciones mineras', subtipos: { '1': 'Explotaciones mineras' } }, 20215 'EA': { name: 'Explotaciones agropecuarias o pesqueras', subtipos: { '1': 'Agricultura', '2': 'GanaderÃa / Granjas', '3': 'Piscigranjas' } }, 20216 'EI': { name: 'Explotaciones industriales', subtipos: { '1': 'Fábricas', '2': 'Tra
20216piches', '3': 'Bodegas', '4': 'Destiladoras y vitivinÃcolas' } }, 20217 'C': { name: 'Centros CientÃficos y Técnicos', subtipos: { '1': 'Zoológicos', '2': 'Jardines Botánicos', '3': 'Planetarios', '4': 'Acuarios', '5': 'Viveros', '6': 'Túneles', '7': 'Puentes', '8': 'Hidroeléctricas', '9': 'Represas' } }, 20218 'P': { name: 'Planicies', subtipos: { '1': 'Desiertos', '2': 'Llanuras', '3': 'Pampas', '4': 'Salinas' } }, 20219 'O': { name: 'Otros' } 20220 } }, 20221 'AP' : { name: 'Acontecimientos Programados' } 20222 }; 20223 20224 }; 20225})(); 20226 20227//// File columns.component.js //// 20228(function() { 20229 20230 $angular.components['columns'] = { 20231 templateUrl: 'columns.component.html', 20232 bindings: { meta: '=', model: '<', columns: '=?', opts: '=?', ext: '=?', ientity: '=?' }, 20233 controller: function($scope, $timeout) { 20234 var self = $angular.prepareComponent(this, $scope, $timeout); 20235 20236 $scope.refresh = function() { 20237 if (self.columns) { 20238 20239 //console.log('#' + $scope.$id + ' init columns:' + self.columns.length + ' -> ' + getColumnNames()); 20240 $utils.initColumns($scope, self.meta, self.columns, self.model, self.opts, self.ext, self.ientity); 20241 20242 self.$onChanges = function(val) { 20243 if (val.model) { 20244 //console.log('model changed', val.model); 20245 $scope.refresh(); 20246 } 20247 }; 20248 20249 } else { 20250 $angular.log('warn: init columns with no columns') 20251 } 20252 }; 20253 20254// function getColumnNames() { 20255// var list = []; 20256// for (var k in self.columns) { 20257// if (list.length == 5) { 20258// list.push("..."); 20259// break; 20260// } 20261// var col = self.columns[k]; 20262// list.push(col.name); 20263// } 20264// return $utils.join(list, ", "); 20265// } 20266 20267 $scope.removeColumnItem = function(data, column, index, item) { 20268 20269 if ($utils.isBlank(item.id)) { 20270 // remove from list 20271 if (data[column.name] && $utils.isArray(data[column.name])) { 20272 data[column.name].splice(index, 1); 20273 } 20274 return; 20275 } 20276 20277 // remove from server 20278 //console.log(entity + " -> " + id) 20279 $rest.remove({ 20280 url: contextPath + "/api/geo/" + item.entity + "/" + item.id + ".json?force=true", 20281 loading: "generic", 20282 confirmTitle: $angular.get("$translate").instant("msg.remove"), 20283 successMessage: $angular.get("$translate").instant('msg.removed') 20284 }).then(function() { 20285 $angular.contentScope.refresh(); 20286 }); 20287 }; 20288 20289 } 20290 } 20291 20292})(); 20293 20294//// File spreadsheet-filters.component.js //// 20295(function() { 20296 20297 $angular.controllers['spreadsheet-filters-component'] = function($scope) { 20298 20299 $scope.$on('initSpreadsheetFiltersComponent', function(event, config) { 20300 $scope.spreadsheet = config.model; 20301 $scope.model = prepareModel(); 20302 }); 20303 20304 $scope.$on('refreshSpreadsheetFiltersComponent', function(event, data) { 20305 $scope.spreadsheet = data.model; 20306 $scope.model = prepareModel(); 20307 }); 20308 20309 $scope.$watch('model.custom', function(val) { 20310 if (!$scope.spreadsheet.filters) { 20311 $scope.spreadsheet.filters = {}; 20312 } 20313 $scope.spreadsheet.filters.custom = val; 20314 }); 20315 20316 $scope.$watch('model.query', function(val) { 20317 if (!$scope.spreadsheet.filters) { 20318 $scope.spreadsheet.filters = {}; 20319 } 20320 $scope.spreadsheet.filters.query = val; 20321 }); 20322 20323 $scope.buildQuery = function() { 20324 var entity = $scope.spreadsheet.entities && $scope.spreadsheet.entities.length > 0 ? $scope.spreadsheet.entities[0] : null; 20325 $angular.openModalLocal('panel-query-builder', { 20326 size: 'xl', 20327 entity: entity, 20328 query: $scope.model.query 20329 }).then(function(result) { 20330 $scope.model.query = result; 20331 }); 20332 }; 20333 20334 function prepareModel() { 20335 var model = { 20336 custom: false, 20337 columns: [] 20338 }; 20339 var filters = $scope.spreadsheet.filters; 20340 if (filters) { 20341 model.query = filters.query; 20342 model.custom = $utils.isTrue(filters.custom); 20343 if (filters.columns) { 20344 model.columns = angular.fromJson(filters.columns); 20345 } 20346 } 20347 return model; 20348 } 20349 20350 $scope.onChange = function(columns) { 20351 if (!$scope.spreadsheet.filters) { 20352 $scope.spreadsheet.filters = {}; 20353 } 20354 $scope.spreadsheet.filters.columns = angular.toJson(columns); 20355 }; 20356 } 20357})(); 20358 20359//// File fidesur-eval.js //// 20360(function() { 20361 20362 $angular.controllers['fidesur-eval-component'] = function($scope, $element) { 20363 20364 function verifyData() { 20365 var o = $angular.contentScope.model.fidesur_eval; 20366 if (o == null) { 20367 o = {}; 20368 $angular.contentScope.model.fidesur_eval = o; 20369 } 20370 } 20371 verifyData(); 20372 20373 $angular.contentScope.submitFidesurEval = function() { 20374 $rest.put({ 20375 url: contextPath + '/api/geo/' + $angular.contentScope.entity + '/' + $angular.contentScope.entityId + '/updateCustom.json', 20376 form: '#fidesurEvalForm', 20377 loading: 'generic', 20378 successMessage: $angular.get('$translate').instant('msg.updated') 20379 }).then(function(data, url) { 20380 if ($angular.contentScope.postSubmit) { 20381 $angular.contentScope.postSubmit(); 20382 } 20383 }); 20384 }; 20385 } 20386 20387})(); 20388//// File input-check.js //// 20389(function() { 20390 20391 $angular.components['inputCheck'] = { 20392 //transclude: true, 20393 templateUrl: "input-check.html", 20394 bindings: { 20395 key: '@', model: '=', label: '@', required: '@', changed: '&' 20396 }, 20397 controller: function($scope, $timeout) { 20398 $scope.rw = $utils.getRandom(); 20399 var self = this; 20400 $timeout(function() { 20401 self.model = $utils.isTrue(self.model); 20402// console.log("key: " + self.key); 20403// console.log("model", self.model); 20404// console.log("msg: " + self.msg); 20405 }); 20406 } 20407 } 20408 20409})(); 20410//// File cart-content.component.js //// 20411(function() { 20412 20413 $angular.components['cartContent'] = { 20414 templateUrl: 'cart-content.component.html', 20415 bindings: { 20416 cart: '<', 20417 readonly: '<', 20418 showFormEntities: '<', 20419 onChange: '&' 20420 }, 20421 controller: function($scope, $timeout) { 20422 var self = $angular.prepareComponent(this, $scope, $timeout); 20423 20424 self.$onChanges = function() { 20425 $scope.refresh(); 20426 }; 20427 20428 $scope.refresh = function() { 20429 20430 $scope.readonly = self.readonly; 20431 $scope.onChange = self.onChange; 20432 $scope.cart = self.cart; 20433 20434 $scope.formConfigs = {}; 20435 20436 if (self.showFormEntities) { 20437 prepareFormConfigs(); 20438 } 20439 }; 20440 20441 $scope.remove = function(item) { 20442 $cart.removeItem(item); 20443 emitOnChange(); 20444 }; 20445 20446 $scope.addQuantity = function(item) { 20447 item.quantity++; 20448 $scope.modifiedQuantity(item); 20449 }; 20450 20451 $scope.removeQuantity = function(item) { 20452 if (item.quantity === 1) { 20453 return; 20454 } 20455 item.quantity--; 20456 $scope.modifiedQuantity(item); 20457 }; 20458 20459 $scope.modifiedQuantity = function(item) { 20460 if (isValidQuantity(item)) { 20461 $cart.addItem(item.product.entity, item.product.entity_id, item); 20462 emitOnChange(); 20463 } 20464 }; 20465 20466 function emitOnChange() { 20467 if ($scope.onChange) { 20468 var ready = Object.keys($scope.formConfigs).every(function(key) { 20469 var config = $scope.formConfigs[key]; 20470 return config == null || config.ready; 20471 }); 20472 $scope.onChange({ 20473 isReady: ready && !hasInvalidQuantities() 20474 }); 20475 } 20476 } 20477 20478 function hasInvalidQuantities() { 20479 if (!$scope.readonly) { 20480 var items = $scope.cart.items; 20481 if (items) { 20482 for (var iter = 0; iter < items.length; iter++) { 20483 var item = items[iter]; 20484 if (!isValidQuantity(item) || (item.stock != null && item.stock < item.quantity)) { 20485 return true; 20486 } 20487 } 20488 } 20489 } 20490 return false;
20491 } 20492 20493 function isValidQuantity(item) { 20494 var quantity = item.quantity; 20495 return quantity && !isNaN(quantity) && quantity > 0 && quantity < 1000000; 20496 } 20497 20498 function prepareFormConfigs() { 20499 var items = $scope.cart ? $scope.cart.items : null; 20500 if (!items) { 20501 return; 20502 } 20503 20504 items.forEach(function(cartItem) { 20505 var key = cartItem.product.entity + ';' + cartItem.product.entity_id; 20506 var formEntity = cartItem.extra_data_entity; 20507 if (formEntity && $entity.isGeoForm(formEntity) && $entity.isPermitted(formEntity, 'create')) { 20508 var config = { 20509 entity: $entity.getEntity(formEntity), 20510 ready: true 20511 }; 20512 config.onChange = function(formModel, isReady) { 20513 config.ready = isReady; 20514 cartItem.extra_data = formModel; 20515 emitOnChange(); 20516 }; 20517 $scope.formConfigs[key] = config; 20518 } 20519 }); 20520 emitOnChange(); 20521 } 20522 } 20523 }; 20524})(); 20525 20526//// File price-breakdown.component.js //// 20527(function() { 20528 20529 $angular.components['priceBreakdown'] = { 20530 templateUrl: 'price-breakdown.component.html', 20531 bindings: {cart: '<', hideTip: '<', hideShippingCosts: '<'}, 20532 controller: function($scope, $timeout) { 20533 var self = $angular.prepareComponent(this, $scope, $timeout); 20534 20535 self.$onChanges = function() { 20536 $scope.refresh(); 20537 }; 20538 20539 $scope.refresh = function() { 20540 $scope.hideTip = self.hideTip; 20541 $scope.hideShippingCosts = self.hideShippingCosts; 20542 prepareData(self.cart); 20543 }; 20544 20545 function prepareData(cart) { 20546 if (cart) { 20547 var cartSubtotal = 0; 20548 var taxes = {}; 20549 var dataItems = []; 20550 for (var i in cart.items) { 20551 var item = cart.items[i]; 20552 var price = 0; 20553 var discount = 0; 20554 if (!$utils.isTrue(item.free)) { 20555 if (item.price > 0) { 20556 price = Number(item.price); 20557 } 20558 if (item.discount > 0) { 20559 discount = Number(item.discount); 20560 } 20561 } 20562 var amountWithoutTaxes = price - discount; 20563 if (amountWithoutTaxes < 0) { 20564 amountWithoutTaxes = 0; 20565 } 20566 var taxAmount = 0; 20567 if (amountWithoutTaxes > 0 && item.tax && !isNaN(item.tax)) { 20568 var tax = taxes[item.tax]; 20569 if (!tax) { 20570 tax = 0; 20571 } 20572 taxAmount = (Math.round((amountWithoutTaxes * Number(item.tax)) + Number.EPSILON) / 100); 20573 taxes[item.tax] = tax + (taxAmount * item.quantity); 20574 } 20575 cartSubtotal += item.amount * item.quantity; 20576 dataItems.push({ 20577 name: item.name, 20578 quantity: item.quantity, 20579 unitAmount: amountWithoutTaxes, 20580 totalAmount: amountWithoutTaxes * item.quantity 20581 }); 20582 } 20583 20584 var cartTotal = cartSubtotal; 20585 if (!$scope.hideTip && cart.tip && !isNaN(cart.tip)) { 20586 cartTotal += cart.tip; 20587 } 20588 20589 if (!$scope.hideShippingCosts && cart.delivery_method && cart.delivery_method.price && !isNaN(cart.delivery_method.price)) { 20590 cartTotal += cart.delivery_method.price; 20591 } 20592 20593 cartTotal = Math.round((cartTotal + Number.EPSILON) * 100) / 100; 20594 cartSubtotal = Math.round((cartSubtotal + Number.EPSILON) * 100) / 100; 20595 20596 $scope.data = { 20597 items: dataItems, 20598 taxes: Object.keys(taxes).length > 0 ? taxes : null, 20599 totalAmount: cartTotal, 20600 subtotalAmount: cartSubtotal, 20601 tip: cart.tip, 20602 shippingCosts: cart.delivery_method ? cart.delivery_method.price : null 20603 }; 20604 } else { 20605 $scope.data = null; 20606 } 20607 } 20608 } 20609 }; 20610})(); 20611 20612//// File login.component.js //// 20613(function() { 20614 20615 $angular.components['login'] = { 20616 templateUrl: 'login.component.html', 20617 bindings: { 20618 hideTitle: '<', 20619 onLogin: '&', 20620 onCancel: '&' 20621 }, 20622 controller: function($scope, $timeout, $attrs) { 20623 var self = $angular.prepareComponent(this, $scope, $timeout); 20624 20625 self.$onChanges = function() { 20626 $scope.refresh(); 20627 }; 20628 20629 $scope.refresh = function() { 20630 20631 $scope.user = null; 20632 $scope.model = {}; 20633 $scope.showTitle = !$utils.isTrue(self.hideTitle); 20634 20635 $scope.showSignUp = $constants.isWeb; 20636 if ($instance.current && $instance.current.geo_login) { 20637 var login = $instance.current.geo_login; 20638 if ($utils.isTrue(login.disabled_register)) { 20639 $scope.showSignUp = false;
20640 } 20641 if ($utils.isTrue(login.disabled)) { 20642 self.onCancel(); 20643 $utils.showAccessDenied(); 20644 } 20645 } 20646 }; 20647 20648 function hideAll() { 20649 $scope.showBack = false; 20650 $("#login").hide(); 20651 $("#register").hide(); 20652 $("#update").hide(); 20653 $("#restore").hide(); 20654 $("#restoring").hide(); 20655 $("#verify").hide(); 20656 } 20657 20658 $scope.back = function() { 20659 hideAll(); 20660 $("#login").fadeIn(); 20661 20662 if ($scope.user) { 20663 $scope.signOut(); 20664 } 20665 }; 20666 $scope.showRegister = function() { 20667 hideAll(); 20668 $scope.model.user_id = ""; 20669 $scope.model.name = ""; 20670 $("#register").fadeIn(); 20671 $scope.showBack = true; 20672 }; 20673 $scope.showUpdate = function() { 20674 hideAll(); 20675 $("#update").fadeIn(); 20676 $scope.showBack = true; 20677 }; 20678 $scope.showRestore = function() { 20679 hideAll(); 20680 $("#restore").fadeIn(); 20681 $scope.showBack = true; 20682 }; 20683 $scope.showRestoring = function() { 20684 hideAll(); 20685 $("#restoring").fadeIn(); 20686 $scope.showBack = true; 20687 }; 20688 $scope.showVerify = function() { 20689 hideAll(); 20690 $("#verify").fadeIn(); 20691 $scope.showBack = true; 20692 $scope.sendEmailVerify(); 20693 }; 20694 20695 $scope.signOut = function(callback) { 20696 $scope.user = null; 20697 firebase.auth().signOut().then(function() { 20698 if (callback) { 20699 callback(); 20700 } 20701 }, function() { 20702 if (callback) { 20703 callback(); 20704 } 20705 }); 20706 }; 20707 20708 $scope.login = function() { 20709 $utils.closeFloating(); 20710 20711 var email = $scope.model.email; 20712 var password = $scope.model.password; 20713 if ($utils.isBlank(email) || $utils.isBlank(password)) { 20714 return; 20715 } 20716 20717 $utils.showLoading(); 20718 $scope.signOut(function() { 20719 firebase.auth().signInWithEmailAndPassword(email, password).then(function(o) { 20720 $utils.hideLoading(); 20721 20722 var user = o.user; 20723 $scope.user = user; 20724 if (!user.emailVerified) { 20725 $scope.showVerify(); 20726 return; 20727 } 20728 20729 // login ok 20730 $scope.model.token = user.refreshToken; 20731 $scope.model.password = null; 20732 $angular.apply($scope); 20733 $scope.loginFinal(); 20734 20735 }).catch(function() { 20736 $utils.hideLoading(); 20737 20738 $scope.model.token = ""; 20739 $angular.apply($scope); 20740 $scope.loginFinal(); 20741 }); 20742 }); 20743 }; 20744 20745 $scope.loginWithGoogle = function() { 20746 $utils.closeFloating(); 20747 $utils.showLoading(); 20748 20749 var provider = new firebase.auth.GoogleAuthProvider(); 20750 firebase.auth().signInWithPopup(provider).then(function(result) { 20751 $utils.hideLoading(); 20752 20753 var user = result.user; 20754 $scope.user = user; 20755 20756 // login ok 20757 $scope.model.email = user.email; 20758 $scope.model.token = user.refreshToken || (user.stsTokenManager && user.stsTokenManager.refreshToken); 20759 $scope.model.password = null; 20760 $angular.apply($scope); 20761 $scope.loginFinal(); 20762 20763 }).catch(function(error) { 20764 $utils.hideLoading(); 20765 console.error("Google sign in error", error); 20766 resolveError(error, error.message); 20767 }); 20768 }; 20769 20770 $scope.loginFinal = function() { 20771 $rest.post({ 20772 loading: "generic", 20773 url: contextPath + "/log-in", 20774 contentType: "urlencoded", 20775 form: "#loginForm", 20776 showError: false 20777 }).then(function() { 20778 $user.set($attrs.onLogin ? self.onLogin : null); 20779 20780 }).catch(function(e) { 20781 resolveError(e, "msg.login.error"); 20782 }); 20783 } 20784 20785 $scope.register = function() { 20786 $utils.closeFloating(); 20787 20788 if (!$utils.isTrue($scope.model.licenses)) { 20789 return; 20790 } 20791 20792 $rest.post({ 20793 loading: "generic", 20794 url: contextPath + "/www/user.json", 20795 contentType: "urlencoded", 20796 form: "#registerForm", 20797 showError: false, 20798 successMessage: $angular.get("$translate").instant("msg.created") 20799 }).then(function() { 20800 $scope.back(); 20801 }).catch(function(e) { 20802 resolveError(e); 20803 }); 20804 }; 20805 20806 $scope.update = function() { 20807 $utils.closeFloating(); 20808 20809 if (!$utils.isTrue($scope.model.licenses)) { 20810 return; 20811 } 20812 20813 $rest.post({ 20814 loading: "generic", 20815 url: contextPath + "/www/user/a/update.json", 20816 contentType: "urlencoded", 20817 form: "#updateForm", 20818 showError: false, 20819 successMessage: $angular.get("$translate").instant("msg.updated") 20820 }).then(function() { 20821 $scope.back(); 20822 20823 }).catch(function(e) { 20824 resolveError(e); 20825 }); 20826 }; 20827 20828 $scope.restore = function() { 20829 $utils.closeFloating(); 20830 20831 if ($utils.isBlank($scope.model.email) || !$utils.isEmail($scope.model.email)) { 20832 console.log('invalid email') 20833 return; 20834 } 20835 20836 $rest.post({ 20837 loading: "generic", 20838 url: contextPath + "/www/user/a/restore.json", 20839 data: $scope.model, 20840 showError: false 20841 }).then(function() { 20842 $scope.showRestoring(); 20843 }).catch(function() { 20844 $scope.showRestoring(); 20845 }); 20846 }; 20847 20848 $scope.sendEmailVerify = function() { 20849 var email = $scope.model.email; 20850 var password = $scope.model.password; 20851 $utils.showLoading(); 20852 20853 if ($scope.user && $scope.user.email === email) { 20854 sendEmail(); 20855 return; 20856 } 20857 20858 firebase.auth().signInWithEmailAndPassword(email, password).then(function(o) { 20859 $scope.user = o.user; 20860 sendEmail(); 20861 20862 }).catch(function() { 20863 $utils.hideLoading(); 20864 $utils.floatingError($angular.get("$translate").instant("msg.error")); 20865 $scope.back(); 20866 }); 20867 }; 20868 20869 function sendEmail() { 20870 $rest.post({ 20871 loading: "generic", 20872 url: contextPath + "/www/user/a/verify.json", 20873 data: $scope.model, 20874 showError: false 20875 }).then(function() { 20876 $utils.hideLoading(); 20877 }).catch(function() { 20878 $utils.hideLoading(); 20879 $utils.floatingError($angular.get("$translate").instant("msg.error")); 20880 $scope.back(); 20881 }); 20882 } 20883 20884 $scope.verify = function() { 20885 $utils.closeFloating(); 20886 20887 var email = $scope.model.email; 20888 var password = $scope.model.password; 20889 $utils.showLoading(); 20890 firebase.auth().signInWithEmailAndPassword(email, password).then(function(o) { 20891 $utils.hideLoading(); 20892 20893 var user = o.user; 20894 $scope.user = user; 20895 if (user.emailVerified) { 20896 $scope.back(); 20897 $scope.login(); 20898 return; 20899 } 20900 $utils.floatingError($angular.get("$translate").instant("msg.verify.error")); 20901 20902 }).catch(function(error) { 20903 $utils.hideLoading(); 20904 console.log('error verifying: ' + error.message); 20905 $utils.floatingError($angular.get("$translate").instant("msg.error")); 20906 $scope.back(); 20907 }); 20908 20909 }; 20910 20911 function resolveError(e, msg) { 20912 //console.log('error login', e.response) 20913 20914 if (e && e.response && e.response.status === 409) { 20915 20916 if (e.response.data && e.response.data.key === "UPDATE") { 20917 $scope.showUpdate(); 20918 $scope.model.user_id = e.response.data.user_id; 20919 $scope.model.name = e.response.data.name; 20920 $scope.model.username = $scope.model.email; 20921 $scope.model.password_old = $scope.model.password; 20922 return true; 20923 } 20924 20925 if (e.response.data && e.response.data.key === "NOT_VERIFIED") { 20926 $scope.showVerify(); 20927 return true; 20928 } 20929 20930 if (e.response.data && e.response.data.key === "RESTORE") { 20931 $scope.showRestore(); 20932 return true; 20933 } 20934 20935 if (e.response.data && e.response.data.key === "APP_ERROR") { 20936 $utils.floatingError($angular.get("$translate").instant(e.response.data.messageKey)); 20937 return true; 20938 } 20939 20940 } 20941 20942 if (msg) { 20943 $utils.floatingError($angular.get("$translate").instant(msg)); 20944 } else if (e.msg) { 20945 $utils.floatingError(e.msg); 20946 } else { 20947 $utils.floatingError($angular.get("$translate").instant("msg.error")); 20948 } 20949 20950 return false;
20951 } 20952 } 20953 }; 20954})(); 20955 20956//// File entity-columns.component.js //// 20957(function() { 20958 20959 $angular.components['entityColumns'] = { 20960 templateUrl: 'entity-columns.component.html', 20961 bindings: { 20962 model: '<', noEdit: '<', showInfo: '<', noJson: '<', 20963 labeled: '<', rowColPosition: '<', compareOperators: '<', autopathEnabled: '<', autopathRootEntity: '<', 20964 onChange: '&' 20965 }, 20966 controller: function($scope, $timeout) { 20967 var self = $angular.prepareComponent(this, $scope, $timeout); 20968 20969 //console.log('init columns ' + $scope.$id + ' controller'); 20970 $scope.refresh = function() { 20971 if (self.model) { 20972 20973 //console.log('#' + $scope.$id + ' init entity columns', self.model); 20974 $scope.entity = $angular.contentScope.entity; 20975 $scope.editImage = $angular.contentScope.editImage; 20976 20977 $scope.model = self.model; 20978 $scope.editEnabled = !$utils.isTrue(self.noEdit); 20979 $scope.jsonEditEnabled = !$utils.isTrue(self.noJson) && $user.isModeler(); 20980 $scope.showInfo = $utils.isTrue(self.showInfo); 20981 $scope.labeled = $utils.isTrue(self.labeled); 20982 $scope.rowColPosition = $utils.isTrue(self.rowColPosition); 20983 $scope.compareOperators = $utils.isTrue(self.compareOperators); 20984 $scope.autopathEnabled = $utils.isTrue(self.autopathEnabled); 20985 20986 if ($scope.entity === 'entity' && $scope.model.columns) { 20987 // save last name/type to detect column renames etc 20988 $scope.model.columns.forEach(function(col) { 20989 col._name = col.name; 20990 col._type = col.type; 20991 }); 20992 } 20993 20994 $scope.$watch('model', self.onChange, true); 20995 20996 self.$onChanges = function(val) { 20997 if (val.model) { 20998 console.log('entity columns model changed', val.model); 20999 $scope.refresh(); 21000 } 21001 }; 21002 21003 } else { 21004 $angular.log('warn: init entity columns with no model') 21005 } 21006 }; 21007 21008 $scope.addColumn = function(o) { 21009 if (o.columns == null) { 21010 o.columns = []; 21011 } 21012 var column = {}; 21013 if ($scope.entity === 'entity') { 21014 column.type = 'string'; 21015 } else if ($scope.entity === 'form') { 21016 column.long = true; 21017 } 21018 o.columns.push(column); 21019 }; 21020 $scope.removeColumn = function(o, index) { 21021 o.columns.splice(index, 1); 21022 }; 21023 21024 $scope.editColumnsAsJson = function(obj) { 21025 if (!obj.columns) { 21026 obj.columns = []; 21027 } 21028 $angular.openModal('panel-edit-json', { 21029 json: obj.columns, 21030 size: 'lg', 21031 successFunction: function(json) { 21032 if (Array.isArray(json)) { 21033 obj.columns.length = 0; 21034 obj.columns.push.apply(obj.columns, json); 21035 } 21036 } 21037 }); 21038 }; 21039 21040 $scope.reloadFormulas = function(obj) { 21041 $rest.post({ 21042 url: contextPath + "/api/geo/" + obj.id + "/a/reloadFormulas.json", 21043 loading: "generic", 21044 successMessage: $angular.get("$translate").instant('msg.done') 21045 }).then(function(o) { 21046 }); 21047 }; 21048 21049 $scope.showChecks = null; 21050 $scope.editChecks = function(key) { 21051 $scope.showChecks = key; 21052 } 21053 $scope.closeChecks = function() { 21054 $scope.showChecks = null; 21055 } 21056 21057 $scope.selectColumnType = function(column) { 21058 $angular.openModal('panel-column-types', { 21059 column: column, 21060 size: 'lg' 21061 }); 21062 } 21063 21064 $scope.hasColumns = function(column) { 21065 if (column.columns && column.columns.length > 0) { 21066 return true; 21067 } 21068 if (column.type == 'group' || column.type == 'relation_entity' || column.type == 'relation' || column.type == 'table') { 21069 return true; 21070 } 21071 if ($scope.entity == 'form' && (column.type == 'inner_entity' || column.type == 'inner_entity_list')) { 21072 return true; 21073 } 21074 return false; 21075 }; 21076 21077 $scope.getEntities = function() { 21078 if ($scope.entity === 'spreadsheet') { 21079 return $scope.model.entities ? $scope.model.entities : []; 21080 21081 } else if ($scope.entity === 'synchronizer') { 21082 return $scope.model.entity_to_sync ? [$scope.model.entity_to_sync] : []; 21083 21084 } else if ($scope.model.root_entity) { 21085 return [$scope.model.root_entity]; 21086 21087 } else if ($angular.contentScope.entityId) { 21088 return [$angular.contentScope.entityId]; 21089 } 21090 return []; 21091 }; 21092 21093 $scope.getInnerEntities = function() { 21094 var innerEntities = [];
21095 $scope.getEntities().forEach(function(entityId) { 21096 var e = $entity.getEntity(entityId); 21097 if (e && e.inner_entities) { 21098 e.inner_entities.forEach(function(innerEntity) { 21099 if (innerEntities.indexOf(innerEntity) < 0) { 21100 innerEntities.push(innerEntity); 21101 } 21102 }); 21103 } 21104 }); 21105 return innerEntities; 21106 }; 21107 21108 $scope.getAutoPathEntity = function() { 21109 var entity = $scope.model.param; 21110 if ($utils.isBlank(entity)) { 21111 entity = self.autopathRootEntity; 21112 } 21113 if ($utils.isBlank(entity)) { 21114 entity = $scope.getEntities().join(','); 21115 } 21116 return entity; 21117 }; 21118 21119 $scope.isShowDoc = false; 21120 $scope.showDoc = function() { 21121 $scope.isShowDoc = !$scope.isShowDoc; 21122 }; 21123 21124 $scope.buildFormula = function(column) { 21125 var entity = $scope.getAutoPathEntity(); 21126 if (entity && entity.indexOf(',') >= 0) { 21127 entity = entity.split(',')[0]; 21128 } 21129 $angular.openModalLocal('panel-formula-builder', { 21130 size: 'xl', 21131 entity: entity, 21132 formula: column.formula 21133 }).then(function(result) { 21134 column.formula = result; 21135 }); 21136 }; 21137 } 21138 } 21139})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.