Switch javascript to coffeescript
This commit is contained in:
parent
1500a1b8b2
commit
d1923af517
14
Makefile
14
Makefile
|
@ -190,6 +190,10 @@ JSSRCFILES:=$(shell find $(SRCMANAGERDIR)/site/static/js $(SRCPORTALDIR)/example
|
||||||
$(SRCMANAGERDIR)/site/static/bwr/file-saver.js/FileSaver.js
|
$(SRCMANAGERDIR)/site/static/bwr/file-saver.js/FileSaver.js
|
||||||
CSSSRCFILES:=$(shell find $(SRCMANAGERDIR)/site/static/css $(SRCPORTALDIR)/example -type f -name '*.css' ! -name '*.min.css')
|
CSSSRCFILES:=$(shell find $(SRCMANAGERDIR)/site/static/css $(SRCPORTALDIR)/example -type f -name '*.css' ! -name '*.min.css')
|
||||||
|
|
||||||
|
# Coffee files
|
||||||
|
COFFEESRCFILES:=$(shell find $(SRCMANAGERDIR)/site/coffee/ -type f)
|
||||||
|
COFFEEDSTFILES:=$(subst coffee/,static/js/,$(COFFEESRCFILES:.coffee=.js))
|
||||||
|
|
||||||
# Minified files
|
# Minified files
|
||||||
JSDSTFILES=$(JSSRCFILES:.js=.min.js)
|
JSDSTFILES=$(JSSRCFILES:.js=.min.js)
|
||||||
CSSDSTFILES=$(CSSSRCFILES:.css=.min.css)
|
CSSDSTFILES=$(CSSSRCFILES:.css=.min.css)
|
||||||
|
@ -258,6 +262,12 @@ configure: json common_conf handler_conf portal_conf manager_conf
|
||||||
|
|
||||||
minify: $(JSDSTFILES) $(CSSDSTFILES)
|
minify: $(JSDSTFILES) $(CSSDSTFILES)
|
||||||
|
|
||||||
|
$(SRCMANAGERDIR)/site/static/js/%.js: $(SRCMANAGERDIR)/site/coffee/%.coffee
|
||||||
|
@if which coffee >/dev/null; then \
|
||||||
|
echo "Compiling $(SRCMANAGERDIR)/site/coffee/$*.coffee"; \
|
||||||
|
coffee -c -o $(SRCMANAGERDIR)/site/static/js/ $(SRCMANAGERDIR)/site/coffee/$*.coffee; \
|
||||||
|
fi
|
||||||
|
|
||||||
%.min.css: %.css
|
%.min.css: %.css
|
||||||
@echo "Compressing $*.css"
|
@echo "Compressing $*.css"
|
||||||
@yui-compressor $*.css > $*.min.css
|
@yui-compressor $*.css > $*.min.css
|
||||||
|
@ -272,7 +282,7 @@ fastcgi-server/man/llng-fastcgi-server.1p: fastcgi-server/sbin/llng-fastcgi-serv
|
||||||
# Perl libraries configuration
|
# Perl libraries configuration
|
||||||
|
|
||||||
json: $(MANAGERJSONDST) fastcgi-server/man/llng-fastcgi-server.1p
|
json: $(MANAGERJSONDST) fastcgi-server/man/llng-fastcgi-server.1p
|
||||||
@if which yui-compressor; then $(MAKE) minify; fi
|
@if which yui-compressor >/dev/null; then $(MAKE) minify; fi
|
||||||
|
|
||||||
$(MANAGERJSONDST): $(MANAGERJSONSRC)
|
$(MANAGERJSONDST): $(MANAGERJSONSRC)
|
||||||
./scripts/jsongenerator.pl
|
./scripts/jsongenerator.pl
|
||||||
|
@ -1010,7 +1020,7 @@ tidy: clean
|
||||||
$(MAKE) json
|
$(MAKE) json
|
||||||
|
|
||||||
tidy-js: clean
|
tidy-js: clean
|
||||||
@find $(SRCMANAGERDIR)/site/static/js/ e2e-tests/ $(SRCPORTALDIR)/example \
|
@find e2e-tests/ $(SRCPORTALDIR)/example \
|
||||||
-type f \
|
-type f \
|
||||||
-name '*.js' \
|
-name '*.js' \
|
||||||
! -name 'jq*' \
|
! -name 'jq*' \
|
||||||
|
|
237
lemonldap-ng-manager/site/coffee/llApp.coffee
Normal file
237
lemonldap-ng-manager/site/coffee/llApp.coffee
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
###
|
||||||
|
LemonLDAP::NG base app module
|
||||||
|
|
||||||
|
This file contains:
|
||||||
|
- 3 AngularJS directives (HTML attributes):
|
||||||
|
* `on-read-file` to get file content
|
||||||
|
* `resizer` to resize HTML div
|
||||||
|
* `trspan` to set translated message in HTML content
|
||||||
|
- a AngularJS factory to handle 401 Ajax responses
|
||||||
|
###
|
||||||
|
|
||||||
|
llapp = angular.module 'llApp', []
|
||||||
|
|
||||||
|
# TRANSLATION SYSTEM
|
||||||
|
#
|
||||||
|
# It provides:
|
||||||
|
# - 3 functions to translate:
|
||||||
|
# * translate(word)
|
||||||
|
# * translateP(paragraph): only __words__ are translated
|
||||||
|
# * translateField(object, property)
|
||||||
|
# - an HTML attribute called 'trspan'. Exemple: <h3 trspan="portal"/>
|
||||||
|
|
||||||
|
# $translator provider
|
||||||
|
|
||||||
|
llapp.provider '$translator', ->
|
||||||
|
res = {}
|
||||||
|
# Language detection
|
||||||
|
if navigator
|
||||||
|
langs = []
|
||||||
|
langs2 = []
|
||||||
|
nlangs = [ navigator.language ]
|
||||||
|
if navigator.languages
|
||||||
|
nlangs = navigator.languages
|
||||||
|
for nl in nlangs
|
||||||
|
for al in window.availableLanguages
|
||||||
|
if al == nl
|
||||||
|
langs.push al
|
||||||
|
else if al.substring(0, 1) == nl.substring(0, 1)
|
||||||
|
langs2.push al
|
||||||
|
res.lang = if langs[0] then langs[0] else if langs2[0] then langs2[0] else 'en';
|
||||||
|
else
|
||||||
|
res.lang = 'en'
|
||||||
|
|
||||||
|
# Internal properties
|
||||||
|
res.deferredTr = []
|
||||||
|
res.translationFields = {}
|
||||||
|
|
||||||
|
# Translation methods
|
||||||
|
# 1. word translation
|
||||||
|
res.translate = (s) ->
|
||||||
|
if res.translationFields[s]
|
||||||
|
s = res.translationFields[s]
|
||||||
|
return s
|
||||||
|
|
||||||
|
# 2. node field translation
|
||||||
|
res.translateField = (node, field) ->
|
||||||
|
res.translate node[field]
|
||||||
|
|
||||||
|
# 3. paragraph translation (verify that json is available
|
||||||
|
res.translateP = (s) ->
|
||||||
|
if s and res.translationFields.portal
|
||||||
|
s = s.replace /__(\w+)__/g, (match,w) ->
|
||||||
|
res.translate w
|
||||||
|
s
|
||||||
|
|
||||||
|
# Initialization
|
||||||
|
this.$get = [ '$q', '$http', ($q, $http) ->
|
||||||
|
res.last = ''
|
||||||
|
res.init = (lang) ->
|
||||||
|
lang = res.lang unless lang
|
||||||
|
d = $q.defer()
|
||||||
|
if res.last != lang
|
||||||
|
res.last = lang
|
||||||
|
$http.get("#{window.staticPrefix}languages/#{lang}.json").then (response) ->
|
||||||
|
res.translationFields = response.data
|
||||||
|
for h in res.deferredTr
|
||||||
|
h.e[h.f] res.translationFields[h.m]
|
||||||
|
res.deferredTr = []
|
||||||
|
d.resolve "Translation files loaded"
|
||||||
|
, (response) ->
|
||||||
|
d.reject ''
|
||||||
|
else
|
||||||
|
d.resolve "No change"
|
||||||
|
d.promise
|
||||||
|
res
|
||||||
|
]
|
||||||
|
this
|
||||||
|
|
||||||
|
# Translation directive (HTML trspan tag)
|
||||||
|
llapp.directive 'trspan', [ '$translator', ($translator) ->
|
||||||
|
restrict: 'A'
|
||||||
|
replace: false
|
||||||
|
transclude: true
|
||||||
|
scope:
|
||||||
|
trspan: "@"
|
||||||
|
link: (scope, elem, attr) ->
|
||||||
|
if $translator.translationFields.portal
|
||||||
|
attr.trspan = $translator.translate(attr.trspan)
|
||||||
|
# Deferred translations will be done after JSON download
|
||||||
|
else
|
||||||
|
$translator.deferredTr.push
|
||||||
|
e: elem
|
||||||
|
f: 'text'
|
||||||
|
m: attr.trspan
|
||||||
|
elem.text attr.trspan
|
||||||
|
template: ''
|
||||||
|
]
|
||||||
|
|
||||||
|
# Form menu management
|
||||||
|
#
|
||||||
|
# Two parts:
|
||||||
|
# - $htmlParams: used to store values inserted as <script type="text/menu">.
|
||||||
|
# It provides menu() method to get them
|
||||||
|
# - HTML "script" element handler
|
||||||
|
llapp.provider '$htmlParams', ->
|
||||||
|
this.$get = ->
|
||||||
|
params = {}
|
||||||
|
set: (key, obj) ->
|
||||||
|
params[key] = obj
|
||||||
|
menu: ->
|
||||||
|
params.menu
|
||||||
|
# To be used later
|
||||||
|
params: ->
|
||||||
|
params.params
|
||||||
|
this
|
||||||
|
|
||||||
|
llapp.directive 'script', ['$htmlParams', ($htmlParams) ->
|
||||||
|
restrict: 'E'
|
||||||
|
terminal: true
|
||||||
|
compile: (element, attr) ->
|
||||||
|
if t = attr.type.match /text\/(menu|parameters)/
|
||||||
|
$htmlParams.set t[1], eval element[0].text
|
||||||
|
]
|
||||||
|
|
||||||
|
# Modal controller used to display messages
|
||||||
|
|
||||||
|
llapp.controller 'ModalInstanceCtrl', ['$scope', '$uibModalInstance', 'elem', 'set', 'init', ($scope, $uibModalInstance, elem, set, init) ->
|
||||||
|
oldvalue = null
|
||||||
|
$scope.elem = elem
|
||||||
|
$scope.set = set
|
||||||
|
$scope.result = init
|
||||||
|
$scope.staticPrefix = window.staticPrefix
|
||||||
|
currentNode = elem 'currentNode'
|
||||||
|
$scope.translateP = elem 'translateP'
|
||||||
|
if currentNode
|
||||||
|
oldValue = currentNode.data
|
||||||
|
$scope.currentNode = currentNode
|
||||||
|
|
||||||
|
$scope.ok = ->
|
||||||
|
set('result', $scope.result)
|
||||||
|
$uibModalInstance.close(true)
|
||||||
|
|
||||||
|
$scope.cancel = ->
|
||||||
|
if currentNode then $scope.currentNode.data = oldValue
|
||||||
|
$uibModalInstance.dismiss('cancel')
|
||||||
|
|
||||||
|
# test if value is in select
|
||||||
|
$scope.inSelect = (value) ->
|
||||||
|
for i in $scope.currentNode.select
|
||||||
|
if i.k == value then return true
|
||||||
|
return false
|
||||||
|
]
|
||||||
|
|
||||||
|
# File reader directive
|
||||||
|
#
|
||||||
|
# Add "onReadFile" HTML attribute to be used in a "file" input
|
||||||
|
# The content off attribute will be launched.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# <input type="file" on-read-file="replaceContent($fileContent)"/>
|
||||||
|
|
||||||
|
llapp.directive 'onReadFile', [ '$parse', ($parse) ->
|
||||||
|
restrict: 'A'
|
||||||
|
scope: false
|
||||||
|
link: (scope, element, attrs) ->
|
||||||
|
fn = $parse attrs.onReadFile
|
||||||
|
element.on 'change', (onChangeEvent) ->
|
||||||
|
reader = new FileReader()
|
||||||
|
reader.onload = (onLoadEvent) ->
|
||||||
|
scope.$apply () ->
|
||||||
|
fn scope,
|
||||||
|
$fileContent: onLoadEvent.target.result
|
||||||
|
reader.readAsText ((onChangeEvent.srcElement || onChangeEvent.target).files[0])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Resize system
|
||||||
|
#
|
||||||
|
# Add a "resizer" HTML attribute
|
||||||
|
llapp.directive 'resizer', ['$document', ($document) ->
|
||||||
|
hsize = null
|
||||||
|
rsize = null
|
||||||
|
($scope, $element, $attrs) ->
|
||||||
|
$element.on 'mousedown', (event) ->
|
||||||
|
if $attrs.resizer == 'vertical'
|
||||||
|
rsize = $($attrs.resizerRight).width() + $($attrs.resizerLeft).width()
|
||||||
|
else
|
||||||
|
hsize = $($attrs.resizerTop).height() + $($attrs.resizerBottom).height()
|
||||||
|
event.preventDefault()
|
||||||
|
$document.on 'mousemove', mousemove
|
||||||
|
$document.on 'mouseup', mouseup
|
||||||
|
mousemove = (event) ->
|
||||||
|
# Handle vertical resizer
|
||||||
|
if $attrs.resizer == 'vertical'
|
||||||
|
x = event.pageX
|
||||||
|
if $attrs.resizerMax and x > $attrs.resizerMax
|
||||||
|
x = parseInt $attrs.resizerMax
|
||||||
|
$($attrs.resizerLeft).css
|
||||||
|
width: "#{x}px"
|
||||||
|
$($attrs.resizerRight).css
|
||||||
|
width: "#{rsize-x}px"
|
||||||
|
# Handle horizontal resizer
|
||||||
|
else
|
||||||
|
y = event.pageY - $('#navbar').height()
|
||||||
|
$($attrs.resizerTop).css
|
||||||
|
height: "#{y}px"
|
||||||
|
$($attrs.resizerBottom).css
|
||||||
|
height: "#{hsize-y}px"
|
||||||
|
mouseup = () ->
|
||||||
|
$document.unbind 'mousemove', mousemove
|
||||||
|
$document.unbind 'mouseup', mouseup
|
||||||
|
]
|
||||||
|
|
||||||
|
###
|
||||||
|
# Authentication system
|
||||||
|
#
|
||||||
|
# If a 401 code is returned and if "Authorization" header contains an url,
|
||||||
|
# user is redirected to this url (but target is replaced by location.href
|
||||||
|
###
|
||||||
|
llapp.factory '$lmhttp', ['$q', '$location', ($q, $location) ->
|
||||||
|
responseError: (rejection) ->
|
||||||
|
if rejection.status == 401 and window.portal
|
||||||
|
window.location = "#{window.portal}?url=" + window.btoa(window.location).replace(/\//, '_')
|
||||||
|
]
|
||||||
|
|
||||||
|
llapp.config [ '$httpProvider', ($httpProvider) ->
|
||||||
|
$httpProvider.interceptors.push '$lmhttp'
|
||||||
|
]
|
722
lemonldap-ng-manager/site/coffee/manager.coffee
Normal file
722
lemonldap-ng-manager/site/coffee/manager.coffee
Normal file
|
@ -0,0 +1,722 @@
|
||||||
|
###
|
||||||
|
LemonLDAP::NG Manager client
|
||||||
|
|
||||||
|
This is the main app file. Other are:
|
||||||
|
- struct.json and js/confTree.js that contains the full tree
|
||||||
|
- translate.json that contains the keywords translation
|
||||||
|
|
||||||
|
This file contains:
|
||||||
|
- the AngularJS controller
|
||||||
|
###
|
||||||
|
|
||||||
|
llapp = angular.module 'llngManager', ['ui.tree', 'ui.bootstrap', 'llApp', 'ngCookies']
|
||||||
|
|
||||||
|
###
|
||||||
|
Main AngularJS controller
|
||||||
|
###
|
||||||
|
|
||||||
|
llapp.controller 'TreeCtrl', [
|
||||||
|
'$scope', '$http', '$location', '$q', '$uibModal', '$translator', '$cookies', '$htmlParams',
|
||||||
|
($scope, $http, $location, $q, $uibModal, $translator, $cookies, $htmlParams) ->
|
||||||
|
$scope.links = window.links
|
||||||
|
$scope.menu = $htmlParams.menu
|
||||||
|
$scope.menulinks = window.menulinks
|
||||||
|
$scope.staticPrefix = window.staticPrefix
|
||||||
|
$scope.formPrefix = window.formPrefix
|
||||||
|
$scope.availableLanguages = window.availableLanguages
|
||||||
|
$scope.waiting = true
|
||||||
|
$scope.showM = false
|
||||||
|
$scope.showT = false
|
||||||
|
$scope.form = 'home'
|
||||||
|
$scope.currentCfg = {}
|
||||||
|
$scope.confPrefix = window.confPrefix
|
||||||
|
$scope.message = {}
|
||||||
|
$scope.result = ''
|
||||||
|
|
||||||
|
# Import translations functions
|
||||||
|
$scope.translateTitle = (node) ->
|
||||||
|
return $translator.translateField node, 'title'
|
||||||
|
$scope.translateP = $translator.translateP
|
||||||
|
$scope.translate = $translator.translate
|
||||||
|
|
||||||
|
# HELP DISPLAY
|
||||||
|
$scope.helpUrl = 'start.html#configuration'
|
||||||
|
$scope.setShowHelp = (val) ->
|
||||||
|
val = !$scope.showH unless val?
|
||||||
|
$scope.showH = val
|
||||||
|
d = new Date(Date.now())
|
||||||
|
d.setFullYear(d.getFullYear() + 1)
|
||||||
|
$cookies.put 'showhelp', (if val then 'true' else 'false'), {"expires": d}
|
||||||
|
$scope.showH = if $cookies.get('showhelp') == 'false' then false else true
|
||||||
|
$scope.setShowHelp(true) unless $scope.showH?
|
||||||
|
|
||||||
|
# INTERCEPT AJAX ERRORS
|
||||||
|
readError = (response) ->
|
||||||
|
e = response.status
|
||||||
|
j = response.statusLine
|
||||||
|
$scope.waiting = false
|
||||||
|
if e == 403
|
||||||
|
$scope.message =
|
||||||
|
title: 'forbidden'
|
||||||
|
message: ''
|
||||||
|
items: []
|
||||||
|
else if e == 401
|
||||||
|
console.log 'Authentication needed'
|
||||||
|
$scope.message =
|
||||||
|
title: 'authenticationNeeded'
|
||||||
|
message: '__waitOrF5__'
|
||||||
|
items: []
|
||||||
|
else if e == 400
|
||||||
|
$scope.message =
|
||||||
|
title: 'badRequest'
|
||||||
|
message: j
|
||||||
|
items: []
|
||||||
|
else if e > 0
|
||||||
|
$scope.message =
|
||||||
|
title: 'badRequest'
|
||||||
|
message: j
|
||||||
|
items: []
|
||||||
|
else
|
||||||
|
$scope.message =
|
||||||
|
title: 'networkProblem'
|
||||||
|
message: ''
|
||||||
|
items: []
|
||||||
|
return $scope.showModal 'message.html'
|
||||||
|
|
||||||
|
# Modal launcher
|
||||||
|
$scope.showModal = (tpl, init) ->
|
||||||
|
modalInstance = $uibModal.open
|
||||||
|
templateUrl: tpl
|
||||||
|
controller: 'ModalInstanceCtrl'
|
||||||
|
size: 'lg'
|
||||||
|
resolve:
|
||||||
|
elem: ->
|
||||||
|
return (s) ->
|
||||||
|
return $scope[s]
|
||||||
|
set: ->
|
||||||
|
return (f, s) ->
|
||||||
|
$scope[f] = s
|
||||||
|
init: ->
|
||||||
|
return init
|
||||||
|
d = $q.defer()
|
||||||
|
modalInstance.result.then (msgok) ->
|
||||||
|
$scope.message =
|
||||||
|
title: ''
|
||||||
|
message: ''
|
||||||
|
items: []
|
||||||
|
d.resolve msgok
|
||||||
|
,(msgnok) ->
|
||||||
|
$scope.message =
|
||||||
|
title: ''
|
||||||
|
message: ''
|
||||||
|
items: []
|
||||||
|
d.reject msgnok
|
||||||
|
return modalInstance.result
|
||||||
|
|
||||||
|
# FORM DISPLAY FUNCTIONS
|
||||||
|
|
||||||
|
# Function called when a menu item is selected. It launch function stored in
|
||||||
|
# "action" or "title"
|
||||||
|
$scope.menuClick = (button) ->
|
||||||
|
if button.popup
|
||||||
|
window.open button.popup
|
||||||
|
else
|
||||||
|
button.action = button.title unless button.action
|
||||||
|
switch typeof button.action
|
||||||
|
when 'function'
|
||||||
|
button.action $scope.currentNode, $scope
|
||||||
|
when 'string'
|
||||||
|
$scope[button.action]()
|
||||||
|
else
|
||||||
|
console.log typeof button.action
|
||||||
|
$scope.showM = false
|
||||||
|
|
||||||
|
# Display main form
|
||||||
|
$scope.home = ->
|
||||||
|
$scope.form = 'home'
|
||||||
|
$scope.showM = false
|
||||||
|
|
||||||
|
# SAVE FUNCTIONS
|
||||||
|
|
||||||
|
# Private method called by $scope.save()
|
||||||
|
_checkSaveResponse = (data) ->
|
||||||
|
$scope.message =
|
||||||
|
title: ''
|
||||||
|
message: ''
|
||||||
|
items: []
|
||||||
|
$scope.confirmNeeded = true if data.message == '__needConfirmation__'
|
||||||
|
$scope.message.message = data.message if data.message
|
||||||
|
if data.details
|
||||||
|
for m of data.details when m != '__changes__'
|
||||||
|
$scope.message.items.push
|
||||||
|
message: m
|
||||||
|
items: data.details[m]
|
||||||
|
$scope.waiting = false
|
||||||
|
if data.result == 1
|
||||||
|
# Force reloading page
|
||||||
|
$location.path '/confs/'
|
||||||
|
$scope.message.title = 'successfullySaved'
|
||||||
|
else
|
||||||
|
$scope.message.title = 'saveReport'
|
||||||
|
$scope.showModal 'message.html'
|
||||||
|
|
||||||
|
# Main save function
|
||||||
|
$scope.save = ->
|
||||||
|
$scope.showModal('save.html').then ->
|
||||||
|
$scope.waiting = true
|
||||||
|
$scope.data.push
|
||||||
|
id: "cfgLog"
|
||||||
|
title: "cfgLog"
|
||||||
|
data: if $scope.result then $scope.result else ''
|
||||||
|
$http.post("#{window.confPrefix}?cfgNum=#{$scope.currentCfg.cfgNum}#{if $scope.forceSave then "&force=1" else ''}", $scope.data).then (response) ->
|
||||||
|
$scope.data.pop()
|
||||||
|
_checkSaveResponse response.data
|
||||||
|
,(response) ->
|
||||||
|
readError response
|
||||||
|
$scope.data.pop()
|
||||||
|
, ->
|
||||||
|
console.log 'Saving canceled'
|
||||||
|
$scope.showM = false
|
||||||
|
|
||||||
|
# Raw save function
|
||||||
|
$scope.saveRawConf = ($fileContent) ->
|
||||||
|
$scope.waiting = true
|
||||||
|
$http.post("#{window.confPrefix}/raw", $fileContent).then (response) ->
|
||||||
|
_checkSaveResponse(response.data)
|
||||||
|
, readError
|
||||||
|
|
||||||
|
# Restore raw conffunction
|
||||||
|
$scope.restore = ->
|
||||||
|
$scope.currentNode = null
|
||||||
|
$scope.form = 'restore'
|
||||||
|
|
||||||
|
# Cancel save function
|
||||||
|
$scope.cancel = ->
|
||||||
|
$scope.currentNode.data = null
|
||||||
|
$scope.getKey($scope.currentNode)
|
||||||
|
|
||||||
|
# NODES MANAGEMENT
|
||||||
|
id = 1
|
||||||
|
$scope._findContainer = ->
|
||||||
|
return $scope._findScopeContainer().$modelValue
|
||||||
|
$scope._findScopeContainer = ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
while not cs.$modelValue.type.match(/Container$/)
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
return cs
|
||||||
|
$scope._findScopeByKey = (k) ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
while not (cs.$modelValue.title == k)
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
return cs
|
||||||
|
|
||||||
|
# Add grant rule entry
|
||||||
|
$scope.newGrantRule = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
l = node.nodes.length
|
||||||
|
n = if l > 0 then l - 1 else 0
|
||||||
|
node.nodes.splice n, 0,
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: 'New rule'
|
||||||
|
re: '1'
|
||||||
|
comment: 'New rule'
|
||||||
|
data: 'Message'
|
||||||
|
type: "grant"
|
||||||
|
|
||||||
|
# Add rules entry
|
||||||
|
$scope.newRule = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
l = node.nodes.length
|
||||||
|
n = if l > 0 then l - 1 else 0
|
||||||
|
node.nodes.splice n, 0,
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: 'New rule'
|
||||||
|
re: '^/new'
|
||||||
|
comment: 'New rule'
|
||||||
|
data: 'accept'
|
||||||
|
type: "rule"
|
||||||
|
|
||||||
|
# Add form replay
|
||||||
|
$scope.newPost = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
node.nodes.push
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: "/absolute/path/to/form"
|
||||||
|
data: {}
|
||||||
|
type: "post"
|
||||||
|
|
||||||
|
$scope.newPostVar = ->
|
||||||
|
$scope.currentNode.data.vars = [] unless $scope.currentNode.data.vars?
|
||||||
|
$scope.currentNode.data.vars.push ['var1', '$uid']
|
||||||
|
|
||||||
|
# Add auth chain entry to authChoice
|
||||||
|
$scope.newAuthChoice = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
node.nodes.push
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: "1_Key"
|
||||||
|
data: ['Null', 'Null', 'Null']
|
||||||
|
type: "authChoice"
|
||||||
|
$scope.execFilters $scope._findScopeByKey 'authParams'
|
||||||
|
|
||||||
|
# Add hash entry
|
||||||
|
$scope.newHashEntry = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
node.nodes.push
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: 'new'
|
||||||
|
data: ''
|
||||||
|
type: "keyText"
|
||||||
|
|
||||||
|
# Menu cat entry
|
||||||
|
$scope.newCat = ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
if cs.$modelValue.type == 'menuApp'
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
cs.$modelValue.nodes.push
|
||||||
|
id: "#{cs.$modelValue.id}/n#{id++}"
|
||||||
|
title: "New category"
|
||||||
|
type: "menuCat"
|
||||||
|
nodes: []
|
||||||
|
|
||||||
|
# Menu app entry
|
||||||
|
$scope.newApp = ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
if cs.$modelValue.type == 'menuApp'
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
cs.$modelValue.nodes.push
|
||||||
|
id: "#{cs.$modelValue.id}/n#{id++}"
|
||||||
|
title: "New application"
|
||||||
|
type: "menuApp"
|
||||||
|
data:
|
||||||
|
description: "New app description"
|
||||||
|
uri: "https://test.example.com/"
|
||||||
|
logo: "network.png"
|
||||||
|
display: "auto"
|
||||||
|
|
||||||
|
# SAML attribute entry
|
||||||
|
$scope.addSamlAttribute = ->
|
||||||
|
node = $scope._findContainer()
|
||||||
|
node.nodes.push
|
||||||
|
id: "#{node.id}/n#{id++}"
|
||||||
|
title: 'new'
|
||||||
|
type: 'samlAttribute'
|
||||||
|
data: [0, 'New', '', '']
|
||||||
|
|
||||||
|
# Nodes with template
|
||||||
|
$scope.addVhost = ->
|
||||||
|
name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
|
||||||
|
$scope.message =
|
||||||
|
title: 'virtualHostName'
|
||||||
|
field: 'hostname'
|
||||||
|
$scope.showModal('prompt.html', name).then ->
|
||||||
|
n= $scope.result
|
||||||
|
if n
|
||||||
|
node = $scope.addTemplateNode n, 'virtualHost'
|
||||||
|
delete node.nodes[0].cnodes
|
||||||
|
node.nodes[0].nodes = [
|
||||||
|
id: "virtualHosts/new__#{n}/locationRules/default",
|
||||||
|
type: "rule",
|
||||||
|
title: "default",
|
||||||
|
comment: "",
|
||||||
|
re: "default",
|
||||||
|
data: "deny"
|
||||||
|
]
|
||||||
|
|
||||||
|
$scope.duplicateVhost = ->
|
||||||
|
name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
|
||||||
|
$scope.message =
|
||||||
|
title: 'virtualHostName',
|
||||||
|
field: 'hostname'
|
||||||
|
$scope.showModal('prompt.html', name).then ->
|
||||||
|
n = $scope.result
|
||||||
|
return $scope.duplicateNode n, 'virtualHost', $scope.currentNode.title
|
||||||
|
|
||||||
|
$scope.addSamlIDP = ->
|
||||||
|
$scope.newTemplateNode 'samlIDPMetaDataNode', 'samlPartnerName', 'idp-example'
|
||||||
|
|
||||||
|
$scope.addSamlSP = ->
|
||||||
|
$scope.newTemplateNode 'samlSPMetaDataNode', 'samlPartnerName', 'sp-example'
|
||||||
|
|
||||||
|
$scope.addOidcOp = ->
|
||||||
|
$scope.newTemplateNode 'oidcOPMetaDataNode', 'oidcOPName', 'op-example'
|
||||||
|
|
||||||
|
$scope.addOidcRp = ->
|
||||||
|
$scope.newTemplateNode 'oidcRPMetaDataNode', 'oidcRPName', 'rp-example'
|
||||||
|
|
||||||
|
$scope.newTemplateNode = (type, title, init) ->
|
||||||
|
$scope.message =
|
||||||
|
title: title
|
||||||
|
field: 'name'
|
||||||
|
$scope.showModal('prompt.html', init).then ->
|
||||||
|
name = $scope.result
|
||||||
|
if (name)
|
||||||
|
$scope.addTemplateNode name, type
|
||||||
|
|
||||||
|
$scope.addTemplateNode = (name, type) ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
while cs.$modelValue.title != "#{type}s"
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
t =
|
||||||
|
id: "#{type}s/new__#{name}"
|
||||||
|
title: name
|
||||||
|
type: type
|
||||||
|
nodes: templates type, "new__#{name}"
|
||||||
|
cs.$modelValue.nodes.push t
|
||||||
|
cs.expand()
|
||||||
|
return t
|
||||||
|
|
||||||
|
_getAll = (node) ->
|
||||||
|
d = $q.defer()
|
||||||
|
d2 = $q.defer()
|
||||||
|
if node._nodes
|
||||||
|
_stoggle node
|
||||||
|
d.resolve()
|
||||||
|
else if node.cnodes
|
||||||
|
_download(node).then ->
|
||||||
|
d.resolve()
|
||||||
|
else if node.nodes or node.data
|
||||||
|
d.resolve()
|
||||||
|
else
|
||||||
|
$scope.getKey(node).then ->
|
||||||
|
d.resolve()
|
||||||
|
d.promise.then ->
|
||||||
|
t = []
|
||||||
|
if node.nodes
|
||||||
|
for n in node.nodes
|
||||||
|
t.push _getAll(n)
|
||||||
|
$q.all(t).then ->
|
||||||
|
d2.resolve()
|
||||||
|
return d2.promise
|
||||||
|
|
||||||
|
$scope.duplicateNode = (name, type) ->
|
||||||
|
cs = $scope.currentScope
|
||||||
|
_getAll($scope.currentNode).then ->
|
||||||
|
while cs.$modelValue.title != "#{type}s"
|
||||||
|
cs = cs.$parentNodeScope
|
||||||
|
t = JSON.parse JSON.stringify($scope.currentNode).replace(new RegExp(idkey, 'g'), 'new__' + name)
|
||||||
|
t.id = "#{type}s/new__#{name}"
|
||||||
|
t.title = name
|
||||||
|
cs.$modelValue.nodes.push(t)
|
||||||
|
return t
|
||||||
|
|
||||||
|
$scope.del = (a, i) ->
|
||||||
|
a.splice(i, 1)
|
||||||
|
|
||||||
|
$scope.deleteEntry = ->
|
||||||
|
p = $scope.currentScope.$parentNodeScope
|
||||||
|
$scope.currentScope.remove()
|
||||||
|
$scope.displayForm p
|
||||||
|
|
||||||
|
$scope.down = ->
|
||||||
|
id = $scope.currentNode.id
|
||||||
|
p = $scope.currentScope.$parentNodeScope.$modelValue
|
||||||
|
ind = p.nodes.length
|
||||||
|
for n, i in p.nodes
|
||||||
|
if n.id == id then ind = i
|
||||||
|
if ind < p.nodes.length - 1
|
||||||
|
tmp = p.nodes[ind]
|
||||||
|
p.nodes[ind] = p.nodes[ind + 1]
|
||||||
|
p.nodes[ind + 1] = tmp
|
||||||
|
ind
|
||||||
|
|
||||||
|
$scope.up = ->
|
||||||
|
id = $scope.currentNode.id
|
||||||
|
p = $scope.currentScope.$parentNodeScope.$modelValue
|
||||||
|
ind = -1
|
||||||
|
for n, i in p.nodes
|
||||||
|
if n.id == id then ind = i
|
||||||
|
if ind > 0
|
||||||
|
tmp = p.nodes[ind]
|
||||||
|
p.nodes[ind] = p.nodes[ind - 1]
|
||||||
|
p.nodes[ind - 1] = tmp
|
||||||
|
ind
|
||||||
|
|
||||||
|
# test if value is in select
|
||||||
|
$scope.inSelect = (value) ->
|
||||||
|
for n in $scope.currentNode.select
|
||||||
|
return true if n.k == value
|
||||||
|
return false
|
||||||
|
|
||||||
|
# This is for rule form: title = comment if defined, else title = re
|
||||||
|
$scope.changeRuleTitle = (node) ->
|
||||||
|
node.title = if node.comment.length > 0 then node.comment else node.re
|
||||||
|
|
||||||
|
# Node opening
|
||||||
|
|
||||||
|
# authParams mechanism: show used auth modules only (launched by stoggle)
|
||||||
|
$scope.filters = {}
|
||||||
|
$scope.execFilters = (scope) ->
|
||||||
|
scope = if scope then scope else $scope
|
||||||
|
for filter,func of $scope.filters
|
||||||
|
if $scope.filters.hasOwnProperty(filter)
|
||||||
|
return filterFunctions[filter](scope, $q, func)
|
||||||
|
false
|
||||||
|
|
||||||
|
# To avoid binding all the tree, nodes are pushed in DOM only when opened
|
||||||
|
$scope.stoggle = (scope) ->
|
||||||
|
node = scope.$modelValue
|
||||||
|
_stoggle node
|
||||||
|
scope.toggle()
|
||||||
|
_stoggle = (node) ->
|
||||||
|
for n in ['nodes', 'nodes_cond']
|
||||||
|
if node["_#{n}"]
|
||||||
|
node[n] = []
|
||||||
|
for a in node["_#{n}"]
|
||||||
|
node[n].push a
|
||||||
|
delete node["_#{n}"]
|
||||||
|
# Call execFilter for authParams
|
||||||
|
if node._nodes_filter
|
||||||
|
if node.nodes
|
||||||
|
for n in node.nodes
|
||||||
|
n.onChange = $scope.execFilters
|
||||||
|
$scope.filters[node._nodes_filter] = node
|
||||||
|
$scope.execFilters()
|
||||||
|
|
||||||
|
# Simple toggle management
|
||||||
|
$scope.toggle = (scope) ->
|
||||||
|
scope.toggle()
|
||||||
|
|
||||||
|
# cnodes management: hash keys/values are loaded when parent node is opened
|
||||||
|
$scope.download = (scope) ->
|
||||||
|
node = scope.$modelValue
|
||||||
|
return _download(node)
|
||||||
|
_download = (node) ->
|
||||||
|
d = $q.defer()
|
||||||
|
d.notify 'Trying to get datas'
|
||||||
|
$scope.waiting = true
|
||||||
|
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{node.cnodes}").then (response) ->
|
||||||
|
data = response.data
|
||||||
|
# Manage datas errors
|
||||||
|
if not data
|
||||||
|
d.reject 'Empty response from server'
|
||||||
|
else if data.error
|
||||||
|
if data.error.match(/setDefault$/)
|
||||||
|
if node['default']
|
||||||
|
node.nodes = node['default'].slice(0)
|
||||||
|
else
|
||||||
|
node.nodes = []
|
||||||
|
delete node.cnodes
|
||||||
|
d.resolve 'Set data to default value'
|
||||||
|
else
|
||||||
|
d.reject "Server return an error: #{data.error}"
|
||||||
|
else
|
||||||
|
# Store datas
|
||||||
|
delete node.cnodes
|
||||||
|
if not node.type
|
||||||
|
node.type = 'keyTextContainer'
|
||||||
|
node.nodes = []
|
||||||
|
# TODO: try/catch
|
||||||
|
for a in data
|
||||||
|
if a.template
|
||||||
|
a._nodes = templates a.template, a.title
|
||||||
|
node.nodes.push a
|
||||||
|
d.resolve 'OK'
|
||||||
|
$scope.waiting = false
|
||||||
|
, (response) ->
|
||||||
|
readError response
|
||||||
|
d.reject ''
|
||||||
|
return d.promise
|
||||||
|
|
||||||
|
$scope.openCnode = (scope) ->
|
||||||
|
$scope.download(scope).then ->
|
||||||
|
scope.toggle()
|
||||||
|
|
||||||
|
setHelp = (scope) ->
|
||||||
|
while !scope.$modelValue.help and scope.$parentNodeScope
|
||||||
|
scope = scope.$parentNodeScope
|
||||||
|
$scope.helpUrl = scope.$modelValue.help || 'start.html#configuration'
|
||||||
|
|
||||||
|
# Form management
|
||||||
|
#
|
||||||
|
# `currentNode` contains the last select node
|
||||||
|
#
|
||||||
|
# method `diplayForm()`:
|
||||||
|
# - set the `form` property to the name of the form to download
|
||||||
|
# (`text` by default or `home` for node without `type` property)
|
||||||
|
# - launch getKeys to set `node.data`
|
||||||
|
# - hide tree when in XS size
|
||||||
|
#
|
||||||
|
$scope.displayForm = (scope) ->
|
||||||
|
node = scope.$modelValue
|
||||||
|
if node.cnodes
|
||||||
|
$scope.download scope
|
||||||
|
if node._nodes
|
||||||
|
$scope.stoggle scope
|
||||||
|
$scope.currentNode = node
|
||||||
|
$scope.currentScope = scope
|
||||||
|
f = if node.type then node.type else 'text'
|
||||||
|
if node.nodes || node._nodes || node.cnodes
|
||||||
|
$scope.form = if f != 'text' then f else 'mini'
|
||||||
|
else
|
||||||
|
$scope.form = f
|
||||||
|
# Get datas
|
||||||
|
$scope.getKey node
|
||||||
|
if node.type and node.type == 'simpleInputContainer'
|
||||||
|
for n in node.nodes
|
||||||
|
$scope.getKey(n)
|
||||||
|
$scope.showT = false
|
||||||
|
setHelp scope
|
||||||
|
|
||||||
|
$scope.keyWritable = (scope) ->
|
||||||
|
node = scope.$modelValue
|
||||||
|
return if node.type and node.type.match /^(authChoice|keyText|virtualHost|rule|menuCat|menuApp|saml(Attribute|(IDP|SP)MetaDataNode))$/ then true else false
|
||||||
|
|
||||||
|
# RSA keys generation
|
||||||
|
$scope.newRSAKey = ->
|
||||||
|
$scope.showModal('password.html').then ->
|
||||||
|
$scope.waiting = true
|
||||||
|
currentNode = $scope.currentNode
|
||||||
|
password = $scope.result
|
||||||
|
$http.post("#{window.confPrefix}/newRSAKey", {"password": password}).then (response) ->
|
||||||
|
currentNode.data[0].data = response.data.private
|
||||||
|
currentNode.data[1].data = password
|
||||||
|
currentNode.data[2].data = response.data.public
|
||||||
|
$scope.waiting = false
|
||||||
|
, readError
|
||||||
|
, ->
|
||||||
|
console.log('New key cancelled')
|
||||||
|
|
||||||
|
$scope.newRSAKeyNoPassword = ->
|
||||||
|
$scope.waiting = true
|
||||||
|
currentNode = $scope.currentNode
|
||||||
|
$http.post("#{window.confPrefix}/newRSAKey", {"password": ''}).then (response) ->
|
||||||
|
currentNode.data[0].data = response.data.private
|
||||||
|
currentNode.data[1].data = response.data.public
|
||||||
|
$scope.waiting = false
|
||||||
|
, readError
|
||||||
|
|
||||||
|
# method `getKey()`:
|
||||||
|
# - return a promise with the data:
|
||||||
|
# - from node when set
|
||||||
|
# - after downloading else
|
||||||
|
#
|
||||||
|
$scope.getKey = (node) ->
|
||||||
|
d = $q.defer()
|
||||||
|
if !node.data
|
||||||
|
$scope.waiting = true
|
||||||
|
if node.get and typeof(node.get) == 'object'
|
||||||
|
node.data = []
|
||||||
|
tmp = []
|
||||||
|
for n, i in node.get
|
||||||
|
node.data[i] =
|
||||||
|
title: n
|
||||||
|
id: n
|
||||||
|
tmp.push $scope.getKey(node.data[i])
|
||||||
|
$q.all(tmp).then ->
|
||||||
|
d.resolve(node.data)
|
||||||
|
,(response) ->
|
||||||
|
d.reject response.statusLine
|
||||||
|
$scope.waiting = false
|
||||||
|
else
|
||||||
|
$http.get("#{window.confPrefix}#{$scope.currentCfg.cfgNum}/#{if node.get then node.get else node.title}").then (response) ->
|
||||||
|
# Set default value if response is null or if asked by server
|
||||||
|
data = response.data
|
||||||
|
if (data.value == null or (data.error and data.error.match /setDefault$/ ) ) and node['default'] != null
|
||||||
|
node.data = node['default']
|
||||||
|
else
|
||||||
|
node.data = data.value
|
||||||
|
# Cast int as int (remember that booleans are int for Perl)
|
||||||
|
if node.type and node.type.match /^(int|bool|trool)$/
|
||||||
|
node.data = parseInt(node.data)
|
||||||
|
# Split SAML types
|
||||||
|
else if node.type and node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) and not (typeof node.data == 'object')
|
||||||
|
node.data = node.data.split ';'
|
||||||
|
$scope.waiting = false
|
||||||
|
d.resolve node.data
|
||||||
|
, (response) ->
|
||||||
|
readError response
|
||||||
|
d.reject response.status
|
||||||
|
else
|
||||||
|
d.resolve node.data
|
||||||
|
return d.promise
|
||||||
|
|
||||||
|
# function `pathEvent(event, next; current)`:
|
||||||
|
# Called when $location.path() change, launch getCfg() with the new
|
||||||
|
# configuration number
|
||||||
|
pathEvent = (event, next, current) ->
|
||||||
|
n = next.match(new RegExp('#/confs/(latest|[0-9]+)'))
|
||||||
|
if n == null
|
||||||
|
$location.path '/confs/latest'
|
||||||
|
else
|
||||||
|
console.log "Trying to get cfg number #{n[1]}"
|
||||||
|
$scope.getCfg n[1]
|
||||||
|
$scope.$on '$locationChangeSuccess', pathEvent
|
||||||
|
|
||||||
|
# function `getCfg(n)
|
||||||
|
# Download configuration metadatas
|
||||||
|
$scope.getCfg = (n) ->
|
||||||
|
if $scope.currentCfg.cfgNum != n
|
||||||
|
$http.get("#{window.confPrefix}#{n}").then (response) ->
|
||||||
|
$scope.currentCfg = response.data
|
||||||
|
d = new Date $scope.currentCfg.cfgDate * 1000
|
||||||
|
$scope.currentCfg.date = d.toLocaleString()
|
||||||
|
console.log "Metadatas of cfg #{n} loaded"
|
||||||
|
$location.path "/confs/#{n}"
|
||||||
|
$scope.init()
|
||||||
|
, (response) ->
|
||||||
|
readError(response).then ->
|
||||||
|
$scope.currentCfg.cfgNum = 0
|
||||||
|
$scope.init()
|
||||||
|
else
|
||||||
|
$scope.waiting = false
|
||||||
|
|
||||||
|
# method `getLanguage(lang)`
|
||||||
|
# Launch init() after setting current language
|
||||||
|
$scope.getLanguage = (lang) ->
|
||||||
|
$scope.lang = lang
|
||||||
|
# Force reload home
|
||||||
|
$scope.form = 'white'
|
||||||
|
$scope.init()
|
||||||
|
$scope.showM = false
|
||||||
|
|
||||||
|
# Initialization
|
||||||
|
|
||||||
|
# Load JSON files:
|
||||||
|
# - struct.json: the main tree
|
||||||
|
# - languages/<lang>.json: the chosen language datas
|
||||||
|
$scope.init = ->
|
||||||
|
tmp = null
|
||||||
|
$scope.waiting = true
|
||||||
|
$scope.data = []
|
||||||
|
$scope.confirmNeeded = false
|
||||||
|
$scope.forceSave = false
|
||||||
|
$q.all [
|
||||||
|
$translator.init($scope.lang),
|
||||||
|
$http.get("#{window.staticPrefix}struct.json").then (response) ->
|
||||||
|
tmp = response.data
|
||||||
|
console.log("Structure loaded")
|
||||||
|
]
|
||||||
|
.then ->
|
||||||
|
console.log("Starting structure binding")
|
||||||
|
$scope.data = tmp
|
||||||
|
tmp = null
|
||||||
|
if $scope.currentCfg.cfgNum != 0
|
||||||
|
setScopeVars $scope
|
||||||
|
else
|
||||||
|
$scope.message =
|
||||||
|
title: 'emptyConf'
|
||||||
|
message: '__zeroConfExplanations__'
|
||||||
|
$scope.showModal 'message.html'
|
||||||
|
$scope.form = 'home'
|
||||||
|
$scope.waiting = false
|
||||||
|
, readError
|
||||||
|
c = $location.path().match(new RegExp('^/confs/(latest|[0-9]+)'))
|
||||||
|
unless c
|
||||||
|
console.log "Redirecting to /confs/latest"
|
||||||
|
$location.path '/confs/latest'
|
||||||
|
|
||||||
|
# File form function
|
||||||
|
$scope.replaceContentByUrl = (node, url) ->
|
||||||
|
$scope.waiting = true
|
||||||
|
$http.post(window.scriptname + "prx", {url: url}).then (response) ->
|
||||||
|
node.data = response.data.content
|
||||||
|
$scope.waiting = false
|
||||||
|
, readError
|
||||||
|
$scope.replaceContent = (node, $fileContent) ->
|
||||||
|
node.data = $fileContent
|
||||||
|
|
||||||
|
# Import Filesaver.js saveAs()
|
||||||
|
$scope.saveAs = (content, type, filename) ->
|
||||||
|
saveAs(new Blob([content], {"type": type}), filename)
|
||||||
|
]
|
|
@ -1,148 +1,134 @@
|
||||||
/* LemonLDAP::NG base app module
|
// Generated by CoffeeScript 1.10.0
|
||||||
*
|
|
||||||
* This file contains:
|
/*
|
||||||
* - 3 AngularJS directives (HTML attributes):
|
LemonLDAP::NG base app module
|
||||||
* * `on-read-file` to get file content
|
|
||||||
* * `resizer` to resize HTML div
|
This file contains:
|
||||||
* * `trspan` to set translated message in HTML content
|
- 3 AngularJS directives (HTML attributes):
|
||||||
* - a AngularJS factory to handle 401 Ajax responses
|
* `on-read-file` to get file content
|
||||||
|
* `resizer` to resize HTML div
|
||||||
|
* `trspan` to set translated message in HTML content
|
||||||
|
- a AngularJS factory to handle 401 Ajax responses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
var llapp;
|
||||||
var llapp = angular.module('llApp', []);
|
|
||||||
|
|
||||||
/* Translation system
|
llapp = angular.module('llApp', []);
|
||||||
*
|
|
||||||
* This part provides:
|
|
||||||
* - 3 functions to translate:
|
|
||||||
* * translate(word)
|
|
||||||
* * translateP(paragraph)
|
|
||||||
* * translateField(object, property)
|
|
||||||
* - an HTML attribute called 'trspan'. Exemple: <h3 trspan="portal"/>
|
|
||||||
*/
|
|
||||||
|
|
||||||
llapp.provider('$translator', $Translator);
|
llapp.provider('$translator', function() {
|
||||||
|
var al, j, k, langs, langs2, len, len1, nl, nlangs, ref, res;
|
||||||
function $Translator() {
|
res = {};
|
||||||
var res = {};
|
|
||||||
|
|
||||||
/* Search for default language */
|
|
||||||
if (navigator) {
|
if (navigator) {
|
||||||
var nlangs = [navigator.language];
|
langs = [];
|
||||||
if (navigator.languages) nlangs = navigator.languages;
|
|
||||||
var langs = [],
|
|
||||||
langs2 = [];
|
langs2 = [];
|
||||||
nlangs.forEach(function(nl) {
|
nlangs = [navigator.language];
|
||||||
availableLanguages.forEach(function(al) {
|
if (navigator.languages) {
|
||||||
if (al == nl) {
|
nlangs = navigator.languages;
|
||||||
langs.push(al)
|
}
|
||||||
} else if (al.substring(0, 1) == nl.substring(0, 1)) {
|
for (j = 0, len = nlangs.length; j < len; j++) {
|
||||||
|
nl = nlangs[j];
|
||||||
|
ref = window.availableLanguages;
|
||||||
|
for (k = 0, len1 = ref.length; k < len1; k++) {
|
||||||
|
al = ref[k];
|
||||||
|
if (al === nl) {
|
||||||
|
langs.push(al);
|
||||||
|
} else if (al.substring(0, 1) === nl.substring(0, 1)) {
|
||||||
langs2.push(al);
|
langs2.push(al);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
});
|
}
|
||||||
res.lang = langs[0] ? langs[0] : langs2[0] ? langs2[0] : 'en';
|
res.lang = langs[0] ? langs[0] : langs2[0] ? langs2[0] : 'en';
|
||||||
} else {
|
} else {
|
||||||
res.lang = 'en';
|
res.lang = 'en';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Private properties */
|
|
||||||
res.deferredTr = [];
|
res.deferredTr = [];
|
||||||
res.translationFields = {};
|
res.translationFields = {};
|
||||||
|
|
||||||
/* Translation methods */
|
|
||||||
|
|
||||||
/* 1 - word translation */
|
|
||||||
res.translate = function(s) {
|
res.translate = function(s) {
|
||||||
if (res.translationFields[s]) {
|
if (res.translationFields[s]) {
|
||||||
s = res.translationFields[s];
|
s = res.translationFields[s];
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 2 - object key translation */
|
|
||||||
res.translateField = function(node, field) {
|
res.translateField = function(node, field) {
|
||||||
return res.translate(node[field]);
|
return res.translate(node[field]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 3 - paragraph translation */
|
|
||||||
res.translateP = function(s) {
|
res.translateP = function(s) {
|
||||||
if (s && res.translationFields.portal) s = s.replace(/__(\w+)__/g, function(match, w) {
|
if (s && res.translationFields.portal) {
|
||||||
return res.translate(w);
|
s = s.replace(/__(\w+)__/g, function(match, w) {
|
||||||
});
|
return res.translate(w);
|
||||||
|
});
|
||||||
|
}
|
||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
this.$get = [
|
||||||
/* Initialization */
|
'$q', '$http', function($q, $http) {
|
||||||
this.$get = ['$q', '$http', function($q, $http) {
|
res.last = '';
|
||||||
res.last = '';
|
res.init = function(lang) {
|
||||||
res.init = function(lang) {
|
var d;
|
||||||
if (!lang) lang = res.lang;
|
if (!lang) {
|
||||||
var d = $q.defer();
|
lang = res.lang;
|
||||||
if (res.last != lang) {
|
}
|
||||||
res.last = lang;
|
d = $q.defer();
|
||||||
$http.get(staticPrefix + 'languages/' + lang + '.json').then(function(response) {
|
if (res.last !== lang) {
|
||||||
res.translationFields = response.data;
|
res.last = lang;
|
||||||
res.deferredTr.forEach(function(h) {
|
$http.get(window.staticPrefix + "languages/" + lang + ".json").then(function(response) {
|
||||||
h.e[h.f](res.translationFields[h.m]);
|
var h, l, len2, ref1;
|
||||||
|
res.translationFields = response.data;
|
||||||
|
ref1 = res.deferredTr;
|
||||||
|
for (l = 0, len2 = ref1.length; l < len2; l++) {
|
||||||
|
h = ref1[l];
|
||||||
|
h.e[h.f](res.translationFields[h.m]);
|
||||||
|
}
|
||||||
|
res.deferredTr = [];
|
||||||
|
return d.resolve("Translation files loaded");
|
||||||
|
}, function(response) {
|
||||||
|
return d.reject('');
|
||||||
});
|
});
|
||||||
res.deferredTr = [];
|
} else {
|
||||||
d.resolve("Translation files loaded");
|
d.resolve("No change");
|
||||||
},
|
}
|
||||||
function(resp) {
|
return d.promise;
|
||||||
d.reject('');
|
};
|
||||||
});
|
return res;
|
||||||
} else {
|
}
|
||||||
d.resolve('No change');
|
];
|
||||||
}
|
return this;
|
||||||
return d.promise;
|
});
|
||||||
|
|
||||||
|
llapp.directive('trspan', [
|
||||||
|
'$translator', function($translator) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
replace: false,
|
||||||
|
transclude: true,
|
||||||
|
scope: {
|
||||||
|
trspan: "@"
|
||||||
|
},
|
||||||
|
link: function(scope, elem, attr) {
|
||||||
|
if ($translator.translationFields.portal) {
|
||||||
|
attr.trspan = $translator.translate(attr.trspan);
|
||||||
|
} else {
|
||||||
|
$translator.deferredTr.push({
|
||||||
|
e: elem,
|
||||||
|
f: 'text',
|
||||||
|
m: attr.trspan
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return elem.text(attr.trspan);
|
||||||
|
},
|
||||||
|
template: ''
|
||||||
};
|
};
|
||||||
return res;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Translation directive (HTML trspan tag) */
|
|
||||||
llapp.directive('trspan', ['$translator', function($translator) {
|
|
||||||
return {
|
|
||||||
restrict: 'A',
|
|
||||||
replace: false,
|
|
||||||
transclude: true,
|
|
||||||
scope: {
|
|
||||||
trspan: "@"
|
|
||||||
},
|
|
||||||
link: function(scope, elem, attr) {
|
|
||||||
if ($translator.translationFields.portal) {
|
|
||||||
attr.trspan = $translator.translate(attr.trspan)
|
|
||||||
}
|
|
||||||
/* Deferred translations will be done after JSON download */
|
|
||||||
else {
|
|
||||||
$translator.deferredTr.push({
|
|
||||||
e: elem,
|
|
||||||
f: 'text',
|
|
||||||
m: attr.trspan
|
|
||||||
});
|
|
||||||
}
|
|
||||||
elem.text(attr.trspan);
|
|
||||||
},
|
|
||||||
template: ""
|
|
||||||
}
|
}
|
||||||
}]);
|
]);
|
||||||
|
|
||||||
/* Form menu management
|
llapp.provider('$htmlParams', function() {
|
||||||
*
|
|
||||||
* Two parts:
|
|
||||||
* - $htmlParams: used to store values inserted as <script type="text/menu">.
|
|
||||||
* It provides menu() method to get them
|
|
||||||
* - HTML "script" element handler
|
|
||||||
*/
|
|
||||||
llapp.provider('$htmlParams', $HtmlParamsProvider);
|
|
||||||
function $HtmlParamsProvider() {
|
|
||||||
this.$get = function() {
|
this.$get = function() {
|
||||||
var params = {};
|
var params;
|
||||||
|
params = {};
|
||||||
return {
|
return {
|
||||||
set: function(key, obj) {
|
set: function(key, obj) {
|
||||||
params[key] = obj;
|
return params[key] = obj;
|
||||||
},
|
},
|
||||||
menu: function() {
|
menu: function() {
|
||||||
return params.menu;
|
return params.menu;
|
||||||
|
@ -152,155 +138,159 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
return this;
|
||||||
|
});
|
||||||
|
|
||||||
llapp.directive('script', ['$htmlParams', function($htmlParams) {
|
llapp.directive('script', [
|
||||||
return {
|
'$htmlParams', function($htmlParams) {
|
||||||
restrict: 'E',
|
return {
|
||||||
terminal: true,
|
restrict: 'E',
|
||||||
compile: function(element, attr) {
|
terminal: true,
|
||||||
var t;
|
compile: function(element, attr) {
|
||||||
if (t = attr.type.match(/text\/(menu|parameters)/)) {
|
var t;
|
||||||
$htmlParams.set(t[1], eval(element[0].text));
|
if (t = attr.type.match(/text\/(menu|parameters)/)) {
|
||||||
}
|
return $htmlParams.set(t[1], eval(element[0].text));
|
||||||
}
|
|
||||||
}
|
|
||||||
}]);
|
|
||||||
|
|
||||||
/* Modal controller
|
|
||||||
*
|
|
||||||
* Used to display messages
|
|
||||||
*/
|
|
||||||
llapp.controller('ModalInstanceCtrl', ['$scope', '$uibModalInstance', 'elem', 'set', 'init', function($scope, $uibModalInstance, elem, set, init) {
|
|
||||||
var oldValue;
|
|
||||||
$scope.elem = elem;
|
|
||||||
$scope.set = set;
|
|
||||||
$scope.result = init;
|
|
||||||
$scope.staticPrefix = staticPrefix;
|
|
||||||
var currentNode = elem('currentNode');
|
|
||||||
$scope.translateP = elem('translateP');
|
|
||||||
if (currentNode) {
|
|
||||||
oldValue = currentNode.data;
|
|
||||||
$scope.currentNode = currentNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.ok = function() {
|
|
||||||
set('result', $scope.result);
|
|
||||||
$uibModalInstance.close(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.cancel = function() {
|
|
||||||
if (currentNode) $scope.currentNode.data = oldValue;
|
|
||||||
$uibModalInstance.dismiss('cancel');
|
|
||||||
};
|
|
||||||
|
|
||||||
/* test if value is in select */
|
|
||||||
$scope.inSelect = function(value) {
|
|
||||||
for (var i = 0; i < $scope.currentNode.select.length; i++) {
|
|
||||||
if ($scope.currentNode.select[i].k == value) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}]);
|
|
||||||
|
|
||||||
/* File reader directive
|
|
||||||
*
|
|
||||||
* Add "onReadFile" HTML attribute to be used in a "file" input
|
|
||||||
* The content off attribute will be launched.
|
|
||||||
*
|
|
||||||
* Example:
|
|
||||||
* <input type="file" on-read-file="replaceContent($fileContent)"/>
|
|
||||||
*/
|
|
||||||
llapp.directive('onReadFile', ['$parse', function($parse) {
|
|
||||||
return {
|
|
||||||
restrict: 'A',
|
|
||||||
scope: false,
|
|
||||||
link: function(scope, element, attrs) {
|
|
||||||
var fn = $parse(attrs.onReadFile);
|
|
||||||
element.on('change', function(onChangeEvent) {
|
|
||||||
var reader = new FileReader();
|
|
||||||
reader.onload = function(onLoadEvent) {
|
|
||||||
scope.$apply(function() {
|
|
||||||
fn(scope, {
|
|
||||||
$fileContent: onLoadEvent.target.result
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}]);
|
|
||||||
|
|
||||||
/* Resizable system
|
|
||||||
*
|
|
||||||
* Add a "resizer" HTML attribute
|
|
||||||
*/
|
|
||||||
llapp.directive('resizer', ['$document', function($document) {
|
|
||||||
var rsize, hsize;
|
|
||||||
return function($scope, $element, $attrs) {
|
|
||||||
$element.on('mousedown', function(event) {
|
|
||||||
if ($attrs.resizer == 'vertical') {
|
|
||||||
rsize = $($attrs.resizerRight).width() + $($attrs.resizerLeft).width();
|
|
||||||
} else {
|
|
||||||
hsize = $($attrs.resizerTop).height() + $($attrs.resizerBottom).height();
|
|
||||||
}
|
|
||||||
event.preventDefault();
|
|
||||||
$document.on('mousemove', mousemove);
|
|
||||||
$document.on('mouseup', mouseup);
|
|
||||||
});
|
|
||||||
|
|
||||||
function mousemove(event) {
|
|
||||||
if ($attrs.resizer == 'vertical') {
|
|
||||||
// Handle vertical resizer
|
|
||||||
var x = event.pageX;
|
|
||||||
|
|
||||||
if ($attrs.resizerMax && x > $attrs.resizerMax) {
|
|
||||||
x = parseInt($attrs.resizerMax);
|
|
||||||
}
|
}
|
||||||
$($attrs.resizerLeft).css({
|
}
|
||||||
width: x + 'px'
|
};
|
||||||
});
|
}
|
||||||
$($attrs.resizerRight).css({
|
]);
|
||||||
width: (rsize - x) + 'px'
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
llapp.controller('ModalInstanceCtrl', [
|
||||||
// Handle horizontal resizer
|
'$scope', '$uibModalInstance', 'elem', 'set', 'init', function($scope, $uibModalInstance, elem, set, init) {
|
||||||
var y = event.pageY - $('#navbar').height();
|
var currentNode, oldValue, oldvalue;
|
||||||
$($attrs.resizerTop).css({
|
oldvalue = null;
|
||||||
height: y + 'px'
|
$scope.elem = elem;
|
||||||
});
|
$scope.set = set;
|
||||||
$($attrs.resizerBottom).css({
|
$scope.result = init;
|
||||||
height: (hsize - y) + 'px'
|
$scope.staticPrefix = window.staticPrefix;
|
||||||
|
currentNode = elem('currentNode');
|
||||||
|
$scope.translateP = elem('translateP');
|
||||||
|
if (currentNode) {
|
||||||
|
oldValue = currentNode.data;
|
||||||
|
$scope.currentNode = currentNode;
|
||||||
|
}
|
||||||
|
$scope.ok = function() {
|
||||||
|
set('result', $scope.result);
|
||||||
|
return $uibModalInstance.close(true);
|
||||||
|
};
|
||||||
|
$scope.cancel = function() {
|
||||||
|
if (currentNode) {
|
||||||
|
$scope.currentNode.data = oldValue;
|
||||||
|
}
|
||||||
|
return $uibModalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
return $scope.inSelect = function(value) {
|
||||||
|
var i, j, len, ref;
|
||||||
|
ref = $scope.currentNode.select;
|
||||||
|
for (j = 0, len = ref.length; j < len; j++) {
|
||||||
|
i = ref[j];
|
||||||
|
if (i.k === value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
llapp.directive('onReadFile', [
|
||||||
|
'$parse', function($parse) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
scope: false,
|
||||||
|
link: function(scope, element, attrs) {
|
||||||
|
var fn;
|
||||||
|
fn = $parse(attrs.onReadFile);
|
||||||
|
return element.on('change', function(onChangeEvent) {
|
||||||
|
var reader;
|
||||||
|
reader = new FileReader();
|
||||||
|
reader.onload = function(onLoadEvent) {
|
||||||
|
return scope.$apply(function() {
|
||||||
|
return fn(scope, {
|
||||||
|
$fileContent: onLoadEvent.target.result
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
function mouseup() {
|
llapp.directive('resizer', [
|
||||||
$document.unbind('mousemove', mousemove);
|
'$document', function($document) {
|
||||||
$document.unbind('mouseup', mouseup);
|
var hsize, rsize;
|
||||||
}
|
hsize = null;
|
||||||
};
|
rsize = null;
|
||||||
}]);
|
return function($scope, $element, $attrs) {
|
||||||
/* Authentication system
|
var mousemove, mouseup;
|
||||||
|
$element.on('mousedown', function(event) {
|
||||||
|
if ($attrs.resizer === 'vertical') {
|
||||||
|
rsize = $($attrs.resizerRight).width() + $($attrs.resizerLeft).width();
|
||||||
|
} else {
|
||||||
|
hsize = $($attrs.resizerTop).height() + $($attrs.resizerBottom).height();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
$document.on('mousemove', mousemove);
|
||||||
|
return $document.on('mouseup', mouseup);
|
||||||
|
});
|
||||||
|
mousemove = function(event) {
|
||||||
|
var x, y;
|
||||||
|
if ($attrs.resizer === 'vertical') {
|
||||||
|
x = event.pageX;
|
||||||
|
if ($attrs.resizerMax && x > $attrs.resizerMax) {
|
||||||
|
x = parseInt($attrs.resizerMax);
|
||||||
|
}
|
||||||
|
$($attrs.resizerLeft).css({
|
||||||
|
width: x + "px"
|
||||||
|
});
|
||||||
|
return $($attrs.resizerRight).css({
|
||||||
|
width: (rsize - x) + "px"
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
y = event.pageY - $('#navbar').height();
|
||||||
|
$($attrs.resizerTop).css({
|
||||||
|
height: y + "px"
|
||||||
|
});
|
||||||
|
return $($attrs.resizerBottom).css({
|
||||||
|
height: (hsize - y) + "px"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return mouseup = function() {
|
||||||
|
$document.unbind('mousemove', mousemove);
|
||||||
|
return $document.unbind('mouseup', mouseup);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Authentication system
|
||||||
*
|
*
|
||||||
* If a 401 code is returned and if "Authorization" header contains an url,
|
* If a 401 code is returned and if "Authorization" header contains an url,
|
||||||
* user is redirected to this url (but target is replaced by location.href)
|
* user is redirected to this url (but target is replaced by location.href
|
||||||
*/
|
*/
|
||||||
llapp.factory('$lmhttp', ['$q', '$location', function($q, $location) {
|
|
||||||
return {
|
llapp.factory('$lmhttp', [
|
||||||
responseError: function(rejection) {
|
'$q', '$location', function($q, $location) {
|
||||||
if (rejection.status == 401 && window.portal) {
|
return {
|
||||||
window.location = window.portal + '?url=' + window.btoa(window.location).replace(/\//, '_');
|
responseError: function(rejection) {
|
||||||
|
if (rejection.status === 401 && window.portal) {
|
||||||
|
return window.location = (window.portal + "?url=") + window.btoa(window.location).replace(/\//, '_');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
}
|
||||||
}]);
|
]);
|
||||||
|
|
||||||
llapp.config(['$httpProvider', function($httpProvider) {
|
llapp.config([
|
||||||
$httpProvider.interceptors.push('$lmhttp');
|
'$httpProvider', function($httpProvider) {
|
||||||
}]);
|
return $httpProvider.interceptors.push('$lmhttp');
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
|
||||||
})();
|
}).call(this);
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
(function(){var llapp=angular.module("llApp",[]);llapp.provider("$translator",$Translator);function $Translator(){var res={};if(navigator){var nlangs=[navigator.language];if(navigator.languages){nlangs=navigator.languages}var langs=[],langs2=[];nlangs.forEach(function(nl){availableLanguages.forEach(function(al){if(al==nl){langs.push(al)}else{if(al.substring(0,1)==nl.substring(0,1)){langs2.push(al)}}})});res.lang=langs[0]?langs[0]:langs2[0]?langs2[0]:"en"}else{res.lang="en"}res.deferredTr=[];res.translationFields={};res.translate=function(s){if(res.translationFields[s]){s=res.translationFields[s]}return s};res.translateField=function(node,field){return res.translate(node[field])};res.translateP=function(s){if(s&&res.translationFields.portal){s=s.replace(/__(\w+)__/g,function(match,w){return res.translate(w)})}return s};this.$get=["$q","$http",function($q,$http){res.last="";res.init=function(lang){if(!lang){lang=res.lang}var d=$q.defer();if(res.last!=lang){res.last=lang;$http.get(staticPrefix+"languages/"+lang+".json").then(function(response){res.translationFields=response.data;res.deferredTr.forEach(function(h){h.e[h.f](res.translationFields[h.m])});res.deferredTr=[];d.resolve("Translation files loaded")},function(resp){d.reject("")})}else{d.resolve("No change")}return d.promise};return res}]}llapp.directive("trspan",["$translator",function($translator){return{restrict:"A",replace:false,transclude:true,scope:{trspan:"@"},link:function(scope,elem,attr){if($translator.translationFields.portal){attr.trspan=$translator.translate(attr.trspan)}else{$translator.deferredTr.push({e:elem,f:"text",m:attr.trspan})}elem.text(attr.trspan)},template:""}}]);llapp.provider("$htmlParams",$HtmlParamsProvider);function $HtmlParamsProvider(){this.$get=function(){var params={};return{set:function(key,obj){params[key]=obj},menu:function(){return params.menu},params:function(){return params.params}}}}llapp.directive("script",["$htmlParams",function($htmlParams){return{restrict:"E",terminal:true,compile:function(element,attr){var t;if(t=attr.type.match(/text\/(menu|parameters)/)){$htmlParams.set(t[1],eval(element[0].text))}}}}]);llapp.controller("ModalInstanceCtrl",["$scope","$uibModalInstance","elem","set","init",function($scope,$uibModalInstance,elem,set,init){var oldValue;$scope.elem=elem;$scope.set=set;$scope.result=init;$scope.staticPrefix=staticPrefix;var currentNode=elem("currentNode");$scope.translateP=elem("translateP");if(currentNode){oldValue=currentNode.data;$scope.currentNode=currentNode}$scope.ok=function(){set("result",$scope.result);$uibModalInstance.close(true)};$scope.cancel=function(){if(currentNode){$scope.currentNode.data=oldValue}$uibModalInstance.dismiss("cancel")};$scope.inSelect=function(value){for(var i=0;i<$scope.currentNode.select.length;i++){if($scope.currentNode.select[i].k==value){return true}}return false}}]);llapp.directive("onReadFile",["$parse",function($parse){return{restrict:"A",scope:false,link:function(scope,element,attrs){var fn=$parse(attrs.onReadFile);element.on("change",function(onChangeEvent){var reader=new FileReader();reader.onload=function(onLoadEvent){scope.$apply(function(){fn(scope,{$fileContent:onLoadEvent.target.result})})};reader.readAsText((onChangeEvent.srcElement||onChangeEvent.target).files[0])})}}}]);llapp.directive("resizer",["$document",function($document){var rsize,hsize;return function($scope,$element,$attrs){$element.on("mousedown",function(event){if($attrs.resizer=="vertical"){rsize=$($attrs.resizerRight).width()+$($attrs.resizerLeft).width()}else{hsize=$($attrs.resizerTop).height()+$($attrs.resizerBottom).height()}event.preventDefault();$document.on("mousemove",mousemove);$document.on("mouseup",mouseup)});function mousemove(event){if($attrs.resizer=="vertical"){var x=event.pageX;if($attrs.resizerMax&&x>$attrs.resizerMax){x=parseInt($attrs.resizerMax)}$($attrs.resizerLeft).css({width:x+"px"});$($attrs.resizerRight).css({width:(rsize-x)+"px"})}else{var y=event.pageY-$("#navbar").height();$($attrs.resizerTop).css({height:y+"px"});$($attrs.resizerBottom).css({height:(hsize-y)+"px"})}}function mouseup(){$document.unbind("mousemove",mousemove);$document.unbind("mouseup",mouseup)}}}]);llapp.factory("$lmhttp",["$q","$location",function($q,$location){return{responseError:function(rejection){if(rejection.status==401&&window.portal){window.location=window.portal+"?url="+window.btoa(window.location).replace(/\//,"_")}}}}]);llapp.config(["$httpProvider",function($httpProvider){$httpProvider.interceptors.push("$lmhttp")}])})();
|
(function(){var llapp;llapp=angular.module("llApp",[]);llapp.provider("$translator",function(){var al,j,k,langs,langs2,len,len1,nl,nlangs,ref,res;res={};if(navigator){langs=[];langs2=[];nlangs=[navigator.language];if(navigator.languages){nlangs=navigator.languages}for(j=0,len=nlangs.length;j<len;j++){nl=nlangs[j];ref=window.availableLanguages;for(k=0,len1=ref.length;k<len1;k++){al=ref[k];if(al===nl){langs.push(al)}else{if(al.substring(0,1)===nl.substring(0,1)){langs2.push(al)}}}}res.lang=langs[0]?langs[0]:langs2[0]?langs2[0]:"en"}else{res.lang="en"}res.deferredTr=[];res.translationFields={};res.translate=function(s){if(res.translationFields[s]){s=res.translationFields[s]}return s};res.translateField=function(node,field){return res.translate(node[field])};res.translateP=function(s){if(s&&res.translationFields.portal){s=s.replace(/__(\w+)__/g,function(match,w){return res.translate(w)})}return s};this.$get=["$q","$http",function($q,$http){res.last="";res.init=function(lang){var d;if(!lang){lang=res.lang}d=$q.defer();if(res.last!==lang){res.last=lang;$http.get(window.staticPrefix+"languages/"+lang+".json").then(function(response){var h,l,len2,ref1;res.translationFields=response.data;ref1=res.deferredTr;for(l=0,len2=ref1.length;l<len2;l++){h=ref1[l];h.e[h.f](res.translationFields[h.m])}res.deferredTr=[];return d.resolve("Translation files loaded")},function(response){return d.reject("")})}else{d.resolve("No change")}return d.promise};return res}];return this});llapp.directive("trspan",["$translator",function($translator){return{restrict:"A",replace:false,transclude:true,scope:{trspan:"@"},link:function(scope,elem,attr){if($translator.translationFields.portal){attr.trspan=$translator.translate(attr.trspan)}else{$translator.deferredTr.push({e:elem,f:"text",m:attr.trspan})}return elem.text(attr.trspan)},template:""}}]);llapp.provider("$htmlParams",function(){this.$get=function(){var params;params={};return{set:function(key,obj){return params[key]=obj},menu:function(){return params.menu},params:function(){return params.params}}};return this});llapp.directive("script",["$htmlParams",function($htmlParams){return{restrict:"E",terminal:true,compile:function(element,attr){var t;if(t=attr.type.match(/text\/(menu|parameters)/)){return $htmlParams.set(t[1],eval(element[0].text))}}}}]);llapp.controller("ModalInstanceCtrl",["$scope","$uibModalInstance","elem","set","init",function($scope,$uibModalInstance,elem,set,init){var currentNode,oldValue,oldvalue;oldvalue=null;$scope.elem=elem;$scope.set=set;$scope.result=init;$scope.staticPrefix=window.staticPrefix;currentNode=elem("currentNode");$scope.translateP=elem("translateP");if(currentNode){oldValue=currentNode.data;$scope.currentNode=currentNode}$scope.ok=function(){set("result",$scope.result);return $uibModalInstance.close(true)};$scope.cancel=function(){if(currentNode){$scope.currentNode.data=oldValue}return $uibModalInstance.dismiss("cancel")};return $scope.inSelect=function(value){var i,j,len,ref;ref=$scope.currentNode.select;for(j=0,len=ref.length;j<len;j++){i=ref[j];if(i.k===value){return true}}return false}}]);llapp.directive("onReadFile",["$parse",function($parse){return{restrict:"A",scope:false,link:function(scope,element,attrs){var fn;fn=$parse(attrs.onReadFile);return element.on("change",function(onChangeEvent){var reader;reader=new FileReader();reader.onload=function(onLoadEvent){return scope.$apply(function(){return fn(scope,{$fileContent:onLoadEvent.target.result})})};return reader.readAsText((onChangeEvent.srcElement||onChangeEvent.target).files[0])})}}}]);llapp.directive("resizer",["$document",function($document){var hsize,rsize;hsize=null;rsize=null;return function($scope,$element,$attrs){var mousemove,mouseup;$element.on("mousedown",function(event){if($attrs.resizer==="vertical"){rsize=$($attrs.resizerRight).width()+$($attrs.resizerLeft).width()}else{hsize=$($attrs.resizerTop).height()+$($attrs.resizerBottom).height()}event.preventDefault();$document.on("mousemove",mousemove);return $document.on("mouseup",mouseup)});mousemove=function(event){var x,y;if($attrs.resizer==="vertical"){x=event.pageX;if($attrs.resizerMax&&x>$attrs.resizerMax){x=parseInt($attrs.resizerMax)}$($attrs.resizerLeft).css({width:x+"px"});return $($attrs.resizerRight).css({width:(rsize-x)+"px"})}else{y=event.pageY-$("#navbar").height();$($attrs.resizerTop).css({height:y+"px"});return $($attrs.resizerBottom).css({height:(hsize-y)+"px"})}};return mouseup=function(){$document.unbind("mousemove",mousemove);return $document.unbind("mouseup",mouseup)}}}]);llapp.factory("$lmhttp",["$q","$location",function($q,$location){return{responseError:function(rejection){if(rejection.status===401&&window.portal){return window.location=(window.portal+"?url=")+window.btoa(window.location).replace(/\//,"_")}}}}]);llapp.config(["$httpProvider",function($httpProvider){return $httpProvider.interceptors.push("$lmhttp")}])}).call(this);
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user