mirror of
https://github.com/nottinghamtec/PyRIGS.git
synced 2026-03-15 08:25:56 +00:00
Compare commits
120 Commits
forms
...
hotfix/su-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3269e92ef2 | ||
|
|
0ae7bcaf7c | ||
|
|
9694d407ae | ||
|
|
82aa2785ea | ||
|
|
337dbd74fd | ||
|
|
caa55fe89a | ||
|
|
289b30e823 | ||
|
|
b939bc5a64 | ||
|
|
5e8f2312d3 | ||
|
|
90c8b19915 | ||
|
|
d82ef3f8d1 | ||
|
|
fc006dc53e | ||
|
|
3ce191aaf2 | ||
|
|
6fc89727f2 | ||
|
|
b235ac540f | ||
|
|
97decf8c52 | ||
|
|
97cdf34c18 | ||
|
|
92c77c07e0 | ||
|
|
0541a70cec | ||
|
|
e0cb2f4925 | ||
|
|
68a46af1a8 | ||
|
|
f61158b9c0 | ||
|
|
88954eca5c | ||
|
|
3fc04616b3 | ||
|
|
2d5f768523 | ||
|
|
5949ff74ec | ||
|
|
879ecd1f6d | ||
|
|
0e72c3f896 | ||
|
|
b93a716a3b | ||
|
|
0d92c3812a | ||
|
|
fc110a0bff | ||
|
|
008edd8bee | ||
|
|
ac7e85c24a | ||
|
|
73b8ce4add | ||
|
|
511ce554b1 | ||
|
|
536842971d | ||
|
|
3e224a33a7 | ||
|
|
3f4c362bfa | ||
|
|
8a838aa4bd | ||
|
|
7e379b33db | ||
|
|
5e9f7e2c63 | ||
|
|
3f752cd7b7 | ||
|
|
25a3ef3f0c | ||
|
|
1b28efb6af | ||
|
|
441a2be0b8 | ||
|
|
1bdc4bd293 | ||
|
|
f0bb4c5b02 | ||
|
|
4660322964 | ||
|
|
59efc2c485 | ||
|
|
69b0ff9fae | ||
|
|
4b94ea7ef2 | ||
|
|
0244f5cfca | ||
|
|
17c7a3c524 | ||
|
|
a02087bf2a | ||
|
|
585f909d3f | ||
|
|
eb10c8e21f | ||
|
|
f7ea0cb834 | ||
|
|
64f3842a13 | ||
|
|
6370679b62 | ||
|
|
e77728c52c | ||
|
|
92f4e26883 | ||
|
|
024f08562b | ||
|
|
b4246fe170 | ||
|
|
fc6db5bff2 | ||
|
|
c5d3e7c0f2 | ||
|
|
10b57adb37 | ||
|
|
4f839d05f9 | ||
|
|
84393e9e4a | ||
|
|
b94cef92d2 | ||
|
|
10c04be051 | ||
|
|
7ecd6212ac | ||
|
|
11180e507c | ||
|
|
1c90ce5b41 | ||
|
|
11dd9ad02f | ||
|
|
27c0deaba3 | ||
|
|
4c09258566 | ||
|
|
7d14429d84 | ||
|
|
190825f5ef | ||
|
|
021edfd39d | ||
|
|
3052f28329 | ||
|
|
4cec20e357 | ||
|
|
8a0cbe32bd | ||
|
|
8a3a52a21b | ||
|
|
98a9b22e0e | ||
|
|
9178cf6062 | ||
|
|
abbb20e49e | ||
|
|
01d2eae7bc | ||
|
|
39d27d2730 | ||
|
|
05b2de561e | ||
|
|
667b0c80ca | ||
|
|
67624eea6f | ||
|
|
e1578eb0d4 | ||
|
|
a7247c273e | ||
|
|
f265da2f1d | ||
|
|
1163b117e4 | ||
|
|
f92f418bc5 | ||
|
|
9108cb3c4e | ||
|
|
08d17adc8a | ||
|
|
68b35c2d24 | ||
|
|
5cc69cbb41 | ||
|
|
a48afb9157 | ||
|
|
3ccbdff737 | ||
|
|
0990f0bfbb | ||
|
|
f43635ee89 | ||
|
|
705f1bda2b | ||
|
|
0ff0d06eaf | ||
|
|
a769486c9c | ||
|
|
83302c4439 | ||
|
|
ba020b43f1 | ||
|
|
eaf5c9687e | ||
|
|
a725ef5caf | ||
|
|
aa79f3628e | ||
|
|
000351d884 | ||
|
|
db58c113aa | ||
|
|
7cb8503164 | ||
|
|
cc2450ff87 | ||
|
|
6b77393414 | ||
|
|
7ccc8faf20 | ||
|
|
6030288956 | ||
|
|
e4a955f323 |
32
.codeclimate.yml
Normal file
32
.codeclimate.yml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
engines:
|
||||||
|
csslint:
|
||||||
|
enabled: true
|
||||||
|
duplication:
|
||||||
|
enabled: true
|
||||||
|
config:
|
||||||
|
languages:
|
||||||
|
- ruby
|
||||||
|
- javascript
|
||||||
|
- python
|
||||||
|
- php
|
||||||
|
eslint:
|
||||||
|
enabled: true
|
||||||
|
fixme:
|
||||||
|
enabled: true
|
||||||
|
radon:
|
||||||
|
enabled: true
|
||||||
|
rubocop:
|
||||||
|
enabled: true
|
||||||
|
ratings:
|
||||||
|
paths:
|
||||||
|
- "**.css"
|
||||||
|
- "**.inc"
|
||||||
|
- "**.js"
|
||||||
|
- "**.jsx"
|
||||||
|
- "**.module"
|
||||||
|
- "**.php"
|
||||||
|
- "**.py"
|
||||||
|
- "**.rb"
|
||||||
|
exclude_paths:
|
||||||
|
- config/
|
||||||
6
.coveragerc
Normal file
6
.coveragerc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[run]
|
||||||
|
source =
|
||||||
|
./
|
||||||
|
|
||||||
|
omit =
|
||||||
|
*/migrations/*
|
||||||
2
.csslintrc
Normal file
2
.csslintrc
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
--exclude-exts=.min.css
|
||||||
|
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
|
||||||
1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
**/*{.,-}min.js
|
||||||
213
.eslintrc
Normal file
213
.eslintrc
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
ecmaFeatures:
|
||||||
|
modules: true
|
||||||
|
jsx: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
amd: true
|
||||||
|
browser: true
|
||||||
|
es6: true
|
||||||
|
jquery: true
|
||||||
|
node: true
|
||||||
|
|
||||||
|
# http://eslint.org/docs/rules/
|
||||||
|
rules:
|
||||||
|
# Possible Errors
|
||||||
|
comma-dangle: [2, never]
|
||||||
|
no-cond-assign: 2
|
||||||
|
no-console: 0
|
||||||
|
no-constant-condition: 2
|
||||||
|
no-control-regex: 2
|
||||||
|
no-debugger: 2
|
||||||
|
no-dupe-args: 2
|
||||||
|
no-dupe-keys: 2
|
||||||
|
no-duplicate-case: 2
|
||||||
|
no-empty: 2
|
||||||
|
no-empty-character-class: 2
|
||||||
|
no-ex-assign: 2
|
||||||
|
no-extra-boolean-cast: 2
|
||||||
|
no-extra-parens: 0
|
||||||
|
no-extra-semi: 2
|
||||||
|
no-func-assign: 2
|
||||||
|
no-inner-declarations: [2, functions]
|
||||||
|
no-invalid-regexp: 2
|
||||||
|
no-irregular-whitespace: 2
|
||||||
|
no-negated-in-lhs: 2
|
||||||
|
no-obj-calls: 2
|
||||||
|
no-regex-spaces: 2
|
||||||
|
no-sparse-arrays: 2
|
||||||
|
no-unexpected-multiline: 2
|
||||||
|
no-unreachable: 2
|
||||||
|
use-isnan: 2
|
||||||
|
valid-jsdoc: 0
|
||||||
|
valid-typeof: 2
|
||||||
|
|
||||||
|
# Best Practices
|
||||||
|
accessor-pairs: 2
|
||||||
|
block-scoped-var: 0
|
||||||
|
complexity: [2, 6]
|
||||||
|
consistent-return: 0
|
||||||
|
curly: 0
|
||||||
|
default-case: 0
|
||||||
|
dot-location: 0
|
||||||
|
dot-notation: 0
|
||||||
|
eqeqeq: 2
|
||||||
|
guard-for-in: 2
|
||||||
|
no-alert: 2
|
||||||
|
no-caller: 2
|
||||||
|
no-case-declarations: 2
|
||||||
|
no-div-regex: 2
|
||||||
|
no-else-return: 0
|
||||||
|
no-empty-label: 2
|
||||||
|
no-empty-pattern: 2
|
||||||
|
no-eq-null: 2
|
||||||
|
no-eval: 2
|
||||||
|
no-extend-native: 2
|
||||||
|
no-extra-bind: 2
|
||||||
|
no-fallthrough: 2
|
||||||
|
no-floating-decimal: 0
|
||||||
|
no-implicit-coercion: 0
|
||||||
|
no-implied-eval: 2
|
||||||
|
no-invalid-this: 0
|
||||||
|
no-iterator: 2
|
||||||
|
no-labels: 0
|
||||||
|
no-lone-blocks: 2
|
||||||
|
no-loop-func: 2
|
||||||
|
no-magic-number: 0
|
||||||
|
no-multi-spaces: 0
|
||||||
|
no-multi-str: 0
|
||||||
|
no-native-reassign: 2
|
||||||
|
no-new-func: 2
|
||||||
|
no-new-wrappers: 2
|
||||||
|
no-new: 2
|
||||||
|
no-octal-escape: 2
|
||||||
|
no-octal: 2
|
||||||
|
no-proto: 2
|
||||||
|
no-redeclare: 2
|
||||||
|
no-return-assign: 2
|
||||||
|
no-script-url: 2
|
||||||
|
no-self-compare: 2
|
||||||
|
no-sequences: 0
|
||||||
|
no-throw-literal: 0
|
||||||
|
no-unused-expressions: 2
|
||||||
|
no-useless-call: 2
|
||||||
|
no-useless-concat: 2
|
||||||
|
no-void: 2
|
||||||
|
no-warning-comments: 0
|
||||||
|
no-with: 2
|
||||||
|
radix: 2
|
||||||
|
vars-on-top: 0
|
||||||
|
wrap-iife: 2
|
||||||
|
yoda: 0
|
||||||
|
|
||||||
|
# Strict
|
||||||
|
strict: 0
|
||||||
|
|
||||||
|
# Variables
|
||||||
|
init-declarations: 0
|
||||||
|
no-catch-shadow: 2
|
||||||
|
no-delete-var: 2
|
||||||
|
no-label-var: 2
|
||||||
|
no-shadow-restricted-names: 2
|
||||||
|
no-shadow: 0
|
||||||
|
no-undef-init: 2
|
||||||
|
no-undef: 0
|
||||||
|
no-undefined: 0
|
||||||
|
no-unused-vars: 0
|
||||||
|
no-use-before-define: 0
|
||||||
|
|
||||||
|
# Node.js and CommonJS
|
||||||
|
callback-return: 2
|
||||||
|
global-require: 2
|
||||||
|
handle-callback-err: 2
|
||||||
|
no-mixed-requires: 0
|
||||||
|
no-new-require: 0
|
||||||
|
no-path-concat: 2
|
||||||
|
no-process-exit: 2
|
||||||
|
no-restricted-modules: 0
|
||||||
|
no-sync: 0
|
||||||
|
|
||||||
|
# Stylistic Issues
|
||||||
|
array-bracket-spacing: 0
|
||||||
|
block-spacing: 0
|
||||||
|
brace-style: 0
|
||||||
|
camelcase: 0
|
||||||
|
comma-spacing: 0
|
||||||
|
comma-style: 0
|
||||||
|
computed-property-spacing: 0
|
||||||
|
consistent-this: 0
|
||||||
|
eol-last: 0
|
||||||
|
func-names: 0
|
||||||
|
func-style: 0
|
||||||
|
id-length: 0
|
||||||
|
id-match: 0
|
||||||
|
indent: 0
|
||||||
|
jsx-quotes: 0
|
||||||
|
key-spacing: 0
|
||||||
|
linebreak-style: 0
|
||||||
|
lines-around-comment: 0
|
||||||
|
max-depth: 0
|
||||||
|
max-len: 0
|
||||||
|
max-nested-callbacks: 0
|
||||||
|
max-params: 0
|
||||||
|
max-statements: [2, 30]
|
||||||
|
new-cap: 0
|
||||||
|
new-parens: 0
|
||||||
|
newline-after-var: 0
|
||||||
|
no-array-constructor: 0
|
||||||
|
no-bitwise: 0
|
||||||
|
no-continue: 0
|
||||||
|
no-inline-comments: 0
|
||||||
|
no-lonely-if: 0
|
||||||
|
no-mixed-spaces-and-tabs: 0
|
||||||
|
no-multiple-empty-lines: 0
|
||||||
|
no-negated-condition: 0
|
||||||
|
no-nested-ternary: 0
|
||||||
|
no-new-object: 0
|
||||||
|
no-plusplus: 0
|
||||||
|
no-restricted-syntax: 0
|
||||||
|
no-spaced-func: 0
|
||||||
|
no-ternary: 0
|
||||||
|
no-trailing-spaces: 0
|
||||||
|
no-underscore-dangle: 0
|
||||||
|
no-unneeded-ternary: 0
|
||||||
|
object-curly-spacing: 0
|
||||||
|
one-var: 0
|
||||||
|
operator-assignment: 0
|
||||||
|
operator-linebreak: 0
|
||||||
|
padded-blocks: 0
|
||||||
|
quote-props: 0
|
||||||
|
quotes: 0
|
||||||
|
require-jsdoc: 0
|
||||||
|
semi-spacing: 0
|
||||||
|
semi: 0
|
||||||
|
sort-vars: 0
|
||||||
|
space-after-keywords: 0
|
||||||
|
space-before-blocks: 0
|
||||||
|
space-before-function-paren: 0
|
||||||
|
space-before-keywords: 0
|
||||||
|
space-in-parens: 0
|
||||||
|
space-infix-ops: 0
|
||||||
|
space-return-throw-case: 0
|
||||||
|
space-unary-ops: 0
|
||||||
|
spaced-comment: 0
|
||||||
|
wrap-regex: 0
|
||||||
|
|
||||||
|
# ECMAScript 6
|
||||||
|
arrow-body-style: 0
|
||||||
|
arrow-parens: 0
|
||||||
|
arrow-spacing: 0
|
||||||
|
constructor-super: 0
|
||||||
|
generator-star-spacing: 0
|
||||||
|
no-arrow-condition: 0
|
||||||
|
no-class-assign: 0
|
||||||
|
no-const-assign: 0
|
||||||
|
no-dupe-class-members: 0
|
||||||
|
no-this-before-super: 0
|
||||||
|
no-var: 0
|
||||||
|
object-shorthand: 0
|
||||||
|
prefer-arrow-callback: 0
|
||||||
|
prefer-const: 0
|
||||||
|
prefer-reflect: 0
|
||||||
|
prefer-spread: 0
|
||||||
|
prefer-template: 0
|
||||||
|
require-yield: 0
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
tmp/
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
@@ -25,9 +28,6 @@ var/
|
|||||||
|
|
||||||
# Continer extras
|
# Continer extras
|
||||||
.vagrant
|
.vagrant
|
||||||
_builds
|
|
||||||
_steps
|
|
||||||
_projects
|
|
||||||
|
|
||||||
# PyInstaller
|
# PyInstaller
|
||||||
# Usually these files are written by a python script from a template
|
# Usually these files are written by a python script from a template
|
||||||
|
|||||||
1156
.rubocop.yml
Normal file
1156
.rubocop.yml
Normal file
File diff suppressed because it is too large
Load Diff
21
.travis.yml
Normal file
21
.travis.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
language: python
|
||||||
|
python:
|
||||||
|
"2.7"
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- "export DISPLAY=:99.0"
|
||||||
|
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x16"
|
||||||
|
|
||||||
|
install:
|
||||||
|
- pip install -r requirements.txt
|
||||||
|
- pip install coveralls codeclimate-test-reporter
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- python manage.py collectstatic --noinput
|
||||||
|
|
||||||
|
script:
|
||||||
|
- coverage run manage.py test RIGS
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- coveralls
|
||||||
|
- codeclimate-test-reporter
|
||||||
@@ -2,23 +2,37 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
|
|||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
def user_passes_test_with_403(test_func, login_url=None):
|
from RIGS import models
|
||||||
|
|
||||||
|
|
||||||
|
def user_passes_test_with_403(test_func, login_url=None, oembed_view=None):
|
||||||
"""
|
"""
|
||||||
Decorator for views that checks that the user passes the given test.
|
Decorator for views that checks that the user passes the given test.
|
||||||
|
|
||||||
Anonymous users will be redirected to login_url, while users that fail
|
Anonymous users will be redirected to login_url, while users that fail
|
||||||
the test will be given a 403 error.
|
the test will be given a 403 error.
|
||||||
|
If embed_view is set, then a JS redirect will be used, and a application/json+oembed
|
||||||
|
meta tag set with the url of oembed_view
|
||||||
|
(oembed_view will be passed the kwargs from the main function)
|
||||||
"""
|
"""
|
||||||
if not login_url:
|
if not login_url:
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
login_url = settings.LOGIN_URL
|
login_url = settings.LOGIN_URL
|
||||||
|
|
||||||
def _dec(view_func):
|
def _dec(view_func):
|
||||||
def _checklogin(request, *args, **kwargs):
|
def _checklogin(request, *args, **kwargs):
|
||||||
if test_func(request.user):
|
if test_func(request.user):
|
||||||
return view_func(request, *args, **kwargs)
|
return view_func(request, *args, **kwargs)
|
||||||
elif not request.user.is_authenticated():
|
elif not request.user.is_authenticated():
|
||||||
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, request.get_full_path()))
|
if oembed_view is not None:
|
||||||
|
extra_context = {}
|
||||||
|
extra_context['oembed_url'] = "{0}://{1}{2}".format(request.scheme, request.META['HTTP_HOST'], reverse(oembed_view, kwargs=kwargs))
|
||||||
|
extra_context['login_url'] = "{0}?{1}={2}".format(login_url, REDIRECT_FIELD_NAME, request.get_full_path())
|
||||||
|
resp = render_to_response('login_redirect.html', extra_context, context_instance=RequestContext(request))
|
||||||
|
return resp
|
||||||
|
else:
|
||||||
|
return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, request.get_full_path()))
|
||||||
else:
|
else:
|
||||||
resp = render_to_response('403.html', context_instance=RequestContext(request))
|
resp = render_to_response('403.html', context_instance=RequestContext(request))
|
||||||
resp.status_code = 403
|
resp.status_code = 403
|
||||||
@@ -28,14 +42,14 @@ def user_passes_test_with_403(test_func, login_url=None):
|
|||||||
return _checklogin
|
return _checklogin
|
||||||
return _dec
|
return _dec
|
||||||
|
|
||||||
def permission_required_with_403(perm, login_url=None):
|
|
||||||
|
def permission_required_with_403(perm, login_url=None, oembed_view=None):
|
||||||
"""
|
"""
|
||||||
Decorator for views that checks whether a user has a particular permission
|
Decorator for views that checks whether a user has a particular permission
|
||||||
enabled, redirecting to the log-in page or rendering a 403 as necessary.
|
enabled, redirecting to the log-in page or rendering a 403 as necessary.
|
||||||
"""
|
"""
|
||||||
return user_passes_test_with_403(lambda u: u.has_perm(perm), login_url=login_url)
|
return user_passes_test_with_403(lambda u: u.has_perm(perm), login_url=login_url, oembed_view=oembed_view)
|
||||||
|
|
||||||
from RIGS import models
|
|
||||||
|
|
||||||
def api_key_required(function):
|
def api_key_required(function):
|
||||||
"""
|
"""
|
||||||
@@ -58,10 +72,10 @@ def api_key_required(function):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
user_object = models.Profile.objects.get(pk=userid)
|
user_object = models.Profile.objects.get(pk=userid)
|
||||||
except Profile.DoesNotExist:
|
except models.Profile.DoesNotExist:
|
||||||
return error_resp
|
return error_resp
|
||||||
|
|
||||||
if user_object.api_key != key:
|
if user_object.api_key != key:
|
||||||
return error_resp
|
return error_resp
|
||||||
return function(request, *args, **kwargs)
|
return function(request, *args, **kwargs)
|
||||||
return wrap
|
return wrap
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ https://docs.djangoproject.com/en/1.7/ref/settings/
|
|||||||
import os
|
import os
|
||||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||||
|
|
||||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
# See https://docs.djangoproject.com/en/1.7/howto/deployment/checklist/
|
||||||
|
|
||||||
@@ -23,10 +21,19 @@ SECRET_KEY = os.environ.get('SECRET_KEY') if os.environ.get('SECRET_KEY') else '
|
|||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
DEBUG = bool(int(os.environ.get('DEBUG'))) if os.environ.get('DEBUG') else True
|
DEBUG = bool(int(os.environ.get('DEBUG'))) if os.environ.get('DEBUG') else True
|
||||||
|
|
||||||
|
STAGING = bool(int(os.environ.get('STAGING'))) if os.environ.get('STAGING') else False
|
||||||
|
|
||||||
TEMPLATE_DEBUG = True
|
TEMPLATE_DEBUG = True
|
||||||
|
|
||||||
ALLOWED_HOSTS = ['pyrigs.nottinghamtec.co.uk', 'rigs.nottinghamtec.co.uk', 'pyrigs.herokuapp.com']
|
ALLOWED_HOSTS = ['pyrigs.nottinghamtec.co.uk', 'rigs.nottinghamtec.co.uk', 'pyrigs.herokuapp.com']
|
||||||
|
|
||||||
|
if STAGING:
|
||||||
|
ALLOWED_HOSTS.append('.herokuapp.com')
|
||||||
|
|
||||||
|
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
|
||||||
|
if not DEBUG:
|
||||||
|
SECURE_SSL_REDIRECT = True # Redirect all http requests to https
|
||||||
|
|
||||||
INTERNAL_IPS = ['127.0.0.1']
|
INTERNAL_IPS = ['127.0.0.1']
|
||||||
|
|
||||||
ADMINS = (
|
ADMINS = (
|
||||||
@@ -44,7 +51,6 @@ INSTALLED_APPS = (
|
|||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'RIGS',
|
'RIGS',
|
||||||
'rigForms',
|
|
||||||
|
|
||||||
'debug_toolbar',
|
'debug_toolbar',
|
||||||
'registration',
|
'registration',
|
||||||
@@ -56,6 +62,7 @@ INSTALLED_APPS = (
|
|||||||
|
|
||||||
MIDDLEWARE_CLASSES = (
|
MIDDLEWARE_CLASSES = (
|
||||||
'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware',
|
'raven.contrib.django.raven_compat.middleware.SentryResponseErrorIdMiddleware',
|
||||||
|
'django.middleware.security.SecurityMiddleware',
|
||||||
'reversion.middleware.RevisionMiddleware',
|
'reversion.middleware.RevisionMiddleware',
|
||||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ urlpatterns = patterns('',
|
|||||||
url('^user/', include('registration.backends.default.urls')),
|
url('^user/', include('registration.backends.default.urls')),
|
||||||
|
|
||||||
url(r'^admin/', include(admin.site.urls)),
|
url(r'^admin/', include(admin.site.urls)),
|
||||||
|
|
||||||
url(r'^forms/', include('rigForms.urls')),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -1,5 +1,6 @@
|
|||||||
# TEC PA & Lighting - PyRIGS #
|
# TEC PA & Lighting - PyRIGS #
|
||||||
[](https://app.wercker.com/project/bykey/2dbe0517c3d83859c985ffc5a55a2802)
|
[](https://travis-ci.org/nottinghamtec/PyRIGS)
|
||||||
|
[](https://coveralls.io/github/nottinghamtec/PyRIGS?branch=develop)
|
||||||
|
|
||||||
Welcome to TEC PA & Lightings PyRIGS program. This is a reimplementation of the existing Rig Information Gathering System (RIGS) that was developed using Ruby on Rails.
|
Welcome to TEC PA & Lightings PyRIGS program. This is a reimplementation of the existing Rig Information Gathering System (RIGS) that was developed using Ruby on Rails.
|
||||||
|
|
||||||
@@ -74,5 +75,23 @@ python manage.py runserver
|
|||||||
```
|
```
|
||||||
Please refer to Django documentation for a full list of options available here.
|
Please refer to Django documentation for a full list of options available here.
|
||||||
|
|
||||||
|
### Sample Data ###
|
||||||
|
Sample data is available to aid local development and user acceptance testing. To load this data into your local database, first ensure the database is empty:
|
||||||
|
```
|
||||||
|
python manage.py flush
|
||||||
|
```
|
||||||
|
Then load the sample data using the command:
|
||||||
|
```
|
||||||
|
python manage.py generateSampleData
|
||||||
|
```
|
||||||
|
4 user accounts are created for convenience:
|
||||||
|
|
||||||
|
|Username |Password |
|
||||||
|
|---------|---------|
|
||||||
|
|superuser|superuser|
|
||||||
|
|finance |finance |
|
||||||
|
|keyholder|keyholder|
|
||||||
|
|basic |basic |
|
||||||
|
|
||||||
### Committing, pushing and testing ###
|
### Committing, pushing and testing ###
|
||||||
Feel free to commit as you wish, on your own branch. On my branch (master for development) do not commit code that you either know doesn't work or don't know works. If you must commit this code, please make sure you say in the commit message that it isn't working, and if you can why it isn't working. If and only if you absolutely must push, then please don't leave it as the HEAD for too long, it's not much to ask but when you are done just make sure you haven't broken the HEAD for the next person.
|
Feel free to commit as you wish, on your own branch. On my branch (master for development) do not commit code that you either know doesn't work or don't know works. If you must commit this code, please make sure you say in the commit message that it isn't working, and if you can why it isn't working. If and only if you absolutely must push, then please don't leave it as the HEAD for too long, it's not much to ask but when you are done just make sure you haven't broken the HEAD for the next person.
|
||||||
|
|||||||
@@ -1,32 +1,41 @@
|
|||||||
import cStringIO as StringIO
|
import cStringIO as StringIO
|
||||||
|
import datetime
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.contrib import messages
|
||||||
from django.core.urlresolvers import reverse_lazy
|
from django.core.urlresolvers import reverse_lazy
|
||||||
from django.db import connection
|
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.views import generic
|
|
||||||
from django.template import RequestContext
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.contrib import messages
|
from django.template import RequestContext
|
||||||
import datetime
|
from django.template.loader import get_template
|
||||||
|
from django.views import generic
|
||||||
|
from django.db.models import Q
|
||||||
from z3c.rml import rml2pdf
|
from z3c.rml import rml2pdf
|
||||||
|
|
||||||
from RIGS import models
|
from RIGS import models
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
class InvoiceIndex(generic.ListView):
|
class InvoiceIndex(generic.ListView):
|
||||||
model = models.Invoice
|
model = models.Invoice
|
||||||
template_name = 'RIGS/invoice_list.html'
|
template_name = 'RIGS/invoice_list_active.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(InvoiceIndex, self).get_context_data(**kwargs)
|
||||||
|
total = 0
|
||||||
|
for i in context['object_list']:
|
||||||
|
total += i.balance
|
||||||
|
context['total'] = total
|
||||||
|
context['count'] = len(list(context['object_list']))
|
||||||
|
return context
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
# Manual query is the only way I have found to do this efficiently. Not ideal but needs must
|
# Manual query is the only way I have found to do this efficiently. Not ideal but needs must
|
||||||
sql = "SELECT * FROM " \
|
sql = "SELECT * FROM " \
|
||||||
"(SELECT " \
|
"(SELECT " \
|
||||||
"(SELECT COUNT(p.amount) FROM \"RIGS_payment\" as p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payment_count\", " \
|
"(SELECT COUNT(p.amount) FROM \"RIGS_payment\" AS p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payment_count\", " \
|
||||||
"(SELECT SUM(ei.cost * ei.quantity) FROM \"RIGS_eventitem\" AS ei WHERE ei.event_id=\"RIGS_invoice\".event_id) AS \"cost\", " \
|
"(SELECT SUM(ei.cost * ei.quantity) FROM \"RIGS_eventitem\" AS ei WHERE ei.event_id=\"RIGS_invoice\".event_id) AS \"cost\", " \
|
||||||
"(SELECT SUM(p.amount) FROM \"RIGS_payment\" as p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payments\", " \
|
"(SELECT SUM(p.amount) FROM \"RIGS_payment\" AS p WHERE p.invoice_id=\"RIGS_invoice\".id) AS \"payments\", " \
|
||||||
"\"RIGS_invoice\".\"id\", \"RIGS_invoice\".\"event_id\", \"RIGS_invoice\".\"invoice_date\", \"RIGS_invoice\".\"void\" FROM \"RIGS_invoice\") " \
|
"\"RIGS_invoice\".\"id\", \"RIGS_invoice\".\"event_id\", \"RIGS_invoice\".\"invoice_date\", \"RIGS_invoice\".\"void\" FROM \"RIGS_invoice\") " \
|
||||||
"AS sub " \
|
"AS sub " \
|
||||||
"WHERE (((cost > 0.0) AND (payment_count=0)) OR (cost - payments) <> 0.0) AND void = '0'" \
|
"WHERE (((cost > 0.0) AND (payment_count=0)) OR (cost - payments) <> 0.0) AND void = '0'" \
|
||||||
@@ -40,6 +49,7 @@ class InvoiceIndex(generic.ListView):
|
|||||||
class InvoiceDetail(generic.DetailView):
|
class InvoiceDetail(generic.DetailView):
|
||||||
model = models.Invoice
|
model = models.Invoice
|
||||||
|
|
||||||
|
|
||||||
class InvoicePrint(generic.View):
|
class InvoicePrint(generic.View):
|
||||||
def get(self, request, pk):
|
def get(self, request, pk):
|
||||||
invoice = get_object_or_404(models.Invoice, pk=pk)
|
invoice = get_object_or_404(models.Invoice, pk=pk)
|
||||||
@@ -54,8 +64,8 @@ class InvoicePrint(generic.View):
|
|||||||
'bold': 'RIGS/static/fonts/OPENSANS-BOLD.TTF',
|
'bold': 'RIGS/static/fonts/OPENSANS-BOLD.TTF',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'invoice':invoice,
|
'invoice': invoice,
|
||||||
'current_user':request.user,
|
'current_user': request.user,
|
||||||
})
|
})
|
||||||
|
|
||||||
rml = template.render(context)
|
rml = template.render(context)
|
||||||
@@ -72,6 +82,7 @@ class InvoicePrint(generic.View):
|
|||||||
response.write(pdfData)
|
response.write(pdfData)
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
class InvoiceVoid(generic.View):
|
class InvoiceVoid(generic.View):
|
||||||
def get(self, *args, **kwargs):
|
def get(self, *args, **kwargs):
|
||||||
pk = kwargs.get('pk')
|
pk = kwargs.get('pk')
|
||||||
@@ -83,9 +94,29 @@ class InvoiceVoid(generic.View):
|
|||||||
return HttpResponseRedirect(reverse_lazy('invoice_list'))
|
return HttpResponseRedirect(reverse_lazy('invoice_list'))
|
||||||
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': object.pk}))
|
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': object.pk}))
|
||||||
|
|
||||||
|
class InvoiceDelete(generic.DeleteView):
|
||||||
|
model = models.Invoice
|
||||||
|
|
||||||
|
def get(self, request, pk):
|
||||||
|
obj = self.get_object()
|
||||||
|
if obj.payment_set.all().count() > 0:
|
||||||
|
messages.info(self.request, 'To delete an invoice, delete the payments first.')
|
||||||
|
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk}))
|
||||||
|
return super(InvoiceDelete, self).get(pk)
|
||||||
|
|
||||||
|
def post(self, request, pk):
|
||||||
|
obj = self.get_object()
|
||||||
|
if obj.payment_set.all().count() > 0:
|
||||||
|
messages.info(self.request, 'To delete an invoice, delete the payments first.')
|
||||||
|
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': obj.pk}))
|
||||||
|
return super(InvoiceDelete, self).post(pk)
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return self.request.POST.get('next')
|
||||||
|
|
||||||
class InvoiceArchive(generic.ListView):
|
class InvoiceArchive(generic.ListView):
|
||||||
model = models.Invoice
|
model = models.Invoice
|
||||||
|
template_name = 'RIGS/invoice_list_archive.html'
|
||||||
paginate_by = 25
|
paginate_by = 25
|
||||||
|
|
||||||
|
|
||||||
@@ -94,14 +125,33 @@ class InvoiceWaiting(generic.ListView):
|
|||||||
paginate_by = 25
|
paginate_by = 25
|
||||||
template_name = 'RIGS/event_invoice.html'
|
template_name = 'RIGS/event_invoice.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(InvoiceWaiting, self).get_context_data(**kwargs)
|
||||||
|
total = 0
|
||||||
|
for obj in self.get_objects():
|
||||||
|
total += obj.sum_total
|
||||||
|
context['total'] = total
|
||||||
|
context['count'] = len(self.get_objects())
|
||||||
|
return context
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
return self.get_objects()
|
||||||
|
|
||||||
|
def get_objects(self):
|
||||||
# @todo find a way to select items
|
# @todo find a way to select items
|
||||||
events = self.model.objects.filter(is_rig=True, end_date__lt=datetime.date.today(),
|
events = self.model.objects.filter(
|
||||||
invoice__isnull=True) \
|
(
|
||||||
.order_by('start_date') \
|
Q(start_date__lte=datetime.date.today(), end_date__isnull=True) | # Starts before with no end
|
||||||
|
Q(end_date__lte=datetime.date.today()) # Has end date, finishes before
|
||||||
|
) & Q(invoice__isnull=True) # Has not already been invoiced
|
||||||
|
& Q(is_rig=True) # Is a rig (not non-rig)
|
||||||
|
|
||||||
|
).order_by('start_date') \
|
||||||
.select_related('person',
|
.select_related('person',
|
||||||
'organisation',
|
'organisation',
|
||||||
'venue', 'mic')
|
'venue', 'mic') \
|
||||||
|
.prefetch_related('items')
|
||||||
|
|
||||||
return events
|
return events
|
||||||
|
|
||||||
|
|
||||||
@@ -113,13 +163,14 @@ class InvoiceEvent(generic.View):
|
|||||||
|
|
||||||
if created:
|
if created:
|
||||||
invoice.invoice_date = datetime.date.today()
|
invoice.invoice_date = datetime.date.today()
|
||||||
|
messages.success(self.request, 'Invoice created successfully')
|
||||||
|
|
||||||
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': invoice.pk}))
|
return HttpResponseRedirect(reverse_lazy('invoice_detail', kwargs={'pk': invoice.pk}))
|
||||||
|
|
||||||
|
|
||||||
class PaymentCreate(generic.CreateView):
|
class PaymentCreate(generic.CreateView):
|
||||||
model = models.Payment
|
model = models.Payment
|
||||||
fields = ['invoice','date','amount','method']
|
fields = ['invoice', 'date', 'amount', 'method']
|
||||||
|
|
||||||
def get_initial(self):
|
def get_initial(self):
|
||||||
initial = super(generic.CreateView, self).get_initial()
|
initial = super(generic.CreateView, self).get_initial()
|
||||||
@@ -139,4 +190,4 @@ class PaymentDelete(generic.DeleteView):
|
|||||||
model = models.Payment
|
model = models.Payment
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self):
|
||||||
return self.request.POST.get('next')
|
return self.request.POST.get('next')
|
||||||
|
|||||||
248
RIGS/management/commands/generateSampleData.py
Normal file
248
RIGS/management/commands/generateSampleData.py
Normal file
@@ -0,0 +1,248 @@
|
|||||||
|
from django.core.management.base import BaseCommand, CommandError
|
||||||
|
from django.contrib.auth.models import Group, Permission
|
||||||
|
from django.db import transaction
|
||||||
|
import reversion
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import random
|
||||||
|
|
||||||
|
from RIGS import models
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Adds sample data to use for testing'
|
||||||
|
can_import_settings = True
|
||||||
|
|
||||||
|
people = []
|
||||||
|
organisations = []
|
||||||
|
venues = []
|
||||||
|
profiles = []
|
||||||
|
|
||||||
|
keyholder_group = None
|
||||||
|
finance_group = None
|
||||||
|
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
if not (settings.DEBUG or settings.STAGING):
|
||||||
|
raise CommandError('You cannot run this command in production')
|
||||||
|
|
||||||
|
random.seed('Some object to seed the random number generator') # otherwise it is done by time, which could lead to inconsistant tests
|
||||||
|
|
||||||
|
with transaction.atomic():
|
||||||
|
models.VatRate.objects.create(start_at='2014-03-05',rate=0.20,comment='test1')
|
||||||
|
|
||||||
|
self.setupGenericProfiles()
|
||||||
|
|
||||||
|
self.setupPeople()
|
||||||
|
self.setupOrganisations()
|
||||||
|
self.setupVenues()
|
||||||
|
|
||||||
|
self.setupGroups()
|
||||||
|
|
||||||
|
self.setupEvents()
|
||||||
|
|
||||||
|
self.setupUsefulProfiles()
|
||||||
|
|
||||||
|
def setupPeople(self):
|
||||||
|
names = ["Regulus Black","Sirius Black","Lavender Brown","Cho Chang","Vincent Crabbe","Vincent Crabbe","Bartemius Crouch","Fleur Delacour","Cedric Diggory","Alberforth Dumbledore","Albus Dumbledore","Dudley Dursley","Petunia Dursley","Vernon Dursley","Argus Filch","Seamus Finnigan","Nicolas Flamel","Cornelius Fudge","Goyle","Gregory Goyle","Hermione Granger","Rubeus Hagrid","Igor Karkaroff","Viktor Krum","Bellatrix Lestrange","Alice Longbottom","Frank Longbottom","Neville Longbottom","Luna Lovegood","Xenophilius Lovegood","Remus Lupin","Draco Malfoy","Lucius Malfoy","Narcissa Malfoy","Olympe Maxime","Minerva McGonagall","Mad-Eye Moody","Peter Pettigrew","Harry Potter","James Potter","Lily Potter","Quirinus Quirrell","Tom Riddle","Mary Riddle","Lord Voldemort","Rita Skeeter","Severus Snape","Nymphadora Tonks","Dolores Janes Umbridge","Arthur Weasley","Bill Weasley","Charlie Weasley","Fred Weasley","George Weasley","Ginny Weasley","Molly Weasley","Percy Weasley","Ron Weasley","Dobby","Fluffy","Hedwig","Moaning Myrtle","Aragog","Grawp"]
|
||||||
|
for i, name in enumerate(names):
|
||||||
|
with reversion.create_revision():
|
||||||
|
reversion.set_user(random.choice(self.profiles))
|
||||||
|
|
||||||
|
newPerson = models.Person.objects.create(name=name)
|
||||||
|
if i % 3 == 0:
|
||||||
|
newPerson.email = "address@person.com"
|
||||||
|
|
||||||
|
if i % 5 == 0:
|
||||||
|
newPerson.notes = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
|
||||||
|
|
||||||
|
if i % 7 == 0:
|
||||||
|
newPerson.address = "1 Person Test Street \n Demoton \n United States of TEC \n RMRF 567"
|
||||||
|
|
||||||
|
if i % 9 == 0:
|
||||||
|
newPerson.phone = "01234 567894"
|
||||||
|
|
||||||
|
newPerson.save()
|
||||||
|
self.people.append(newPerson)
|
||||||
|
|
||||||
|
def setupOrganisations(self):
|
||||||
|
names = ["Acme, inc.","Widget Corp","123 Warehousing","Demo Company","Smith and Co.","Foo Bars","ABC Telecom","Fake Brothers","QWERTY Logistics","Demo, inc.","Sample Company","Sample, inc","Acme Corp","Allied Biscuit","Ankh-Sto Associates","Extensive Enterprise","Galaxy Corp","Globo-Chem","Mr. Sparkle","Globex Corporation","LexCorp","LuthorCorp","North Central Positronics","Omni Consimer Products","Praxis Corporation","Sombra Corporation","Sto Plains Holdings","Tessier-Ashpool","Wayne Enterprises","Wentworth Industries","ZiffCorp","Bluth Company","Strickland Propane","Thatherton Fuels","Three Waters","Water and Power","Western Gas & Electric","Mammoth Pictures","Mooby Corp","Gringotts","Thrift Bank","Flowers By Irene","The Legitimate Businessmens Club","Osato Chemicals","Transworld Consortium","Universal Export","United Fried Chicken","Virtucon","Kumatsu Motors","Keedsler Motors","Powell Motors","Industrial Automation","Sirius Cybernetics Corporation","U.S. Robotics and Mechanical Men","Colonial Movers","Corellian Engineering Corporation","Incom Corporation","General Products","Leeding Engines Ltd.","Blammo","Input, Inc.","Mainway Toys","Videlectrix","Zevo Toys","Ajax","Axis Chemical Co.","Barrytron","Carrys Candles","Cogswell Cogs","Spacely Sprockets","General Forge and Foundry","Duff Brewing Company","Dunder Mifflin","General Services Corporation","Monarch Playing Card Co.","Krustyco","Initech","Roboto Industries","Primatech","Sonky Rubber Goods","St. Anky Beer","Stay Puft Corporation","Vandelay Industries","Wernham Hogg","Gadgetron","Burleigh and Stronginthearm","BLAND Corporation","Nordyne Defense Dynamics","Petrox Oil Company","Roxxon","McMahon and Tate","Sixty Second Avenue","Charles Townsend Agency","Spade and Archer","Megadodo Publications","Rouster and Sideways","C.H. Lavatory and Sons","Globo Gym American Corp","The New Firm","SpringShield","Compuglobalhypermeganet","Data Systems","Gizmonic Institute","Initrode","Taggart Transcontinental","Atlantic Northern","Niagular","Plow King","Big Kahuna Burger","Big T Burgers and Fries","Chez Quis","Chotchkies","The Frying Dutchman","Klimpys","The Krusty Krab","Monks Diner","Milliways","Minuteman Cafe","Taco Grande","Tip Top Cafe","Moes Tavern","Central Perk","Chasers"]
|
||||||
|
for i, name in enumerate(names):
|
||||||
|
with reversion.create_revision():
|
||||||
|
reversion.set_user(random.choice(self.profiles))
|
||||||
|
newOrganisation = models.Organisation.objects.create(name=name)
|
||||||
|
if i % 2 == 0:
|
||||||
|
newOrganisation.has_su_account = True
|
||||||
|
|
||||||
|
if i % 3 == 0:
|
||||||
|
newOrganisation.email = "address@organisation.com"
|
||||||
|
|
||||||
|
if i % 5 == 0:
|
||||||
|
newOrganisation.notes = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
|
||||||
|
|
||||||
|
if i % 7 == 0:
|
||||||
|
newOrganisation.address = "1 Organisation Test Street \n Demoton \n United States of TEC \n RMRF 567"
|
||||||
|
|
||||||
|
if i % 9 == 0:
|
||||||
|
newOrganisation.phone = "01234 567894"
|
||||||
|
|
||||||
|
newOrganisation.save()
|
||||||
|
self.organisations.append(newOrganisation)
|
||||||
|
|
||||||
|
def setupVenues(self):
|
||||||
|
names = ["Bear Island","Crossroads Inn","Deepwood Motte","The Dreadfort","The Eyrie","Greywater Watch","The Iron Islands","Karhold","Moat Cailin","Oldstones","Raventree Hall","Riverlands","The Ruby Ford","Saltpans","Seagard","Torrhen's Square","The Trident","The Twins","The Vale of Arryn","The Whispering Wood","White Harbor","Winterfell","The Arbor","Ashemark","Brightwater Keep","Casterly Rock","Clegane's Keep","Dragonstone","Dorne","God's Eye","The Golden Tooth","Harrenhal","Highgarden","Horn Hill","Fingers","King's Landing","Lannisport","Oldtown","Rainswood","Storm's End","Summerhall","Sunspear","Tarth","Castle Black","Craster's Keep","Fist of the First Men","The Frostfangs","The Gift","The Skirling Pass","The Wall","Asshai","Astapor","Braavos","The Dothraki Sea","Lys","Meereen","Myr","Norvos","Pentos","Qarth","Qohor","The Red Waste","Tyrosh","Vaes Dothrak","Valyria","Village of the Lhazareen","Volantis","Yunkai"]
|
||||||
|
for i, name in enumerate(names):
|
||||||
|
with reversion.create_revision():
|
||||||
|
reversion.set_user(random.choice(self.profiles))
|
||||||
|
newVenue = models.Venue.objects.create(name=name)
|
||||||
|
if i % 2 == 0:
|
||||||
|
newVenue.three_phase_available = True
|
||||||
|
|
||||||
|
if i % 3 == 0:
|
||||||
|
newVenue.email = "address@venue.com"
|
||||||
|
|
||||||
|
if i % 5 == 0:
|
||||||
|
newVenue.notes = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua"
|
||||||
|
|
||||||
|
if i % 7 == 0:
|
||||||
|
newVenue.address = "1 Venue Test Street \n Demoton \n United States of TEC \n RMRF 567"
|
||||||
|
|
||||||
|
if i % 9 == 0:
|
||||||
|
newVenue.phone = "01234 567894"
|
||||||
|
|
||||||
|
newVenue.save()
|
||||||
|
self.venues.append(newVenue)
|
||||||
|
|
||||||
|
def setupGroups(self):
|
||||||
|
self.keyholder_group = Group.objects.create(name='Keyholders')
|
||||||
|
self.finance_group = Group.objects.create(name='Finance')
|
||||||
|
|
||||||
|
keyholderPerms = ["add_event","change_event","view_event","add_eventitem","change_eventitem","delete_eventitem","add_organisation","change_organisation","view_organisation","add_person","change_person","view_person","view_profile","add_venue","change_venue","view_venue"]
|
||||||
|
financePerms = ["change_event","view_event","add_eventitem","change_eventitem","add_invoice","change_invoice","view_invoice","add_organisation","change_organisation","view_organisation","add_payment","change_payment","delete_payment","add_person","change_person","view_person"]
|
||||||
|
|
||||||
|
for permId in keyholderPerms:
|
||||||
|
self.keyholder_group.permissions.add(Permission.objects.get(codename=permId))
|
||||||
|
|
||||||
|
for permId in financePerms:
|
||||||
|
self.finance_group.permissions.add(Permission.objects.get(codename=permId))
|
||||||
|
|
||||||
|
def setupGenericProfiles(self):
|
||||||
|
names = ["Clara Oswin Oswald","Rory Williams","Amy Pond","River Song","Martha Jones","Donna Noble","Jack Harkness","Mickey Smith","Rose Tyler"]
|
||||||
|
for i, name in enumerate(names):
|
||||||
|
newProfile = models.Profile.objects.create(username=name.replace(" ",""), first_name=name.split(" ")[0], last_name=name.split(" ")[-1],
|
||||||
|
email=name.replace(" ","")+"@example.com",
|
||||||
|
initials="".join([ j[0].upper() for j in name.split() ]))
|
||||||
|
if i % 2 == 0:
|
||||||
|
newProfile.phone = "01234 567894"
|
||||||
|
|
||||||
|
newProfile.save()
|
||||||
|
self.profiles.append(newProfile)
|
||||||
|
|
||||||
|
def setupUsefulProfiles(self):
|
||||||
|
superUser = models.Profile.objects.create(username="superuser", first_name="Super", last_name="User", initials="SU",
|
||||||
|
email="superuser@example.com", is_superuser=True, is_active=True, is_staff=True)
|
||||||
|
superUser.set_password('superuser')
|
||||||
|
superUser.save()
|
||||||
|
|
||||||
|
financeUser = models.Profile.objects.create(username="finance", first_name="Finance", last_name="User", initials="FU",
|
||||||
|
email="financeuser@example.com", is_active=True)
|
||||||
|
financeUser.groups.add(self.finance_group)
|
||||||
|
financeUser.groups.add(self.keyholder_group)
|
||||||
|
financeUser.set_password('finance')
|
||||||
|
financeUser.save()
|
||||||
|
|
||||||
|
keyholderUser = models.Profile.objects.create(username="keyholder", first_name="Keyholder", last_name="User", initials="KU",
|
||||||
|
email="keyholderuser@example.com", is_active=True)
|
||||||
|
keyholderUser.groups.add(self.keyholder_group)
|
||||||
|
keyholderUser.set_password('keyholder')
|
||||||
|
keyholderUser.save()
|
||||||
|
|
||||||
|
basicUser = models.Profile.objects.create(username="basic", first_name="Basic", last_name="User", initials="BU",
|
||||||
|
email="basicuser@example.com", is_active=True)
|
||||||
|
basicUser.set_password('basic')
|
||||||
|
basicUser.save()
|
||||||
|
|
||||||
|
def setupEvents(self):
|
||||||
|
names = ["Outdoor Concert","Hall Open Mic Night","Festival","Weekend Event","Magic Show","Society Ball","Evening Show","Talent Show","Acoustic Evening","Hire of Things","SU Event","End of Term Show","Theatre Show","Outdoor Fun Day","Summer Carnival","Open Days","Magic Show","Awards Ceremony","Debating Event","Club Night","DJ Evening","Building Projection","Choir Concert"]
|
||||||
|
descriptions = ["A brief desciption of the event","This event is boring","Probably wont happen","Warning: this has lots of kit"]
|
||||||
|
notes = ["The client came into the office at some point","Who knows if this will happen", "Probably should check this event", "Maybe not happening", "Run away!"]
|
||||||
|
|
||||||
|
itemOptions = [{'name': 'Speakers', 'description': 'Some really really big speakers \n these are very loud', 'quantity': 2, 'cost': 200.00},
|
||||||
|
{'name': 'Projector', 'description': 'Some kind of video thinamejig, probably with unnecessary processing for free', 'quantity': 1, 'cost': 500.00},
|
||||||
|
{'name': 'Lighting Desk', 'description': 'Cannot provide guarentee that it will work', 'quantity': 1, 'cost': 200.52},
|
||||||
|
{'name': 'Moving lights', 'description': 'Flashy lights, with the copper', 'quantity': 8, 'cost': 50.00},
|
||||||
|
{'name': 'Microphones', 'description': 'Make loud noise \n you will want speakers with this', 'quantity': 5, 'cost': 0.50},
|
||||||
|
{'name': 'Sound Mixer Thing', 'description': 'Might be analogue, might be digital', 'quantity': 1, 'cost': 100.00},
|
||||||
|
{'name': 'Electricity', 'description': 'You need this', 'quantity': 1, 'cost': 200.00},
|
||||||
|
{'name': 'Crew', 'description': 'Costs nothing, because reasons', 'quantity': 1, 'cost': 0.00},
|
||||||
|
{'name': 'Loyalty Discount', 'description': 'Have some negative moneys', 'quantity': 1, 'cost': -50.00}]
|
||||||
|
|
||||||
|
dayDelta = -120 # start adding events from 4 months ago
|
||||||
|
|
||||||
|
for i in range(150): # Let's add 100 events
|
||||||
|
with reversion.create_revision():
|
||||||
|
reversion.set_user(random.choice(self.profiles))
|
||||||
|
|
||||||
|
name = names[i%len(names)]
|
||||||
|
|
||||||
|
startDate = datetime.date.today() + datetime.timedelta(days=dayDelta)
|
||||||
|
dayDelta = dayDelta + random.randint(0,3)
|
||||||
|
|
||||||
|
newEvent = models.Event.objects.create(name=name, start_date=startDate)
|
||||||
|
|
||||||
|
if random.randint(0,2) > 1: # 1 in 3 have a start time
|
||||||
|
newEvent.start_time = datetime.time(random.randint(15,20))
|
||||||
|
if random.randint(0,2) > 1: # of those, 1 in 3 have an end time on the same day
|
||||||
|
newEvent.end_time = datetime.time(random.randint(21,23))
|
||||||
|
elif random.randint(0,1)>0: # half of the others finish early the next day
|
||||||
|
newEvent.end_date = newEvent.start_date + datetime.timedelta(days=1)
|
||||||
|
newEvent.end_time = datetime.time(random.randint(0,5))
|
||||||
|
elif random.randint(0,2)>1: # 1 in 3 of the others finish a few days ahead
|
||||||
|
newEvent.end_date = newEvent.start_date + datetime.timedelta(days=random.randint(1,4))
|
||||||
|
|
||||||
|
|
||||||
|
if random.randint(0,6) > 0: # 5 in 6 have MIC
|
||||||
|
newEvent.mic = random.choice(self.profiles)
|
||||||
|
|
||||||
|
if random.randint(0,6) > 0: # 5 in 6 have organisation
|
||||||
|
newEvent.organisation = random.choice(self.organisations)
|
||||||
|
|
||||||
|
if random.randint(0,6) > 0: # 5 in 6 have person
|
||||||
|
newEvent.person = random.choice(self.people)
|
||||||
|
|
||||||
|
if random.randint(0,6) > 0: # 5 in 6 have venue
|
||||||
|
newEvent.venue = random.choice(self.venues)
|
||||||
|
|
||||||
|
# Could have any status, equally weighted
|
||||||
|
newEvent.status = random.choice([models.Event.BOOKED,models.Event.CONFIRMED,models.Event.PROVISIONAL, models.Event.CANCELLED])
|
||||||
|
|
||||||
|
newEvent.dry_hire = (random.randint(0,7)==0) # 1 in 7 are dry hire
|
||||||
|
|
||||||
|
if random.randint(0,1) > 0: # 1 in 2 have description
|
||||||
|
newEvent.description = random.choice(descriptions)
|
||||||
|
|
||||||
|
if random.randint(0,1) > 0: # 1 in 2 have notes
|
||||||
|
newEvent.notes = random.choice(notes)
|
||||||
|
|
||||||
|
newEvent.save()
|
||||||
|
|
||||||
|
# Now add some items
|
||||||
|
for j in range(random.randint(1,5)):
|
||||||
|
itemData = itemOptions[random.randint(0,len(itemOptions)-1)]
|
||||||
|
newItem = models.EventItem.objects.create(event=newEvent, order=j, **itemData)
|
||||||
|
newItem.save()
|
||||||
|
|
||||||
|
while newEvent.sum_total < 0:
|
||||||
|
itemData = itemOptions[random.randint(0,len(itemOptions)-1)]
|
||||||
|
newItem = models.EventItem.objects.create(event=newEvent, order=j, **itemData)
|
||||||
|
newItem.save()
|
||||||
|
|
||||||
|
with reversion.create_revision():
|
||||||
|
reversion.set_user(random.choice(self.profiles))
|
||||||
|
if newEvent.start_date < datetime.date.today(): # think about adding an invoice
|
||||||
|
if random.randint(0,2) > 0: # 2 in 3 have had paperwork sent to treasury
|
||||||
|
newInvoice = models.Invoice.objects.create(event=newEvent)
|
||||||
|
if newEvent.status is models.Event.CANCELLED: # void cancelled events
|
||||||
|
newInvoice.void = True
|
||||||
|
elif random.randint(0,2)>1: # 1 in 3 have been paid
|
||||||
|
models.Payment.objects.create(invoice=newInvoice, amount=newInvoice.balance, date=datetime.date.today())
|
||||||
155
RIGS/models.py
155
RIGS/models.py
@@ -1,33 +1,32 @@
|
|||||||
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import datetime, pytz
|
import pytz
|
||||||
|
|
||||||
from django.db import models, connection
|
|
||||||
from django.contrib.auth.models import AbstractUser
|
|
||||||
from django.conf import settings
|
|
||||||
from django.utils.functional import cached_property
|
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
|
||||||
import reversion
|
|
||||||
import string
|
|
||||||
import random
|
import random
|
||||||
|
import string
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from django.core.urlresolvers import reverse_lazy
|
|
||||||
from django.core.exceptions import ValidationError
|
|
||||||
|
|
||||||
import versioning
|
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
import reversion
|
||||||
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import AbstractUser
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
from django.core.urlresolvers import reverse_lazy
|
||||||
|
from django.db import models
|
||||||
|
from django.utils.encoding import python_2_unicode_compatible
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Profile(AbstractUser):
|
class Profile(AbstractUser):
|
||||||
initials = models.CharField(max_length=5, unique=True, null=True, blank=False)
|
initials = models.CharField(max_length=5, unique=True, null=True, blank=False)
|
||||||
phone = models.CharField(max_length=13, null=True, blank=True)
|
phone = models.CharField(max_length=13, null=True, blank=True)
|
||||||
api_key = models.CharField(max_length=40,blank=True,editable=False, null=True)
|
api_key = models.CharField(max_length=40, blank=True, editable=False, null=True)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def make_api_key(cls):
|
def make_api_key(cls):
|
||||||
size=20
|
size = 20
|
||||||
chars=string.ascii_letters + string.digits
|
chars = string.ascii_letters + string.digits
|
||||||
new_api_key = ''.join(random.choice(chars) for x in range(size))
|
new_api_key = ''.join(random.choice(chars) for x in range(size))
|
||||||
return new_api_key;
|
return new_api_key;
|
||||||
|
|
||||||
@@ -57,6 +56,7 @@ class Profile(AbstractUser):
|
|||||||
('view_profile', 'Can view Profile'),
|
('view_profile', 'Can view Profile'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class RevisionMixin(object):
|
class RevisionMixin(object):
|
||||||
@property
|
@property
|
||||||
def last_edited_at(self):
|
def last_edited_at(self):
|
||||||
@@ -81,12 +81,12 @@ class RevisionMixin(object):
|
|||||||
versions = reversion.get_for_object(self)
|
versions = reversion.get_for_object(self)
|
||||||
if versions:
|
if versions:
|
||||||
version = reversion.get_for_object(self)[0]
|
version = reversion.get_for_object(self)[0]
|
||||||
return "V{0} | R{1}".format(version.pk,version.revision.pk)
|
return "V{0} | R{1}".format(version.pk, version.revision.pk)
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@reversion.register
|
@reversion.register
|
||||||
@versioning.register
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Person(models.Model, RevisionMixin):
|
class Person(models.Model, RevisionMixin):
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
@@ -98,9 +98,9 @@ class Person(models.Model, RevisionMixin):
|
|||||||
notes = models.TextField(blank=True, null=True)
|
notes = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
string = "Person | {}".format(self.name)
|
string = self.name
|
||||||
if self.notes is not None:
|
if self.notes is not None:
|
||||||
if len(self.notes) > 0:
|
if len(self.notes) > 0:
|
||||||
string += "*"
|
string += "*"
|
||||||
return string
|
return string
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ class Person(models.Model, RevisionMixin):
|
|||||||
if e.organisation:
|
if e.organisation:
|
||||||
o.append(e.organisation)
|
o.append(e.organisation)
|
||||||
|
|
||||||
#Count up occurances and put them in descending order
|
# Count up occurances and put them in descending order
|
||||||
c = Counter(o)
|
c = Counter(o)
|
||||||
stats = c.most_common()
|
stats = c.most_common()
|
||||||
return stats
|
return stats
|
||||||
@@ -130,7 +130,6 @@ class Person(models.Model, RevisionMixin):
|
|||||||
|
|
||||||
|
|
||||||
@reversion.register
|
@reversion.register
|
||||||
@versioning.register
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Organisation(models.Model, RevisionMixin):
|
class Organisation(models.Model, RevisionMixin):
|
||||||
name = models.CharField(max_length=50)
|
name = models.CharField(max_length=50)
|
||||||
@@ -143,9 +142,9 @@ class Organisation(models.Model, RevisionMixin):
|
|||||||
union_account = models.BooleanField(default=False)
|
union_account = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
string = "Organisation | {}".format(self.name)
|
string = self.name
|
||||||
if self.notes is not None:
|
if self.notes is not None:
|
||||||
if len(self.notes) > 0:
|
if len(self.notes) > 0:
|
||||||
string += "*"
|
string += "*"
|
||||||
return string
|
return string
|
||||||
|
|
||||||
@@ -155,8 +154,8 @@ class Organisation(models.Model, RevisionMixin):
|
|||||||
for e in Event.objects.filter(organisation=self).select_related('person'):
|
for e in Event.objects.filter(organisation=self).select_related('person'):
|
||||||
if e.person:
|
if e.person:
|
||||||
p.append(e.person)
|
p.append(e.person)
|
||||||
|
|
||||||
#Count up occurances and put them in descending order
|
# Count up occurances and put them in descending order
|
||||||
c = Counter(p)
|
c = Counter(p)
|
||||||
stats = c.most_common()
|
stats = c.most_common()
|
||||||
return stats
|
return stats
|
||||||
@@ -210,7 +209,6 @@ class VatRate(models.Model, RevisionMixin):
|
|||||||
|
|
||||||
|
|
||||||
@reversion.register
|
@reversion.register
|
||||||
@versioning.register
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Venue(models.Model, RevisionMixin):
|
class Venue(models.Model, RevisionMixin):
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
@@ -222,7 +220,7 @@ class Venue(models.Model, RevisionMixin):
|
|||||||
address = models.TextField(blank=True, null=True)
|
address = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
string = "Venue | {}".format(self.name)
|
string = self.name
|
||||||
if self.notes and len(self.notes) > 0:
|
if self.notes and len(self.notes) > 0:
|
||||||
string += "*"
|
string += "*"
|
||||||
return string
|
return string
|
||||||
@@ -243,12 +241,18 @@ class Venue(models.Model, RevisionMixin):
|
|||||||
class EventManager(models.Manager):
|
class EventManager(models.Manager):
|
||||||
def current_events(self):
|
def current_events(self):
|
||||||
events = self.filter(
|
events = self.filter(
|
||||||
(models.Q(start_date__gte=datetime.date.today(), end_date__isnull=True, dry_hire=False) & ~models.Q(status=Event.CANCELLED)) | # Starts after with no end
|
(models.Q(start_date__gte=datetime.date.today(), end_date__isnull=True, dry_hire=False) & ~models.Q(
|
||||||
(models.Q(end_date__gte=datetime.date.today(), dry_hire=False) & ~models.Q(status=Event.CANCELLED)) | # Ends after
|
status=Event.CANCELLED)) | # Starts after with no end
|
||||||
(models.Q(dry_hire=True, start_date__gte=datetime.date.today()) & ~models.Q(status=Event.CANCELLED)) | # Active dry hire
|
(models.Q(end_date__gte=datetime.date.today(), dry_hire=False) & ~models.Q(
|
||||||
(models.Q(dry_hire=True, checked_in_by__isnull=True) & (models.Q(status=Event.BOOKED) | models.Q(status=Event.CONFIRMED))) | # Active dry hire GT
|
status=Event.CANCELLED)) | # Ends after
|
||||||
|
(models.Q(dry_hire=True, start_date__gte=datetime.date.today()) & ~models.Q(
|
||||||
|
status=Event.CANCELLED)) | # Active dry hire
|
||||||
|
(models.Q(dry_hire=True, checked_in_by__isnull=True) & (
|
||||||
|
models.Q(status=Event.BOOKED) | models.Q(status=Event.CONFIRMED))) | # Active dry hire GT
|
||||||
models.Q(status=Event.CANCELLED, start_date__gte=datetime.date.today()) # Canceled but not started
|
models.Q(status=Event.CANCELLED, start_date__gte=datetime.date.today()) # Canceled but not started
|
||||||
).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person', 'organisation', 'venue', 'mic')
|
).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person',
|
||||||
|
'organisation',
|
||||||
|
'venue', 'mic')
|
||||||
return events
|
return events
|
||||||
|
|
||||||
def events_in_bounds(self, start, end):
|
def events_in_bounds(self, start, end):
|
||||||
@@ -256,15 +260,17 @@ class EventManager(models.Manager):
|
|||||||
(models.Q(start_date__gte=start.date(), start_date__lte=end.date())) | # Start date in bounds
|
(models.Q(start_date__gte=start.date(), start_date__lte=end.date())) | # Start date in bounds
|
||||||
(models.Q(end_date__gte=start.date(), end_date__lte=end.date())) | # End date in bounds
|
(models.Q(end_date__gte=start.date(), end_date__lte=end.date())) | # End date in bounds
|
||||||
(models.Q(access_at__gte=start, access_at__lte=end)) | # Access at in bounds
|
(models.Q(access_at__gte=start, access_at__lte=end)) | # Access at in bounds
|
||||||
(models.Q(meet_at__gte=start, meet_at__lte=end)) | # Meet at in bounds
|
(models.Q(meet_at__gte=start, meet_at__lte=end)) | # Meet at in bounds
|
||||||
|
|
||||||
(models.Q(start_date__lte=start, end_date__gte=end)) | # Start before, end after
|
(models.Q(start_date__lte=start, end_date__gte=end)) | # Start before, end after
|
||||||
(models.Q(access_at__lte=start, start_date__gte=end)) | # Access before, start after
|
(models.Q(access_at__lte=start, start_date__gte=end)) | # Access before, start after
|
||||||
(models.Q(access_at__lte=start, end_date__gte=end)) | # Access before, end after
|
(models.Q(access_at__lte=start, end_date__gte=end)) | # Access before, end after
|
||||||
(models.Q(meet_at__lte=start, start_date__gte=end)) | # Meet before, start after
|
(models.Q(meet_at__lte=start, start_date__gte=end)) | # Meet before, start after
|
||||||
(models.Q(meet_at__lte=start, end_date__gte=end)) # Meet before, end after
|
(models.Q(meet_at__lte=start, end_date__gte=end)) # Meet before, end after
|
||||||
|
|
||||||
).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person', 'organisation', 'venue', 'mic')
|
).order_by('start_date', 'end_date', 'start_time', 'end_time', 'meet_at').select_related('person',
|
||||||
|
'organisation',
|
||||||
|
'venue', 'mic')
|
||||||
return events
|
return events
|
||||||
|
|
||||||
def rig_count(self):
|
def rig_count(self):
|
||||||
@@ -283,7 +289,6 @@ class EventManager(models.Manager):
|
|||||||
|
|
||||||
|
|
||||||
@reversion.register(follow=['items'])
|
@reversion.register(follow=['items'])
|
||||||
@versioning.register
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class Event(models.Model, RevisionMixin):
|
class Event(models.Model, RevisionMixin):
|
||||||
# Done to make it much nicer on the database
|
# Done to make it much nicer on the database
|
||||||
@@ -307,7 +312,8 @@ class Event(models.Model, RevisionMixin):
|
|||||||
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
|
status = models.IntegerField(choices=EVENT_STATUS_CHOICES, default=PROVISIONAL)
|
||||||
dry_hire = models.BooleanField(default=False)
|
dry_hire = models.BooleanField(default=False)
|
||||||
is_rig = models.BooleanField(default=True)
|
is_rig = models.BooleanField(default=True)
|
||||||
based_on = models.ForeignKey('Event', on_delete=models.SET_NULL, related_name='future_events', blank=True, null=True)
|
based_on = models.ForeignKey('Event', on_delete=models.SET_NULL, related_name='future_events', blank=True,
|
||||||
|
null=True)
|
||||||
|
|
||||||
# Timing
|
# Timing
|
||||||
start_date = models.DateField()
|
start_date = models.DateField()
|
||||||
@@ -333,6 +339,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
"""
|
"""
|
||||||
EX Vat
|
EX Vat
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def sum_total(self):
|
def sum_total(self):
|
||||||
# Manual querying is required for efficiency whilst maintaining floating point arithmetic
|
# Manual querying is required for efficiency whilst maintaining floating point arithmetic
|
||||||
@@ -340,14 +347,15 @@ class Event(models.Model, RevisionMixin):
|
|||||||
# sql = "SELECT SUM(quantity * cost) AS sum_total FROM \"RIGS_eventitem\" WHERE event_id=%i" % self.id
|
# sql = "SELECT SUM(quantity * cost) AS sum_total FROM \"RIGS_eventitem\" WHERE event_id=%i" % self.id
|
||||||
# else:
|
# else:
|
||||||
# sql = "SELECT id, SUM(quantity * cost) AS sum_total FROM RIGS_eventitem WHERE event_id=%i" % self.id
|
# sql = "SELECT id, SUM(quantity * cost) AS sum_total FROM RIGS_eventitem WHERE event_id=%i" % self.id
|
||||||
#total = self.items.raw(sql)[0]
|
# total = self.items.raw(sql)[0]
|
||||||
#if total.sum_total:
|
# if total.sum_total:
|
||||||
# return total.sum_total
|
# return total.sum_total
|
||||||
#total = 0.0
|
# total = 0.0
|
||||||
#for item in self.items.filter(cost__gt=0).extra(select="SUM(cost * quantity) AS sum"):
|
# for item in self.items.filter(cost__gt=0).extra(select="SUM(cost * quantity) AS sum"):
|
||||||
# total += item.sum
|
# total += item.sum
|
||||||
total = EventItem.objects.filter(event=self).aggregate(
|
total = EventItem.objects.filter(event=self).aggregate(
|
||||||
sum_total=models.Sum(models.F('cost')*models.F('quantity'), output_field=models.DecimalField(max_digits=10, decimal_places=2))
|
sum_total=models.Sum(models.F('cost') * models.F('quantity'),
|
||||||
|
output_field=models.DecimalField(max_digits=10, decimal_places=2))
|
||||||
)['sum_total']
|
)['sum_total']
|
||||||
if total:
|
if total:
|
||||||
return total
|
return total
|
||||||
@@ -364,6 +372,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
"""
|
"""
|
||||||
Inc VAT
|
Inc VAT
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total(self):
|
def total(self):
|
||||||
return self.sum_total + self.vat
|
return self.sum_total + self.vat
|
||||||
@@ -388,7 +397,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
def earliest_time(self):
|
def earliest_time(self):
|
||||||
"""Finds the earliest time defined in the event - this function could return either a tzaware datetime, or a naiive date object"""
|
"""Finds the earliest time defined in the event - this function could return either a tzaware datetime, or a naiive date object"""
|
||||||
|
|
||||||
#Put all the datetimes in a list
|
# Put all the datetimes in a list
|
||||||
datetime_list = []
|
datetime_list = []
|
||||||
|
|
||||||
if self.access_at:
|
if self.access_at:
|
||||||
@@ -400,22 +409,22 @@ class Event(models.Model, RevisionMixin):
|
|||||||
# If there is no start time defined, pretend it's midnight
|
# If there is no start time defined, pretend it's midnight
|
||||||
startTimeFaked = False
|
startTimeFaked = False
|
||||||
if self.has_start_time:
|
if self.has_start_time:
|
||||||
startDateTime = datetime.datetime.combine(self.start_date,self.start_time)
|
startDateTime = datetime.datetime.combine(self.start_date, self.start_time)
|
||||||
else:
|
else:
|
||||||
startDateTime = datetime.datetime.combine(self.start_date,datetime.time(00,00))
|
startDateTime = datetime.datetime.combine(self.start_date, datetime.time(00, 00))
|
||||||
startTimeFaked = True
|
startTimeFaked = True
|
||||||
|
|
||||||
#timezoneIssues - apply the default timezone to the naiive datetime
|
# timezoneIssues - apply the default timezone to the naiive datetime
|
||||||
tz = pytz.timezone(settings.TIME_ZONE)
|
tz = pytz.timezone(settings.TIME_ZONE)
|
||||||
startDateTime = tz.localize(startDateTime)
|
startDateTime = tz.localize(startDateTime)
|
||||||
datetime_list.append(startDateTime) # then add it to the list
|
datetime_list.append(startDateTime) # then add it to the list
|
||||||
|
|
||||||
earliest = min(datetime_list).astimezone(tz) #find the earliest datetime in the list
|
earliest = min(datetime_list).astimezone(tz) # find the earliest datetime in the list
|
||||||
|
|
||||||
# if we faked it & it's the earliest, better own up
|
# if we faked it & it's the earliest, better own up
|
||||||
if startTimeFaked and earliest==startDateTime:
|
if startTimeFaked and earliest == startDateTime:
|
||||||
return self.start_date
|
return self.start_date
|
||||||
|
|
||||||
return earliest
|
return earliest
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -427,7 +436,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
endDate = self.start_date
|
endDate = self.start_date
|
||||||
|
|
||||||
if self.has_end_time:
|
if self.has_end_time:
|
||||||
endDateTime = datetime.datetime.combine(endDate,self.end_time)
|
endDateTime = datetime.datetime.combine(endDate, self.end_time)
|
||||||
tz = pytz.timezone(settings.TIME_ZONE)
|
tz = pytz.timezone(settings.TIME_ZONE)
|
||||||
endDateTime = tz.localize(endDateTime)
|
endDateTime = tz.localize(endDateTime)
|
||||||
|
|
||||||
@@ -436,24 +445,13 @@ class Event(models.Model, RevisionMixin):
|
|||||||
else:
|
else:
|
||||||
return endDate
|
return endDate
|
||||||
|
|
||||||
|
|
||||||
objects = EventManager()
|
objects = EventManager()
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse_lazy('event_detail', kwargs={'pk': self.pk})
|
return reverse_lazy('event_detail', kwargs={'pk': self.pk})
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
string = ""
|
return unicode(self.pk) + ": " + self.name
|
||||||
if self.is_rig and self.dry_hire:
|
|
||||||
string += "Dry Hire"
|
|
||||||
elif self.is_rig:
|
|
||||||
string += "Rig"
|
|
||||||
else:
|
|
||||||
string += "Non-rig"
|
|
||||||
|
|
||||||
string += " | {}".format(self.name)
|
|
||||||
|
|
||||||
return string
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.end_date and self.start_date > self.end_date:
|
if self.end_date and self.start_date > self.end_date:
|
||||||
@@ -462,7 +460,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
startEndSameDay = not self.end_date or self.end_date == self.start_date
|
||||||
hasStartAndEnd = self.has_start_time and self.has_end_time
|
hasStartAndEnd = self.has_start_time and self.has_end_time
|
||||||
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
if startEndSameDay and hasStartAndEnd and self.start_time > self.end_time:
|
||||||
raise ValidationError('Unless you\'ve invented time travel, the event can\'t finish before it has started.')
|
raise ValidationError('Unless you\'ve invented time travel, the event can\'t finish before it has started.')
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
def save(self, *args, **kwargs):
|
||||||
"""Call :meth:`full_clean` before saving."""
|
"""Call :meth:`full_clean` before saving."""
|
||||||
@@ -474,7 +472,7 @@ class Event(models.Model, RevisionMixin):
|
|||||||
('view_event', 'Can view Events'),
|
('view_event', 'Can view Events'),
|
||||||
)
|
)
|
||||||
|
|
||||||
@versioning.set_related
|
|
||||||
class EventItem(models.Model):
|
class EventItem(models.Model):
|
||||||
event = models.ForeignKey('Event', related_name='items', blank=True)
|
event = models.ForeignKey('Event', related_name='items', blank=True)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
@@ -519,15 +517,6 @@ class Invoice(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def payment_total(self):
|
def payment_total(self):
|
||||||
# Manual querying is required for efficiency whilst maintaining floating point arithmetic
|
|
||||||
#if connection.vendor == 'postgresql':
|
|
||||||
# sql = "SELECT SUM(amount) AS total FROM \"RIGS_payment\" WHERE invoice_id=%i" % self.id
|
|
||||||
#else:
|
|
||||||
# sql = "SELECT id, SUM(amount) AS total FROM RIGS_payment WHERE invoice_id=%i" % self.id
|
|
||||||
#total = self.payment_set.raw(sql)[0]
|
|
||||||
#if total.total:
|
|
||||||
# return total.total
|
|
||||||
#return 0.0
|
|
||||||
total = self.payment_set.aggregate(total=models.Sum('amount'))['total']
|
total = self.payment_set.aggregate(total=models.Sum('amount'))['total']
|
||||||
if total:
|
if total:
|
||||||
return total
|
return total
|
||||||
@@ -537,6 +526,10 @@ class Invoice(models.Model):
|
|||||||
def balance(self):
|
def balance(self):
|
||||||
return self.sum_total - self.payment_total
|
return self.sum_total - self.payment_total
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_closed(self):
|
||||||
|
return self.balance == 0 or self.void
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%i: %s (%.2f)" % (self.pk, self.event, self.balance)
|
return "%i: %s (%.2f)" % (self.pk, self.event, self.balance)
|
||||||
|
|
||||||
@@ -568,4 +561,4 @@ class Payment(models.Model):
|
|||||||
method = models.CharField(max_length=2, choices=METHODS, null=True, blank=True)
|
method = models.CharField(max_length=2, choices=METHODS, null=True, blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s: %d" % (self.get_method_display(), self.amount)
|
return "%s: %d" % (self.get_method_display(), self.amount)
|
||||||
|
|||||||
@@ -9,11 +9,13 @@ from django.shortcuts import get_object_or_404
|
|||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.template.loader import get_template
|
from django.template.loader import get_template
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from z3c.rml import rml2pdf
|
from z3c.rml import rml2pdf
|
||||||
from PyPDF2 import PdfFileMerger, PdfFileReader
|
from PyPDF2 import PdfFileMerger, PdfFileReader
|
||||||
|
import simplejson
|
||||||
|
|
||||||
from RIGS import models, forms
|
from RIGS import models, forms
|
||||||
import datetime
|
import datetime
|
||||||
@@ -47,6 +49,29 @@ class EventDetail(generic.DetailView):
|
|||||||
model = models.Event
|
model = models.Event
|
||||||
|
|
||||||
|
|
||||||
|
class EventOembed(generic.View):
|
||||||
|
model = models.Event
|
||||||
|
|
||||||
|
def get(self, request, pk=None):
|
||||||
|
|
||||||
|
embed_url = reverse('event_embed', args=[pk])
|
||||||
|
full_url = "{0}://{1}{2}".format(request.scheme, request.META['HTTP_HOST'], embed_url)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
'html': '<iframe src="{0}" frameborder="0" width="100%" height="250"></iframe>'.format(full_url),
|
||||||
|
'version': '1.0',
|
||||||
|
'type': 'rich',
|
||||||
|
'height': '250'
|
||||||
|
}
|
||||||
|
|
||||||
|
json = simplejson.JSONEncoderForHTML().encode(data)
|
||||||
|
return HttpResponse(json, content_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
|
class EventEmbed(EventDetail):
|
||||||
|
template_name = 'RIGS/event_embed.html'
|
||||||
|
|
||||||
|
|
||||||
class EventCreate(generic.CreateView):
|
class EventCreate(generic.CreateView):
|
||||||
model = models.Event
|
model = models.Event
|
||||||
form_class = forms.EventForm
|
form_class = forms.EventForm
|
||||||
@@ -59,7 +84,7 @@ class EventCreate(generic.CreateView):
|
|||||||
form = context['form']
|
form = context['form']
|
||||||
if re.search('"-\d+"', form['items_json'].value()):
|
if re.search('"-\d+"', form['items_json'].value()):
|
||||||
messages.info(self.request, "Your item changes have been saved. Please fix the errors and save the event.")
|
messages.info(self.request, "Your item changes have been saved. Please fix the errors and save the event.")
|
||||||
|
|
||||||
|
|
||||||
# Get some other objects to include in the form. Used when there are errors but also nice and quick.
|
# Get some other objects to include in the form. Used when there are errors but also nice and quick.
|
||||||
for field, model in form.related_models.iteritems():
|
for field, model in form.related_models.iteritems():
|
||||||
@@ -97,11 +122,12 @@ class EventDuplicate(EventUpdate):
|
|||||||
old = super(EventDuplicate, self).get_object(queryset) # Get the object (the event you're duplicating)
|
old = super(EventDuplicate, self).get_object(queryset) # Get the object (the event you're duplicating)
|
||||||
new = copy.copy(old) # Make a copy of the object in memory
|
new = copy.copy(old) # Make a copy of the object in memory
|
||||||
new.based_on = old # Make the new event based on the old event
|
new.based_on = old # Make the new event based on the old event
|
||||||
|
new.purchase_order = None
|
||||||
|
|
||||||
if self.request.method in ('POST', 'PUT'): # This only happens on save (otherwise items won't display in editor)
|
if self.request.method in ('POST', 'PUT'): # This only happens on save (otherwise items won't display in editor)
|
||||||
new.pk = None # This means a new event will be created on save, and all items will be re-created
|
new.pk = None # This means a new event will be created on save, and all items will be re-created
|
||||||
|
else:
|
||||||
messages.info(self.request, 'Event data duplicated but not yet saved. Click save to complete operation.')
|
messages.info(self.request, 'Event data duplicated but not yet saved. Click save to complete operation.')
|
||||||
|
|
||||||
return new
|
return new
|
||||||
|
|
||||||
@@ -192,4 +218,4 @@ class EventArchive(generic.ArchiveIndexView):
|
|||||||
if len(qs) == 0:
|
if len(qs) == 0:
|
||||||
messages.add_message(self.request, messages.WARNING, "No events have been found matching those criteria.")
|
messages.add_message(self.request, messages.WARNING, "No events have been found matching those criteria.")
|
||||||
|
|
||||||
return qs
|
return qs
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -147,3 +147,45 @@ ins {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html.embedded{
|
||||||
|
min-height:100%;
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
body{
|
||||||
|
padding:0;
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
width:100%;
|
||||||
|
background:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.embed_container{
|
||||||
|
border:5px solid #e9e9e9;
|
||||||
|
padding:12px 0px;
|
||||||
|
min-height:100%;
|
||||||
|
width:100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source{
|
||||||
|
background: url('/static/imgs/pyrigs-avatar.png') no-repeat;
|
||||||
|
background-size: 16px 16px;
|
||||||
|
padding-left: 20px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3{
|
||||||
|
margin-top:10px;
|
||||||
|
margin-bottom:5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
p{
|
||||||
|
margin-bottom:2px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-mic-photo{
|
||||||
|
max-width: 3em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,17 +25,17 @@
|
|||||||
class="hidden-xs">Duplicate</span></a>
|
class="hidden-xs">Duplicate</span></a>
|
||||||
{% if event.is_rig %}
|
{% if event.is_rig %}
|
||||||
{% if perms.RIGS.add_invoice %}
|
{% if perms.RIGS.add_invoice %}
|
||||||
<a href="{% url 'invoice_event' event.pk %}" class="btn btn-default" title="Invoice Rig"><span
|
<a id="invoiceDropdownLabel" href="{% url 'invoice_event' event.pk %}" class="btn
|
||||||
class="glyphicon glyphicon-gbp"></span> <span
|
{% if event.invoice and event.invoice.is_closed %}
|
||||||
class="hidden-xs">Invoice</span></a>
|
btn-success
|
||||||
{% endif %}
|
{% elif event.invoice %}
|
||||||
{% url 'form_list' event_pk=event.pk as forms_url %}
|
btn-warning
|
||||||
{% if forms_url %}
|
{% else %}
|
||||||
{% if perms.rigForms.view_form %}
|
btn-danger
|
||||||
<a href="{% url 'form_list' event.pk %}" class="btn btn-default" title="Rig Forms"><span
|
|
||||||
class="glyphicon glyphicon-check"></span> <span
|
|
||||||
class="hidden-xs">Forms</span></a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
" title="Invoice Rig"><span
|
||||||
|
class="glyphicon glyphicon-gbp"></span>
|
||||||
|
<span class="hidden-xs">Invoice</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if object.person %}
|
{% if object.person %}
|
||||||
<a href="{% url 'person_detail' object.person.pk %}" class="modal-href">
|
<a href="{% url 'person_detail' object.person.pk %}" class="modal-href">
|
||||||
{{ object.person.name }}
|
{{ object.person }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if object.organisation %}
|
{% if object.organisation %}
|
||||||
<a href="{% url 'organisation_detail' object.organisation.pk %}" class="modal-href">
|
<a href="{% url 'organisation_detail' object.organisation.pk %}" class="modal-href">
|
||||||
{{ object.organisation.name }}
|
{{ object.organisation }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if object.venue %}
|
{% if object.venue %}
|
||||||
<a href="{% url 'venue_detail' object.venue.pk %}" class="modal-href">
|
<a href="{% url 'venue_detail' object.venue.pk %}" class="modal-href">
|
||||||
{{ object.venue.name }}
|
{{ object.venue }}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</dd>
|
</dd>
|
||||||
@@ -198,17 +198,17 @@
|
|||||||
class="hidden-xs">Duplicate</span></a>
|
class="hidden-xs">Duplicate</span></a>
|
||||||
{% if event.is_rig %}
|
{% if event.is_rig %}
|
||||||
{% if perms.RIGS.add_invoice %}
|
{% if perms.RIGS.add_invoice %}
|
||||||
<a href="{% url 'invoice_event' event.pk %}" class="btn btn-default" title="Invoice Rig"><span
|
<a id="invoiceDropdownLabel" href="{% url 'invoice_event' event.pk %}" class="btn
|
||||||
class="glyphicon glyphicon-gbp"></span> <span
|
{% if event.invoice and event.invoice.is_closed %}
|
||||||
class="hidden-xs">Invoice</span></a>
|
btn-success
|
||||||
{% endif %}
|
{% elif event.invoice %}
|
||||||
{% url 'form_list' event_pk=event.pk as forms_url %}
|
btn-warning
|
||||||
{% if forms_url %}
|
{% else %}
|
||||||
{% if perms.rigForms.view_form %}
|
btn-danger
|
||||||
<a href="{% url 'form_list' event.pk %}" class="btn btn-default" title="Rig Forms"><span
|
|
||||||
class="glyphicon glyphicon-check"></span> <span
|
|
||||||
class="hidden-xs">Forms</span></a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
" title="Invoice Rig"><span
|
||||||
|
class="glyphicon glyphicon-gbp"></span>
|
||||||
|
<span class="hidden-xs">Invoice</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@@ -243,17 +243,17 @@
|
|||||||
class="hidden-xs">Duplicate</span></a>
|
class="hidden-xs">Duplicate</span></a>
|
||||||
{% if event.is_rig %}
|
{% if event.is_rig %}
|
||||||
{% if perms.RIGS.add_invoice %}
|
{% if perms.RIGS.add_invoice %}
|
||||||
<a href="{% url 'invoice_event' event.pk %}" class="btn btn-default" title="Invoice Rig"><span
|
<a id="invoiceDropdownLabel" href="{% url 'invoice_event' event.pk %}" class="btn
|
||||||
class="glyphicon glyphicon-gbp"></span> <span
|
{% if event.invoice and event.invoice.is_closed %}
|
||||||
class="hidden-xs">Invoice</span></a>
|
btn-success
|
||||||
{% endif %}
|
{% elif event.invoice %}
|
||||||
{% url 'form_list' event_pk=event.pk as forms_url %}
|
btn-warning
|
||||||
{% if forms_url %}
|
{% else %}
|
||||||
{% if perms.rigForms.view_form %}
|
btn-danger
|
||||||
<a href="{% url 'form_list' event.pk %}" class="btn btn-default" title="Rig Forms"><span
|
|
||||||
class="glyphicon glyphicon-check"></span> <span
|
|
||||||
class="hidden-xs">Forms</span></a>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
" title="Invoice Rig"><span
|
||||||
|
class="glyphicon glyphicon-gbp"></span>
|
||||||
|
<span class="hidden-xs">Invoice</span></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
106
RIGS/templates/RIGS/event_embed.html
Normal file
106
RIGS/templates/RIGS/event_embed.html
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
{% extends 'base_embed.html' %}
|
||||||
|
{% load static from staticfiles %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<a href="/">
|
||||||
|
<span class="source"> R<small>ig</small> I<small>nformation</small> G<small>athering</small> S<small>ystem</small></span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<span class="pull-right">
|
||||||
|
{% if object.mic %}
|
||||||
|
<div class="text-center">
|
||||||
|
<img src="{{ object.mic.profile_picture }}" class="event-mic-photo img-rounded"/>
|
||||||
|
</div>
|
||||||
|
{% elif object.is_rig %}
|
||||||
|
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
||||||
|
{% endif %}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<h3>
|
||||||
|
<a {% if perms.RIGS.view_event %}href="{% url 'event_detail' object.pk %}"{% endif %}>
|
||||||
|
{% if object.is_rig %}N{{ object.pk|stringformat:"05d" }}{% else %}{{ object.pk }}{% endif %}
|
||||||
|
| {{ object.name }} </a>
|
||||||
|
{% if object.venue %}
|
||||||
|
<small>at {{ object.venue }}</small>
|
||||||
|
{% endif %}
|
||||||
|
<br/><small>
|
||||||
|
{{ object.start_date|date:"D d/m/Y" }}
|
||||||
|
{% if object.has_start_time %}
|
||||||
|
{{ object.start_time|date:"H:i" }}
|
||||||
|
{% endif %}
|
||||||
|
{% if object.end_date or object.has_end_time %}
|
||||||
|
–
|
||||||
|
{% endif %}
|
||||||
|
{% if object.end_date and object.end_date != object.start_date %}
|
||||||
|
{{ object.end_date|date:"D d/m/Y" }}
|
||||||
|
{% endif %}
|
||||||
|
{% if object.has_end_time %}
|
||||||
|
{{ object.end_time|date:"H:i" }}
|
||||||
|
{% endif %}
|
||||||
|
</small>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-6">
|
||||||
|
<p>
|
||||||
|
<strong>Status:</strong>
|
||||||
|
{{ object.get_status_display }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{% if object.is_rig %}
|
||||||
|
<strong>Client:</strong> {{ object.person.name }}
|
||||||
|
{% if object.organisation %}
|
||||||
|
for {{ object.organisation.name }}
|
||||||
|
{% endif %}
|
||||||
|
{% if object.dry_hire %}(Dry Hire){% endif %}
|
||||||
|
{% else %}
|
||||||
|
<strong>Non-Rig</strong>
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>MIC:</strong>
|
||||||
|
{% if object.mic %}
|
||||||
|
{{object.mic.name}}
|
||||||
|
{% else %}
|
||||||
|
None
|
||||||
|
{% endif %}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-xs-6">
|
||||||
|
|
||||||
|
{% if object.meet_at %}
|
||||||
|
<p>
|
||||||
|
<strong>Crew meet:</strong>
|
||||||
|
{{ object.meet_at|date:"H:i" }} {{ object.meet_at|date:"(Y-m-d)" }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% if object.access_at %}
|
||||||
|
<p>
|
||||||
|
<strong>Access at:</strong>
|
||||||
|
{{ object.access_at|date:"H:i" }} {{ object.access_at|date:"(Y-m-d)" }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
<p>
|
||||||
|
<strong>Last updated:</strong>
|
||||||
|
{{ object.last_edited_at }} by "{{ object.last_edited_by.initials }}"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% if object.description %}
|
||||||
|
<p>
|
||||||
|
<strong>Description: </strong>
|
||||||
|
{{ object.description|linebreaksbr }}
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
} else {
|
} else {
|
||||||
$('.form-is_rig').slideDown();
|
$('.form-is_rig').slideDown();
|
||||||
}
|
}
|
||||||
$('.form-hws').css('overflow', 'visible');
|
$('.form-hws, .form-hws .form-is_rig').css('overflow', 'visible');
|
||||||
} else {
|
} else {
|
||||||
$('#{{form.is_rig.auto_id}}').prop('checked', false);
|
$('#{{form.is_rig.auto_id}}').prop('checked', false);
|
||||||
$('.form-is_rig').slideUp();
|
$('.form-is_rig').slideUp();
|
||||||
@@ -445,4 +445,4 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% include 'RIGS/item_modal.html' %}
|
{% include 'RIGS/item_modal.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -1,68 +1,91 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load paginator from filters %}
|
{% load paginator from filters %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
{% block title %}Events for Invoice{% endblock %}
|
{% block title %}Events for Invoice{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
<script src="{% static "js/tooltip.js" %}"></script>
|
||||||
|
<script>
|
||||||
|
$(function () {
|
||||||
|
$('[data-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h2>Events for Invoice</h2>
|
<h2>Events for Invoice ({{count}} Events, £ {{ total|floatformat:2 }})</h2>
|
||||||
|
<p>These events have happened, but paperwork has not yet been sent to treasury</p>
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
||||||
{% paginator %}
|
{% paginator %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table table-responsive table-hover">
|
<div class="table-responsive col-sm-12">
|
||||||
<thead>
|
<table class="table table-hover">
|
||||||
<tr>
|
<thead>
|
||||||
<th class="hiddenx-xs">#</th>
|
<tr>
|
||||||
<th>Date</th>
|
<th>Event #</th>
|
||||||
<th>Event</th>
|
<th>Start Date</th>
|
||||||
<th>Client</th>
|
<th>Event Name</th>
|
||||||
<th>Cost</th>
|
<th>Client</th>
|
||||||
<th class="hidden-xs">MIC</th>
|
<th>Cost</th>
|
||||||
<th></th>
|
<th>MIC</th>
|
||||||
</tr>
|
<th></th>
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for object in object_list %}
|
|
||||||
<tr class="
|
|
||||||
{% if object.cancelled %}
|
|
||||||
active text-muted
|
|
||||||
{% elif not object.is_rig %}
|
|
||||||
info
|
|
||||||
{% elif object.confirmed and object.mic %}
|
|
||||||
{# interpreated as (booked and mic) #}
|
|
||||||
success
|
|
||||||
{% elif object.mic %}
|
|
||||||
warning
|
|
||||||
{% else %}
|
|
||||||
danger
|
|
||||||
{% endif %}
|
|
||||||
">
|
|
||||||
<td class="hidden-xs"><a href="{% url 'event_detail' object.pk %}" target="_blank">N{{ object.pk|stringformat:"05d" }}</a></td>
|
|
||||||
<td>{{ object.end_date }}</td>
|
|
||||||
<td>{{ object.name }}</td>
|
|
||||||
<td>
|
|
||||||
{% if object.organisation %}
|
|
||||||
{{ object.organisation.name }}
|
|
||||||
{% else %}
|
|
||||||
{{ object.person.name }}
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td>{{ object.sum_total|floatformat:2 }}</td>
|
|
||||||
<td class="text-center">
|
|
||||||
{{ object.mic.initials }}<br/>
|
|
||||||
<img src="{{ object.mic.profile_picture }}" class="event-mic-photo"/>
|
|
||||||
</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<a href="{% url 'invoice_event' object.pk %}" target="_blank" class="btn btn-default">
|
|
||||||
<span class="glyphicon glyphicon-gbp"></span>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{% for object in object_list %}
|
||||||
|
<tr class="
|
||||||
|
{% if object.cancelled %}
|
||||||
|
active text-muted
|
||||||
|
{% elif not object.is_rig %}
|
||||||
|
info
|
||||||
|
{% elif object.confirmed and object.mic %}
|
||||||
|
{# interpreated as (booked and mic) #}
|
||||||
|
success
|
||||||
|
{% elif object.mic %}
|
||||||
|
warning
|
||||||
|
{% else %}
|
||||||
|
danger
|
||||||
|
{% endif %}
|
||||||
|
">
|
||||||
|
<td><a href="{% url 'event_detail' object.pk %}">N{{ object.pk|stringformat:"05d" }}</a><br>
|
||||||
|
<span class="text-muted">{{ object.get_status_display }}</span></td>
|
||||||
|
<td>{{ object.start_date }}</td>
|
||||||
|
<td>{{ object.name }}</td>
|
||||||
|
<td>
|
||||||
|
{% if object.organisation %}
|
||||||
|
{{ object.organisation.name }}
|
||||||
|
<br>
|
||||||
|
<span class="text-muted">{{ object.organisation.union_account|yesno:'Internal,External' }}</span>
|
||||||
|
{% else %}
|
||||||
|
{{ object.person.name }}
|
||||||
|
<br>
|
||||||
|
<span class="text-muted">External</span>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>{{ object.sum_total|floatformat:2 }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
{% if object.mic %}
|
||||||
|
{{ object.mic.initials }}<br>
|
||||||
|
<img src="{{ object.mic.profile_picture }}" class="event-mic-photo"/>
|
||||||
|
{% else %}
|
||||||
|
<span class="glyphicon glyphicon-exclamation-sign"></span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="{% url 'invoice_event' object.pk %}" class="btn btn-default" data-toggle="tooltip" title="'Invoice' this event - click this when paperwork has been sent to treasury">
|
||||||
|
<span class="glyphicon glyphicon-gbp"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
||||||
{% paginator %}
|
{% paginator %}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<td class="hidden-xs">#</td>
|
<td>#</td>
|
||||||
<td>Event Date</td>
|
<td>Event Date</td>
|
||||||
<td>Event Details</td>
|
<td>Event Details</td>
|
||||||
<td>Event Timings</td>
|
<td>Event Timings</td>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
danger
|
danger
|
||||||
{% endif %}
|
{% endif %}
|
||||||
">
|
">
|
||||||
<td class="hidden-xs">{{ event.pk }}</td>
|
<td>{{ event.pk }}</td>
|
||||||
<td>
|
<td>
|
||||||
<div><strong>{{ event.start_date|date:"D d/m/Y" }}</strong></div>
|
<div><strong>{{ event.start_date|date:"D d/m/Y" }}</strong></div>
|
||||||
{% if event.end_date and event.end_date != event.start_date %}
|
{% if event.end_date and event.end_date != event.start_date %}
|
||||||
|
|||||||
@@ -23,9 +23,11 @@
|
|||||||
|
|
||||||
<div class="list-group-item default"></div>
|
<div class="list-group-item default"></div>
|
||||||
|
|
||||||
<a class="list-group-item" href="//members.nottinghamtec.co.uk/forum" target="_blank"><span class="glyphicon glyphicon-link"></span> TEC Forum</a>
|
<a class="list-group-item" href="https://forum.nottinghamtec.co.uk" target="_blank"><span class="glyphicon glyphicon-link"></span> TEC Forum</a>
|
||||||
<a class="list-group-item" href="//members.nottinghamtec.co.uk/wiki" target="_blank"><span class="glyphicon glyphicon-link"></span> TEC Wiki</a>
|
<a class="list-group-item" href="//members.nottinghamtec.co.uk/wiki" target="_blank"><span class="glyphicon glyphicon-link"></span> TEC Wiki</a>
|
||||||
|
<a class="list-group-item" href="http://members.nottinghamtec.co.uk/wiki/images/2/22/Event_Risk_Assesment.pdf" target="_blank"><span class="glyphicon glyphicon-link"></span> Pre-Event Risk Assessment</a>
|
||||||
<a class="list-group-item" href="//members.nottinghamtec.co.uk/price" target="_blank"><span class="glyphicon glyphicon-link"></span> Price List</a>
|
<a class="list-group-item" href="//members.nottinghamtec.co.uk/price" target="_blank"><span class="glyphicon glyphicon-link"></span> Price List</a>
|
||||||
|
<a class="list-group-item" href="https://form.jotformeu.com/62203600438344" target="_blank"><span class="glyphicon glyphicon-link"></span> Subhire Insurance Form</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -75,4 +77,4 @@
|
|||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
35
RIGS/templates/RIGS/invoice_confirm_delete.html
Normal file
35
RIGS/templates/RIGS/invoice_confirm_delete.html
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Delete payment on invoice {{ object.invoice.pk }}{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="col-sm-offset-2 col-sm-8">
|
||||||
|
<div class="alert alert-danger" role="alert">
|
||||||
|
<h2>Delete invoice {{ object.pk }}</h2>
|
||||||
|
|
||||||
|
<p>Are you sure you wish to delete invoice {{ object.pk }}?</p>
|
||||||
|
|
||||||
|
<p class="text-center"><strong>This action cannot be undone!</strong></p>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<form action="{{ action_link }}" method="post">{% csrf_token %}
|
||||||
|
<input type="hidden" name="next" value="{% url 'invoice_list' %}"/>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<input type="submit" value="Yes" class="btn btn-danger col-sm-1"/>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default col-sm-1">No</a>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -11,6 +11,10 @@
|
|||||||
|
|
||||||
<div class="col-sm-4 text-right">
|
<div class="col-sm-4 text-right">
|
||||||
<div class="btn-group btn-page">
|
<div class="btn-group btn-page">
|
||||||
|
<a href="{% url 'invoice_delete' object.pk %}" class="btn btn-default" title="Void Invoice">
|
||||||
|
<span class="glyphicon glyphicon-remove"></span> <span
|
||||||
|
class="hidden-xs">Delete</span>
|
||||||
|
</a>
|
||||||
<a href="{% url 'invoice_void' object.pk %}" class="btn btn-default" title="Void Invoice">
|
<a href="{% url 'invoice_void' object.pk %}" class="btn btn-default" title="Void Invoice">
|
||||||
<span class="glyphicon glyphicon-ban-circle"></span> <span
|
<span class="glyphicon glyphicon-ban-circle"></span> <span
|
||||||
class="hidden-xs">Void</span>
|
class="hidden-xs">Void</span>
|
||||||
@@ -38,8 +42,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6">
|
||||||
<div class="panel panel-{% if object.void %}danger{% else %}info{% endif %}">
|
<div class="panel panel-{% if object.is_closed %}success{% else %}warning{% endif %}">
|
||||||
<div class="panel-heading">Event Details</div>
|
<div class="panel-heading">Event Details<span class="pull-right">
|
||||||
|
{% if object.void %}(VOID){% elif object.is_closed %}(PAID){% else %}(OUTSTANDING){% endif %}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt>Event Number</dt>
|
<dt>Event Number</dt>
|
||||||
@@ -109,6 +116,11 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
<tr>
|
||||||
|
<td class="text-right"><strong>Balance:</strong></td>
|
||||||
|
<td>{{ object.balance|floatformat:2 }}</td>
|
||||||
|
<td></td>
|
||||||
|
<td></td>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,38 +5,71 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h2>Invoices</h2>
|
<h2>{% block heading %}Invoices{% endblock %}</h2>
|
||||||
|
{% block description %}{% endblock %}
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
||||||
{% paginator %}
|
{% paginator %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<table class="table table-responsive table-hover">
|
<div class="table-responsive col-sm-12">
|
||||||
<thead>
|
<table class="table table-hover">
|
||||||
<tr>
|
<thead>
|
||||||
<th>#</th>
|
<tr>
|
||||||
<th>Event</th>
|
<th>Invoice #</th>
|
||||||
<th>Invoice Date</th>
|
<th>Event</th>
|
||||||
<th>Balance</th>
|
<th>Client</th>
|
||||||
<th></th>
|
<th>Event Date</th>
|
||||||
</tr>
|
<th>Invoice Date</th>
|
||||||
</thead>
|
<th>Balance</th>
|
||||||
<tbody>
|
<th></th>
|
||||||
{% for object in object_list %}
|
|
||||||
<tr class="{% if object.void %}danger{% elif object.balance == 0 %}success{% endif %}">
|
|
||||||
<td>{{ object.pk }}</td>
|
|
||||||
<td><a href="{% url 'event_detail' object.event.pk %}" target="_blank">N{{ object.event.pk|stringformat:"05d" }}</a>: {{ object.event.name }}</td>
|
|
||||||
<td>{{ object.invoice_date }}</td>
|
|
||||||
<td>{{ object.balance|floatformat:2 }}</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default">
|
|
||||||
<span class="glyphicon glyphicon-pencil"></span>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
</thead>
|
||||||
</tbody>
|
<tbody>
|
||||||
</table>
|
{% for object in object_list %}
|
||||||
|
<tr>
|
||||||
|
<td class="{% if object.is_closed %}success{% else %}warning{% endif %}">{{ object.pk }}<br>
|
||||||
|
<span class="text-muted">{% if object.void %}(VOID){% elif object.is_closed %}(PAID){% else %}(O/S){% endif %}</span></td>
|
||||||
|
<td class="
|
||||||
|
{% if object.event.cancelled %}
|
||||||
|
active text-muted
|
||||||
|
{% elif not object.event.is_rig %}
|
||||||
|
info
|
||||||
|
{% elif object.event.confirmed and object.event.mic %}
|
||||||
|
{# interpreated as (booked and mic) #}
|
||||||
|
success
|
||||||
|
{% elif object.event.mic %}
|
||||||
|
warning
|
||||||
|
{% else %}
|
||||||
|
danger
|
||||||
|
{% endif %}
|
||||||
|
"><a href="{% url 'event_detail' object.event.pk %}">N{{ object.event.pk|stringformat:"05d" }}</a>: {{ object.event.name }} <br>
|
||||||
|
<span class="text-muted">{{ object.event.get_status_display }}{% if not object.event.mic %}, No MIC{% endif %}
|
||||||
|
</span></td>
|
||||||
|
</td>
|
||||||
|
<td>{% if object.event.organisation %}
|
||||||
|
{{ object.event.organisation.name }}
|
||||||
|
<br>
|
||||||
|
<span class="text-muted">{{ object.event.organisation.union_account|yesno:'Internal,External' }}</span>
|
||||||
|
{% else %}
|
||||||
|
{{ object.event.person.name }}
|
||||||
|
<br>
|
||||||
|
<span class="text-muted">External</span>
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td>{{ object.event.start_date }}</td>
|
||||||
|
<td>{{ object.invoice_date }}</td>
|
||||||
|
<td>{{ object.balance|floatformat:2 }}</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<a href="{% url 'invoice_detail' object.pk %}" class="btn btn-default">
|
||||||
|
<span class="glyphicon glyphicon-pencil"></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
{% if is_paginated %}
|
{% if is_paginated %}
|
||||||
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
<div class="col-md-6 col-md-offset-6 col-sm-12 text-right">
|
||||||
{% paginator %}
|
{% paginator %}
|
||||||
|
|||||||
13
RIGS/templates/RIGS/invoice_list_active.html
Normal file
13
RIGS/templates/RIGS/invoice_list_active.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends 'RIGS/invoice_list.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Outstanding Invoices
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block heading %}
|
||||||
|
Outstanding Invoices ({{ count }} Events, £ {{ total|floatformat:2 }})
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
<p>Paperwork for these events has been sent to treasury, but the full balance has not yet appeared on a ledger</p>
|
||||||
|
{% endblock %}
|
||||||
13
RIGS/templates/RIGS/invoice_list_archive.html
Normal file
13
RIGS/templates/RIGS/invoice_list_archive.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{% extends 'RIGS/invoice_list.html' %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
Invoice Archive
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block heading %}
|
||||||
|
All Invoices
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block description %}
|
||||||
|
<p>This page displays all invoices: outstanding, paid, and void</p>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{% load to_class_name from filters %}
|
{% load to_class_name from filters %}
|
||||||
{# pass in variable "object" to this template #}
|
{# pass in variable "object" to this template #}
|
||||||
|
|
||||||
<a title="'{{ object }}'" href="{{ object.get_absolute_url }}">'{{ object }}'</a>
|
<a title="{% if object.is_rig == False %}Non-rig{% elif object.dry_hire %}Dry Hire{% elif object.is_rig %}Rig{%else%}{{object|to_class_name}}{% endif %} | '{{object.name}}'" href="{{ object.get_absolute_url }}">{% if object.is_rig == False %}Non-rig{% elif object.dry_hire %}Dry Hire{% elif object.is_rig %}Rig{%else%}{{object|to_class_name}}{% endif %} | '{{object.name}}'</a>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<td>{{ object.pk }}</td>
|
<td>{{ object.pk }}</td>
|
||||||
<td>{{ object.name }}</td>
|
<td>{{ object.name }}</td>
|
||||||
<td>{{ object.email }}</td>
|
<td>{{ object.email }}</td>
|
||||||
<td>{{ object.phone }}</td>
|
<td><a href="tel:{{ object.phone }}">{{ object.phone }}</a></td>
|
||||||
<td>{{ object.notes|yesno|capfirst }}</td>
|
<td>{{ object.notes|yesno|capfirst }}</td>
|
||||||
<td>{{ object.union_account|yesno|capfirst }}</td>
|
<td>{{ object.union_account|yesno|capfirst }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@
|
|||||||
<td>{{ person.pk }}</td>
|
<td>{{ person.pk }}</td>
|
||||||
<td>{{ person.name }}</td>
|
<td>{{ person.name }}</td>
|
||||||
<td>{{ person.email }}</td>
|
<td>{{ person.email }}</td>
|
||||||
<td>{{ person.phone }}</td>
|
<td><a href="tel:{{ person.phone }}">{{ person.phone }}</a></td>
|
||||||
<td>{{ person.notes|yesno|capfirst }}</td>
|
<td>{{ person.notes|yesno|capfirst }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'person_detail' person.pk %}" class="btn btn-default modal-href">
|
<a href="{% url 'person_detail' person.pk %}" class="btn btn-default modal-href">
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
<dd>{{object.initials}}</dd>
|
<dd>{{object.initials}}</dd>
|
||||||
|
|
||||||
<dt>Phone</dt>
|
<dt>Phone</dt>
|
||||||
<dd>{{object.phone}}</dd>
|
<dd><a href="tel:{{ object.phone }}">{{object.phone}}</a></dd>
|
||||||
</dl>
|
</dl>
|
||||||
{% if not request.is_ajax %}
|
{% if not request.is_ajax %}
|
||||||
{% if object.pk == user.pk %}
|
{% if object.pk == user.pk %}
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
<dd>
|
<dd>
|
||||||
{% if user.api_key %}
|
{% if user.api_key %}
|
||||||
<pre id="cal-url" data-url="http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}"></pre>
|
<pre id="cal-url" data-url="http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}"></pre>
|
||||||
<small><a id="gcal-link" data-url="http://www.google.com/calendar/render?cid=http{{ request.is_secure|yesno:"s,"}}://{{ request.get_host }}{% url 'ics_calendar' api_pk=user.pk api_key=user.api_key %}" href="">Click here</a> to add to google calendar.<br/>
|
<small><a id="gcal-link" data-url="https://support.google.com/calendar/answer/37100" href="">Click here</a> for instructions on adding to google calendar.<br/>
|
||||||
To sync from google calendar to mobile device, visit <a href="https://www.google.com/calendar/syncselect" target="_blank">this page</a> on your device and tick "RIGS Calendar".</small>
|
To sync from google calendar to mobile device, visit <a href="https://www.google.com/calendar/syncselect" target="_blank">this page</a> on your device and tick "RIGS Calendar".</small>
|
||||||
{% else %}
|
{% else %}
|
||||||
<pre>No API Key Generated</pre>
|
<pre>No API Key Generated</pre>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<td>{{ object.pk }}</td>
|
<td>{{ object.pk }}</td>
|
||||||
<td>{{ object.name }}</td>
|
<td>{{ object.name }}</td>
|
||||||
<td>{{ object.email }}</td>
|
<td>{{ object.email }}</td>
|
||||||
<td>{{ object.phone }}</td>
|
<td><a href="tel:{{ object.phone }}">{{ object.phone }}</a></td>
|
||||||
<td>{{ object.notes|yesno|capfirst }}</td>
|
<td>{{ object.notes|yesno|capfirst }}</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="{% url 'venue_detail' object.pk %}" class="btn btn-default modal-href">
|
<a href="{% url 'venue_detail' object.pk %}" class="btn btn-default modal-href">
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
from datetime import date, timedelta
|
||||||
|
|
||||||
|
import reversion
|
||||||
|
from django.core import mail
|
||||||
|
from django.db import transaction
|
||||||
from django.test import LiveServerTestCase
|
from django.test import LiveServerTestCase
|
||||||
from django.test.client import Client
|
from django.test.client import Client
|
||||||
from django.core import mail
|
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
from selenium.webdriver.common.keys import Keys
|
|
||||||
from selenium.common.exceptions import StaleElementReferenceException, WebDriverException
|
from selenium.common.exceptions import StaleElementReferenceException, WebDriverException
|
||||||
|
from selenium.webdriver.common.keys import Keys
|
||||||
from selenium.webdriver.support.ui import WebDriverWait
|
from selenium.webdriver.support.ui import WebDriverWait
|
||||||
|
|
||||||
from RIGS import models
|
from RIGS import models
|
||||||
import re
|
|
||||||
import os
|
|
||||||
from datetime import date, timedelta
|
|
||||||
from django.db import transaction
|
|
||||||
import reversion
|
|
||||||
import json
|
|
||||||
|
|
||||||
|
|
||||||
class UserRegistrationTest(LiveServerTestCase):
|
class UserRegistrationTest(LiveServerTestCase):
|
||||||
@@ -103,7 +104,7 @@ class UserRegistrationTest(LiveServerTestCase):
|
|||||||
# Check Email
|
# Check Email
|
||||||
self.assertEqual(len(mail.outbox), 1)
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
email = mail.outbox[0]
|
email = mail.outbox[0]
|
||||||
self.assertIn('activation required', email.subject)
|
self.assertIn('John Smith "JS" activation required', email.subject)
|
||||||
urls = re.findall(
|
urls = re.findall(
|
||||||
'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', email.body)
|
'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', email.body)
|
||||||
self.assertEqual(len(urls), 1)
|
self.assertEqual(len(urls), 1)
|
||||||
@@ -437,7 +438,7 @@ class EventTest(LiveServerTestCase):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def testEventDuplicate(self):
|
def testEventDuplicate(self):
|
||||||
testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, start_date=date.today() + timedelta(days=6), description="start future no end")
|
testEvent = models.Event.objects.create(name="TE E1", status=models.Event.PROVISIONAL, start_date=date.today() + timedelta(days=6), description="start future no end", purchase_order="TESTPO")
|
||||||
|
|
||||||
item1 = models.EventItem(
|
item1 = models.EventItem(
|
||||||
event=testEvent,
|
event=testEvent,
|
||||||
@@ -470,6 +471,9 @@ class EventTest(LiveServerTestCase):
|
|||||||
self.assertIn("Test Item 1", table.text)
|
self.assertIn("Test Item 1", table.text)
|
||||||
self.assertIn("Test Item 2", table.text)
|
self.assertIn("Test Item 2", table.text)
|
||||||
|
|
||||||
|
# Check the info message is visible
|
||||||
|
self.assertIn("Event data duplicated but not yet saved",self.browser.find_element_by_id('content').text)
|
||||||
|
|
||||||
# Add item
|
# Add item
|
||||||
form.find_element_by_xpath('//button[contains(@class, "item-add")]').click()
|
form.find_element_by_xpath('//button[contains(@class, "item-add")]').click()
|
||||||
wait.until(animation_is_finished())
|
wait.until(animation_is_finished())
|
||||||
@@ -488,6 +492,7 @@ class EventTest(LiveServerTestCase):
|
|||||||
save.click()
|
save.click()
|
||||||
|
|
||||||
self.assertNotIn("N0000%d"%testEvent.pk, self.browser.find_element_by_xpath('//h1').text)
|
self.assertNotIn("N0000%d"%testEvent.pk, self.browser.find_element_by_xpath('//h1').text)
|
||||||
|
self.assertNotIn("Event data duplicated but not yet saved", self.browser.find_element_by_id('content').text) # Check info message not visible
|
||||||
|
|
||||||
# Check the new items are visible
|
# Check the new items are visible
|
||||||
table = self.browser.find_element_by_id('item-table') # ID number is known, see above
|
table = self.browser.find_element_by_id('item-table') # ID number is known, see above
|
||||||
@@ -497,6 +502,8 @@ class EventTest(LiveServerTestCase):
|
|||||||
|
|
||||||
infoPanel = self.browser.find_element_by_xpath('//div[contains(text(), "Event Info")]/..')
|
infoPanel = self.browser.find_element_by_xpath('//div[contains(text(), "Event Info")]/..')
|
||||||
self.assertIn("N0000%d"%testEvent.pk, infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text)
|
self.assertIn("N0000%d"%testEvent.pk, infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text)
|
||||||
|
# Check the PO hasn't carried through
|
||||||
|
self.assertNotIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -505,6 +512,8 @@ class EventTest(LiveServerTestCase):
|
|||||||
#Check that based-on hasn't crept into the old event
|
#Check that based-on hasn't crept into the old event
|
||||||
infoPanel = self.browser.find_element_by_xpath('//div[contains(text(), "Event Info")]/..')
|
infoPanel = self.browser.find_element_by_xpath('//div[contains(text(), "Event Info")]/..')
|
||||||
self.assertNotIn("N0000%d"%testEvent.pk, infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text)
|
self.assertNotIn("N0000%d"%testEvent.pk, infoPanel.find_element_by_xpath('//dt[text()="Based On"]/following-sibling::dd[1]').text)
|
||||||
|
# Check the PO remains on the old event
|
||||||
|
self.assertIn("TESTPO", infoPanel.find_element_by_xpath('//dt[text()="PO"]/following-sibling::dd[1]').text)
|
||||||
|
|
||||||
# Check the items are as they were
|
# Check the items are as they were
|
||||||
table = self.browser.find_element_by_id('item-table') # ID number is known, see above
|
table = self.browser.find_element_by_id('item-table') # ID number is known, see above
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.test import TestCase
|
|
||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from RIGS import models
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
from django.test import TestCase
|
||||||
|
from django.test.utils import override_settings
|
||||||
|
|
||||||
|
from RIGS import models
|
||||||
|
|
||||||
|
|
||||||
class TestAdminMergeObjects(TestCase):
|
class TestAdminMergeObjects(TestCase):
|
||||||
@@ -155,3 +158,153 @@ class TestAdminMergeObjects(TestCase):
|
|||||||
if event.organisation == self.organisations[3]: # The one we left in place
|
if event.organisation == self.organisations[3]: # The one we left in place
|
||||||
continue
|
continue
|
||||||
self.assertEqual(updatedEvent.organisation, self.organisations[1])
|
self.assertEqual(updatedEvent.organisation, self.organisations[1])
|
||||||
|
|
||||||
|
class TestInvoiceDelete(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.profile = models.Profile.objects.create(username="testuser1", email="1@test.com", is_superuser=True, is_active=True, is_staff=True)
|
||||||
|
|
||||||
|
cls.events = {
|
||||||
|
1: models.Event.objects.create(name="TE E1", start_date=date.today()),
|
||||||
|
2: models.Event.objects.create(name="TE E2", start_date=date.today())
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.invoices = {
|
||||||
|
1: models.Invoice.objects.create(event=cls.events[1]),
|
||||||
|
2: models.Invoice.objects.create(event=cls.events[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.payments = {
|
||||||
|
1: models.Payment.objects.create(invoice=cls.invoices[1], date=date.today(), amount=12.34, method=models.Payment.CASH)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.profile.set_password('testuser')
|
||||||
|
self.profile.save()
|
||||||
|
self.assertTrue(self.client.login(username=self.profile.username, password='testuser'))
|
||||||
|
|
||||||
|
def test_invoice_delete_allowed(self):
|
||||||
|
request_url = reverse('invoice_delete', kwargs={'pk':self.invoices[2].pk})
|
||||||
|
|
||||||
|
response = self.client.get(request_url, follow=True)
|
||||||
|
self.assertContains(response, "Are you sure")
|
||||||
|
|
||||||
|
# Check the invoice still exists
|
||||||
|
self.assertTrue(models.Invoice.objects.get(pk=self.invoices[2].pk))
|
||||||
|
|
||||||
|
# Actually delete it
|
||||||
|
response = self.client.post(request_url, follow=True)
|
||||||
|
|
||||||
|
# Check the invoice is deleted
|
||||||
|
self.assertRaises(ObjectDoesNotExist, models.Invoice.objects.get, pk=self.invoices[2].pk)
|
||||||
|
|
||||||
|
def test_invoice_delete_not_allowed(self):
|
||||||
|
request_url = reverse('invoice_delete', kwargs={'pk':self.invoices[1].pk})
|
||||||
|
|
||||||
|
response = self.client.get(request_url, follow=True)
|
||||||
|
self.assertContains(response, "To delete an invoice, delete the payments first.")
|
||||||
|
|
||||||
|
# Check the invoice still exists
|
||||||
|
self.assertTrue(models.Invoice.objects.get(pk=self.invoices[1].pk))
|
||||||
|
|
||||||
|
# Try to actually delete it
|
||||||
|
response = self.client.post(request_url, follow=True)
|
||||||
|
|
||||||
|
# Check this didn't work
|
||||||
|
self.assertTrue(models.Invoice.objects.get(pk=self.invoices[1].pk))
|
||||||
|
|
||||||
|
|
||||||
|
class TestEmbeddedViews(TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
cls.profile = models.Profile.objects.create(username="testuser1", email="1@test.com", is_superuser=True, is_active=True, is_staff=True)
|
||||||
|
|
||||||
|
cls.events = {
|
||||||
|
1: models.Event.objects.create(name="TE E1", start_date=date.today()),
|
||||||
|
2: models.Event.objects.create(name="TE E2", start_date=date.today())
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.invoices = {
|
||||||
|
1: models.Invoice.objects.create(event=cls.events[1]),
|
||||||
|
2: models.Invoice.objects.create(event=cls.events[2])
|
||||||
|
}
|
||||||
|
|
||||||
|
cls.payments = {
|
||||||
|
1: models.Payment.objects.create(invoice=cls.invoices[1], date=date.today(), amount=12.34, method=models.Payment.CASH)
|
||||||
|
}
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.profile.set_password('testuser')
|
||||||
|
self.profile.save()
|
||||||
|
|
||||||
|
def testLoginRedirect(self):
|
||||||
|
request_url = reverse('event_embed', kwargs={'pk': 1})
|
||||||
|
expected_url = "{0}?next={1}".format(reverse('login_embed'), request_url)
|
||||||
|
|
||||||
|
# Request the page and check it redirects
|
||||||
|
response = self.client.get(request_url, follow=True)
|
||||||
|
self.assertRedirects(response, expected_url, status_code=302, target_status_code=200)
|
||||||
|
|
||||||
|
# Now login
|
||||||
|
self.assertTrue(self.client.login(username=self.profile.username, password='testuser'))
|
||||||
|
|
||||||
|
# And check that it no longer redirects
|
||||||
|
response = self.client.get(request_url, follow=True)
|
||||||
|
self.assertEqual(len(response.redirect_chain), 0)
|
||||||
|
|
||||||
|
def testLoginCookieWarning(self):
|
||||||
|
login_url = reverse('login_embed')
|
||||||
|
response = self.client.post(login_url, follow=True)
|
||||||
|
self.assertContains(response, "Cookies do not seem to be enabled")
|
||||||
|
|
||||||
|
def testXFrameHeaders(self):
|
||||||
|
event_url = reverse('event_embed', kwargs={'pk': 1})
|
||||||
|
login_url = reverse('login_embed')
|
||||||
|
|
||||||
|
self.assertTrue(self.client.login(username=self.profile.username, password='testuser'))
|
||||||
|
|
||||||
|
response = self.client.get(event_url, follow=True)
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
response._headers["X-Frame-Options"]
|
||||||
|
|
||||||
|
response = self.client.get(login_url, follow=True)
|
||||||
|
with self.assertRaises(KeyError):
|
||||||
|
response._headers["X-Frame-Options"]
|
||||||
|
|
||||||
|
def testOEmbed(self):
|
||||||
|
event_url = reverse('event_detail', kwargs={'pk': 1})
|
||||||
|
event_embed_url = reverse('event_embed', kwargs={'pk': 1})
|
||||||
|
oembed_url = reverse('event_oembed', kwargs={'pk': 1})
|
||||||
|
|
||||||
|
alt_oembed_url = reverse('event_oembed', kwargs={'pk': 999})
|
||||||
|
alt_event_embed_url = reverse('event_embed', kwargs={'pk': 999})
|
||||||
|
|
||||||
|
# Test the meta tag is in place
|
||||||
|
response = self.client.get(event_url, follow=True, HTTP_HOST='example.com')
|
||||||
|
self.assertContains(response, '<link rel="alternate" type="application/json+oembed"')
|
||||||
|
self.assertContains(response, oembed_url)
|
||||||
|
|
||||||
|
# Test that the JSON exists
|
||||||
|
response = self.client.get(oembed_url, follow=True, HTTP_HOST='example.com')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, event_embed_url)
|
||||||
|
|
||||||
|
# Should also work for non-existant events
|
||||||
|
response = self.client.get(alt_oembed_url, follow=True, HTTP_HOST='example.com')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, alt_event_embed_url)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSampleDataGenerator(TestCase):
|
||||||
|
@override_settings(DEBUG=True)
|
||||||
|
def test_generate_sample_data(self):
|
||||||
|
# Run the management command and check there are no exceptions
|
||||||
|
call_command('generateSampleData')
|
||||||
|
|
||||||
|
# Check there are lots of events
|
||||||
|
self.assertTrue(models.Event.objects.all().count() > 100)
|
||||||
|
|
||||||
|
def test_production_exception(self):
|
||||||
|
from django.core.management.base import CommandError
|
||||||
|
|
||||||
|
self.assertRaisesRegexp(CommandError, ".*production", call_command, 'generateSampleData')
|
||||||
|
|||||||
36
RIGS/urls.py
36
RIGS/urls.py
@@ -1,7 +1,8 @@
|
|||||||
from django.conf.urls import patterns, include, url
|
from django.conf.urls import patterns, url
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from RIGS import models, views, rigboard, finance, ical, versioning, forms
|
from RIGS import models, views, rigboard, finance, ical, versioning, forms
|
||||||
from django.views.generic import RedirectView
|
from django.views.generic import RedirectView
|
||||||
|
from django.views.decorators.clickjacking import xframe_options_exempt
|
||||||
|
|
||||||
from PyRIGS.decorators import permission_required_with_403
|
from PyRIGS.decorators import permission_required_with_403
|
||||||
from PyRIGS.decorators import api_key_required
|
from PyRIGS.decorators import api_key_required
|
||||||
@@ -14,7 +15,8 @@ urlpatterns = patterns('',
|
|||||||
url(r'^closemodal/$', views.CloseModal.as_view(), name='closemodal'),
|
url(r'^closemodal/$', views.CloseModal.as_view(), name='closemodal'),
|
||||||
|
|
||||||
url('^user/login/$', 'RIGS.views.login', name='login'),
|
url('^user/login/$', 'RIGS.views.login', name='login'),
|
||||||
url(r'^user/password_reset/$', 'django.contrib.auth.views.password_reset', {'password_reset_form':forms.PasswordReset}),
|
url('^user/login/embed/$', xframe_options_exempt(views.login_embed), name='login_embed'),
|
||||||
|
url(r'^user/password_reset/$', 'django.contrib.auth.views.password_reset', {'password_reset_form': forms.PasswordReset}),
|
||||||
|
|
||||||
# People
|
# People
|
||||||
url(r'^people/$', permission_required_with_403('RIGS.view_person')(views.PersonList.as_view()),
|
url(r'^people/$', permission_required_with_403('RIGS.view_person')(views.PersonList.as_view()),
|
||||||
@@ -71,7 +73,7 @@ urlpatterns = patterns('',
|
|||||||
url(r'^rigboard/calendar/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
url(r'^rigboard/calendar/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
||||||
url(r'^rigboard/calendar/(?P<view>(month|week|day))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
url(r'^rigboard/calendar/(?P<view>(month|week|day))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
||||||
url(r'^rigboard/calendar/(?P<view>(month|week|day))/(?P<date>(\d{4}-\d{2}-\d{2}))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
url(r'^rigboard/calendar/(?P<view>(month|week|day))/(?P<date>(\d{4}-\d{2}-\d{2}))/$', login_required()(rigboard.WebCalendar.as_view()), name='web_calendar'),
|
||||||
url(r'^rigboard/archive/$', RedirectView.as_view(permanent=True,pattern_name='event_archive')),
|
url(r'^rigboard/archive/$', RedirectView.as_view(permanent=True, pattern_name='event_archive')),
|
||||||
url(r'^rigboard/activity/$',
|
url(r'^rigboard/activity/$',
|
||||||
permission_required_with_403('RIGS.view_event')(versioning.ActivityTable.as_view()),
|
permission_required_with_403('RIGS.view_event')(versioning.ActivityTable.as_view()),
|
||||||
name='activity_table'),
|
name='activity_table'),
|
||||||
@@ -80,8 +82,14 @@ urlpatterns = patterns('',
|
|||||||
name='activity_feed'),
|
name='activity_feed'),
|
||||||
|
|
||||||
url(r'^event/(?P<pk>\d+)/$',
|
url(r'^event/(?P<pk>\d+)/$',
|
||||||
permission_required_with_403('RIGS.view_event')(rigboard.EventDetail.as_view()),
|
permission_required_with_403('RIGS.view_event', oembed_view="event_oembed")(rigboard.EventDetail.as_view()),
|
||||||
name='event_detail'),
|
name='event_detail'),
|
||||||
|
url(r'^event/(?P<pk>\d+)/embed/$',
|
||||||
|
xframe_options_exempt(login_required(login_url='/user/login/embed/')(rigboard.EventEmbed.as_view())),
|
||||||
|
name='event_embed'),
|
||||||
|
url(r'^event/(?P<pk>\d+)/oembed_json/$',
|
||||||
|
rigboard.EventOembed.as_view(),
|
||||||
|
name='event_oembed'),
|
||||||
url(r'^event/(?P<pk>\d+)/print/$',
|
url(r'^event/(?P<pk>\d+)/print/$',
|
||||||
permission_required_with_403('RIGS.view_event')(rigboard.EventPrint.as_view()),
|
permission_required_with_403('RIGS.view_event')(rigboard.EventPrint.as_view()),
|
||||||
name='event_print'),
|
name='event_print'),
|
||||||
@@ -101,7 +109,7 @@ urlpatterns = patterns('',
|
|||||||
permission_required_with_403('RIGS.view_event')(versioning.VersionHistory.as_view()),
|
permission_required_with_403('RIGS.view_event')(versioning.VersionHistory.as_view()),
|
||||||
name='event_history', kwargs={'model': models.Event}),
|
name='event_history', kwargs={'model': models.Event}),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Finance
|
# Finance
|
||||||
url(r'^invoice/$',
|
url(r'^invoice/$',
|
||||||
@@ -127,6 +135,9 @@ urlpatterns = patterns('',
|
|||||||
url(r'^invoice/(?P<pk>\d+)/void/$',
|
url(r'^invoice/(?P<pk>\d+)/void/$',
|
||||||
permission_required_with_403('RIGS.change_invoice')(finance.InvoiceVoid.as_view()),
|
permission_required_with_403('RIGS.change_invoice')(finance.InvoiceVoid.as_view()),
|
||||||
name='invoice_void'),
|
name='invoice_void'),
|
||||||
|
url(r'^invoice/(?P<pk>\d+)/delete/$',
|
||||||
|
permission_required_with_403('RIGS.change_invoice')(finance.InvoiceDelete.as_view()),
|
||||||
|
name='invoice_delete'),
|
||||||
url(r'^payment/create/$',
|
url(r'^payment/create/$',
|
||||||
permission_required_with_403('RIGS.add_payment')(finance.PaymentCreate.as_view()),
|
permission_required_with_403('RIGS.add_payment')(finance.PaymentCreate.as_view()),
|
||||||
name='payment_create'),
|
name='payment_create'),
|
||||||
@@ -137,10 +148,10 @@ urlpatterns = patterns('',
|
|||||||
# User editing
|
# User editing
|
||||||
url(r'^user/$', login_required(views.ProfileDetail.as_view()), name='profile_detail'),
|
url(r'^user/$', login_required(views.ProfileDetail.as_view()), name='profile_detail'),
|
||||||
url(r'^user/(?P<pk>\d+)/$',
|
url(r'^user/(?P<pk>\d+)/$',
|
||||||
permission_required_with_403('RIGS.view_profile')(views.ProfileDetail.as_view()),
|
permission_required_with_403('RIGS.view_profile')(views.ProfileDetail.as_view()),
|
||||||
name='profile_detail'),
|
name='profile_detail'),
|
||||||
url(r'^user/edit/$', login_required(views.ProfileUpdateSelf.as_view()),
|
url(r'^user/edit/$', login_required(views.ProfileUpdateSelf.as_view()),
|
||||||
name='profile_update_self'),
|
name='profile_update_self'),
|
||||||
url(r'^user/reset_api_key$', login_required(views.ResetApiKey.as_view(permanent=False)), name='reset_api_key'),
|
url(r'^user/reset_api_key$', login_required(views.ResetApiKey.as_view(permanent=False)), name='reset_api_key'),
|
||||||
|
|
||||||
# ICS Calendar - API key authentication
|
# ICS Calendar - API key authentication
|
||||||
@@ -151,8 +162,7 @@ urlpatterns = patterns('',
|
|||||||
url(r'^api/(?P<model>\w+)/(?P<pk>\d+)/$', login_required(views.SecureAPIRequest.as_view()), name="api_secure"),
|
url(r'^api/(?P<model>\w+)/(?P<pk>\d+)/$', login_required(views.SecureAPIRequest.as_view()), name="api_secure"),
|
||||||
|
|
||||||
# Legacy URL's
|
# Legacy URL's
|
||||||
url(r'^rig/show/(?P<pk>\d+)/$', RedirectView.as_view(permanent=True,pattern_name='event_detail')),
|
url(r'^rig/show/(?P<pk>\d+)/$', RedirectView.as_view(permanent=True, pattern_name='event_detail')),
|
||||||
url(r'^bookings/$', RedirectView.as_view(permanent=True,pattern_name='rigboard')),
|
url(r'^bookings/$', RedirectView.as_view(permanent=True, pattern_name='rigboard')),
|
||||||
url(r'^bookings/past/$', RedirectView.as_view(permanent=True,pattern_name='event_archive')),
|
url(r'^bookings/past/$', RedirectView.as_view(permanent=True, pattern_name='event_archive')),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,6 @@ def model_compare(oldObj, newObj, excluded_keys=[]):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
|
||||||
def json(self):
|
|
||||||
if "JSON" in self.field.description:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def linebreaks(self):
|
def linebreaks(self):
|
||||||
if isinstance(self.field, TextField):
|
if isinstance(self.field, TextField):
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ from django.contrib import messages
|
|||||||
import datetime, pytz
|
import datetime, pytz
|
||||||
import operator
|
import operator
|
||||||
from registration.views import RegistrationView
|
from registration.views import RegistrationView
|
||||||
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
|
|
||||||
|
|
||||||
from RIGS import models, forms
|
from RIGS import models, forms
|
||||||
|
|
||||||
@@ -29,12 +31,37 @@ class Index(generic.TemplateView):
|
|||||||
def login(request, **kwargs):
|
def login(request, **kwargs):
|
||||||
if request.user.is_authenticated():
|
if request.user.is_authenticated():
|
||||||
next = request.REQUEST.get('next', '/')
|
next = request.REQUEST.get('next', '/')
|
||||||
return HttpResponseRedirect(request.REQUEST.get('next', '/'))
|
return HttpResponseRedirect(next)
|
||||||
else:
|
else:
|
||||||
from django.contrib.auth.views import login
|
from django.contrib.auth.views import login
|
||||||
|
|
||||||
return login(request)
|
return login(request)
|
||||||
|
|
||||||
|
|
||||||
|
# This view should be exempt from requiring CSRF token.
|
||||||
|
# Then we can check for it and show a nice error
|
||||||
|
# Don't worry, django.contrib.auth.views.login will
|
||||||
|
# check for it before logging the user in
|
||||||
|
@csrf_exempt
|
||||||
|
def login_embed(request, **kwargs):
|
||||||
|
print("Running LOGIN")
|
||||||
|
if request.user.is_authenticated():
|
||||||
|
next = request.REQUEST.get('next', '/')
|
||||||
|
return HttpResponseRedirect(next)
|
||||||
|
else:
|
||||||
|
from django.contrib.auth.views import login
|
||||||
|
|
||||||
|
if request.method == "POST":
|
||||||
|
csrf_cookie = request.COOKIES.get('csrftoken', None)
|
||||||
|
|
||||||
|
if csrf_cookie is None:
|
||||||
|
messages.warning(request, 'Cookies do not seem to be enabled. Try logging in using a new tab.')
|
||||||
|
request.method = 'GET' # Render the page without trying to login
|
||||||
|
|
||||||
|
return login(request, template_name="registration/login_embed.html")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Called from a modal window (e.g. when an item is submitted to an event/invoice).
|
Called from a modal window (e.g. when an item is submitted to an event/invoice).
|
||||||
May optionally also include some javascript in a success message to cause a load of
|
May optionally also include some javascript in a success message to cause a load of
|
||||||
|
|||||||
53
app.json
Normal file
53
app.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"name": "PyRIGS",
|
||||||
|
"description": "",
|
||||||
|
"scripts": {
|
||||||
|
"postdeploy": "python manage.py migrate && python manage.py generateSampleData"
|
||||||
|
},
|
||||||
|
"env": {
|
||||||
|
"DEBUG": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"STAGING": "1",
|
||||||
|
"EMAIL_FROM": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"EMAIL_HOST": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"EMAIL_HOST_PASSWORD": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"EMAIL_HOST_USER": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"EMAIL_PORT": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"EMAIL_USE_SSL": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"RECAPTCHA_PRIVATE_KEY": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"RECAPTCHA_PUBLIC_KEY": {
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
"SECRET_KEY": {
|
||||||
|
"generator": "secret"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"formation": {
|
||||||
|
"web": {
|
||||||
|
"quantity": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"addons": [
|
||||||
|
"heroku-postgresql"
|
||||||
|
],
|
||||||
|
"buildpacks": [
|
||||||
|
{
|
||||||
|
"url": "heroku/python"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ django-toolbelt==0.0.1
|
|||||||
django-widget-tweaks==1.3
|
django-widget-tweaks==1.3
|
||||||
gunicorn==19.3.0
|
gunicorn==19.3.0
|
||||||
icalendar==3.9.0
|
icalendar==3.9.0
|
||||||
jsonschema==2.5.1
|
|
||||||
lxml==3.4.4
|
lxml==3.4.4
|
||||||
Pillow==2.8.1
|
Pillow==2.8.1
|
||||||
psycopg2==2.6
|
psycopg2==2.6
|
||||||
@@ -21,7 +20,7 @@ python-dateutil==2.4.2
|
|||||||
pytz==2015.4
|
pytz==2015.4
|
||||||
raven==5.8.1
|
raven==5.8.1
|
||||||
reportlab==3.1.44
|
reportlab==3.1.44
|
||||||
selenium==2.53.1
|
selenium==2.53.6
|
||||||
simplejson==3.7.2
|
simplejson==3.7.2
|
||||||
six==1.9.0
|
six==1.9.0
|
||||||
sqlparse==0.1.15
|
sqlparse==0.1.15
|
||||||
@@ -32,4 +31,3 @@ z3c.rml==2.8.1
|
|||||||
zope.event==4.0.3
|
zope.event==4.0.3
|
||||||
zope.interface==4.1.2
|
zope.interface==4.1.2
|
||||||
zope.schema==4.4.2
|
zope.schema==4.4.2
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
from rigForms import models
|
|
||||||
|
|
||||||
import reversion
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
admin.site.register(models.Type, reversion.VersionAdmin)
|
|
||||||
admin.site.register(models.Schema, reversion.VersionAdmin)
|
|
||||||
admin.site.register(models.Form, reversion.VersionAdmin)
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
import RIGS.models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('RIGS', '0023_auto_20150529_0048'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Form',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
||||||
('data', models.TextField(default=b'{}')),
|
|
||||||
('event', models.ForeignKey(related_name='forms', to='RIGS.Event')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'permissions': (('create_form', 'Can complete a form'), ('update_form', 'Can change a form'), ('view_form', 'Can view forms')),
|
|
||||||
},
|
|
||||||
bases=(models.Model, RIGS.models.RevisionMixin),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Schema',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
||||||
('start_at', models.DateTimeField()),
|
|
||||||
('schema', models.TextField(default=b'{}')),
|
|
||||||
('layout', models.TextField(default=b'{}')),
|
|
||||||
('comment', models.CharField(max_length=255)),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ['-start_at'],
|
|
||||||
'get_latest_by': 'start_at',
|
|
||||||
},
|
|
||||||
bases=(models.Model, RIGS.models.RevisionMixin),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Type',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
||||||
('name', models.CharField(max_length=255)),
|
|
||||||
('description', models.CharField(max_length=255, null=True, blank=True)),
|
|
||||||
('active', models.BooleanField(default=True)),
|
|
||||||
],
|
|
||||||
bases=(models.Model, RIGS.models.RevisionMixin),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='schema',
|
|
||||||
name='schema_type',
|
|
||||||
field=models.ForeignKey(related_name='schemas', to='rigForms.Type'),
|
|
||||||
),
|
|
||||||
migrations.AddField(
|
|
||||||
model_name='form',
|
|
||||||
name='schema',
|
|
||||||
field=models.ForeignKey(related_name='forms', to='rigForms.Schema'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
|
|
||||||
from django.db import models, migrations
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('rigForms', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='schema',
|
|
||||||
name='layout',
|
|
||||||
field=models.TextField(default=b'[]'),
|
|
||||||
),
|
|
||||||
]
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
from django.db import models
|
|
||||||
from django.utils.encoding import python_2_unicode_compatible
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
|
||||||
import reversion
|
|
||||||
|
|
||||||
import json
|
|
||||||
import jsonschema
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
from RIGS.models import RevisionMixin
|
|
||||||
from RIGS import versioning
|
|
||||||
|
|
||||||
from django.template import Context,Template
|
|
||||||
from django.core.urlresolvers import reverse_lazy
|
|
||||||
|
|
||||||
class JSONField(models.TextField):
|
|
||||||
description = "String representing a JSON Schema"
|
|
||||||
|
|
||||||
@reversion.register
|
|
||||||
class Type(models.Model, RevisionMixin):
|
|
||||||
name = models.CharField(max_length=255, blank=False, null=False)
|
|
||||||
description = models.CharField(max_length=255, blank=True, null=True)
|
|
||||||
active = models.BooleanField(default=True)
|
|
||||||
|
|
||||||
class SchemaManager(models.Manager):
|
|
||||||
def current_schema(self, schemaType):
|
|
||||||
return self.find_schema(schemaType, datetime.datetime.now())
|
|
||||||
|
|
||||||
def find_schema(self, schemaType, date):
|
|
||||||
return self.filter(schema_type=schemaType, start_at__lte=date).latest()
|
|
||||||
|
|
||||||
@reversion.register
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Schema(models.Model, RevisionMixin):
|
|
||||||
schema_type = models.ForeignKey('Type', related_name='schemas', blank=False)
|
|
||||||
|
|
||||||
start_at = models.DateTimeField()
|
|
||||||
|
|
||||||
schema = JSONField(blank=False, null=False, default="{}")
|
|
||||||
layout = JSONField(blank=False, null=False, default="[]")
|
|
||||||
|
|
||||||
comment = models.CharField(max_length=255)
|
|
||||||
|
|
||||||
objects = SchemaManager()
|
|
||||||
|
|
||||||
def clean(self):
|
|
||||||
# raise ValidationError('Invalid JSON received')
|
|
||||||
try:
|
|
||||||
jsonData = json.loads(self.schema)
|
|
||||||
except ValueError:
|
|
||||||
raise ValidationError('Invalid JSON in schema')
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
|
|
||||||
try:
|
|
||||||
jsonData = json.loads('{"data":'+self.layout+"}")
|
|
||||||
except ValueError:
|
|
||||||
raise ValidationError('Invalid JSON in layout')
|
|
||||||
except:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
"""Call :meth:`full_clean` before saving."""
|
|
||||||
self.full_clean()
|
|
||||||
super(Schema, self).save(*args, **kwargs)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
ordering = ['-start_at']
|
|
||||||
get_latest_by = 'start_at'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.schema_type.name + "|" + self.comment + " " + str(self.start_at)
|
|
||||||
|
|
||||||
@reversion.register
|
|
||||||
@versioning.register
|
|
||||||
@python_2_unicode_compatible
|
|
||||||
class Form(models.Model, RevisionMixin):
|
|
||||||
event = models.ForeignKey('RIGS.Event', related_name='forms', blank=False)
|
|
||||||
schema = models.ForeignKey('Schema', related_name='forms', blank=False)
|
|
||||||
|
|
||||||
data = JSONField(blank=False, null=False, default="{}")
|
|
||||||
|
|
||||||
@property
|
|
||||||
def renderedSchema(self):
|
|
||||||
template = Template(self.schema.schema)
|
|
||||||
|
|
||||||
context = Context({
|
|
||||||
"event": self.event, # allow stuff to be auto-filled
|
|
||||||
"SfCurrentIndex": "{{ $index +1 }}" # Convenience for schemaform array index
|
|
||||||
})
|
|
||||||
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def renderedLayout(self):
|
|
||||||
template = Template(self.schema.layout)
|
|
||||||
|
|
||||||
context = Context({
|
|
||||||
"event": self.event, # allow stuff to be auto-filled
|
|
||||||
"SfCurrentIndex": "{{ $index +1 }}" # Convenience for schemaform array index
|
|
||||||
})
|
|
||||||
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def get_absolute_url(self):
|
|
||||||
return reverse_lazy('form_detail', kwargs={'pk': self.pk})
|
|
||||||
|
|
||||||
def clean(self):
|
|
||||||
try:
|
|
||||||
jsonData = json.loads(self.data)
|
|
||||||
except ValueError:
|
|
||||||
raise ValidationError('Invalid JSON received from browser')
|
|
||||||
|
|
||||||
try:
|
|
||||||
schemaValue = json.loads(self.schema.schema)
|
|
||||||
jsonschema.validate(jsonData,schemaValue) #This will raise jsonschema.ValidationError if data doesn't match schema
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
pass #halfway through creation this can cause issues
|
|
||||||
except ValueError:
|
|
||||||
raise ValidationError('Invalid JSON in schema, cannot validate')
|
|
||||||
except jsonschema.ValidationError as e: #raise a django exception
|
|
||||||
raise ValidationError('Data is not valid, cannot save: '+e.message)
|
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
"""Call :meth:`full_clean` before saving."""
|
|
||||||
self.full_clean()
|
|
||||||
super(Form, self).save(*args, **kwargs)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
string = "Form | '{}' (for {})".format(self.schema.schema_type.name, self.event)
|
|
||||||
return string
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
permissions = (
|
|
||||||
('create_form', 'Can complete a form'),
|
|
||||||
('update_form', 'Can change a form'),
|
|
||||||
('view_form', 'Can view forms'),
|
|
||||||
)
|
|
||||||
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 6.1 KiB |
103
rigForms/static/js/angular-schema-form/ObjectPath.js
vendored
103
rigForms/static/js/angular-schema-form/ObjectPath.js
vendored
@@ -1,103 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
;!function(undefined) {
|
|
||||||
|
|
||||||
var ObjectPath = {
|
|
||||||
parse: function(str){
|
|
||||||
if(typeof str !== 'string'){
|
|
||||||
throw new TypeError('ObjectPath.parse must be passed a string');
|
|
||||||
}
|
|
||||||
|
|
||||||
var i = 0;
|
|
||||||
var parts = [];
|
|
||||||
var d, b, q, c;
|
|
||||||
while (i < str.length){
|
|
||||||
d = str.indexOf('.', i);
|
|
||||||
b = str.indexOf('[', i);
|
|
||||||
|
|
||||||
// we've reached the end
|
|
||||||
if (d === -1 && b === -1){
|
|
||||||
parts.push(str.slice(i, str.length));
|
|
||||||
i = str.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
// dots
|
|
||||||
else if (b === -1 || (d !== -1 && d < b)) {
|
|
||||||
parts.push(str.slice(i, d));
|
|
||||||
i = d + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// brackets
|
|
||||||
else {
|
|
||||||
if (b > i){
|
|
||||||
parts.push(str.slice(i, b));
|
|
||||||
i = b;
|
|
||||||
}
|
|
||||||
q = str.slice(b+1, b+2);
|
|
||||||
if (q !== '"' && q !=='\'') {
|
|
||||||
c = str.indexOf(']', b);
|
|
||||||
if (c === -1) c = str.length;
|
|
||||||
parts.push(str.slice(i + 1, c));
|
|
||||||
i = (str.slice(c + 1, c + 2) === '.') ? c + 2 : c + 1;
|
|
||||||
} else {
|
|
||||||
c = str.indexOf(q+']', b);
|
|
||||||
if (c === -1) c = str.length;
|
|
||||||
while (str.slice(c - 1, c) === '\\' && b < str.length){
|
|
||||||
b++;
|
|
||||||
c = str.indexOf(q+']', b);
|
|
||||||
}
|
|
||||||
parts.push(str.slice(i + 2, c).replace(new RegExp('\\'+q,'g'), q));
|
|
||||||
i = (str.slice(c + 2, c + 3) === '.') ? c + 3 : c + 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parts;
|
|
||||||
},
|
|
||||||
|
|
||||||
// root === true : auto calculate root; must be dot-notation friendly
|
|
||||||
// root String : the string to use as root
|
|
||||||
stringify: function(arr, quote){
|
|
||||||
|
|
||||||
if(!Array.isArray(arr))
|
|
||||||
arr = [arr.toString()];
|
|
||||||
|
|
||||||
quote = quote === '"' ? '"' : '\'';
|
|
||||||
|
|
||||||
return arr.map(function(n){ return '[' + quote + (n.toString()).replace(new RegExp(quote, 'g'), '\\' + quote) + quote + ']'; }).join('');
|
|
||||||
},
|
|
||||||
|
|
||||||
normalize: function(data, quote){
|
|
||||||
return ObjectPath.stringify(Array.isArray(data) ? data : ObjectPath.parse(data), quote);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Angular
|
|
||||||
registerModule: function(angular) {
|
|
||||||
angular.module('ObjectPath', []).provider('ObjectPath', function(){
|
|
||||||
this.parse = ObjectPath.parse;
|
|
||||||
this.stringify = ObjectPath.stringify;
|
|
||||||
this.normalize = ObjectPath.normalize;
|
|
||||||
this.$get = function(){
|
|
||||||
return ObjectPath;
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// AMD
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
define(function() {
|
|
||||||
return {ObjectPath: ObjectPath};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// CommonJS
|
|
||||||
else if (typeof exports === 'object') {
|
|
||||||
exports.ObjectPath = ObjectPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Browser global
|
|
||||||
else {
|
|
||||||
window.ObjectPath = ObjectPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
}();
|
|
||||||
@@ -1,679 +0,0 @@
|
|||||||
/**
|
|
||||||
* @license AngularJS v1.3.17
|
|
||||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
|
||||||
* License: MIT
|
|
||||||
*/
|
|
||||||
(function(window, angular, undefined) {'use strict';
|
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
||||||
* Any commits to this file should be reviewed with security in mind. *
|
|
||||||
* Changes to this file can potentially create security vulnerabilities. *
|
|
||||||
* An approval from 2 Core members with history of modifying *
|
|
||||||
* this file is required. *
|
|
||||||
* *
|
|
||||||
* Does the change somehow allow for arbitrary javascript to be executed? *
|
|
||||||
* Or allows for someone to change the prototype of built-in objects? *
|
|
||||||
* Or gives undesired access to variables likes document or window? *
|
|
||||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
||||||
|
|
||||||
var $sanitizeMinErr = angular.$$minErr('$sanitize');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc module
|
|
||||||
* @name ngSanitize
|
|
||||||
* @description
|
|
||||||
*
|
|
||||||
* # ngSanitize
|
|
||||||
*
|
|
||||||
* The `ngSanitize` module provides functionality to sanitize HTML.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* <div doc-module-components="ngSanitize"></div>
|
|
||||||
*
|
|
||||||
* See {@link ngSanitize.$sanitize `$sanitize`} for usage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HTML Parser By Misko Hevery (misko@hevery.com)
|
|
||||||
* based on: HTML Parser By John Resig (ejohn.org)
|
|
||||||
* Original code by Erik Arvidsson, Mozilla Public License
|
|
||||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
|
||||||
*
|
|
||||||
* // Use like so:
|
|
||||||
* htmlParser(htmlString, {
|
|
||||||
* start: function(tag, attrs, unary) {},
|
|
||||||
* end: function(tag) {},
|
|
||||||
* chars: function(text) {},
|
|
||||||
* comment: function(text) {}
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc service
|
|
||||||
* @name $sanitize
|
|
||||||
* @kind function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
|
|
||||||
* then serialized back to properly escaped html string. This means that no unsafe input can make
|
|
||||||
* it into the returned string, however, since our parser is more strict than a typical browser
|
|
||||||
* parser, it's possible that some obscure input, which would be recognized as valid HTML by a
|
|
||||||
* browser, won't make it through the sanitizer. The input may also contain SVG markup.
|
|
||||||
* The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
|
|
||||||
* `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
|
|
||||||
*
|
|
||||||
* @param {string} html HTML input.
|
|
||||||
* @returns {string} Sanitized HTML.
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
<example module="sanitizeExample" deps="angular-sanitize.js">
|
|
||||||
<file name="index.html">
|
|
||||||
<script>
|
|
||||||
angular.module('sanitizeExample', ['ngSanitize'])
|
|
||||||
.controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
|
|
||||||
$scope.snippet =
|
|
||||||
'<p style="color:blue">an html\n' +
|
|
||||||
'<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
|
|
||||||
'snippet</p>';
|
|
||||||
$scope.deliberatelyTrustDangerousSnippet = function() {
|
|
||||||
return $sce.trustAsHtml($scope.snippet);
|
|
||||||
};
|
|
||||||
}]);
|
|
||||||
</script>
|
|
||||||
<div ng-controller="ExampleController">
|
|
||||||
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Directive</td>
|
|
||||||
<td>How</td>
|
|
||||||
<td>Source</td>
|
|
||||||
<td>Rendered</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="bind-html-with-sanitize">
|
|
||||||
<td>ng-bind-html</td>
|
|
||||||
<td>Automatically uses $sanitize</td>
|
|
||||||
<td><pre><div ng-bind-html="snippet"><br/></div></pre></td>
|
|
||||||
<td><div ng-bind-html="snippet"></div></td>
|
|
||||||
</tr>
|
|
||||||
<tr id="bind-html-with-trust">
|
|
||||||
<td>ng-bind-html</td>
|
|
||||||
<td>Bypass $sanitize by explicitly trusting the dangerous value</td>
|
|
||||||
<td>
|
|
||||||
<pre><div ng-bind-html="deliberatelyTrustDangerousSnippet()">
|
|
||||||
</div></pre>
|
|
||||||
</td>
|
|
||||||
<td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
|
|
||||||
</tr>
|
|
||||||
<tr id="bind-default">
|
|
||||||
<td>ng-bind</td>
|
|
||||||
<td>Automatically escapes</td>
|
|
||||||
<td><pre><div ng-bind="snippet"><br/></div></pre></td>
|
|
||||||
<td><div ng-bind="snippet"></div></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</file>
|
|
||||||
<file name="protractor.js" type="protractor">
|
|
||||||
it('should sanitize the html snippet by default', function() {
|
|
||||||
expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
|
|
||||||
toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should inline raw snippet if bound to a trusted value', function() {
|
|
||||||
expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
|
|
||||||
toBe("<p style=\"color:blue\">an html\n" +
|
|
||||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
|
||||||
"snippet</p>");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should escape snippet without any filter', function() {
|
|
||||||
expect(element(by.css('#bind-default div')).getInnerHtml()).
|
|
||||||
toBe("<p style=\"color:blue\">an html\n" +
|
|
||||||
"<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
|
|
||||||
"snippet</p>");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update', function() {
|
|
||||||
element(by.model('snippet')).clear();
|
|
||||||
element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
|
|
||||||
expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
|
|
||||||
toBe('new <b>text</b>');
|
|
||||||
expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
|
|
||||||
'new <b onclick="alert(1)">text</b>');
|
|
||||||
expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
|
|
||||||
"new <b onclick=\"alert(1)\">text</b>");
|
|
||||||
});
|
|
||||||
</file>
|
|
||||||
</example>
|
|
||||||
*/
|
|
||||||
function $SanitizeProvider() {
|
|
||||||
this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
|
|
||||||
return function(html) {
|
|
||||||
var buf = [];
|
|
||||||
htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
|
|
||||||
return !/^unsafe/.test($$sanitizeUri(uri, isImage));
|
|
||||||
}));
|
|
||||||
return buf.join('');
|
|
||||||
};
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeText(chars) {
|
|
||||||
var buf = [];
|
|
||||||
var writer = htmlSanitizeWriter(buf, angular.noop);
|
|
||||||
writer.chars(chars);
|
|
||||||
return buf.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Regular Expressions for parsing tags and attributes
|
|
||||||
var START_TAG_REGEXP =
|
|
||||||
/^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
|
|
||||||
END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
|
|
||||||
ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
|
|
||||||
BEGIN_TAG_REGEXP = /^</,
|
|
||||||
BEGING_END_TAGE_REGEXP = /^<\//,
|
|
||||||
COMMENT_REGEXP = /<!--(.*?)-->/g,
|
|
||||||
DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
|
|
||||||
CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
|
|
||||||
SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
|
|
||||||
// Match everything outside of normal chars and " (quote character)
|
|
||||||
NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
|
|
||||||
|
|
||||||
|
|
||||||
// Good source of info about elements and attributes
|
|
||||||
// http://dev.w3.org/html5/spec/Overview.html#semantics
|
|
||||||
// http://simon.html5.org/html-elements
|
|
||||||
|
|
||||||
// Safe Void Elements - HTML5
|
|
||||||
// http://dev.w3.org/html5/spec/Overview.html#void-elements
|
|
||||||
var voidElements = makeMap("area,br,col,hr,img,wbr");
|
|
||||||
|
|
||||||
// Elements that you can, intentionally, leave open (and which close themselves)
|
|
||||||
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
|
|
||||||
var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
|
|
||||||
optionalEndTagInlineElements = makeMap("rp,rt"),
|
|
||||||
optionalEndTagElements = angular.extend({},
|
|
||||||
optionalEndTagInlineElements,
|
|
||||||
optionalEndTagBlockElements);
|
|
||||||
|
|
||||||
// Safe Block Elements - HTML5
|
|
||||||
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
|
|
||||||
"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
|
|
||||||
"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
|
|
||||||
|
|
||||||
// Inline Elements - HTML5
|
|
||||||
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
|
|
||||||
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
|
|
||||||
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
|
|
||||||
|
|
||||||
// SVG Elements
|
|
||||||
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
|
|
||||||
var svgElements = makeMap("animate,animateColor,animateMotion,animateTransform,circle,defs," +
|
|
||||||
"desc,ellipse,font-face,font-face-name,font-face-src,g,glyph,hkern,image,linearGradient," +
|
|
||||||
"line,marker,metadata,missing-glyph,mpath,path,polygon,polyline,radialGradient,rect,set," +
|
|
||||||
"stop,svg,switch,text,title,tspan,use");
|
|
||||||
|
|
||||||
// Special Elements (can contain anything)
|
|
||||||
var specialElements = makeMap("script,style");
|
|
||||||
|
|
||||||
var validElements = angular.extend({},
|
|
||||||
voidElements,
|
|
||||||
blockElements,
|
|
||||||
inlineElements,
|
|
||||||
optionalEndTagElements,
|
|
||||||
svgElements);
|
|
||||||
|
|
||||||
//Attributes that have href and hence need to be sanitized
|
|
||||||
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
|
|
||||||
|
|
||||||
var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
|
|
||||||
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
|
|
||||||
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
|
|
||||||
'scope,scrolling,shape,size,span,start,summary,target,title,type,' +
|
|
||||||
'valign,value,vspace,width');
|
|
||||||
|
|
||||||
// SVG attributes (without "id" and "name" attributes)
|
|
||||||
// https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
|
|
||||||
var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
|
|
||||||
'attributeName,attributeType,baseProfile,bbox,begin,by,calcMode,cap-height,class,color,' +
|
|
||||||
'color-rendering,content,cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,' +
|
|
||||||
'font-size,font-stretch,font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,' +
|
|
||||||
'gradientUnits,hanging,height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,' +
|
|
||||||
'keySplines,keyTimes,lang,marker-end,marker-mid,marker-start,markerHeight,markerUnits,' +
|
|
||||||
'markerWidth,mathematical,max,min,offset,opacity,orient,origin,overline-position,' +
|
|
||||||
'overline-thickness,panose-1,path,pathLength,points,preserveAspectRatio,r,refX,refY,' +
|
|
||||||
'repeatCount,repeatDur,requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,' +
|
|
||||||
'stemv,stop-color,stop-opacity,strikethrough-position,strikethrough-thickness,stroke,' +
|
|
||||||
'stroke-dasharray,stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,' +
|
|
||||||
'stroke-opacity,stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,' +
|
|
||||||
'underline-position,underline-thickness,unicode,unicode-range,units-per-em,values,version,' +
|
|
||||||
'viewBox,visibility,width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,' +
|
|
||||||
'xlink:show,xlink:title,xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,' +
|
|
||||||
'zoomAndPan');
|
|
||||||
|
|
||||||
var validAttrs = angular.extend({},
|
|
||||||
uriAttrs,
|
|
||||||
svgAttrs,
|
|
||||||
htmlAttrs);
|
|
||||||
|
|
||||||
function makeMap(str) {
|
|
||||||
var obj = {}, items = str.split(','), i;
|
|
||||||
for (i = 0; i < items.length; i++) obj[items[i]] = true;
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @example
|
|
||||||
* htmlParser(htmlString, {
|
|
||||||
* start: function(tag, attrs, unary) {},
|
|
||||||
* end: function(tag) {},
|
|
||||||
* chars: function(text) {},
|
|
||||||
* comment: function(text) {}
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* @param {string} html string
|
|
||||||
* @param {object} handler
|
|
||||||
*/
|
|
||||||
function htmlParser(html, handler) {
|
|
||||||
if (typeof html !== 'string') {
|
|
||||||
if (html === null || typeof html === 'undefined') {
|
|
||||||
html = '';
|
|
||||||
} else {
|
|
||||||
html = '' + html;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var index, chars, match, stack = [], last = html, text;
|
|
||||||
stack.last = function() { return stack[stack.length - 1]; };
|
|
||||||
|
|
||||||
while (html) {
|
|
||||||
text = '';
|
|
||||||
chars = true;
|
|
||||||
|
|
||||||
// Make sure we're not in a script or style element
|
|
||||||
if (!stack.last() || !specialElements[stack.last()]) {
|
|
||||||
|
|
||||||
// Comment
|
|
||||||
if (html.indexOf("<!--") === 0) {
|
|
||||||
// comments containing -- are not allowed unless they terminate the comment
|
|
||||||
index = html.indexOf("--", 4);
|
|
||||||
|
|
||||||
if (index >= 0 && html.lastIndexOf("-->", index) === index) {
|
|
||||||
if (handler.comment) handler.comment(html.substring(4, index));
|
|
||||||
html = html.substring(index + 3);
|
|
||||||
chars = false;
|
|
||||||
}
|
|
||||||
// DOCTYPE
|
|
||||||
} else if (DOCTYPE_REGEXP.test(html)) {
|
|
||||||
match = html.match(DOCTYPE_REGEXP);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
html = html.replace(match[0], '');
|
|
||||||
chars = false;
|
|
||||||
}
|
|
||||||
// end tag
|
|
||||||
} else if (BEGING_END_TAGE_REGEXP.test(html)) {
|
|
||||||
match = html.match(END_TAG_REGEXP);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
html = html.substring(match[0].length);
|
|
||||||
match[0].replace(END_TAG_REGEXP, parseEndTag);
|
|
||||||
chars = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start tag
|
|
||||||
} else if (BEGIN_TAG_REGEXP.test(html)) {
|
|
||||||
match = html.match(START_TAG_REGEXP);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
// We only have a valid start-tag if there is a '>'.
|
|
||||||
if (match[4]) {
|
|
||||||
html = html.substring(match[0].length);
|
|
||||||
match[0].replace(START_TAG_REGEXP, parseStartTag);
|
|
||||||
}
|
|
||||||
chars = false;
|
|
||||||
} else {
|
|
||||||
// no ending tag found --- this piece should be encoded as an entity.
|
|
||||||
text += '<';
|
|
||||||
html = html.substring(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (chars) {
|
|
||||||
index = html.indexOf("<");
|
|
||||||
|
|
||||||
text += index < 0 ? html : html.substring(0, index);
|
|
||||||
html = index < 0 ? "" : html.substring(index);
|
|
||||||
|
|
||||||
if (handler.chars) handler.chars(decodeEntities(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w].
|
|
||||||
html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
|
|
||||||
function(all, text) {
|
|
||||||
text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
|
|
||||||
|
|
||||||
if (handler.chars) handler.chars(decodeEntities(text));
|
|
||||||
|
|
||||||
return "";
|
|
||||||
});
|
|
||||||
|
|
||||||
parseEndTag("", stack.last());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (html == last) {
|
|
||||||
throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
|
|
||||||
"of html: {0}", html);
|
|
||||||
}
|
|
||||||
last = html;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up any remaining tags
|
|
||||||
parseEndTag();
|
|
||||||
|
|
||||||
function parseStartTag(tag, tagName, rest, unary) {
|
|
||||||
tagName = angular.lowercase(tagName);
|
|
||||||
if (blockElements[tagName]) {
|
|
||||||
while (stack.last() && inlineElements[stack.last()]) {
|
|
||||||
parseEndTag("", stack.last());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optionalEndTagElements[tagName] && stack.last() == tagName) {
|
|
||||||
parseEndTag("", tagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
unary = voidElements[tagName] || !!unary;
|
|
||||||
|
|
||||||
if (!unary)
|
|
||||||
stack.push(tagName);
|
|
||||||
|
|
||||||
var attrs = {};
|
|
||||||
|
|
||||||
rest.replace(ATTR_REGEXP,
|
|
||||||
function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
|
|
||||||
var value = doubleQuotedValue
|
|
||||||
|| singleQuotedValue
|
|
||||||
|| unquotedValue
|
|
||||||
|| '';
|
|
||||||
|
|
||||||
attrs[name] = decodeEntities(value);
|
|
||||||
});
|
|
||||||
if (handler.start) handler.start(tagName, attrs, unary);
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseEndTag(tag, tagName) {
|
|
||||||
var pos = 0, i;
|
|
||||||
tagName = angular.lowercase(tagName);
|
|
||||||
if (tagName)
|
|
||||||
// Find the closest opened tag of the same type
|
|
||||||
for (pos = stack.length - 1; pos >= 0; pos--)
|
|
||||||
if (stack[pos] == tagName)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (pos >= 0) {
|
|
||||||
// Close all the open elements, up the stack
|
|
||||||
for (i = stack.length - 1; i >= pos; i--)
|
|
||||||
if (handler.end) handler.end(stack[i]);
|
|
||||||
|
|
||||||
// Remove the open elements from the stack
|
|
||||||
stack.length = pos;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var hiddenPre=document.createElement("pre");
|
|
||||||
/**
|
|
||||||
* decodes all entities into regular string
|
|
||||||
* @param value
|
|
||||||
* @returns {string} A string with decoded entities.
|
|
||||||
*/
|
|
||||||
function decodeEntities(value) {
|
|
||||||
if (!value) { return ''; }
|
|
||||||
|
|
||||||
hiddenPre.innerHTML = value.replace(/</g,"<");
|
|
||||||
// innerText depends on styling as it doesn't display hidden elements.
|
|
||||||
// Therefore, it's better to use textContent not to cause unnecessary reflows.
|
|
||||||
return hiddenPre.textContent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Escapes all potentially dangerous characters, so that the
|
|
||||||
* resulting string can be safely inserted into attribute or
|
|
||||||
* element text.
|
|
||||||
* @param value
|
|
||||||
* @returns {string} escaped text
|
|
||||||
*/
|
|
||||||
function encodeEntities(value) {
|
|
||||||
return value.
|
|
||||||
replace(/&/g, '&').
|
|
||||||
replace(SURROGATE_PAIR_REGEXP, function(value) {
|
|
||||||
var hi = value.charCodeAt(0);
|
|
||||||
var low = value.charCodeAt(1);
|
|
||||||
return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
|
|
||||||
}).
|
|
||||||
replace(NON_ALPHANUMERIC_REGEXP, function(value) {
|
|
||||||
return '&#' + value.charCodeAt(0) + ';';
|
|
||||||
}).
|
|
||||||
replace(/</g, '<').
|
|
||||||
replace(/>/g, '>');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create an HTML/XML writer which writes to buffer
|
|
||||||
* @param {Array} buf use buf.jain('') to get out sanitized html string
|
|
||||||
* @returns {object} in the form of {
|
|
||||||
* start: function(tag, attrs, unary) {},
|
|
||||||
* end: function(tag) {},
|
|
||||||
* chars: function(text) {},
|
|
||||||
* comment: function(text) {}
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
function htmlSanitizeWriter(buf, uriValidator) {
|
|
||||||
var ignore = false;
|
|
||||||
var out = angular.bind(buf, buf.push);
|
|
||||||
return {
|
|
||||||
start: function(tag, attrs, unary) {
|
|
||||||
tag = angular.lowercase(tag);
|
|
||||||
if (!ignore && specialElements[tag]) {
|
|
||||||
ignore = tag;
|
|
||||||
}
|
|
||||||
if (!ignore && validElements[tag] === true) {
|
|
||||||
out('<');
|
|
||||||
out(tag);
|
|
||||||
angular.forEach(attrs, function(value, key) {
|
|
||||||
var lkey=angular.lowercase(key);
|
|
||||||
var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
|
|
||||||
if (validAttrs[lkey] === true &&
|
|
||||||
(uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
|
|
||||||
out(' ');
|
|
||||||
out(key);
|
|
||||||
out('="');
|
|
||||||
out(encodeEntities(value));
|
|
||||||
out('"');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
out(unary ? '/>' : '>');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
end: function(tag) {
|
|
||||||
tag = angular.lowercase(tag);
|
|
||||||
if (!ignore && validElements[tag] === true) {
|
|
||||||
out('</');
|
|
||||||
out(tag);
|
|
||||||
out('>');
|
|
||||||
}
|
|
||||||
if (tag == ignore) {
|
|
||||||
ignore = false;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
chars: function(chars) {
|
|
||||||
if (!ignore) {
|
|
||||||
out(encodeEntities(chars));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// define ngSanitize module and register $sanitize service
|
|
||||||
angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
|
|
||||||
|
|
||||||
/* global sanitizeText: false */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ngdoc filter
|
|
||||||
* @name linky
|
|
||||||
* @kind function
|
|
||||||
*
|
|
||||||
* @description
|
|
||||||
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
|
|
||||||
* plain email address links.
|
|
||||||
*
|
|
||||||
* Requires the {@link ngSanitize `ngSanitize`} module to be installed.
|
|
||||||
*
|
|
||||||
* @param {string} text Input text.
|
|
||||||
* @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
|
|
||||||
* @returns {string} Html-linkified text.
|
|
||||||
*
|
|
||||||
* @usage
|
|
||||||
<span ng-bind-html="linky_expression | linky"></span>
|
|
||||||
*
|
|
||||||
* @example
|
|
||||||
<example module="linkyExample" deps="angular-sanitize.js">
|
|
||||||
<file name="index.html">
|
|
||||||
<script>
|
|
||||||
angular.module('linkyExample', ['ngSanitize'])
|
|
||||||
.controller('ExampleController', ['$scope', function($scope) {
|
|
||||||
$scope.snippet =
|
|
||||||
'Pretty text with some links:\n'+
|
|
||||||
'http://angularjs.org/,\n'+
|
|
||||||
'mailto:us@somewhere.org,\n'+
|
|
||||||
'another@somewhere.org,\n'+
|
|
||||||
'and one more: ftp://127.0.0.1/.';
|
|
||||||
$scope.snippetWithTarget = 'http://angularjs.org/';
|
|
||||||
}]);
|
|
||||||
</script>
|
|
||||||
<div ng-controller="ExampleController">
|
|
||||||
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Filter</td>
|
|
||||||
<td>Source</td>
|
|
||||||
<td>Rendered</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="linky-filter">
|
|
||||||
<td>linky filter</td>
|
|
||||||
<td>
|
|
||||||
<pre><div ng-bind-html="snippet | linky"><br></div></pre>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div ng-bind-html="snippet | linky"></div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="linky-target">
|
|
||||||
<td>linky target</td>
|
|
||||||
<td>
|
|
||||||
<pre><div ng-bind-html="snippetWithTarget | linky:'_blank'"><br></div></pre>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr id="escaped-html">
|
|
||||||
<td>no filter</td>
|
|
||||||
<td><pre><div ng-bind="snippet"><br></div></pre></td>
|
|
||||||
<td><div ng-bind="snippet"></div></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</file>
|
|
||||||
<file name="protractor.js" type="protractor">
|
|
||||||
it('should linkify the snippet with urls', function() {
|
|
||||||
expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
|
|
||||||
toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
|
|
||||||
'another@somewhere.org, and one more: ftp://127.0.0.1/.');
|
|
||||||
expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not linkify snippet without the linky filter', function() {
|
|
||||||
expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
|
|
||||||
toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
|
|
||||||
'another@somewhere.org, and one more: ftp://127.0.0.1/.');
|
|
||||||
expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update', function() {
|
|
||||||
element(by.model('snippet')).clear();
|
|
||||||
element(by.model('snippet')).sendKeys('new http://link.');
|
|
||||||
expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
|
|
||||||
toBe('new http://link.');
|
|
||||||
expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
|
|
||||||
expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
|
|
||||||
.toBe('new http://link.');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should work with the target property', function() {
|
|
||||||
expect(element(by.id('linky-target')).
|
|
||||||
element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
|
|
||||||
toBe('http://angularjs.org/');
|
|
||||||
expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
|
|
||||||
});
|
|
||||||
</file>
|
|
||||||
</example>
|
|
||||||
*/
|
|
||||||
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
|
|
||||||
var LINKY_URL_REGEXP =
|
|
||||||
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/i,
|
|
||||||
MAILTO_REGEXP = /^mailto:/i;
|
|
||||||
|
|
||||||
return function(text, target) {
|
|
||||||
if (!text) return text;
|
|
||||||
var match;
|
|
||||||
var raw = text;
|
|
||||||
var html = [];
|
|
||||||
var url;
|
|
||||||
var i;
|
|
||||||
while ((match = raw.match(LINKY_URL_REGEXP))) {
|
|
||||||
// We can not end in these as they are sometimes found at the end of the sentence
|
|
||||||
url = match[0];
|
|
||||||
// if we did not match ftp/http/www/mailto then assume mailto
|
|
||||||
if (!match[2] && !match[4]) {
|
|
||||||
url = (match[3] ? 'http://' : 'mailto:') + url;
|
|
||||||
}
|
|
||||||
i = match.index;
|
|
||||||
addText(raw.substr(0, i));
|
|
||||||
addLink(url, match[0].replace(MAILTO_REGEXP, ''));
|
|
||||||
raw = raw.substring(i + match[0].length);
|
|
||||||
}
|
|
||||||
addText(raw);
|
|
||||||
return $sanitize(html.join(''));
|
|
||||||
|
|
||||||
function addText(text) {
|
|
||||||
if (!text) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
html.push(sanitizeText(text));
|
|
||||||
}
|
|
||||||
|
|
||||||
function addLink(url, text) {
|
|
||||||
html.push('<a ');
|
|
||||||
if (angular.isDefined(target)) {
|
|
||||||
html.push('target="',
|
|
||||||
target,
|
|
||||||
'" ');
|
|
||||||
}
|
|
||||||
html.push('href="',
|
|
||||||
url.replace(/"/g, '"'),
|
|
||||||
'">');
|
|
||||||
addText(text);
|
|
||||||
html.push('</a>');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}]);
|
|
||||||
|
|
||||||
|
|
||||||
})(window, window.angular);
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
/*
|
|
||||||
AngularJS v1.4.3
|
|
||||||
(c) 2010-2015 Google, Inc. http://angularjs.org
|
|
||||||
License: MIT
|
|
||||||
*/
|
|
||||||
(function(O,U,t){'use strict';function J(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.4.3/"+(b?b+"/":"")+a;for(a=1;a<arguments.length;a++){c=c+(1==a?"?":"&")+"p"+(a-1)+"=";var d=encodeURIComponent,e;e=arguments[a];e="function"==typeof e?e.toString().replace(/ \{[\s\S]*$/,""):"undefined"==typeof e?"undefined":"string"!=typeof e?JSON.stringify(e):e;c+=d(e)}return Error(c)}}function Ea(b){if(null==b||Wa(b))return!1;var a="length"in Object(b)&&b.length;
|
|
||||||
return b.nodeType===qa&&a?!0:L(b)||G(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function m(b,a,c){var d,e;if(b)if(z(b))for(d in b)"prototype"==d||"length"==d||"name"==d||b.hasOwnProperty&&!b.hasOwnProperty(d)||a.call(c,b[d],d,b);else if(G(b)||Ea(b)){var f="object"!==typeof b;d=0;for(e=b.length;d<e;d++)(f||d in b)&&a.call(c,b[d],d,b)}else if(b.forEach&&b.forEach!==m)b.forEach(a,c,b);else if(nc(b))for(d in b)a.call(c,b[d],d,b);else if("function"===typeof b.hasOwnProperty)for(d in b)b.hasOwnProperty(d)&&
|
|
||||||
a.call(c,b[d],d,b);else for(d in b)Xa.call(b,d)&&a.call(c,b[d],d,b);return b}function oc(b,a,c){for(var d=Object.keys(b).sort(),e=0;e<d.length;e++)a.call(c,b[d[e]],d[e]);return d}function pc(b){return function(a,c){b(c,a)}}function Ud(){return++nb}function qc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function Nb(b,a,c){for(var d=b.$$hashKey,e=0,f=a.length;e<f;++e){var g=a[e];if(H(g)||z(g))for(var h=Object.keys(g),l=0,k=h.length;l<k;l++){var n=h[l],r=g[n];c&&H(r)?aa(r)?b[n]=new Date(r.valueOf()):(H(b[n])||
|
|
||||||
(b[n]=G(r)?[]:{}),Nb(b[n],[r],!0)):b[n]=r}}qc(b,d);return b}function P(b){return Nb(b,za.call(arguments,1),!1)}function Vd(b){return Nb(b,za.call(arguments,1),!0)}function W(b){return parseInt(b,10)}function Ob(b,a){return P(Object.create(b),a)}function v(){}function Ya(b){return b}function ra(b){return function(){return b}}function rc(b){return z(b.toString)&&b.toString!==Object.prototype.toString}function A(b){return"undefined"===typeof b}function w(b){return"undefined"!==typeof b}function H(b){return null!==
|
|
||||||
b&&"object"===typeof b}function nc(b){return null!==b&&"object"===typeof b&&!sc(b)}function L(b){return"string"===typeof b}function V(b){return"number"===typeof b}function aa(b){return"[object Date]"===sa.call(b)}function z(b){return"function"===typeof b}function Za(b){return"[object RegExp]"===sa.call(b)}function Wa(b){return b&&b.window===b}function $a(b){return b&&b.$evalAsync&&b.$watch}function ab(b){return"boolean"===typeof b}function tc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))}
|
|
||||||
function Wd(b){var a={};b=b.split(",");var c;for(c=0;c<b.length;c++)a[b[c]]=!0;return a}function ta(b){return M(b.nodeName||b[0]&&b[0].nodeName)}function bb(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return c}function fa(b,a,c,d){if(Wa(b)||$a(b))throw Fa("cpws");if(uc.test(sa.call(a)))throw Fa("cpta");if(a){if(b===a)throw Fa("cpi");c=c||[];d=d||[];H(b)&&(c.push(b),d.push(a));var e;if(G(b))for(e=a.length=0;e<b.length;e++)a.push(fa(b[e],null,c,d));else{var f=a.$$hashKey;G(a)?a.length=0:m(a,function(b,
|
|
||||||
c){delete a[c]});if(nc(b))for(e in b)a[e]=fa(b[e],null,c,d);else if(b&&"function"===typeof b.hasOwnProperty)for(e in b)b.hasOwnProperty(e)&&(a[e]=fa(b[e],null,c,d));else for(e in b)Xa.call(b,e)&&(a[e]=fa(b[e],null,c,d));qc(a,f)}}else if(a=b,H(b)){if(c&&-1!==(f=c.indexOf(b)))return d[f];if(G(b))return fa(b,[],c,d);if(uc.test(sa.call(b)))a=new b.constructor(b);else if(aa(b))a=new Date(b.getTime());else if(Za(b))a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex;else return e=
|
|
||||||
Object.create(sc(b)),fa(b,e,c,d);d&&(c.push(b),d.push(a))}return a}function ia(b,a){if(G(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(H(b))for(c in a=a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=b[c];return a||b}function ka(b,a){if(b===a)return!0;if(null===b||null===a)return!1;if(b!==b&&a!==a)return!0;var c=typeof b,d;if(c==typeof a&&"object"==c)if(G(b)){if(!G(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!ka(b[d],a[d]))return!1;return!0}}else{if(aa(b))return aa(a)?
|
|
||||||
ka(b.getTime(),a.getTime()):!1;if(Za(b))return Za(a)?b.toString()==a.toString():!1;if($a(b)||$a(a)||Wa(b)||Wa(a)||G(a)||aa(a)||Za(a))return!1;c=ga();for(d in b)if("$"!==d.charAt(0)&&!z(b[d])){if(!ka(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!(d in c||"$"===d.charAt(0)||a[d]===t||z(a[d])))return!1;return!0}return!1}function cb(b,a,c){return b.concat(za.call(a,c))}function vc(b,a){var c=2<arguments.length?za.call(arguments,2):[];return!z(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?
|
|
||||||
a.apply(b,cb(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Xd(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)?c=t:Wa(a)?c="$WINDOW":a&&U===a?c="$DOCUMENT":$a(a)&&(c="$SCOPE");return c}function db(b,a){if("undefined"===typeof b)return t;V(a)||(a=a?2:null);return JSON.stringify(b,Xd,a)}function wc(b){return L(b)?JSON.parse(b):b}function xc(b,a){var c=Date.parse("Jan 01, 1970 00:00:00 "+b)/6E4;return isNaN(c)?a:c}function Pb(b,
|
|
||||||
a,c){c=c?-1:1;var d=xc(a,b.getTimezoneOffset());a=b;b=c*(d-b.getTimezoneOffset());a=new Date(a.getTime());a.setMinutes(a.getMinutes()+b);return a}function ua(b){b=y(b).clone();try{b.empty()}catch(a){}var c=y("<div>").append(b).html();try{return b[0].nodeType===Na?M(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+M(b)})}catch(d){return M(c)}}function yc(b){try{return decodeURIComponent(b)}catch(a){}}function zc(b){var a={},c,d;m((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,
|
|
||||||
"%20").split("="),d=yc(c[0]),w(d)&&(b=w(c[1])?yc(c[1]):!0,Xa.call(a,d)?G(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Qb(b){var a=[];m(b,function(b,d){G(b)?m(b,function(b){a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))}):a.push(ma(d,!0)+(!0===b?"":"="+ma(b,!0)))});return a.length?a.join("&"):""}function ob(b){return ma(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function ma(b,a){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,
|
|
||||||
"$").replace(/%2C/gi,",").replace(/%3B/gi,";").replace(/%20/g,a?"%20":"+")}function Yd(b,a){var c,d,e=Oa.length;for(d=0;d<e;++d)if(c=Oa[d]+a,L(c=b.getAttribute(c)))return c;return null}function Zd(b,a){var c,d,e={};m(Oa,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});m(Oa,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Yd(c,"strict-di"),a(c,d?[d]:[],e))}function Ac(b,a,c){H(c)||
|
|
||||||
(c={});c=P({strictDi:!1},c);var d=function(){b=y(b);if(b.injector()){var d=b[0]===U?"document":ua(b);throw Fa("btstrpd",d.replace(/</,"<").replace(/>/,">"));}a=a||[];a.unshift(["$provide",function(a){a.value("$rootElement",b)}]);c.debugInfoEnabled&&a.push(["$compileProvider",function(a){a.debugInfoEnabled(!0)}]);a.unshift("ng");d=eb(a,c.strictDi);d.invoke(["$rootScope","$rootElement","$compile","$injector",function(a,b,c,d){a.$apply(function(){b.data("$injector",d);c(b)(a)})}]);return d},e=
|
|
||||||
/^NG_ENABLE_DEBUG_INFO!/,f=/^NG_DEFER_BOOTSTRAP!/;O&&e.test(O.name)&&(c.debugInfoEnabled=!0,O.name=O.name.replace(e,""));if(O&&!f.test(O.name))return d();O.name=O.name.replace(f,"");ca.resumeBootstrap=function(b){m(b,function(b){a.push(b)});return d()};z(ca.resumeDeferredBootstrap)&&ca.resumeDeferredBootstrap()}function $d(){O.name="NG_ENABLE_DEBUG_INFO!"+O.name;O.location.reload()}function ae(b){b=ca.element(b).injector();if(!b)throw Fa("test");return b.get("$$testability")}function Bc(b,a){a=a||
|
|
||||||
"_";return b.replace(be,function(b,d){return(d?a:"")+b.toLowerCase()})}function ce(){var b;if(!Cc){var a=pb();la=O.jQuery;w(a)&&(la=null===a?t:O[a]);la&&la.fn.on?(y=la,P(la.fn,{scope:Pa.scope,isolateScope:Pa.isolateScope,controller:Pa.controller,injector:Pa.injector,inheritedData:Pa.inheritedData}),b=la.cleanData,la.cleanData=function(a){var d;if(Rb)Rb=!1;else for(var e=0,f;null!=(f=a[e]);e++)(d=la._data(f,"events"))&&d.$destroy&&la(f).triggerHandler("$destroy");b(a)}):y=Q;ca.element=y;Cc=!0}}function Sb(b,
|
|
||||||
a,c){if(!b)throw Fa("areq",a||"?",c||"required");return b}function Qa(b,a,c){c&&G(b)&&(b=b[b.length-1]);Sb(z(b),a,"not a function, got "+(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function Ra(b,a){if("hasOwnProperty"===b)throw Fa("badname",a);}function Dc(b,a,c){if(!a)return b;a=a.split(".");for(var d,e=b,f=a.length,g=0;g<f;g++)d=a[g],b&&(b=(e=b)[d]);return!c&&z(b)?vc(e,b):b}function qb(b){var a=b[0];b=b[b.length-1];var c=[a];do{a=a.nextSibling;if(!a)break;c.push(a)}while(a!==
|
|
||||||
b);return y(c)}function ga(){return Object.create(null)}function de(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=J("$injector"),d=J("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||J;return a(b,"module",function(){var b={};return function(f,g,h){if("hasOwnProperty"===f)throw d("badname","module");g&&b.hasOwnProperty(f)&&(b[f]=null);return a(b,f,function(){function a(b,c,e,f){f||(f=d);return function(){f[e||"push"]([b,c,arguments]);return C}}function b(a,c){return function(b,e){e&&z(e)&&
|
|
||||||
(e.$$moduleName=f);d.push([a,c,arguments]);return C}}if(!g)throw c("nomod",f);var d=[],e=[],s=[],x=a("$injector","invoke","push",e),C={_invokeQueue:d,_configBlocks:e,_runBlocks:s,requires:g,name:f,provider:b("$provide","provider"),factory:b("$provide","factory"),service:b("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),decorator:b("$provide","decorator"),animation:b("$animateProvider","register"),filter:b("$filterProvider","register"),controller:b("$controllerProvider",
|
|
||||||
"register"),directive:b("$compileProvider","directive"),config:x,run:function(a){s.push(a);return this}};h&&x(h);return C})}})}function ee(b){P(b,{bootstrap:Ac,copy:fa,extend:P,merge:Vd,equals:ka,element:y,forEach:m,injector:eb,noop:v,bind:vc,toJson:db,fromJson:wc,identity:Ya,isUndefined:A,isDefined:w,isString:L,isFunction:z,isObject:H,isNumber:V,isElement:tc,isArray:G,version:fe,isDate:aa,lowercase:M,uppercase:rb,callbacks:{counter:0},getTestability:ae,$$minErr:J,$$csp:fb,reloadWithDebugInfo:$d});
|
|
||||||
gb=de(O);try{gb("ngLocale")}catch(a){gb("ngLocale",[]).provider("$locale",ge)}gb("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:he});a.provider("$compile",Ec).directive({a:ie,input:Fc,textarea:Fc,form:je,script:ke,select:le,style:me,option:ne,ngBind:oe,ngBindHtml:pe,ngBindTemplate:qe,ngClass:re,ngClassEven:se,ngClassOdd:te,ngCloak:ue,ngController:ve,ngForm:we,ngHide:xe,ngIf:ye,ngInclude:ze,ngInit:Ae,ngNonBindable:Be,ngPluralize:Ce,ngRepeat:De,ngShow:Ee,ngStyle:Fe,ngSwitch:Ge,
|
|
||||||
ngSwitchWhen:He,ngSwitchDefault:Ie,ngOptions:Je,ngTransclude:Ke,ngModel:Le,ngList:Me,ngChange:Ne,pattern:Gc,ngPattern:Gc,required:Hc,ngRequired:Hc,minlength:Ic,ngMinlength:Ic,maxlength:Jc,ngMaxlength:Jc,ngValue:Oe,ngModelOptions:Pe}).directive({ngInclude:Qe}).directive(sb).directive(Kc);a.provider({$anchorScroll:Re,$animate:Se,$$animateQueue:Te,$$AnimateRunner:Ue,$browser:Ve,$cacheFactory:We,$controller:Xe,$document:Ye,$exceptionHandler:Ze,$filter:Lc,$interpolate:$e,$interval:af,$http:bf,$httpParamSerializer:cf,
|
|
||||||
$httpParamSerializerJQLike:df,$httpBackend:ef,$location:ff,$log:gf,$parse:hf,$rootScope:jf,$q:kf,$$q:lf,$sce:mf,$sceDelegate:nf,$sniffer:of,$templateCache:pf,$templateRequest:qf,$$testability:rf,$timeout:sf,$window:tf,$$rAF:uf,$$jqLite:vf,$$HashMap:wf,$$cookieReader:xf})}])}function hb(b){return b.replace(yf,function(a,b,d,e){return e?d.toUpperCase():d}).replace(zf,"Moz$1")}function Mc(b){b=b.nodeType;return b===qa||!b||9===b}function Nc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Tb.test(b)){c=
|
|
||||||
c||e.appendChild(a.createElement("div"));d=(Af.exec(b)||["",""])[1].toLowerCase();d=na[d]||na._default;c.innerHTML=d[1]+b.replace(Bf,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=cb(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";m(f,function(a){e.appendChild(a)});return e}function Q(b){if(b instanceof Q)return b;var a;L(b)&&(b=R(b),a=!0);if(!(this instanceof Q)){if(a&&"<"!=b.charAt(0))throw Ub("nosel");return new Q(b)}if(a){a=U;
|
|
||||||
var c;b=(c=Cf.exec(b))?[a.createElement(c[1])]:(c=Nc(b,a))?c.childNodes:[]}Oc(this,b)}function Vb(b){return b.cloneNode(!0)}function tb(b,a){a||ub(b);if(b.querySelectorAll)for(var c=b.querySelectorAll("*"),d=0,e=c.length;d<e;d++)ub(c[d])}function Pc(b,a,c,d){if(w(d))throw Ub("offargs");var e=(d=vb(b))&&d.events,f=d&&d.handle;if(f)if(a)m(a.split(" "),function(a){if(w(c)){var d=e[a];bb(d||[],c);if(d&&0<d.length)return}b.removeEventListener(a,f,!1);delete e[a]});else for(a in e)"$destroy"!==a&&b.removeEventListener(a,
|
|
||||||
f,!1),delete e[a]}function ub(b,a){var c=b.ng339,d=c&&ib[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Pc(b)),delete ib[c],b.ng339=t))}function vb(b,a){var c=b.ng339,c=c&&ib[c];a&&!c&&(b.ng339=c=++Df,c=ib[c]={events:{},data:{},handle:t});return c}function Wb(b,a,c){if(Mc(b)){var d=w(c),e=!d&&a&&!H(a),f=!a;b=(b=vb(b,!e))&&b.data;if(d)b[a]=c;else{if(f)return b;if(e)return b&&b[a];P(b,a)}}}function wb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+
|
|
||||||
" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function xb(b,a){a&&b.setAttribute&&m(a.split(" "),function(a){b.setAttribute("class",R((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+R(a)+" "," ")))})}function yb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");m(a.split(" "),function(a){a=R(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",R(c))}}function Oc(b,a){if(a)if(a.nodeType)b[b.length++]=a;else{var c=
|
|
||||||
a.length;if("number"===typeof c&&a.window!==a){if(c)for(var d=0;d<c;d++)b[b.length++]=a[d]}else b[b.length++]=a}}function Qc(b,a){return zb(b,"$"+(a||"ngController")+"Controller")}function zb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=G(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=y.data(b,a[d]))!==t)return c;b=b.parentNode||11===b.nodeType&&b.host}}function Rc(b){for(tb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}function Xb(b,a){a||tb(b);var c=b.parentNode;c&&c.removeChild(b)}function Ef(b,
|
|
||||||
a){a=a||O;if("complete"===a.document.readyState)a.setTimeout(b);else y(a).on("load",b)}function Sc(b,a){var c=Ab[a.toLowerCase()];return c&&Tc[ta(b)]&&c}function Ff(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Uc[a]}function Gf(b,a){var c=function(c,e){c.isDefaultPrevented=function(){return c.defaultPrevented};var f=a[e||c.type],g=f?f.length:0;if(g){if(A(c.immediatePropagationStopped)){var h=c.stopImmediatePropagation;c.stopImmediatePropagation=function(){c.immediatePropagationStopped=
|
|
||||||
!0;c.stopPropagation&&c.stopPropagation();h&&h.call(c)}}c.isImmediatePropagationStopped=function(){return!0===c.immediatePropagationStopped};1<g&&(f=ia(f));for(var l=0;l<g;l++)c.isImmediatePropagationStopped()||f[l].call(b,c)}};c.elem=b;return c}function vf(){this.$get=function(){return P(Q,{hasClass:function(b,a){b.attr&&(b=b[0]);return wb(b,a)},addClass:function(b,a){b.attr&&(b=b[0]);return yb(b,a)},removeClass:function(b,a){b.attr&&(b=b[0]);return xb(b,a)}})}}function Ga(b,a){var c=b&&b.$$hashKey;
|
|
||||||
if(c)return"function"===typeof c&&(c=b.$$hashKey()),c;c=typeof b;return c="function"==c||"object"==c&&null!==b?b.$$hashKey=c+":"+(a||Ud)():c+":"+b}function Sa(b,a){if(a){var c=0;this.nextUid=function(){return++c}}m(b,this.put,this)}function Hf(b){return(b=b.toString().replace(Vc,"").match(Wc))?"function("+(b[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function eb(b,a){function c(a){return function(b,c){if(H(b))m(b,pc(a));else return a(b,c)}}function d(a,b){Ra(a,"service");if(z(b)||G(b))b=s.instantiate(b);
|
|
||||||
if(!b.$get)throw Ha("pget",a);return r[a+"Provider"]=b}function e(a,b){return function(){var c=C.invoke(b,this);if(A(c))throw Ha("undef",a);return c}}function f(a,b,c){return d(a,{$get:!1!==c?e(a,b):b})}function g(a){var b=[],c;m(a,function(a){function d(a){var b,c;b=0;for(c=a.length;b<c;b++){var e=a[b],f=s.get(e[0]);f[e[1]].apply(f,e[2])}}if(!n.get(a)){n.put(a,!0);try{L(a)?(c=gb(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):z(a)?b.push(s.invoke(a)):G(a)?
|
|
||||||
b.push(s.invoke(a)):Qa(a,"module")}catch(e){throw G(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ha("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a,e){if(b.hasOwnProperty(a)){if(b[a]===l)throw Ha("cdep",a+" <- "+k.join(" <- "));return b[a]}try{return k.unshift(a),b[a]=l,b[a]=c(a,e)}catch(f){throw b[a]===l&&delete b[a],f;}finally{k.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var h=[],k=eb.$$annotate(b,
|
|
||||||
a,g),l,s,n;s=0;for(l=k.length;s<l;s++){n=k[s];if("string"!==typeof n)throw Ha("itkn",n);h.push(f&&f.hasOwnProperty(n)?f[n]:d(n,g))}G(b)&&(b=b[l]);return b.apply(c,h)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((G(a)?a[a.length-1]:a).prototype||null);a=e(a,d,b,c);return H(a)||z(a)?a:d},get:d,annotate:eb.$$annotate,has:function(a){return r.hasOwnProperty(a+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var l={},k=[],n=new Sa([],!0),r={$provide:{provider:c(d),factory:c(f),service:c(function(a,
|
|
||||||
b){return f(a,["$injector",function(a){return a.instantiate(b)}])}),value:c(function(a,b){return f(a,ra(b),!1)}),constant:c(function(a,b){Ra(a,"constant");r[a]=b;x[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=C.invoke(d,c);return C.invoke(b,null,{$delegate:a})}}}},s=r.$injector=h(r,function(a,b){ca.isString(b)&&k.push(b);throw Ha("unpr",k.join(" <- "));}),x={},C=x.$injector=h(x,function(a,b){var c=s.get(a+"Provider",b);return C.invoke(c.$get,c,t,a)});m(g(b),
|
|
||||||
function(a){a&&C.invoke(a)});return C}function Re(){var b=!0;this.disableAutoScrolling=function(){b=!1};this.$get=["$window","$location","$rootScope",function(a,c,d){function e(a){var b=null;Array.prototype.some.call(a,function(a){if("a"===ta(a))return b=a,!0});return b}function f(b){if(b){b.scrollIntoView();var c;c=g.yOffset;z(c)?c=c():tc(c)?(c=c[0],c="fixed"!==a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):V(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,
|
|
||||||
0)}function g(a){a=L(a)?a:c.hash();var b;a?(b=h.getElementById(a))?f(b):(b=e(h.getElementsByName(a)))?f(b):"top"===a&&f(null):f(null)}var h=a.document;b&&d.$watch(function(){return c.hash()},function(a,b){a===b&&""===a||Ef(function(){d.$evalAsync(g)})});return g}]}function jb(b,a){if(!b&&!a)return"";if(!b)return a;if(!a)return b;G(b)&&(b=b.join(" "));G(a)&&(a=a.join(" "));return b+" "+a}function If(b){L(b)&&(b=b.split(" "));var a=ga();m(b,function(b){b.length&&(a[b]=!0)});return a}function Ia(b){return H(b)?
|
|
||||||
b:{}}function Jf(b,a,c,d){function e(a){try{a.apply(null,za.call(arguments,1))}finally{if(C--,0===C)for(;F.length;)try{F.pop()()}catch(b){c.error(b)}}}function f(){g();h()}function g(){a:{try{u=n.state;break a}catch(a){}u=void 0}u=A(u)?null:u;ka(u,D)&&(u=D);D=u}function h(){if(K!==l.url()||p!==u)K=l.url(),p=u,m(B,function(a){a(l.url(),u)})}var l=this,k=b.location,n=b.history,r=b.setTimeout,s=b.clearTimeout,x={};l.isMock=!1;var C=0,F=[];l.$$completeOutstandingRequest=e;l.$$incOutstandingRequestCount=
|
|
||||||
function(){C++};l.notifyWhenNoOutstandingRequests=function(a){0===C?a():F.push(a)};var u,p,K=k.href,q=a.find("base"),I=null;g();p=u;l.url=function(a,c,e){A(e)&&(e=null);k!==b.location&&(k=b.location);n!==b.history&&(n=b.history);if(a){var f=p===e;if(K===a&&(!d.history||f))return l;var h=K&&Ja(K)===Ja(a);K=a;p=e;if(!d.history||h&&f){if(!h||I)I=a;c?k.replace(a):h?(c=k,e=a.indexOf("#"),a=-1===e?"":a.substr(e),c.hash=a):k.href=a}else n[c?"replaceState":"pushState"](e,"",a),g(),p=u;return l}return I||
|
|
||||||
k.href.replace(/%27/g,"'")};l.state=function(){return u};var B=[],N=!1,D=null;l.onUrlChange=function(a){if(!N){if(d.history)y(b).on("popstate",f);y(b).on("hashchange",f);N=!0}B.push(a);return a};l.$$applicationDestroyed=function(){y(b).off("hashchange popstate",f)};l.$$checkUrlChange=h;l.baseHref=function(){var a=q.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};l.defer=function(a,b){var c;C++;c=r(function(){delete x[c];e(a)},b||0);x[c]=!0;return c};l.defer.cancel=function(a){return x[a]?
|
|
||||||
(delete x[a],s(a),e(v),!0):!1}}function Ve(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new Jf(b,d,a,c)}]}function We(){this.$get=function(){function b(b,d){function e(a){a!=r&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,r),r=a,r.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw J("$cacheFactory")("iid",b);var g=0,h=P({},d,{id:b}),l={},k=d&&d.capacity||Number.MAX_VALUE,n={},r=null,s=null;return a[b]={put:function(a,b){if(!A(b)){if(k<Number.MAX_VALUE){var c=
|
|
||||||
n[a]||(n[a]={key:a});e(c)}a in l||g++;l[a]=b;g>k&&this.remove(s.key);return b}},get:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;e(b)}return l[a]},remove:function(a){if(k<Number.MAX_VALUE){var b=n[a];if(!b)return;b==r&&(r=b.p);b==s&&(s=b.n);f(b.n,b.p);delete n[a]}delete l[a];g--},removeAll:function(){l={};g=0;n={};r=s=null},destroy:function(){n=h=l=null;delete a[b]},info:function(){return P({},h,{size:g})}}}var a={};b.info=function(){var b={};m(a,function(a,e){b[e]=a.info()});return b};
|
|
||||||
b.get=function(b){return a[b]};return b}}function pf(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function Ec(b,a){function c(a,b,c){var d=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,e={};m(a,function(a,f){var g=a.match(d);if(!g)throw ea("iscp",b,f,a,c?"controller bindings definition":"isolate scope definition");e[f]={mode:g[1][0],collection:"*"===g[2],optional:"?"===g[3],attrName:g[4]||f}});return e}function d(a){var b=a.charAt(0);if(!b||b!==M(b))throw ea("baddir",a);if(a!==a.trim())throw ea("baddir",
|
|
||||||
a);}var e={},f=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,g=/(([\w\-]+)(?:\:([^;]+))?;?)/,h=Wd("ngSrc,ngSrcset,src,srcset"),l=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,k=/^(on[a-z]+|formaction)$/;this.directive=function s(a,f){Ra(a,"directive");L(a)?(d(a),Sb(f,"directiveFactory"),e.hasOwnProperty(a)||(e[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,d){var f=[];m(e[a],function(e,g){try{var h=b.invoke(e);z(h)?h={compile:ra(h)}:!h.compile&&h.link&&(h.compile=ra(h.link));h.priority=h.priority||
|
|
||||||
0;h.index=g;h.name=h.name||a;h.require=h.require||h.controller&&h.name;h.restrict=h.restrict||"EA";var k=h,l=h,s=h.name,n={isolateScope:null,bindToController:null};H(l.scope)&&(!0===l.bindToController?(n.bindToController=c(l.scope,s,!0),n.isolateScope={}):n.isolateScope=c(l.scope,s,!1));H(l.bindToController)&&(n.bindToController=c(l.bindToController,s,!0));if(H(n.bindToController)){var C=l.controller,$=l.controllerAs;if(!C)throw ea("noctrl",s);var ha;a:if($&&L($))ha=$;else{if(L(C)){var m=Xc.exec(C);
|
|
||||||
if(m){ha=m[3];break a}}ha=void 0}if(!ha)throw ea("noident",s);}var q=k.$$bindings=n;H(q.isolateScope)&&(h.$$isolateBindings=q.isolateScope);h.$$moduleName=e.$$moduleName;f.push(h)}catch(t){d(t)}});return f}])),e[a].push(f)):m(a,pc(s));return this};this.aHrefSanitizationWhitelist=function(b){return w(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};
|
|
||||||
var n=!0;this.debugInfoEnabled=function(a){return w(a)?(n=a,this):n};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,d,u,p,K,q,I,B,N){function D(a,b){try{a.addClass(b)}catch(c){}}function Z(a,b,c,d,e){a instanceof y||(a=y(a));m(a,function(b,c){b.nodeType==Na&&b.nodeValue.match(/\S+/)&&(a[c]=y(b).wrap("<span></span>").parent()[0])});var f=S(a,b,a,c,d,e);Z.$$addScopeClass(a);
|
|
||||||
var g=null;return function(b,c,d){Sb(b,"scope");d=d||{};var e=d.parentBoundTranscludeFn,h=d.transcludeControllers;d=d.futureParentElement;e&&e.$$boundTransclude&&(e=e.$$boundTransclude);g||(g=(d=d&&d[0])?"foreignobject"!==ta(d)&&d.toString().match(/SVG/)?"svg":"html":"html");d="html"!==g?y(Yb(g,y("<div>").append(a).html())):c?Pa.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);Z.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function S(a,b,c,d,e,f){function g(a,
|
|
||||||
c,d,e){var f,k,l,s,n,B,C;if(p)for(C=Array(c.length),s=0;s<h.length;s+=3)f=h[s],C[f]=c[f];else C=c;s=0;for(n=h.length;s<n;)if(k=C[h[s++]],c=h[s++],f=h[s++],c){if(c.scope){if(l=a.$new(),Z.$$addScopeInfo(y(k),l),B=c.$$destroyBindings)c.$$destroyBindings=null,l.$on("$destroyed",B)}else l=a;B=c.transcludeOnThisElement?$(a,c.transclude,e):!c.templateOnThisElement&&e?e:!e&&b?$(a,b):null;c(f,l,k,d,B,c)}else f&&f(a,k.childNodes,t,e)}for(var h=[],k,l,s,n,p,B=0;B<a.length;B++){k=new aa;l=ha(a[B],[],k,0===B?
|
|
||||||
d:t,e);(f=l.length?E(l,a[B],k,b,c,null,[],[],f):null)&&f.scope&&Z.$$addScopeClass(k.$$element);k=f&&f.terminal||!(s=a[B].childNodes)||!s.length?null:S(s,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(B,f,k),n=!0,p=p||f;f=null}return n?g:null}function $(a,b,c){return function(d,e,f,g,h){d||(d=a.$new(!1,h),d.$$transcluded=!0);return b(d,e,{parentBoundTranscludeFn:c,transcludeControllers:f,futureParentElement:g})}}function ha(a,b,c,d,e){var h=c.$attr,k;switch(a.nodeType){case qa:w(b,
|
|
||||||
wa(ta(a)),"E",d,e);for(var l,s,n,p=a.attributes,B=0,C=p&&p.length;B<C;B++){var x=!1,S=!1;l=p[B];k=l.name;s=R(l.value);l=wa(k);if(n=ia.test(l))k=k.replace(Zc,"").substr(8).replace(/_(.)/g,function(a,b){return b.toUpperCase()});var F=l.replace(/(Start|End)$/,"");A(F)&&l===F+"Start"&&(x=k,S=k.substr(0,k.length-5)+"end",k=k.substr(0,k.length-6));l=wa(k.toLowerCase());h[l]=k;if(n||!c.hasOwnProperty(l))c[l]=s,Sc(a,l)&&(c[l]=!0);V(a,b,s,l,n);w(b,l,"A",d,e,x,S)}a=a.className;H(a)&&(a=a.animVal);if(L(a)&&
|
|
||||||
""!==a)for(;k=g.exec(a);)l=wa(k[2]),w(b,l,"C",d,e)&&(c[l]=R(k[3])),a=a.substr(k.index+k[0].length);break;case Na:if(11===Ua)for(;a.parentNode&&a.nextSibling&&a.nextSibling.nodeType===Na;)a.nodeValue+=a.nextSibling.nodeValue,a.parentNode.removeChild(a.nextSibling);xa(b,a.nodeValue);break;case 8:try{if(k=f.exec(a.nodeValue))l=wa(k[1]),w(b,l,"M",d,e)&&(c[l]=R(k[2]))}catch($){}}b.sort(Aa);return b}function va(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ea("uterdir",b,c);
|
|
||||||
a.nodeType==qa&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return y(d)}function Yc(a,b,c){return function(d,e,f,g,h){e=va(e[0],b,c);return a(d,e,f,g,h)}}function E(a,b,d,e,f,g,h,k,s){function n(a,b,c,d){if(a){c&&(a=Yc(a,c,d));a.require=E.require;a.directiveName=w;if(u===E||E.$$isolateScope)a=X(a,{isolateScope:!0});h.push(a)}if(b){c&&(b=Yc(b,c,d));b.require=E.require;b.directiveName=w;if(u===E||E.$$isolateScope)b=X(b,{isolateScope:!0});k.push(b)}}
|
|
||||||
function B(a,b,c,d){var e;if(L(b)){var f=b.match(l);b=b.substring(f[0].length);var g=f[1]||f[3],f="?"===f[2];"^^"===g?c=c.parent():e=(e=d&&d[b])&&e.instance;e||(d="$"+b+"Controller",e=g?c.inheritedData(d):c.data(d));if(!e&&!f)throw ea("ctreq",b,a);}else if(G(b))for(e=[],g=0,f=b.length;g<f;g++)e[g]=B(a,b[g],c,d);return e||null}function x(a,b,c,d,e,f){var g=ga(),h;for(h in d){var k=d[h],l={$scope:k===u||k.$$isolateScope?e:f,$element:a,$attrs:b,$transclude:c},s=k.controller;"@"==s&&(s=b[k.name]);l=p(s,
|
|
||||||
l,!0,k.controllerAs);g[k.name]=l;q||a.data("$"+k.name+"Controller",l.instance)}return g}function S(a,c,e,f,g,l){function s(a,b,c){var d;$a(a)||(c=b,b=a,a=t);q&&(d=m);c||(c=q?ja.parent():ja);return g(a,b,d,c,va)}var n,p,C,F,m,ha,ja;b===e?(f=d,ja=d.$$element):(ja=y(e),f=new aa(ja,d));u&&(F=c.$new(!0));g&&(ha=s,ha.$$boundTransclude=g);N&&(m=x(ja,f,ha,N,F,c));u&&(Z.$$addScopeInfo(ja,F,!0,!(D&&(D===u||D===u.$$originalDirective))),Z.$$addScopeClass(ja,!0),F.$$isolateBindings=u.$$isolateBindings,W(c,f,F,
|
|
||||||
F.$$isolateBindings,u,F));if(m){var K=u||$,I;K&&m[K.name]&&(p=K.$$bindings.bindToController,(C=m[K.name])&&C.identifier&&p&&(I=C,l.$$destroyBindings=W(c,f,C.instance,p,K)));for(n in m){C=m[n];var E=C();E!==C.instance&&(C.instance=E,ja.data("$"+n+"Controller",E),C===I&&(l.$$destroyBindings(),l.$$destroyBindings=W(c,f,E,p,K)))}}n=0;for(l=h.length;n<l;n++)p=h[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha);var va=c;u&&(u.template||null===u.templateUrl)&&(va=F);a&&a(va,
|
|
||||||
e.childNodes,t,g);for(n=k.length-1;0<=n;n--)p=k[n],Y(p,p.isolateScope?F:c,ja,f,p.require&&B(p.directiveName,p.require,ja,m),ha)}s=s||{};for(var F=-Number.MAX_VALUE,$=s.newScopeDirective,N=s.controllerDirectives,u=s.newIsolateScopeDirective,D=s.templateDirective,m=s.nonTlbTranscludeDirective,K=!1,I=!1,q=s.hasElementTranscludeDirective,ba=d.$$element=y(b),E,w,v,A=e,Aa,xa=0,Ta=a.length;xa<Ta;xa++){E=a[xa];var M=E.$$start,P=E.$$end;M&&(ba=va(b,M,P));v=t;if(F>E.priority)break;if(v=E.scope)E.templateUrl||
|
|
||||||
(H(v)?(O("new/isolated scope",u||$,E,ba),u=E):O("new/isolated scope",u,E,ba)),$=$||E;w=E.name;!E.templateUrl&&E.controller&&(v=E.controller,N=N||ga(),O("'"+w+"' controller",N[w],E,ba),N[w]=E);if(v=E.transclude)K=!0,E.$$tlb||(O("transclusion",m,E,ba),m=E),"element"==v?(q=!0,F=E.priority,v=ba,ba=d.$$element=y(U.createComment(" "+w+": "+d[w]+" ")),b=ba[0],T(f,za.call(v,0),b),A=Z(v,e,F,g&&g.name,{nonTlbTranscludeDirective:m})):(v=y(Vb(b)).contents(),ba.empty(),A=Z(v,e));if(E.template)if(I=!0,O("template",
|
|
||||||
D,E,ba),D=E,v=z(E.template)?E.template(ba,d):E.template,v=fa(v),E.replace){g=E;v=Tb.test(v)?$c(Yb(E.templateNamespace,R(v))):[];b=v[0];if(1!=v.length||b.nodeType!==qa)throw ea("tplrt",w,"");T(f,ba,b);Ta={$attr:{}};v=ha(b,[],Ta);var Q=a.splice(xa+1,a.length-(xa+1));u&&ad(v);a=a.concat(v).concat(Q);J(d,Ta);Ta=a.length}else ba.html(v);if(E.templateUrl)I=!0,O("template",D,E,ba),D=E,E.replace&&(g=E),S=Lf(a.splice(xa,a.length-xa),ba,d,f,K&&A,h,k,{controllerDirectives:N,newScopeDirective:$!==E&&$,newIsolateScopeDirective:u,
|
|
||||||
templateDirective:D,nonTlbTranscludeDirective:m}),Ta=a.length;else if(E.compile)try{Aa=E.compile(ba,d,A),z(Aa)?n(null,Aa,M,P):Aa&&n(Aa.pre,Aa.post,M,P)}catch(Kf){c(Kf,ua(ba))}E.terminal&&(S.terminal=!0,F=Math.max(F,E.priority))}S.scope=$&&!0===$.scope;S.transcludeOnThisElement=K;S.templateOnThisElement=I;S.transclude=A;s.hasElementTranscludeDirective=q;return S}function ad(a){for(var b=0,c=a.length;b<c;b++)a[b]=Ob(a[b],{$$isolateScope:!0})}function w(b,d,f,g,h,k,l){if(d===h)return null;h=null;if(e.hasOwnProperty(d)){var n;
|
|
||||||
d=a.get(d+"Directive");for(var p=0,B=d.length;p<B;p++)try{n=d[p],(g===t||g>n.priority)&&-1!=n.restrict.indexOf(f)&&(k&&(n=Ob(n,{$$start:k,$$end:l})),b.push(n),h=n)}catch(x){c(x)}}return h}function A(b){if(e.hasOwnProperty(b))for(var c=a.get(b+"Directive"),d=0,f=c.length;d<f;d++)if(b=c[d],b.multiElement)return!0;return!1}function J(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;m(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});m(b,function(b,f){"class"==
|
|
||||||
f?(D(e,b),a["class"]=(a["class"]?a["class"]+" ":"")+b):"style"==f?(e.attr("style",e.attr("style")+";"+b),a.style=(a.style?a.style+";":"")+b):"$"==f.charAt(0)||a.hasOwnProperty(f)||(a[f]=b,d[f]=c[f])})}function Lf(a,b,c,e,f,g,h,k){var l=[],s,n,p=b[0],B=a.shift(),C=Ob(B,{templateUrl:null,transclude:null,replace:null,$$originalDirective:B}),x=z(B.templateUrl)?B.templateUrl(b,c):B.templateUrl,N=B.templateNamespace;b.empty();d(x).then(function(d){var F,u;d=fa(d);if(B.replace){d=Tb.test(d)?$c(Yb(N,R(d))):
|
|
||||||
[];F=d[0];if(1!=d.length||F.nodeType!==qa)throw ea("tplrt",B.name,x);d={$attr:{}};T(e,b,F);var K=ha(F,[],d);H(B.scope)&&ad(K);a=K.concat(a);J(c,d)}else F=p,b.html(d);a.unshift(C);s=E(a,F,c,f,b,B,g,h,k);m(e,function(a,c){a==F&&(e[c]=b[0])});for(n=S(b[0].childNodes,f);l.length;){d=l.shift();u=l.shift();var I=l.shift(),va=l.shift(),K=b[0];if(!d.$$destroyed){if(u!==p){var Z=u.className;k.hasElementTranscludeDirective&&B.replace||(K=Vb(F));T(I,y(u),K);D(y(K),Z)}u=s.transcludeOnThisElement?$(d,s.transclude,
|
|
||||||
va):va;s(n,d,K,e,u,s)}}l=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(l?l.push(b,c,d,a):(s.transcludeOnThisElement&&(a=$(b,s.transclude,e)),s(n,b,c,d,a,s)))}}function Aa(a,b){var c=b.priority-a.priority;return 0!==c?c:a.name!==b.name?a.name<b.name?-1:1:a.index-b.index}function O(a,b,c,d){function e(a){return a?" (module: "+a+")":""}if(b)throw ea("multidir",b.name,e(b.$$moduleName),c.name,e(c.$$moduleName),a,ua(d));}function xa(a,c){var d=b(c,!0);d&&a.push({priority:0,compile:function(a){a=
|
|
||||||
a.parent();var b=!!a.length;b&&Z.$$addBindingClass(a);return function(a,c){var e=c.parent();b||Z.$$addBindingClass(e);Z.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function Yb(a,b){a=M(a||"html");switch(a){case "svg":case "math":var c=U.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Q(a,b){if("srcdoc"==b)return I.HTML;var c=ta(a);if("xlinkHref"==b||"form"==c&&"action"==b||"img"!=c&&("src"==b||
|
|
||||||
"ngSrc"==b))return I.RESOURCE_URL}function V(a,c,d,e,f){var g=Q(a,e);f=h[e]||f;var l=b(d,!0,g,f);if(l){if("multiple"===e&&"select"===ta(a))throw ea("selmulti",ua(a));c.push({priority:100,compile:function(){return{pre:function(a,c,h){c=h.$$observers||(h.$$observers={});if(k.test(e))throw ea("nodomevents");var s=h[e];s!==d&&(l=s&&b(s,!0,g,f),d=s);l&&(h[e]=l(a),(c[e]||(c[e]=[])).$$inter=!0,(h.$$observers&&h.$$observers[e].$$scope||a).$watch(l,function(a,b){"class"===e&&a!=b?h.$updateClass(a,b):h.$set(e,
|
|
||||||
a)}))}}}})}}function T(a,b,c){var d=b[0],e=b.length,f=d.parentNode,g,h;if(a)for(g=0,h=a.length;g<h;g++)if(a[g]==d){a[g++]=c;h=g+e-1;for(var k=a.length;g<k;g++,h++)h<k?a[g]=a[h]:delete a[g];a.length-=e-1;a.context===d&&(a.context=c);break}f&&f.replaceChild(c,d);a=U.createDocumentFragment();a.appendChild(d);y.hasData(d)&&(y(c).data(y(d).data()),la?(Rb=!0,la.cleanData([d])):delete y.cache[d[y.expando]]);d=1;for(e=b.length;d<e;d++)f=b[d],y(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function X(a,
|
|
||||||
b){return P(function(){return a.apply(null,arguments)},a,b)}function Y(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,ua(d))}}function W(a,c,d,e,f,g){var h;m(e,function(e,g){var k=e.attrName,l=e.optional,s=e.mode,n,p,B,C;Xa.call(c,k)||(c[k]=t);switch(s){case "@":c[k]||l||(d[g]=t);c.$observe(k,function(a){d[g]=a});c.$$observers[k].$$scope=a;c[k]&&(d[g]=b(c[k])(a));break;case "=":if(l&&!c[k])break;p=u(c[k]);C=p.literal?ka:function(a,b){return a===b||a!==a&&b!==b};B=p.assign||function(){n=d[g]=p(a);throw ea("nonassign",
|
|
||||||
c[k],f.name);};n=d[g]=p(a);l=function(b){C(b,d[g])||(C(b,n)?B(a,b=d[g]):d[g]=b);return n=b};l.$stateful=!0;l=e.collection?a.$watchCollection(c[k],l):a.$watch(u(c[k],l),null,p.literal);h=h||[];h.push(l);break;case "&":p=u(c[k]);if(p===v&&l)break;d[g]=function(b){return p(a,b)}}});e=h?function(){for(var a=0,b=h.length;a<b;++a)h[a]()}:v;return g&&e!==v?(g.$on("$destroy",e),v):e}var aa=function(a,b){if(b){var c=Object.keys(b),d,e,f;d=0;for(e=c.length;d<e;d++)f=c[d],this[f]=b[f]}else this.$attr={};this.$$element=
|
|
||||||
a};aa.prototype={$normalize:wa,$addClass:function(a){a&&0<a.length&&B.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&B.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=bd(a,b);c&&c.length&&B.addClass(this.$$element,c);(c=bd(b,a))&&c.length&&B.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Sc(f,a),h=Ff(f,a),f=a;g?(this.$$element.prop(a,b),e=g):h&&(this[h]=b,f=h);this[a]=b;e?this.$attr[a]=e:(e=this.$attr[a])||(this.$attr[a]=e=Bc(a,
|
|
||||||
"-"));g=ta(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=N(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=R(b),k=/(\s+\d+x\s*,|\s+\d+w\s*,|\s+,|,\s+)/,k=/\s/.test(h)?k:/(,)/,h=h.split(k),k=Math.floor(h.length/2),l=0;l<k;l++)var s=2*l,g=g+N(R(h[s]),!0),g=g+(" "+R(h[s+1]));h=R(h[2*l]).split(/\s/);g+=N(R(h[0]),!0);2===h.length&&(g+=" "+R(h[1]));this[a]=b=g}!1!==d&&(null===b||b===t?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&m(a[f],
|
|
||||||
function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ga()),e=d[a]||(d[a]=[]);e.push(b);K.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});return function(){bb(e,b)}}};var ca=b.startSymbol(),da=b.endSymbol(),fa="{{"==ca||"}}"==da?Ya:function(a){return a.replace(/\{\{/g,ca).replace(/}}/g,da)},ia=/^ngAttr[A-Z]/;Z.$$addBindingInfo=n?function(a,b){var c=a.data("$binding")||[];G(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:v;Z.$$addBindingClass=
|
|
||||||
n?function(a){D(a,"ng-binding")}:v;Z.$$addScopeInfo=n?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:v;Z.$$addScopeClass=n?function(a,b){D(a,b?"ng-isolate-scope":"ng-scope")}:v;return Z}]}function wa(b){return hb(b.replace(Zc,""))}function bd(b,a){var c="",d=b.split(/\s+/),e=a.split(/\s+/),f=0;a:for(;f<d.length;f++){for(var g=d[f],h=0;h<e.length;h++)if(g==e[h])continue a;c+=(0<c.length?" ":"")+g}return c}function $c(b){b=y(b);var a=b.length;if(1>=a)return b;for(;a--;)8===
|
|
||||||
b[a].nodeType&&Mf.call(b,a,1);return b}function Xe(){var b={},a=!1;this.register=function(a,d){Ra(a,"controller");H(a)?P(b,a):b[a]=d};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(c,d){function e(a,b,c,d){if(!a||!H(a.$scope))throw J("$controller")("noscp",d,b);a.$scope[b]=c}return function(f,g,h,l){var k,n,r;h=!0===h;l&&L(l)&&(r=l);if(L(f)){l=f.match(Xc);if(!l)throw Nf("ctrlfmt",f);n=l[1];r=r||l[3];f=b.hasOwnProperty(n)?b[n]:Dc(g.$scope,n,!0)||(a?Dc(d,n,!0):t);Qa(f,
|
|
||||||
n,!0)}if(h)return h=(G(f)?f[f.length-1]:f).prototype,k=Object.create(h||null),r&&e(g,r,k,n||f.name),P(function(){var a=c.invoke(f,k,g,n);a!==k&&(H(a)||z(a))&&(k=a,r&&e(g,r,k,n||f.name));return k},{instance:k,identifier:r});k=c.instantiate(f,g,n);r&&e(g,r,k,n||f.name);return k}}]}function Ye(){this.$get=["$window",function(b){return y(b.document)}]}function Ze(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Zb(b){return H(b)?aa(b)?b.toISOString():db(b):b}
|
|
||||||
function cf(){this.$get=function(){return function(b){if(!b)return"";var a=[];oc(b,function(b,d){null===b||A(b)||(G(b)?m(b,function(b,c){a.push(ma(d)+"="+ma(Zb(b)))}):a.push(ma(d)+"="+ma(Zb(b))))});return a.join("&")}}}function df(){this.$get=function(){return function(b){function a(b,e,f){null===b||A(b)||(G(b)?m(b,function(b){a(b,e+"[]")}):H(b)&&!aa(b)?oc(b,function(b,c){a(b,e+(f?"":"[")+c+(f?"":"]"))}):c.push(ma(e)+"="+ma(Zb(b))))}if(!b)return"";var c=[];a(b,"",!0);return c.join("&")}}}function $b(b,
|
|
||||||
a){if(L(b)){var c=b.replace(Of,"").trim();if(c){var d=a("Content-Type");(d=d&&0===d.indexOf(cd))||(d=(d=c.match(Pf))&&Qf[d[0]].test(c));d&&(b=wc(c))}}return b}function dd(b){var a=ga(),c;L(b)?m(b.split("\n"),function(b){c=b.indexOf(":");var e=M(R(b.substr(0,c)));b=R(b.substr(c+1));e&&(a[e]=a[e]?a[e]+", "+b:b)}):H(b)&&m(b,function(b,c){var f=M(c),g=R(b);f&&(a[f]=a[f]?a[f]+", "+g:g)});return a}function ed(b){var a;return function(c){a||(a=dd(b));return c?(c=a[M(c)],void 0===c&&(c=null),c):a}}function fd(b,
|
|
||||||
a,c,d){if(z(d))return d(b,a,c);m(d,function(d){b=d(b,a,c)});return b}function bf(){var b=this.defaults={transformResponse:[$b],transformRequest:[function(a){return H(a)&&"[object File]"!==sa.call(a)&&"[object Blob]"!==sa.call(a)&&"[object FormData]"!==sa.call(a)?db(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ia(ac),put:ia(ac),patch:ia(ac)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",paramSerializer:"$httpParamSerializer"},a=!1;this.useApplyAsync=function(b){return w(b)?
|
|
||||||
(a=!!b,this):a};var c=this.interceptors=[];this.$get=["$httpBackend","$$cookieReader","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,l){function k(a){function c(a){var b=P({},a);b.data=a.data?fd(a.data,a.headers,a.status,e.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}function d(a,b){var c,e={};m(a,function(a,d){z(a)?(c=a(b),null!=c&&(e[d]=c)):e[d]=a});return e}if(!ca.isObject(a))throw J("$http")("badreq",a);var e=P({method:"get",transformRequest:b.transformRequest,
|
|
||||||
transformResponse:b.transformResponse,paramSerializer:b.paramSerializer},a);e.headers=function(a){var c=b.headers,e=P({},a.headers),f,g,h,c=P({},c.common,c[M(a.method)]);a:for(f in c){g=M(f);for(h in e)if(M(h)===g)continue a;e[f]=c[f]}return d(e,ia(a))}(a);e.method=rb(e.method);e.paramSerializer=L(e.paramSerializer)?l.get(e.paramSerializer):e.paramSerializer;var f=[function(a){var d=a.headers,e=fd(a.data,ed(d),t,a.transformRequest);A(e)&&m(d,function(a,b){"content-type"===M(b)&&delete d[b]});A(a.withCredentials)&&
|
|
||||||
!A(b.withCredentials)&&(a.withCredentials=b.withCredentials);return n(a,e).then(c,c)},t],g=h.when(e);for(m(x,function(a){(a.request||a.requestError)&&f.unshift(a.request,a.requestError);(a.response||a.responseError)&&f.push(a.response,a.responseError)});f.length;){a=f.shift();var k=f.shift(),g=g.then(a,k)}g.success=function(a){Qa(a,"fn");g.then(function(b){a(b.data,b.status,b.headers,e)});return g};g.error=function(a){Qa(a,"fn");g.then(null,function(b){a(b.data,b.status,b.headers,e)});return g};return g}
|
|
||||||
function n(c,f){function l(b,c,d,e){function f(){n(c,b,d,e)}N&&(200<=b&&300>b?N.put(S,[b,c,dd(d),e]):N.remove(S));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function n(a,b,d,e){b=Math.max(b,0);(200<=b&&300>b?I.resolve:I.reject)({data:a,status:b,headers:ed(d),config:c,statusText:e})}function x(a){n(a.data,a.status,ia(a.headers()),a.statusText)}function m(){var a=k.pendingRequests.indexOf(c);-1!==a&&k.pendingRequests.splice(a,1)}var I=h.defer(),B=I.promise,N,D,q=c.headers,S=r(c.url,c.paramSerializer(c.params));
|
|
||||||
k.pendingRequests.push(c);B.then(m,m);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(N=H(c.cache)?c.cache:H(b.cache)?b.cache:s);N&&(D=N.get(S),w(D)?D&&z(D.then)?D.then(x,x):G(D)?n(D[1],D[0],ia(D[2]),D[3]):n(D,200,{},"OK"):N.put(S,B));A(D)&&((D=gd(c.url)?e()[c.xsrfCookieName||b.xsrfCookieName]:t)&&(q[c.xsrfHeaderName||b.xsrfHeaderName]=D),d(c.method,S,f,l,q,c.timeout,c.withCredentials,c.responseType));return B}function r(a,b){0<b.length&&(a+=(-1==a.indexOf("?")?"?":"&")+b);
|
|
||||||
return a}var s=f("$http");b.paramSerializer=L(b.paramSerializer)?l.get(b.paramSerializer):b.paramSerializer;var x=[];m(c,function(a){x.unshift(L(a)?l.get(a):l.invoke(a))});k.pendingRequests=[];(function(a){m(arguments,function(a){k[a]=function(b,c){return k(P({},c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){m(arguments,function(a){k[a]=function(b,c,d){return k(P({},d||{},{method:a,url:b,data:c}))}})})("post","put","patch");k.defaults=b;return k}]}function Rf(){return new O.XMLHttpRequest}
|
|
||||||
function ef(){this.$get=["$browser","$window","$document",function(b,a,c){return Sf(b,Rf,b.defer,a.angular.callbacks,c[0])}]}function Sf(b,a,c,d,e){function f(a,b,c){var f=e.createElement("script"),n=null;f.type="text/javascript";f.src=a;f.async=!0;n=function(a){f.removeEventListener("load",n,!1);f.removeEventListener("error",n,!1);e.body.removeChild(f);f=null;var g=-1,x="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),x=a.type,g="error"===a.type?404:200);c&&c(g,x)};f.addEventListener("load",
|
|
||||||
n,!1);f.addEventListener("error",n,!1);e.body.appendChild(f);return n}return function(e,h,l,k,n,r,s,x){function C(){p&&p();K&&K.abort()}function F(a,d,e,f,g){I!==t&&c.cancel(I);p=K=null;a(d,e,f,g);b.$$completeOutstandingRequest(v)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==M(e)){var u="_"+(d.counter++).toString(36);d[u]=function(a){d[u].data=a;d[u].called=!0};var p=f(h.replace("JSON_CALLBACK","angular.callbacks."+u),u,function(a,b){F(k,a,d[u].data,"",b);d[u]=v})}else{var K=a();K.open(e,
|
|
||||||
h,!0);m(n,function(a,b){w(a)&&K.setRequestHeader(b,a)});K.onload=function(){var a=K.statusText||"",b="response"in K?K.response:K.responseText,c=1223===K.status?204:K.status;0===c&&(c=b?200:"file"==Ba(h).protocol?404:0);F(k,c,b,K.getAllResponseHeaders(),a)};e=function(){F(k,-1,null,null,"")};K.onerror=e;K.onabort=e;s&&(K.withCredentials=!0);if(x)try{K.responseType=x}catch(q){if("json"!==x)throw q;}K.send(l)}if(0<r)var I=c(C,r);else r&&z(r.then)&&r.then(C)}}function $e(){var b="{{",a="}}";this.startSymbol=
|
|
||||||
function(a){return a?(b=a,this):b};this.endSymbol=function(b){return b?(a=b,this):a};this.$get=["$parse","$exceptionHandler","$sce",function(c,d,e){function f(a){return"\\\\\\"+a}function g(c){return c.replace(n,b).replace(r,a)}function h(f,h,n,r){function u(a){try{var b=a;a=n?e.getTrusted(n,b):e.valueOf(b);var c;if(r&&!w(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=db(a)}c=a}return c}catch(g){d(Ka.interr(f,g))}}r=!!r;for(var p,m,q=0,I=
|
|
||||||
[],B=[],N=f.length,D=[],t=[];q<N;)if(-1!=(p=f.indexOf(b,q))&&-1!=(m=f.indexOf(a,p+l)))q!==p&&D.push(g(f.substring(q,p))),q=f.substring(p+l,m),I.push(q),B.push(c(q,u)),q=m+k,t.push(D.length),D.push("");else{q!==N&&D.push(g(f.substring(q)));break}n&&1<D.length&&Ka.throwNoconcat(f);if(!h||I.length){var S=function(a){for(var b=0,c=I.length;b<c;b++){if(r&&A(a[b]))return;D[t[b]]=a[b]}return D.join("")};return P(function(a){var b=0,c=I.length,e=Array(c);try{for(;b<c;b++)e[b]=B[b](a);return S(e)}catch(g){d(Ka.interr(f,
|
|
||||||
g))}},{exp:f,expressions:I,$$watchDelegate:function(a,b){var c;return a.$watchGroup(B,function(d,e){var f=S(d);z(b)&&b.call(this,f,d!==e?c:f,a);c=f})}})}}var l=b.length,k=a.length,n=new RegExp(b.replace(/./g,f),"g"),r=new RegExp(a.replace(/./g,f),"g");h.startSymbol=function(){return b};h.endSymbol=function(){return a};return h}]}function af(){this.$get=["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,l,k){var n=4<arguments.length,r=n?za.call(arguments,4):[],s=a.setInterval,x=a.clearInterval,
|
|
||||||
C=0,F=w(k)&&!k,u=(F?d:c).defer(),p=u.promise;l=w(l)?l:0;p.then(null,null,n?function(){e.apply(null,r)}:e);p.$$intervalId=s(function(){u.notify(C++);0<l&&C>=l&&(u.resolve(C),x(p.$$intervalId),delete f[p.$$intervalId]);F||b.$apply()},h);f[p.$$intervalId]=u;return p}var f={};e.cancel=function(b){return b&&b.$$intervalId in f?(f[b.$$intervalId].reject("canceled"),a.clearInterval(b.$$intervalId),delete f[b.$$intervalId],!0):!1};return e}]}function ge(){this.$get=function(){return{id:"en-us",NUMBER_FORMATS:{DECIMAL_SEP:".",
|
|
||||||
GROUP_SEP:",",PATTERNS:[{minInt:1,minFrac:0,maxFrac:3,posPre:"",posSuf:"",negPre:"-",negSuf:"",gSize:3,lgSize:3},{minInt:1,minFrac:2,maxFrac:2,posPre:"\u00a4",posSuf:"",negPre:"(\u00a4",negSuf:")",gSize:3,lgSize:3}],CURRENCY_SYM:"$"},DATETIME_FORMATS:{MONTH:"January February March April May June July August September October November December".split(" "),SHORTMONTH:"Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),DAY:"Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" "),
|
|
||||||
SHORTDAY:"Sun Mon Tue Wed Thu Fri Sat".split(" "),AMPMS:["AM","PM"],medium:"MMM d, y h:mm:ss a","short":"M/d/yy h:mm a",fullDate:"EEEE, MMMM d, y",longDate:"MMMM d, y",mediumDate:"MMM d, y",shortDate:"M/d/yy",mediumTime:"h:mm:ss a",shortTime:"h:mm a",ERANAMES:["Before Christ","Anno Domini"],ERAS:["BC","AD"]},pluralCat:function(b){return 1===b?"one":"other"}}}}function bc(b){b=b.split("/");for(var a=b.length;a--;)b[a]=ob(b[a]);return b.join("/")}function hd(b,a){var c=Ba(b);a.$$protocol=c.protocol;
|
|
||||||
a.$$host=c.hostname;a.$$port=W(c.port)||Tf[c.protocol]||null}function id(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Ba(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=zc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function ya(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Ja(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function Bb(b){return b.replace(/(#.+)|#$/,
|
|
||||||
"$1")}function cc(b){return b.substr(0,Ja(b).lastIndexOf("/")+1)}function dc(b,a){this.$$html5=!0;a=a||"";var c=cc(b);hd(b,this);this.$$parse=function(a){var b=ya(c,a);if(!L(b))throw Cb("ipthprfx",a,c);id(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=function(){var a=Qb(this.$$search),b=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(a?"?"+a:"")+b;this.$$absUrl=c+this.$$url.substr(1)};this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),
|
|
||||||
!0;var f,g;(f=ya(b,d))!==t?(g=f,g=(f=ya(a,f))!==t?c+(ya("/",f)||f):b+g):(f=ya(c,d))!==t?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function ec(b,a){var c=cc(b);hd(b,this);this.$$parse=function(d){var e=ya(b,d)||ya(c,d),f;A(e)||"#"!==e.charAt(0)?this.$$html5?f=e:(f="",A(e)&&(b=d,this.replace())):(f=ya(a,e),A(f)&&(f=e));id(f,this);d=this.$$path;var e=b,g=/^\/[A-Z]:(\/.*)/;0===f.indexOf(e)&&(f=f.replace(e,""));g.exec(f)||(d=(f=g.exec(d))?f[1]:d);this.$$path=d;this.$$compose()};this.$$compose=
|
|
||||||
function(){var c=Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Ja(b)==Ja(a)?(this.$$parse(a),!0):!1}}function jd(b,a){this.$$html5=!0;ec.apply(this,arguments);var c=cc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Ja(d)?f=d:(g=ya(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=
|
|
||||||
Qb(this.$$search),e=this.$$hash?"#"+ob(this.$$hash):"";this.$$url=bc(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Db(b){return function(){return this[b]}}function kd(b,a){return function(c){if(A(c))return this[b];this[b]=a(c);this.$$compose();return this}}function ff(){var b="",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return w(a)?(b=a,this):b};this.html5Mode=function(b){return ab(b)?(a.enabled=b,this):H(b)?(ab(b.enabled)&&(a.enabled=b.enabled),
|
|
||||||
ab(b.requireBase)&&(a.requireBase=b.requireBase),ab(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement","$window",function(c,d,e,f,g){function h(a,b,c){var e=k.url(),f=k.$$state;try{d.url(a,b,c),k.$$state=d.state()}catch(g){throw k.url(e),k.$$state=f,g;}}function l(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,n;n=d.baseHref();var r=d.url(),s;if(a.enabled){if(!n&&a.requireBase)throw Cb("nobase");s=r.substring(0,
|
|
||||||
r.indexOf("/",r.indexOf("//")+2))+(n||"/");n=e.history?dc:jd}else s=Ja(r),n=ec;k=new n(s,"#"+b);k.$$parseLinkUrl(r,r);k.$$state=d.state();var x=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&!b.shiftKey&&2!=b.which&&2!=b.button){for(var e=y(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||!(e=e.parent())[0])return;var h=e.prop("href"),l=e.attr("href")||e.attr("xlink:href");H(h)&&"[object SVGAnimatedString]"===h.toString()&&(h=Ba(h.animVal).href);x.test(h)||
|
|
||||||
!h||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(h,l)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),g.angular["ff-684208-preventDefault"]=!0))}});Bb(k.absUrl())!=Bb(r)&&d.url(k.absUrl(),!0);var C=!0;d.onUrlChange(function(a,b){c.$evalAsync(function(){var d=k.absUrl(),e=k.$$state,f;k.$$parse(a);k.$$state=b;f=c.$broadcast("$locationChangeStart",a,d,b,e).defaultPrevented;k.absUrl()===a&&(f?(k.$$parse(d),k.$$state=e,h(d,!1,e)):(C=!1,l(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=
|
|
||||||
Bb(d.url()),b=Bb(k.absUrl()),f=d.state(),g=k.$$replace,n=a!==b||k.$$html5&&e.history&&f!==k.$$state;if(C||n)C=!1,c.$evalAsync(function(){var b=k.absUrl(),d=c.$broadcast("$locationChangeStart",b,a,k.$$state,f).defaultPrevented;k.absUrl()===b&&(d?(k.$$parse(a),k.$$state=f):(n&&h(b,g,f===k.$$state?null:k.$$state),l(a,f)))});k.$$replace=!1});return k}]}function gf(){var b=!0,a=this;this.debugEnabled=function(a){return w(a)?(b=a,this):b};this.$get=["$window",function(c){function d(a){a instanceof Error&&
|
|
||||||
(a.stack?a=a.message&&-1===a.stack.indexOf(a.message)?"Error: "+a.message+"\n"+a.stack:a.stack:a.sourceURL&&(a=a.message+"\n"+a.sourceURL+":"+a.line));return a}function e(a){var b=c.console||{},e=b[a]||b.log||v;a=!1;try{a=!!e.apply}catch(l){}return a?function(){var a=[];m(arguments,function(b){a.push(d(b))});return e.apply(b,a)}:function(a,b){e(a,null==b?"":b)}}return{log:e("log"),info:e("info"),warn:e("warn"),error:e("error"),debug:function(){var c=e("debug");return function(){b&&c.apply(a,arguments)}}()}}]}
|
|
||||||
function Ca(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw da("isecfld",a);return b}function oa(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b.window===b)throw da("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw da("isecdom",a);if(b===Object)throw da("isecobj",a);}return b}function ld(b,a){if(b){if(b.constructor===b)throw da("isecfn",a);if(b===Uf||b===Vf||b===Wf)throw da("isecff",a);
|
|
||||||
}}function Xf(b,a){return"undefined"!==typeof b?b:a}function md(b,a){return"undefined"===typeof b?a:"undefined"===typeof a?b:b+a}function T(b,a){var c,d;switch(b.type){case q.Program:c=!0;m(b.body,function(b){T(b.expression,a);c=c&&b.expression.constant});b.constant=c;break;case q.Literal:b.constant=!0;b.toWatch=[];break;case q.UnaryExpression:T(b.argument,a);b.constant=b.argument.constant;b.toWatch=b.argument.toWatch;break;case q.BinaryExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&
|
|
||||||
b.right.constant;b.toWatch=b.left.toWatch.concat(b.right.toWatch);break;case q.LogicalExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=b.constant?[]:[b];break;case q.ConditionalExpression:T(b.test,a);T(b.alternate,a);T(b.consequent,a);b.constant=b.test.constant&&b.alternate.constant&&b.consequent.constant;b.toWatch=b.constant?[]:[b];break;case q.Identifier:b.constant=!1;b.toWatch=[b];break;case q.MemberExpression:T(b.object,a);b.computed&&T(b.property,a);
|
|
||||||
b.constant=b.object.constant&&(!b.computed||b.property.constant);b.toWatch=[b];break;case q.CallExpression:c=b.filter?!a(b.callee.name).$stateful:!1;d=[];m(b.arguments,function(b){T(b,a);c=c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=b.filter&&!a(b.callee.name).$stateful?d:[b];break;case q.AssignmentExpression:T(b.left,a);T(b.right,a);b.constant=b.left.constant&&b.right.constant;b.toWatch=[b];break;case q.ArrayExpression:c=!0;d=[];m(b.elements,function(b){T(b,a);c=
|
|
||||||
c&&b.constant;b.constant||d.push.apply(d,b.toWatch)});b.constant=c;b.toWatch=d;break;case q.ObjectExpression:c=!0;d=[];m(b.properties,function(b){T(b.value,a);c=c&&b.value.constant;b.value.constant||d.push.apply(d,b.value.toWatch)});b.constant=c;b.toWatch=d;break;case q.ThisExpression:b.constant=!1,b.toWatch=[]}}function nd(b){if(1==b.length){b=b[0].expression;var a=b.toWatch;return 1!==a.length?a:a[0]!==b?a:t}}function od(b){return b.type===q.Identifier||b.type===q.MemberExpression}function pd(b){if(1===
|
|
||||||
b.body.length&&od(b.body[0].expression))return{type:q.AssignmentExpression,left:b.body[0].expression,right:{type:q.NGValueParameter},operator:"="}}function qd(b){return 0===b.body.length||1===b.body.length&&(b.body[0].expression.type===q.Literal||b.body[0].expression.type===q.ArrayExpression||b.body[0].expression.type===q.ObjectExpression)}function rd(b,a){this.astBuilder=b;this.$filter=a}function sd(b,a){this.astBuilder=b;this.$filter=a}function Eb(b,a,c,d){oa(b,d);a=a.split(".");for(var e,f=0;1<
|
|
||||||
a.length;f++){e=Ca(a.shift(),d);var g=oa(b[e],d);g||(g={},b[e]=g);b=g}e=Ca(a.shift(),d);oa(b[e],d);return b[e]=c}function Fb(b){return"constructor"==b}function fc(b){return z(b.valueOf)?b.valueOf():Yf.call(b)}function hf(){var b=ga(),a=ga();this.$get=["$filter","$sniffer",function(c,d){function e(a,b){return null==a||null==b?a===b:"object"===typeof a&&(a=fc(a),"object"===typeof a)?!1:a===b||a!==a&&b!==b}function f(a,b,c,d,f){var g=d.inputs,h;if(1===g.length){var k=e,g=g[0];return a.$watch(function(a){var b=
|
|
||||||
g(a);e(b,k)||(h=d(a,t,t,[b]),k=b&&fc(b));return h},b,c,f)}for(var l=[],n=[],r=0,m=g.length;r<m;r++)l[r]=e,n[r]=null;return a.$watch(function(a){for(var b=!1,c=0,f=g.length;c<f;c++){var k=g[c](a);if(b||(b=!e(k,l[c])))n[c]=k,l[c]=k&&fc(k)}b&&(h=d(a,t,t,n));return h},b,c,f)}function g(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;z(b)&&b.apply(this,arguments);w(a)&&d.$$postDigest(function(){w(f)&&e()})},c)}function h(a,b,c,d){function e(a){var b=!0;m(a,function(a){w(a)||
|
|
||||||
(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;z(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function l(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){z(b)&&b.apply(this,arguments);e()},c)}function k(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==h&&c!==g?function(c,d,e,f){e=a(c,d,e,f);return b(e,c,d)}:function(c,d,e,f){e=a(c,d,e,f);c=b(e,c,d);return w(e)?c:e};a.$$watchDelegate&&a.$$watchDelegate!==
|
|
||||||
f?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=f,c.inputs=a.inputs?a.inputs:[a]);return c}var n={csp:d.csp,expensiveChecks:!1},r={csp:d.csp,expensiveChecks:!0};return function(d,e,C){var m,u,p;switch(typeof d){case "string":p=d=d.trim();var q=C?a:b;m=q[p];m||(":"===d.charAt(0)&&":"===d.charAt(1)&&(u=!0,d=d.substring(2)),C=C?r:n,m=new gc(C),m=(new hc(m,c,C)).parse(d),m.constant?m.$$watchDelegate=l:u?m.$$watchDelegate=m.literal?h:g:m.inputs&&(m.$$watchDelegate=f),q[p]=m);return k(m,
|
|
||||||
e);case "function":return k(d,e);default:return v}}}]}function kf(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return td(function(a){b.$evalAsync(a)},a)}]}function lf(){this.$get=["$browser","$exceptionHandler",function(b,a){return td(function(a){b.defer(a)},a)}]}function td(b,a){function c(a,b,c){function d(b){return function(c){e||(e=!0,b.call(a,c))}}var e=!1;return[d(b),d(c)]}function d(){this.$$state={status:0}}function e(a,b){return function(c){b.call(a,c)}}function f(c){!c.processScheduled&&
|
|
||||||
c.pending&&(c.processScheduled=!0,b(function(){var b,d,e;e=c.pending;c.processScheduled=!1;c.pending=t;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{z(b)?d.resolve(b(c.value)):1===c.status?d.resolve(c.value):d.reject(c.value)}catch(h){d.reject(h),a(h)}}}))}function g(){this.promise=new d;this.resolve=e(this,this.resolve);this.reject=e(this,this.reject);this.notify=e(this,this.notify)}var h=J("$q",TypeError);d.prototype={then:function(a,b,c){var d=new g;this.$$state.pending=this.$$state.pending||
|
|
||||||
[];this.$$state.pending.push([d,a,b,c]);0<this.$$state.status&&f(this.$$state);return d.promise},"catch":function(a){return this.then(null,a)},"finally":function(a,b){return this.then(function(b){return k(b,!0,a)},function(b){return k(b,!1,a)},b)}};g.prototype={resolve:function(a){this.promise.$$state.status||(a===this.promise?this.$$reject(h("qcycle",a)):this.$$resolve(a))},$$resolve:function(b){var d,e;e=c(this,this.$$resolve,this.$$reject);try{if(H(b)||z(b))d=b&&b.then;z(d)?(this.promise.$$state.status=
|
|
||||||
-1,d.call(b,e[0],e[1],this.notify)):(this.promise.$$state.value=b,this.promise.$$state.status=1,f(this.promise.$$state))}catch(g){e[1](g),a(g)}},reject:function(a){this.promise.$$state.status||this.$$reject(a)},$$reject:function(a){this.promise.$$state.value=a;this.promise.$$state.status=2;f(this.promise.$$state)},notify:function(c){var d=this.promise.$$state.pending;0>=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;f<g;f++){e=d[f][0];b=d[f][3];try{e.notify(z(b)?
|
|
||||||
b(c):c)}catch(h){a(h)}}})}};var l=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},k=function(a,b,c){var d=null;try{z(c)&&(d=c())}catch(e){return l(e,!1)}return d&&z(d.then)?d.then(function(){return l(a,b)},function(a){return l(a,!1)}):l(a,b)},n=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},r=function x(a){if(!z(a))throw h("norslvr",a);if(!(this instanceof x))return new x(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
|
|
||||||
r.defer=function(){return new g};r.reject=function(a){var b=new g;b.reject(a);return b.promise};r.when=n;r.resolve=n;r.all=function(a){var b=new g,c=0,d=G(a)?[]:{};m(a,function(a,e){c++;n(a).then(function(a){d.hasOwnProperty(e)||(d[e]=a,--c||b.resolve(d))},function(a){d.hasOwnProperty(e)||b.reject(a)})});0===c&&b.resolve(d);return b.promise};return r}function uf(){this.$get=["$window","$timeout",function(b,a){function c(){for(var a=0;a<n.length;a++){var b=n[a];b&&(n[a]=null,b())}k=n.length=0}function d(a){var b=
|
|
||||||
n.length;k++;n.push(a);0===b&&(l=h(c));return function(){0<=b&&(b=n[b]=null,0===--k&&l&&(l(),l=null,n.length=0))}}var e=b.requestAnimationFrame||b.webkitRequestAnimationFrame,f=b.cancelAnimationFrame||b.webkitCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,g=!!e,h=g?function(a){var b=e(a);return function(){f(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};d.supported=g;var l,k=0,n=[];return d}]}function jf(){function b(a){function b(){this.$$watchers=this.$$nextSibling=
|
|
||||||
this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$id=++nb;this.$$ChildScope=null}b.prototype=a;return b}var a=10,c=J("$rootScope"),d=null,e=null;this.digestTtl=function(b){arguments.length&&(a=b);return a};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(f,g,h,l){function k(a){a.currentScope.$$destroyed=!0}function n(){this.$id=++nb;this.$$phase=this.$parent=this.$$watchers=this.$$nextSibling=this.$$prevSibling=this.$$childHead=
|
|
||||||
this.$$childTail=null;this.$root=this;this.$$destroyed=!1;this.$$listeners={};this.$$listenerCount={};this.$$watchersCount=0;this.$$isolateBindings=null}function r(a){if(p.$$phase)throw c("inprog",p.$$phase);p.$$phase=a}function s(a,b){do a.$$watchersCount+=b;while(a=a.$parent)}function x(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function q(){}function F(){for(;I.length;)try{I.shift()()}catch(a){g(a)}e=null}function u(){null===e&&(e=
|
|
||||||
l.defer(function(){p.$apply(F)}))}n.prototype={constructor:n,$new:function(a,c){var d;c=c||this;a?(d=new n,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=b(this)),d=new this.$$ChildScope);d.$parent=c;d.$$prevSibling=c.$$childTail;c.$$childHead?(c.$$childTail.$$nextSibling=d,c.$$childTail=d):c.$$childHead=c.$$childTail=d;(a||c!=this)&&d.$on("$destroy",k);return d},$watch:function(a,b,c,e){var f=h(a);if(f.$$watchDelegate)return f.$$watchDelegate(this,b,c,f,a);var g=this,k=g.$$watchers,l=
|
|
||||||
{fn:b,last:q,get:f,exp:e||a,eq:!!c};d=null;z(b)||(l.fn=v);k||(k=g.$$watchers=[]);k.unshift(l);s(this,1);return function(){0<=bb(k,l)&&s(g,-1);d=null}},$watchGroup:function(a,b){function c(){h=!1;k?(k=!1,b(e,e,g)):b(e,d,g)}var d=Array(a.length),e=Array(a.length),f=[],g=this,h=!1,k=!0;if(!a.length){var l=!0;g.$evalAsync(function(){l&&b(e,e,g)});return function(){l=!1}}if(1===a.length)return this.$watch(a[0],function(a,c,f){e[0]=a;d[0]=c;b(e,a===c?e:d,f)});m(a,function(a,b){var k=g.$watch(a,function(a,
|
|
||||||
f){e[b]=a;d[b]=f;h||(h=!0,g.$evalAsync(c))});f.push(k)});return function(){for(;f.length;)f.shift()()}},$watchCollection:function(a,b){function c(a){e=a;var b,d,g,h;if(!A(e)){if(H(e))if(Ea(e))for(f!==r&&(f=r,m=f.length=0,l++),a=e.length,m!==a&&(l++,f.length=m=a),b=0;b<a;b++)h=f[b],g=e[b],d=h!==h&&g!==g,d||h===g||(l++,f[b]=g);else{f!==s&&(f=s={},m=0,l++);a=0;for(b in e)e.hasOwnProperty(b)&&(a++,g=e[b],h=f[b],b in f?(d=h!==h&&g!==g,d||h===g||(l++,f[b]=g)):(m++,f[b]=g,l++));if(m>a)for(b in l++,f)e.hasOwnProperty(b)||
|
|
||||||
(m--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,g,k=1<b.length,l=0,n=h(a,c),r=[],s={},p=!0,m=0;return this.$watch(n,function(){p?(p=!1,b(e,e,d)):b(e,g,d);if(k)if(H(e))if(Ea(e)){g=Array(e.length);for(var a=0;a<e.length;a++)g[a]=e[a]}else for(a in g={},e)Xa.call(e,a)&&(g[a]=e[a]);else g=e})},$digest:function(){var b,f,h,k,n,s,m=a,x,u=[],E,I;r("$digest");l.$$checkUrlChange();this===p&&null!==e&&(l.defer.cancel(e),F());d=null;do{s=!1;for(x=this;t.length;){try{I=t.shift(),
|
|
||||||
I.scope.$eval(I.expression,I.locals)}catch(v){g(v)}d=null}a:do{if(k=x.$$watchers)for(n=k.length;n--;)try{if(b=k[n])if((f=b.get(x))!==(h=b.last)&&!(b.eq?ka(f,h):"number"===typeof f&&"number"===typeof h&&isNaN(f)&&isNaN(h)))s=!0,d=b,b.last=b.eq?fa(f,null):f,b.fn(f,h===q?f:h,x),5>m&&(E=4-m,u[E]||(u[E]=[]),u[E].push({msg:z(b.exp)?"fn: "+(b.exp.name||b.exp.toString()):b.exp,newVal:f,oldVal:h}));else if(b===d){s=!1;break a}}catch(A){g(A)}if(!(k=x.$$watchersCount&&x.$$childHead||x!==this&&x.$$nextSibling))for(;x!==
|
|
||||||
this&&!(k=x.$$nextSibling);)x=x.$parent}while(x=k);if((s||t.length)&&!m--)throw p.$$phase=null,c("infdig",a,u);}while(s||t.length);for(p.$$phase=null;w.length;)try{w.shift()()}catch(y){g(y)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;this===p&&l.$$applicationDestroyed();s(this,-this.$$watchersCount);for(var b in this.$$listenerCount)x(this,this.$$listenerCount[b],b);a&&a.$$childHead==this&&(a.$$childHead=this.$$nextSibling);a&&a.$$childTail==
|
|
||||||
this&&(a.$$childTail=this.$$prevSibling);this.$$prevSibling&&(this.$$prevSibling.$$nextSibling=this.$$nextSibling);this.$$nextSibling&&(this.$$nextSibling.$$prevSibling=this.$$prevSibling);this.$destroy=this.$digest=this.$apply=this.$evalAsync=this.$applyAsync=v;this.$on=this.$watch=this.$watchGroup=function(){return v};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=null}},$eval:function(a,b){return h(a)(this,b)},
|
|
||||||
$evalAsync:function(a,b){p.$$phase||t.length||l.defer(function(){t.length&&p.$digest()});t.push({scope:this,expression:a,locals:b})},$$postDigest:function(a){w.push(a)},$apply:function(a){try{return r("$apply"),this.$eval(a)}catch(b){g(b)}finally{p.$$phase=null;try{p.$digest()}catch(c){throw g(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&I.push(b);u()},$on:function(a,b){var c=this.$$listeners[a];c||(this.$$listeners[a]=c=[]);c.push(b);var d=this;do d.$$listenerCount[a]||
|
|
||||||
(d.$$listenerCount[a]=0),d.$$listenerCount[a]++;while(d=d.$parent);var e=this;return function(){var d=c.indexOf(b);-1!==d&&(c[d]=null,x(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,f=!1,h={name:a,targetScope:e,stopPropagation:function(){f=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=cb([h],arguments,1),l,n;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(n=d.length;l<n;l++)if(d[l])try{d[l].apply(null,k)}catch(r){g(r)}else d.splice(l,1),l--,n--;if(f)return h.currentScope=
|
|
||||||
null,h;e=e.$parent}while(e);h.currentScope=null;return h},$broadcast:function(a,b){var c=this,d=this,e={name:a,targetScope:this,preventDefault:function(){e.defaultPrevented=!0},defaultPrevented:!1};if(!this.$$listenerCount[a])return e;for(var f=cb([e],arguments,1),h,k;c=d;){e.currentScope=c;d=c.$$listeners[a]||[];h=0;for(k=d.length;h<k;h++)if(d[h])try{d[h].apply(null,f)}catch(l){g(l)}else d.splice(h,1),h--,k--;if(!(d=c.$$listenerCount[a]&&c.$$childHead||c!==this&&c.$$nextSibling))for(;c!==this&&!(d=
|
|
||||||
c.$$nextSibling);)c=c.$parent}e.currentScope=null;return e}};var p=new n,t=p.$$asyncQueue=[],w=p.$$postDigestQueue=[],I=p.$$applyAsyncQueue=[];return p}]}function he(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(a){return w(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return w(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Ba(c).href;return""===f||f.match(e)?c:"unsafe:"+
|
|
||||||
f}}}function Zf(b){if("self"===b)return b;if(L(b)){if(-1<b.indexOf("***"))throw Da("iwcard",b);b=ud(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(Za(b))return new RegExp("^"+b.source+"$");throw Da("imatcher");}function vd(b){var a=[];w(b)&&m(b,function(b){a.push(Zf(b))});return a}function nf(){this.SCE_CONTEXTS=pa;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=vd(a));return b};this.resourceUrlBlacklist=function(b){arguments.length&&
|
|
||||||
(a=vd(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?gd(b):!!a.exec(b.href)}function e(a){var b=function(a){this.$$unwrapTrustedValue=function(){return a}};a&&(b.prototype=new a);b.prototype.valueOf=function(){return this.$$unwrapTrustedValue()};b.prototype.toString=function(){return this.$$unwrapTrustedValue().toString()};return b}var f=function(a){throw Da("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[pa.HTML]=e(g);h[pa.CSS]=e(g);h[pa.URL]=
|
|
||||||
e(g);h[pa.JS]=e(g);h[pa.RESOURCE_URL]=e(h[pa.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Da("icontext",a,b);if(null===b||b===t||""===b)return b;if("string"!==typeof b)throw Da("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===t||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===pa.RESOURCE_URL){var g=Ba(e.toString()),r,s,m=!1;r=0;for(s=b.length;r<s;r++)if(d(b[r],g)){m=!0;break}if(m)for(r=
|
|
||||||
0,s=a.length;r<s;r++)if(d(a[r],g)){m=!1;break}if(m)return e;throw Da("insecurl",e.toString());}if(c===pa.HTML)return f(e);throw Da("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function mf(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ua)throw Da("iequirks");var d=ia(pa);d.isEnabled=function(){return b};d.trustAs=c.trustAs;d.getTrusted=c.getTrusted;d.valueOf=c.valueOf;b||(d.trustAs=
|
|
||||||
d.getTrusted=function(a,b){return b},d.valueOf=Ya);d.parseAs=function(b,c){var e=a(c);return e.literal&&e.constant?e:a(c,function(a){return d.getTrusted(b,a)})};var e=d.parseAs,f=d.getTrusted,g=d.trustAs;m(pa,function(a,b){var c=M(b);d[hb("parse_as_"+c)]=function(b){return e(a,b)};d[hb("get_trusted_"+c)]=function(b){return f(a,b)};d[hb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function of(){this.$get=["$window","$document",function(b,a){var c={},d=W((/android (\d+)/.exec(M((b.navigator||
|
|
||||||
{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,l=f.body&&f.body.style,k=!1,n=!1;if(l){for(var r in l)if(k=h.exec(r)){g=k[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in l&&"webkit");k=!!("transition"in l||g+"Transition"in l);n=!!("animation"in l||g+"Animation"in l);!d||k&&n||(k=L(l.webkitTransition),n=L(l.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"===
|
|
||||||
a&&11>=Ua)return!1;if(A(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:fb(),vendorPrefix:g,transitions:k,animations:n,android:d}}]}function qf(){this.$get=["$templateCache","$http","$q","$sce",function(b,a,c,d){function e(f,g){e.totalPendingRequests++;L(f)&&b.get(f)||(f=d.getTrustedResourceUrl(f));var h=a.defaults&&a.defaults.transformResponse;G(h)?h=h.filter(function(a){return a!==$b}):h===$b&&(h=null);return a.get(f,{cache:b,transformResponse:h})["finally"](function(){e.totalPendingRequests--}).then(function(a){b.put(f,
|
|
||||||
a.data);return a.data},function(a){if(!g)throw ea("tpload",f,a.status,a.statusText);return c.reject(a)})}e.totalPendingRequests=0;return e}]}function rf(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];m(a,function(a){var d=ca.element(a).data("$binding");d&&m(d,function(d){c?(new RegExp("(^|\\s)"+ud(b)+"(\\s|\\||$)")).test(d)&&g.push(a):-1!=d.indexOf(b)&&g.push(a)})});return g},findModels:function(a,
|
|
||||||
b,c){for(var g=["ng-","data-ng-","ng\\:"],h=0;h<g.length;++h){var l=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(l.length)return l}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function sf(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,l,k){z(f)||(k=l,l=f,f=v);var n=za.call(arguments,3),r=w(k)&&!k,s=(r?d:c).defer(),
|
|
||||||
m=s.promise,q;q=a.defer(function(){try{s.resolve(f.apply(null,n))}catch(a){s.reject(a),e(a)}finally{delete g[m.$$timeoutId]}r||b.$apply()},l);m.$$timeoutId=q;g[q]=s;return m}var g={};f.cancel=function(b){return b&&b.$$timeoutId in g?(g[b.$$timeoutId].reject("canceled"),delete g[b.$$timeoutId],a.defer.cancel(b.$$timeoutId)):!1};return f}]}function Ba(b){Ua&&(X.setAttribute("href",b),b=X.href);X.setAttribute("href",b);return{href:X.href,protocol:X.protocol?X.protocol.replace(/:$/,""):"",host:X.host,
|
|
||||||
search:X.search?X.search.replace(/^\?/,""):"",hash:X.hash?X.hash.replace(/^#/,""):"",hostname:X.hostname,port:X.port,pathname:"/"===X.pathname.charAt(0)?X.pathname:"/"+X.pathname}}function gd(b){b=L(b)?Ba(b):b;return b.protocol===wd.protocol&&b.host===wd.host}function tf(){this.$get=ra(O)}function xd(b){function a(a){try{return decodeURIComponent(a)}catch(b){return a}}var c=b[0]||{},d={},e="";return function(){var b,g,h,l,k;b=c.cookie||"";if(b!==e)for(e=b,b=e.split("; "),d={},h=0;h<b.length;h++)g=
|
|
||||||
b[h],l=g.indexOf("="),0<l&&(k=a(g.substring(0,l)),d[k]===t&&(d[k]=a(g.substring(l+1))));return d}}function xf(){this.$get=xd}function Lc(b){function a(c,d){if(H(c)){var e={};m(c,function(b,c){e[c]=a(c,b)});return e}return b.factory(c+"Filter",d)}this.register=a;this.$get=["$injector",function(a){return function(b){return a.get(b+"Filter")}}];a("currency",yd);a("date",zd);a("filter",$f);a("json",ag);a("limitTo",bg);a("lowercase",cg);a("number",Ad);a("orderBy",Bd);a("uppercase",dg)}function $f(){return function(b,
|
|
||||||
a,c){if(!Ea(b)){if(null==b)return b;throw J("filter")("notarray",b);}var d;switch(ic(a)){case "function":break;case "boolean":case "null":case "number":case "string":d=!0;case "object":a=eg(a,c,d);break;default:return b}return Array.prototype.filter.call(b,a)}}function eg(b,a,c){var d=H(b)&&"$"in b;!0===a?a=ka:z(a)||(a=function(a,b){if(A(a))return!1;if(null===a||null===b)return a===b;if(H(b)||H(a)&&!rc(a))return!1;a=M(""+a);b=M(""+b);return-1!==a.indexOf(b)});return function(e){return d&&!H(e)?La(e,
|
|
||||||
b.$,a,!1):La(e,b,a,c)}}function La(b,a,c,d,e){var f=ic(b),g=ic(a);if("string"===g&&"!"===a.charAt(0))return!La(b,a.substring(1),c,d);if(G(b))return b.some(function(b){return La(b,a,c,d)});switch(f){case "object":var h;if(d){for(h in b)if("$"!==h.charAt(0)&&La(b[h],a,c,!0))return!0;return e?!1:La(b,a,c,!1)}if("object"===g){for(h in a)if(e=a[h],!z(e)&&!A(e)&&(f="$"===h,!La(f?b:b[h],e,c,f,f)))return!1;return!0}return c(b,a);case "function":return!1;default:return c(b,a)}}function ic(b){return null===
|
|
||||||
b?"null":typeof b}function yd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){A(d)&&(d=a.CURRENCY_SYM);A(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:Cd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function Ad(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:Cd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function Cd(b,a,c,d,e){if(H(b))return"";var f=0>b;b=Math.abs(b);var g=Infinity===b;if(!g&&!isFinite(b))return"";var h=b+"",l="",k=!1,n=[];g&&(l="\u221e");
|
|
||||||
if(!g&&-1!==h.indexOf("e")){var r=h.match(/([\d\.]+)e(-?)(\d+)/);r&&"-"==r[2]&&r[3]>e+1?b=0:(l=h,k=!0)}if(g||k)0<e&&1>b&&(l=b.toFixed(e),b=parseFloat(l));else{g=(h.split(Dd)[1]||"").length;A(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);var g=(""+b).split(Dd),h=g[0],g=g[1]||"",r=0,s=a.lgSize,m=a.gSize;if(h.length>=s+m)for(r=h.length-s,k=0;k<r;k++)0===(r-k)%m&&0!==k&&(l+=c),l+=h.charAt(k);for(k=r;k<h.length;k++)0===(h.length-k)%s&&0!==k&&
|
|
||||||
(l+=c),l+=h.charAt(k);for(;g.length<e;)g+="0";e&&"0"!==e&&(l+=d+g.substr(0,e))}0===b&&(f=!1);n.push(f?a.negPre:a.posPre,l,f?a.negSuf:a.posSuf);return n.join("")}function Gb(b,a,c){var d="";0>b&&(d="-",b=-b);for(b=""+b;b.length<a;)b="0"+b;c&&(b=b.substr(b.length-a));return d+b}function Y(b,a,c,d){c=c||0;return function(e){e=e["get"+b]();if(0<c||e>-c)e+=c;0===e&&-12==c&&(e=12);return Gb(e,a,d)}}function Hb(b,a){return function(c,d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function Ed(b){var a=
|
|
||||||
(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function Fd(b){return function(a){var c=Ed(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Gb(a,b)}}function jc(b,a){return 0>=b.getFullYear()?a.ERAS[0]:a.ERAS[1]}function zd(b){function a(a){var b;if(b=a.match(c)){a=new Date(0);var f=0,g=0,h=b[8]?a.setUTCFullYear:a.setFullYear,l=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=W(b[9]+b[10]),g=W(b[9]+b[11]));h.call(a,W(b[1]),
|
|
||||||
W(b[2])-1,W(b[3]));f=W(b[4]||0)-f;g=W(b[5]||0)-g;h=W(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));l.call(a,f,g,h,b)}return a}var c=/^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/;return function(c,e,f){var g="",h=[],l,k;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;L(c)&&(c=fg.test(c)?W(c):a(c));V(c)&&(c=new Date(c));if(!aa(c)||!isFinite(c.getTime()))return c;for(;e;)(k=gg.exec(e))?(h=cb(h,k,1),e=h.pop()):(h.push(e),e=null);var n=c.getTimezoneOffset();
|
|
||||||
f&&(n=xc(f,c.getTimezoneOffset()),c=Pb(c,f,!0));m(h,function(a){l=hg[a];g+=l?l(c,b.DATETIME_FORMATS,n):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function ag(){return function(b,a){A(a)&&(a=2);return db(b,a)}}function bg(){return function(b,a,c){a=Infinity===Math.abs(Number(a))?Number(a):W(a);if(isNaN(a))return b;V(b)&&(b=b.toString());if(!G(b)&&!L(b))return b;c=!c||isNaN(c)?0:W(c);c=0>c&&c>=-b.length?b.length+c:c;return 0<=a?b.slice(c,c+a):0===c?b.slice(a,b.length):b.slice(Math.max(0,
|
|
||||||
c+a),c)}}function Bd(b){function a(a,c){c=c?-1:1;return a.map(function(a){var d=1,h=Ya;if(z(a))h=a;else if(L(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))d="-"==a.charAt(0)?-1:1,a=a.substring(1);if(""!==a&&(h=b(a),h.constant))var l=h(),h=function(a){return a[l]}}return{get:h,descending:d*c}})}function c(a){switch(typeof a){case "number":case "boolean":case "string":return!0;default:return!1}}return function(b,e,f){if(!Ea(b))return b;G(e)||(e=[e]);0===e.length&&(e=["+"]);var g=a(e,f);b=Array.prototype.map.call(b,
|
|
||||||
function(a,b){return{value:a,predicateValues:g.map(function(d){var e=d.get(a);d=typeof e;if(null===e)d="string",e="null";else if("string"===d)e=e.toLowerCase();else if("object"===d)a:{if("function"===typeof e.valueOf&&(e=e.valueOf(),c(e)))break a;if(rc(e)&&(e=e.toString(),c(e)))break a;e=b}return{value:e,type:d}})}});b.sort(function(a,b){for(var c=0,d=0,e=g.length;d<e;++d){var c=a.predicateValues[d],f=b.predicateValues[d],m=0;c.type===f.type?c.value!==f.value&&(m=c.value<f.value?-1:1):m=c.type<f.type?
|
|
||||||
-1:1;if(c=m*g[d].descending)break}return c});return b=b.map(function(a){return a.value})}}function Ma(b){z(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ra(b)}function Gd(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Ib;f.$error={};f.$$success={};f.$pending=t;f.$name=e(a.name||a.ngForm||"")(c);f.$dirty=!1;f.$pristine=!0;f.$valid=!0;f.$invalid=!1;f.$submitted=!1;h.$addControl(f);f.$rollbackViewValue=function(){m(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=
|
|
||||||
function(){m(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){Ra(a.$name,"input");g.push(a);a.$name&&(f[a.$name]=a)};f.$$renameControl=function(a,b){var c=a.$name;f[c]===a&&delete f[c];f[b]=a;a.$name=b};f.$removeControl=function(a){a.$name&&f[a.$name]===a&&delete f[a.$name];m(f.$pending,function(b,c){f.$setValidity(c,null,a)});m(f.$error,function(b,c){f.$setValidity(c,null,a)});m(f.$$success,function(b,c){f.$setValidity(c,null,a)});bb(g,a)};Hd({ctrl:this,$element:b,set:function(a,b,
|
|
||||||
c){var d=a[b];d?-1===d.indexOf(c)&&d.push(c):a[b]=[c]},unset:function(a,b,c){var d=a[b];d&&(bb(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Va);d.addClass(b,Jb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Va,Jb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;f.$submitted=!1;m(g,function(a){a.$setPristine()})};f.$setUntouched=function(){m(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,
|
|
||||||
"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function kc(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function kb(b,a,c,d,e,f){var g=M(a[0].type);if(!e.android){var h=!1;a.on("compositionstart",function(a){h=!0});a.on("compositionend",function(){h=!1;l()})}var l=function(b){k&&(f.defer.cancel(k),k=null);if(!h){var e=a.val();b=b&&b.type;"password"===g||c.ngTrim&&"false"===c.ngTrim||(e=R(e));(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,b)}};
|
|
||||||
if(e.hasEvent("input"))a.on("input",l);else{var k,n=function(a,b,c){k||(k=f.defer(function(){k=null;b&&b.value===c||l(a)}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||n(a,this,this.value)});if(e.hasEvent("paste"))a.on("paste cut",n)}a.on("change",l);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?"":d.$viewValue)}}function Kb(b,a){return function(c,d){var e,f;if(aa(c))return c;if(L(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));
|
|
||||||
if(ig.test(c))return new Date(c);b.lastIndex=0;if(e=b.exec(c))return e.shift(),f=d?{yyyy:d.getFullYear(),MM:d.getMonth()+1,dd:d.getDate(),HH:d.getHours(),mm:d.getMinutes(),ss:d.getSeconds(),sss:d.getMilliseconds()/1E3}:{yyyy:1970,MM:1,dd:1,HH:0,mm:0,ss:0,sss:0},m(e,function(b,c){c<a.length&&(f[a[c]]=+b)}),new Date(f.yyyy,f.MM-1,f.dd,f.HH,f.mm,f.ss||0,1E3*f.sss||0)}return NaN}}function lb(b,a,c,d){return function(e,f,g,h,l,k,n){function r(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return w(a)?
|
|
||||||
aa(a)?a:c(a):t}Id(e,f,g,h);kb(e,f,g,h,l,k);var m=h&&h.$options&&h.$options.timezone,q;h.$$parserName=b;h.$parsers.push(function(b){return h.$isEmpty(b)?null:a.test(b)?(b=c(b,q),m&&(b=Pb(b,m)),b):t});h.$formatters.push(function(a){if(a&&!aa(a))throw Lb("datefmt",a);if(r(a))return(q=a)&&m&&(q=Pb(q,m,!0)),n("date")(a,d,m);q=null;return""});if(w(g.min)||g.ngMin){var F;h.$validators.min=function(a){return!r(a)||A(F)||c(a)>=F};g.$observe("min",function(a){F=s(a);h.$validate()})}if(w(g.max)||g.ngMax){var u;
|
|
||||||
h.$validators.max=function(a){return!r(a)||A(u)||c(a)<=u};g.$observe("max",function(a){u=s(a);h.$validate()})}}}function Id(b,a,c,d){(d.$$hasNativeValidators=H(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||{};return c.badInput&&!c.typeMismatch?t:b})}function Jd(b,a,c,d,e){if(w(d)){b=b(d);if(!b.constant)throw J("ngModel")("constexpr",c,d);return b(a)}return e}function lc(b,a){b="ngClass"+b;return["$animate",function(c){function d(a,b){var c=[],d=0;a:for(;d<a.length;d++){for(var e=
|
|
||||||
a[d],n=0;n<b.length;n++)if(e==b[n])continue a;c.push(e)}return c}function e(a){var b=[];return G(a)?(m(a,function(a){b=b.concat(e(a))}),b):L(a)?a.split(" "):H(a)?(m(a,function(a,c){a&&(b=b.concat(c.split(" ")))}),b):a}return{restrict:"AC",link:function(f,g,h){function l(a,b){var c=g.data("$classCounts")||ga(),d=[];m(a,function(a){if(0<b||c[a])c[a]=(c[a]||0)+b,c[a]===+(0<b)&&d.push(a)});g.data("$classCounts",c);return d.join(" ")}function k(b){if(!0===a||f.$index%2===a){var k=e(b||[]);if(!n){var m=
|
|
||||||
l(k,1);h.$addClass(m)}else if(!ka(b,n)){var q=e(n),m=d(k,q),k=d(q,k),m=l(m,1),k=l(k,-1);m&&m.length&&c.addClass(g,m);k&&k.length&&c.removeClass(g,k)}}n=ia(b)}var n;f.$watch(h[b],k,!0);h.$observe("class",function(a){k(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var k=e(f.$eval(h[b]));g===a?(g=l(k,1),h.$addClass(g)):(g=l(k,-1),h.$removeClass(g))}})}}}]}function Hd(b){function a(a,b){b&&!f[a]?(k.addClass(e,a),f[a]=!0):!b&&f[a]&&(k.removeClass(e,a),f[a]=!1)}
|
|
||||||
function c(b,c){b=b?"-"+Bc(b,"-"):"";a(mb+b,!0===c);a(Kd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,l=b.parentForm,k=b.$animate;f[Kd]=!(f[mb]=e.hasClass(mb));d.$setValidity=function(b,e,f){e===t?(d.$pending||(d.$pending={}),g(d.$pending,b,f)):(d.$pending&&h(d.$pending,b,f),Ld(d.$pending)&&(d.$pending=t));ab(e)?e?(h(d.$error,b,f),g(d.$$success,b,f)):(g(d.$error,b,f),h(d.$$success,b,f)):(h(d.$error,b,f),h(d.$$success,b,f));d.$pending?(a(Md,!0),d.$valid=d.$invalid=t,c("",null)):(a(Md,
|
|
||||||
!1),d.$valid=Ld(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?t:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);l.$setValidity(b,e,d)}}function Ld(b){if(b)for(var a in b)if(b.hasOwnProperty(a))return!1;return!0}var jg=/^\/(.+)\/([a-z]*)$/,M=function(b){return L(b)?b.toLowerCase():b},Xa=Object.prototype.hasOwnProperty,rb=function(b){return L(b)?b.toUpperCase():b},Ua,y,la,za=[].slice,Mf=[].splice,kg=[].push,sa=Object.prototype.toString,sc=Object.getPrototypeOf,Fa=J("ng"),ca=
|
|
||||||
O.angular||(O.angular={}),gb,nb=0;Ua=U.documentMode;v.$inject=[];Ya.$inject=[];var G=Array.isArray,uc=/^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/,R=function(b){return L(b)?b.trim():b},ud=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},fb=function(){if(w(fb.isActive_))return fb.isActive_;var b=!(!U.querySelector("[ng-csp]")&&!U.querySelector("[data-ng-csp]"));if(!b)try{new Function("")}catch(a){b=!0}return fb.isActive_=
|
|
||||||
b},pb=function(){if(w(pb.name_))return pb.name_;var b,a,c=Oa.length,d,e;for(a=0;a<c;++a)if(d=Oa[a],b=U.querySelector("["+d.replace(":","\\:")+"jq]")){e=b.getAttribute(d+"jq");break}return pb.name_=e},Oa=["ng-","data-ng-","ng:","x-ng-"],be=/[A-Z]/g,Cc=!1,Rb,qa=1,Na=3,fe={full:"1.4.3",major:1,minor:4,dot:3,codeName:"foam-acceleration"};Q.expando="ng339";var ib=Q.cache={},Df=1;Q._data=function(b){return this.cache[b[this.expando]]||{}};var yf=/([\:\-\_]+(.))/g,zf=/^moz([A-Z])/,lg={mouseleave:"mouseout",
|
|
||||||
mouseenter:"mouseover"},Ub=J("jqLite"),Cf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Tb=/<|&#?\w+;/,Af=/<([\w:]+)/,Bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,na={option:[1,'<select multiple="multiple">',"</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};na.optgroup=na.option;na.tbody=na.tfoot=na.colgroup=na.caption=na.thead;
|
|
||||||
na.th=na.td;var Pa=Q.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===U.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),Q(O).on("load",a))},toString:function(){var b=[];m(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?y(this[b]):y(this[this.length+b])},length:0,push:kg,sort:[].sort,splice:[].splice},Ab={};m("multiple selected checked disabled readOnly required open".split(" "),function(b){Ab[M(b)]=b});var Tc={};m("input select option textarea button form details".split(" "),
|
|
||||||
function(b){Tc[b]=!0});var Uc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};m({data:Wb,removeData:ub,hasData:function(b){for(var a in ib[b.ng339])return!0;return!1}},function(b,a){Q[a]=b});m({data:Wb,inheritedData:zb,scope:function(b){return y.data(b,"$scope")||zb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return y.data(b,"$isolateScope")||y.data(b,"$isolateScopeNoTemplate")},controller:Qc,injector:function(b){return zb(b,
|
|
||||||
"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:wb,css:function(b,a,c){a=hb(a);if(w(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=b.nodeType;if(d!==Na&&2!==d&&8!==d)if(d=M(a),Ab[d])if(w(c))c?(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||v).specified?d:t;else if(w(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?t:b},prop:function(b,a,c){if(w(c))b[a]=c;else return b[a]},
|
|
||||||
text:function(){function b(a,b){if(A(b)){var d=a.nodeType;return d===qa||d===Na?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(A(a)){if(b.multiple&&"select"===ta(b)){var c=[];m(b.options,function(a){a.selected&&c.push(a.value||a.text)});return 0===c.length?null:c}return b.value}b.value=a},html:function(b,a){if(A(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Rc},function(b,a){Q.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Rc&&(2==b.length&&b!==wb&&b!==Qc?
|
|
||||||
a:d)===t){if(H(a)){for(e=0;e<g;e++)if(b===Wb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===t?Math.min(g,1):g;for(f=0;f<g;f++){var h=b(this[f],a,d);e=e?e+h:h}return e}for(e=0;e<g;e++)b(this[e],a,d);return this}});m({removeData:ub,on:function a(c,d,e,f){if(w(f))throw Ub("onargs");if(Mc(c)){var g=vb(c,!0);f=g.events;var h=g.handle;h||(h=g.handle=Gf(c,f));for(var g=0<=d.indexOf(" ")?d.split(" "):[d],l=g.length;l--;){d=g[l];var k=f[d];k||(f[d]=[],"mouseenter"===d||"mouseleave"===
|
|
||||||
d?a(c,lg[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),k=f[d]);k.push(e)}}},off:Pc,one:function(a,c,d){a=y(a);a.on(c,function f(){a.off(c,d);a.off(c,f)});a.on(c,d)},replaceWith:function(a,c){var d,e=a.parentNode;tb(a);m(new Q(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];m(a.childNodes,function(a){a.nodeType===qa&&c.push(a)});return c},contents:function(a){return a.contentDocument||
|
|
||||||
a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===qa||11===d){c=new Q(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===qa){var d=a.firstChild;m(new Q(c),function(c){a.insertBefore(c,d)})}},wrap:function(a,c){c=y(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Xb,detach:function(a){Xb(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new Q(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,
|
|
||||||
d.nextSibling);d=h}},addClass:yb,removeClass:xb,toggleClass:function(a,c,d){c&&m(c.split(" "),function(c){var f=d;A(f)&&(f=!wb(a,c));(f?yb:xb)(a,c)})},parent:function(a){return(a=a.parentNode)&&11!==a.nodeType?a:null},next:function(a){return a.nextElementSibling},find:function(a,c){return a.getElementsByTagName?a.getElementsByTagName(c):[]},clone:Vb,triggerHandler:function(a,c,d){var e,f,g=c.type||c,h=vb(a);if(h=(h=h&&h.events)&&h[g])e={preventDefault:function(){this.defaultPrevented=!0},isDefaultPrevented:function(){return!0===
|
|
||||||
this.defaultPrevented},stopImmediatePropagation:function(){this.immediatePropagationStopped=!0},isImmediatePropagationStopped:function(){return!0===this.immediatePropagationStopped},stopPropagation:v,type:g,target:a},c.type&&(e=P(e,c)),c=ia(h),f=d?[e].concat(d):[e],m(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){Q.prototype[c]=function(c,e,f){for(var g,h=0,l=this.length;h<l;h++)A(g)?(g=a(this[h],c,e,f),w(g)&&(g=y(g))):Oc(g,a(this[h],c,e,f));return w(g)?g:this};Q.prototype.bind=
|
|
||||||
Q.prototype.on;Q.prototype.unbind=Q.prototype.off});Sa.prototype={put:function(a,c){this[Ga(a,this.nextUid)]=c},get:function(a){return this[Ga(a,this.nextUid)]},remove:function(a){var c=this[a=Ga(a,this.nextUid)];delete this[a];return c}};var wf=[function(){this.$get=[function(){return Sa}]}],Wc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,mg=/,/,ng=/^\s*(_?)(\S+?)\1\s*$/,Vc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ha=J("$injector");eb.$$annotate=function(a,c,d){var e;if("function"===typeof a){if(!(e=a.$inject)){e=
|
|
||||||
[];if(a.length){if(c)throw L(d)&&d||(d=a.name||Hf(a)),Ha("strictdi",d);c=a.toString().replace(Vc,"");c=c.match(Wc);m(c[1].split(mg),function(a){a.replace(ng,function(a,c,d){e.push(d)})})}a.$inject=e}}else G(a)?(c=a.length-1,Qa(a[c],"fn"),e=a.slice(0,c)):Qa(a,"fn",!0);return e};var Nd=J("$animate"),Ue=function(){this.$get=["$q","$$rAF",function(a,c){function d(){}d.all=v;d.chain=v;d.prototype={end:v,cancel:v,resume:v,pause:v,complete:v,then:function(d,f){return a(function(a){c(function(){a()})}).then(d,
|
|
||||||
f)}};return d}]},Te=function(){var a=new Sa,c=[];this.$get=["$$AnimateRunner","$rootScope",function(d,e){function f(d,f,l){var k=a.get(d);k||(a.put(d,k={}),c.push(d));f&&m(f.split(" "),function(a){a&&(k[a]=!0)});l&&m(l.split(" "),function(a){a&&(k[a]=!1)});1<c.length||e.$$postDigest(function(){m(c,function(c){var d=a.get(c);if(d){var e=If(c.attr("class")),f="",g="";m(d,function(a,c){a!==!!e[c]&&(a?f+=(f.length?" ":"")+c:g+=(g.length?" ":"")+c)});m(c,function(a){f&&yb(a,f);g&&xb(a,g)});a.remove(c)}});
|
|
||||||
c.length=0})}return{enabled:v,on:v,off:v,pin:v,push:function(a,c,e,k){k&&k();e=e||{};e.from&&a.css(e.from);e.to&&a.css(e.to);(e.addClass||e.removeClass)&&f(a,e.addClass,e.removeClass);return new d}}}]},Se=["$provide",function(a){var c=this;this.$$registeredAnimations=Object.create(null);this.register=function(d,e){if(d&&"."!==d.charAt(0))throw Nd("notcsel",d);var f=d+"-animation";c.$$registeredAnimations[d.substr(1)]=f;a.factory(f,e)};this.classNameFilter=function(a){if(1===arguments.length&&(this.$$classNameFilter=
|
|
||||||
a instanceof RegExp?a:null)&&/(\s+|\/)ng-animate(\s+|\/)/.test(this.$$classNameFilter.toString()))throw Nd("nongcls","ng-animate");return this.$$classNameFilter};this.$get=["$$animateQueue",function(a){function c(a,d,e){if(e){var l;a:{for(l=0;l<e.length;l++){var k=e[l];if(1===k.nodeType){l=k;break a}}l=void 0}!l||l.parentNode||l.previousElementSibling||(e=null)}e?e.after(a):d.prepend(a)}return{on:a.on,off:a.off,pin:a.pin,enabled:a.enabled,cancel:function(a){a.end&&a.end()},enter:function(f,g,h,l){g=
|
|
||||||
g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"enter",Ia(l))},move:function(f,g,h,l){g=g&&y(g);h=h&&y(h);g=g||h.parent();c(f,g,h);return a.push(f,"move",Ia(l))},leave:function(c,e){return a.push(c,"leave",Ia(e),function(){c.remove()})},addClass:function(c,e,h){h=Ia(h);h.addClass=jb(h.addclass,e);return a.push(c,"addClass",h)},removeClass:function(c,e,h){h=Ia(h);h.removeClass=jb(h.removeClass,e);return a.push(c,"removeClass",h)},setClass:function(c,e,h,l){l=Ia(l);l.addClass=jb(l.addClass,
|
|
||||||
e);l.removeClass=jb(l.removeClass,h);return a.push(c,"setClass",l)},animate:function(c,e,h,l,k){k=Ia(k);k.from=k.from?P(k.from,e):e;k.to=k.to?P(k.to,h):h;k.tempClasses=jb(k.tempClasses,l||"ng-inline-animate");return a.push(c,"animate",k)}}}]}],ea=J("$compile");Ec.$inject=["$provide","$$sanitizeUriProvider"];var Zc=/^((?:x|data)[\:\-_])/i,Nf=J("$controller"),Xc=/^(\S+)(\s+as\s+(\w+))?$/,cd="application/json",ac={"Content-Type":cd+";charset=utf-8"},Pf=/^\[|^\{(?!\{)/,Qf={"[":/]$/,"{":/}$/},Of=/^\)\]\}',?\n/,
|
|
||||||
Ka=ca.$interpolateMinErr=J("$interpolate");Ka.throwNoconcat=function(a){throw Ka("noconcat",a);};Ka.interr=function(a,c){return Ka("interr",a,c.toString())};var og=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,Tf={http:80,https:443,ftp:21},Cb=J("$location"),pg={$$html5:!1,$$replace:!1,absUrl:Db("$$absUrl"),url:function(a){if(A(a))return this.$$url;var c=og.exec(a);(c[1]||""===a)&&this.path(decodeURIComponent(c[1]));(c[2]||c[1]||""===a)&&this.search(c[3]||"");this.hash(c[5]||"");return this},protocol:Db("$$protocol"),
|
|
||||||
host:Db("$$host"),port:Db("$$port"),path:kd("$$path",function(a){a=null!==a?a.toString():"";return"/"==a.charAt(0)?a:"/"+a}),search:function(a,c){switch(arguments.length){case 0:return this.$$search;case 1:if(L(a)||V(a))a=a.toString(),this.$$search=zc(a);else if(H(a))a=fa(a,{}),m(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw Cb("isrcharg");break;default:A(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:kd("$$hash",function(a){return null!==
|
|
||||||
a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};m([jd,ec,dc],function(a){a.prototype=Object.create(pg);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==dc||!this.$$html5)throw Cb("nostate");this.$$state=A(c)?null:c;return this}});var da=J("$parse"),Uf=Function.prototype.call,Vf=Function.prototype.apply,Wf=Function.prototype.bind,Mb=ga();m("+ - * / % === !== == != < > <= >= && || ! = |".split(" "),function(a){Mb[a]=!0});var qg={n:"\n",f:"\f",r:"\r",
|
|
||||||
t:"\t",v:"\v","'":"'",'"':'"'},gc=function(a){this.options=a};gc.prototype={constructor:gc,lex:function(a){this.text=a;this.index=0;for(this.tokens=[];this.index<this.text.length;)if(a=this.text.charAt(this.index),'"'===a||"'"===a)this.readString(a);else if(this.isNumber(a)||"."===a&&this.isNumber(this.peek()))this.readNumber();else if(this.isIdent(a))this.readIdent();else if(this.is(a,"(){}[].,;:?"))this.tokens.push({index:this.index,text:a}),this.index++;else if(this.isWhitespace(a))this.index++;
|
|
||||||
else{var c=a+this.peek(),d=c+this.peek(2),e=Mb[c],f=Mb[d];Mb[a]||e||f?(a=f?d:e?c:a,this.tokens.push({index:this.index,text:a,operator:!0}),this.index+=a.length):this.throwError("Unexpected next character ",this.index,this.index+1)}return this.tokens},is:function(a,c){return-1!==c.indexOf(a)},peek:function(a){a=a||1;return this.index+a<this.text.length?this.text.charAt(this.index+a):!1},isNumber:function(a){return"0"<=a&&"9">=a&&"string"===typeof a},isWhitespace:function(a){return" "===a||"\r"===a||
|
|
||||||
"\t"===a||"\n"===a||"\v"===a||"\u00a0"===a},isIdent:function(a){return"a"<=a&&"z">=a||"A"<=a&&"Z">=a||"_"===a||"$"===a},isExpOperator:function(a){return"-"===a||"+"===a||this.isNumber(a)},throwError:function(a,c,d){d=d||this.index;c=w(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw da("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=M(this.text.charAt(this.index));if("."==d||this.isNumber(d))a+=d;else{var e=this.peek();
|
|
||||||
if("e"==d&&this.isExpOperator(e))a+=d;else if(this.isExpOperator(d)&&e&&this.isNumber(e)&&"e"==a.charAt(a.length-1))a+=d;else if(!this.isExpOperator(d)||e&&this.isNumber(e)||"e"!=a.charAt(a.length-1))break;else this.throwError("Invalid exponent")}this.index++}this.tokens.push({index:c,text:a,constant:!0,value:Number(a)})},readIdent:function(){for(var a=this.index;this.index<this.text.length;){var c=this.text.charAt(this.index);if(!this.isIdent(c)&&!this.isNumber(c))break;this.index++}this.tokens.push({index:a,
|
|
||||||
text:this.text.slice(a,this.index),identifier:!0})},readString:function(a){var c=this.index;this.index++;for(var d="",e=a,f=!1;this.index<this.text.length;){var g=this.text.charAt(this.index),e=e+g;if(f)"u"===g?(f=this.text.substring(this.index+1,this.index+5),f.match(/[\da-f]{4}/i)||this.throwError("Invalid unicode escape [\\u"+f+"]"),this.index+=4,d+=String.fromCharCode(parseInt(f,16))):d+=qg[g]||g,f=!1;else if("\\"===g)f=!0;else{if(g===a){this.index++;this.tokens.push({index:c,text:e,constant:!0,
|
|
||||||
value:d});return}d+=g}this.index++}this.throwError("Unterminated quote",c)}};var q=function(a,c){this.lexer=a;this.options=c};q.Program="Program";q.ExpressionStatement="ExpressionStatement";q.AssignmentExpression="AssignmentExpression";q.ConditionalExpression="ConditionalExpression";q.LogicalExpression="LogicalExpression";q.BinaryExpression="BinaryExpression";q.UnaryExpression="UnaryExpression";q.CallExpression="CallExpression";q.MemberExpression="MemberExpression";q.Identifier="Identifier";q.Literal=
|
|
||||||
"Literal";q.ArrayExpression="ArrayExpression";q.Property="Property";q.ObjectExpression="ObjectExpression";q.ThisExpression="ThisExpression";q.NGValueParameter="NGValueParameter";q.prototype={ast:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.program();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);return a},program:function(){for(var a=[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.expressionStatement()),!this.expect(";"))return{type:q.Program,
|
|
||||||
body:a}},expressionStatement:function(){return{type:q.ExpressionStatement,expression:this.filterChain()}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary();this.expect("=")&&(a={type:q.AssignmentExpression,left:a,right:this.assignment(),operator:"="});return a},ternary:function(){var a=this.logicalOR(),c,d;return this.expect("?")&&(c=this.expression(),this.consume(":"))?
|
|
||||||
(d=this.expression(),{type:q.ConditionalExpression,test:a,alternate:c,consequent:d}):a},logicalOR:function(){for(var a=this.logicalAND();this.expect("||");)a={type:q.LogicalExpression,operator:"||",left:a,right:this.logicalAND()};return a},logicalAND:function(){for(var a=this.equality();this.expect("&&");)a={type:q.LogicalExpression,operator:"&&",left:a,right:this.equality()};return a},equality:function(){for(var a=this.relational(),c;c=this.expect("==","!=","===","!==");)a={type:q.BinaryExpression,
|
|
||||||
operator:c.text,left:a,right:this.relational()};return a},relational:function(){for(var a=this.additive(),c;c=this.expect("<",">","<=",">=");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.additive()};return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a={type:q.BinaryExpression,operator:c.text,left:a,right:this.multiplicative()};return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a={type:q.BinaryExpression,operator:c.text,
|
|
||||||
left:a,right:this.unary()};return a},unary:function(){var a;return(a=this.expect("+","-","!"))?{type:q.UnaryExpression,operator:a.text,prefix:!0,argument:this.unary()}:this.primary()},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.constants.hasOwnProperty(this.peek().text)?a=fa(this.constants[this.consume().text]):this.peek().identifier?a=this.identifier():this.peek().constant?a=this.constant():
|
|
||||||
this.throwError("not a primary expression",this.peek());for(var c;c=this.expect("(","[",".");)"("===c.text?(a={type:q.CallExpression,callee:a,arguments:this.parseArguments()},this.consume(")")):"["===c.text?(a={type:q.MemberExpression,object:a,property:this.expression(),computed:!0},this.consume("]")):"."===c.text?a={type:q.MemberExpression,object:a,property:this.identifier(),computed:!1}:this.throwError("IMPOSSIBLE");return a},filter:function(a){a=[a];for(var c={type:q.CallExpression,callee:this.identifier(),
|
|
||||||
arguments:a,filter:!0};this.expect(":");)a.push(this.expression());return c},parseArguments:function(){var a=[];if(")"!==this.peekToken().text){do a.push(this.expression());while(this.expect(","))}return a},identifier:function(){var a=this.consume();a.identifier||this.throwError("is not a valid identifier",a);return{type:q.Identifier,name:a.text}},constant:function(){return{type:q.Literal,value:this.consume().value}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;
|
|
||||||
a.push(this.expression())}while(this.expect(","))}this.consume("]");return{type:q.ArrayExpression,elements:a}},object:function(){var a=[],c;if("}"!==this.peekToken().text){do{if(this.peek("}"))break;c={type:q.Property,kind:"init"};this.peek().constant?c.key=this.constant():this.peek().identifier?c.key=this.identifier():this.throwError("invalid key",this.peek());this.consume(":");c.value=this.expression();a.push(c)}while(this.expect(","))}this.consume("}");return{type:q.ObjectExpression,properties:a}},
|
|
||||||
throwError:function(a,c){throw da("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},consume:function(a){if(0===this.tokens.length)throw da("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},peekToken:function(){if(0===this.tokens.length)throw da("ueoe",this.text);return this.tokens[0]},peek:function(a,c,d,e){return this.peekAhead(0,a,c,d,e)},peekAhead:function(a,c,d,e,f){if(this.tokens.length>a){a=this.tokens[a];
|
|
||||||
var g=a.text;if(g===c||g===d||g===e||g===f||!(c||d||e||f))return a}return!1},expect:function(a,c,d,e){return(a=this.peek(a,c,d,e))?(this.tokens.shift(),a):!1},constants:{"true":{type:q.Literal,value:!0},"false":{type:q.Literal,value:!1},"null":{type:q.Literal,value:null},undefined:{type:q.Literal,value:t},"this":{type:q.ThisExpression}}};rd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.state={nextId:0,filters:{},expensiveChecks:c,fn:{vars:[],body:[],own:{}},assign:{vars:[],
|
|
||||||
body:[],own:{}},inputs:[]};T(e,d.$filter);var f="",g;this.stage="assign";if(g=pd(e))this.state.computing="assign",f=this.nextId(),this.recurse(g,f),f="fn.assign="+this.generateFunction("assign","s,v,l");g=nd(e.body);d.stage="inputs";m(g,function(a,c){var e="fn"+c;d.state[e]={vars:[],body:[],own:{}};d.state.computing=e;var f=d.nextId();d.recurse(a,f);d.return_(f);d.state.inputs.push(e);a.watchId=c});this.state.computing="fn";this.stage="main";this.recurse(e);f='"'+this.USE+" "+this.STRICT+'";\n'+this.filterPrefix()+
|
|
||||||
"var fn="+this.generateFunction("fn","s,l,a,i")+f+this.watchFns()+"return fn;";f=(new Function("$filter","ensureSafeMemberName","ensureSafeObject","ensureSafeFunction","ifDefined","plus","text",f))(this.$filter,Ca,oa,ld,Xf,md,a);this.state=this.stage=t;f.literal=qd(e);f.constant=e.constant;return f},USE:"use",STRICT:"strict",watchFns:function(){var a=[],c=this.state.inputs,d=this;m(c,function(c){a.push("var "+c+"="+d.generateFunction(c,"s"))});c.length&&a.push("fn.inputs=["+c.join(",")+"];");return a.join("")},
|
|
||||||
generateFunction:function(a,c){return"function("+c+"){"+this.varsPrefix(a)+this.body(a)+"};"},filterPrefix:function(){var a=[],c=this;m(this.state.filters,function(d,e){a.push(d+"=$filter("+c.escape(e)+")")});return a.length?"var "+a.join(",")+";":""},varsPrefix:function(a){return this.state[a].vars.length?"var "+this.state[a].vars.join(",")+";":""},body:function(a){return this.state[a].body.join("")},recurse:function(a,c,d,e,f,g){var h,l,k=this,n,r;e=e||v;if(!g&&w(a.watchId))c=c||this.nextId(),this.if_("i",
|
|
||||||
this.lazyAssign(c,this.computedMember("i",a.watchId)),this.lazyRecurse(a,c,d,e,f,!0));else switch(a.type){case q.Program:m(a.body,function(c,d){k.recurse(c.expression,t,t,function(a){l=a});d!==a.body.length-1?k.current().body.push(l,";"):k.return_(l)});break;case q.Literal:r=this.escape(a.value);this.assign(c,r);e(r);break;case q.UnaryExpression:this.recurse(a.argument,t,t,function(a){l=a});r=a.operator+"("+this.ifDefined(l,0)+")";this.assign(c,r);e(r);break;case q.BinaryExpression:this.recurse(a.left,
|
|
||||||
t,t,function(a){h=a});this.recurse(a.right,t,t,function(a){l=a});r="+"===a.operator?this.plus(h,l):"-"===a.operator?this.ifDefined(h,0)+a.operator+this.ifDefined(l,0):"("+h+")"+a.operator+"("+l+")";this.assign(c,r);e(r);break;case q.LogicalExpression:c=c||this.nextId();k.recurse(a.left,c);k.if_("&&"===a.operator?c:k.not(c),k.lazyRecurse(a.right,c));e(c);break;case q.ConditionalExpression:c=c||this.nextId();k.recurse(a.test,c);k.if_(c,k.lazyRecurse(a.alternate,c),k.lazyRecurse(a.consequent,c));e(c);
|
|
||||||
break;case q.Identifier:c=c||this.nextId();d&&(d.context="inputs"===k.stage?"s":this.assign(this.nextId(),this.getHasOwnProperty("l",a.name)+"?l:s"),d.computed=!1,d.name=a.name);Ca(a.name);k.if_("inputs"===k.stage||k.not(k.getHasOwnProperty("l",a.name)),function(){k.if_("inputs"===k.stage||"s",function(){f&&1!==f&&k.if_(k.not(k.nonComputedMember("s",a.name)),k.lazyAssign(k.nonComputedMember("s",a.name),"{}"));k.assign(c,k.nonComputedMember("s",a.name))})},c&&k.lazyAssign(c,k.nonComputedMember("l",
|
|
||||||
a.name)));(k.state.expensiveChecks||Fb(a.name))&&k.addEnsureSafeObject(c);e(c);break;case q.MemberExpression:h=d&&(d.context=this.nextId())||this.nextId();c=c||this.nextId();k.recurse(a.object,h,t,function(){k.if_(k.notNull(h),function(){if(a.computed)l=k.nextId(),k.recurse(a.property,l),k.addEnsureSafeMemberName(l),f&&1!==f&&k.if_(k.not(k.computedMember(h,l)),k.lazyAssign(k.computedMember(h,l),"{}")),r=k.ensureSafeObject(k.computedMember(h,l)),k.assign(c,r),d&&(d.computed=!0,d.name=l);else{Ca(a.property.name);
|
|
||||||
f&&1!==f&&k.if_(k.not(k.nonComputedMember(h,a.property.name)),k.lazyAssign(k.nonComputedMember(h,a.property.name),"{}"));r=k.nonComputedMember(h,a.property.name);if(k.state.expensiveChecks||Fb(a.property.name))r=k.ensureSafeObject(r);k.assign(c,r);d&&(d.computed=!1,d.name=a.property.name)}},function(){k.assign(c,"undefined")});e(c)},!!f);break;case q.CallExpression:c=c||this.nextId();a.filter?(l=k.filter(a.callee.name),n=[],m(a.arguments,function(a){var c=k.nextId();k.recurse(a,c);n.push(c)}),r=l+
|
|
||||||
"("+n.join(",")+")",k.assign(c,r),e(c)):(l=k.nextId(),h={},n=[],k.recurse(a.callee,l,h,function(){k.if_(k.notNull(l),function(){k.addEnsureSafeFunction(l);m(a.arguments,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(k.ensureSafeObject(a))})});h.name?(k.state.expensiveChecks||k.addEnsureSafeObject(h.context),r=k.member(h.context,h.name,h.computed)+"("+n.join(",")+")"):r=l+"("+n.join(",")+")";r=k.ensureSafeObject(r);k.assign(c,r)},function(){k.assign(c,"undefined")});e(c)}));break;case q.AssignmentExpression:l=
|
|
||||||
this.nextId();h={};if(!od(a.left))throw da("lval");this.recurse(a.left,t,h,function(){k.if_(k.notNull(h.context),function(){k.recurse(a.right,l);k.addEnsureSafeObject(k.member(h.context,h.name,h.computed));r=k.member(h.context,h.name,h.computed)+a.operator+l;k.assign(c,r);e(c||r)})},1);break;case q.ArrayExpression:n=[];m(a.elements,function(a){k.recurse(a,k.nextId(),t,function(a){n.push(a)})});r="["+n.join(",")+"]";this.assign(c,r);e(r);break;case q.ObjectExpression:n=[];m(a.properties,function(a){k.recurse(a.value,
|
|
||||||
k.nextId(),t,function(c){n.push(k.escape(a.key.type===q.Identifier?a.key.name:""+a.key.value)+":"+c)})});r="{"+n.join(",")+"}";this.assign(c,r);e(r);break;case q.ThisExpression:this.assign(c,"s");e("s");break;case q.NGValueParameter:this.assign(c,"v"),e("v")}},getHasOwnProperty:function(a,c){var d=a+"."+c,e=this.current().own;e.hasOwnProperty(d)||(e[d]=this.nextId(!1,a+"&&("+this.escape(c)+" in "+a+")"));return e[d]},assign:function(a,c){if(a)return this.current().body.push(a,"=",c,";"),a},filter:function(a){this.state.filters.hasOwnProperty(a)||
|
|
||||||
(this.state.filters[a]=this.nextId(!0));return this.state.filters[a]},ifDefined:function(a,c){return"ifDefined("+a+","+this.escape(c)+")"},plus:function(a,c){return"plus("+a+","+c+")"},return_:function(a){this.current().body.push("return ",a,";")},if_:function(a,c,d){if(!0===a)c();else{var e=this.current().body;e.push("if(",a,"){");c();e.push("}");d&&(e.push("else{"),d(),e.push("}"))}},not:function(a){return"!("+a+")"},notNull:function(a){return a+"!=null"},nonComputedMember:function(a,c){return a+
|
|
||||||
"."+c},computedMember:function(a,c){return a+"["+c+"]"},member:function(a,c,d){return d?this.computedMember(a,c):this.nonComputedMember(a,c)},addEnsureSafeObject:function(a){this.current().body.push(this.ensureSafeObject(a),";")},addEnsureSafeMemberName:function(a){this.current().body.push(this.ensureSafeMemberName(a),";")},addEnsureSafeFunction:function(a){this.current().body.push(this.ensureSafeFunction(a),";")},ensureSafeObject:function(a){return"ensureSafeObject("+a+",text)"},ensureSafeMemberName:function(a){return"ensureSafeMemberName("+
|
|
||||||
a+",text)"},ensureSafeFunction:function(a){return"ensureSafeFunction("+a+",text)"},lazyRecurse:function(a,c,d,e,f,g){var h=this;return function(){h.recurse(a,c,d,e,f,g)}},lazyAssign:function(a,c){var d=this;return function(){d.assign(a,c)}},stringEscapeRegex:/[^ a-zA-Z0-9]/g,stringEscapeFn:function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)},escape:function(a){if(L(a))return"'"+a.replace(this.stringEscapeRegex,this.stringEscapeFn)+"'";if(V(a))return a.toString();if(!0===a)return"true";
|
|
||||||
if(!1===a)return"false";if(null===a)return"null";if("undefined"===typeof a)return"undefined";throw da("esc");},nextId:function(a,c){var d="v"+this.state.nextId++;a||this.current().vars.push(d+(c?"="+c:""));return d},current:function(){return this.state[this.state.computing]}};sd.prototype={compile:function(a,c){var d=this,e=this.astBuilder.ast(a);this.expression=a;this.expensiveChecks=c;T(e,d.$filter);var f,g;if(f=pd(e))g=this.recurse(f);f=nd(e.body);var h;f&&(h=[],m(f,function(a,c){var e=d.recurse(a);
|
|
||||||
a.input=e;h.push(e);a.watchId=c}));var l=[];m(e.body,function(a){l.push(d.recurse(a.expression))});f=0===e.body.length?function(){}:1===e.body.length?l[0]:function(a,c){var d;m(l,function(e){d=e(a,c)});return d};g&&(f.assign=function(a,c,d){return g(a,d,c)});h&&(f.inputs=h);f.literal=qd(e);f.constant=e.constant;return f},recurse:function(a,c,d){var e,f,g=this,h;if(a.input)return this.inputs(a.input,a.watchId);switch(a.type){case q.Literal:return this.value(a.value,c);case q.UnaryExpression:return f=
|
|
||||||
this.recurse(a.argument),this["unary"+a.operator](f,c);case q.BinaryExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.LogicalExpression:return e=this.recurse(a.left),f=this.recurse(a.right),this["binary"+a.operator](e,f,c);case q.ConditionalExpression:return this["ternary?:"](this.recurse(a.test),this.recurse(a.alternate),this.recurse(a.consequent),c);case q.Identifier:return Ca(a.name,g.expression),g.identifier(a.name,g.expensiveChecks||Fb(a.name),
|
|
||||||
c,d,g.expression);case q.MemberExpression:return e=this.recurse(a.object,!1,!!d),a.computed||(Ca(a.property.name,g.expression),f=a.property.name),a.computed&&(f=this.recurse(a.property)),a.computed?this.computedMember(e,f,c,d,g.expression):this.nonComputedMember(e,f,g.expensiveChecks,c,d,g.expression);case q.CallExpression:return h=[],m(a.arguments,function(a){h.push(g.recurse(a))}),a.filter&&(f=this.$filter(a.callee.name)),a.filter||(f=this.recurse(a.callee,!0)),a.filter?function(a,d,e,g){for(var m=
|
|
||||||
[],q=0;q<h.length;++q)m.push(h[q](a,d,e,g));a=f.apply(t,m,g);return c?{context:t,name:t,value:a}:a}:function(a,d,e,r){var m=f(a,d,e,r),q;if(null!=m.value){oa(m.context,g.expression);ld(m.value,g.expression);q=[];for(var t=0;t<h.length;++t)q.push(oa(h[t](a,d,e,r),g.expression));q=oa(m.value.apply(m.context,q),g.expression)}return c?{value:q}:q};case q.AssignmentExpression:return e=this.recurse(a.left,!0,1),f=this.recurse(a.right),function(a,d,h,r){var m=e(a,d,h,r);a=f(a,d,h,r);oa(m.value,g.expression);
|
|
||||||
m.context[m.name]=a;return c?{value:a}:a};case q.ArrayExpression:return h=[],m(a.elements,function(a){h.push(g.recurse(a))}),function(a,d,e,f){for(var g=[],m=0;m<h.length;++m)g.push(h[m](a,d,e,f));return c?{value:g}:g};case q.ObjectExpression:return h=[],m(a.properties,function(a){h.push({key:a.key.type===q.Identifier?a.key.name:""+a.key.value,value:g.recurse(a.value)})}),function(a,d,e,f){for(var g={},m=0;m<h.length;++m)g[h[m].key]=h[m].value(a,d,e,f);return c?{value:g}:g};case q.ThisExpression:return function(a){return c?
|
|
||||||
{value:a}:a};case q.NGValueParameter:return function(a,d,e,f){return c?{value:e}:e}}},"unary+":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?+d:0;return c?{value:d}:d}},"unary-":function(a,c){return function(d,e,f,g){d=a(d,e,f,g);d=w(d)?-d:0;return c?{value:d}:d}},"unary!":function(a,c){return function(d,e,f,g){d=!a(d,e,f,g);return c?{value:d}:d}},"binary+":function(a,c,d){return function(e,f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=md(l,e);return d?{value:l}:l}},"binary-":function(a,c,d){return function(e,
|
|
||||||
f,g,h){var l=a(e,f,g,h);e=c(e,f,g,h);l=(w(l)?l:0)-(w(e)?e:0);return d?{value:l}:l}},"binary*":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)*c(e,f,g,h);return d?{value:e}:e}},"binary/":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)/c(e,f,g,h);return d?{value:e}:e}},"binary%":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)%c(e,f,g,h);return d?{value:e}:e}},"binary===":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)===c(e,f,g,h);return d?{value:e}:e}},"binary!==":function(a,
|
|
||||||
c,d){return function(e,f,g,h){e=a(e,f,g,h)!==c(e,f,g,h);return d?{value:e}:e}},"binary==":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)==c(e,f,g,h);return d?{value:e}:e}},"binary!=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)!=c(e,f,g,h);return d?{value:e}:e}},"binary<":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)<c(e,f,g,h);return d?{value:e}:e}},"binary>":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>c(e,f,g,h);return d?{value:e}:e}},"binary<=":function(a,c,d){return function(e,
|
|
||||||
f,g,h){e=a(e,f,g,h)<=c(e,f,g,h);return d?{value:e}:e}},"binary>=":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)>=c(e,f,g,h);return d?{value:e}:e}},"binary&&":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)&&c(e,f,g,h);return d?{value:e}:e}},"binary||":function(a,c,d){return function(e,f,g,h){e=a(e,f,g,h)||c(e,f,g,h);return d?{value:e}:e}},"ternary?:":function(a,c,d,e){return function(f,g,h,l){f=a(f,g,h,l)?c(f,g,h,l):d(f,g,h,l);return e?{value:f}:f}},value:function(a,c){return function(){return c?
|
|
||||||
{context:t,name:t,value:a}:a}},identifier:function(a,c,d,e,f){return function(g,h,l,k){g=h&&a in h?h:g;e&&1!==e&&g&&!g[a]&&(g[a]={});h=g?g[a]:t;c&&oa(h,f);return d?{context:g,name:a,value:h}:h}},computedMember:function(a,c,d,e,f){return function(g,h,l,k){var n=a(g,h,l,k),m,s;null!=n&&(m=c(g,h,l,k),Ca(m,f),e&&1!==e&&n&&!n[m]&&(n[m]={}),s=n[m],oa(s,f));return d?{context:n,name:m,value:s}:s}},nonComputedMember:function(a,c,d,e,f,g){return function(h,l,k,n){h=a(h,l,k,n);f&&1!==f&&h&&!h[c]&&(h[c]={});
|
|
||||||
l=null!=h?h[c]:t;(d||Fb(c))&&oa(l,g);return e?{context:h,name:c,value:l}:l}},inputs:function(a,c){return function(d,e,f,g){return g?g[c]:a(d,e,f)}}};var hc=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d;this.ast=new q(this.lexer);this.astCompiler=d.csp?new sd(this.ast,c):new rd(this.ast,c)};hc.prototype={constructor:hc,parse:function(a){return this.astCompiler.compile(a,this.options.expensiveChecks)}};ga();ga();var Yf=Object.prototype.valueOf,Da=J("$sce"),pa={HTML:"html",CSS:"css",URL:"url",
|
|
||||||
RESOURCE_URL:"resourceUrl",JS:"js"},ea=J("$compile"),X=U.createElement("a"),wd=Ba(O.location.href);xd.$inject=["$document"];Lc.$inject=["$provide"];yd.$inject=["$locale"];Ad.$inject=["$locale"];var Dd=".",hg={yyyy:Y("FullYear",4),yy:Y("FullYear",2,0,!0),y:Y("FullYear",1),MMMM:Hb("Month"),MMM:Hb("Month",!0),MM:Y("Month",2,1),M:Y("Month",1,1),dd:Y("Date",2),d:Y("Date",1),HH:Y("Hours",2),H:Y("Hours",1),hh:Y("Hours",2,-12),h:Y("Hours",1,-12),mm:Y("Minutes",2),m:Y("Minutes",1),ss:Y("Seconds",2),s:Y("Seconds",
|
|
||||||
1),sss:Y("Milliseconds",3),EEEE:Hb("Day"),EEE:Hb("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a,c,d){a=-1*d;return a=(0<=a?"+":"")+(Gb(Math[0<a?"floor":"ceil"](a/60),2)+Gb(Math.abs(a%60),2))},ww:Fd(2),w:Fd(1),G:jc,GG:jc,GGG:jc,GGGG:function(a,c){return 0>=a.getFullYear()?c.ERANAMES[0]:c.ERANAMES[1]}},gg=/((?:[^yMdHhmsaZEwG']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|G+|w+))(.*)/,fg=/^\-?\d+$/;zd.$inject=["$locale"];var cg=ra(M),dg=ra(rb);Bd.$inject=
|
|
||||||
["$parse"];var ie=ra({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref)return function(a,c){if("a"===c[0].nodeName.toLowerCase()){var f="[object SVGAnimatedString]"===sa.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}}),sb={};m(Ab,function(a,c){function d(a,d,f){a.$watch(f[e],function(a){f.$set(c,!!a)})}if("multiple"!=a){var e=wa("ng-"+c),f=d;"checked"===a&&(f=function(a,c,f){f.ngModel!==f[e]&&d(a,c,f)});sb[e]=function(){return{restrict:"A",
|
|
||||||
priority:100,link:f}}}});m(Uc,function(a,c){sb[c]=function(){return{priority:100,link:function(a,e,f){if("ngPattern"===c&&"/"==f.ngPattern.charAt(0)&&(e=f.ngPattern.match(jg))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});m(["src","srcset","href"],function(a){var c=wa("ng-"+a);sb[c]=function(){return{priority:99,link:function(d,e,f){var g=a,h=a;"href"===a&&"[object SVGAnimatedString]"===sa.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",
|
|
||||||
g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ua&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Ib={$addControl:v,$$renameControl:function(a,c){a.$name=c},$removeControl:v,$setValidity:v,$setDirty:v,$setPristine:v,$setSubmitted:v};Gd.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var Od=function(a){return["$timeout",function(c){return{name:"form",restrict:a?"EAC":"E",controller:Gd,compile:function(d,e){d.addClass(Va).addClass(mb);var f=e.name?"name":a&&e.ngForm?"ngForm":
|
|
||||||
!1;return{pre:function(a,d,e,k){if(!("action"in e)){var n=function(c){a.$apply(function(){k.$commitViewValue();k.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",n,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",n,!1)},0,!1)})}var m=k.$$parentForm;f&&(Eb(a,k.$name,k,k.$name),e.$observe(f,function(c){k.$name!==c&&(Eb(a,k.$name,t,k.$name),m.$$renameControl(k,c),Eb(a,k.$name,k,k.$name))}));d.on("$destroy",function(){m.$removeControl(k);f&&Eb(a,e[f],t,
|
|
||||||
k.$name);P(k,Ib)})}}}}}]},je=Od(),we=Od(!0),ig=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,rg=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,sg=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,tg=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))([eE][+-]?\d+)?\s*$/,Pd=/^(\d{4})-(\d{2})-(\d{2})$/,Qd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,mc=/^(\d{4})-W(\d\d)$/,Rd=/^(\d{4})-(\d\d)$/,
|
|
||||||
Sd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Td={text:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e)},date:lb("date",Pd,Kb(Pd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":lb("datetimelocal",Qd,Kb(Qd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:lb("time",Sd,Kb(Sd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:lb("week",mc,function(a,c){if(aa(a))return a;if(L(a)){mc.lastIndex=0;var d=mc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,l=0,k=Ed(e),f=7*(f-1);c&&(d=c.getHours(),g=
|
|
||||||
c.getMinutes(),h=c.getSeconds(),l=c.getMilliseconds());return new Date(e,0,k.getDate()+f,d,g,h,l)}}return NaN},"yyyy-Www"),month:lb("month",Rd,Kb(Rd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){Id(a,c,d,e);kb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:tg.test(a)?parseFloat(a):t});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!V(a))throw Lb("numfmt",a);a=a.toString()}return a});if(w(d.min)||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||
|
|
||||||
A(h)||a>=h};d.$observe("min",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));h=V(a)&&!isNaN(a)?a:t;e.$validate()})}if(w(d.max)||d.ngMax){var l;e.$validators.max=function(a){return e.$isEmpty(a)||A(l)||a<=l};d.$observe("max",function(a){w(a)&&!V(a)&&(a=parseFloat(a,10));l=V(a)&&!isNaN(a)?a:t;e.$validate()})}},url:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);e.$$parserName="url";e.$validators.url=function(a,c){var d=a||c;return e.$isEmpty(d)||rg.test(d)}},email:function(a,c,d,e,f,g){kb(a,c,d,e,f,g);kc(e);
|
|
||||||
e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||sg.test(d)}},radio:function(a,c,d,e){A(d.name)&&c.attr("name",++nb);c.on("click",function(a){c[0].checked&&e.$setViewValue(d.value,a&&a.type)});e.$render=function(){c[0].checked=d.value==e.$viewValue};d.$observe("value",e.$render)},checkbox:function(a,c,d,e,f,g,h,l){var k=Jd(l,a,"ngTrueValue",d.ngTrueValue,!0),n=Jd(l,a,"ngFalseValue",d.ngFalseValue,!1);c.on("click",function(a){e.$setViewValue(c[0].checked,a&&
|
|
||||||
a.type)});e.$render=function(){c[0].checked=e.$viewValue};e.$isEmpty=function(a){return!1===a};e.$formatters.push(function(a){return ka(a,k)});e.$parsers.push(function(a){return a?k:n})},hidden:v,button:v,submit:v,reset:v,file:v},Fc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,l){l[0]&&(Td[M(h.type)]||Td.text)(f,g,h,l[0],c,a,d,e)}}}}],ug=/^(true|false|\d+)$/,Oe=function(){return{restrict:"A",priority:100,compile:function(a,
|
|
||||||
c){return ug.test(c.ngValue)?function(a,c,f){f.$set("value",a.$eval(f.ngValue))}:function(a,c,f){a.$watch(f.ngValue,function(a){f.$set("value",a)})}}}},oe=["$compile",function(a){return{restrict:"AC",compile:function(c){a.$$addBindingClass(c);return function(c,e,f){a.$$addBindingInfo(e,f.ngBind);e=e[0];c.$watch(f.ngBind,function(a){e.textContent=a===t?"":a})}}}}],qe=["$interpolate","$compile",function(a,c){return{compile:function(d){c.$$addBindingClass(d);return function(d,f,g){d=a(f.attr(g.$attr.ngBindTemplate));
|
|
||||||
c.$$addBindingInfo(f,d.expressions);f=f[0];g.$observe("ngBindTemplate",function(a){f.textContent=a===t?"":a})}}}}],pe=["$sce","$parse","$compile",function(a,c,d){return{restrict:"A",compile:function(e,f){var g=c(f.ngBindHtml),h=c(f.ngBindHtml,function(a){return(a||"").toString()});d.$$addBindingClass(e);return function(c,e,f){d.$$addBindingInfo(e,f.ngBindHtml);c.$watch(h,function(){e.html(a.getTrustedHtml(g(c))||"")})}}}}],Ne=ra({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),
|
|
||||||
re=lc("",!0),te=lc("Odd",0),se=lc("Even",1),ue=Ma({compile:function(a,c){c.$set("ngCloak",t);a.removeClass("ng-cloak")}}),ve=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Kc={},vg={blur:!0,focus:!0};m("click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste".split(" "),function(a){var c=wa("ng-"+a);Kc[c]=["$parse","$rootScope",function(d,e){return{restrict:"A",compile:function(f,g){var h=
|
|
||||||
d(g[c],null,!0);return function(c,d){d.on(a,function(d){var f=function(){h(c,{$event:d})};vg[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var ye=["$animate",function(a){return{multiElement:!0,transclude:"element",priority:600,terminal:!0,restrict:"A",$$tlb:!0,link:function(c,d,e,f,g){var h,l,k;c.$watch(e.ngIf,function(c){c?l||g(function(c,f){l=f;c[c.length++]=U.createComment(" end ngIf: "+e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(k&&(k.remove(),k=null),l&&(l.$destroy(),l=null),h&&(k=
|
|
||||||
qb(h.clone),a.leave(k).then(function(){k=null}),h=null))})}}}],ze=["$templateRequest","$anchorScroll","$animate",function(a,c,d){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ca.noop,compile:function(e,f){var g=f.ngInclude||f.src,h=f.onload||"",l=f.autoscroll;return function(e,f,m,s,q){var t=0,F,u,p,v=function(){u&&(u.remove(),u=null);F&&(F.$destroy(),F=null);p&&(d.leave(p).then(function(){u=null}),u=p,p=null)};e.$watch(g,function(g){var m=function(){!w(l)||l&&!e.$eval(l)||
|
|
||||||
c()},r=++t;g?(a(g,!0).then(function(a){if(r===t){var c=e.$new();s.template=a;a=q(c,function(a){v();d.enter(a,null,f).then(m)});F=c;p=a;F.$emit("$includeContentLoaded",g);e.$eval(h)}},function(){r===t&&(v(),e.$emit("$includeContentError",g))}),e.$emit("$includeContentRequested",g)):(v(),s.template=null)})}}}}],Qe=["$compile",function(a){return{restrict:"ECA",priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Nc(f.template,U).childNodes)(c,function(a){d.append(a)},
|
|
||||||
{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],Ae=Ma({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),Me=function(){return{restrict:"A",priority:100,require:"ngModel",link:function(a,c,d,e){var f=c.attr(d.$attr.ngList)||", ",g="false"!==d.ngTrim,h=g?R(f):f;e.$parsers.push(function(a){if(!A(a)){var c=[];a&&m(a.split(h),function(a){a&&c.push(g?R(a):a)});return c}});e.$formatters.push(function(a){return G(a)?a.join(f):t});e.$isEmpty=function(a){return!a||
|
|
||||||
!a.length}}}},mb="ng-valid",Kd="ng-invalid",Va="ng-pristine",Jb="ng-dirty",Md="ng-pending",Lb=new J("ngModel"),wg=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,l,k,n){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=t;this.$validators={};this.$asyncValidators={};this.$parsers=[];this.$formatters=[];this.$viewChangeListeners=[];this.$untouched=!0;this.$touched=!1;this.$pristine=!0;this.$dirty=
|
|
||||||
!1;this.$valid=!0;this.$invalid=!1;this.$error={};this.$$success={};this.$pending=t;this.$name=n(d.name||"",!1)(a);var r=f(d.ngModel),s=r.assign,q=r,C=s,F=null,u,p=this;this.$$setOptions=function(a){if((p.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");q=function(a){var d=r(a);z(d)&&(d=c(a));return d};C=function(a,c){z(r(a))?g(a,{$$$p:p.$modelValue}):s(a,p.$modelValue)}}else if(!r.assign)throw Lb("nonassign",d.ngModel,ua(e));};this.$render=v;this.$isEmpty=function(a){return A(a)||
|
|
||||||
""===a||null===a||a!==a};var K=e.inheritedData("$formController")||Ib,y=0;Hd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:K,$animate:g});this.$setPristine=function(){p.$dirty=!1;p.$pristine=!0;g.removeClass(e,Jb);g.addClass(e,Va)};this.$setDirty=function(){p.$dirty=!0;p.$pristine=!1;g.removeClass(e,Va);g.addClass(e,Jb);K.$setDirty()};this.$setUntouched=function(){p.$touched=!1;p.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=
|
|
||||||
function(){p.$touched=!0;p.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(F);p.$viewValue=p.$$lastCommittedViewValue;p.$render()};this.$validate=function(){if(!V(p.$modelValue)||!isNaN(p.$modelValue)){var a=p.$$rawModelValue,c=p.$valid,d=p.$modelValue,e=p.$options&&p.$options.allowInvalid;p.$$runValidators(a,p.$$lastCommittedViewValue,function(f){e||c===f||(p.$modelValue=f?a:t,p.$modelValue!==d&&p.$$writeModelToScope())})}};this.$$runValidators=
|
|
||||||
function(a,c,d){function e(){var d=!0;m(p.$validators,function(e,f){var h=e(a,c);d=d&&h;g(f,h)});return d?!0:(m(p.$asyncValidators,function(a,c){g(c,null)}),!1)}function f(){var d=[],e=!0;m(p.$asyncValidators,function(f,h){var k=f(a,c);if(!k||!z(k.then))throw Lb("$asyncValidators",k);g(h,t);d.push(k.then(function(){g(h,!0)},function(a){e=!1;g(h,!1)}))});d.length?k.all(d).then(function(){h(e)},v):h(!0)}function g(a,c){l===y&&p.$setValidity(a,c)}function h(a){l===y&&d(a)}y++;var l=y;(function(){var a=
|
|
||||||
p.$$parserName||"parse";if(u===t)g(a,null);else return u||(m(p.$validators,function(a,c){g(c,null)}),m(p.$asyncValidators,function(a,c){g(c,null)})),g(a,u),u;return!0})()?e()?f():h(!1):h(!1)};this.$commitViewValue=function(){var a=p.$viewValue;h.cancel(F);if(p.$$lastCommittedViewValue!==a||""===a&&p.$$hasNativeValidators)p.$$lastCommittedViewValue=a,p.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=p.$$lastCommittedViewValue;if(u=A(c)?t:!0)for(var d=
|
|
||||||
0;d<p.$parsers.length;d++)if(c=p.$parsers[d](c),A(c)){u=!1;break}V(p.$modelValue)&&isNaN(p.$modelValue)&&(p.$modelValue=q(a));var e=p.$modelValue,f=p.$options&&p.$options.allowInvalid;p.$$rawModelValue=c;f&&(p.$modelValue=c,p.$modelValue!==e&&p.$$writeModelToScope());p.$$runValidators(c,p.$$lastCommittedViewValue,function(a){f||(p.$modelValue=a?c:t,p.$modelValue!==e&&p.$$writeModelToScope())})};this.$$writeModelToScope=function(){C(a,p.$modelValue);m(p.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};
|
|
||||||
this.$setViewValue=function(a,c){p.$viewValue=a;p.$options&&!p.$options.updateOnDefault||p.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=p.$options;e&&w(e.debounce)&&(e=e.debounce,V(e)?d=e:V(e[c])?d=e[c]:V(e["default"])&&(d=e["default"]));h.cancel(F);d?F=h(function(){p.$commitViewValue()},d):l.$$phase?p.$commitViewValue():a.$apply(function(){p.$commitViewValue()})};a.$watch(function(){var c=q(a);if(c!==p.$modelValue&&(p.$modelValue===p.$modelValue||c===c)){p.$modelValue=
|
|
||||||
p.$$rawModelValue=c;u=t;for(var d=p.$formatters,e=d.length,f=c;e--;)f=d[e](f);p.$viewValue!==f&&(p.$viewValue=p.$$lastCommittedViewValue=f,p.$render(),p.$$runValidators(c,f,v))}return c})}],Le=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:wg,priority:1,compile:function(c){c.addClass(Va).addClass("ng-untouched").addClass(mb);return{pre:function(a,c,f,g){var h=g[0],l=g[1]||Ib;h.$$setOptions(g[2]&&g[2].$options);l.$addControl(h);f.$observe("name",
|
|
||||||
function(a){h.$name!==a&&l.$$renameControl(h,a)});a.$on("$destroy",function(){l.$removeControl(h)})},post:function(c,e,f,g){var h=g[0];if(h.$options&&h.$options.updateOn)e.on(h.$options.updateOn,function(a){h.$$debounceViewValueCommit(a&&a.type)});e.on("blur",function(e){h.$touched||(a.$$phase?c.$evalAsync(h.$setTouched):c.$apply(h.$setTouched))})}}}}}],xg=/(\s+|^)default(\s+|$)/,Pe=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=fa(a.$eval(c.ngModelOptions));
|
|
||||||
this.$options.updateOn!==t?(this.$options.updateOnDefault=!1,this.$options.updateOn=R(this.$options.updateOn.replace(xg,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Be=Ma({terminal:!0,priority:1E3}),yg=J("ngOptions"),zg=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/,
|
|
||||||
Je=["$compile","$parse",function(a,c){function d(a,d,e){function f(a,c,d,e,g){this.selectValue=a;this.viewValue=c;this.label=d;this.group=e;this.disabled=g}function n(a){var c;if(!q&&Ea(a))c=a;else{c=[];for(var d in a)a.hasOwnProperty(d)&&"$"!==d.charAt(0)&&c.push(d)}return c}var m=a.match(zg);if(!m)throw yg("iexp",a,ua(d));var s=m[5]||m[7],q=m[6];a=/ as /.test(m[0])&&m[1];var t=m[9];d=c(m[2]?m[1]:s);var v=a&&c(a)||d,u=t&&c(t),p=t?function(a,c){return u(e,c)}:function(a){return Ga(a)},w=function(a,
|
|
||||||
c){return p(a,z(a,c))},y=c(m[2]||m[1]),A=c(m[3]||""),B=c(m[4]||""),N=c(m[8]),D={},z=q?function(a,c){D[q]=c;D[s]=a;return D}:function(a){D[s]=a;return D};return{trackBy:t,getTrackByValue:w,getWatchables:c(N,function(a){var c=[];a=a||[];for(var d=n(a),f=d.length,g=0;g<f;g++){var h=a===d?g:d[g],k=z(a[h],h),h=p(a[h],k);c.push(h);if(m[2]||m[1])h=y(e,k),c.push(h);m[4]&&(k=B(e,k),c.push(k))}return c}),getOptions:function(){for(var a=[],c={},d=N(e)||[],g=n(d),h=g.length,m=0;m<h;m++){var r=d===g?m:g[m],s=
|
|
||||||
z(d[r],r),q=v(e,s),r=p(q,s),u=y(e,s),x=A(e,s),s=B(e,s),q=new f(r,q,u,x,s);a.push(q);c[r]=q}return{items:a,selectValueMap:c,getOptionFromViewValue:function(a){return c[w(a)]},getViewValueFromOption:function(a){return t?ca.copy(a.viewValue):a.viewValue}}}}}var e=U.createElement("option"),f=U.createElement("optgroup");return{restrict:"A",terminal:!0,require:["select","?ngModel"],link:function(c,h,l,k){function n(a,c){a.element=c;c.disabled=a.disabled;a.value!==c.value&&(c.value=a.selectValue);a.label!==
|
|
||||||
c.label&&(c.label=a.label,c.textContent=a.label)}function r(a,c,d,e){c&&M(c.nodeName)===d?d=c:(d=e.cloneNode(!1),c?a.insertBefore(d,c):a.appendChild(d));return d}function s(a){for(var c;a;)c=a.nextSibling,Xb(a),a=c}function q(a){var c=p&&p[0],d=N&&N[0];if(c||d)for(;a&&(a===c||a===d);)a=a.nextSibling;return a}function t(){var a=D&&u.readValue();D=z.getOptions();var c={},d=h[0].firstChild;B&&h.prepend(p);d=q(d);D.items.forEach(function(a){var g,k;a.group?(g=c[a.group],g||(g=r(h[0],d,"optgroup",f),d=
|
|
||||||
g.nextSibling,g.label=a.group,g=c[a.group]={groupElement:g,currentOptionElement:g.firstChild}),k=r(g.groupElement,g.currentOptionElement,"option",e),n(a,k),g.currentOptionElement=k.nextSibling):(k=r(h[0],d,"option",e),n(a,k),d=k.nextSibling)});Object.keys(c).forEach(function(a){s(c[a].currentOptionElement)});s(d);v.$render();if(!v.$isEmpty(a)){var g=u.readValue();(z.trackBy?ka(a,g):a===g)||(v.$setViewValue(g),v.$render())}}var v=k[1];if(v){var u=k[0];k=l.multiple;for(var p,w=0,A=h.children(),I=A.length;w<
|
|
||||||
I;w++)if(""===A[w].value){p=A.eq(w);break}var B=!!p,N=y(e.cloneNode(!1));N.val("?");var D,z=d(l.ngOptions,h,c);k?(v.$isEmpty=function(a){return!a||0===a.length},u.writeValue=function(a){D.items.forEach(function(a){a.element.selected=!1});a&&a.forEach(function(a){(a=D.getOptionFromViewValue(a))&&!a.disabled&&(a.element.selected=!0)})},u.readValue=function(){var a=h.val()||[],c=[];m(a,function(a){a=D.selectValueMap[a];a.disabled||c.push(D.getViewValueFromOption(a))});return c},z.trackBy&&c.$watchCollection(function(){if(G(v.$viewValue))return v.$viewValue.map(function(a){return z.getTrackByValue(a)})},
|
|
||||||
function(){v.$render()})):(u.writeValue=function(a){var c=D.getOptionFromViewValue(a);c&&!c.disabled?h[0].value!==c.selectValue&&(N.remove(),B||p.remove(),h[0].value=c.selectValue,c.element.selected=!0,c.element.setAttribute("selected","selected")):null===a||B?(N.remove(),B||h.prepend(p),h.val(""),p.prop("selected",!0),p.attr("selected",!0)):(B||p.remove(),h.prepend(N),h.val("?"),N.prop("selected",!0),N.attr("selected",!0))},u.readValue=function(){var a=D.selectValueMap[h.val()];return a&&!a.disabled?
|
|
||||||
(B||p.remove(),N.remove(),D.getViewValueFromOption(a)):null},z.trackBy&&c.$watch(function(){return z.getTrackByValue(v.$viewValue)},function(){v.$render()}));B?(p.remove(),a(p)(c),p.removeClass("ng-scope")):p=y(e.cloneNode(!1));t();c.$watchCollection(z.getWatchables,t)}}}}],Ce=["$locale","$interpolate","$log",function(a,c,d){var e=/{}/g,f=/^when(Minus)?(.+)$/;return{link:function(g,h,l){function k(a){h.text(a||"")}var n=l.count,r=l.$attr.when&&h.attr(l.$attr.when),s=l.offset||0,q=g.$eval(r)||{},t=
|
|
||||||
{},w=c.startSymbol(),u=c.endSymbol(),p=w+n+"-"+s+u,y=ca.noop,z;m(l,function(a,c){var d=f.exec(c);d&&(d=(d[1]?"-":"")+M(d[2]),q[d]=h.attr(l.$attr[c]))});m(q,function(a,d){t[d]=c(a.replace(e,p))});g.$watch(n,function(c){var e=parseFloat(c),f=isNaN(e);f||e in q||(e=a.pluralCat(e-s));e===z||f&&V(z)&&isNaN(z)||(y(),f=t[e],A(f)?(null!=c&&d.debug("ngPluralize: no rule defined for '"+e+"' in "+r),y=v,k()):y=g.$watch(f,k),z=e)})}}}],De=["$parse","$animate",function(a,c){var d=J("ngRepeat"),e=function(a,c,
|
|
||||||
d,e,k,m,r){a[d]=e;k&&(a[k]=m);a.$index=c;a.$first=0===c;a.$last=c===r-1;a.$middle=!(a.$first||a.$last);a.$odd=!(a.$even=0===(c&1))};return{restrict:"A",multiElement:!0,transclude:"element",priority:1E3,terminal:!0,$$tlb:!0,compile:function(f,g){var h=g.ngRepeat,l=U.createComment(" end ngRepeat: "+h+" "),k=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!k)throw d("iexp",h);var n=k[1],r=k[2],s=k[3],q=k[4],k=n.match(/^(?:(\s*[\$\w]+)|\(\s*([\$\w]+)\s*,\s*([\$\w]+)\s*\))$/);
|
|
||||||
if(!k)throw d("iidexp",n);var v=k[3]||k[1],w=k[2];if(s&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(s)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(s)))throw d("badident",s);var u,p,z,A,I={$id:Ga};q?u=a(q):(z=function(a,c){return Ga(c)},A=function(a){return a});return function(a,f,g,k,n){u&&(p=function(c,d,e){w&&(I[w]=c);I[v]=d;I.$index=e;return u(a,I)});var q=ga();a.$watchCollection(r,function(g){var k,r,u=f[0],x,D=ga(),I,H,L,G,M,J,O;s&&(a[s]=g);if(Ea(g))M=
|
|
||||||
g,r=p||z;else for(O in r=p||A,M=[],g)g.hasOwnProperty(O)&&"$"!==O.charAt(0)&&M.push(O);I=M.length;O=Array(I);for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],G=r(H,L,k),q[G])J=q[G],delete q[G],D[G]=J,O[k]=J;else{if(D[G])throw m(O,function(a){a&&a.scope&&(q[a.id]=a)}),d("dupes",h,G,L);O[k]={id:G,scope:t,clone:t};D[G]=!0}for(x in q){J=q[x];G=qb(J.clone);c.leave(G);if(G[0].parentNode)for(k=0,r=G.length;k<r;k++)G[k].$$NG_REMOVED=!0;J.scope.$destroy()}for(k=0;k<I;k++)if(H=g===M?k:M[k],L=g[H],J=O[k],J.scope){x=
|
|
||||||
u;do x=x.nextSibling;while(x&&x.$$NG_REMOVED);J.clone[0]!=x&&c.move(qb(J.clone),null,y(u));u=J.clone[J.clone.length-1];e(J.scope,k,v,L,w,H,I)}else n(function(a,d){J.scope=d;var f=l.cloneNode(!1);a[a.length++]=f;c.enter(a,null,y(u));u=f;J.clone=a;D[J.id]=J;e(J.scope,k,v,L,w,H,I)});q=D})}}}}],Ee=["$animate",function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngShow,function(c){a[c?"removeClass":"addClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],xe=["$animate",
|
|
||||||
function(a){return{restrict:"A",multiElement:!0,link:function(c,d,e){c.$watch(e.ngHide,function(c){a[c?"addClass":"removeClass"](d,"ng-hide",{tempClasses:"ng-hide-animate"})})}}}],Fe=Ma(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&m(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),Ge=["$animate",function(a){return{require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],l=[],k=[],n=function(a,c){return function(){a.splice(c,1)}};c.$watch(e.ngSwitch||
|
|
||||||
e.on,function(c){var d,e;d=0;for(e=l.length;d<e;++d)a.cancel(l[d]);d=l.length=0;for(e=k.length;d<e;++d){var q=qb(h[d].clone);k[d].$destroy();(l[d]=a.leave(q)).then(n(l,d))}h.length=0;k.length=0;(g=f.cases["!"+c]||f.cases["?"])&&m(g,function(c){c.transclude(function(d,e){k.push(e);var f=c.element;d[d.length++]=U.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],He=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,
|
|
||||||
f){e.cases["!"+d.ngSwitchWhen]=e.cases["!"+d.ngSwitchWhen]||[];e.cases["!"+d.ngSwitchWhen].push({transclude:f,element:c})}}),Ie=Ma({transclude:"element",priority:1200,require:"^ngSwitch",multiElement:!0,link:function(a,c,d,e,f){e.cases["?"]=e.cases["?"]||[];e.cases["?"].push({transclude:f,element:c})}}),Ke=Ma({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw J("ngTransclude")("orphan",ua(c));f(function(a){c.empty();c.append(a)})}}),ke=["$templateCache",function(a){return{restrict:"E",terminal:!0,
|
|
||||||
compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],Ag={$setViewValue:v,$render:v},Bg=["$element","$scope","$attrs",function(a,c,d){var e=this,f=new Sa;e.ngModelCtrl=Ag;e.unknownOption=y(U.createElement("option"));e.renderUnknownOption=function(c){c="? "+Ga(c)+" ?";e.unknownOption.val(c);a.prepend(e.unknownOption);a.val(c)};c.$on("$destroy",function(){e.renderUnknownOption=v});e.removeUnknownOption=function(){e.unknownOption.parent()&&e.unknownOption.remove()};e.readValue=
|
|
||||||
function(){e.removeUnknownOption();return a.val()};e.writeValue=function(c){e.hasOption(c)?(e.removeUnknownOption(),a.val(c),""===c&&e.emptyOption.prop("selected",!0)):null==c&&e.emptyOption?(e.removeUnknownOption(),a.val("")):e.renderUnknownOption(c)};e.addOption=function(a,c){Ra(a,'"option value"');""===a&&(e.emptyOption=c);var d=f.get(a)||0;f.put(a,d+1)};e.removeOption=function(a){var c=f.get(a);c&&(1===c?(f.remove(a),""===a&&(e.emptyOption=t)):f.put(a,c-1))};e.hasOption=function(a){return!!f.get(a)}}],
|
|
||||||
le=function(){return{restrict:"E",require:["select","?ngModel"],controller:Bg,link:function(a,c,d,e){var f=e[1];if(f){var g=e[0];g.ngModelCtrl=f;f.$render=function(){g.writeValue(f.$viewValue)};c.on("change",function(){a.$apply(function(){f.$setViewValue(g.readValue())})});if(d.multiple){g.readValue=function(){var a=[];m(c.find("option"),function(c){c.selected&&a.push(c.value)});return a};g.writeValue=function(a){var d=new Sa(a);m(c.find("option"),function(a){a.selected=w(d.get(a.value))})};var h,
|
|
||||||
l=NaN;a.$watch(function(){l!==f.$viewValue||ka(h,f.$viewValue)||(h=ia(f.$viewValue),f.$render());l=f.$viewValue});f.$isEmpty=function(a){return!a||0===a.length}}}}}},ne=["$interpolate",function(a){function c(a){a[0].hasAttribute("selected")&&(a[0].selected=!0)}return{restrict:"E",priority:100,compile:function(d,e){if(A(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var k=d.parent(),m=k.data("$selectController")||k.parent().data("$selectController");m&&m.ngModelCtrl&&
|
|
||||||
(f?a.$watch(f,function(a,f){e.$set("value",a);f!==a&&m.removeOption(f);m.addOption(a,d);m.ngModelCtrl.$render();c(d)}):(m.addOption(e.value,d),m.ngModelCtrl.$render(),c(d)),d.on("$destroy",function(){m.removeOption(e.value);m.ngModelCtrl.$render()}))}}}}],me=ra({restrict:"E",terminal:!1}),Hc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){e&&(d.required=!0,e.$validators.required=function(a,c){return!d.required||!e.$isEmpty(c)},d.$observe("required",function(){e.$validate()}))}}},
|
|
||||||
Gc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f,g=d.ngPattern||d.pattern;d.$observe("pattern",function(a){L(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw J("ngPattern")("noregexp",g,a,ua(c));f=a||t;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||A(f)||f.test(a)}}}}},Jc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=W(a);f=isNaN(a)?-1:a;e.$validate()});
|
|
||||||
e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(c)||c.length<=f}}}}},Ic=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=W(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}};O.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(ce(),ee(ca),y(U).ready(function(){Zd(U,Ac)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document.head).prepend('<style type="text/css">@charset "UTF-8";[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide:not(.ng-hide-animate){display:none !important;}ng\\:form{display:block;}.ng-animate-shim{visibility:hidden;}.ng-anchor{position:absolute;}</style>');
|
|
||||||
//# sourceMappingURL=angular.min.js.map
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,9 +0,0 @@
|
|||||||
/*!
|
|
||||||
* bootstrap-vertical-tabs - v1.2.1
|
|
||||||
* https://dbtek.github.io/bootstrap-vertical-tabs
|
|
||||||
* 2014-11-07
|
|
||||||
* Copyright (c) 2014 İsmail Demirbilek
|
|
||||||
* License: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
.tabs-left,.tabs-right{border-bottom:none;padding-top:2px}.tabs-left{border-right:1px solid #ddd}.tabs-right{border-left:1px solid #ddd}.tabs-left>li,.tabs-right>li{float:none;margin-bottom:2px}.tabs-left>li{margin-right:-1px}.tabs-right>li{margin-left:-1px}.tabs-left>li.active>a,.tabs-left>li.active>a:focus,.tabs-left>li.active>a:hover{border-bottom-color:#ddd;border-right-color:transparent}.tabs-right>li.active>a,.tabs-right>li.active>a:focus,.tabs-right>li.active>a:hover{border-bottom:1px solid #ddd;border-left-color:transparent}.tabs-left>li>a{border-radius:4px 0 0 4px;margin-right:0;display:block}.tabs-right>li>a{border-radius:0 4px 4px 0;margin-right:0}.sideways{margin-top:50px;border:none;position:relative}.sideways>li{height:20px;width:120px;margin-bottom:100px}.sideways>li>a{border-bottom:1px solid #ddd;border-right-color:transparent;text-align:center;border-radius:4px 4px 0 0}.sideways>li.active>a,.sideways>li.active>a:focus,.sideways>li.active>a:hover{border-bottom-color:transparent;border-right-color:#ddd;border-left-color:#ddd}.sideways.tabs-left{left:-50px}.sideways.tabs-right{right:-50px}.sideways.tabs-right>li{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.sideways.tabs-left>li{-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,109 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load widget_tweaks %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}"{{object.schema.schema_type.name}}" for "N{{object.event.pk|stringformat:"05d"}} | {{object.event.name}}"{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<h2>"{{object.schema.schema_type.name}}" for "<a href="{% url 'event_detail' object.event.pk %}">N{{object.event.pk|stringformat:"05d"}} | {{object.event.name}}</a>"</h2>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div ng-controller="FormController" class="col-sm-12">
|
|
||||||
|
|
||||||
<form name="theForm" ng-submit="onSubmit(theForm)">
|
|
||||||
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<a href="{% url 'form_list' object.event.pk %}" class="btn btn-default" title="Rig Forms"><span class="glyphicon glyphicon-chevron-left"></span> Other forms for N{{object.event.pk|stringformat:"05d"}}</a>
|
|
||||||
|
|
||||||
<div class="btn-group btn-page pull-right">
|
|
||||||
{% if not edit %}
|
|
||||||
<a href="{% url 'update_form' object.pk %}" class="btn btn-default"><span class="glyphicon glyphicon-edit"></span> <span class="hidden-xs">Edit</span></a>
|
|
||||||
<a href="{% url 'form_print' object.pk %}" class="btn btn-default"><span class="glyphicon glyphicon-print"></span> <span class="hidden-xs">Print</span></a>
|
|
||||||
{% endif %}
|
|
||||||
{% if edit %}
|
|
||||||
<button type="submit" class="btn btn-default" title="Save"><span
|
|
||||||
class="glyphicon glyphicon-floppy-disk"></span> <span class="hidden-xs">Save</button>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
{% include 'form_errors.html' %}
|
|
||||||
|
|
||||||
<div sf-schema="schema" sf-form="form" sf-model="model"
|
|
||||||
sf-options=" { formDefaults: { startEmpty: true,
|
|
||||||
{% if not edit %}
|
|
||||||
readonly: true,
|
|
||||||
{% endif %}
|
|
||||||
} }"></div>
|
|
||||||
|
|
||||||
{% if edit %}
|
|
||||||
<div class="btn-group btn-page pull-right">
|
|
||||||
<button type="submit" class="btn btn-default" title="Save"><span class="glyphicon glyphicon-floppy-disk"></span> <span class="hidden-xs">Save</button>
|
|
||||||
</div>
|
|
||||||
{% endif %}
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block js %}
|
|
||||||
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/angular.min.js"%}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/angular-sanitize.js"%}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/tv4.min.js"%}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/ObjectPath.js"%}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/schema-form.min.js"%}"></script>
|
|
||||||
<script type="text/javascript" src="{% static "js/angular-schema-form/bootstrap-decorator.min.js"%}"></script>
|
|
||||||
<link rel="stylesheet" type="text/css" href="{% static "js/angular-schema-form/bootstrap.vertical-tabs.min.css"%}"/>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
$(document).ready(function () {
|
|
||||||
angular.module('myModule', ['schemaForm']).controller('FormController', function($scope) {
|
|
||||||
{% autoescape off %} {# otherwise quotes get replaced with HTML entities #}
|
|
||||||
$scope.schema = {{ object.renderedSchema }};
|
|
||||||
|
|
||||||
$scope.form = {{ object.renderedLayout }};
|
|
||||||
|
|
||||||
{% comment %}
|
|
||||||
//This is useful for development, allowing the schema & layout to reside in the file system (you need to make the relevant files in the templates directory). Commented out for production
|
|
||||||
$scope.schema = {% include "rigForms/schema.js" %};
|
|
||||||
|
|
||||||
$scope.form = {% include "rigForms/layout.js" %};
|
|
||||||
{% endcomment %}
|
|
||||||
|
|
||||||
$scope.model = {{ object.data }};
|
|
||||||
{% endautoescape %}
|
|
||||||
|
|
||||||
$scope.onSubmit = function(form) {
|
|
||||||
// First we broadcast an event so all fields validate themselves
|
|
||||||
$scope.$broadcast('schemaFormValidate');
|
|
||||||
|
|
||||||
// Then we check if the form is valid
|
|
||||||
if (form.$valid) {
|
|
||||||
|
|
||||||
//Submit the data in JSON form
|
|
||||||
var form = $('<form action="" method="post">' + "{% csrf_token %}" +
|
|
||||||
'<input style="display:none" type="text" name="data" value="" />' +
|
|
||||||
'</form>');
|
|
||||||
|
|
||||||
$('input[name="data"]', form).val(JSON.stringify($scope.model));
|
|
||||||
|
|
||||||
$('body').append(form);
|
|
||||||
|
|
||||||
form.submit();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
angular.bootstrap(document, ['myModule']);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
{% extends request.is_ajax|yesno:"base_ajax.html,base.html" %}
|
|
||||||
{% load widget_tweaks %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
|
|
||||||
{% block title %}List of Forms{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<h2>Forms for "<a href="{% url 'event_detail' event.pk %}">N{{event.pk|stringformat:"05d"}} | {{event.name}}</a>"</h2>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-12 text-right">
|
|
||||||
<div class="btn-group btn-page">
|
|
||||||
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
|
||||||
<span class="glyphicon glyphicon-plus"></span> Add Form <span class="caret"></span>
|
|
||||||
</button>
|
|
||||||
<ul class="dropdown-menu">
|
|
||||||
{% for type in formTypes %}
|
|
||||||
<li><a href="{% url 'create_form' event_pk=event.pk type_pk=type.pk %}">{{type.name}}</a></li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<table class="table table-responsive table-hover">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>#</th>
|
|
||||||
<th>Form Type</th>
|
|
||||||
<th>Last Edited</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for object in object_list %}
|
|
||||||
<tr>
|
|
||||||
<td>{{ object.pk }}</td>
|
|
||||||
<td>{{ object.schema.schema_type.name }}</td>
|
|
||||||
<td>{{ object.last_edited_by }} at {{ object.last_edited_at }}</td>
|
|
||||||
<td class="text-right">
|
|
||||||
<div class="btn-group">
|
|
||||||
<a href="{% url 'form_detail' object.pk %}" class="btn btn-default">
|
|
||||||
<span class="glyphicon glyphicon-eye-open"></span>
|
|
||||||
</a>
|
|
||||||
<a href="{% url 'update_form' object.pk %}" class="btn btn-default">
|
|
||||||
<span class="glyphicon glyphicon-pencil"></span>
|
|
||||||
</a>
|
|
||||||
<a href="{% url 'form_print' object.pk %}" target="_blank" class="btn btn-default">
|
|
||||||
<span class="glyphicon glyphicon-print"></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
{% load multiply from filters %}
|
|
||||||
{% load static %}
|
|
||||||
<!DOCTYPE document SYSTEM "rml.dtd">
|
|
||||||
|
|
||||||
<document filename="Form Print.pdf">
|
|
||||||
<docinit>
|
|
||||||
<registerTTFont faceName="OpenSans" fileName="{{ fonts.opensans.regular }}"/>
|
|
||||||
<registerTTFont faceName="OpenSans-Bold" fileName="{{ fonts.opensans.bold }}"/>
|
|
||||||
<registerFontFamily name="OpenSans" bold="OpenSans-Bold" boldItalic="OpenSans-Bold"/>
|
|
||||||
</docinit>
|
|
||||||
|
|
||||||
<stylesheet>
|
|
||||||
<initialize>
|
|
||||||
<color id="LightGray" RGB="#D3D3D3"/>
|
|
||||||
<color id="DarkGray" RGB="#707070"/>
|
|
||||||
</initialize>
|
|
||||||
|
|
||||||
<paraStyle name="style.para" fontName="OpenSans" />
|
|
||||||
<paraStyle name="blockPara" spaceAfter="5" spaceBefore="5"/>
|
|
||||||
<paraStyle name="style.Heading1" fontName="OpenSans" fontSize="16" leading="18" spaceAfter="0"/>
|
|
||||||
<paraStyle name="style.Heading2" fontName="OpenSans-Bold" fontSize="10" spaceAfter="2"/>
|
|
||||||
<paraStyle name="style.Heading3" fontName="OpenSans" fontSize="10" spaceAfter="0"/>
|
|
||||||
<paraStyle name="center" alignment="center"/>
|
|
||||||
|
|
||||||
<blockTableStyle id="checkboxTable">
|
|
||||||
<blockValign start="0,0" stop="-1,-1" value="top"/>
|
|
||||||
<lineStyle kind="linebelow" start="1,0" stop="-1,-1" colorName="lightgrey"/>
|
|
||||||
<blockLeftPadding start="0,0" stop="-1,-1" length="0"/>
|
|
||||||
</blockTableStyle>
|
|
||||||
|
|
||||||
<blockTableStyle id="stringTable">
|
|
||||||
<blockValign start="0,0" stop="-1,-1" value="top"/>
|
|
||||||
<lineStyle kind="linebelow" start="1,0" stop="-1,-1" colorName="lightgrey"/>
|
|
||||||
</blockTableStyle>
|
|
||||||
<blockTableStyle id="objectTable">
|
|
||||||
<blockValign start="0,0" stop="-1,-1" value="top"/>
|
|
||||||
<lineStyle kind="linebelow" start="1,0" stop="-1,-1" colorName="lightgrey"/>
|
|
||||||
</blockTableStyle>
|
|
||||||
</stylesheet>
|
|
||||||
|
|
||||||
<template > {# Note: page is 595x842 points (1 point=1/72in) #}
|
|
||||||
<pageTemplate id="Headed" >
|
|
||||||
<pageGraphics>
|
|
||||||
<image file="RIGS/static/imgs/paperwork/corner-tr-su.jpg" x="395" y="642" height="200" width="200"/>
|
|
||||||
<image file="RIGS/static/imgs/paperwork/corner-bl.jpg" x="0" y="0" height="200" width="200"/>
|
|
||||||
|
|
||||||
{# logo positioned 42 from left, 33 from top #}
|
|
||||||
<image file="RIGS/static/imgs/paperwork/tec-logo.jpg" x="42" y="719" height="90" width="84"/>
|
|
||||||
|
|
||||||
<setFont name="OpenSans-Bold" size="22.5" leading="10"/>
|
|
||||||
<drawString x="137" y="780">TEC PA & Lighting</drawString>
|
|
||||||
|
|
||||||
<setFont name="OpenSans" size="9"/>
|
|
||||||
<drawString x="137" y="760">Portland Building, University Park, Nottingham, NG7 2RD</drawString>
|
|
||||||
<drawString x="137" y="746">www.nottinghamtec.co.uk</drawString>
|
|
||||||
<drawString x="265" y="746">info@nottinghamtec.co.uk</drawString>
|
|
||||||
<drawString x="137" y="732">Phone: (0115) 846 8720</drawString>
|
|
||||||
|
|
||||||
<setFont name="OpenSans" size="10" />
|
|
||||||
{% if copy %}<drawCenteredString x="302.5" y="50">[{{ copy }} Copy]</drawCenteredString>{% endif %}
|
|
||||||
<drawCenteredString x="302.5" y="38">[Page <pageNumber/> of <getName id="lastPage" default="0" />]</drawCenteredString>
|
|
||||||
</pageGraphics>
|
|
||||||
|
|
||||||
<frame id="main" x1="50" y1="65" width="495" height="645"/>
|
|
||||||
</pageTemplate>
|
|
||||||
|
|
||||||
<pageTemplate id="Main">
|
|
||||||
<pageGraphics>
|
|
||||||
<image file="RIGS/static/imgs/paperwork/corner-tr.jpg" x="395" y="642" height="200" width="200"/>
|
|
||||||
<image file="RIGS/static/imgs/paperwork/corner-bl.jpg" x="0" y="0" height="200" width="200"/>
|
|
||||||
|
|
||||||
<setFont name="OpenSans" size="10"/>
|
|
||||||
{% if copy %}<drawCenteredString x="302.5" y="50">[{{ copy }} Copy]</drawCenteredString>{% endif %}
|
|
||||||
<drawCenteredString x="302.5" y="38">[Page <pageNumber/> of <getName id="lastPage" default="0" />]</drawCenteredString>
|
|
||||||
</pageGraphics>
|
|
||||||
<frame id="main" x1="50" y1="65" width="495" height="727"/>
|
|
||||||
</pageTemplate>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<story firstPageTemplate="Headed">
|
|
||||||
{% include "rigForms/form_print_page.xml" %}
|
|
||||||
</story>
|
|
||||||
|
|
||||||
</document>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<setNextFrame name="main"/>
|
|
||||||
<nextFrame/>
|
|
||||||
<setNextTemplate name="Main"/>
|
|
||||||
|
|
||||||
<h1><b>{{ form.schema.schema_type.name }}</b><small></small></h1>
|
|
||||||
<spacer length="10"/>
|
|
||||||
|
|
||||||
|
|
||||||
{% autoescape off %}
|
|
||||||
|
|
||||||
{{ formData }}
|
|
||||||
|
|
||||||
{% endautoescape %}
|
|
||||||
|
|
||||||
<namedString id="lastPage"><pageNumber/></namedString>
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<blockTable colWidths="{{currentIndent}},100%" alignment="left" style="objectTable">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td><h1>{{field.title}}</h1></td>
|
|
||||||
</tr>
|
|
||||||
</blockTable>
|
|
||||||
|
|
||||||
{% autoescape off %}
|
|
||||||
|
|
||||||
{% for child in children %}
|
|
||||||
{{ child }}
|
|
||||||
{% empty %}
|
|
||||||
<blockTable colWidths="{{currentIndent}},100%" alignment="left" style="objectTable">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td><para>(No items recorded)</para></td>
|
|
||||||
</tr>
|
|
||||||
</blockTable>
|
|
||||||
{% endfor %}
|
|
||||||
|
|
||||||
{% endautoescape %}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<blockTable colWidths="{{currentIndent}},25,100%" alignment="left" style="checkboxTable">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td>
|
|
||||||
{% if value %}
|
|
||||||
<img src="rigForms/static/images/form-print/checked_checkbox.jpg" width="20" height="20"/>
|
|
||||||
{% else %}
|
|
||||||
<img src="rigForms/static/images/form-print/unchecked_checkbox.jpg" width="20" height="20"/>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td><h4>{{field.title}}</h4>
|
|
||||||
<para>{{field.description}}</para></td>
|
|
||||||
</tr>
|
|
||||||
</blockTable>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<blockTable colWidths="{{currentIndent}},100%" alignment="left" style="objectTable">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td><h1>{{field.title}}</h1>
|
|
||||||
<para>{{field.description}}</para></td>
|
|
||||||
</tr>
|
|
||||||
</blockTable>
|
|
||||||
|
|
||||||
{% autoescape off %}
|
|
||||||
|
|
||||||
{{ children }}
|
|
||||||
|
|
||||||
{% endautoescape %}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<blockTable colWidths="{{currentIndent}},100%,100%" alignment="left" style="stringTable">
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td>
|
|
||||||
<h4>{{field.title}}</h4>
|
|
||||||
<para>{{field.description}}</para>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<para>{{value|default_if_none:""|linebreaksbr}}</para></td>
|
|
||||||
</tr>
|
|
||||||
</blockTable>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
from django.test import TestCase
|
|
||||||
from rigForms import models
|
|
||||||
|
|
||||||
class FormModelsTestCase(TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.schemaType1 = models.Type.objects.create(name="Test Type",description="Description of a test type")
|
|
||||||
models.Schema.objects.create(start_at='2014-03-01',comment='test1', schema_type=self.schemaType1)
|
|
||||||
models.Schema.objects.create(start_at='2016-03-01',comment='test2', schema_type=self.schemaType1)
|
|
||||||
|
|
||||||
self.schemaType2 = models.Type.objects.create(name="Test Type 2",description="Description of the second test type")
|
|
||||||
models.Schema.objects.create(start_at='2014-03-01',comment='test3', schema_type=self.schemaType2)
|
|
||||||
models.Schema.objects.create(start_at='2016-03-01',comment='test4', schema_type=self.schemaType2)
|
|
||||||
|
|
||||||
def test_find_correct(self):
|
|
||||||
r = models.Schema.objects.find_schema(self.schemaType1, '2015-03-01')
|
|
||||||
self.assertEqual(r.comment, 'test1')
|
|
||||||
r = models.Schema.objects.find_schema(self.schemaType1, '2016-03-01')
|
|
||||||
self.assertEqual(r.comment, 'test2')
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
from django.conf.urls import patterns, url
|
|
||||||
|
|
||||||
from PyRIGS.decorators import permission_required_with_403
|
|
||||||
|
|
||||||
from rigForms import views
|
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
|
||||||
url(r'^create/(?P<type_pk>\d+)/for-event/(?P<event_pk>\d+)/$', permission_required_with_403('rigForms.create_form')(views.FormCreate.as_view()),
|
|
||||||
name='create_form'),
|
|
||||||
url(r'^(?P<pk>\d+)/$', permission_required_with_403('rigForms.view_form')(views.FormDetail.as_view()),
|
|
||||||
name='form_detail'),
|
|
||||||
url(r'^(?P<pk>\d+)/edit/$', permission_required_with_403('rigForms.update_form')(views.FormUpdate.as_view()),
|
|
||||||
name='update_form'),
|
|
||||||
url(r'^for-event/(?P<event_pk>\d+)/$', permission_required_with_403('rigForms.view_form')(views.FormList.as_view()),
|
|
||||||
name='form_list'),
|
|
||||||
url(r'^(?P<pk>\d+)/print/$', permission_required_with_403('rigForms.view_form')(views.FormPrint.as_view()), name='form_print'),
|
|
||||||
)
|
|
||||||
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
from django.shortcuts import render
|
|
||||||
from django.views import generic
|
|
||||||
from rigForms import models
|
|
||||||
|
|
||||||
from django.shortcuts import get_object_or_404
|
|
||||||
from django.http.response import HttpResponseRedirect
|
|
||||||
from django.core.urlresolvers import reverse_lazy, reverse, NoReverseMatch
|
|
||||||
from django.db.models import Q
|
|
||||||
|
|
||||||
import json
|
|
||||||
from collections import OrderedDict
|
|
||||||
from z3c.rml import rml2pdf
|
|
||||||
from django.template.loader import get_template
|
|
||||||
from django.template import RequestContext
|
|
||||||
import cStringIO as StringIO
|
|
||||||
import re
|
|
||||||
import copy
|
|
||||||
|
|
||||||
|
|
||||||
from django.http import HttpResponse
|
|
||||||
|
|
||||||
import RIGS
|
|
||||||
|
|
||||||
class FormCreate(generic.CreateView):
|
|
||||||
model = models.Form
|
|
||||||
fields = ['data']
|
|
||||||
|
|
||||||
"""
|
|
||||||
Whenever this view is loaded, get the schema from the url
|
|
||||||
Expects kwarg "type_pk" to contain PK of required type
|
|
||||||
"""
|
|
||||||
def dispatch(self, *args, **kwargs):
|
|
||||||
|
|
||||||
schemaType = get_object_or_404(models.Type, pk=kwargs['type_pk'])
|
|
||||||
currentSchema = models.Schema.objects.current_schema(schemaType)
|
|
||||||
|
|
||||||
event = get_object_or_404(RIGS.models.Event, pk=kwargs['event_pk'])
|
|
||||||
|
|
||||||
self.initial_object = models.Form(event=event, schema=currentSchema)
|
|
||||||
|
|
||||||
return super(FormCreate, self).dispatch(*args, **kwargs)
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(FormCreate, self).get_context_data()
|
|
||||||
|
|
||||||
context["object"] = self.initial_object
|
|
||||||
context["edit"] = True
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
def form_valid(self, form):
|
|
||||||
self.object = self.initial_object
|
|
||||||
|
|
||||||
self.object.data = form.save(commit=False).data
|
|
||||||
|
|
||||||
self.object.save()
|
|
||||||
return HttpResponseRedirect(self.get_success_url())
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse_lazy('form_detail', kwargs={
|
|
||||||
'pk': self.object.pk,
|
|
||||||
})
|
|
||||||
|
|
||||||
class FormDetail(generic.DetailView):
|
|
||||||
model = models.Form
|
|
||||||
template_name = 'rigForms/form_form.html'
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse_lazy('update_form', kwargs={
|
|
||||||
'pk': self.object.pk,
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(FormDetail, self).get_context_data()
|
|
||||||
|
|
||||||
context["edit"] = False
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
class FormUpdate(generic.UpdateView):
|
|
||||||
model = models.Form
|
|
||||||
fields = ['data']
|
|
||||||
|
|
||||||
def get_success_url(self):
|
|
||||||
return reverse_lazy('form_detail', kwargs={
|
|
||||||
'pk': self.object.pk,
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
|
||||||
context = super(FormUpdate, self).get_context_data()
|
|
||||||
|
|
||||||
context["edit"] = True
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
class FormList(generic.ListView):
|
|
||||||
model = models.Form
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
event = get_object_or_404(RIGS.models.Event,pk=self.kwargs["event_pk"])
|
|
||||||
object_list = self.model.objects.filter(Q(event=event))
|
|
||||||
|
|
||||||
return object_list
|
|
||||||
|
|
||||||
def get_context_data(self):
|
|
||||||
context = super(FormList, self).get_context_data()
|
|
||||||
context['event'] = get_object_or_404(RIGS.models.Event,pk=self.kwargs["event_pk"])
|
|
||||||
|
|
||||||
context['formTypes'] = models.Type.objects.filter(Q(active=True))
|
|
||||||
|
|
||||||
return context
|
|
||||||
|
|
||||||
class FormPrint(generic.TemplateView):
|
|
||||||
indentBy = 20
|
|
||||||
|
|
||||||
def _render_array(self, field, value, current_indent):
|
|
||||||
# Render all the child form bits first
|
|
||||||
children=[]
|
|
||||||
|
|
||||||
try:
|
|
||||||
numberOfChildren = len(value)
|
|
||||||
|
|
||||||
for key,item in enumerate(value):
|
|
||||||
# Append the item number onto the item title
|
|
||||||
thisField = copy.deepcopy(field["items"])
|
|
||||||
thisField["title"] = thisField.get("title","Item") + " " + str(key+1)
|
|
||||||
|
|
||||||
children.append(self._render_field_item(thisField,item,current_indent+self.indentBy))
|
|
||||||
except TypeError:
|
|
||||||
numberOfChildren = 0
|
|
||||||
|
|
||||||
template = get_template('rigForms/print/render-array.xml')
|
|
||||||
context = {
|
|
||||||
'field': field,
|
|
||||||
'children': children,
|
|
||||||
'currentIndent':current_indent
|
|
||||||
}
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def _render_object(self, field, value, current_indent):
|
|
||||||
# Render all the child form bits first
|
|
||||||
children = self._render_field(field["properties"], value, current_indent + self.indentBy)
|
|
||||||
|
|
||||||
template = get_template('rigForms/print/render-object.xml')
|
|
||||||
context = {
|
|
||||||
'field': field,
|
|
||||||
'children': children,
|
|
||||||
'currentIndent':current_indent
|
|
||||||
}
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def _render_string(self, field, value, current_indent):
|
|
||||||
template = get_template('rigForms/print/render-string.xml')
|
|
||||||
context = {
|
|
||||||
'field': field,
|
|
||||||
'currentIndent':current_indent,
|
|
||||||
'value':value
|
|
||||||
}
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def _render_boolean(self, field, value, current_indent):
|
|
||||||
template = get_template('rigForms/print/render-boolean.xml')
|
|
||||||
context = {
|
|
||||||
'field': field,
|
|
||||||
'currentIndent':current_indent,
|
|
||||||
'value':value
|
|
||||||
}
|
|
||||||
return template.render(context)
|
|
||||||
|
|
||||||
def _render_field_item(self, field, value, current_indent):
|
|
||||||
renderFunctions = {
|
|
||||||
"object": self._render_object,
|
|
||||||
"string": self._render_string,
|
|
||||||
"number": self._render_string,
|
|
||||||
"integer": self._render_string,
|
|
||||||
"array": self._render_array,
|
|
||||||
"boolean": self._render_boolean,
|
|
||||||
|
|
||||||
#error values:
|
|
||||||
"unknown": lambda: "<h4>(Field type unknown: " + str(key) + ": " + str(field) + ")</h4>",
|
|
||||||
"notype": lambda: "<h4>(No field type: " + str(key) + ": " + str(field) + ")</h4>",
|
|
||||||
"notOD": lambda: "<h4>(Not an OrderedDict: " + str(key) + ": " + str(field) + ")</h4>",
|
|
||||||
}
|
|
||||||
|
|
||||||
result = ""
|
|
||||||
if type(field) is OrderedDict:
|
|
||||||
fieldType = field.get("type","notype")
|
|
||||||
func = renderFunctions.get(fieldType, renderFunctions["unknown"])
|
|
||||||
result += func(field, value, current_indent)
|
|
||||||
else:
|
|
||||||
result += renderFunctions["notOD"]()
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _render_field(self, parentField, parentValue, current_indent):
|
|
||||||
result = ""
|
|
||||||
for (key,field) in parentField.items():
|
|
||||||
try:
|
|
||||||
value = parentValue.get(key,None)
|
|
||||||
except AttributeError: # if parentValue is None
|
|
||||||
value = None
|
|
||||||
result += self._render_field_item(field, value, current_indent)
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
def get(self, request, pk):
|
|
||||||
form = get_object_or_404(models.Form, pk=pk)
|
|
||||||
|
|
||||||
jsonSchema = json.loads(form.schema.schema, object_pairs_hook=OrderedDict)
|
|
||||||
jsonData = json.loads(form.data, object_pairs_hook=OrderedDict)
|
|
||||||
|
|
||||||
formData = self._render_field(jsonSchema["properties"], jsonData, 0)
|
|
||||||
|
|
||||||
# For development return the raw string
|
|
||||||
# response = HttpResponse()
|
|
||||||
# response.write(pdfData)
|
|
||||||
# return response
|
|
||||||
|
|
||||||
template = get_template('rigForms/form_print.xml')
|
|
||||||
|
|
||||||
context = RequestContext(request, {
|
|
||||||
'fonts': {
|
|
||||||
'opensans': {
|
|
||||||
'regular': 'RIGS/static/fonts/OPENSANS-REGULAR.TTF',
|
|
||||||
'bold': 'RIGS/static/fonts/OPENSANS-BOLD.TTF',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'formData':formData,
|
|
||||||
'form':form
|
|
||||||
})
|
|
||||||
|
|
||||||
rml = template.render(context)
|
|
||||||
buffer = StringIO.StringIO()
|
|
||||||
|
|
||||||
buffer = rml2pdf.parseString(rml)
|
|
||||||
|
|
||||||
pdfData = buffer.read()
|
|
||||||
|
|
||||||
# escapedEventName = re.sub('[^a-zA-Z0-9 \n\.]', '', object.name)
|
|
||||||
|
|
||||||
response = HttpResponse(content_type='application/pdf')
|
|
||||||
response['Content-Disposition'] = "filename=Form.pdf"
|
|
||||||
response.write(pdfData)
|
|
||||||
return response
|
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<link rel="icon" type="image/png" href="{% static "imgs/pyrigs-avatar.png" %}">
|
<link rel="icon" type="image/png" href="{% static "imgs/pyrigs-avatar.png" %}">
|
||||||
<link rel="apple-touch-icon" href="{% static "imgs/pyrigs-avatar.png" %}">
|
<link rel="apple-touch-icon" href="{% static "imgs/pyrigs-avatar.png" %}">
|
||||||
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400italic,700,300,400' rel='stylesheet'
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400italic,700,300,400' rel='stylesheet'
|
||||||
type='text/css'>
|
type='text/css'>
|
||||||
|
|
||||||
|
|
||||||
@@ -74,12 +74,12 @@
|
|||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Invoices<b class="caret"></b></a>
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Invoices<b class="caret"></b></a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li><a href="{% url 'invoice_list' %}"><span class="glyphicon glyphicon-gbp"></span> Active</a>
|
|
||||||
</li>
|
|
||||||
{% if perms.RIGS.add_invoice %}
|
{% if perms.RIGS.add_invoice %}
|
||||||
<li><a href="{% url 'invoice_waiting' %}"><span
|
<li><a href="{% url 'invoice_waiting' %}"><span
|
||||||
class="glyphicon glyphicon-briefcase"></span> Waiting</a></li>
|
class="glyphicon glyphicon-briefcase text-danger"></span> Waiting</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li><a href="{% url 'invoice_list' %}"><span class="glyphicon glyphicon-gbp text-warning"></span> Outstanding</a>
|
||||||
|
</li>
|
||||||
<li><a href="{% url 'invoice_archive' %}"><span class="glyphicon glyphicon-book"></span>
|
<li><a href="{% url 'invoice_archive' %}"><span class="glyphicon glyphicon-book"></span>
|
||||||
Archive</a></li>
|
Archive</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
49
templates/base_embed.html
Normal file
49
templates/base_embed.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{% load static from staticfiles %}
|
||||||
|
{% load raven %}
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html
|
||||||
|
dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
|
||||||
|
xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
|
||||||
|
lang="{% firstof LANGUAGE_CODE 'en' %}"
|
||||||
|
class="embedded">
|
||||||
|
<head>
|
||||||
|
<base target="_blank" />
|
||||||
|
<!-- Open all links in a new tab, not in the iframe -->
|
||||||
|
|
||||||
|
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400italic,700,300,400' rel='stylesheet'
|
||||||
|
type='text/css'>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static "css/screen.css" %}">
|
||||||
|
|
||||||
|
<script src="https://code.jquery.com/jquery-1.8.3.min.js"
|
||||||
|
integrity="sha256-YcbK69I5IXQftf/mYD8WY0/KmEDCv1asggHpJk1trM8=" crossorigin="anonymous"></script>
|
||||||
|
<script src="https://cdn.ravenjs.com/1.3.0/jquery,native/raven.min.js"></script>
|
||||||
|
<script>Raven.config('{% sentry_public_dsn %}').install()</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{% include "analytics.html" %}
|
||||||
|
|
||||||
|
<div class="embed_container">
|
||||||
|
<div class="container-fluid">
|
||||||
|
{% if messages %}
|
||||||
|
{% for message in messages %}
|
||||||
|
<div class="alert alert-{{ message.level_tag }} alert-dismissible" role="alert">
|
||||||
|
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
|
||||||
|
aria-hidden="true">×</span></button>
|
||||||
|
{{ message }}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% endblock %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
templates/login_redirect.html
Normal file
24
templates/login_redirect.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% block title %}Login Required{% endblock %}
|
||||||
|
|
||||||
|
{% block js %}
|
||||||
|
<script>
|
||||||
|
document.location = "{{login_url}}"
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block extra-head %}
|
||||||
|
{% if oembed_url %}
|
||||||
|
<link rel="alternate" type="application/json+oembed"
|
||||||
|
href="{{oembed_url}}"
|
||||||
|
title="RIGS Embed" />
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="text-center">
|
||||||
|
<h2>Login is required for this page</h2>
|
||||||
|
<a href="{{login_url}}" class="btn btn-primary">Login</a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@@ -1 +1 @@
|
|||||||
{{ user }} activation required
|
{{ user|safe }} activation required
|
||||||
|
|||||||
@@ -3,5 +3,8 @@
|
|||||||
{% block title %}Login{% endblock %}
|
{% block title %}Login{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<div class="text-center">
|
||||||
|
<h1>R<small>ig</small> I<small>nformation</small> G<small>athering</small> S<small>ystem</small></h1>
|
||||||
|
</div>
|
||||||
{% include 'registration/loginform.html' %}
|
{% include 'registration/loginform.html' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
34
templates/registration/login_embed.html
Normal file
34
templates/registration/login_embed.html
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% extends 'base_embed.html' %}
|
||||||
|
{% load widget_tweaks %}
|
||||||
|
|
||||||
|
{% block title %}Login{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="text-center">
|
||||||
|
<h1>R<small>ig</small> I<small>nformation</small> G<small>athering</small> S<small>ystem</small></h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'form_errors.html' %}
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-sm-6 col-sm-offset-3 col-lg-4 col-lg-offset-4">
|
||||||
|
|
||||||
|
<form id="loginForm" action="" method="post" role="form" target="_self">{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="id_username">{{ form.username.label }}</label>
|
||||||
|
{% render_field form.username class+="form-control" placeholder=form.username.label %}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="{{ form.password.id_for_label }}">{{ form.password.label }}</label>
|
||||||
|
{% render_field form.password class+="form-control" placeholder=form.password.label %}
|
||||||
|
</div>
|
||||||
|
<div class="text-right">
|
||||||
|
<input type="submit" value="Login" class="btn btn-primary"/>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="next" value="{{ next }}"/>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
{% include 'form_errors.html' %}
|
{% include 'form_errors.html' %}
|
||||||
<div class="col-sm-6 col-sm-offset-3 col-lg-4 col-lg-offset-4">
|
<div class="col-sm-6 col-sm-offset-3 col-lg-4 col-lg-offset-4">
|
||||||
|
|
||||||
<form action="{% url 'login' %}" method="post" role="form">{% csrf_token %}
|
<form action="{% url 'login' %}" method="post" role="form" target="_self">{% csrf_token %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="id_username">{{ form.username.label }}</label>
|
<label for="id_username">{{ form.username.label }}</label>
|
||||||
{% render_field form.username class+="form-control" placeholder=form.username.label autofocus="" %}
|
{% render_field form.username class+="form-control" placeholder=form.username.label autofocus="" %}
|
||||||
@@ -12,9 +12,11 @@
|
|||||||
<label for="{{ form.password.id_for_label }}">{{ form.password.label }}</label>
|
<label for="{{ form.password.id_for_label }}">{{ form.password.label }}</label>
|
||||||
{% render_field form.password class+="form-control" placeholder=form.password.label %}
|
{% render_field form.password class+="form-control" placeholder=form.password.label %}
|
||||||
</div>
|
</div>
|
||||||
<a href="{% url 'registration_register' %}" class="btn">Register</a>
|
<div class="text-right">
|
||||||
<a href="{% url 'password_reset' %}" class="btn">Forgotten Password</a>
|
<a href="{% url 'registration_register' %}" class="btn">Register</a>
|
||||||
<input type="submit" value="Login" class="btn btn-primary"/>
|
<a href="{% url 'password_reset' %}" class="btn">Forgotten Password</a>
|
||||||
<input type="hidden" name="next" value="{{ next }}"/>
|
<input type="submit" value="Login" class="btn btn-primary"/>
|
||||||
|
<input type="hidden" name="next" value="{{ next }}"/>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
103
wercker.yml
103
wercker.yml
@@ -1,103 +0,0 @@
|
|||||||
# This references the default Python container from
|
|
||||||
# the Docker Hub with the 2.7 tag:
|
|
||||||
# https://registry.hub.docker.com/_/python/
|
|
||||||
# If you want to use a slim Python container with
|
|
||||||
# version 3.4.3 you would use: python:3.4-slim
|
|
||||||
# If you want Google's container you would reference google/python
|
|
||||||
# Read more about containers on our dev center
|
|
||||||
# http://devcenter.wercker.com/docs/containers/index.html
|
|
||||||
box: heroku/python
|
|
||||||
# You can also use services such as databases. Read more on our dev center:
|
|
||||||
# http://devcenter.wercker.com/docs/services/index.html
|
|
||||||
services:
|
|
||||||
# - id: postgres
|
|
||||||
# env:
|
|
||||||
# POSTGRES_PASSWORD: pyrigstesting
|
|
||||||
# POSTGRES_USER: pyrigs
|
|
||||||
# http://devcenter.wercker.com/docs/services/postgresql.html
|
|
||||||
|
|
||||||
# - mongodb
|
|
||||||
# http://devcenter.wercker.com/docs/services/mongodb.html
|
|
||||||
|
|
||||||
# This is the build pipeline. Pipelines are the core of wercker
|
|
||||||
# Read more about pipelines on our dev center
|
|
||||||
# http://devcenter.wercker.com/docs/pipelines/index.html
|
|
||||||
build:
|
|
||||||
# The steps that will be executed on build
|
|
||||||
# Steps make up the actions in your pipeline
|
|
||||||
# Read more about steps on our dev center:
|
|
||||||
# http://devcenter.wercker.com/docs/steps/index.html
|
|
||||||
steps:
|
|
||||||
- install-packages:
|
|
||||||
packages: firefox xvfb
|
|
||||||
|
|
||||||
- script:
|
|
||||||
name: Enable virtual display
|
|
||||||
code: |-
|
|
||||||
# Start xvfb which gives the context an virtual display
|
|
||||||
# which is required for tests that require an GUI
|
|
||||||
export DISPLAY=:99.0
|
|
||||||
start-stop-daemon --start --quiet --pidfile /tmp/xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 1024x768x24 -ac +extension GLX +render -noreset
|
|
||||||
# Give xvfb time to start. 3 seconds is the default for all xvfb-run commands.
|
|
||||||
# sleep 3
|
|
||||||
|
|
||||||
- script:
|
|
||||||
name: virtualenv install
|
|
||||||
code: |
|
|
||||||
pip install virtualenv
|
|
||||||
|
|
||||||
# A step that sets up the python virtual environment
|
|
||||||
- virtualenv:
|
|
||||||
name: setup virtual environment
|
|
||||||
install_wheel: false # Enable wheel to speed up builds (experimental)
|
|
||||||
|
|
||||||
# # Use this virtualenv step for python 3.2
|
|
||||||
# - virtualenv
|
|
||||||
# name: setup virtual environment
|
|
||||||
# python_location: /usr/bin/python3.2
|
|
||||||
|
|
||||||
# # This pip-install clears the local wheel cache
|
|
||||||
# - pip-install:
|
|
||||||
# clean_wheel_dir: true
|
|
||||||
|
|
||||||
# A custom script step, name value is used in the UI
|
|
||||||
# and the code value contains the command that get executed
|
|
||||||
- script:
|
|
||||||
name: Python Version
|
|
||||||
code: |
|
|
||||||
echo "python version $(python --version) running"
|
|
||||||
echo "pip version $(pip --version) running"
|
|
||||||
|
|
||||||
# Django uses this to connect to the database
|
|
||||||
# - script:
|
|
||||||
# name: set environment
|
|
||||||
# code: |
|
|
||||||
# export DEBUG=0
|
|
||||||
# export DATABASE_URL="postgres://pyrigs:pyrigstesting@$POSTGRES_PORT_5432_TCP_ADDR:$POSTGRES_PORT_5432_TCP_PORT$POSTGRES_NAME"
|
|
||||||
|
|
||||||
# A step that executes `pip install` command.
|
|
||||||
- pip-install
|
|
||||||
|
|
||||||
# Install coverage
|
|
||||||
- script:
|
|
||||||
name: install coverage
|
|
||||||
code: |
|
|
||||||
pip install coverage
|
|
||||||
|
|
||||||
# Collect static files so the manifest storage knows where to look
|
|
||||||
- script:
|
|
||||||
name: collect static
|
|
||||||
code: |
|
|
||||||
python manage.py collectstatic --noinput
|
|
||||||
|
|
||||||
# Run python tests
|
|
||||||
- script:
|
|
||||||
name: run tests
|
|
||||||
code: |
|
|
||||||
coverage run manage.py test RIGS
|
|
||||||
|
|
||||||
- script:
|
|
||||||
name: collect coverage data
|
|
||||||
code: |
|
|
||||||
coverage report -m --include=PyRIGS/*.*,RIGS/*.* --omit=*/migrations/* | tee coverage.txt
|
|
||||||
coverage html --include=PyRIGS/*.*,RIGS/*.* --omit=*/migrations/*
|
|
||||||
Reference in New Issue
Block a user