mirror of
https://github.com/YunoHost-Apps/linuxdash_ynh.git
synced 2024-09-03 19:36:07 +02:00
commit
ffa6bd20eb
100 changed files with 794 additions and 5095 deletions
55
.github/ISSUE_TEMPLATE.md
vendored
Normal file
55
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: When creating a bug report, please use the following template to provide all the relevant information and help debugging efficiently.
|
||||
|
||||
---
|
||||
|
||||
**How to post a meaningful bug report**
|
||||
1. *Read this whole template first.*
|
||||
2. *Determine if you are on the right place:*
|
||||
- *If you were performing an action on the app from the webadmin or the CLI (install, update, backup, restore, change_url...), you are on the right place!*
|
||||
- *Otherwise, the issue may be due to the app itself. Refer to its documentation or repository for help.*
|
||||
- *When in doubt, post here and we will figure it out together.*
|
||||
3. *Delete the italic comments as you write over them below, and remove this guide.*
|
||||
---
|
||||
|
||||
### Describe the bug
|
||||
|
||||
*A clear and concise description of what the bug is.*
|
||||
|
||||
### Context
|
||||
|
||||
- Hardware: *VPS bought online / Old laptop or computer / Raspberry Pi at home / Internet Cube with VPN / Other ARM board / ...*
|
||||
- YunoHost version: x.x.x
|
||||
- I have access to my server: *Through SSH | through the webadmin | direct access via keyboard / screen | ...*
|
||||
- Are you in a special context or did you perform some particular tweaking on your YunoHost instance?: *no / yes*
|
||||
- If yes, please explain:
|
||||
- Using, or trying to install package version/branch:
|
||||
- If upgrading, current package version: *can be found in the admin, or with `yunohost app info $app_id`*
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
- *If you performed a command from the CLI, the command itself is enough. For example:*
|
||||
```sh
|
||||
sudo yunohost app install the_app
|
||||
```
|
||||
- *If you used the webadmin, please perform the equivalent command from the CLI first.*
|
||||
- *If the error occurs in your browser, explain what you did:*
|
||||
1. *Go to '...'*
|
||||
2. *Click on '...'*
|
||||
3. *Scroll down to '...'*
|
||||
4. *See error*
|
||||
|
||||
### Expected behavior
|
||||
|
||||
*A clear and concise description of what you expected to happen. You can remove this section if the command above is enough to understand your intent.*
|
||||
|
||||
### Logs
|
||||
|
||||
*When an operation fails, YunoHost provides a simple way to share the logs.*
|
||||
- *In the webadmin, the error message contains a link to the relevant log page. On that page, you will be able to 'Share with Yunopaste'. If you missed it, the logs of previous operations are also available under Tools > Logs.*
|
||||
- *In command line, the command to share the logs is displayed at the end of the operation and looks like `yunohost log display [log name] --share`. If you missed it, you can find the log ID of a previous operation using `yunohost log list`.*
|
||||
|
||||
*After sharing the log, please copypaste directly the link provided by YunoHost (to help readability, no need to copypaste the entire content of the log here, just the link is enough...)*
|
||||
|
||||
*If applicable and useful, add screenshots to help explain your problem.*
|
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
## Problem
|
||||
|
||||
- *Description of why you made this PR*
|
||||
|
||||
## Solution
|
||||
|
||||
- *And how do you fix that problem*
|
||||
|
||||
## PR Status
|
||||
|
||||
- [ ] Code finished and ready to be reviewed/tested
|
||||
- [ ] The fix/enhancement were manually tested (if applicable)
|
||||
|
||||
## Automatic tests
|
||||
|
||||
Automatic tests can be triggered on https://ci-apps-dev.yunohost.org/ *after creating the PR*, by commenting "!testme", "!gogogadgetoci" or "By the power of systemd, I invoke The Great App CI to test this Pull Request!". (N.B. : for this to work you need to be a member of the Yunohost-Apps organization)
|
48
README.md
48
README.md
|
@ -1,16 +1,44 @@
|
|||
# Linux-Dash package for YunoHost
|
||||
<!--
|
||||
N.B.: This README was automatically generated by https://github.com/YunoHost/apps/tree/master/tools/README-generator
|
||||
It shall NOT be edited by hand.
|
||||
-->
|
||||
|
||||
# Linux-Dash for YunoHost
|
||||
|
||||
[![Integration level](https://dash.yunohost.org/integration/linuxdash.svg)](https://dash.yunohost.org/appci/app/linuxdash) ![](https://ci-apps.yunohost.org/ci/badges/linuxdash.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/linuxdash.maintain.svg)
|
||||
[![Install Linux-Dash with YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=linuxdash)
|
||||
|
||||
*[Lire ce readme en français.](./README_fr.md)*
|
||||
|
||||
> *This package allows you to install Linux-Dash quickly and simply on a YunoHost server.
|
||||
If you don't have YunoHost, please consult [the guide](https://yunohost.org/#/install) to learn how to install it.*
|
||||
|
||||
## Overview
|
||||
|
||||
Linux-Dash package for YunoHost
|
||||
A beautiful web dashboard for GNU/Linux which display CPU, RAM, memory, network and other usage.
|
||||
|
||||
* [Linux-Dash repository](https://github.com/afaqurk/linux-dash)
|
||||
* [Linux-Dash demo](http://linuxdash.afaqtariq.com/)
|
||||
* [YunoHost website](https://yunohost.org/)
|
||||
|
||||
### Install app
|
||||
```bash
|
||||
sudo yunohost app install https://github.com/M5oul/linuxdash_ynh
|
||||
**Shipped version:** 2.0
|
||||
|
||||
**Demo:** https://afaqurk.github.io/linux-dash/
|
||||
|
||||
## Documentation and resources
|
||||
|
||||
* Official app website: https://github.com/afaqurk/linux-dash
|
||||
* Official admin documentation: https://github.com/afaqurk/linux-dash/wiki
|
||||
* Upstream app code repository: https://github.com/afaqurk/linux-dash
|
||||
* YunoHost documentation for this app: https://yunohost.org/app_linuxdash
|
||||
* Report a bug: https://github.com/YunoHost-Apps/linuxdash_ynh/issues
|
||||
|
||||
## Developer info
|
||||
|
||||
Please send your pull request to the [testing branch](https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing).
|
||||
|
||||
To try the testing branch, please proceed like that.
|
||||
```
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing --debug
|
||||
or
|
||||
sudo yunohost app upgrade linuxdash -u https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
### App state
|
||||
App is `working`.
|
||||
**More info regarding app packaging:** https://yunohost.org/packaging_apps
|
40
README_fr.md
Normal file
40
README_fr.md
Normal file
|
@ -0,0 +1,40 @@
|
|||
# Linux-Dash pour YunoHost
|
||||
|
||||
[![Niveau d'intégration](https://dash.yunohost.org/integration/linuxdash.svg)](https://dash.yunohost.org/appci/app/linuxdash) ![](https://ci-apps.yunohost.org/ci/badges/linuxdash.status.svg) ![](https://ci-apps.yunohost.org/ci/badges/linuxdash.maintain.svg)
|
||||
[![Installer Linux-Dash avec YunoHost](https://install-app.yunohost.org/install-with-yunohost.svg)](https://install-app.yunohost.org/?app=linuxdash)
|
||||
|
||||
*[Read this readme in english.](./README.md)*
|
||||
*[Lire ce readme en français.](./README_fr.md)*
|
||||
|
||||
> *Ce package vous permet d'installer Linux-Dash rapidement et simplement sur un serveur YunoHost.
|
||||
Si vous n'avez pas YunoHost, regardez [ici](https://yunohost.org/#/install) pour savoir comment l'installer et en profiter.*
|
||||
|
||||
## Vue d'ensemble
|
||||
|
||||
A beautiful web dashboard for GNU/Linux which display CPU, RAM, memory, network and other usage.
|
||||
|
||||
|
||||
**Version incluse :** 2.0
|
||||
|
||||
**Démo :** https://afaqurk.github.io/linux-dash/
|
||||
|
||||
## Documentations et ressources
|
||||
|
||||
* Site officiel de l'app : https://github.com/afaqurk/linux-dash
|
||||
* Documentation officielle de l'admin : https://github.com/afaqurk/linux-dash/wiki
|
||||
* Dépôt de code officiel de l'app : https://github.com/afaqurk/linux-dash
|
||||
* Documentation YunoHost pour cette app : https://yunohost.org/app_linuxdash
|
||||
* Signaler un bug : https://github.com/YunoHost-Apps/linuxdash_ynh/issues
|
||||
|
||||
## Informations pour les développeurs
|
||||
|
||||
Merci de faire vos pull request sur la [branche testing](https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing).
|
||||
|
||||
Pour essayer la branche testing, procédez comme suit.
|
||||
```
|
||||
sudo yunohost app install https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing --debug
|
||||
ou
|
||||
sudo yunohost app upgrade linuxdash -u https://github.com/YunoHost-Apps/linuxdash_ynh/tree/testing --debug
|
||||
```
|
||||
|
||||
**Plus d'infos sur le packaging d'applications :** https://yunohost.org/packaging_apps
|
21
check_process
Normal file
21
check_process
Normal file
|
@ -0,0 +1,21 @@
|
|||
;; Test complet
|
||||
; Manifest
|
||||
domain="domain.tld"
|
||||
path="/path"
|
||||
admin="john"
|
||||
; Checks
|
||||
pkg_linter=1
|
||||
setup_sub_dir=1
|
||||
setup_root=1
|
||||
setup_nourl=0
|
||||
setup_private=0
|
||||
setup_public=0
|
||||
upgrade=1
|
||||
#upgrade=1 from_commit=CommitHash
|
||||
backup_restore=1
|
||||
multi_instance=1
|
||||
port_already_use=0
|
||||
change_url=1
|
||||
;;; Options
|
||||
Email=
|
||||
Notification=none
|
7
conf/app.src
Normal file
7
conf/app.src
Normal file
|
@ -0,0 +1,7 @@
|
|||
SOURCE_URL=https://codeload.github.com/afaqurk/linux-dash/tar.gz/186a802ea76e8bfcab7e8e7ebc533b74f80306fc
|
||||
SOURCE_SUM=506ae346f69b2002d4e3494d6aaa92104dbc8e50c8740acb2c49bc592a5939ce
|
||||
SOURCE_SUM_PRG=sha256sum
|
||||
SOURCE_FORMAT=tar.gz
|
||||
SOURCE_IN_SUBDIR=true
|
||||
SOURCE_FILENAME=
|
||||
SOURCE_EXTRACT=true
|
|
@ -1,9 +1,10 @@
|
|||
location YNH_WWW_PATH/ {
|
||||
rewrite ^YNH_WWW_PATH$ YNH_WWW_PATH/ permanent;
|
||||
proxy_pass http://localhost:8081/;
|
||||
proxy_set_header Host $host;
|
||||
proxy_buffering off;
|
||||
#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent;
|
||||
location __PATH__/ {
|
||||
|
||||
proxy_pass http://localhost:__PORT__/;
|
||||
proxy_redirect off;
|
||||
proxy_hide_header Content-Type;
|
||||
|
||||
# Include SSOWAT user panel.
|
||||
include conf.d/yunohost_panel.conf.inc;
|
||||
#include conf.d/yunohost_panel.conf.inc;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
[program:linuxdash]
|
||||
directory=/var/www/linuxdash/
|
||||
command=python python-server.py
|
||||
[program:__APP__]
|
||||
directory=__FINALPATH__/app/server/
|
||||
command=python index.py --port __PORT__
|
||||
autostart=true
|
||||
autorestart=true
|
||||
user=__APP__
|
||||
|
|
0
doc/.gitkeep
Normal file
0
doc/.gitkeep
Normal file
1
doc/DESCRIPTION.md
Normal file
1
doc/DESCRIPTION.md
Normal file
|
@ -0,0 +1 @@
|
|||
A beautiful web dashboard for GNU/Linux which display CPU, RAM, memory, network and other usage.
|
0
doc/DISCLAIMER.md
Normal file
0
doc/DISCLAIMER.md
Normal file
0
doc/screenshots/.gitkeep
Normal file
0
doc/screenshots/.gitkeep
Normal file
|
@ -1,44 +1,47 @@
|
|||
{
|
||||
"name": "Linux-Dash",
|
||||
"id": "linuxdash",
|
||||
"packaging_format": 1,
|
||||
"description": {
|
||||
"en": "A drop-in, low-overhead monitoring web dashboard for GNU/linux machine.",
|
||||
"fr": "Tableau de bord léger pour le monitoring d’un serveur GNU/linux."
|
||||
},
|
||||
"version": "2.0",
|
||||
"url": "https://github.com/afaqurk/linux-dash",
|
||||
"license": "free",
|
||||
"upstream": {
|
||||
"license": "MIT",
|
||||
"website": "https://github.com/afaqurk/linux-dash",
|
||||
"demo": "https://afaqurk.github.io/linux-dash/",
|
||||
"admindoc": "https://github.com/afaqurk/linux-dash/wiki",
|
||||
"code": "https://github.com/afaqurk/linux-dash"
|
||||
},
|
||||
"license": "MIT",
|
||||
"maintainer": {
|
||||
"name": "Moul",
|
||||
"email": "moul@moul.re",
|
||||
"url": "https://moul.re"
|
||||
},
|
||||
"multi_instance": "false",
|
||||
"requirements": {
|
||||
"yunohost": ">= 4.3.0"
|
||||
},
|
||||
"multi_instance": true,
|
||||
"services": [
|
||||
"nginx"
|
||||
],
|
||||
"arguments": {
|
||||
"install" : [
|
||||
"install": [
|
||||
{
|
||||
"name": "domain",
|
||||
"type": "domain",
|
||||
"ask": {
|
||||
"en": "Choose a domain name for Linux-Dash",
|
||||
"fr": "Choisissez un nom de domaine pour Linux-Dash"
|
||||
},
|
||||
"example": "domain.org"
|
||||
"type": "domain"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"type": "path",
|
||||
"ask": {
|
||||
"en": "Choose a path for Linux-Dash",
|
||||
"fr": "Choisissez un chemin pour Linux-Dash"
|
||||
},
|
||||
"example": "/dash",
|
||||
"default": "/dash"
|
||||
},
|
||||
{
|
||||
"name": "user",
|
||||
"name": "admin",
|
||||
"type": "user",
|
||||
"ask": {
|
||||
"en": "Choose the YunoHost user which have access to Linux-Dash",
|
||||
|
|
20
scripts/_common.sh
Normal file
20
scripts/_common.sh
Normal file
|
@ -0,0 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
#=================================================
|
||||
# COMMON VARIABLES
|
||||
#=================================================
|
||||
|
||||
# dependencies used by the app
|
||||
pkg_dependencies="supervisor"
|
||||
|
||||
#=================================================
|
||||
# PERSONAL HELPERS
|
||||
#=================================================
|
||||
|
||||
#=================================================
|
||||
# EXPERIMENTAL HELPERS
|
||||
#=================================================
|
||||
|
||||
#=================================================
|
||||
# FUTURE OFFICIAL HELPERS
|
||||
#=================================================
|
59
scripts/backup
Executable file
59
scripts/backup
Executable file
|
@ -0,0 +1,59 @@
|
|||
#!/bin/bash
|
||||
|
||||
#=================================================
|
||||
# GENERIC START
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts
|
||||
source ../settings/scripts/_common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
#=================================================
|
||||
# MANAGE SCRIPT FAILURE
|
||||
#=================================================
|
||||
|
||||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#=================================================
|
||||
# LOAD SETTINGS
|
||||
#=================================================
|
||||
ynh_print_info --message="Loading installation settings..."
|
||||
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||
domain=$(ynh_app_setting_get --app=$app --key=domain)
|
||||
|
||||
#=================================================
|
||||
# DECLARE DATA AND CONF FILES TO BACKUP
|
||||
#=================================================
|
||||
ynh_print_info --message="Declaring files to be backed up..."
|
||||
|
||||
#=================================================
|
||||
# BACKUP THE APP MAIN DIR
|
||||
#=================================================
|
||||
|
||||
ynh_backup --src_path="$final_path"
|
||||
|
||||
#=================================================
|
||||
# BACKUP THE NGINX CONFIGURATION
|
||||
#=================================================
|
||||
|
||||
ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
|
||||
#=================================================
|
||||
# SPECIFIC BACKUP
|
||||
#=================================================
|
||||
# BACKUP SUPERVISOR
|
||||
#=================================================
|
||||
|
||||
ynh_backup --src_path="/etc/supervisor/conf.d/$app.conf"
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)."
|
113
scripts/change_url
Normal file
113
scripts/change_url
Normal file
|
@ -0,0 +1,113 @@
|
|||
#!/bin/bash
|
||||
|
||||
#=================================================
|
||||
# GENERIC STARTING
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
source _common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
#=================================================
|
||||
# RETRIEVE ARGUMENTS
|
||||
#=================================================
|
||||
|
||||
old_domain=$YNH_APP_OLD_DOMAIN
|
||||
old_path=$YNH_APP_OLD_PATH
|
||||
|
||||
new_domain=$YNH_APP_NEW_DOMAIN
|
||||
new_path=$YNH_APP_NEW_PATH
|
||||
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
#=================================================
|
||||
# LOAD SETTINGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
# Needed for helper "ynh_add_nginx_config"
|
||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||
|
||||
# Add settings here as needed by your application
|
||||
port=$(ynh_app_setting_get --app=$app --key=port)
|
||||
|
||||
#=================================================
|
||||
# BACKUP BEFORE CHANGE URL THEN ACTIVE TRAP
|
||||
#=================================================
|
||||
ynh_script_progression --message="Backing up the app before changing its URL (may take a while)..."
|
||||
|
||||
# Backup the current version of the app
|
||||
ynh_backup_before_upgrade
|
||||
ynh_clean_setup () {
|
||||
ynh_clean_check_starting
|
||||
# Remove the new domain config file, the remove script won't do it as it doesn't know yet its location.
|
||||
ynh_secure_remove --file="/etc/nginx/conf.d/$new_domain.d/$app.conf"
|
||||
|
||||
# Restore it if the upgrade fails
|
||||
ynh_restore_upgradebackup
|
||||
}
|
||||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#=================================================
|
||||
# CHECK WHICH PARTS SHOULD BE CHANGED
|
||||
#=================================================
|
||||
|
||||
change_domain=0
|
||||
if [ "$old_domain" != "$new_domain" ]
|
||||
then
|
||||
change_domain=1
|
||||
fi
|
||||
|
||||
change_path=0
|
||||
if [ "$old_path" != "$new_path" ]
|
||||
then
|
||||
change_path=1
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# STANDARD MODIFICATIONS
|
||||
#=================================================
|
||||
# MODIFY URL IN NGINX CONF
|
||||
#=================================================
|
||||
ynh_script_progression --message="Updating NGINX web server configuration..."
|
||||
|
||||
nginx_conf_path=/etc/nginx/conf.d/$old_domain.d/$app.conf
|
||||
|
||||
# Change the path in the NGINX config file
|
||||
if [ $change_path -eq 1 ]
|
||||
then
|
||||
# Make a backup of the original NGINX config file if modified
|
||||
ynh_backup_if_checksum_is_different --file="$nginx_conf_path"
|
||||
# Set global variables for NGINX helper
|
||||
domain="$old_domain"
|
||||
path_url="$new_path"
|
||||
# Create a dedicated NGINX config
|
||||
ynh_add_nginx_config
|
||||
fi
|
||||
|
||||
# Change the domain for NGINX
|
||||
if [ $change_domain -eq 1 ]
|
||||
then
|
||||
# Delete file checksum for the old conf file location
|
||||
ynh_delete_file_checksum --file="$nginx_conf_path"
|
||||
mv $nginx_conf_path /etc/nginx/conf.d/$new_domain.d/$app.conf
|
||||
# Store file checksum for the new config file location
|
||||
ynh_store_file_checksum --file="/etc/nginx/conf.d/$new_domain.d/$app.conf"
|
||||
fi
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALISATION
|
||||
#=================================================
|
||||
# RELOAD NGINX
|
||||
#=================================================
|
||||
ynh_script_progression --message="Reloading NGINX web server..."
|
||||
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_script_progression --message="Change of URL completed for $app"
|
158
scripts/install
158
scripts/install
|
@ -1,48 +1,134 @@
|
|||
#!/bin/bash
|
||||
|
||||
app=linuxdash
|
||||
#=================================================
|
||||
# GENERIC START
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
# Retrieve arguments
|
||||
domain=$1
|
||||
path=$2
|
||||
user=$3
|
||||
source _common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
# Check domain/path availability
|
||||
sudo yunohost app checkurl $domain$path -a $app
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
#=================================================
|
||||
# MANAGE SCRIPT FAILURE
|
||||
#=================================================
|
||||
|
||||
# Check port availability
|
||||
sudo yunohost app checkport 8081
|
||||
if [[ ! $? -eq 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#=================================================
|
||||
# RETRIEVE ARGUMENTS FROM THE MANIFEST
|
||||
#=================================================
|
||||
|
||||
domain=$YNH_APP_ARG_DOMAIN
|
||||
path_url=$YNH_APP_ARG_PATH
|
||||
admin=$YNH_APP_ARG_ADMIN
|
||||
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
#=================================================
|
||||
# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Validating installation parameters..."
|
||||
|
||||
# Copy files to the right place
|
||||
final_path=/var/www/$app
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -a ../sources/* $final_path
|
||||
test ! -e "$final_path" || ynh_die --message="This path already contains a folder"
|
||||
|
||||
# Set permissions
|
||||
sudo chown -R www-data: $final_path
|
||||
# Register (book) web path
|
||||
ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url
|
||||
|
||||
# Set as a service with supervisor
|
||||
sudo apt-get -y -qq install supervisor
|
||||
sudo cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf
|
||||
sudo supervisorctl update
|
||||
sudo supervisorctl start $app
|
||||
#=================================================
|
||||
# STORE SETTINGS FROM MANIFEST
|
||||
#=================================================
|
||||
ynh_script_progression --message="Storing installation settings..."
|
||||
|
||||
# Modify Nginx configuration file and copy it to Nginx conf directory
|
||||
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
|
||||
nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf
|
||||
sudo cp ../conf/nginx.conf $nginxconf
|
||||
sudo chown root: $nginxconf
|
||||
sudo chmod 600 $nginxconf
|
||||
ynh_app_setting_set --app=$app --key=domain --value=$domain
|
||||
ynh_app_setting_set --app=$app --key=path --value=$path_url
|
||||
ynh_app_setting_set --app=$app --key=admin --value=$admin
|
||||
|
||||
# Only give one user access to this app
|
||||
sudo yunohost app removeaccess $app
|
||||
sudo yunohost app addaccess $app -u $user
|
||||
#=================================================
|
||||
# STANDARD MODIFICATIONS
|
||||
#=================================================
|
||||
# FIND AND OPEN A PORT
|
||||
#=================================================
|
||||
ynh_script_progression --message="Finding an available port..."
|
||||
|
||||
# Reload web server
|
||||
sudo service nginx reload
|
||||
# Find an available port
|
||||
port=$(ynh_find_port --port=8095)
|
||||
ynh_app_setting_set --app=$app --key=port --value=$port
|
||||
|
||||
#=================================================
|
||||
# INSTALL DEPENDENCIES
|
||||
#=================================================
|
||||
ynh_script_progression --message="Installing dependencies..."
|
||||
|
||||
ynh_install_app_dependencies $pkg_dependencies
|
||||
|
||||
#=================================================
|
||||
# CREATE DEDICATED USER
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring system user..."
|
||||
|
||||
# Create a system user
|
||||
ynh_system_user_create --username=$app --home_dir="$final_path"
|
||||
|
||||
#=================================================
|
||||
# DOWNLOAD, CHECK AND UNPACK SOURCE
|
||||
#=================================================
|
||||
ynh_script_progression --message="Setting up source files..."
|
||||
|
||||
ynh_app_setting_set --app=$app --key=final_path --value=$final_path
|
||||
# Download, check integrity, uncompress and patch the source from app.src
|
||||
ynh_setup_source --dest_dir="$final_path"
|
||||
|
||||
chmod 750 "$final_path"
|
||||
chmod -R o-rwx "$final_path"
|
||||
chown -R $app:www-data "$final_path"
|
||||
|
||||
#=================================================
|
||||
# NGINX CONFIGURATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring NGINX web server..."
|
||||
|
||||
# Create a dedicated NGINX config
|
||||
ynh_add_nginx_config
|
||||
|
||||
#=================================================
|
||||
# SPECIFIC SETUP
|
||||
#=================================================
|
||||
# REMOVE GOOGLE !!!
|
||||
#=================================================
|
||||
|
||||
sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html"
|
||||
|
||||
#=================================================
|
||||
# SETUP SUPERVISOR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring supervisor..."
|
||||
|
||||
ynh_add_config --template="../conf/supervisor.conf" --destination="/etc/supervisor/conf.d/$app.conf"
|
||||
supervisorctl update
|
||||
supervisorctl restart $app
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
# SETUP SSOWAT
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring permissions..."
|
||||
|
||||
# Only the admin can access the admin panel of the app (if the app has an admin panel)
|
||||
ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin
|
||||
|
||||
#=================================================
|
||||
# RELOAD NGINX
|
||||
#=================================================
|
||||
ynh_script_progression --message="Reloading NGINX web server..."
|
||||
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_script_progression --message="Installation of $app completed"
|
||||
|
|
|
@ -1,19 +1,72 @@
|
|||
#!/bin/bash
|
||||
|
||||
app=linuxdash
|
||||
domain=$(sudo yunohost app setting $app domain)
|
||||
#=================================================
|
||||
# GENERIC START
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
# Remove sources and nginx configuration
|
||||
sudo rm -rf /var/www/$app
|
||||
sudo rm -f /etc/nginx/conf.d/$domain.d/$app.conf
|
||||
source _common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
# Remove service
|
||||
sudo supervisorctl stop $app
|
||||
sudo rm -f /etc/supervisor/conf.d/$app.conf
|
||||
#=================================================
|
||||
# LOAD SETTINGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
# Remove supervisor package
|
||||
# Need to be manage with future manifest/moulinette Debian package management
|
||||
# sudo apt-get -y -qq remove supervisor
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
# Reload nginx configuration
|
||||
sudo service nginx reload
|
||||
domain=$(ynh_app_setting_get --app=$app --key=domain)
|
||||
port=$(ynh_app_setting_get --app=$app --key=port)
|
||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||
|
||||
#=================================================
|
||||
# STANDARD REMOVE
|
||||
#=================================================
|
||||
# REMOVE SUPERVISOR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing supervisor configuration..."
|
||||
|
||||
supervisorctl stop $app
|
||||
ynh_secure_remove --file="/etc/supervisor/conf.d/$app.conf"
|
||||
supervisorctl update
|
||||
|
||||
#=================================================
|
||||
# REMOVE APP MAIN DIR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing app main directory..."
|
||||
|
||||
# Remove the app directory securely
|
||||
ynh_secure_remove --file="$final_path"
|
||||
|
||||
#=================================================
|
||||
# REMOVE NGINX CONFIGURATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing NGINX web server configuration..."
|
||||
|
||||
# Remove the dedicated NGINX config
|
||||
ynh_remove_nginx_config
|
||||
|
||||
#=================================================
|
||||
# REMOVE DEPENDENCIES
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing dependencies..."
|
||||
|
||||
# Remove metapackage and its dependencies
|
||||
ynh_remove_app_dependencies
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
# REMOVE DEDICATED USER
|
||||
#=================================================
|
||||
ynh_script_progression --message="Removing the dedicated system user..."
|
||||
|
||||
# Delete a system user
|
||||
ynh_system_user_delete --username=$app
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_script_progression --message="Removal of $app completed"
|
||||
|
|
99
scripts/restore
Executable file
99
scripts/restore
Executable file
|
@ -0,0 +1,99 @@
|
|||
#!/bin/bash
|
||||
|
||||
#=================================================
|
||||
# GENERIC START
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts
|
||||
source ../settings/scripts/_common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
#=================================================
|
||||
# MANAGE SCRIPT FAILURE
|
||||
#=================================================
|
||||
|
||||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#=================================================
|
||||
# LOAD SETTINGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
domain=$(ynh_app_setting_get --app=$app --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app=$app --key=path)
|
||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||
|
||||
#=================================================
|
||||
# CHECK IF THE APP CAN BE RESTORED
|
||||
#=================================================
|
||||
ynh_script_progression --message="Validating restoration parameters..."
|
||||
|
||||
test ! -d $final_path \
|
||||
|| ynh_die --message="There is already a directory: $final_path "
|
||||
|
||||
#=================================================
|
||||
# STANDARD RESTORATION STEPS
|
||||
#=================================================
|
||||
# RESTORE THE NGINX CONFIGURATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Restoring the NGINX web server configuration..."
|
||||
|
||||
ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf"
|
||||
|
||||
#=================================================
|
||||
# RECREATE THE DEDICATED USER
|
||||
#=================================================
|
||||
ynh_script_progression --message="Recreating the dedicated system user..."
|
||||
|
||||
# Create the dedicated user (if not existing)
|
||||
ynh_system_user_create --username=$app --home_dir="$final_path"
|
||||
|
||||
#=================================================
|
||||
# RESTORE THE APP MAIN DIR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Restoring the app main directory..."
|
||||
|
||||
ynh_restore_file --origin_path="$final_path"
|
||||
|
||||
chmod 750 "$final_path"
|
||||
chmod -R o-rwx "$final_path"
|
||||
chown -R $app:www-data "$final_path"
|
||||
|
||||
#=================================================
|
||||
# SPECIFIC RESTORATION
|
||||
#=================================================
|
||||
# REINSTALL DEPENDENCIES
|
||||
#=================================================
|
||||
ynh_script_progression --message="Reinstalling dependencies..."
|
||||
|
||||
# Define and install dependencies
|
||||
ynh_install_app_dependencies $pkg_dependencies
|
||||
|
||||
#=================================================
|
||||
# RESTORE SUPERVISOR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Restoring the supervisor configuration..."
|
||||
|
||||
ynh_restore_file --origin_path="/etc/supervisor/conf.d/$app.conf"
|
||||
supervisorctl update
|
||||
supervisorctl restart $app
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
# RELOAD NGINX
|
||||
#=================================================
|
||||
ynh_script_progression --message="Reloading NGINX web server..."
|
||||
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_script_progression --message="Restoration completed for $app"
|
128
scripts/upgrade
128
scripts/upgrade
|
@ -1,30 +1,114 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Retrieve settings
|
||||
app=linuxdash
|
||||
domain=$(sudo yunohost app setting $app domain)
|
||||
path=$(sudo yunohost app setting $app path)
|
||||
#=================================================
|
||||
# GENERIC START
|
||||
#=================================================
|
||||
# IMPORT GENERIC HELPERS
|
||||
#=================================================
|
||||
|
||||
# Remove trailing "/" for next commands
|
||||
path=${path%/}
|
||||
source _common.sh
|
||||
source /usr/share/yunohost/helpers
|
||||
|
||||
# Copy files to the right place
|
||||
final_path=/var/www/$app
|
||||
sudo mkdir -p $final_path
|
||||
sudo cp -a ../sources/* $final_path
|
||||
#=================================================
|
||||
# LOAD SETTINGS
|
||||
#=================================================
|
||||
ynh_script_progression --message="Loading installation settings..."
|
||||
|
||||
# Set permissions
|
||||
sudo chown -R www-data: $final_path
|
||||
app=$YNH_APP_INSTANCE_NAME
|
||||
|
||||
# Modify Nginx configuration file and copy it to Nginx conf directory
|
||||
sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf
|
||||
nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf
|
||||
sudo cp ../conf/nginx.conf $nginxconf
|
||||
sudo chown root: $nginxconf
|
||||
sudo chmod 600 $nginxconf
|
||||
domain=$(ynh_app_setting_get --app=$app --key=domain)
|
||||
path_url=$(ynh_app_setting_get --app=$app --key=path)
|
||||
admin=$(ynh_app_setting_get --app=$app --key=admin)
|
||||
final_path=$(ynh_app_setting_get --app=$app --key=final_path)
|
||||
port=$(ynh_app_setting_get --app=$app --key=port)
|
||||
|
||||
# Restart Linux-dash service
|
||||
sudo supervisorctl restart $app
|
||||
#=================================================
|
||||
# CHECK VERSION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Checking version..."
|
||||
|
||||
# Reload web server & sso
|
||||
sudo service nginx reload
|
||||
upgrade_type=$(ynh_check_app_version_changed)
|
||||
|
||||
#=================================================
|
||||
# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP
|
||||
#=================================================
|
||||
ynh_script_progression --message="Backing up the app before upgrading (may take a while)..."
|
||||
|
||||
# Backup the current version of the app
|
||||
ynh_backup_before_upgrade
|
||||
ynh_clean_setup () {
|
||||
# Restore it if the upgrade fails
|
||||
ynh_restore_upgradebackup
|
||||
}
|
||||
# Exit if an error occurs during the execution of the script
|
||||
ynh_abort_if_errors
|
||||
|
||||
#=================================================
|
||||
# STANDARD UPGRADE STEPS
|
||||
#=================================================
|
||||
# ENSURE DOWNWARD COMPATIBILITY
|
||||
#=================================================
|
||||
ynh_script_progression --message="Ensuring downward compatibility..."
|
||||
#=================================================
|
||||
# CREATE DEDICATED USER
|
||||
#=================================================
|
||||
ynh_script_progression --message="Making sure dedicated system user exists..."
|
||||
|
||||
# Create a dedicated user (if not existing)
|
||||
ynh_system_user_create --username=$app --home_dir="$final_path"
|
||||
|
||||
#=================================================
|
||||
# DOWNLOAD, CHECK AND UNPACK SOURCE
|
||||
#=================================================
|
||||
|
||||
if [ "$upgrade_type" == "UPGRADE_APP" ]
|
||||
then
|
||||
ynh_script_progression --message="Upgrading source files..."
|
||||
|
||||
# Download, check integrity, uncompress and patch the source from app.src
|
||||
ynh_setup_source --dest_dir="$final_path"
|
||||
fi
|
||||
|
||||
chmod 750 "$final_path"
|
||||
chmod -R o-rwx "$final_path"
|
||||
chown -R $app:www-data "$final_path"
|
||||
|
||||
#=================================================
|
||||
# NGINX CONFIGURATION
|
||||
#=================================================
|
||||
ynh_script_progression --message="Upgrading NGINX web server configuration..."
|
||||
|
||||
# Create a dedicated NGINX config
|
||||
ynh_add_nginx_config
|
||||
|
||||
#=================================================
|
||||
# SPECIFIC UPGRADE
|
||||
#=================================================
|
||||
# REMOVE GOOGLE !!!
|
||||
#=================================================
|
||||
|
||||
sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html"
|
||||
|
||||
#=================================================
|
||||
# SETUP SUPERVISOR
|
||||
#=================================================
|
||||
ynh_script_progression --message="Configuring supervisor..."
|
||||
|
||||
ynh_add_config --template="../conf/supervisor.conf" --destination="/etc/supervisor/conf.d/$app.conf"
|
||||
supervisorctl update
|
||||
supervisorctl restart $app
|
||||
|
||||
#=================================================
|
||||
# GENERIC FINALIZATION
|
||||
#=================================================
|
||||
# RELOAD NGINX
|
||||
#=================================================
|
||||
ynh_script_progression --message="Reloading NGINX web server..."
|
||||
|
||||
ynh_systemd_action --service_name=nginx --action=reload
|
||||
|
||||
#=================================================
|
||||
# END OF SCRIPT
|
||||
#=================================================
|
||||
|
||||
ynh_script_progression --message="Upgrade of $app completed"
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
2
sources/.gitignore
vendored
2
sources/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
vendor
|
||||
node_modules
|
|
@ -1,20 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 afaqurk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -1,54 +0,0 @@
|
|||
<br/>
|
||||
<h1 align="center"><i>Linux Dash</i></h1>
|
||||
|
||||
<h6 align="center">
|
||||
<i>A simple, low-overhead web dashboard for Linux</i>
|
||||
</h6>
|
||||
|
||||
<p align="center">
|
||||
<strong>
|
||||
<a href="http://linuxdash.afaqtariq.com"><i>Demo</i></a> |
|
||||
<a href="#features"><i>Features</i></a> |
|
||||
<a href="https://github.com/afaqurk/linux-dash/wiki/Install-Linux-Dash">
|
||||
<i>Installation</i></a> |
|
||||
<a href="#support"><i>Support</i></a>
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://gitter.im/afaqurk/linux-dash">
|
||||
<img
|
||||
src="https://badges.gitter.im/gitterHQ/gitter.png"
|
||||
alt="Linux Dash Gitter chat">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
<p align="center">
|
||||
<a href="http://linuxdash.afaqtariq.com">
|
||||
<img
|
||||
width="80%"
|
||||
alt="Linux Dash screenshot"
|
||||
src="http://i.imgur.com/tehGyrQ.gif">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<br/>
|
||||
|
||||
## Features
|
||||
* A beautiful, simple web-based dashboard for monitoring a linux server
|
||||
* Only ~1MB on disk! *(.git removed)*
|
||||
* Live graphs, refresh-able widgets, and a growing # of supported modules
|
||||
* Drop-in installation for PHP, Node.js, Python, and Go
|
||||
|
||||
## Support
|
||||
|
||||
For help with general setup and configuration issues please use the [Linux Dash Gitter chat room](https://gitter.im/afaqurk/linux-dash).
|
||||
|
||||
The following distributions are supported:
|
||||
* Arch
|
||||
* Debian 6,7
|
||||
* Ubuntu 11.04+
|
||||
* Linux Mint 16+
|
||||
* CentOS 5, 6
|
||||
* openSUSE
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"name": "afaqurk/linux-dash",
|
||||
"description": "A drop-in, low-overhead monitoring web dashboard for a linux machine.",
|
||||
"license": "MIT",
|
||||
"version": "1.2.0",
|
||||
"keywords": ["linux", "dashboard", "linux-dash", "server dashboard"],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Afaq Tariq",
|
||||
"email": "afaq05@gmail.com"
|
||||
}
|
||||
],
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"support": {
|
||||
"issues": "https://github.com/afaqurk/linux-dash/issues?state=open",
|
||||
"forum": "https://gitter.im/afaqurk/linux-dash",
|
||||
"source": "https://github.com/afaqurk/linux-dash"
|
||||
}
|
||||
}
|
6
sources/css/animate.css
vendored
6
sources/css/animate.css
vendored
File diff suppressed because one or more lines are too long
|
@ -1,488 +0,0 @@
|
|||
/***** Template ****/
|
||||
* {
|
||||
font-family: 'Merriweather', Arial, sans-serif;
|
||||
letter-spacing: .1rem;
|
||||
}
|
||||
html {
|
||||
margin-top: 0px;
|
||||
padding-top: 0;
|
||||
border-top: 1px solid #4F8EF7;
|
||||
|
||||
background: url(../img/themes/crossword.png);
|
||||
|
||||
-webkit-transition: all 1s ease;
|
||||
-moz-transition: all 1s ease;
|
||||
-ms-transition: all 1s ease;
|
||||
-o-transition: all 1s ease;
|
||||
transition: all 1s ease;
|
||||
}
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
.title {
|
||||
color: rgb(34, 34, 34);
|
||||
display: block;
|
||||
font-size: 30px;
|
||||
font-weight: 300;
|
||||
height: 32px;
|
||||
letter-spacing: .1rem;
|
||||
line-height: 52.5px;
|
||||
margin-bottom: 20px;
|
||||
margin-top: 0px;
|
||||
text-align: center;
|
||||
}
|
||||
.plugin ::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
}
|
||||
.plugin ::-webkit-scrollbar-button {
|
||||
width: 8px;
|
||||
height:5px;
|
||||
}
|
||||
.plugin ::-webkit-scrollbar-track {
|
||||
background:#eee;
|
||||
border: thin solid lightgray;
|
||||
box-shadow: 0px 0px 3px #dfdfdf inset;
|
||||
border-radius:10px;
|
||||
}
|
||||
.plugin ::-webkit-scrollbar-thumb {
|
||||
background: #999;
|
||||
border: thin solid gray;
|
||||
border-radius:10px;
|
||||
}
|
||||
.plugin ::-webkit-scrollbar-thumb:hover {
|
||||
background:#7d7d7d;
|
||||
}
|
||||
.centered {
|
||||
margin: 0 auto;
|
||||
}
|
||||
.hero {
|
||||
padding: 10px 0 20px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.hero nav-bar {
|
||||
display: block;
|
||||
}
|
||||
.hero nav-bar ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
display: inline;
|
||||
}
|
||||
.hero nav-bar ul li a {
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
letter-spacing: .2rem;
|
||||
margin-right: 35px;
|
||||
text-decoration: none;
|
||||
line-height: 2.3rem;
|
||||
color: #222;
|
||||
}
|
||||
.hero nav-bar ul li.active a,
|
||||
.hero nav-bar ul li a:hover {
|
||||
color: #1EAEDB;
|
||||
}
|
||||
.hero nav-bar ul li {
|
||||
margin-left: 20px;
|
||||
display: inline;
|
||||
}
|
||||
.hero nav-bar ul li a {
|
||||
display: inline;
|
||||
}
|
||||
#theme-switcher {
|
||||
position: fixed;
|
||||
top: 25px;
|
||||
right: -371px;
|
||||
border-radius: 5px 0px 0px 5px;
|
||||
padding: 4px;
|
||||
z-index: 999999;
|
||||
cursor: pointer;
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: #517fa4;
|
||||
|
||||
-webkit-transition: all 0.5s ease;
|
||||
-moz-transition: all 0.5s ease;
|
||||
-ms-transition: all 0.5s ease;
|
||||
-o-transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
#theme-switcher .settings-icon{
|
||||
font-size: 25px;
|
||||
height: 100%;
|
||||
margin-top: 5px;
|
||||
float: left;
|
||||
display: inline-block;
|
||||
}
|
||||
#theme-switcher .settings-icon:hover{
|
||||
color: #243949;
|
||||
}
|
||||
#theme-switcher.open {
|
||||
right: 0;
|
||||
}
|
||||
#theme-switcher .option {
|
||||
margin: 5px;
|
||||
border: 1px solid transparent;
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
color: black;
|
||||
background-color: #ececec;
|
||||
border-radius: 2px;
|
||||
-webkit-transition: all 0.5s ease;
|
||||
-moz-transition: all 0.5s ease;
|
||||
-ms-transition: all 0.5s ease;
|
||||
-o-transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
#theme-switcher .option:hover,
|
||||
#theme-switcher .option.selected {
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,.53),0 3px 10px rgba(0,0,0,.16);
|
||||
background-color: #FFF94C;
|
||||
}
|
||||
#theme-switcher .option.selected:hover {
|
||||
background-color: lightgrey;
|
||||
}
|
||||
@media (min-width: 1080px) {
|
||||
#plugins {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
@media (max-width: 1079px) {
|
||||
#plugins {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
/***** Plugins Container ****/
|
||||
#plugins {
|
||||
padding: 20px;
|
||||
padding-top: 0;
|
||||
margin-top: 0;
|
||||
border: 1px;
|
||||
}
|
||||
|
||||
/***** Plugin ****/
|
||||
.plugin {
|
||||
float: left;
|
||||
padding: 0;
|
||||
background-color: #FFFFFF;
|
||||
color: black;
|
||||
text-align: center;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,.53),0 3px 10px rgba(0,0,0,.16);
|
||||
margin-top: 10px;
|
||||
margin: 0 auto;
|
||||
margin-top: 20px;
|
||||
margin-left: 50px;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.plugin {
|
||||
max-width: 80%;
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.plugin-body {
|
||||
max-height: 400px;
|
||||
}
|
||||
}
|
||||
.plugin .top-bar {
|
||||
height: 25px;
|
||||
max-width: 100%;
|
||||
padding: 20px;
|
||||
letter-spacing: .1rem;
|
||||
line-height: 1.3rem;
|
||||
font-size: 11px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 600;
|
||||
color: #009587;
|
||||
text-align: center;
|
||||
}
|
||||
.plugin .no-padding {
|
||||
padding: 0px;
|
||||
}
|
||||
.plugin-body {
|
||||
height: 400px;
|
||||
font-size: 12px;
|
||||
padding: 10px;
|
||||
line-height: 30px;
|
||||
overflow: auto;
|
||||
border-top: 1px solid #ececec;
|
||||
}
|
||||
.plugin last-update{
|
||||
font-size: 11px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
no-data {
|
||||
font-style: italic;
|
||||
}
|
||||
refresh-btn button {
|
||||
background-color: #009587;
|
||||
border: 0;
|
||||
float: right;
|
||||
font-size: 15px;
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
padding: 5px;
|
||||
|
||||
-webkit-transition: all 0.5s ease;
|
||||
-moz-transition: all 0.5s ease;
|
||||
-ms-transition: all 0.5s ease;
|
||||
-o-transition: all 0.5s ease;
|
||||
transition: all 0.5s ease;
|
||||
|
||||
box-shadow: 0 1px 6px rgba(0,0,0,.12),0 1px 6px rgba(0,0,0,.5);
|
||||
}
|
||||
refresh-btn button:hover {
|
||||
background-color: #ffeb3b;
|
||||
color: black;
|
||||
}
|
||||
refresh-btn button:active {
|
||||
background-color: #0f9d58;
|
||||
}
|
||||
|
||||
/**** Loader ****/
|
||||
.spinner {
|
||||
margin: 100px auto;
|
||||
width: 50px;
|
||||
height: 30px;
|
||||
text-align: center;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.spinner > div {
|
||||
background-color: #009587;
|
||||
height: 100%;
|
||||
width: 6px;
|
||||
display: inline-block;
|
||||
|
||||
-webkit-animation: stretchdelay 1.2s infinite ease-in-out;
|
||||
animation: stretchdelay 1.2s infinite ease-in-out;
|
||||
}
|
||||
|
||||
.spinner .rect2 {
|
||||
-webkit-animation-delay: -1.1s;
|
||||
animation-delay: -1.1s;
|
||||
}
|
||||
|
||||
.spinner .rect3 {
|
||||
-webkit-animation-delay: -1.0s;
|
||||
animation-delay: -1.0s;
|
||||
}
|
||||
|
||||
.spinner .rect4 {
|
||||
-webkit-animation-delay: -0.9s;
|
||||
animation-delay: -0.9s;
|
||||
}
|
||||
|
||||
.spinner .rect5 {
|
||||
-webkit-animation-delay: -0.8s;
|
||||
animation-delay: -0.8s;
|
||||
}
|
||||
|
||||
@-webkit-keyframes stretchdelay {
|
||||
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
|
||||
20% { -webkit-transform: scaleY(1.0) }
|
||||
}
|
||||
|
||||
@keyframes stretchdelay {
|
||||
0%, 40%, 100% {
|
||||
transform: scaleY(0.4);
|
||||
-webkit-transform: scaleY(0.4);
|
||||
} 20% {
|
||||
transform: scaleY(1.0);
|
||||
-webkit-transform: scaleY(1.0);
|
||||
}
|
||||
}
|
||||
|
||||
/**** General Elements ****/
|
||||
table
|
||||
{
|
||||
font-size: 10px;
|
||||
margin: 0;
|
||||
min-width: 400px;
|
||||
border-collapse: collapse;
|
||||
text-align: left;
|
||||
table-layout:fixed;
|
||||
}
|
||||
table th,
|
||||
table td {
|
||||
padding: 5px;
|
||||
max-width: 250px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
table th
|
||||
{
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
}
|
||||
table td {
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
padding: 9px 8px;
|
||||
font-family: Arial, sans-serif;
|
||||
font-size: 11px;
|
||||
letter-spacing: .1em;
|
||||
color: rgba(0,0,0,.65);
|
||||
}
|
||||
table tbody tr:hover td
|
||||
{
|
||||
background-color: #fafafa;
|
||||
}
|
||||
table.metrics-table {
|
||||
text-align: center;
|
||||
}
|
||||
canvas {
|
||||
float: none;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
/*********************************************
|
||||
Widget Elements
|
||||
*********************************************/
|
||||
.progress-bar {
|
||||
background-color: #eec;
|
||||
border-radius: 10px; /* (height of inner div) / 2 + padding */
|
||||
padding: 0px;
|
||||
clear: both;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.progress-bar > div {
|
||||
background-color: #1EAEDB;
|
||||
width: 0%;
|
||||
height: 5px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.table-data-plugin .filter-container {
|
||||
padding-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.table-data-plugin .filter,
|
||||
.table-data-plugin .filter:focus,
|
||||
.table-data-plugin .filter:active {
|
||||
height: 20px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
border: none;
|
||||
outline-color: transparent;
|
||||
background: transparent;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
font-size: 15px;
|
||||
}
|
||||
.table-data-plugin .filter:focus {
|
||||
border-bottom: 1px solid #ff5722;
|
||||
}
|
||||
.table-data-plugin thead tr th a,
|
||||
.table-data-plugin thead tr th a:visited {
|
||||
color: black;
|
||||
text-decoration: none;
|
||||
}
|
||||
.table-data-plugin .column-sort-caret {
|
||||
font-size: 10px;
|
||||
color: #1EAEDB;
|
||||
}
|
||||
/*
|
||||
* Popover
|
||||
* http://codepen.io/derekpcollins/pen/JCLhG/
|
||||
*/
|
||||
|
||||
/* The element to hover over */
|
||||
.qs {
|
||||
cursor: default;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
.qs .popover {
|
||||
text-transform: none;
|
||||
background-color: rgba(0, 0, 0, 0.85);
|
||||
border-radius: 5px;
|
||||
bottom: 42px;
|
||||
box-shadow: 0 0 5px rgba(0, 0, 0, 0.4);
|
||||
color: #fff;
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
font-family: 'Helvetica',sans-serif;
|
||||
padding: 7px 10px;
|
||||
position: absolute;
|
||||
left: -80px;
|
||||
width: 200px;
|
||||
z-index: 4;
|
||||
}
|
||||
.qs .popover:before {
|
||||
border-top: 7px solid rgba(0, 0, 0, 0.85);
|
||||
border-right: 7px solid transparent;
|
||||
border-left: 7px solid transparent;
|
||||
bottom: -7px;
|
||||
content: '';
|
||||
display: block;
|
||||
left: 50%;
|
||||
margin-left: -7px;
|
||||
position: absolute;
|
||||
}
|
||||
.qs:hover .popover {
|
||||
display: block;
|
||||
-webkit-animation: fade-in .3s linear 1, move-up .3s linear 1;
|
||||
-moz-animation: fade-in .3s linear 1, move-up .3s linear 1;
|
||||
-ms-animation: fade-in .3s linear 1, move-up .3s linear 1;
|
||||
}
|
||||
|
||||
@-webkit-keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes move-up {
|
||||
from {
|
||||
bottom: 30px;
|
||||
}
|
||||
to {
|
||||
bottom: 42px;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes move-up {
|
||||
from {
|
||||
bottom: 30px;
|
||||
}
|
||||
to {
|
||||
bottom: 42px;
|
||||
}
|
||||
}
|
||||
@-ms-keyframes move-up {
|
||||
from {
|
||||
bottom: 30px;
|
||||
}
|
||||
to {
|
||||
bottom: 42px;
|
||||
}
|
||||
}
|
|
@ -1,170 +0,0 @@
|
|||
/**************************************
|
||||
Theme: linux-dash beta
|
||||
**************************************/
|
||||
html.old {
|
||||
background: #F9F6F1;
|
||||
}
|
||||
html.old body {
|
||||
margin: 0;
|
||||
}
|
||||
html.old body * {
|
||||
font-family: "Open Sans";
|
||||
letter-spacing: 0;
|
||||
}
|
||||
html.old body .hero {
|
||||
background: #00BA8B;
|
||||
color: #ffffff;
|
||||
padding: 0;
|
||||
}
|
||||
html.old body .hero h4 {
|
||||
color: #ffffff;
|
||||
display: inline-block;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
height: 40px;
|
||||
line-height: 35px;
|
||||
margin: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
html.old body .hero small {
|
||||
letter-spacing: 0.1rem;
|
||||
line-height: 40px;
|
||||
margin-left: 20px;
|
||||
opacity: 0.9;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
html.old body .hero #theme-switcher {
|
||||
right: -315px;
|
||||
}
|
||||
html.old body .hero #theme-switcher.open {
|
||||
right: 0;
|
||||
}
|
||||
html.old body .hero nav-bar {
|
||||
background: #ffffff;
|
||||
border-bottom: 1px solid #d6d6d6;
|
||||
color: #333333;
|
||||
}
|
||||
html.old body .hero nav-bar br {
|
||||
display: none;
|
||||
}
|
||||
html.old body .hero nav-bar ul {
|
||||
display: inline-block;
|
||||
}
|
||||
html.old body .hero nav-bar ul li {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
}
|
||||
html.old body .hero nav-bar ul li:not(:first-child) {
|
||||
border-left: 1px solid #e6e6e6;
|
||||
}
|
||||
html.old body .hero nav-bar ul li a {
|
||||
color: #B2AFAA;
|
||||
display: block;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
line-height: 30px;
|
||||
margin: 0;
|
||||
padding: 0 15px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
html.old body .hero nav-bar ul li:hover a {
|
||||
color: #888888;
|
||||
}
|
||||
html.old body #plugins {
|
||||
display: flex;
|
||||
flex-flow: row wrap;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
html.old body .plugin {
|
||||
border: 1px solid #d5d5d5;
|
||||
border-radius: 0 0 5px 5px;
|
||||
box-shadow: none;
|
||||
margin: 10px;
|
||||
}
|
||||
html.old body .plugin .top-bar {
|
||||
background: transparent linear-gradient(to bottom, #f9f6f1 0%, #f2efea 100%) repeat scroll 0px 0px;
|
||||
border-bottom: 1px solid #d6d6d6;
|
||||
color: #525252;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 0 0 15px;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
text-transform: none;
|
||||
}
|
||||
html.old body .plugin .top-bar last-update {
|
||||
float: right;
|
||||
margin: 0 10px;
|
||||
opacity: 0.8;
|
||||
}
|
||||
html.old body .plugin .top-bar refresh-btn {
|
||||
float: right;
|
||||
}
|
||||
html.old body .plugin .top-bar refresh-btn button {
|
||||
background: #ffffff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.1) inset, 0px 1px 2px rgba(0, 0, 0, 0.1);
|
||||
color: #555555;
|
||||
cursor: pointer;
|
||||
box-shadow: none;
|
||||
display: inline-block;
|
||||
float: none;
|
||||
font-size: 14px;
|
||||
height: auto;
|
||||
margin: 0 -5px 0 10px;
|
||||
padding: 0 4px;
|
||||
width: auto;
|
||||
}
|
||||
html.old body .plugin .top-bar refresh-btn button:hover {
|
||||
background: #e6e6e6;
|
||||
}
|
||||
html.old body .plugin .plugin-body {
|
||||
border: none;
|
||||
height: auto;
|
||||
line-height: normal;
|
||||
max-height: 300px;
|
||||
padding: 0;
|
||||
}
|
||||
html.old body .plugin .plugin-body table {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
font-size: 12px;
|
||||
min-width: 300px;
|
||||
}
|
||||
html.old body .plugin .plugin-body table tr:not(:first-child) th {
|
||||
border-top: 1px solid #dddddd;
|
||||
}
|
||||
html.old body .plugin .plugin-body table td,
|
||||
html.old body .plugin .plugin-body table th {
|
||||
border-bottom: none;
|
||||
padding: 4px 5px;
|
||||
}
|
||||
html.old body .plugin .plugin-body table td:not(:first-child),
|
||||
html.old body .plugin .plugin-body table th:not(:first-child) {
|
||||
border-left: 1px solid #dddddd;
|
||||
}
|
||||
html.old body .plugin .plugin-body table th:not(.filter-container) {
|
||||
background: transparent -moz-linear-gradient(center top, #fafafa 0%, #e9e9e9 100%) repeat scroll 0% 0%;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
html.old body .plugin .plugin-body table th.filter-container .filter {
|
||||
border-bottom: none;
|
||||
font-size: 12px;
|
||||
height: auto;
|
||||
padding: 2px;
|
||||
}
|
||||
html.old body .plugin .plugin-body table th.filter-container .filter::before {
|
||||
content: 'Search >';
|
||||
opacity: 0.5;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
html.old body .plugin .plugin-body table td {
|
||||
border-top: 1px solid #dddddd;
|
||||
}
|
||||
html.old body .plugin canvas {
|
||||
width: 100%;
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
@import "theme-old.css";
|
||||
|
||||
/**************************************
|
||||
Theme: Winter
|
||||
**************************************/
|
||||
|
||||
html.winter {
|
||||
background: url(../img/themes/contemporary_china_2.png) ;
|
||||
}
|
||||
html.winter .hero nav-bar ul li.active a,
|
||||
html.winter .hero nav-bar ul li a:hover {
|
||||
color: #23568f;
|
||||
}
|
||||
html.winter .plugin {
|
||||
background-color: rgba(255, 255, 255, 0.60);
|
||||
}
|
||||
html.winter .plugin .top-bar {
|
||||
color: #012e40;
|
||||
}
|
||||
html.winter .plugin refresh-btn button {
|
||||
background-color: #4c6c73;
|
||||
}
|
||||
table th {
|
||||
color: #012e40;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
Theme: Summer
|
||||
**************************************/
|
||||
|
||||
html.summer {
|
||||
clear: both;
|
||||
background: url(../img/themes/congruent_pentagon.png);
|
||||
}
|
||||
html.summer .hero nav-bar ul li.active a,
|
||||
html.summer .hero nav-bar ul li a:hover {
|
||||
color: #D84315;
|
||||
}
|
||||
html.summer .plugin{
|
||||
background-color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
html.summer .plugin .top-bar {
|
||||
color: #BF360C;
|
||||
}
|
||||
html.summer .plugin refresh-btn button {
|
||||
background-color: #BF360C;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
Theme: Spring
|
||||
**************************************/
|
||||
|
||||
html.spring {
|
||||
clear: both;
|
||||
background: url(../img/themes/food.png);
|
||||
}
|
||||
html.spring .hero nav-bar ul li.active a,
|
||||
html.spring .hero nav-bar ul li a:hover {
|
||||
color: #E65100;
|
||||
}
|
||||
html.spring .plugin {
|
||||
background-color: rgba(255,255,255,0.95);
|
||||
}
|
||||
html.spring .plugin .top-bar {
|
||||
color: #FF6D00;
|
||||
}
|
||||
html.spring .plugin refresh-btn button {
|
||||
background-color: #E65100;
|
||||
}
|
||||
|
||||
/**************************************
|
||||
Theme: Fall
|
||||
**************************************/
|
||||
|
||||
html.fall {
|
||||
background: url(../img/themes/skulls.png);
|
||||
}
|
||||
html.fall .plugin {
|
||||
background: url(../img/themes/crossword.png);
|
||||
}
|
||||
html.fall .hero nav-bar ul li.active a,
|
||||
html.fall .hero nav-bar ul li a:hover,
|
||||
html.fall .plugin .top-bar {
|
||||
color: #F09819;
|
||||
}
|
||||
html.fall .plugin refresh-btn button {
|
||||
background-color: #FF512F;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="linuxDash">
|
||||
<head>
|
||||
<title>linux-dash : Server Monitoring Web Dashboard</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Monitor your Linux server through a simple web dashboard. Open source and free!">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link href='http://fonts.googleapis.com/css?family=Merriweather:300italic,300|Open+Sans:400,600' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/themes.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/animate.css">
|
||||
|
||||
<!-- Angular Libs -->
|
||||
<script src="js/angular.min.js" type="text/javascript"></script>
|
||||
<script src="js/angular-route.js" type="text/javascript"></script>
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body ng-controller="body">
|
||||
|
||||
<a href="https://github.com/afaqurk/linux-dash">
|
||||
<img
|
||||
style="position: absolute; top: 0; left: 0; border: 0; z-index:10;"
|
||||
src="https://camo.githubusercontent.com/567c3a48d796e2fc06ea80409cc9dd82bf714434/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f6c6566745f6461726b626c75655f3132313632312e706e67"
|
||||
alt="Fork me on GitHub"
|
||||
data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_left_darkblue_121621.png">
|
||||
</a>
|
||||
|
||||
<div class="hero">
|
||||
<h4 class="title">Linux Dash</h4>
|
||||
|
||||
<small>A simple linux dashboard</small>
|
||||
|
||||
<theme-switcher></theme-switcher>
|
||||
|
||||
<nav-bar></nav-bar>
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-if="!serverSet">
|
||||
<h2>Setting server...</h2>
|
||||
<loader></loader>
|
||||
</div>
|
||||
|
||||
<!-- Templates Get Rendered Here -->
|
||||
<div ng-if="serverSet" id="plugins" class="animated fadeInDown" ng-view></div>
|
||||
|
||||
<!-- Javascript-->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="js/linuxDash.js" type="text/javascript"></script>
|
||||
<script src="js/modules.js" type="text/javascript"></script>
|
||||
<script src="js/smoothie.min.js" type="text/javascript"></script>
|
||||
<script async src="//www.google-analytics.com/analytics.js"></script>
|
||||
<script type="text/javascript">
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-44168418-2', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Binary file not shown.
Before Width: | Height: | Size: 97 KiB |
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 43 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 65 KiB |
|
@ -1,45 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" ng-app="linuxDash">
|
||||
<head>
|
||||
<title>linux-dash : Server Monitoring Web Dashboard</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="Monitor your Linux server through a simple web dashboard. Open source and free!">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="icon" href="favicon.ico" type="image/x-icon">
|
||||
<link href='//fonts.googleapis.com/css?family=Merriweather:300italic,300|Open+Sans:400,600' rel='stylesheet' type='text/css'>
|
||||
<link rel="stylesheet" type="text/css" href="css/main.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/themes.css">
|
||||
<link rel="stylesheet" type="text/css" href="css/animate.css">
|
||||
|
||||
<!-- Angular Libs -->
|
||||
<script src="js/angular.min.js" type="text/javascript"></script>
|
||||
<script src="js/angular-route.js" type="text/javascript"></script>
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="https://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="hero">
|
||||
<h4 class="title">Linux Dash</h4>
|
||||
<small>A simple linux dashboard</small>
|
||||
<theme-switcher></theme-switcher>
|
||||
<nav-bar></nav-bar>
|
||||
</div>
|
||||
|
||||
<!-- Templates Get Rendered Here -->
|
||||
<div
|
||||
id="plugins"
|
||||
class="animated fadeInDown"
|
||||
ng-view>
|
||||
</div>
|
||||
|
||||
<!-- Javascript-->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="js/linuxDash.js" type="text/javascript"></script>
|
||||
<script src="js/modules.js" type="text/javascript"></script>
|
||||
<script src="js/smoothie.min.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
996
sources/js/angular-route.js
vendored
996
sources/js/angular-route.js
vendored
|
@ -1,996 +0,0 @@
|
|||
/**
|
||||
* @license AngularJS v1.3.4
|
||||
* (c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
* License: MIT
|
||||
*/
|
||||
(function(window, angular, undefined) {'use strict';
|
||||
|
||||
/**
|
||||
* @ngdoc module
|
||||
* @name ngRoute
|
||||
* @description
|
||||
*
|
||||
* # ngRoute
|
||||
*
|
||||
* The `ngRoute` module provides routing and deeplinking services and directives for angular apps.
|
||||
*
|
||||
* ## Example
|
||||
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
|
||||
*
|
||||
*
|
||||
* <div doc-module-components="ngRoute"></div>
|
||||
*/
|
||||
/* global -ngRouteModule */
|
||||
var ngRouteModule = angular.module('ngRoute', ['ng']).
|
||||
provider('$route', $RouteProvider),
|
||||
$routeMinErr = angular.$$minErr('ngRoute');
|
||||
|
||||
/**
|
||||
* @ngdoc provider
|
||||
* @name $routeProvider
|
||||
*
|
||||
* @description
|
||||
*
|
||||
* Used for configuring routes.
|
||||
*
|
||||
* ## Example
|
||||
* See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`.
|
||||
*
|
||||
* ## Dependencies
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*/
|
||||
function $RouteProvider() {
|
||||
function inherit(parent, extra) {
|
||||
return angular.extend(Object.create(parent), extra);
|
||||
}
|
||||
|
||||
var routes = {};
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $routeProvider#when
|
||||
*
|
||||
* @param {string} path Route path (matched against `$location.path`). If `$location.path`
|
||||
* contains redundant trailing slash or is missing one, the route will still match and the
|
||||
* `$location.path` will be updated to add or drop the trailing slash to exactly match the
|
||||
* route definition.
|
||||
*
|
||||
* * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up
|
||||
* to the next slash are matched and stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain named groups starting with a colon and ending with a star:
|
||||
* e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name`
|
||||
* when the route matches.
|
||||
* * `path` can contain optional named groups with a question mark: e.g.`:name?`.
|
||||
*
|
||||
* For example, routes like `/color/:color/largecode/:largecode*\/edit` will match
|
||||
* `/color/brown/largecode/code/with/slashes/edit` and extract:
|
||||
*
|
||||
* * `color: brown`
|
||||
* * `largecode: code/with/slashes`.
|
||||
*
|
||||
*
|
||||
* @param {Object} route Mapping information to be assigned to `$route.current` on route
|
||||
* match.
|
||||
*
|
||||
* Object properties:
|
||||
*
|
||||
* - `controller` – `{(string|function()=}` – Controller fn that should be associated with
|
||||
* newly created scope or the name of a {@link angular.Module#controller registered
|
||||
* controller} if passed as a string.
|
||||
* - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be
|
||||
* published to scope under the `controllerAs` name.
|
||||
* - `template` – `{string=|function()=}` – html template as a string or a function that
|
||||
* returns an html template as a string which should be used by {@link
|
||||
* ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives.
|
||||
* This property takes precedence over `templateUrl`.
|
||||
*
|
||||
* If `template` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Array.<Object>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route
|
||||
*
|
||||
* - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html
|
||||
* template that should be used by {@link ngRoute.directive:ngView ngView}.
|
||||
*
|
||||
* If `templateUrl` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Array.<Object>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route
|
||||
*
|
||||
* - `resolve` - `{Object.<string, function>=}` - An optional map of dependencies which should
|
||||
* be injected into the controller. If any of these dependencies are promises, the router
|
||||
* will wait for them all to be resolved or one to be rejected before the controller is
|
||||
* instantiated.
|
||||
* If all the promises are resolved successfully, the values of the resolved promises are
|
||||
* injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is
|
||||
* fired. If any of the promises are rejected the
|
||||
* {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object
|
||||
* is:
|
||||
*
|
||||
* - `key` – `{string}`: a name of a dependency to be injected into the controller.
|
||||
* - `factory` - `{string|function}`: If `string` then it is an alias for a service.
|
||||
* Otherwise if function, then it is {@link auto.$injector#invoke injected}
|
||||
* and the return value is treated as the dependency. If the result is a promise, it is
|
||||
* resolved before its value is injected into the controller. Be aware that
|
||||
* `ngRoute.$routeParams` will still refer to the previous route within these resolve
|
||||
* functions. Use `$route.current.params` to access the new route parameters, instead.
|
||||
*
|
||||
* - `redirectTo` – {(string|function())=} – value to update
|
||||
* {@link ng.$location $location} path with and trigger route redirection.
|
||||
*
|
||||
* If `redirectTo` is a function, it will be called with the following parameters:
|
||||
*
|
||||
* - `{Object.<string>}` - route parameters extracted from the current
|
||||
* `$location.path()` by applying the current route templateUrl.
|
||||
* - `{string}` - current `$location.path()`
|
||||
* - `{Object}` - current `$location.search()`
|
||||
*
|
||||
* The custom `redirectTo` function is expected to return a string which will be used
|
||||
* to update `$location.path()` and `$location.search()`.
|
||||
*
|
||||
* - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()`
|
||||
* or `$location.hash()` changes.
|
||||
*
|
||||
* If the option is set to `false` and url in the browser changes, then
|
||||
* `$routeUpdate` event is broadcasted on the root scope.
|
||||
*
|
||||
* - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive
|
||||
*
|
||||
* If the option is set to `true`, then the particular route can be matched without being
|
||||
* case sensitive
|
||||
*
|
||||
* @returns {Object} self
|
||||
*
|
||||
* @description
|
||||
* Adds a new route definition to the `$route` service.
|
||||
*/
|
||||
this.when = function(path, route) {
|
||||
//copy original route object to preserve params inherited from proto chain
|
||||
var routeCopy = angular.copy(route);
|
||||
if (angular.isUndefined(routeCopy.reloadOnSearch)) {
|
||||
routeCopy.reloadOnSearch = true;
|
||||
}
|
||||
if (angular.isUndefined(routeCopy.caseInsensitiveMatch)) {
|
||||
routeCopy.caseInsensitiveMatch = this.caseInsensitiveMatch;
|
||||
}
|
||||
routes[path] = angular.extend(
|
||||
routeCopy,
|
||||
path && pathRegExp(path, routeCopy)
|
||||
);
|
||||
|
||||
// create redirection for trailing slashes
|
||||
if (path) {
|
||||
var redirectPath = (path[path.length - 1] == '/')
|
||||
? path.substr(0, path.length - 1)
|
||||
: path + '/';
|
||||
|
||||
routes[redirectPath] = angular.extend(
|
||||
{redirectTo: path},
|
||||
pathRegExp(redirectPath, routeCopy)
|
||||
);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @ngdoc property
|
||||
* @name $routeProvider#caseInsensitiveMatch
|
||||
* @description
|
||||
*
|
||||
* A boolean property indicating if routes defined
|
||||
* using this provider should be matched using a case sensitive
|
||||
* algorithm. Defaults to `false`.
|
||||
*/
|
||||
this.caseInsensitiveMatch = false;
|
||||
|
||||
/**
|
||||
* @param path {string} path
|
||||
* @param opts {Object} options
|
||||
* @return {?Object}
|
||||
*
|
||||
* @description
|
||||
* Normalizes the given path, returning a regular expression
|
||||
* and the original path.
|
||||
*
|
||||
* Inspired by pathRexp in visionmedia/express/lib/utils.js.
|
||||
*/
|
||||
function pathRegExp(path, opts) {
|
||||
var insensitive = opts.caseInsensitiveMatch,
|
||||
ret = {
|
||||
originalPath: path,
|
||||
regexp: path
|
||||
},
|
||||
keys = ret.keys = [];
|
||||
|
||||
path = path
|
||||
.replace(/([().])/g, '\\$1')
|
||||
.replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option) {
|
||||
var optional = option === '?' ? option : null;
|
||||
var star = option === '*' ? option : null;
|
||||
keys.push({ name: key, optional: !!optional });
|
||||
slash = slash || '';
|
||||
return ''
|
||||
+ (optional ? '' : slash)
|
||||
+ '(?:'
|
||||
+ (optional ? slash : '')
|
||||
+ (star && '(.+?)' || '([^/]+)')
|
||||
+ (optional || '')
|
||||
+ ')'
|
||||
+ (optional || '');
|
||||
})
|
||||
.replace(/([\/$\*])/g, '\\$1');
|
||||
|
||||
ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : '');
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $routeProvider#otherwise
|
||||
*
|
||||
* @description
|
||||
* Sets route definition that will be used on route change when no other route definition
|
||||
* is matched.
|
||||
*
|
||||
* @param {Object|string} params Mapping information to be assigned to `$route.current`.
|
||||
* If called with a string, the value maps to `redirectTo`.
|
||||
* @returns {Object} self
|
||||
*/
|
||||
this.otherwise = function(params) {
|
||||
if (typeof params === 'string') {
|
||||
params = {redirectTo: params};
|
||||
}
|
||||
this.when(null, params);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
this.$get = ['$rootScope',
|
||||
'$location',
|
||||
'$routeParams',
|
||||
'$q',
|
||||
'$injector',
|
||||
'$templateRequest',
|
||||
'$sce',
|
||||
function($rootScope, $location, $routeParams, $q, $injector, $templateRequest, $sce) {
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $route
|
||||
* @requires $location
|
||||
* @requires $routeParams
|
||||
*
|
||||
* @property {Object} current Reference to the current route definition.
|
||||
* The route definition contains:
|
||||
*
|
||||
* - `controller`: The controller constructor as define in route definition.
|
||||
* - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for
|
||||
* controller instantiation. The `locals` contain
|
||||
* the resolved values of the `resolve` map. Additionally the `locals` also contain:
|
||||
*
|
||||
* - `$scope` - The current route scope.
|
||||
* - `$template` - The current route template HTML.
|
||||
*
|
||||
* @property {Object} routes Object with all route configuration Objects as its properties.
|
||||
*
|
||||
* @description
|
||||
* `$route` is used for deep-linking URLs to controllers and views (HTML partials).
|
||||
* It watches `$location.url()` and tries to map the path to an existing route definition.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API.
|
||||
*
|
||||
* The `$route` service is typically used in conjunction with the
|
||||
* {@link ngRoute.directive:ngView `ngView`} directive and the
|
||||
* {@link ngRoute.$routeParams `$routeParams`} service.
|
||||
*
|
||||
* @example
|
||||
* This example shows how changing the URL hash causes the `$route` to match a route against the
|
||||
* URL, and the `ngView` pulls in the partial.
|
||||
*
|
||||
* <example name="$route-service" module="ngRouteExample"
|
||||
* deps="angular-route.js" fixBase="true">
|
||||
* <file name="index.html">
|
||||
* <div ng-controller="MainController">
|
||||
* Choose:
|
||||
* <a href="Book/Moby">Moby</a> |
|
||||
* <a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
* <a href="Book/Gatsby">Gatsby</a> |
|
||||
* <a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
|
||||
* <a href="Book/Scarlet">Scarlet Letter</a><br/>
|
||||
*
|
||||
* <div ng-view></div>
|
||||
*
|
||||
* <hr />
|
||||
*
|
||||
* <pre>$location.path() = {{$location.path()}}</pre>
|
||||
* <pre>$route.current.templateUrl = {{$route.current.templateUrl}}</pre>
|
||||
* <pre>$route.current.params = {{$route.current.params}}</pre>
|
||||
* <pre>$route.current.scope.name = {{$route.current.scope.name}}</pre>
|
||||
* <pre>$routeParams = {{$routeParams}}</pre>
|
||||
* </div>
|
||||
* </file>
|
||||
*
|
||||
* <file name="book.html">
|
||||
* controller: {{name}}<br />
|
||||
* Book Id: {{params.bookId}}<br />
|
||||
* </file>
|
||||
*
|
||||
* <file name="chapter.html">
|
||||
* controller: {{name}}<br />
|
||||
* Book Id: {{params.bookId}}<br />
|
||||
* Chapter Id: {{params.chapterId}}
|
||||
* </file>
|
||||
*
|
||||
* <file name="script.js">
|
||||
* angular.module('ngRouteExample', ['ngRoute'])
|
||||
*
|
||||
* .controller('MainController', function($scope, $route, $routeParams, $location) {
|
||||
* $scope.$route = $route;
|
||||
* $scope.$location = $location;
|
||||
* $scope.$routeParams = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .controller('BookController', function($scope, $routeParams) {
|
||||
* $scope.name = "BookController";
|
||||
* $scope.params = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .controller('ChapterController', function($scope, $routeParams) {
|
||||
* $scope.name = "ChapterController";
|
||||
* $scope.params = $routeParams;
|
||||
* })
|
||||
*
|
||||
* .config(function($routeProvider, $locationProvider) {
|
||||
* $routeProvider
|
||||
* .when('/Book/:bookId', {
|
||||
* templateUrl: 'book.html',
|
||||
* controller: 'BookController',
|
||||
* resolve: {
|
||||
* // I will cause a 1 second delay
|
||||
* delay: function($q, $timeout) {
|
||||
* var delay = $q.defer();
|
||||
* $timeout(delay.resolve, 1000);
|
||||
* return delay.promise;
|
||||
* }
|
||||
* }
|
||||
* })
|
||||
* .when('/Book/:bookId/ch/:chapterId', {
|
||||
* templateUrl: 'chapter.html',
|
||||
* controller: 'ChapterController'
|
||||
* });
|
||||
*
|
||||
* // configure html5 to get links working on jsfiddle
|
||||
* $locationProvider.html5Mode(true);
|
||||
* });
|
||||
*
|
||||
* </file>
|
||||
*
|
||||
* <file name="protractor.js" type="protractor">
|
||||
* it('should load and compile correct template', function() {
|
||||
* element(by.linkText('Moby: Ch1')).click();
|
||||
* var content = element(by.css('[ng-view]')).getText();
|
||||
* expect(content).toMatch(/controller\: ChapterController/);
|
||||
* expect(content).toMatch(/Book Id\: Moby/);
|
||||
* expect(content).toMatch(/Chapter Id\: 1/);
|
||||
*
|
||||
* element(by.partialLinkText('Scarlet')).click();
|
||||
*
|
||||
* content = element(by.css('[ng-view]')).getText();
|
||||
* expect(content).toMatch(/controller\: BookController/);
|
||||
* expect(content).toMatch(/Book Id\: Scarlet/);
|
||||
* });
|
||||
* </file>
|
||||
* </example>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeStart
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted before a route change. At this point the route services starts
|
||||
* resolving all of the dependencies needed for the route change to occur.
|
||||
* Typically this involves fetching the view template as well as any dependencies
|
||||
* defined in `resolve` route property. Once all of the dependencies are resolved
|
||||
* `$routeChangeSuccess` is fired.
|
||||
*
|
||||
* The route change (and the `$location` change that triggered it) can be prevented
|
||||
* by calling `preventDefault` method of the event. See {@link ng.$rootScope.Scope#$on}
|
||||
* for more details about event object.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object.
|
||||
* @param {Route} next Future route information.
|
||||
* @param {Route} current Current route information.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeSuccess
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted after a route dependencies are resolved.
|
||||
* {@link ngRoute.directive:ngView ngView} listens for the directive
|
||||
* to instantiate the controller and render the view.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object.
|
||||
* @param {Route} current Current route information.
|
||||
* @param {Route|Undefined} previous Previous route information, or undefined if current is
|
||||
* first route entered.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeChangeError
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
* Broadcasted if any of the resolve promises are rejected.
|
||||
*
|
||||
* @param {Object} angularEvent Synthetic event object
|
||||
* @param {Route} current Current route information.
|
||||
* @param {Route} previous Previous route information.
|
||||
* @param {Route} rejection Rejection of the promise. Usually the error of the failed promise.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name $route#$routeUpdate
|
||||
* @eventType broadcast on root scope
|
||||
* @description
|
||||
*
|
||||
* The `reloadOnSearch` property has been set to false, and we are reusing the same
|
||||
* instance of the Controller.
|
||||
*/
|
||||
|
||||
var forceReload = false,
|
||||
preparedRoute,
|
||||
preparedRouteIsUpdateOnly,
|
||||
$route = {
|
||||
routes: routes,
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $route#reload
|
||||
*
|
||||
* @description
|
||||
* Causes `$route` service to reload the current route even if
|
||||
* {@link ng.$location $location} hasn't changed.
|
||||
*
|
||||
* As a result of that, {@link ngRoute.directive:ngView ngView}
|
||||
* creates new scope and reinstantiates the controller.
|
||||
*/
|
||||
reload: function() {
|
||||
forceReload = true;
|
||||
$rootScope.$evalAsync(function() {
|
||||
// Don't support cancellation of a reload for now...
|
||||
prepareRoute();
|
||||
commitRoute();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc method
|
||||
* @name $route#updateParams
|
||||
*
|
||||
* @description
|
||||
* Causes `$route` service to update the current URL, replacing
|
||||
* current route parameters with those specified in `newParams`.
|
||||
* Provided property names that match the route's path segment
|
||||
* definitions will be interpolated into the location's path, while
|
||||
* remaining properties will be treated as query params.
|
||||
*
|
||||
* @param {Object} newParams mapping of URL parameter names to values
|
||||
*/
|
||||
updateParams: function(newParams) {
|
||||
if (this.current && this.current.$$route) {
|
||||
var searchParams = {}, self=this;
|
||||
|
||||
angular.forEach(Object.keys(newParams), function(key) {
|
||||
if (!self.current.pathParams[key]) searchParams[key] = newParams[key];
|
||||
});
|
||||
|
||||
newParams = angular.extend({}, this.current.params, newParams);
|
||||
$location.path(interpolate(this.current.$$route.originalPath, newParams));
|
||||
$location.search(angular.extend({}, $location.search(), searchParams));
|
||||
}
|
||||
else {
|
||||
throw $routeMinErr('norout', 'Tried updating route when with no current route');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$rootScope.$on('$locationChangeStart', prepareRoute);
|
||||
$rootScope.$on('$locationChangeSuccess', commitRoute);
|
||||
|
||||
return $route;
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param on {string} current url
|
||||
* @param route {Object} route regexp to match the url against
|
||||
* @return {?Object}
|
||||
*
|
||||
* @description
|
||||
* Check if the route matches the current url.
|
||||
*
|
||||
* Inspired by match in
|
||||
* visionmedia/express/lib/router/router.js.
|
||||
*/
|
||||
function switchRouteMatcher(on, route) {
|
||||
var keys = route.keys,
|
||||
params = {};
|
||||
|
||||
if (!route.regexp) return null;
|
||||
|
||||
var m = route.regexp.exec(on);
|
||||
if (!m) return null;
|
||||
|
||||
for (var i = 1, len = m.length; i < len; ++i) {
|
||||
var key = keys[i - 1];
|
||||
|
||||
var val = m[i];
|
||||
|
||||
if (key && val) {
|
||||
params[key.name] = val;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
function prepareRoute($locationEvent) {
|
||||
var lastRoute = $route.current;
|
||||
|
||||
preparedRoute = parseRoute();
|
||||
preparedRouteIsUpdateOnly = preparedRoute && lastRoute && preparedRoute.$$route === lastRoute.$$route
|
||||
&& angular.equals(preparedRoute.pathParams, lastRoute.pathParams)
|
||||
&& !preparedRoute.reloadOnSearch && !forceReload;
|
||||
|
||||
if (!preparedRouteIsUpdateOnly && (lastRoute || preparedRoute)) {
|
||||
if ($rootScope.$broadcast('$routeChangeStart', preparedRoute, lastRoute).defaultPrevented) {
|
||||
if ($locationEvent) {
|
||||
$locationEvent.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function commitRoute() {
|
||||
var lastRoute = $route.current;
|
||||
var nextRoute = preparedRoute;
|
||||
|
||||
if (preparedRouteIsUpdateOnly) {
|
||||
lastRoute.params = nextRoute.params;
|
||||
angular.copy(lastRoute.params, $routeParams);
|
||||
$rootScope.$broadcast('$routeUpdate', lastRoute);
|
||||
} else if (nextRoute || lastRoute) {
|
||||
forceReload = false;
|
||||
$route.current = nextRoute;
|
||||
if (nextRoute) {
|
||||
if (nextRoute.redirectTo) {
|
||||
if (angular.isString(nextRoute.redirectTo)) {
|
||||
$location.path(interpolate(nextRoute.redirectTo, nextRoute.params)).search(nextRoute.params)
|
||||
.replace();
|
||||
} else {
|
||||
$location.url(nextRoute.redirectTo(nextRoute.pathParams, $location.path(), $location.search()))
|
||||
.replace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$q.when(nextRoute).
|
||||
then(function() {
|
||||
if (nextRoute) {
|
||||
var locals = angular.extend({}, nextRoute.resolve),
|
||||
template, templateUrl;
|
||||
|
||||
angular.forEach(locals, function(value, key) {
|
||||
locals[key] = angular.isString(value) ?
|
||||
$injector.get(value) : $injector.invoke(value, null, null, key);
|
||||
});
|
||||
|
||||
if (angular.isDefined(template = nextRoute.template)) {
|
||||
if (angular.isFunction(template)) {
|
||||
template = template(nextRoute.params);
|
||||
}
|
||||
} else if (angular.isDefined(templateUrl = nextRoute.templateUrl)) {
|
||||
if (angular.isFunction(templateUrl)) {
|
||||
templateUrl = templateUrl(nextRoute.params);
|
||||
}
|
||||
templateUrl = $sce.getTrustedResourceUrl(templateUrl);
|
||||
if (angular.isDefined(templateUrl)) {
|
||||
nextRoute.loadedTemplateUrl = templateUrl;
|
||||
template = $templateRequest(templateUrl);
|
||||
}
|
||||
}
|
||||
if (angular.isDefined(template)) {
|
||||
locals['$template'] = template;
|
||||
}
|
||||
return $q.all(locals);
|
||||
}
|
||||
}).
|
||||
// after route change
|
||||
then(function(locals) {
|
||||
if (nextRoute == $route.current) {
|
||||
if (nextRoute) {
|
||||
nextRoute.locals = locals;
|
||||
angular.copy(nextRoute.params, $routeParams);
|
||||
}
|
||||
$rootScope.$broadcast('$routeChangeSuccess', nextRoute, lastRoute);
|
||||
}
|
||||
}, function(error) {
|
||||
if (nextRoute == $route.current) {
|
||||
$rootScope.$broadcast('$routeChangeError', nextRoute, lastRoute, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @returns {Object} the current active route, by matching it against the URL
|
||||
*/
|
||||
function parseRoute() {
|
||||
// Match a route
|
||||
var params, match;
|
||||
angular.forEach(routes, function(route, path) {
|
||||
if (!match && (params = switchRouteMatcher($location.path(), route))) {
|
||||
match = inherit(route, {
|
||||
params: angular.extend({}, $location.search(), params),
|
||||
pathParams: params});
|
||||
match.$$route = route;
|
||||
}
|
||||
});
|
||||
// No route matched; fallback to "otherwise" route
|
||||
return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} interpolation of the redirect path with the parameters
|
||||
*/
|
||||
function interpolate(string, params) {
|
||||
var result = [];
|
||||
angular.forEach((string || '').split(':'), function(segment, i) {
|
||||
if (i === 0) {
|
||||
result.push(segment);
|
||||
} else {
|
||||
var segmentMatch = segment.match(/(\w+)(?:[?*])?(.*)/);
|
||||
var key = segmentMatch[1];
|
||||
result.push(params[key]);
|
||||
result.push(segmentMatch[2] || '');
|
||||
delete params[key];
|
||||
}
|
||||
});
|
||||
return result.join('');
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
ngRouteModule.provider('$routeParams', $RouteParamsProvider);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name $routeParams
|
||||
* @requires $route
|
||||
*
|
||||
* @description
|
||||
* The `$routeParams` service allows you to retrieve the current set of route parameters.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* The route parameters are a combination of {@link ng.$location `$location`}'s
|
||||
* {@link ng.$location#search `search()`} and {@link ng.$location#path `path()`}.
|
||||
* The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched.
|
||||
*
|
||||
* In case of parameter name collision, `path` params take precedence over `search` params.
|
||||
*
|
||||
* The service guarantees that the identity of the `$routeParams` object will remain unchanged
|
||||
* (but its properties will likely change) even when a route change occurs.
|
||||
*
|
||||
* Note that the `$routeParams` are only updated *after* a route change completes successfully.
|
||||
* This means that you cannot rely on `$routeParams` being correct in route resolve functions.
|
||||
* Instead you can use `$route.current.params` to access the new route's parameters.
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* // Given:
|
||||
* // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
|
||||
* // Route: /Chapter/:chapterId/Section/:sectionId
|
||||
* //
|
||||
* // Then
|
||||
* $routeParams ==> {chapterId:'1', sectionId:'2', search:'moby'}
|
||||
* ```
|
||||
*/
|
||||
function $RouteParamsProvider() {
|
||||
this.$get = function() { return {}; };
|
||||
}
|
||||
|
||||
ngRouteModule.directive('ngView', ngViewFactory);
|
||||
ngRouteModule.directive('ngView', ngViewFillContentFactory);
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name ngView
|
||||
* @restrict ECA
|
||||
*
|
||||
* @description
|
||||
* # Overview
|
||||
* `ngView` is a directive that complements the {@link ngRoute.$route $route} service by
|
||||
* including the rendered template of the current route into the main layout (`index.html`) file.
|
||||
* Every time the current route changes, the included view changes with it according to the
|
||||
* configuration of the `$route` service.
|
||||
*
|
||||
* Requires the {@link ngRoute `ngRoute`} module to be installed.
|
||||
*
|
||||
* @animations
|
||||
* enter - animation is used to bring new content into the browser.
|
||||
* leave - animation is used to animate existing content away.
|
||||
*
|
||||
* The enter and leave animation occur concurrently.
|
||||
*
|
||||
* @scope
|
||||
* @priority 400
|
||||
* @param {string=} onload Expression to evaluate whenever the view updates.
|
||||
*
|
||||
* @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll
|
||||
* $anchorScroll} to scroll the viewport after the view is updated.
|
||||
*
|
||||
* - If the attribute is not set, disable scrolling.
|
||||
* - If the attribute is set without value, enable scrolling.
|
||||
* - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated
|
||||
* as an expression yields a truthy value.
|
||||
* @example
|
||||
<example name="ngView-directive" module="ngViewExample"
|
||||
deps="angular-route.js;angular-animate.js"
|
||||
animations="true" fixBase="true">
|
||||
<file name="index.html">
|
||||
<div ng-controller="MainCtrl as main">
|
||||
Choose:
|
||||
<a href="Book/Moby">Moby</a> |
|
||||
<a href="Book/Moby/ch/1">Moby: Ch1</a> |
|
||||
<a href="Book/Gatsby">Gatsby</a> |
|
||||
<a href="Book/Gatsby/ch/4?key=value">Gatsby: Ch4</a> |
|
||||
<a href="Book/Scarlet">Scarlet Letter</a><br/>
|
||||
|
||||
<div class="view-animate-container">
|
||||
<div ng-view class="view-animate"></div>
|
||||
</div>
|
||||
<hr />
|
||||
|
||||
<pre>$location.path() = {{main.$location.path()}}</pre>
|
||||
<pre>$route.current.templateUrl = {{main.$route.current.templateUrl}}</pre>
|
||||
<pre>$route.current.params = {{main.$route.current.params}}</pre>
|
||||
<pre>$routeParams = {{main.$routeParams}}</pre>
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="book.html">
|
||||
<div>
|
||||
controller: {{book.name}}<br />
|
||||
Book Id: {{book.params.bookId}}<br />
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="chapter.html">
|
||||
<div>
|
||||
controller: {{chapter.name}}<br />
|
||||
Book Id: {{chapter.params.bookId}}<br />
|
||||
Chapter Id: {{chapter.params.chapterId}}
|
||||
</div>
|
||||
</file>
|
||||
|
||||
<file name="animations.css">
|
||||
.view-animate-container {
|
||||
position:relative;
|
||||
height:100px!important;
|
||||
position:relative;
|
||||
background:white;
|
||||
border:1px solid black;
|
||||
height:40px;
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
.view-animate {
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.view-animate.ng-enter, .view-animate.ng-leave {
|
||||
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
||||
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s;
|
||||
|
||||
display:block;
|
||||
width:100%;
|
||||
border-left:1px solid black;
|
||||
|
||||
position:absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.view-animate.ng-enter {
|
||||
left:100%;
|
||||
}
|
||||
.view-animate.ng-enter.ng-enter-active {
|
||||
left:0;
|
||||
}
|
||||
.view-animate.ng-leave.ng-leave-active {
|
||||
left:-100%;
|
||||
}
|
||||
</file>
|
||||
|
||||
<file name="script.js">
|
||||
angular.module('ngViewExample', ['ngRoute', 'ngAnimate'])
|
||||
.config(['$routeProvider', '$locationProvider',
|
||||
function($routeProvider, $locationProvider) {
|
||||
$routeProvider
|
||||
.when('/Book/:bookId', {
|
||||
templateUrl: 'book.html',
|
||||
controller: 'BookCtrl',
|
||||
controllerAs: 'book'
|
||||
})
|
||||
.when('/Book/:bookId/ch/:chapterId', {
|
||||
templateUrl: 'chapter.html',
|
||||
controller: 'ChapterCtrl',
|
||||
controllerAs: 'chapter'
|
||||
});
|
||||
|
||||
$locationProvider.html5Mode(true);
|
||||
}])
|
||||
.controller('MainCtrl', ['$route', '$routeParams', '$location',
|
||||
function($route, $routeParams, $location) {
|
||||
this.$route = $route;
|
||||
this.$location = $location;
|
||||
this.$routeParams = $routeParams;
|
||||
}])
|
||||
.controller('BookCtrl', ['$routeParams', function($routeParams) {
|
||||
this.name = "BookCtrl";
|
||||
this.params = $routeParams;
|
||||
}])
|
||||
.controller('ChapterCtrl', ['$routeParams', function($routeParams) {
|
||||
this.name = "ChapterCtrl";
|
||||
this.params = $routeParams;
|
||||
}]);
|
||||
|
||||
</file>
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should load and compile correct template', function() {
|
||||
element(by.linkText('Moby: Ch1')).click();
|
||||
var content = element(by.css('[ng-view]')).getText();
|
||||
expect(content).toMatch(/controller\: ChapterCtrl/);
|
||||
expect(content).toMatch(/Book Id\: Moby/);
|
||||
expect(content).toMatch(/Chapter Id\: 1/);
|
||||
|
||||
element(by.partialLinkText('Scarlet')).click();
|
||||
|
||||
content = element(by.css('[ng-view]')).getText();
|
||||
expect(content).toMatch(/controller\: BookCtrl/);
|
||||
expect(content).toMatch(/Book Id\: Scarlet/);
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @ngdoc event
|
||||
* @name ngView#$viewContentLoaded
|
||||
* @eventType emit on the current ngView scope
|
||||
* @description
|
||||
* Emitted every time the ngView content is reloaded.
|
||||
*/
|
||||
ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate'];
|
||||
function ngViewFactory($route, $anchorScroll, $animate) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
terminal: true,
|
||||
priority: 400,
|
||||
transclude: 'element',
|
||||
link: function(scope, $element, attr, ctrl, $transclude) {
|
||||
var currentScope,
|
||||
currentElement,
|
||||
previousLeaveAnimation,
|
||||
autoScrollExp = attr.autoscroll,
|
||||
onloadExp = attr.onload || '';
|
||||
|
||||
scope.$on('$routeChangeSuccess', update);
|
||||
update();
|
||||
|
||||
function cleanupLastView() {
|
||||
if (previousLeaveAnimation) {
|
||||
$animate.cancel(previousLeaveAnimation);
|
||||
previousLeaveAnimation = null;
|
||||
}
|
||||
|
||||
if (currentScope) {
|
||||
currentScope.$destroy();
|
||||
currentScope = null;
|
||||
}
|
||||
if (currentElement) {
|
||||
previousLeaveAnimation = $animate.leave(currentElement);
|
||||
previousLeaveAnimation.then(function() {
|
||||
previousLeaveAnimation = null;
|
||||
});
|
||||
currentElement = null;
|
||||
}
|
||||
}
|
||||
|
||||
function update() {
|
||||
var locals = $route.current && $route.current.locals,
|
||||
template = locals && locals.$template;
|
||||
|
||||
if (angular.isDefined(template)) {
|
||||
var newScope = scope.$new();
|
||||
var current = $route.current;
|
||||
|
||||
// Note: This will also link all children of ng-view that were contained in the original
|
||||
// html. If that content contains controllers, ... they could pollute/change the scope.
|
||||
// However, using ng-view on an element with additional content does not make sense...
|
||||
// Note: We can't remove them in the cloneAttchFn of $transclude as that
|
||||
// function is called before linking the content, which would apply child
|
||||
// directives to non existing elements.
|
||||
var clone = $transclude(newScope, function(clone) {
|
||||
$animate.enter(clone, null, currentElement || $element).then(function onNgViewEnter() {
|
||||
if (angular.isDefined(autoScrollExp)
|
||||
&& (!autoScrollExp || scope.$eval(autoScrollExp))) {
|
||||
$anchorScroll();
|
||||
}
|
||||
});
|
||||
cleanupLastView();
|
||||
});
|
||||
|
||||
currentElement = clone;
|
||||
currentScope = current.scope = newScope;
|
||||
currentScope.$emit('$viewContentLoaded');
|
||||
currentScope.$eval(onloadExp);
|
||||
} else {
|
||||
cleanupLastView();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This directive is called during the $transclude call of the first `ngView` directive.
|
||||
// It will replace and compile the content of the element with the loaded template.
|
||||
// We need this directive so that the element content is already filled when
|
||||
// the link function of another directive on the same element as ngView
|
||||
// is called.
|
||||
ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route'];
|
||||
function ngViewFillContentFactory($compile, $controller, $route) {
|
||||
return {
|
||||
restrict: 'ECA',
|
||||
priority: -400,
|
||||
link: function(scope, $element) {
|
||||
var current = $route.current,
|
||||
locals = current.locals;
|
||||
|
||||
$element.html(locals.$template);
|
||||
|
||||
var link = $compile($element.contents());
|
||||
|
||||
if (current.controller) {
|
||||
locals.$scope = scope;
|
||||
var controller = $controller(current.controller, locals);
|
||||
if (current.controllerAs) {
|
||||
scope[current.controllerAs] = controller;
|
||||
}
|
||||
$element.data('$ngControllerController', controller);
|
||||
$element.children().data('$ngControllerController', controller);
|
||||
}
|
||||
|
||||
link(scope);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
})(window, window.angular);
|
250
sources/js/angular.min.js
vendored
250
sources/js/angular.min.js
vendored
|
@ -1,250 +0,0 @@
|
|||
/*
|
||||
AngularJS v1.3.4
|
||||
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||
License: MIT
|
||||
*/
|
||||
(function(U,V,u){'use strict';function z(b){return function(){var a=arguments[0],c;c="["+(b?b+":":"")+a+"] http://errors.angularjs.org/1.3.4/"+(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 Ra(b){if(null==b||Sa(b))return!1;var a=b.length;return b.nodeType===
|
||||
na&&a?!0:I(b)||D(b)||0===a||"number"===typeof a&&0<a&&a-1 in b}function r(b,a,c){var d,e;if(b)if(F(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(D(b)||Ra(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!==r)b.forEach(a,c,b);else for(d in b)b.hasOwnProperty(d)&&a.call(c,b[d],d,b);return b}function Bd(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 kc(b){return function(a,c){b(c,a)}}function Cd(){return++kb}function lc(b,a){a?b.$$hashKey=a:delete b.$$hashKey}function C(b){for(var a=b.$$hashKey,c=1,d=arguments.length;c<d;c++){var e=arguments[c];if(e)for(var f=Object.keys(e),g=0,h=f.length;g<h;g++){var k=f[g];b[k]=e[k]}}lc(b,a);return b}function $(b){return parseInt(b,10)}function x(){}function oa(b){return b}function ca(b){return function(){return b}}function G(b){return"undefined"===typeof b}function y(b){return"undefined"!==
|
||||
typeof b}function K(b){return null!==b&&"object"===typeof b}function I(b){return"string"===typeof b}function X(b){return"number"===typeof b}function fa(b){return"[object Date]"===Ja.call(b)}function F(b){return"function"===typeof b}function lb(b){return"[object RegExp]"===Ja.call(b)}function Sa(b){return b&&b.window===b}function Ta(b){return b&&b.$evalAsync&&b.$watch}function Ua(b){return"boolean"===typeof b}function mc(b){return!(!b||!(b.nodeName||b.prop&&b.attr&&b.find))}function Dd(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 R(b.nodeName||b[0]&&b[0].nodeName)}function Va(b,a){var c=b.indexOf(a);0<=c&&b.splice(c,1);return a}function Ca(b,a,c,d){if(Sa(b)||Ta(b))throw Wa("cpws");if(a){if(b===a)throw Wa("cpi");c=c||[];d=d||[];if(K(b)){var e=c.indexOf(b);if(-1!==e)return d[e];c.push(b);d.push(a)}if(D(b))for(var f=a.length=0;f<b.length;f++)e=Ca(b[f],null,c,d),K(b[f])&&(c.push(b[f]),d.push(e)),a.push(e);else{var g=a.$$hashKey;D(a)?a.length=
|
||||
0:r(a,function(b,c){delete a[c]});for(f in b)b.hasOwnProperty(f)&&(e=Ca(b[f],null,c,d),K(b[f])&&(c.push(b[f]),d.push(e)),a[f]=e);lc(a,g)}}else if(a=b)D(b)?a=Ca(b,[],c,d):fa(b)?a=new Date(b.getTime()):lb(b)?(a=new RegExp(b.source,b.toString().match(/[^\/]*$/)[0]),a.lastIndex=b.lastIndex):K(b)&&(e=Object.create(Object.getPrototypeOf(b)),a=Ca(b,e,c,d));return a}function ua(b,a){if(D(b)){a=a||[];for(var c=0,d=b.length;c<d;c++)a[c]=b[c]}else if(K(b))for(c in a=a||{},b)if("$"!==c.charAt(0)||"$"!==c.charAt(1))a[c]=
|
||||
b[c];return a||b}function pa(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(D(b)){if(!D(a))return!1;if((c=b.length)==a.length){for(d=0;d<c;d++)if(!pa(b[d],a[d]))return!1;return!0}}else{if(fa(b))return fa(a)?pa(b.getTime(),a.getTime()):!1;if(lb(b)&&lb(a))return b.toString()==a.toString();if(Ta(b)||Ta(a)||Sa(b)||Sa(a)||D(a))return!1;c={};for(d in b)if("$"!==d.charAt(0)&&!F(b[d])){if(!pa(b[d],a[d]))return!1;c[d]=!0}for(d in a)if(!c.hasOwnProperty(d)&&
|
||||
"$"!==d.charAt(0)&&a[d]!==u&&!F(a[d]))return!1;return!0}return!1}function Xa(b,a,c){return b.concat(Ya.call(a,c))}function nc(b,a){var c=2<arguments.length?Ya.call(arguments,2):[];return!F(a)||a instanceof RegExp?a:c.length?function(){return arguments.length?a.apply(b,Xa(c,arguments,0)):a.apply(b,c)}:function(){return arguments.length?a.apply(b,arguments):a.call(b)}}function Ed(b,a){var c=a;"string"===typeof b&&"$"===b.charAt(0)&&"$"===b.charAt(1)?c=u:Sa(a)?c="$WINDOW":a&&V===a?c="$DOCUMENT":Ta(a)&&
|
||||
(c="$SCOPE");return c}function Za(b,a){return"undefined"===typeof b?u:JSON.stringify(b,Ed,a?" ":null)}function oc(b){return I(b)?JSON.parse(b):b}function va(b){b=A(b).clone();try{b.empty()}catch(a){}var c=A("<div>").append(b).html();try{return b[0].nodeType===mb?R(c):c.match(/^(<[^>]+>)/)[1].replace(/^<([\w\-]+)/,function(a,b){return"<"+R(b)})}catch(d){return R(c)}}function pc(b){try{return decodeURIComponent(b)}catch(a){}}function qc(b){var a={},c,d;r((b||"").split("&"),function(b){b&&(c=b.replace(/\+/g,
|
||||
"%20").split("="),d=pc(c[0]),y(d)&&(b=y(c[1])?pc(c[1]):!0,Jb.call(a,d)?D(a[d])?a[d].push(b):a[d]=[a[d],b]:a[d]=b))});return a}function Kb(b){var a=[];r(b,function(b,d){D(b)?r(b,function(b){a.push(Da(d,!0)+(!0===b?"":"="+Da(b,!0)))}):a.push(Da(d,!0)+(!0===b?"":"="+Da(b,!0)))});return a.length?a.join("&"):""}function nb(b){return Da(b,!0).replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+")}function Da(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 Fd(b,a){var c,d,e=ob.length;b=A(b);for(d=0;d<e;++d)if(c=ob[d]+a,I(c=b.attr(c)))return c;return null}function Gd(b,a){var c,d,e={};r(ob,function(a){a+="app";!c&&b.hasAttribute&&b.hasAttribute(a)&&(c=b,d=b.getAttribute(a))});r(ob,function(a){a+="app";var e;!c&&(e=b.querySelector("["+a.replace(":","\\:")+"]"))&&(c=e,d=e.getAttribute(a))});c&&(e.strictDi=null!==Fd(c,"strict-di"),a(c,d?[d]:[],e))}function rc(b,a,c){K(c)||
|
||||
(c={});c=C({strictDi:!1},c);var d=function(){b=A(b);if(b.injector()){var d=b[0]===V?"document":va(b);throw Wa("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=Lb(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!/;U&&e.test(U.name)&&(c.debugInfoEnabled=!0,U.name=U.name.replace(e,""));if(U&&!f.test(U.name))return d();U.name=U.name.replace(f,"");ha.resumeBootstrap=function(b){r(b,function(b){a.push(b)});d()}}function Hd(){U.name="NG_ENABLE_DEBUG_INFO!"+U.name;U.location.reload()}function Id(b){return ha.element(b).injector().get("$$testability")}function Mb(b,a){a=a||"_";return b.replace(Jd,function(b,d){return(d?a:"")+b.toLowerCase()})}function Kd(){var b;sc||
|
||||
((qa=U.jQuery)&&qa.fn.on?(A=qa,C(qa.fn,{scope:Ka.scope,isolateScope:Ka.isolateScope,controller:Ka.controller,injector:Ka.injector,inheritedData:Ka.inheritedData}),b=qa.cleanData,qa.cleanData=function(a){var c;if(Nb)Nb=!1;else for(var d=0,e;null!=(e=a[d]);d++)(c=qa._data(e,"events"))&&c.$destroy&&qa(e).triggerHandler("$destroy");b(a)}):A=S,ha.element=A,sc=!0)}function Ob(b,a,c){if(!b)throw Wa("areq",a||"?",c||"required");return b}function pb(b,a,c){c&&D(b)&&(b=b[b.length-1]);Ob(F(b),a,"not a function, got "+
|
||||
(b&&"object"===typeof b?b.constructor.name||"Object":typeof b));return b}function La(b,a){if("hasOwnProperty"===b)throw Wa("badname",a);}function tc(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&&F(b)?nc(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 A(c)}function ia(){return Object.create(null)}function Ld(b){function a(a,b,c){return a[b]||(a[b]=c())}var c=z("$injector"),
|
||||
d=z("ng");b=a(b,"angular",Object);b.$$minErr=b.$$minErr||z;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(c,d,e,f){f||(f=b);return function(){f[e||"push"]([c,d,arguments]);return t}}if(!g)throw c("nomod",f);var b=[],d=[],e=[],s=a("$injector","invoke","push",d),t={_invokeQueue:b,_configBlocks:d,_runBlocks:e,requires:g,name:f,provider:a("$provide","provider"),factory:a("$provide",
|
||||
"factory"),service:a("$provide","service"),value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animateProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:s,run:function(a){e.push(a);return this}};h&&s(h);return t})}})}function Md(b){C(b,{bootstrap:rc,copy:Ca,extend:C,equals:pa,element:A,forEach:r,injector:Lb,noop:x,bind:nc,toJson:Za,fromJson:oc,identity:oa,isUndefined:G,
|
||||
isDefined:y,isString:I,isFunction:F,isObject:K,isNumber:X,isElement:mc,isArray:D,version:Nd,isDate:fa,lowercase:R,uppercase:rb,callbacks:{counter:0},getTestability:Id,$$minErr:z,$$csp:$a,reloadWithDebugInfo:Hd});ab=Ld(U);try{ab("ngLocale")}catch(a){ab("ngLocale",[]).provider("$locale",Od)}ab("ng",["ngLocale"],["$provide",function(a){a.provider({$$sanitizeUri:Pd});a.provider("$compile",uc).directive({a:Qd,input:vc,textarea:vc,form:Rd,script:Sd,select:Td,style:Ud,option:Vd,ngBind:Wd,ngBindHtml:Xd,ngBindTemplate:Yd,
|
||||
ngClass:Zd,ngClassEven:$d,ngClassOdd:ae,ngCloak:be,ngController:ce,ngForm:de,ngHide:ee,ngIf:fe,ngInclude:ge,ngInit:he,ngNonBindable:ie,ngPluralize:je,ngRepeat:ke,ngShow:le,ngStyle:me,ngSwitch:ne,ngSwitchWhen:oe,ngSwitchDefault:pe,ngOptions:qe,ngTransclude:re,ngModel:se,ngList:te,ngChange:ue,pattern:wc,ngPattern:wc,required:xc,ngRequired:xc,minlength:yc,ngMinlength:yc,maxlength:zc,ngMaxlength:zc,ngValue:ve,ngModelOptions:we}).directive({ngInclude:xe}).directive(sb).directive(Ac);a.provider({$anchorScroll:ye,
|
||||
$animate:ze,$browser:Ae,$cacheFactory:Be,$controller:Ce,$document:De,$exceptionHandler:Ee,$filter:Bc,$interpolate:Fe,$interval:Ge,$http:He,$httpBackend:Ie,$location:Je,$log:Ke,$parse:Le,$rootScope:Me,$q:Ne,$$q:Oe,$sce:Pe,$sceDelegate:Qe,$sniffer:Re,$templateCache:Se,$templateRequest:Te,$$testability:Ue,$timeout:Ve,$window:We,$$rAF:Xe,$$asyncCallback:Ye})}])}function bb(b){return b.replace(Ze,function(a,b,d,e){return e?d.toUpperCase():d}).replace($e,"Moz$1")}function Cc(b){b=b.nodeType;return b===
|
||||
na||!b||9===b}function Dc(b,a){var c,d,e=a.createDocumentFragment(),f=[];if(Pb.test(b)){c=c||e.appendChild(a.createElement("div"));d=(af.exec(b)||["",""])[1].toLowerCase();d=ja[d]||ja._default;c.innerHTML=d[1]+b.replace(bf,"<$1></$2>")+d[2];for(d=d[0];d--;)c=c.lastChild;f=Xa(f,c.childNodes);c=e.firstChild;c.textContent=""}else f.push(a.createTextNode(b));e.textContent="";e.innerHTML="";r(f,function(a){e.appendChild(a)});return e}function S(b){if(b instanceof S)return b;var a;I(b)&&(b=P(b),a=!0);if(!(this instanceof
|
||||
S)){if(a&&"<"!=b.charAt(0))throw Qb("nosel");return new S(b)}if(a){a=V;var c;b=(c=cf.exec(b))?[a.createElement(c[1])]:(c=Dc(b,a))?c.childNodes:[]}Ec(this,b)}function Rb(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 Fc(b,a,c,d){if(y(d))throw Qb("offargs");var e=(d=vb(b))&&d.events,f=d&&d.handle;if(f)if(a)r(a.split(" "),function(a){if(y(c)){var d=e[a];Va(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&&wb[c];d&&(a?delete d.data[a]:(d.handle&&(d.events.$destroy&&d.handle({},"$destroy"),Fc(b)),delete wb[c],b.ng339=u))}function vb(b,a){var c=b.ng339,c=c&&wb[c];a&&!c&&(b.ng339=c=++df,c=wb[c]={events:{},data:{},handle:u});return c}function Sb(b,a,c){if(Cc(b)){var d=y(c),e=!d&&a&&!K(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];C(b,a)}}}
|
||||
function Tb(b,a){return b.getAttribute?-1<(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").indexOf(" "+a+" "):!1}function Ub(b,a){a&&b.setAttribute&&r(a.split(" "),function(a){b.setAttribute("class",P((" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ").replace(" "+P(a)+" "," ")))})}function Vb(b,a){if(a&&b.setAttribute){var c=(" "+(b.getAttribute("class")||"")+" ").replace(/[\n\t]/g," ");r(a.split(" "),function(a){a=P(a);-1===c.indexOf(" "+a+" ")&&(c+=a+" ")});b.setAttribute("class",
|
||||
P(c))}}function Ec(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 Gc(b,a){return xb(b,"$"+(a||"ngController")+"Controller")}function xb(b,a,c){9==b.nodeType&&(b=b.documentElement);for(a=D(a)?a:[a];b;){for(var d=0,e=a.length;d<e;d++)if((c=A.data(b,a[d]))!==u)return c;b=b.parentNode||11===b.nodeType&&b.host}}function Hc(b){for(tb(b,!0);b.firstChild;)b.removeChild(b.firstChild)}
|
||||
function Ic(b,a){a||tb(b);var c=b.parentNode;c&&c.removeChild(b)}function ef(b,a){a=a||U;if("complete"===a.document.readyState)a.setTimeout(b);else A(a).on("load",b)}function Jc(b,a){var c=yb[a.toLowerCase()];return c&&Kc[ta(b)]&&c}function ff(b,a){var c=b.nodeName;return("INPUT"===c||"TEXTAREA"===c)&&Lc[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(G(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=ua(f));for(var k=0;k<g;k++)c.isImmediatePropagationStopped()||f[k].call(b,c)}};c.elem=b;return c}function Ma(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||Cd)():c+":"+b}function cb(b,
|
||||
a){if(a){var c=0;this.nextUid=function(){return++c}}r(b,this.put,this)}function hf(b){return(b=b.toString().replace(Mc,"").match(Nc))?"function("+(b[1]||"").replace(/[\s\r\n]+/," ")+")":"fn"}function Wb(b,a,c){var d;if("function"===typeof b){if(!(d=b.$inject)){d=[];if(b.length){if(a)throw I(c)&&c||(c=b.name||hf(b)),Ea("strictdi",c);a=b.toString().replace(Mc,"");a=a.match(Nc);r(a[1].split(jf),function(a){a.replace(kf,function(a,b,c){d.push(c)})})}b.$inject=d}}else D(b)?(a=b.length-1,pb(b[a],"fn"),
|
||||
d=b.slice(0,a)):pb(b,"fn",!0);return d}function Lb(b,a){function c(a){return function(b,c){if(K(b))r(b,kc(a));else return a(b,c)}}function d(a,b){La(a,"service");if(F(b)||D(b))b=s.instantiate(b);if(!b.$get)throw Ea("pget",a);return p[a+"Provider"]=b}function e(a,b){return function(){var c=q.invoke(b,this,u,a);if(G(c))throw Ea("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;r(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(!m.get(a)){m.put(a,!0);try{I(a)?(c=ab(a),b=b.concat(g(c.requires)).concat(c._runBlocks),d(c._invokeQueue),d(c._configBlocks)):F(a)?b.push(s.invoke(a)):D(a)?b.push(s.invoke(a)):pb(a,"module")}catch(e){throw D(a)&&(a=a[a.length-1]),e.message&&e.stack&&-1==e.stack.indexOf(e.message)&&(e=e.message+"\n"+e.stack),Ea("modulerr",a,e.stack||e.message||e);}}});return b}function h(b,c){function d(a){if(b.hasOwnProperty(a)){if(b[a]===k)throw Ea("cdep",a+" <- "+l.join(" <- "));
|
||||
return b[a]}try{return l.unshift(a),b[a]=k,b[a]=c(a)}catch(e){throw b[a]===k&&delete b[a],e;}finally{l.shift()}}function e(b,c,f,g){"string"===typeof f&&(g=f,f=null);var k=[];g=Wb(b,a,g);var h,l,q;l=0;for(h=g.length;l<h;l++){q=g[l];if("string"!==typeof q)throw Ea("itkn",q);k.push(f&&f.hasOwnProperty(q)?f[q]:d(q))}D(b)&&(b=b[h]);return b.apply(c,k)}return{invoke:e,instantiate:function(a,b,c){var d=Object.create((D(a)?a[a.length-1]:a).prototype);a=e(a,d,b,c);return K(a)||F(a)?a:d},get:d,annotate:Wb,
|
||||
has:function(a){return p.hasOwnProperty(a+"Provider")||b.hasOwnProperty(a)}}}a=!0===a;var k={},l=[],m=new cb([],!0),p={$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,ca(b),!1)}),constant:c(function(a,b){La(a,"constant");p[a]=b;t[a]=b}),decorator:function(a,b){var c=s.get(a+"Provider"),d=c.$get;c.$get=function(){var a=q.invoke(d,c);return q.invoke(b,null,{$delegate:a})}}}},s=p.$injector=
|
||||
h(p,function(){throw Ea("unpr",l.join(" <- "));}),t={},q=t.$injector=h(t,function(a){var b=s.get(a+"Provider");return q.invoke(b.$get,b,u,a)});r(g(b),function(a){q.invoke(a||x)});return q}function ye(){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;F(c)?c=c():mc(c)?(c=c[0],
|
||||
c="fixed"!==a.getComputedStyle(c).position?0:c.getBoundingClientRect().bottom):X(c)||(c=0);c&&(b=b.getBoundingClientRect().top,a.scrollBy(0,b-c))}else a.scrollTo(0,0)}function g(){var a=c.hash(),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 Ye(){this.$get=["$$rAF","$timeout",function(b,a){return b.supported?function(a){return b(a)}:
|
||||
function(b){return a(b,0,!1)}}]}function lf(b,a,c,d){function e(a){try{a.apply(null,Ya.call(arguments,1))}finally{if(v--,0===v)for(;w.length;)try{w.pop()()}catch(b){c.error(b)}}}function f(a,b){(function ya(){r(O,function(a){a()});E=b(ya,a)})()}function g(){h();k()}function h(){H=b.history.state;H=G(H)?null:H;pa(H,Q)&&(H=Q);Q=H}function k(){if(B!==m.url()||M!==H)B=m.url(),M=H,r(W,function(a){a(m.url(),H)})}function l(a){try{return decodeURIComponent(a)}catch(b){return a}}var m=this,p=a[0],s=b.location,
|
||||
t=b.history,q=b.setTimeout,N=b.clearTimeout,n={};m.isMock=!1;var v=0,w=[];m.$$completeOutstandingRequest=e;m.$$incOutstandingRequestCount=function(){v++};m.notifyWhenNoOutstandingRequests=function(a){r(O,function(a){a()});0===v?a():w.push(a)};var O=[],E;m.addPollFn=function(a){G(E)&&f(100,q);O.push(a);return a};var H,M,B=s.href,ea=a.find("base"),L=null;h();M=H;m.url=function(a,c,e){G(e)&&(e=null);s!==b.location&&(s=b.location);t!==b.history&&(t=b.history);if(a){var f=M===e;if(B===a&&(!d.history||
|
||||
f))return m;var g=B&&Fa(B)===Fa(a);B=a;M=e;!d.history||g&&f?(g||(L=a),c?s.replace(a):s.href=a):(t[c?"replaceState":"pushState"](e,"",a),h(),M=H);return m}return L||s.href.replace(/%27/g,"'")};m.state=function(){return H};var W=[],ba=!1,Q=null;m.onUrlChange=function(a){if(!ba){if(d.history)A(b).on("popstate",g);A(b).on("hashchange",g);ba=!0}W.push(a);return a};m.$$checkUrlChange=k;m.baseHref=function(){var a=ea.attr("href");return a?a.replace(/^(https?\:)?\/\/[^\/]*/,""):""};var aa={},y="",da=m.baseHref();
|
||||
m.cookies=function(a,b){var d,e,f,g;if(a)b===u?p.cookie=encodeURIComponent(a)+"=;path="+da+";expires=Thu, 01 Jan 1970 00:00:00 GMT":I(b)&&(d=(p.cookie=encodeURIComponent(a)+"="+encodeURIComponent(b)+";path="+da).length+1,4096<d&&c.warn("Cookie '"+a+"' possibly not set or overflowed because it was too large ("+d+" > 4096 bytes)!"));else{if(p.cookie!==y)for(y=p.cookie,d=y.split("; "),aa={},f=0;f<d.length;f++)e=d[f],g=e.indexOf("="),0<g&&(a=l(e.substring(0,g)),aa[a]===u&&(aa[a]=l(e.substring(g+1))));
|
||||
return aa}};m.defer=function(a,b){var c;v++;c=q(function(){delete n[c];e(a)},b||0);n[c]=!0;return c};m.defer.cancel=function(a){return n[a]?(delete n[a],N(a),e(x),!0):!1}}function Ae(){this.$get=["$window","$log","$sniffer","$document",function(b,a,c,d){return new lf(b,d,a,c)}]}function Be(){this.$get=function(){function b(b,d){function e(a){a!=p&&(s?s==a&&(s=a.n):s=a,f(a.n,a.p),f(a,p),p=a,p.n=null)}function f(a,b){a!=b&&(a&&(a.p=b),b&&(b.n=a))}if(b in a)throw z("$cacheFactory")("iid",b);var g=0,
|
||||
h=C({},d,{id:b}),k={},l=d&&d.capacity||Number.MAX_VALUE,m={},p=null,s=null;return a[b]={put:function(a,b){if(l<Number.MAX_VALUE){var c=m[a]||(m[a]={key:a});e(c)}if(!G(b))return a in k||g++,k[a]=b,g>l&&this.remove(s.key),b},get:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;e(b)}return k[a]},remove:function(a){if(l<Number.MAX_VALUE){var b=m[a];if(!b)return;b==p&&(p=b.p);b==s&&(s=b.n);f(b.n,b.p);delete m[a]}delete k[a];g--},removeAll:function(){k={};g=0;m={};p=s=null},destroy:function(){m=
|
||||
h=k=null;delete a[b]},info:function(){return C({},h,{size:g})}}}var a={};b.info=function(){var b={};r(a,function(a,e){b[e]=a.info()});return b};b.get=function(b){return a[b]};return b}}function Se(){this.$get=["$cacheFactory",function(b){return b("templates")}]}function uc(b,a){function c(a,b){var c=/^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/,d={};r(a,function(a,e){var f=a.match(c);if(!f)throw ka("iscp",b,e,a);d[e]={mode:f[1][0],collection:"*"===f[2],optional:"?"===f[3],attrName:f[4]||e}});return d}var d=
|
||||
{},e=/^\s*directive\:\s*([\w\-]+)\s+(.*)$/,f=/(([\w\-]+)(?:\:([^;]+))?;?)/,g=Dd("ngSrc,ngSrcset,src,srcset"),h=/^(?:(\^\^?)?(\?)?(\^\^?)?)?/,k=/^(on[a-z]+|formaction)$/;this.directive=function p(a,e){La(a,"directive");I(a)?(Ob(e,"directiveFactory"),d.hasOwnProperty(a)||(d[a]=[],b.factory(a+"Directive",["$injector","$exceptionHandler",function(b,e){var f=[];r(d[a],function(d,g){try{var h=b.invoke(d);F(h)?h={compile:ca(h)}:!h.compile&&h.link&&(h.compile=ca(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";K(h.scope)&&(h.$$isolateBindings=c(h.scope,h.name));f.push(h)}catch(k){e(k)}});return f}])),d[a].push(e)):r(a,kc(p));return this};this.aHrefSanitizationWhitelist=function(b){return y(b)?(a.aHrefSanitizationWhitelist(b),this):a.aHrefSanitizationWhitelist()};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a.imgSrcSanitizationWhitelist(b),this):a.imgSrcSanitizationWhitelist()};var l=!0;this.debugInfoEnabled=
|
||||
function(a){return y(a)?(l=a,this):l};this.$get=["$injector","$interpolate","$exceptionHandler","$templateRequest","$parse","$controller","$rootScope","$document","$sce","$animate","$$sanitizeUri",function(a,b,c,q,N,n,v,w,O,E,H){function M(a,b){try{a.addClass(b)}catch(c){}}function B(a,b,c,d,e){a instanceof A||(a=A(a));r(a,function(b,c){b.nodeType==mb&&b.nodeValue.match(/\S+/)&&(a[c]=A(b).wrap("<span></span>").parent()[0])});var f=ea(a,b,a,c,d,e);B.$$addScopeClass(a);var g=null;return function(b,
|
||||
c,d){Ob(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?A(U(g,A("<div>").append(a).html())):c?Ka.clone.call(a):a;if(h)for(var k in h)d.data("$"+k+"Controller",h[k].instance);B.$$addScopeInfo(d,b);c&&c(d,b);f&&f(b,d,d,e);return d}}function ea(a,b,c,d,e,f){function g(a,c,d,e){var f,k,l,q,s,n,w;if(p)for(w=
|
||||
Array(c.length),q=0;q<h.length;q+=3)f=h[q],w[f]=c[f];else w=c;q=0;for(s=h.length;q<s;)k=w[h[q++]],c=h[q++],f=h[q++],c?(c.scope?(l=a.$new(),B.$$addScopeInfo(A(k),l)):l=a,n=c.transcludeOnThisElement?L(a,c.transclude,e,c.elementTranscludeOnThisElement):!c.templateOnThisElement&&e?e:!e&&b?L(a,b):null,c(f,l,k,d,n)):f&&f(a,k.childNodes,u,e)}for(var h=[],k,l,q,s,p,n=0;n<a.length;n++){k=new X;l=W(a[n],[],k,0===n?d:u,e);(f=l.length?aa(l,a[n],k,b,c,null,[],[],f):null)&&f.scope&&B.$$addScopeClass(k.$$element);
|
||||
k=f&&f.terminal||!(q=a[n].childNodes)||!q.length?null:ea(q,f?(f.transcludeOnThisElement||!f.templateOnThisElement)&&f.transclude:b);if(f||k)h.push(n,f,k),s=!0,p=p||f;f=null}return s?g:null}function L(a,b,c,d){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 W(b,c,g,h,k){var l=g.$attr,q;switch(b.nodeType){case na:da(c,wa(ta(b)),"E",h,k);for(var s,n,w,N=b.attributes,t=0,O=N&&N.length;t<
|
||||
O;t++){var H=!1,v=!1;s=N[t];q=s.name;s=P(s.value);n=wa(q);if(w=za.test(n))q=Mb(n.substr(6),"-");var M=n.replace(/(Start|End)$/,""),E;a:{var B=M;if(d.hasOwnProperty(B)){E=void 0;for(var B=a.get(B+"Directive"),W=0,r=B.length;W<r;W++)if(E=B[W],E.multiElement){E=!0;break a}}E=!1}E&&n===M+"Start"&&(H=q,v=q.substr(0,q.length-5)+"end",q=q.substr(0,q.length-6));n=wa(q.toLowerCase());l[n]=q;if(w||!g.hasOwnProperty(n))g[n]=s,Jc(b,n)&&(g[n]=!0);S(b,c,s,n,w);da(c,n,"A",h,k,H,v)}b=b.className;if(I(b)&&""!==b)for(;q=
|
||||
f.exec(b);)n=wa(q[2]),da(c,n,"C",h,k)&&(g[n]=P(q[3])),b=b.substr(q.index+q[0].length);break;case mb:T(c,b.nodeValue);break;case 8:try{if(q=e.exec(b.nodeValue))n=wa(q[1]),da(c,n,"M",h,k)&&(g[n]=P(q[2]))}catch(Q){}}c.sort(z);return c}function ba(a,b,c){var d=[],e=0;if(b&&a.hasAttribute&&a.hasAttribute(b)){do{if(!a)throw ka("uterdir",b,c);a.nodeType==na&&(a.hasAttribute(b)&&e++,a.hasAttribute(c)&&e--);d.push(a);a=a.nextSibling}while(0<e)}else d.push(a);return A(d)}function Q(a,b,c){return function(d,
|
||||
e,f,g,h){e=ba(e[0],b,c);return a(d,e,f,g,h)}}function aa(a,d,e,f,g,k,l,q,p){function w(a,b,c,d){if(a){c&&(a=Q(a,c,d));a.require=J.require;a.directiveName=ga;if(L===J||J.$$isolateScope)a=Y(a,{isolateScope:!0});l.push(a)}if(b){c&&(b=Q(b,c,d));b.require=J.require;b.directiveName=ga;if(L===J||J.$$isolateScope)b=Y(b,{isolateScope:!0});q.push(b)}}function O(a,b,c,d){var e,f="data",g=!1,k=c,l;if(I(b)){l=b.match(h);b=b.substring(l[0].length);l[3]&&(l[1]?l[3]=null:l[1]=l[3]);"^"===l[1]?f="inheritedData":"^^"===
|
||||
l[1]&&(f="inheritedData",k=c.parent());"?"===l[2]&&(g=!0);e=null;d&&"data"===f&&(e=d[b])&&(e=e.instance);e=e||k[f]("$"+b+"Controller");if(!e&&!g)throw ka("ctreq",b,a);return e||null}D(b)&&(e=[],r(b,function(b){e.push(O(a,b,c,d))}));return e}function H(a,c,f,g,h){function k(a,b,c){var d;Ta(a)||(c=b,b=a,a=u);C&&(d=M);c||(c=C?W.parent():W);return h(a,b,d,c,Xb)}var p,w,t,v,M,db,W,Q;d===f?(Q=e,W=e.$$element):(W=A(f),Q=new X(W,e));L&&(v=c.$new(!0));h&&(db=k,db.$$boundTransclude=h);E&&(ea={},M={},r(E,function(a){var b=
|
||||
{$scope:a===L||a.$$isolateScope?v:c,$element:W,$attrs:Q,$transclude:db};t=a.controller;"@"==t&&(t=Q[a.name]);b=n(t,b,!0,a.controllerAs);M[a.name]=b;C||W.data("$"+a.name+"Controller",b.instance);ea[a.name]=b}));if(L){B.$$addScopeInfo(W,v,!0,!(aa&&(aa===L||aa===L.$$originalDirective)));B.$$addScopeClass(W,!0);g=ea&&ea[L.name];var ba=v;g&&g.identifier&&!0===L.bindToController&&(ba=g.instance);r(v.$$isolateBindings=L.$$isolateBindings,function(a,d){var e=a.attrName,f=a.optional,g,h,k,l;switch(a.mode){case "@":Q.$observe(e,
|
||||
function(a){ba[d]=a});Q.$$observers[e].$$scope=c;Q[e]&&(ba[d]=b(Q[e])(c));break;case "=":if(f&&!Q[e])break;h=N(Q[e]);l=h.literal?pa:function(a,b){return a===b||a!==a&&b!==b};k=h.assign||function(){g=ba[d]=h(c);throw ka("nonassign",Q[e],L.name);};g=ba[d]=h(c);f=function(a){l(a,ba[d])||(l(a,g)?k(c,a=ba[d]):ba[d]=a);return g=a};f.$stateful=!0;f=a.collection?c.$watchCollection(Q[e],f):c.$watch(N(Q[e],f),null,h.literal);v.$on("$destroy",f);break;case "&":h=N(Q[e]),ba[d]=function(a){return h(c,a)}}})}ea&&
|
||||
(r(ea,function(a){a()}),ea=null);g=0;for(p=l.length;g<p;g++)w=l[g],Z(w,w.isolateScope?v:c,W,Q,w.require&&O(w.directiveName,w.require,W,M),db);var Xb=c;L&&(L.template||null===L.templateUrl)&&(Xb=v);a&&a(Xb,f.childNodes,u,h);for(g=q.length-1;0<=g;g--)w=q[g],Z(w,w.isolateScope?v:c,W,Q,w.require&&O(w.directiveName,w.require,W,M),db)}p=p||{};for(var v=-Number.MAX_VALUE,M,E=p.controllerDirectives,ea,L=p.newIsolateScopeDirective,aa=p.templateDirective,da=p.nonTlbTranscludeDirective,x=!1,Na=!1,C=p.hasElementTranscludeDirective,
|
||||
T=e.$$element=A(d),J,ga,z,Ga=f,R,S=0,za=a.length;S<za;S++){J=a[S];var zb=J.$$start,$=J.$$end;zb&&(T=ba(d,zb,$));z=u;if(v>J.priority)break;if(z=J.scope)J.templateUrl||(K(z)?(ya("new/isolated scope",L||M,J,T),L=J):ya("new/isolated scope",L,J,T)),M=M||J;ga=J.name;!J.templateUrl&&J.controller&&(z=J.controller,E=E||{},ya("'"+ga+"' controller",E[ga],J,T),E[ga]=J);if(z=J.transclude)x=!0,J.$$tlb||(ya("transclusion",da,J,T),da=J),"element"==z?(C=!0,v=J.priority,z=T,T=e.$$element=A(V.createComment(" "+ga+": "+
|
||||
e[ga]+" ")),d=T[0],Ab(g,Ya.call(z,0),d),Ga=B(z,f,v,k&&k.name,{nonTlbTranscludeDirective:da})):(z=A(Rb(d)).contents(),T.empty(),Ga=B(z,f));if(J.template)if(Na=!0,ya("template",aa,J,T),aa=J,z=F(J.template)?J.template(T,e):J.template,z=Pc(z),J.replace){k=J;z=Pb.test(z)?Qc(U(J.templateNamespace,P(z))):[];d=z[0];if(1!=z.length||d.nodeType!==na)throw ka("tplrt",ga,"");Ab(g,T,d);za={$attr:{}};z=W(d,[],za);var mf=a.splice(S+1,a.length-(S+1));L&&y(z);a=a.concat(z).concat(mf);Oc(e,za);za=a.length}else T.html(z);
|
||||
if(J.templateUrl)Na=!0,ya("template",aa,J,T),aa=J,J.replace&&(k=J),H=G(a.splice(S,a.length-S),T,e,g,x&&Ga,l,q,{controllerDirectives:E,newIsolateScopeDirective:L,templateDirective:aa,nonTlbTranscludeDirective:da}),za=a.length;else if(J.compile)try{R=J.compile(T,e,Ga),F(R)?w(null,R,zb,$):R&&w(R.pre,R.post,zb,$)}catch(ca){c(ca,va(T))}J.terminal&&(H.terminal=!0,v=Math.max(v,J.priority))}H.scope=M&&!0===M.scope;H.transcludeOnThisElement=x;H.elementTranscludeOnThisElement=C;H.templateOnThisElement=Na;H.transclude=
|
||||
Ga;p.hasElementTranscludeDirective=C;return H}function y(a){for(var b=0,c=a.length;b<c;b++){var d=b,e;e=C(Object.create(a[b]),{$$isolateScope:!0});a[d]=e}}function da(b,e,f,g,h,k,l){if(e===h)return null;h=null;if(d.hasOwnProperty(e)){var q;e=a.get(e+"Directive");for(var s=0,n=e.length;s<n;s++)try{if(q=e[s],(g===u||g>q.priority)&&-1!=q.restrict.indexOf(f)){if(k){var w={$$start:k,$$end:l};q=C(Object.create(q),w)}b.push(q);h=q}}catch(N){c(N)}}return h}function Oc(a,b){var c=b.$attr,d=a.$attr,e=a.$$element;
|
||||
r(a,function(d,e){"$"!=e.charAt(0)&&(b[e]&&b[e]!==d&&(d+=("style"===e?";":" ")+b[e]),a.$set(e,d,!0,c[e]))});r(b,function(b,f){"class"==f?(M(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 G(a,b,c,d,e,f,g,h){var k=[],l,s,p=b[0],n=a.shift(),w=C({},n,{templateUrl:null,transclude:null,replace:null,$$originalDirective:n}),N=F(n.templateUrl)?n.templateUrl(b,
|
||||
c):n.templateUrl,t=n.templateNamespace;b.empty();q(O.getTrustedResourceUrl(N)).then(function(q){var v,O;q=Pc(q);if(n.replace){q=Pb.test(q)?Qc(U(t,P(q))):[];v=q[0];if(1!=q.length||v.nodeType!==na)throw ka("tplrt",n.name,N);q={$attr:{}};Ab(d,b,v);var H=W(v,[],q);K(n.scope)&&y(H);a=H.concat(a);Oc(c,q)}else v=p,b.html(q);a.unshift(w);l=aa(a,v,c,e,b,n,f,g,h);r(d,function(a,c){a==v&&(d[c]=b[0])});for(s=ea(b[0].childNodes,e);k.length;){q=k.shift();O=k.shift();var E=k.shift(),B=k.shift(),H=b[0];if(!q.$$destroyed){if(O!==
|
||||
p){var Q=O.className;h.hasElementTranscludeDirective&&n.replace||(H=Rb(v));Ab(E,A(O),H);M(A(H),Q)}O=l.transcludeOnThisElement?L(q,l.transclude,B):B;l(s,q,H,d,O)}}k=null});return function(a,b,c,d,e){a=e;b.$$destroyed||(k?k.push(b,c,d,a):(l.transcludeOnThisElement&&(a=L(b,l.transclude,e)),l(s,b,c,d,a)))}}function z(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 ya(a,b,c,d){if(b)throw ka("multidir",b.name,c.name,a,va(d));}function T(a,c){var d=
|
||||
b(c,!0);d&&a.push({priority:0,compile:function(a){a=a.parent();var b=!!a.length;b&&B.$$addBindingClass(a);return function(a,c){var e=c.parent();b||B.$$addBindingClass(e);B.$$addBindingInfo(e,d.expressions);a.$watch(d,function(a){c[0].nodeValue=a})}}})}function U(a,b){a=R(a||"html");switch(a){case "svg":case "math":var c=V.createElement("div");c.innerHTML="<"+a+">"+b+"</"+a+">";return c.childNodes[0].childNodes;default:return b}}function Ga(a,b){if("srcdoc"==b)return O.HTML;var c=ta(a);if("xlinkHref"==
|
||||
b||"form"==c&&"action"==b||"img"!=c&&("src"==b||"ngSrc"==b))return O.RESOURCE_URL}function S(a,c,d,e,f){var h=b(d,!0);if(h){if("multiple"===e&&"select"===ta(a))throw ka("selmulti",va(a));c.push({priority:100,compile:function(){return{pre:function(c,d,l){d=l.$$observers||(l.$$observers={});if(k.test(e))throw ka("nodomevents");l[e]&&(h=b(l[e],!0,Ga(a,e),g[e]||f))&&(l[e]=h(c),(d[e]||(d[e]=[])).$$inter=!0,(l.$$observers&&l.$$observers[e].$$scope||c).$watch(h,function(a,b){"class"===e&&a!=b?l.$updateClass(a,
|
||||
b):l.$set(e,a)}))}}}})}}function Ab(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=V.createDocumentFragment();a.appendChild(d);A(c).data(A(d).data());qa?(Nb=!0,qa.cleanData([d])):delete A.cache[d[A.expando]];d=1;for(e=b.length;d<e;d++)f=b[d],A(f).remove(),a.appendChild(f),delete b[d];b[0]=c;b.length=1}function Y(a,
|
||||
b){return C(function(){return a.apply(null,arguments)},a,b)}function Z(a,b,d,e,f,g){try{a(b,d,e,f,g)}catch(h){c(h,va(d))}}var X=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};X.prototype={$normalize:wa,$addClass:function(a){a&&0<a.length&&E.addClass(this.$$element,a)},$removeClass:function(a){a&&0<a.length&&E.removeClass(this.$$element,a)},$updateClass:function(a,b){var c=Rc(a,b);c&&c.length&&E.addClass(this.$$element,
|
||||
c);(c=Rc(b,a))&&c.length&&E.removeClass(this.$$element,c)},$set:function(a,b,d,e){var f=this.$$element[0],g=Jc(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=Mb(a,"-"));g=ta(this.$$element);if("a"===g&&"href"===a||"img"===g&&"src"===a)this[a]=b=H(b,"src"===a);else if("img"===g&&"srcset"===a){for(var g="",h=P(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 q=2*l,g=g+H(P(h[q]),!0),g=g+(" "+P(h[q+1]));h=P(h[2*l]).split(/\s/);g+=H(P(h[0]),!0);2===h.length&&(g+=" "+P(h[1]));this[a]=b=g}!1!==d&&(null===b||b===u?this.$$element.removeAttr(e):this.$$element.attr(e,b));(a=this.$$observers)&&r(a[f],function(a){try{a(b)}catch(d){c(d)}})},$observe:function(a,b){var c=this,d=c.$$observers||(c.$$observers=ia()),e=d[a]||(d[a]=[]);e.push(b);v.$evalAsync(function(){!e.$$inter&&c.hasOwnProperty(a)&&b(c[a])});return function(){Va(e,b)}}};var Na=b.startSymbol(),
|
||||
ga=b.endSymbol(),Pc="{{"==Na||"}}"==ga?oa:function(a){return a.replace(/\{\{/g,Na).replace(/}}/g,ga)},za=/^ngAttr[A-Z]/;B.$$addBindingInfo=l?function(a,b){var c=a.data("$binding")||[];D(b)?c=c.concat(b):c.push(b);a.data("$binding",c)}:x;B.$$addBindingClass=l?function(a){M(a,"ng-binding")}:x;B.$$addScopeInfo=l?function(a,b,c,d){a.data(c?d?"$isolateScopeNoTemplate":"$isolateScope":"$scope",b)}:x;B.$$addScopeClass=l?function(a,b){M(a,b?"ng-isolate-scope":"ng-scope")}:x;return B}]}function wa(b){return bb(b.replace(nf,
|
||||
""))}function Rc(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 Qc(b){b=A(b);var a=b.length;if(1>=a)return b;for(;a--;)8===b[a].nodeType&&of.call(b,a,1);return b}function Ce(){var b={},a=!1,c=/^(\S+)(\s+as\s+(\w+))?$/;this.register=function(a,c){La(a,"controller");K(a)?C(b,a):b[a]=c};this.allowGlobals=function(){a=!0};this.$get=["$injector","$window",function(d,e){function f(a,
|
||||
b,c,d){if(!a||!K(a.$scope))throw z("$controller")("noscp",d,b);a.$scope[b]=c}return function(g,h,k,l){var m,p,s;k=!0===k;l&&I(l)&&(s=l);I(g)&&(l=g.match(c),p=l[1],s=s||l[3],g=b.hasOwnProperty(p)?b[p]:tc(h.$scope,p,!0)||(a?tc(e,p,!0):u),pb(g,p,!0));if(k)return k=(D(g)?g[g.length-1]:g).prototype,m=Object.create(k),s&&f(h,s,m,p||g.name),C(function(){d.invoke(g,m,h,p);return m},{instance:m,identifier:s});m=d.instantiate(g,h,p);s&&f(h,s,m,p||g.name);return m}}]}function De(){this.$get=["$window",function(b){return A(b.document)}]}
|
||||
function Ee(){this.$get=["$log",function(b){return function(a,c){b.error.apply(b,arguments)}}]}function Yb(b,a){if(I(b)){b=b.replace(pf,"");var c=a("Content-Type");if(c&&0===c.indexOf(Sc)&&b.trim()||qf.test(b)&&rf.test(b))b=oc(b)}return b}function Tc(b){var a=ia(),c,d,e;if(!b)return a;r(b.split("\n"),function(b){e=b.indexOf(":");c=R(P(b.substr(0,e)));d=P(b.substr(e+1));c&&(a[c]=a[c]?a[c]+", "+d:d)});return a}function Uc(b){var a=K(b)?b:u;return function(c){a||(a=Tc(b));return c?(c=a[R(c)],void 0===
|
||||
c&&(c=null),c):a}}function Vc(b,a,c){if(F(c))return c(b,a);r(c,function(c){b=c(b,a)});return b}function He(){var b=this.defaults={transformResponse:[Yb],transformRequest:[function(a){return K(a)&&"[object File]"!==Ja.call(a)&&"[object Blob]"!==Ja.call(a)?Za(a):a}],headers:{common:{Accept:"application/json, text/plain, */*"},post:ua(Zb),put:ua(Zb),patch:ua(Zb)},xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN"},a=!1;this.useApplyAsync=function(b){return y(b)?(a=!!b,this):a};var c=this.interceptors=
|
||||
[];this.$get=["$httpBackend","$browser","$cacheFactory","$rootScope","$q","$injector",function(d,e,f,g,h,k){function l(a){function c(a){var b=C({},a);b.data=a.data?Vc(a.data,a.headers,d.transformResponse):a.data;a=a.status;return 200<=a&&300>a?b:h.reject(b)}var d={method:"get",transformRequest:b.transformRequest,transformResponse:b.transformResponse},e=function(a){var c=b.headers,d=C({},a.headers),e,f,c=C({},c.common,c[R(a.method)]);a:for(e in c){a=R(e);for(f in d)if(R(f)===a)continue a;d[e]=c[e]}(function(a){var b;
|
||||
r(a,function(c,d){F(c)&&(b=c(),null!=b?a[d]=b:delete a[d])})})(d);return d}(a);if(!ha.isObject(a))throw z("$http")("badreq",a);C(d,a);d.headers=e;d.method=rb(d.method);var f=[function(a){e=a.headers;var d=Vc(a.data,Uc(e),a.transformRequest);G(d)&&r(e,function(a,b){"content-type"===R(b)&&delete e[b]});G(a.withCredentials)&&!G(b.withCredentials)&&(a.withCredentials=b.withCredentials);return m(a,d,e).then(c,c)},u],g=h.when(d);for(r(t,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){g.then(function(b){a(b.data,b.status,b.headers,d)});return g};g.error=function(a){g.then(null,function(b){a(b.data,b.status,b.headers,d)});return g};return g}function m(c,f,k){function m(b,c,d,e){function f(){w(c,b,d,e)}M&&(200<=b&&300>b?M.put(r,[b,c,Tc(d),e]):M.remove(r));a?g.$applyAsync(f):(f(),g.$$phase||g.$apply())}function w(a,b,d,e){b=Math.max(b,0);(200<=
|
||||
b&&300>b?E.resolve:E.reject)({data:a,status:b,headers:Uc(d),config:c,statusText:e})}function t(){var a=l.pendingRequests.indexOf(c);-1!==a&&l.pendingRequests.splice(a,1)}var E=h.defer(),H=E.promise,M,B,r=p(c.url,c.params);l.pendingRequests.push(c);H.then(t,t);!c.cache&&!b.cache||!1===c.cache||"GET"!==c.method&&"JSONP"!==c.method||(M=K(c.cache)?c.cache:K(b.cache)?b.cache:s);if(M)if(B=M.get(r),y(B)){if(B&&F(B.then))return B.then(t,t),B;D(B)?w(B[1],B[0],ua(B[2]),B[3]):w(B,200,{},"OK")}else M.put(r,H);
|
||||
G(B)&&((B=Wc(c.url)?e.cookies()[c.xsrfCookieName||b.xsrfCookieName]:u)&&(k[c.xsrfHeaderName||b.xsrfHeaderName]=B),d(c.method,r,f,m,k,c.timeout,c.withCredentials,c.responseType));return H}function p(a,b){if(!b)return a;var c=[];Bd(b,function(a,b){null===a||G(a)||(D(a)||(a=[a]),r(a,function(a){K(a)&&(a=fa(a)?a.toISOString():Za(a));c.push(Da(b)+"="+Da(a))}))});0<c.length&&(a+=(-1==a.indexOf("?")?"?":"&")+c.join("&"));return a}var s=f("$http"),t=[];r(c,function(a){t.unshift(I(a)?k.get(a):k.invoke(a))});
|
||||
l.pendingRequests=[];(function(a){r(arguments,function(a){l[a]=function(b,c){return l(C(c||{},{method:a,url:b}))}})})("get","delete","head","jsonp");(function(a){r(arguments,function(a){l[a]=function(b,c,d){return l(C(d||{},{method:a,url:b,data:c}))}})})("post","put","patch");l.defaults=b;return l}]}function sf(){return new U.XMLHttpRequest}function Ie(){this.$get=["$browser","$window","$document",function(b,a,c){return tf(b,sf,b.defer,a.angular.callbacks,c[0])}]}function tf(b,a,c,d,e){function f(a,
|
||||
b,c){var f=e.createElement("script"),m=null;f.type="text/javascript";f.src=a;f.async=!0;m=function(a){f.removeEventListener("load",m,!1);f.removeEventListener("error",m,!1);e.body.removeChild(f);f=null;var g=-1,t="unknown";a&&("load"!==a.type||d[b].called||(a={type:"error"}),t=a.type,g="error"===a.type?404:200);c&&c(g,t)};f.addEventListener("load",m,!1);f.addEventListener("error",m,!1);e.body.appendChild(f);return m}return function(e,h,k,l,m,p,s,t){function q(){v&&v();w&&w.abort()}function N(a,d,
|
||||
e,f,g){E&&c.cancel(E);v=w=null;a(d,e,f,g);b.$$completeOutstandingRequest(x)}b.$$incOutstandingRequestCount();h=h||b.url();if("jsonp"==R(e)){var n="_"+(d.counter++).toString(36);d[n]=function(a){d[n].data=a;d[n].called=!0};var v=f(h.replace("JSON_CALLBACK","angular.callbacks."+n),n,function(a,b){N(l,a,d[n].data,"",b);d[n]=x})}else{var w=a();w.open(e,h,!0);r(m,function(a,b){y(a)&&w.setRequestHeader(b,a)});w.onload=function(){var a=w.statusText||"",b="response"in w?w.response:w.responseText,c=1223===
|
||||
w.status?204:w.status;0===c&&(c=b?200:"file"==Aa(h).protocol?404:0);N(l,c,b,w.getAllResponseHeaders(),a)};e=function(){N(l,-1,null,null,"")};w.onerror=e;w.onabort=e;s&&(w.withCredentials=!0);if(t)try{w.responseType=t}catch(O){if("json"!==t)throw O;}w.send(k||null)}if(0<p)var E=c(q,p);else p&&F(p.then)&&p.then(q)}}function Fe(){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(f,g,t,q){function N(c){return c.replace(l,b).replace(m,a)}function n(a){try{var b=a;a=t?e.getTrusted(t,b):e.valueOf(b);var c;if(q&&!y(a))c=a;else if(null==a)c="";else{switch(typeof a){case "string":break;case "number":a=""+a;break;default:a=Za(a)}c=a}return c}catch(g){c=$b("interr",f,g.toString()),d(c)}}q=!!q;for(var v,w,O=0,E=[],H=[],M=f.length,B=[],r=[];O<M;)if(-1!=(v=f.indexOf(b,O))&&-1!=(w=f.indexOf(a,v+h)))O!==v&&B.push(N(f.substring(O,v))),O=f.substring(v+
|
||||
h,w),E.push(O),H.push(c(O,n)),O=w+k,r.push(B.length),B.push("");else{O!==M&&B.push(N(f.substring(O)));break}if(t&&1<B.length)throw $b("noconcat",f);if(!g||E.length){var L=function(a){for(var b=0,c=E.length;b<c;b++){if(q&&G(a[b]))return;B[r[b]]=a[b]}return B.join("")};return C(function(a){var b=0,c=E.length,e=Array(c);try{for(;b<c;b++)e[b]=H[b](a);return L(e)}catch(g){a=$b("interr",f,g.toString()),d(a)}},{exp:f,expressions:E,$$watchDelegate:function(a,b,c){var d;return a.$watchGroup(H,function(c,e){var f=
|
||||
L(c);F(b)&&b.call(this,f,c!==e?d:f,a);d=f},c)}})}}var h=b.length,k=a.length,l=new RegExp(b.replace(/./g,f),"g"),m=new RegExp(a.replace(/./g,f),"g");g.startSymbol=function(){return b};g.endSymbol=function(){return a};return g}]}function Ge(){this.$get=["$rootScope","$window","$q","$$q",function(b,a,c,d){function e(e,h,k,l){var m=a.setInterval,p=a.clearInterval,s=0,t=y(l)&&!l,q=(t?d:c).defer(),N=q.promise;k=y(k)?k:0;N.then(null,null,e);N.$$intervalId=m(function(){q.notify(s++);0<k&&s>=k&&(q.resolve(s),
|
||||
p(N.$$intervalId),delete f[N.$$intervalId]);t||b.$apply()},h);f[N.$$intervalId]=q;return N}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 Od(){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"},pluralCat:function(b){return 1===b?"one":"other"}}}}function ac(b){b=b.split("/");for(var a=b.length;a--;)b[a]=nb(b[a]);return b.join("/")}function Xc(b,a){var c=Aa(b);a.$$protocol=c.protocol;a.$$host=c.hostname;a.$$port=$(c.port)||uf[c.protocol]||null}function Yc(b,a){var c="/"!==b.charAt(0);c&&(b="/"+b);var d=Aa(b);a.$$path=decodeURIComponent(c&&"/"===d.pathname.charAt(0)?d.pathname.substring(1):d.pathname);a.$$search=
|
||||
qc(d.search);a.$$hash=decodeURIComponent(d.hash);a.$$path&&"/"!=a.$$path.charAt(0)&&(a.$$path="/"+a.$$path)}function xa(b,a){if(0===a.indexOf(b))return a.substr(b.length)}function Fa(b){var a=b.indexOf("#");return-1==a?b:b.substr(0,a)}function bc(b){return b.substr(0,Fa(b).lastIndexOf("/")+1)}function cc(b,a){this.$$html5=!0;a=a||"";var c=bc(b);Xc(b,this);this.$$parse=function(a){var b=xa(c,a);if(!I(b))throw eb("ipthprfx",a,c);Yc(b,this);this.$$path||(this.$$path="/");this.$$compose()};this.$$compose=
|
||||
function(){var a=Kb(this.$$search),b=this.$$hash?"#"+nb(this.$$hash):"";this.$$url=ac(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=xa(b,d))!==u?(g=f,g=(f=xa(a,f))!==u?c+(xa("/",f)||f):b+g):(f=xa(c,d))!==u?g=c+f:c==d+"/"&&(g=c);g&&this.$$parse(g);return!!g}}function dc(b,a){var c=bc(b);Xc(b,this);this.$$parse=function(d){var e=xa(b,d)||xa(c,d),e="#"==e.charAt(0)?xa(a,e):this.$$html5?e:
|
||||
"";if(!I(e))throw eb("ihshprfx",d,a);Yc(e,this);d=this.$$path;var f=/^\/[A-Z]:(\/.*)/;0===e.indexOf(b)&&(e=e.replace(b,""));f.exec(e)||(d=(e=f.exec(d))?e[1]:d);this.$$path=d;this.$$compose()};this.$$compose=function(){var c=Kb(this.$$search),e=this.$$hash?"#"+nb(this.$$hash):"";this.$$url=ac(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+(this.$$url?a+this.$$url:"")};this.$$parseLinkUrl=function(a,c){return Fa(b)==Fa(a)?(this.$$parse(a),!0):!1}}function Zc(b,a){this.$$html5=!0;dc.apply(this,arguments);
|
||||
var c=bc(b);this.$$parseLinkUrl=function(d,e){if(e&&"#"===e[0])return this.hash(e.slice(1)),!0;var f,g;b==Fa(d)?f=d:(g=xa(c,d))?f=b+a+g:c===d+"/"&&(f=c);f&&this.$$parse(f);return!!f};this.$$compose=function(){var c=Kb(this.$$search),e=this.$$hash?"#"+nb(this.$$hash):"";this.$$url=ac(this.$$path)+(c?"?"+c:"")+e;this.$$absUrl=b+a+this.$$url}}function Bb(b){return function(){return this[b]}}function $c(b,a){return function(c){if(G(c))return this[b];this[b]=a(c);this.$$compose();return this}}function Je(){var b=
|
||||
"",a={enabled:!1,requireBase:!0,rewriteLinks:!0};this.hashPrefix=function(a){return y(a)?(b=a,this):b};this.html5Mode=function(b){return Ua(b)?(a.enabled=b,this):K(b)?(Ua(b.enabled)&&(a.enabled=b.enabled),Ua(b.requireBase)&&(a.requireBase=b.requireBase),Ua(b.rewriteLinks)&&(a.rewriteLinks=b.rewriteLinks),this):a};this.$get=["$rootScope","$browser","$sniffer","$rootElement",function(c,d,e,f){function g(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 h(a,b){c.$broadcast("$locationChangeSuccess",k.absUrl(),a,k.$$state,b)}var k,l;l=d.baseHref();var m=d.url(),p;if(a.enabled){if(!l&&a.requireBase)throw eb("nobase");p=m.substring(0,m.indexOf("/",m.indexOf("//")+2))+(l||"/");l=e.history?cc:Zc}else p=Fa(m),l=dc;k=new l(p,"#"+b);k.$$parseLinkUrl(m,m);k.$$state=d.state();var s=/^\s*(javascript|mailto):/i;f.on("click",function(b){if(a.rewriteLinks&&!b.ctrlKey&&!b.metaKey&&2!=b.which){for(var e=A(b.target);"a"!==ta(e[0]);)if(e[0]===f[0]||
|
||||
!(e=e.parent())[0])return;var g=e.prop("href"),h=e.attr("href")||e.attr("xlink:href");K(g)&&"[object SVGAnimatedString]"===g.toString()&&(g=Aa(g.animVal).href);s.test(g)||!g||e.attr("target")||b.isDefaultPrevented()||!k.$$parseLinkUrl(g,h)||(b.preventDefault(),k.absUrl()!=d.url()&&(c.$apply(),U.angular["ff-684208-preventDefault"]=!0))}});k.absUrl()!=m&&d.url(k.absUrl(),!0);var t=!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,g(d,!1,e)):(t=!1,h(d,e)))});c.$$phase||c.$digest()});c.$watch(function(){var a=d.url(),b=d.state(),f=k.$$replace,l=a!==k.absUrl()||k.$$html5&&e.history&&b!==k.$$state;if(t||l)t=!1,c.$evalAsync(function(){var d=k.absUrl(),e=c.$broadcast("$locationChangeStart",d,a,k.$$state,b).defaultPrevented;k.absUrl()===d&&(e?(k.$$parse(a),k.$$state=b):(l&&g(d,f,b===k.$$state?null:k.$$state),h(a,b)))});k.$$replace=!1});return k}]}function Ke(){var b=
|
||||
!0,a=this;this.debugEnabled=function(a){return y(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||x;a=!1;try{a=!!e.apply}catch(k){}return a?function(){var a=[];r(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 ra(b,a){if("__defineGetter__"===b||"__defineSetter__"===b||"__lookupGetter__"===b||"__lookupSetter__"===b||"__proto__"===b)throw la("isecfld",a);return b}function sa(b,a){if(b){if(b.constructor===b)throw la("isecfn",a);if(b.window===b)throw la("isecwindow",a);if(b.children&&(b.nodeName||b.prop&&b.attr&&b.find))throw la("isecdom",a);if(b===Object)throw la("isecobj",
|
||||
a);}return b}function ec(b){return b.constant}function Oa(b,a,c,d){sa(b,d);a=a.split(".");for(var e,f=0;1<a.length;f++){e=ra(a.shift(),d);var g=sa(b[e],d);g||(g={},b[e]=g);b=g}e=ra(a.shift(),d);sa(b[e],d);return b[e]=c}function Pa(b){return"constructor"==b}function ad(b,a,c,d,e,f,g){ra(b,f);ra(a,f);ra(c,f);ra(d,f);ra(e,f);var h=function(a){return sa(a,f)},k=g||Pa(b)?h:oa,l=g||Pa(a)?h:oa,m=g||Pa(c)?h:oa,p=g||Pa(d)?h:oa,s=g||Pa(e)?h:oa;return function(f,g){var h=g&&g.hasOwnProperty(b)?g:f;if(null==
|
||||
h)return h;h=k(h[b]);if(!a)return h;if(null==h)return u;h=l(h[a]);if(!c)return h;if(null==h)return u;h=m(h[c]);if(!d)return h;if(null==h)return u;h=p(h[d]);return e?null==h?u:h=s(h[e]):h}}function vf(b,a){return function(c,d){return b(c,d,sa,a)}}function bd(b,a,c){var d=a.expensiveChecks,e=d?wf:xf,f=e[b];if(f)return f;var g=b.split("."),h=g.length;if(a.csp)f=6>h?ad(g[0],g[1],g[2],g[3],g[4],c,d):function(a,b){var e=0,f;do f=ad(g[e++],g[e++],g[e++],g[e++],g[e++],c,d)(a,b),b=u,a=f;while(e<h);return f};
|
||||
else{var k="";d&&(k+="s = eso(s, fe);\nl = eso(l, fe);\n");var l=d;r(g,function(a,b){ra(a,c);var e=(b?"s":'((l&&l.hasOwnProperty("'+a+'"))?l:s)')+"."+a;if(d||Pa(a))e="eso("+e+", fe)",l=!0;k+="if(s == null) return undefined;\ns="+e+";\n"});k+="return s;";a=new Function("s","l","eso","fe",k);a.toString=ca(k);l&&(a=vf(a,c));f=a}f.sharedGetter=!0;f.assign=function(a,c){return Oa(a,b,c,b)};return e[b]=f}function fc(b){return F(b.valueOf)?b.valueOf():yf.call(b)}function Le(){var b=ia(),a=ia();this.$get=
|
||||
["$filter","$sniffer",function(c,d){function e(a){var b=a;a.sharedGetter&&(b=function(b,c){return a(b,c)},b.literal=a.literal,b.constant=a.constant,b.assign=a.assign);return b}function f(a,b){for(var c=0,d=a.length;c<d;c++){var e=a[c];e.constant||(e.inputs?f(e.inputs,b):-1===b.indexOf(e)&&b.push(e))}return b}function g(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 h(a,b,c,d){var e=d.$$inputs||(d.$$inputs=f(d.inputs,[])),h;if(1===
|
||||
e.length){var k=g,e=e[0];return a.$watch(function(a){var b=e(a);g(b,k)||(h=d(a),k=b&&fc(b));return h},b,c)}for(var l=[],s=0,m=e.length;s<m;s++)l[s]=g;return a.$watch(function(a){for(var b=!1,c=0,f=e.length;c<f;c++){var k=e[c](a);if(b||(b=!g(k,l[c])))l[c]=k&&fc(k)}b&&(h=d(a));return h},b,c)}function k(a,b,c,d){var e,f;return e=a.$watch(function(a){return d(a)},function(a,c,d){f=a;F(b)&&b.apply(this,arguments);y(a)&&d.$$postDigest(function(){y(f)&&e()})},c)}function l(a,b,c,d){function e(a){var b=!0;
|
||||
r(a,function(a){y(a)||(b=!1)});return b}var f,g;return f=a.$watch(function(a){return d(a)},function(a,c,d){g=a;F(b)&&b.call(this,a,c,d);e(a)&&d.$$postDigest(function(){e(g)&&f()})},c)}function m(a,b,c,d){var e;return e=a.$watch(function(a){return d(a)},function(a,c,d){F(b)&&b.apply(this,arguments);e()},c)}function p(a,b){if(!b)return a;var c=a.$$watchDelegate,c=c!==l&&c!==k?function(c,d){var e=a(c,d);return b(e,c,d)}:function(c,d){var e=a(c,d),f=b(e,c,d);return y(e)?f:e};a.$$watchDelegate&&a.$$watchDelegate!==
|
||||
h?c.$$watchDelegate=a.$$watchDelegate:b.$stateful||(c.$$watchDelegate=h,c.inputs=[a]);return c}var s={csp:d.csp,expensiveChecks:!1},t={csp:d.csp,expensiveChecks:!0};return function(d,f,g){var v,w,O;switch(typeof d){case "string":O=d=d.trim();var E=g?a:b;v=E[O];v||(":"===d.charAt(0)&&":"===d.charAt(1)&&(w=!0,d=d.substring(2)),g=g?t:s,v=new gc(g),v=(new fb(v,c,g)).parse(d),v.constant?v.$$watchDelegate=m:w?(v=e(v),v.$$watchDelegate=v.literal?l:k):v.inputs&&(v.$$watchDelegate=h),E[O]=v);return p(v,f);
|
||||
case "function":return p(d,f);default:return p(x,f)}}}]}function Ne(){this.$get=["$rootScope","$exceptionHandler",function(b,a){return cd(function(a){b.$evalAsync(a)},a)}]}function Oe(){this.$get=["$browser","$exceptionHandler",function(b,a){return cd(function(a){b.defer(a)},a)}]}function cd(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=u;for(var f=0,g=e.length;f<g;++f){d=e[f][0];b=e[f][c.status];try{F(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=z("$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 l(b,!0,a)},function(b){return l(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(K(b)||F(b))d=b&&b.then;F(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(F(b)?
|
||||
b(c):c)}catch(h){a(h)}}})}};var k=function(a,b){var c=new g;b?c.resolve(a):c.reject(a);return c.promise},l=function(a,b,c){var d=null;try{F(c)&&(d=c())}catch(e){return k(e,!1)}return d&&F(d.then)?d.then(function(){return k(a,b)},function(a){return k(a,!1)}):k(a,b)},m=function(a,b,c,d){var e=new g;e.resolve(a);return e.promise.then(b,c,d)},p=function t(a){if(!F(a))throw h("norslvr",a);if(!(this instanceof t))return new t(a);var b=new g;a(function(a){b.resolve(a)},function(a){b.reject(a)});return b.promise};
|
||||
p.defer=function(){return new g};p.reject=function(a){var b=new g;b.reject(a);return b.promise};p.when=m;p.all=function(a){var b=new g,c=0,d=D(a)?[]:{};r(a,function(a,e){c++;m(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 p}function Xe(){this.$get=["$window","$timeout",function(b,a){var c=b.requestAnimationFrame||b.webkitRequestAnimationFrame||b.mozRequestAnimationFrame,d=b.cancelAnimationFrame||
|
||||
b.webkitCancelAnimationFrame||b.mozCancelAnimationFrame||b.webkitCancelRequestAnimationFrame,e=!!c,f=e?function(a){var b=c(a);return function(){d(b)}}:function(b){var c=a(b,16.66,!1);return function(){a.cancel(c)}};f.supported=e;return f}]}function Me(){var b=10,a=z("$rootScope"),c=null,d=null;this.digestTtl=function(a){arguments.length&&(b=a);return b};this.$get=["$injector","$exceptionHandler","$parse","$browser",function(e,f,g,h){function k(){this.$id=++kb;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.$$isolateBindings=null}function l(b){if(q.$$phase)throw a("inprog",q.$$phase);q.$$phase=b}function m(a,b,c){do a.$$listenerCount[c]-=b,0===a.$$listenerCount[c]&&delete a.$$listenerCount[c];while(a=a.$parent)}function p(){}function s(){for(;v.length;)try{v.shift()()}catch(a){f(a)}d=null}function t(){null===d&&(d=h.defer(function(){q.$apply(s)}))}
|
||||
k.prototype={constructor:k,$new:function(a,b){function c(){d.$$destroyed=!0}var d;b=b||this;a?(d=new k,d.$root=this.$root):(this.$$ChildScope||(this.$$ChildScope=function(){this.$$watchers=this.$$nextSibling=this.$$childHead=this.$$childTail=null;this.$$listeners={};this.$$listenerCount={};this.$id=++kb;this.$$ChildScope=null},this.$$ChildScope.prototype=this),d=new this.$$ChildScope);d.$parent=b;d.$$prevSibling=b.$$childTail;b.$$childHead?(b.$$childTail.$$nextSibling=d,b.$$childTail=d):b.$$childHead=
|
||||
b.$$childTail=d;(a||b!=this)&&d.$on("$destroy",c);return d},$watch:function(a,b,d){var e=g(a);if(e.$$watchDelegate)return e.$$watchDelegate(this,b,d,e);var f=this.$$watchers,h={fn:b,last:p,get:e,exp:a,eq:!!d};c=null;F(b)||(h.fn=x);f||(f=this.$$watchers=[]);f.unshift(h);return function(){Va(f,h);c=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)});r(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(!G(e)){if(K(e))if(Ra(e))for(f!==p&&(f=p,n=f.length=0,l++),a=e.length,n!==a&&(l++,f.length=n=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={},n=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)):(n++,f[b]=g,l++));if(n>a)for(b in l++,f)e.hasOwnProperty(b)||(n--,delete f[b])}else f!==e&&(f=e,l++);return l}}c.$stateful=!0;var d=this,e,f,h,k=1<b.length,l=0,m=g(a,c),p=[],s={},q=!0,n=0;return this.$watch(m,function(){q?(q=!1,b(e,e,d)):b(e,h,d);if(k)if(K(e))if(Ra(e)){h=Array(e.length);for(var a=0;a<e.length;a++)h[a]=e[a]}else for(a in h={},e)Jb.call(e,a)&&(h[a]=e[a]);else h=e})},$digest:function(){var e,g,k,m,t,v,r=b,L,u=[],y,Q;l("$digest");
|
||||
h.$$checkUrlChange();this===q&&null!==d&&(h.defer.cancel(d),s());c=null;do{v=!1;for(L=this;N.length;){try{Q=N.shift(),Q.scope.$eval(Q.expression)}catch(z){f(z)}c=null}a:do{if(m=L.$$watchers)for(t=m.length;t--;)try{if(e=m[t])if((g=e.get(L))!==(k=e.last)&&!(e.eq?pa(g,k):"number"===typeof g&&"number"===typeof k&&isNaN(g)&&isNaN(k)))v=!0,c=e,e.last=e.eq?Ca(g,null):g,e.fn(g,k===p?g:k,L),5>r&&(y=4-r,u[y]||(u[y]=[]),u[y].push({msg:F(e.exp)?"fn: "+(e.exp.name||e.exp.toString()):e.exp,newVal:g,oldVal:k}));
|
||||
else if(e===c){v=!1;break a}}catch(A){f(A)}if(!(m=L.$$childHead||L!==this&&L.$$nextSibling))for(;L!==this&&!(m=L.$$nextSibling);)L=L.$parent}while(L=m);if((v||N.length)&&!r--)throw q.$$phase=null,a("infdig",b,u);}while(v||N.length);for(q.$$phase=null;n.length;)try{n.shift()()}catch(da){f(da)}},$destroy:function(){if(!this.$$destroyed){var a=this.$parent;this.$broadcast("$destroy");this.$$destroyed=!0;if(this!==q){for(var b in this.$$listenerCount)m(this,this.$$listenerCount[b],b);a.$$childHead==this&&
|
||||
(a.$$childHead=this.$$nextSibling);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=x;this.$on=this.$watch=this.$watchGroup=function(){return x};this.$$listeners={};this.$parent=this.$$nextSibling=this.$$prevSibling=this.$$childHead=this.$$childTail=this.$root=this.$$watchers=
|
||||
null}}},$eval:function(a,b){return g(a)(this,b)},$evalAsync:function(a){q.$$phase||N.length||h.defer(function(){N.length&&q.$digest()});N.push({scope:this,expression:a})},$$postDigest:function(a){n.push(a)},$apply:function(a){try{return l("$apply"),this.$eval(a)}catch(b){f(b)}finally{q.$$phase=null;try{q.$digest()}catch(c){throw f(c),c;}}},$applyAsync:function(a){function b(){c.$eval(a)}var c=this;a&&v.push(b);t()},$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,m(e,1,a))}},$emit:function(a,b){var c=[],d,e=this,g=!1,h={name:a,targetScope:e,stopPropagation:function(){g=!0},preventDefault:function(){h.defaultPrevented=!0},defaultPrevented:!1},k=Xa([h],arguments,1),l,m;do{d=e.$$listeners[a]||c;h.currentScope=e;l=0;for(m=d.length;l<m;l++)if(d[l])try{d[l].apply(null,k)}catch(p){f(p)}else d.splice(l,
|
||||
1),l--,m--;if(g)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 g=Xa([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,g)}catch(l){f(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 q=new k,N=q.$$asyncQueue=[],n=q.$$postDigestQueue=[],v=q.$$applyAsyncQueue=[];return q}]}function Pd(){var b=/^\s*(https?|ftp|mailto|tel|file):/,a=/^\s*((https?|ftp|file|blob):|data:image\/)/;this.aHrefSanitizationWhitelist=function(a){return y(a)?(b=a,this):b};this.imgSrcSanitizationWhitelist=function(b){return y(b)?(a=b,this):a};this.$get=function(){return function(c,d){var e=d?a:b,f;f=Aa(c).href;
|
||||
return""===f||f.match(e)?c:"unsafe:"+f}}}function zf(b){if("self"===b)return b;if(I(b)){if(-1<b.indexOf("***"))throw Ba("iwcard",b);b=dd(b).replace("\\*\\*",".*").replace("\\*","[^:/.?&;]*");return new RegExp("^"+b+"$")}if(lb(b))return new RegExp("^"+b.source+"$");throw Ba("imatcher");}function ed(b){var a=[];y(b)&&r(b,function(b){a.push(zf(b))});return a}function Qe(){this.SCE_CONTEXTS=ma;var b=["self"],a=[];this.resourceUrlWhitelist=function(a){arguments.length&&(b=ed(a));return b};this.resourceUrlBlacklist=
|
||||
function(b){arguments.length&&(a=ed(b));return a};this.$get=["$injector",function(c){function d(a,b){return"self"===a?Wc(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 Ba("unsafe");};c.has("$sanitize")&&(f=c.get("$sanitize"));var g=e(),h={};h[ma.HTML]=
|
||||
e(g);h[ma.CSS]=e(g);h[ma.URL]=e(g);h[ma.JS]=e(g);h[ma.RESOURCE_URL]=e(h[ma.URL]);return{trustAs:function(a,b){var c=h.hasOwnProperty(a)?h[a]:null;if(!c)throw Ba("icontext",a,b);if(null===b||b===u||""===b)return b;if("string"!==typeof b)throw Ba("itype",a);return new c(b)},getTrusted:function(c,e){if(null===e||e===u||""===e)return e;var g=h.hasOwnProperty(c)?h[c]:null;if(g&&e instanceof g)return e.$$unwrapTrustedValue();if(c===ma.RESOURCE_URL){var g=Aa(e.toString()),p,s,t=!1;p=0;for(s=b.length;p<s;p++)if(d(b[p],
|
||||
g)){t=!0;break}if(t)for(p=0,s=a.length;p<s;p++)if(d(a[p],g)){t=!1;break}if(t)return e;throw Ba("insecurl",e.toString());}if(c===ma.HTML)return f(e);throw Ba("unsafe");},valueOf:function(a){return a instanceof g?a.$$unwrapTrustedValue():a}}}]}function Pe(){var b=!0;this.enabled=function(a){arguments.length&&(b=!!a);return b};this.$get=["$parse","$sceDelegate",function(a,c){if(b&&8>Ha)throw Ba("iequirks");var d=ua(ma);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=oa);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;r(ma,function(a,b){var c=R(b);d[bb("parse_as_"+c)]=function(b){return e(a,b)};d[bb("get_trusted_"+c)]=function(b){return f(a,b)};d[bb("trust_as_"+c)]=function(b){return g(a,b)}});return d}]}function Re(){this.$get=["$window","$document",function(b,a){var c={},d=$((/android (\d+)/.exec(R((b.navigator||
|
||||
{}).userAgent))||[])[1]),e=/Boxee/i.test((b.navigator||{}).userAgent),f=a[0]||{},g,h=/^(Moz|webkit|ms)(?=[A-Z])/,k=f.body&&f.body.style,l=!1,m=!1;if(k){for(var p in k)if(l=h.exec(p)){g=l[0];g=g.substr(0,1).toUpperCase()+g.substr(1);break}g||(g="WebkitOpacity"in k&&"webkit");l=!!("transition"in k||g+"Transition"in k);m=!!("animation"in k||g+"Animation"in k);!d||l&&m||(l=I(f.body.style.webkitTransition),m=I(f.body.style.webkitAnimation))}return{history:!(!b.history||!b.history.pushState||4>d||e),hasEvent:function(a){if("input"==
|
||||
a&&9==Ha)return!1;if(G(c[a])){var b=f.createElement("div");c[a]="on"+a in b}return c[a]},csp:$a(),vendorPrefix:g,transitions:l,animations:m,android:d}}]}function Te(){this.$get=["$templateCache","$http","$q",function(b,a,c){function d(e,f){d.totalPendingRequests++;var g=a.defaults&&a.defaults.transformResponse;if(D(g))for(var h=g,g=[],k=0;k<h.length;++k){var l=h[k];l!==Yb&&g.push(l)}else g===Yb&&(g=null);return a.get(e,{cache:b,transformResponse:g}).then(function(a){a=a.data;d.totalPendingRequests--;
|
||||
b.put(e,a);return a},function(){d.totalPendingRequests--;if(!f)throw ka("tpload",e);return c.reject()})}d.totalPendingRequests=0;return d}]}function Ue(){this.$get=["$rootScope","$browser","$location",function(b,a,c){return{findBindings:function(a,b,c){a=a.getElementsByClassName("ng-binding");var g=[];r(a,function(a){var d=ha.element(a).data("$binding");d&&r(d,function(d){c?(new RegExp("(^|\\s)"+dd(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 k=a.querySelectorAll("["+g[h]+"model"+(c?"=":"*=")+'"'+b+'"]');if(k.length)return k}},getLocation:function(){return c.url()},setLocation:function(a){a!==c.url()&&(c.url(a),b.$digest())},whenStable:function(b){a.notifyWhenNoOutstandingRequests(b)}}}]}function Ve(){this.$get=["$rootScope","$browser","$q","$$q","$exceptionHandler",function(b,a,c,d,e){function f(f,k,l){var m=y(l)&&!l,p=(m?d:c).defer(),s=p.promise;k=a.defer(function(){try{p.resolve(f())}catch(a){p.reject(a),
|
||||
e(a)}finally{delete g[s.$$timeoutId]}m||b.$apply()},k);s.$$timeoutId=k;g[k]=p;return s}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 Aa(b){Ha&&(Y.setAttribute("href",b),b=Y.href);Y.setAttribute("href",b);return{href:Y.href,protocol:Y.protocol?Y.protocol.replace(/:$/,""):"",host:Y.host,search:Y.search?Y.search.replace(/^\?/,""):"",hash:Y.hash?Y.hash.replace(/^#/,""):"",hostname:Y.hostname,
|
||||
port:Y.port,pathname:"/"===Y.pathname.charAt(0)?Y.pathname:"/"+Y.pathname}}function Wc(b){b=I(b)?Aa(b):b;return b.protocol===fd.protocol&&b.host===fd.host}function We(){this.$get=ca(U)}function Bc(b){function a(c,d){if(K(c)){var e={};r(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",gd);a("date",hd);a("filter",Af);a("json",Bf);a("limitTo",Cf);a("lowercase",Df);a("number",
|
||||
id);a("orderBy",jd);a("uppercase",Ef)}function Af(){return function(b,a,c){if(!D(b))return b;var d=typeof c,e=[];e.check=function(a,b){for(var c=0;c<e.length;c++)if(!e[c](a,b))return!1;return!0};"function"!==d&&(c="boolean"===d&&c?function(a,b){return ha.equals(a,b)}:function(a,b){if(a&&b&&"object"===typeof a&&"object"===typeof b){for(var d in a)if("$"!==d.charAt(0)&&Jb.call(a,d)&&c(a[d],b[d]))return!0;return!1}b=(""+b).toLowerCase();return-1<(""+a).toLowerCase().indexOf(b)});var f=function(a,b){if("string"===
|
||||
typeof b&&"!"===b.charAt(0))return!f(a,b.substr(1));switch(typeof a){case "boolean":case "number":case "string":return c(a,b);case "object":switch(typeof b){case "object":return c(a,b);default:for(var d in a)if("$"!==d.charAt(0)&&f(a[d],b))return!0}return!1;case "array":for(d=0;d<a.length;d++)if(f(a[d],b))return!0;return!1;default:return!1}};switch(typeof a){case "boolean":case "number":case "string":a={$:a};case "object":for(var g in a)(function(b){"undefined"!==typeof a[b]&&e.push(function(c){return f("$"==
|
||||
b?c:c&&c[b],a[b])})})(g);break;case "function":e.push(a);break;default:return b}d=[];for(g=0;g<b.length;g++){var h=b[g];e.check(h,g)&&d.push(h)}return d}}function gd(b){var a=b.NUMBER_FORMATS;return function(b,d,e){G(d)&&(d=a.CURRENCY_SYM);G(e)&&(e=a.PATTERNS[1].maxFrac);return null==b?b:kd(b,a.PATTERNS[1],a.GROUP_SEP,a.DECIMAL_SEP,e).replace(/\u00A4/g,d)}}function id(b){var a=b.NUMBER_FORMATS;return function(b,d){return null==b?b:kd(b,a.PATTERNS[0],a.GROUP_SEP,a.DECIMAL_SEP,d)}}function kd(b,a,c,
|
||||
d,e){if(!isFinite(b)||K(b))return"";var f=0>b;b=Math.abs(b);var g=b+"",h="",k=[],l=!1;if(-1!==g.indexOf("e")){var m=g.match(/([\d\.]+)e(-?)(\d+)/);m&&"-"==m[2]&&m[3]>e+1?(g="0",b=0):(h=g,l=!0)}if(l)0<e&&-1<b&&1>b&&(h=b.toFixed(e));else{g=(g.split(ld)[1]||"").length;G(e)&&(e=Math.min(Math.max(a.minFrac,g),a.maxFrac));b=+(Math.round(+(b.toString()+"e"+e)).toString()+"e"+-e);0===b&&(f=!1);b=(""+b).split(ld);g=b[0];b=b[1]||"";var m=0,p=a.lgSize,s=a.gSize;if(g.length>=p+s)for(m=g.length-p,l=0;l<m;l++)0===
|
||||
(m-l)%s&&0!==l&&(h+=c),h+=g.charAt(l);for(l=m;l<g.length;l++)0===(g.length-l)%p&&0!==l&&(h+=c),h+=g.charAt(l);for(;b.length<e;)b+="0";e&&"0"!==e&&(h+=d+b.substr(0,e))}k.push(f?a.negPre:a.posPre,h,f?a.negSuf:a.posSuf);return k.join("")}function Cb(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 Z(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 Cb(e,a,d)}}function Db(b,a){return function(c,
|
||||
d){var e=c["get"+b](),f=rb(a?"SHORT"+b:b);return d[f][e]}}function md(b){var a=(new Date(b,0,1)).getDay();return new Date(b,0,(4>=a?5:12)-a)}function nd(b){return function(a){var c=md(a.getFullYear());a=+new Date(a.getFullYear(),a.getMonth(),a.getDate()+(4-a.getDay()))-+c;a=1+Math.round(a/6048E5);return Cb(a,b)}}function hd(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,k=b[8]?a.setUTCHours:a.setHours;b[9]&&(f=$(b[9]+b[10]),g=$(b[9]+b[11]));
|
||||
h.call(a,$(b[1]),$(b[2])-1,$(b[3]));f=$(b[4]||0)-f;g=$(b[5]||0)-g;h=$(b[6]||0);b=Math.round(1E3*parseFloat("0."+(b[7]||0)));k.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=[],k,l;e=e||"mediumDate";e=b.DATETIME_FORMATS[e]||e;I(c)&&(c=Ff.test(c)?$(c):a(c));X(c)&&(c=new Date(c));if(!fa(c))return c;for(;e;)(l=Gf.exec(e))?(h=Xa(h,l,1),e=h.pop()):(h.push(e),e=null);f&&"UTC"===f&&(c=
|
||||
new Date(c.getTime()),c.setMinutes(c.getMinutes()+c.getTimezoneOffset()));r(h,function(a){k=Hf[a];g+=k?k(c,b.DATETIME_FORMATS):a.replace(/(^'|'$)/g,"").replace(/''/g,"'")});return g}}function Bf(){return function(b){return Za(b,!0)}}function Cf(){return function(b,a){X(b)&&(b=b.toString());if(!D(b)&&!I(b))return b;a=Infinity===Math.abs(Number(a))?Number(a):$(a);if(I(b))return a?0<=a?b.slice(0,a):b.slice(a,b.length):"";var c=[],d,e;a>b.length?a=b.length:a<-b.length&&(a=-b.length);0<a?(d=0,e=a):(d=
|
||||
b.length+a,e=b.length);for(;d<e;d++)c.push(b[d]);return c}}function jd(b){return function(a,c,d){function e(a,b){return b?function(b,c){return a(c,b)}:a}function f(a,b){var c=typeof a,d=typeof b;return c==d?(fa(a)&&fa(b)&&(a=a.valueOf(),b=b.valueOf()),"string"==c&&(a=a.toLowerCase(),b=b.toLowerCase()),a===b?0:a<b?-1:1):c<d?-1:1}if(!Ra(a))return a;c=D(c)?c:[c];0===c.length&&(c=["+"]);c=c.map(function(a){var c=!1,d=a||oa;if(I(a)){if("+"==a.charAt(0)||"-"==a.charAt(0))c="-"==a.charAt(0),a=a.substring(1);
|
||||
if(""===a)return e(function(a,b){return f(a,b)},c);d=b(a);if(d.constant){var l=d();return e(function(a,b){return f(a[l],b[l])},c)}}return e(function(a,b){return f(d(a),d(b))},c)});return Ya.call(a).sort(e(function(a,b){for(var d=0;d<c.length;d++){var e=c[d](a,b);if(0!==e)return e}return 0},d))}}function Ia(b){F(b)&&(b={link:b});b.restrict=b.restrict||"AC";return ca(b)}function od(b,a,c,d,e){var f=this,g=[],h=f.$$parentForm=b.parent().controller("form")||Eb;f.$error={};f.$$success={};f.$pending=u;
|
||||
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(){r(g,function(a){a.$rollbackViewValue()})};f.$commitViewValue=function(){r(g,function(a){a.$commitViewValue()})};f.$addControl=function(a){La(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];
|
||||
r(f.$pending,function(b,c){f.$setValidity(c,null,a)});r(f.$error,function(b,c){f.$setValidity(c,null,a)});Va(g,a)};pd({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&&(Va(d,c),0===d.length&&delete a[b])},parentForm:h,$animate:d});f.$setDirty=function(){d.removeClass(b,Qa);d.addClass(b,Fb);f.$dirty=!0;f.$pristine=!1;h.$setDirty()};f.$setPristine=function(){d.setClass(b,Qa,Fb+" ng-submitted");f.$dirty=!1;f.$pristine=!0;
|
||||
f.$submitted=!1;r(g,function(a){a.$setPristine()})};f.$setUntouched=function(){r(g,function(a){a.$setUntouched()})};f.$setSubmitted=function(){d.addClass(b,"ng-submitted");f.$submitted=!0;h.$setSubmitted()}}function hc(b){b.$formatters.push(function(a){return b.$isEmpty(a)?a:a.toString()})}function gb(b,a,c,d,e,f){var g=a[0].placeholder,h={},k=R(a[0].type);if(!e.android){var l=!1;a.on("compositionstart",function(a){l=!0});a.on("compositionend",function(){l=!1;m()})}var m=function(b){if(!l){var e=
|
||||
a.val(),f=b&&b.type;Ha&&"input"===(b||h).type&&a[0].placeholder!==g?g=a[0].placeholder:("password"===k||c.ngTrim&&"false"===c.ngTrim||(e=P(e)),(d.$viewValue!==e||""===e&&d.$$hasNativeValidators)&&d.$setViewValue(e,f))}};if(e.hasEvent("input"))a.on("input",m);else{var p,s=function(a){p||(p=f.defer(function(){m(a);p=null}))};a.on("keydown",function(a){var b=a.keyCode;91===b||15<b&&19>b||37<=b&&40>=b||s(a)});if(e.hasEvent("paste"))a.on("paste cut",s)}a.on("change",m);d.$render=function(){a.val(d.$isEmpty(d.$viewValue)?
|
||||
"":d.$viewValue)}}function Gb(b,a){return function(c,d){var e,f;if(fa(c))return c;if(I(c)){'"'==c.charAt(0)&&'"'==c.charAt(c.length-1)&&(c=c.substring(1,c.length-1));if(If.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},r(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 hb(b,a,c,d){return function(e,f,g,h,k,l,m){function p(a){return a&&!(a.getTime&&a.getTime()!==a.getTime())}function s(a){return y(a)?fa(a)?a:c(a):u}qd(e,f,g,h);gb(e,f,g,h,k,l);var t=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),"UTC"===t&&b.setMinutes(b.getMinutes()-b.getTimezoneOffset()),b):u});h.$formatters.push(function(a){if(a&&!fa(a))throw Hb("datefmt",a);if(p(a)){if((q=
|
||||
a)&&"UTC"===t){var b=6E4*q.getTimezoneOffset();q=new Date(q.getTime()+b)}return m("date")(a,d,t)}q=null;return""});if(y(g.min)||g.ngMin){var r;h.$validators.min=function(a){return!p(a)||G(r)||c(a)>=r};g.$observe("min",function(a){r=s(a);h.$validate()})}if(y(g.max)||g.ngMax){var n;h.$validators.max=function(a){return!p(a)||G(n)||c(a)<=n};g.$observe("max",function(a){n=s(a);h.$validate()})}}}function qd(b,a,c,d){(d.$$hasNativeValidators=K(a[0].validity))&&d.$parsers.push(function(b){var c=a.prop("validity")||
|
||||
{};return c.badInput&&!c.typeMismatch?u:b})}function rd(b,a,c,d,e){if(y(d)){b=b(d);if(!b.constant)throw z("ngModel")("constexpr",c,d);return b(a)}return e}function pd(b){function a(a,b){b&&!f[a]?(l.addClass(e,a),f[a]=!0):!b&&f[a]&&(l.removeClass(e,a),f[a]=!1)}function c(b,c){b=b?"-"+Mb(b,"-"):"";a(ib+b,!0===c);a(sd+b,!1===c)}var d=b.ctrl,e=b.$element,f={},g=b.set,h=b.unset,k=b.parentForm,l=b.$animate;f[sd]=!(f[ib]=e.hasClass(ib));d.$setValidity=function(b,e,f){e===u?(d.$pending||(d.$pending={}),g(d.$pending,
|
||||
b,f)):(d.$pending&&h(d.$pending,b,f),td(d.$pending)&&(d.$pending=u));Ua(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(ud,!0),d.$valid=d.$invalid=u,c("",null)):(a(ud,!1),d.$valid=td(d.$error),d.$invalid=!d.$valid,c("",d.$valid));e=d.$pending&&d.$pending[b]?u:d.$error[b]?!1:d.$$success[b]?!0:null;c(b,e);k.$setValidity(b,e,d)}}function td(b){if(b)for(var a in b)return!1;return!0}function ic(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],m=0;m<b.length;m++)if(e==b[m])continue a;c.push(e)}return c}function e(a){if(!D(a)){if(I(a))return a.split(" ");if(K(a)){var b=[];r(a,function(a,c){a&&(b=b.concat(c.split(" ")))});return b}}return a}return{restrict:"AC",link:function(f,g,h){function k(a,b){var c=g.data("$classCounts")||{},d=[];r(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 l(b){if(!0===
|
||||
a||f.$index%2===a){var l=e(b||[]);if(!m){var t=k(l,1);h.$addClass(t)}else if(!pa(b,m)){var q=e(m),t=d(l,q),l=d(q,l),t=k(t,1),l=k(l,-1);t&&t.length&&c.addClass(g,t);l&&l.length&&c.removeClass(g,l)}}m=ua(b)}var m;f.$watch(h[b],l,!0);h.$observe("class",function(a){l(f.$eval(h[b]))});"ngClass"!==b&&f.$watch("$index",function(c,d){var g=c&1;if(g!==(d&1)){var l=e(f.$eval(h[b]));g===a?(g=k(l,1),h.$addClass(g)):(g=k(l,-1),h.$removeClass(g))}})}}}]}var Jf=/^\/(.+)\/([a-z]*)$/,R=function(b){return I(b)?b.toLowerCase():
|
||||
b},Jb=Object.prototype.hasOwnProperty,rb=function(b){return I(b)?b.toUpperCase():b},Ha,A,qa,Ya=[].slice,of=[].splice,Kf=[].push,Ja=Object.prototype.toString,Wa=z("ng"),ha=U.angular||(U.angular={}),ab,kb=0;Ha=V.documentMode;x.$inject=[];oa.$inject=[];var D=Array.isArray,P=function(b){return I(b)?b.trim():b},dd=function(b){return b.replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g,"\\$1").replace(/\x08/g,"\\x08")},$a=function(){if(y($a.isActive_))return $a.isActive_;var b=!(!V.querySelector("[ng-csp]")&&!V.querySelector("[data-ng-csp]"));
|
||||
if(!b)try{new Function("")}catch(a){b=!0}return $a.isActive_=b},ob=["ng-","data-ng-","ng:","x-ng-"],Jd=/[A-Z]/g,sc=!1,Nb,na=1,mb=3,Nd={full:"1.3.4",major:1,minor:3,dot:4,codeName:"highfalutin-petroglyph"};S.expando="ng339";var wb=S.cache={},df=1;S._data=function(b){return this.cache[b[this.expando]]||{}};var Ze=/([\:\-\_]+(.))/g,$e=/^moz([A-Z])/,Lf={mouseleave:"mouseout",mouseenter:"mouseover"},Qb=z("jqLite"),cf=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,Pb=/<|&#?\w+;/,af=/<([\w:]+)/,bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
|
||||
ja={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,"",""]};ja.optgroup=ja.option;ja.tbody=ja.tfoot=ja.colgroup=ja.caption=ja.thead;ja.th=ja.td;var Ka=S.prototype={ready:function(b){function a(){c||(c=!0,b())}var c=!1;"complete"===V.readyState?setTimeout(a):(this.on("DOMContentLoaded",a),S(U).on("load",a))},
|
||||
toString:function(){var b=[];r(this,function(a){b.push(""+a)});return"["+b.join(", ")+"]"},eq:function(b){return 0<=b?A(this[b]):A(this[this.length+b])},length:0,push:Kf,sort:[].sort,splice:[].splice},yb={};r("multiple selected checked disabled readOnly required open".split(" "),function(b){yb[R(b)]=b});var Kc={};r("input select option textarea button form details".split(" "),function(b){Kc[b]=!0});var Lc={ngMinlength:"minlength",ngMaxlength:"maxlength",ngMin:"min",ngMax:"max",ngPattern:"pattern"};
|
||||
r({data:Sb,removeData:ub},function(b,a){S[a]=b});r({data:Sb,inheritedData:xb,scope:function(b){return A.data(b,"$scope")||xb(b.parentNode||b,["$isolateScope","$scope"])},isolateScope:function(b){return A.data(b,"$isolateScope")||A.data(b,"$isolateScopeNoTemplate")},controller:Gc,injector:function(b){return xb(b,"$injector")},removeAttr:function(b,a){b.removeAttribute(a)},hasClass:Tb,css:function(b,a,c){a=bb(a);if(y(c))b.style[a]=c;else return b.style[a]},attr:function(b,a,c){var d=R(a);if(yb[d])if(y(c))c?
|
||||
(b[a]=!0,b.setAttribute(a,d)):(b[a]=!1,b.removeAttribute(d));else return b[a]||(b.attributes.getNamedItem(a)||x).specified?d:u;else if(y(c))b.setAttribute(a,c);else if(b.getAttribute)return b=b.getAttribute(a,2),null===b?u:b},prop:function(b,a,c){if(y(c))b[a]=c;else return b[a]},text:function(){function b(a,b){if(G(b)){var d=a.nodeType;return d===na||d===mb?a.textContent:""}a.textContent=b}b.$dv="";return b}(),val:function(b,a){if(G(a)){if(b.multiple&&"select"===ta(b)){var c=[];r(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(G(a))return b.innerHTML;tb(b,!0);b.innerHTML=a},empty:Hc},function(b,a){S.prototype[a]=function(a,d){var e,f,g=this.length;if(b!==Hc&&(2==b.length&&b!==Tb&&b!==Gc?a:d)===u){if(K(a)){for(e=0;e<g;e++)if(b===Sb)b(this[e],a);else for(f in a)b(this[e],f,a[f]);return this}e=b.$dv;g=e===u?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}});
|
||||
r({removeData:ub,on:function a(c,d,e,f){if(y(f))throw Qb("onargs");if(Cc(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],k=g.length;k--;){d=g[k];var l=f[d];l||(f[d]=[],"mouseenter"===d||"mouseleave"===d?a(c,Lf[d],function(a){var c=a.relatedTarget;c&&(c===this||this.contains(c))||h(a,d)}):"$destroy"!==d&&c.addEventListener(d,h,!1),l=f[d]);l.push(e)}}},off:Fc,one:function(a,c,d){a=A(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);r(new S(c),function(c){d?e.insertBefore(c,d.nextSibling):e.replaceChild(c,a);d=c})},children:function(a){var c=[];r(a.childNodes,function(a){a.nodeType===na&&c.push(a)});return c},contents:function(a){return a.contentDocument||a.childNodes||[]},append:function(a,c){var d=a.nodeType;if(d===na||11===d){c=new S(c);for(var d=0,e=c.length;d<e;d++)a.appendChild(c[d])}},prepend:function(a,c){if(a.nodeType===na){var d=a.firstChild;r(new S(c),function(c){a.insertBefore(c,
|
||||
d)})}},wrap:function(a,c){c=A(c).eq(0).clone()[0];var d=a.parentNode;d&&d.replaceChild(c,a);c.appendChild(a)},remove:Ic,detach:function(a){Ic(a,!0)},after:function(a,c){var d=a,e=a.parentNode;c=new S(c);for(var f=0,g=c.length;f<g;f++){var h=c[f];e.insertBefore(h,d.nextSibling);d=h}},addClass:Vb,removeClass:Ub,toggleClass:function(a,c,d){c&&r(c.split(" "),function(c){var f=d;G(f)&&(f=!Tb(a,c));(f?Vb:Ub)(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:Rb,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:x,type:g,target:a},c.type&&(e=C(e,
|
||||
c)),c=ua(h),f=d?[e].concat(d):[e],r(c,function(c){e.isImmediatePropagationStopped()||c.apply(a,f)})}},function(a,c){S.prototype[c]=function(c,e,f){for(var g,h=0,k=this.length;h<k;h++)G(g)?(g=a(this[h],c,e,f),y(g)&&(g=A(g))):Ec(g,a(this[h],c,e,f));return y(g)?g:this};S.prototype.bind=S.prototype.on;S.prototype.unbind=S.prototype.off});cb.prototype={put:function(a,c){this[Ma(a,this.nextUid)]=c},get:function(a){return this[Ma(a,this.nextUid)]},remove:function(a){var c=this[a=Ma(a,this.nextUid)];delete this[a];
|
||||
return c}};var Nc=/^function\s*[^\(]*\(\s*([^\)]*)\)/m,jf=/,/,kf=/^\s*(_?)(\S+?)\1\s*$/,Mc=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,Ea=z("$injector");Lb.$$annotate=Wb;var Mf=z("$animate"),ze=["$provide",function(a){this.$$selectors={};this.register=function(c,d){var e=c+"-animation";if(c&&"."!=c.charAt(0))throw Mf("notcsel",c);this.$$selectors[c.substr(1)]=e;a.factory(e,d)};this.classNameFilter=function(a){1===arguments.length&&(this.$$classNameFilter=a instanceof RegExp?a:null);return this.$$classNameFilter};
|
||||
this.$get=["$$q","$$asyncCallback","$rootScope",function(a,d,e){function f(d){var f,g=a.defer();g.promise.$$cancelFn=function(){f&&f()};e.$$postDigest(function(){f=d(function(){g.resolve()})});return g.promise}function g(a,c){var d=[],e=[],f=ia();r((a.attr("class")||"").split(/\s+/),function(a){f[a]=!0});r(c,function(a,c){var g=f[c];!1===a&&g?e.push(c):!0!==a||g||d.push(c)});return 0<d.length+e.length&&[d.length?d:null,e.length?e:null]}function h(a,c,d){for(var e=0,f=c.length;e<f;++e)a[c[e]]=d}function k(){m||
|
||||
(m=a.defer(),d(function(){m.resolve();m=null}));return m.promise}function l(a,c){if(ha.isObject(c)){var d=C(c.from||{},c.to||{});a.css(d)}}var m;return{animate:function(a,c,d){l(a,{from:c,to:d});return k()},enter:function(a,c,d,e){l(a,e);d?d.after(a):c.prepend(a);return k()},leave:function(a,c){a.remove();return k()},move:function(a,c,d,e){return this.enter(a,c,d,e)},addClass:function(a,c,d){return this.setClass(a,c,[],d)},$$addClassImmediately:function(a,c,d){a=A(a);c=I(c)?c:D(c)?c.join(" "):"";
|
||||
r(a,function(a){Vb(a,c)});l(a,d);return k()},removeClass:function(a,c,d){return this.setClass(a,[],c,d)},$$removeClassImmediately:function(a,c,d){a=A(a);c=I(c)?c:D(c)?c.join(" "):"";r(a,function(a){Ub(a,c)});l(a,d);return k()},setClass:function(a,c,d,e){var k=this,l=!1;a=A(a);var m=a.data("$$animateClasses");m?e&&m.options&&(m.options=ha.extend(m.options||{},e)):(m={classes:{},options:e},l=!0);e=m.classes;c=D(c)?c:c.split(" ");d=D(d)?d:d.split(" ");h(e,c,!0);h(e,d,!1);l&&(m.promise=f(function(c){var d=
|
||||
a.data("$$animateClasses");a.removeData("$$animateClasses");if(d){var e=g(a,d.classes);e&&k.$$setClassImmediately(a,e[0],e[1],d.options)}c()}),a.data("$$animateClasses",m));return m.promise},$$setClassImmediately:function(a,c,d,e){c&&this.$$addClassImmediately(a,c);d&&this.$$removeClassImmediately(a,d);l(a,e);return k()},enabled:x,cancel:x}}]}],ka=z("$compile");uc.$inject=["$provide","$$sanitizeUriProvider"];var nf=/^((?:x|data)[\:\-_])/i,Sc="application/json",Zb={"Content-Type":Sc+";charset=utf-8"},
|
||||
qf=/^\s*(\[|\{[^\{])/,rf=/[\}\]]\s*$/,pf=/^\)\]\}',?\n/,$b=z("$interpolate"),Nf=/^([^\?#]*)(\?([^#]*))?(#(.*))?$/,uf={http:80,https:443,ftp:21},eb=z("$location"),Of={$$html5:!1,$$replace:!1,absUrl:Bb("$$absUrl"),url:function(a){if(G(a))return this.$$url;var c=Nf.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:Bb("$$protocol"),host:Bb("$$host"),port:Bb("$$port"),path:$c("$$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(I(a)||X(a))a=a.toString(),this.$$search=qc(a);else if(K(a))a=Ca(a,{}),r(a,function(c,e){null==c&&delete a[e]}),this.$$search=a;else throw eb("isrcharg");break;default:G(c)||null===c?delete this.$$search[a]:this.$$search[a]=c}this.$$compose();return this},hash:$c("$$hash",function(a){return null!==a?a.toString():""}),replace:function(){this.$$replace=!0;return this}};
|
||||
r([Zc,dc,cc],function(a){a.prototype=Object.create(Of);a.prototype.state=function(c){if(!arguments.length)return this.$$state;if(a!==cc||!this.$$html5)throw eb("nostate");this.$$state=G(c)?null:c;return this}});var la=z("$parse"),Pf=Function.prototype.call,Qf=Function.prototype.apply,Rf=Function.prototype.bind,Ib=ia();r({"null":function(){return null},"true":function(){return!0},"false":function(){return!1},undefined:function(){}},function(a,c){a.constant=a.literal=a.sharedGetter=!0;Ib[c]=a});Ib["this"]=
|
||||
function(a){return a};Ib["this"].sharedGetter=!0;var jb=C(ia(),{"+":function(a,c,d,e){d=d(a,c);e=e(a,c);return y(d)?y(e)?d+e:d:y(e)?e:u},"-":function(a,c,d,e){d=d(a,c);e=e(a,c);return(y(d)?d:0)-(y(e)?e:0)},"*":function(a,c,d,e){return d(a,c)*e(a,c)},"/":function(a,c,d,e){return d(a,c)/e(a,c)},"%":function(a,c,d,e){return d(a,c)%e(a,c)},"===":function(a,c,d,e){return d(a,c)===e(a,c)},"!==":function(a,c,d,e){return d(a,c)!==e(a,c)},"==":function(a,c,d,e){return d(a,c)==e(a,c)},"!=":function(a,c,d,e){return d(a,
|
||||
c)!=e(a,c)},"<":function(a,c,d,e){return d(a,c)<e(a,c)},">":function(a,c,d,e){return d(a,c)>e(a,c)},"<=":function(a,c,d,e){return d(a,c)<=e(a,c)},">=":function(a,c,d,e){return d(a,c)>=e(a,c)},"&&":function(a,c,d,e){return d(a,c)&&e(a,c)},"||":function(a,c,d,e){return d(a,c)||e(a,c)},"!":function(a,c,d){return!d(a,c)},"=":!0,"|":!0}),Sf={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=jb[c],f=jb[d];jb[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=y(c)?"s "+c+"-"+this.index+" ["+this.text.substring(c,d)+"]":" "+d;throw la("lexerr",a,c,this.text);},readNumber:function(){for(var a="",c=this.index;this.index<this.text.length;){var d=R(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+=Sf[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 fb=function(a,c,d){this.lexer=a;this.$filter=c;this.options=d};fb.ZERO=C(function(){return 0},
|
||||
{sharedGetter:!0,constant:!0});fb.prototype={constructor:fb,parse:function(a){this.text=a;this.tokens=this.lexer.lex(a);a=this.statements();0!==this.tokens.length&&this.throwError("is an unexpected token",this.tokens[0]);a.literal=!!a.literal;a.constant=!!a.constant;return a},primary:function(){var a;this.expect("(")?(a=this.filterChain(),this.consume(")")):this.expect("[")?a=this.arrayDeclaration():this.expect("{")?a=this.object():this.peek().identifier?a=this.identifier():this.peek().constant?a=
|
||||
this.constant():this.throwError("not a primary expression",this.peek());for(var c,d;c=this.expect("(","[",".");)"("===c.text?(a=this.functionCall(a,d),d=null):"["===c.text?(d=a,a=this.objectIndex(a)):"."===c.text?(d=a,a=this.fieldAccess(a)):this.throwError("IMPOSSIBLE");return a},throwError:function(a,c){throw la("syntax",c.text,a,c.index+1,this.text,this.text.substring(c.index));},peekToken:function(){if(0===this.tokens.length)throw la("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},consume:function(a){if(0===this.tokens.length)throw la("ueoe",this.text);var c=this.expect(a);c||this.throwError("is unexpected, expecting ["+a+"]",this.peek());return c},unaryFn:function(a,c){var d=jb[a];return C(function(a,f){return d(a,
|
||||
f,c)},{constant:c.constant,inputs:[c]})},binaryFn:function(a,c,d,e){var f=jb[c];return C(function(c,e){return f(c,e,a,d)},{constant:a.constant&&d.constant,inputs:!e&&[a,d]})},identifier:function(){for(var a=this.consume().text;this.peek(".")&&this.peekAhead(1).identifier&&!this.peekAhead(2,"(");)a+=this.consume().text+this.consume().text;return Ib[a]||bd(a,this.options,this.text)},constant:function(){var a=this.consume().value;return C(function(){return a},{constant:!0,literal:!0})},statements:function(){for(var a=
|
||||
[];;)if(0<this.tokens.length&&!this.peek("}",")",";","]")&&a.push(this.filterChain()),!this.expect(";"))return 1===a.length?a[0]:function(c,d){for(var e,f=0,g=a.length;f<g;f++)e=a[f](c,d);return e}},filterChain:function(){for(var a=this.expression();this.expect("|");)a=this.filter(a);return a},filter:function(a){var c=this.$filter(this.consume().text),d,e;if(this.peek(":"))for(d=[],e=[];this.expect(":");)d.push(this.expression());var f=[a].concat(d||[]);return C(function(f,h){var k=a(f,h);if(e){e[0]=
|
||||
k;for(k=d.length;k--;)e[k+1]=d[k](f,h);return c.apply(u,e)}return c(k)},{constant:!c.$stateful&&f.every(ec),inputs:!c.$stateful&&f})},expression:function(){return this.assignment()},assignment:function(){var a=this.ternary(),c,d;return(d=this.expect("="))?(a.assign||this.throwError("implies assignment but ["+this.text.substring(0,d.index)+"] can not be assigned to",d),c=this.ternary(),C(function(d,f){return a.assign(d,c(d,f),f)},{inputs:[a,c]})):a},ternary:function(){var a=this.logicalOR(),c;if(this.expect("?")&&
|
||||
(c=this.assignment(),this.consume(":"))){var d=this.assignment();return C(function(e,f){return a(e,f)?c(e,f):d(e,f)},{constant:a.constant&&c.constant&&d.constant})}return a},logicalOR:function(){for(var a=this.logicalAND(),c;c=this.expect("||");)a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},logicalAND:function(){var a=this.equality(),c;if(c=this.expect("&&"))a=this.binaryFn(a,c.text,this.logicalAND(),!0);return a},equality:function(){var a=this.relational(),c;if(c=this.expect("==","!=",
|
||||
"===","!=="))a=this.binaryFn(a,c.text,this.equality());return a},relational:function(){var a=this.additive(),c;if(c=this.expect("<",">","<=",">="))a=this.binaryFn(a,c.text,this.relational());return a},additive:function(){for(var a=this.multiplicative(),c;c=this.expect("+","-");)a=this.binaryFn(a,c.text,this.multiplicative());return a},multiplicative:function(){for(var a=this.unary(),c;c=this.expect("*","/","%");)a=this.binaryFn(a,c.text,this.unary());return a},unary:function(){var a;return this.expect("+")?
|
||||
this.primary():(a=this.expect("-"))?this.binaryFn(fb.ZERO,a.text,this.unary()):(a=this.expect("!"))?this.unaryFn(a.text,this.unary()):this.primary()},fieldAccess:function(a){var c=this.text,d=this.consume().text,e=bd(d,this.options,c);return C(function(c,d,h){return e(h||a(c,d))},{assign:function(e,g,h){(h=a(e,h))||a.assign(e,h={});return Oa(h,d,g,c)}})},objectIndex:function(a){var c=this.text,d=this.expression();this.consume("]");return C(function(e,f){var g=a(e,f),h=d(e,f);ra(h,c);return g?sa(g[h],
|
||||
c):u},{assign:function(e,f,g){var h=ra(d(e,g),c);(g=sa(a(e,g),c))||a.assign(e,g={});return g[h]=f}})},functionCall:function(a,c){var d=[];if(")"!==this.peekToken().text){do d.push(this.expression());while(this.expect(","))}this.consume(")");var e=this.text,f=d.length?[]:null;return function(g,h){var k=c?c(g,h):g,l=a(g,h,k)||x;if(f)for(var m=d.length;m--;)f[m]=sa(d[m](g,h),e);sa(k,e);if(l){if(l.constructor===l)throw la("isecfn",e);if(l===Pf||l===Qf||l===Rf)throw la("isecff",e);}k=l.apply?l.apply(k,
|
||||
f):l(f[0],f[1],f[2],f[3],f[4]);return sa(k,e)}},arrayDeclaration:function(){var a=[];if("]"!==this.peekToken().text){do{if(this.peek("]"))break;a.push(this.expression())}while(this.expect(","))}this.consume("]");return C(function(c,d){for(var e=[],f=0,g=a.length;f<g;f++)e.push(a[f](c,d));return e},{literal:!0,constant:a.every(ec),inputs:a})},object:function(){var a=[],c=[];if("}"!==this.peekToken().text){do{if(this.peek("}"))break;var d=this.consume();d.constant?a.push(d.value):d.identifier?a.push(d.text):
|
||||
this.throwError("invalid key",d);this.consume(":");c.push(this.expression())}while(this.expect(","))}this.consume("}");return C(function(d,f){for(var g={},h=0,k=c.length;h<k;h++)g[a[h]]=c[h](d,f);return g},{literal:!0,constant:c.every(ec),inputs:c})}};var xf=ia(),wf=ia(),yf=Object.prototype.valueOf,Ba=z("$sce"),ma={HTML:"html",CSS:"css",URL:"url",RESOURCE_URL:"resourceUrl",JS:"js"},ka=z("$compile"),Y=V.createElement("a"),fd=Aa(U.location.href);Bc.$inject=["$provide"];gd.$inject=["$locale"];id.$inject=
|
||||
["$locale"];var ld=".",Hf={yyyy:Z("FullYear",4),yy:Z("FullYear",2,0,!0),y:Z("FullYear",1),MMMM:Db("Month"),MMM:Db("Month",!0),MM:Z("Month",2,1),M:Z("Month",1,1),dd:Z("Date",2),d:Z("Date",1),HH:Z("Hours",2),H:Z("Hours",1),hh:Z("Hours",2,-12),h:Z("Hours",1,-12),mm:Z("Minutes",2),m:Z("Minutes",1),ss:Z("Seconds",2),s:Z("Seconds",1),sss:Z("Milliseconds",3),EEEE:Db("Day"),EEE:Db("Day",!0),a:function(a,c){return 12>a.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<=
|
||||
a?"+":"")+(Cb(Math[0<a?"floor":"ceil"](a/60),2)+Cb(Math.abs(a%60),2))},ww:nd(2),w:nd(1)},Gf=/((?:[^yMdHhmsaZEw']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z|w+))(.*)/,Ff=/^\-?\d+$/;hd.$inject=["$locale"];var Df=ca(R),Ef=ca(rb);jd.$inject=["$parse"];var Qd=ca({restrict:"E",compile:function(a,c){if(!c.href&&!c.xlinkHref&&!c.name)return function(a,c){var f="[object SVGAnimatedString]"===Ja.call(c.prop("href"))?"xlink:href":"href";c.on("click",function(a){c.attr(f)||a.preventDefault()})}}}),sb=
|
||||
{};r(yb,function(a,c){if("multiple"!=a){var d=wa("ng-"+c);sb[d]=function(){return{restrict:"A",priority:100,link:function(a,f,g){a.$watch(g[d],function(a){g.$set(c,!!a)})}}}}});r(Lc,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(Jf))){f.$set("ngPattern",new RegExp(e[1],e[2]));return}a.$watch(f[c],function(a){f.$set(c,a)})}}}});r(["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]"===Ja.call(e.prop("href"))&&(h="xlinkHref",f.$attr[h]="xlink:href",g=null);f.$observe(c,function(c){c?(f.$set(h,c),Ha&&g&&e.prop(g,f[h])):"href"===a&&f.$set(h,null)})}}}});var Eb={$addControl:x,$$renameControl:function(a,c){a.$name=c},$removeControl:x,$setValidity:x,$setDirty:x,$setPristine:x,$setSubmitted:x};od.$inject=["$element","$attrs","$scope","$animate","$interpolate"];var vd=function(a){return["$timeout",function(c){return{name:"form",
|
||||
restrict:a?"EAC":"E",controller:od,compile:function(a){a.addClass(Qa).addClass(ib);return{pre:function(a,d,g,h){if(!("action"in g)){var k=function(c){a.$apply(function(){h.$commitViewValue();h.$setSubmitted()});c.preventDefault()};d[0].addEventListener("submit",k,!1);d.on("$destroy",function(){c(function(){d[0].removeEventListener("submit",k,!1)},0,!1)})}var l=h.$$parentForm,m=h.$name;m&&(Oa(a,m,h,m),g.$observe(g.name?"name":"ngForm",function(c){m!==c&&(Oa(a,m,u,m),m=c,Oa(a,m,h,m),l.$$renameControl(h,
|
||||
m))}));d.on("$destroy",function(){l.$removeControl(h);m&&Oa(a,m,u,m);C(h,Eb)})}}}}}]},Rd=vd(),de=vd(!0),If=/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/,Tf=/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/,Uf=/^[a-z0-9!#$%&'*+\/=?^_`{|}~.-]+@[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i,Vf=/^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/,wd=/^(\d{4})-(\d{2})-(\d{2})$/,xd=/^(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,
|
||||
jc=/^(\d{4})-W(\d\d)$/,yd=/^(\d{4})-(\d\d)$/,zd=/^(\d\d):(\d\d)(?::(\d\d)(\.\d{1,3})?)?$/,Wf=/(\s+|^)default(\s+|$)/,Hb=new z("ngModel"),Ad={text:function(a,c,d,e,f,g){gb(a,c,d,e,f,g);hc(e)},date:hb("date",wd,Gb(wd,["yyyy","MM","dd"]),"yyyy-MM-dd"),"datetime-local":hb("datetimelocal",xd,Gb(xd,"yyyy MM dd HH mm ss sss".split(" ")),"yyyy-MM-ddTHH:mm:ss.sss"),time:hb("time",zd,Gb(zd,["HH","mm","ss","sss"]),"HH:mm:ss.sss"),week:hb("week",jc,function(a,c){if(fa(a))return a;if(I(a)){jc.lastIndex=0;var d=
|
||||
jc.exec(a);if(d){var e=+d[1],f=+d[2],g=d=0,h=0,k=0,l=md(e),f=7*(f-1);c&&(d=c.getHours(),g=c.getMinutes(),h=c.getSeconds(),k=c.getMilliseconds());return new Date(e,0,l.getDate()+f,d,g,h,k)}}return NaN},"yyyy-Www"),month:hb("month",yd,Gb(yd,["yyyy","MM"]),"yyyy-MM"),number:function(a,c,d,e,f,g){qd(a,c,d,e);gb(a,c,d,e,f,g);e.$$parserName="number";e.$parsers.push(function(a){return e.$isEmpty(a)?null:Vf.test(a)?parseFloat(a):u});e.$formatters.push(function(a){if(!e.$isEmpty(a)){if(!X(a))throw Hb("numfmt",
|
||||
a);a=a.toString()}return a});if(d.min||d.ngMin){var h;e.$validators.min=function(a){return e.$isEmpty(a)||G(h)||a>=h};d.$observe("min",function(a){y(a)&&!X(a)&&(a=parseFloat(a,10));h=X(a)&&!isNaN(a)?a:u;e.$validate()})}if(d.max||d.ngMax){var k;e.$validators.max=function(a){return e.$isEmpty(a)||G(k)||a<=k};d.$observe("max",function(a){y(a)&&!X(a)&&(a=parseFloat(a,10));k=X(a)&&!isNaN(a)?a:u;e.$validate()})}},url:function(a,c,d,e,f,g){gb(a,c,d,e,f,g);hc(e);e.$$parserName="url";e.$validators.url=function(a,
|
||||
c){var d=a||c;return e.$isEmpty(d)||Tf.test(d)}},email:function(a,c,d,e,f,g){gb(a,c,d,e,f,g);hc(e);e.$$parserName="email";e.$validators.email=function(a,c){var d=a||c;return e.$isEmpty(d)||Uf.test(d)}},radio:function(a,c,d,e){G(d.name)&&c.attr("name",++kb);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,k){var l=rd(k,a,"ngTrueValue",d.ngTrueValue,!0),
|
||||
m=rd(k,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 pa(a,l)});e.$parsers.push(function(a){return a?l:m})},hidden:x,button:x,submit:x,reset:x,file:x},vc=["$browser","$sniffer","$filter","$parse",function(a,c,d,e){return{restrict:"E",require:["?ngModel"],link:{pre:function(f,g,h,k){k[0]&&(Ad[R(h.type)]||Ad.text)(f,g,h,k[0],
|
||||
c,a,d,e)}}}}],ib="ng-valid",sd="ng-invalid",Qa="ng-pristine",Fb="ng-dirty",ud="ng-pending",Xf=["$scope","$exceptionHandler","$attrs","$element","$parse","$animate","$timeout","$rootScope","$q","$interpolate",function(a,c,d,e,f,g,h,k,l,m){this.$modelValue=this.$viewValue=Number.NaN;this.$$rawModelValue=u;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=u;this.$name=m(d.name||"",!1)(a);var p=f(d.ngModel),s=p.assign,t=p,q=s,N=null,n=this;this.$$setOptions=function(a){if((n.$options=a)&&a.getterSetter){var c=f(d.ngModel+"()"),g=f(d.ngModel+"($$$p)");t=function(a){var d=p(a);F(d)&&(d=c(a));return d};q=function(a,c){F(p(a))?g(a,{$$$p:n.$modelValue}):s(a,n.$modelValue)}}else if(!p.assign)throw Hb("nonassign",d.ngModel,va(e));};this.$render=x;this.$isEmpty=function(a){return G(a)||""===a||null===a||a!==
|
||||
a};var v=e.inheritedData("$formController")||Eb,w=0;pd({ctrl:this,$element:e,set:function(a,c){a[c]=!0},unset:function(a,c){delete a[c]},parentForm:v,$animate:g});this.$setPristine=function(){n.$dirty=!1;n.$pristine=!0;g.removeClass(e,Fb);g.addClass(e,Qa)};this.$setDirty=function(){n.$dirty=!0;n.$pristine=!1;g.removeClass(e,Qa);g.addClass(e,Fb);v.$setDirty()};this.$setUntouched=function(){n.$touched=!1;n.$untouched=!0;g.setClass(e,"ng-untouched","ng-touched")};this.$setTouched=function(){n.$touched=
|
||||
!0;n.$untouched=!1;g.setClass(e,"ng-touched","ng-untouched")};this.$rollbackViewValue=function(){h.cancel(N);n.$viewValue=n.$$lastCommittedViewValue;n.$render()};this.$validate=function(){if(!X(n.$modelValue)||!isNaN(n.$modelValue)){var a=n.$$rawModelValue,c=n.$valid,d=n.$modelValue,e=n.$options&&n.$options.allowInvalid;n.$$runValidators(n.$error[n.$$parserName||"parse"]?!1:u,a,n.$$lastCommittedViewValue,function(f){e||c===f||(n.$modelValue=f?a:u,n.$modelValue!==d&&n.$$writeModelToScope())})}};this.$$runValidators=
|
||||
function(a,c,d,e){function f(){var a=!0;r(n.$validators,function(e,f){var g=e(c,d);a=a&&g;h(f,g)});return a?!0:(r(n.$asyncValidators,function(a,c){h(c,null)}),!1)}function g(){var a=[],e=!0;r(n.$asyncValidators,function(f,g){var k=f(c,d);if(!k||!F(k.then))throw Hb("$asyncValidators",k);h(g,u);a.push(k.then(function(){h(g,!0)},function(a){e=!1;h(g,!1)}))});a.length?l.all(a).then(function(){k(e)},x):k(!0)}function h(a,c){m===w&&n.$setValidity(a,c)}function k(a){m===w&&e(a)}w++;var m=w;(function(a){var c=
|
||||
n.$$parserName||"parse";if(a===u)h(c,null);else if(h(c,a),!a)return r(n.$validators,function(a,c){h(c,null)}),r(n.$asyncValidators,function(a,c){h(c,null)}),!1;return!0})(a)?f()?g():k(!1):k(!1)};this.$commitViewValue=function(){var a=n.$viewValue;h.cancel(N);if(n.$$lastCommittedViewValue!==a||""===a&&n.$$hasNativeValidators)n.$$lastCommittedViewValue=a,n.$pristine&&this.$setDirty(),this.$$parseAndValidate()};this.$$parseAndValidate=function(){var c=n.$$lastCommittedViewValue,d=c,e=G(d)?u:!0;if(e)for(var f=
|
||||
0;f<n.$parsers.length;f++)if(d=n.$parsers[f](d),G(d)){e=!1;break}X(n.$modelValue)&&isNaN(n.$modelValue)&&(n.$modelValue=t(a));var g=n.$modelValue,h=n.$options&&n.$options.allowInvalid;n.$$rawModelValue=d;h&&(n.$modelValue=d,n.$modelValue!==g&&n.$$writeModelToScope());n.$$runValidators(e,d,c,function(a){h||(n.$modelValue=a?d:u,n.$modelValue!==g&&n.$$writeModelToScope())})};this.$$writeModelToScope=function(){q(a,n.$modelValue);r(n.$viewChangeListeners,function(a){try{a()}catch(d){c(d)}})};this.$setViewValue=
|
||||
function(a,c){n.$viewValue=a;n.$options&&!n.$options.updateOnDefault||n.$$debounceViewValueCommit(c)};this.$$debounceViewValueCommit=function(c){var d=0,e=n.$options;e&&y(e.debounce)&&(e=e.debounce,X(e)?d=e:X(e[c])?d=e[c]:X(e["default"])&&(d=e["default"]));h.cancel(N);d?N=h(function(){n.$commitViewValue()},d):k.$$phase?n.$commitViewValue():a.$apply(function(){n.$commitViewValue()})};a.$watch(function(){var c=t(a);if(c!==n.$modelValue){n.$modelValue=n.$$rawModelValue=c;for(var d=n.$formatters,e=d.length,
|
||||
f=c;e--;)f=d[e](f);n.$viewValue!==f&&(n.$viewValue=n.$$lastCommittedViewValue=f,n.$render(),n.$$runValidators(u,c,f,x))}return c})}],se=["$rootScope",function(a){return{restrict:"A",require:["ngModel","^?form","^?ngModelOptions"],controller:Xf,priority:1,compile:function(c){c.addClass(Qa).addClass("ng-untouched").addClass(ib);return{pre:function(a,c,f,g){var h=g[0],k=g[1]||Eb;h.$$setOptions(g[2]&&g[2].$options);k.$addControl(h);f.$observe("name",function(a){h.$name!==a&&k.$$renameControl(h,a)});a.$on("$destroy",
|
||||
function(){k.$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))})}}}}}],ue=ca({restrict:"A",require:"ngModel",link:function(a,c,d,e){e.$viewChangeListeners.push(function(){a.$eval(d.ngChange)})}}),xc=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()}))}}},wc=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){I(a)&&0<a.length&&(a=new RegExp("^"+a+"$"));if(a&&!a.test)throw z("ngPattern")("noregexp",g,a,va(c));f=a||u;e.$validate()});e.$validators.pattern=function(a){return e.$isEmpty(a)||G(f)||f.test(a)}}}}},zc=function(){return{restrict:"A",
|
||||
require:"?ngModel",link:function(a,c,d,e){if(e){var f=-1;d.$observe("maxlength",function(a){a=$(a);f=isNaN(a)?-1:a;e.$validate()});e.$validators.maxlength=function(a,c){return 0>f||e.$isEmpty(a)||c.length<=f}}}}},yc=function(){return{restrict:"A",require:"?ngModel",link:function(a,c,d,e){if(e){var f=0;d.$observe("minlength",function(a){f=$(a)||0;e.$validate()});e.$validators.minlength=function(a,c){return e.$isEmpty(c)||c.length>=f}}}}},te=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?P(f):f;e.$parsers.push(function(a){if(!G(a)){var c=[];a&&r(a.split(h),function(a){a&&c.push(g?P(a):a)});return c}});e.$formatters.push(function(a){return D(a)?a.join(f):u});e.$isEmpty=function(a){return!a||!a.length}}}},Yf=/^(true|false|\d+)$/,ve=function(){return{restrict:"A",priority:100,compile:function(a,c){return Yf.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)})}}}},we=function(){return{restrict:"A",controller:["$scope","$attrs",function(a,c){var d=this;this.$options=a.$eval(c.ngModelOptions);this.$options.updateOn!==u?(this.$options.updateOnDefault=!1,this.$options.updateOn=P(this.$options.updateOn.replace(Wf,function(){d.$options.updateOnDefault=!0;return" "}))):this.$options.updateOnDefault=!0}]}},Wd=["$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===u?"":a})}}}}],Yd=["$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===u?"":a})}}}}],Xd=["$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))||"")})}}}}],Zd=ic("",!0),ae=ic("Odd",0),$d=ic("Even",1),be=Ia({compile:function(a,c){c.$set("ngCloak",u);a.removeClass("ng-cloak")}}),ce=[function(){return{restrict:"A",scope:!0,controller:"@",priority:500}}],Ac={},Zf={blur:!0,focus:!0};r("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);Ac[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})};Zf[a]&&e.$$phase?c.$evalAsync(f):c.$apply(f)})}}}}]});var fe=["$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,k,l;c.$watch(e.ngIf,function(c){c?k||g(function(c,f){k=f;c[c.length++]=V.createComment(" end ngIf: "+
|
||||
e.ngIf+" ");h={clone:c};a.enter(c,d.parent(),d)}):(l&&(l.remove(),l=null),k&&(k.$destroy(),k=null),h&&(l=qb(h.clone),a.leave(l).then(function(){l=null}),h=null))})}}}],ge=["$templateRequest","$anchorScroll","$animate","$sce",function(a,c,d,e){return{restrict:"ECA",priority:400,terminal:!0,transclude:"element",controller:ha.noop,compile:function(f,g){var h=g.ngInclude||g.src,k=g.onload||"",l=g.autoscroll;return function(f,g,s,r,q){var u=0,n,v,w,O=function(){v&&(v.remove(),v=null);n&&(n.$destroy(),
|
||||
n=null);w&&(d.leave(w).then(function(){v=null}),v=w,w=null)};f.$watch(e.parseAsResourceUrl(h),function(e){var h=function(){!y(l)||l&&!f.$eval(l)||c()},s=++u;e?(a(e,!0).then(function(a){if(s===u){var c=f.$new();r.template=a;a=q(c,function(a){O();d.enter(a,null,g).then(h)});n=c;w=a;n.$emit("$includeContentLoaded",e);f.$eval(k)}},function(){s===u&&(O(),f.$emit("$includeContentError",e))}),f.$emit("$includeContentRequested",e)):(O(),r.template=null)})}}}}],xe=["$compile",function(a){return{restrict:"ECA",
|
||||
priority:-400,require:"ngInclude",link:function(c,d,e,f){/SVG/.test(d[0].toString())?(d.empty(),a(Dc(f.template,V).childNodes)(c,function(a){d.append(a)},{futureParentElement:d})):(d.html(f.template),a(d.contents())(c))}}}],he=Ia({priority:450,compile:function(){return{pre:function(a,c,d){a.$eval(d.ngInit)}}}}),ie=Ia({terminal:!0,priority:1E3}),je=["$locale","$interpolate",function(a,c){var d=/{}/g,e=/^when(Minus)?(.+)$/;return{restrict:"EA",link:function(f,g,h){function k(a){g.text(a||"")}var l=
|
||||
h.count,m=h.$attr.when&&g.attr(h.$attr.when),p=h.offset||0,s=f.$eval(m)||{},t={},m=c.startSymbol(),q=c.endSymbol(),u=m+l+"-"+p+q,n=ha.noop,v;r(h,function(a,c){var d=e.exec(c);d&&(d=(d[1]?"-":"")+R(d[2]),s[d]=g.attr(h.$attr[c]))});r(s,function(a,e){t[e]=c(a.replace(d,u))});f.$watch(l,function(c){c=parseFloat(c);var d=isNaN(c);d||c in s||(c=a.pluralCat(c-p));c===v||d&&isNaN(v)||(n(),n=f.$watch(t[c],k),v=c)})}}}],ke=["$parse","$animate",function(a,c){var d=z("ngRepeat"),e=function(a,c,d,e,l,m,p){a[d]=
|
||||
e;l&&(a[l]=m);a.$index=c;a.$first=0===c;a.$last=c===p-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,k=V.createComment(" end ngRepeat: "+h+" "),l=h.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!l)throw d("iexp",h);var m=l[1],p=l[2],s=l[3],t=l[4],l=m.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/);
|
||||
if(!l)throw d("iidexp",m);var q=l[3]||l[1],y=l[2];if(s&&(!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(s)||/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent)$/.test(s)))throw d("badident",s);var n,v,w,z,E={$id:Ma};t?n=a(t):(w=function(a,c){return Ma(c)},z=function(a){return a});return function(a,f,g,l,m){n&&(v=function(c,d,e){y&&(E[y]=c);E[q]=d;E.$index=e;return n(a,E)});var t=ia();a.$watchCollection(p,function(g){var l,n,p=f[0],B,E=ia(),C,x,G,T,D,F,I;s&&(a[s]=g);if(Ra(g))D=g,n=v||
|
||||
w;else{n=v||z;D=[];for(I in g)g.hasOwnProperty(I)&&"$"!=I.charAt(0)&&D.push(I);D.sort()}C=D.length;I=Array(C);for(l=0;l<C;l++)if(x=g===D?l:D[l],G=g[x],T=n(x,G,l),t[T])F=t[T],delete t[T],E[T]=F,I[l]=F;else{if(E[T])throw r(I,function(a){a&&a.scope&&(t[a.id]=a)}),d("dupes",h,T,G);I[l]={id:T,scope:u,clone:u};E[T]=!0}for(B in t){F=t[B];T=qb(F.clone);c.leave(T);if(T[0].parentNode)for(l=0,n=T.length;l<n;l++)T[l].$$NG_REMOVED=!0;F.scope.$destroy()}for(l=0;l<C;l++)if(x=g===D?l:D[l],G=g[x],F=I[l],F.scope){B=
|
||||
p;do B=B.nextSibling;while(B&&B.$$NG_REMOVED);F.clone[0]!=B&&c.move(qb(F.clone),null,A(p));p=F.clone[F.clone.length-1];e(F.scope,l,q,G,y,x,C)}else m(function(a,d){F.scope=d;var f=k.cloneNode(!1);a[a.length++]=f;c.enter(a,null,A(p));p=f;F.clone=a;E[F.id]=F;e(F.scope,l,q,G,y,x,C)});t=E})}}}}],le=["$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"})})}}}],ee=["$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"})})}}}],me=Ia(function(a,c,d){a.$watch(d.ngStyle,function(a,d){d&&a!==d&&r(d,function(a,d){c.css(d,"")});a&&c.css(a)},!0)}),ne=["$animate",function(a){return{restrict:"EA",require:"ngSwitch",controller:["$scope",function(){this.cases={}}],link:function(c,d,e,f){var g=[],h=[],k=[],l=[],m=function(a,c){return function(){a.splice(c,
|
||||
1)}};c.$watch(e.ngSwitch||e.on,function(c){var d,e;d=0;for(e=k.length;d<e;++d)a.cancel(k[d]);d=k.length=0;for(e=l.length;d<e;++d){var q=qb(h[d].clone);l[d].$destroy();(k[d]=a.leave(q)).then(m(k,d))}h.length=0;l.length=0;(g=f.cases["!"+c]||f.cases["?"])&&r(g,function(c){c.transclude(function(d,e){l.push(e);var f=c.element;d[d.length++]=V.createComment(" end ngSwitchWhen: ");h.push({clone:d});a.enter(d,f.parent(),f)})})})}}}],oe=Ia({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})}}),pe=Ia({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})}}),re=Ia({restrict:"EAC",link:function(a,c,d,e,f){if(!f)throw z("ngTransclude")("orphan",va(c));f(function(a){c.empty();c.append(a)})}}),Sd=["$templateCache",function(a){return{restrict:"E",
|
||||
terminal:!0,compile:function(c,d){"text/ng-template"==d.type&&a.put(d.id,c[0].text)}}}],$f=z("ngOptions"),qe=ca({restrict:"A",terminal:!0}),Td=["$compile","$parse",function(a,c){var d=/^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\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]+?))?$/,e={$setViewValue:x};return{restrict:"E",require:["select","?ngModel"],controller:["$element","$scope","$attrs",function(a,
|
||||
c,d){var k=this,l={},m=e,p;k.databound=d.ngModel;k.init=function(a,c,d){m=a;p=d};k.addOption=function(c,d){La(c,'"option value"');l[c]=!0;m.$viewValue==c&&(a.val(c),p.parent()&&p.remove());d&&d[0].hasAttribute("selected")&&(d[0].selected=!0)};k.removeOption=function(a){this.hasOption(a)&&(delete l[a],m.$viewValue==a&&this.renderUnknownOption(a))};k.renderUnknownOption=function(c){c="? "+Ma(c)+" ?";p.val(c);a.prepend(p);a.val(c);p.prop("selected",!0)};k.hasOption=function(a){return l.hasOwnProperty(a)};
|
||||
c.$on("$destroy",function(){k.renderUnknownOption=x})}],link:function(e,g,h,k){function l(a,c,d,e){d.$render=function(){var a=d.$viewValue;e.hasOption(a)?(E.parent()&&E.remove(),c.val(a),""===a&&n.prop("selected",!0)):G(a)&&n?c.val(""):e.renderUnknownOption(a)};c.on("change",function(){a.$apply(function(){E.parent()&&E.remove();d.$setViewValue(c.val())})})}function m(a,c,d){var e;d.$render=function(){var a=new cb(d.$viewValue);r(c.find("option"),function(c){c.selected=y(a.get(c.value))})};a.$watch(function(){pa(e,
|
||||
d.$viewValue)||(e=ua(d.$viewValue),d.$render())});c.on("change",function(){a.$apply(function(){var a=[];r(c.find("option"),function(c){c.selected&&a.push(c.value)});d.$setViewValue(a)})})}function p(e,f,g){function h(a,c,d){U[x]=d;G&&(U[G]=c);return a(e,U)}function k(a){var c;if(t)if(K&&D(a)){c=new cb([]);for(var d=0;d<a.length;d++)c.put(h(K,null,a[d]),!0)}else c=new cb(a);else K&&(a=h(K,null,a));return function(d,e){var f;f=K?K:C?C:H;return t?y(c.remove(h(f,d,e))):a===h(f,d,e)}}function l(){v||(e.$$postDigest(n),
|
||||
v=!0)}function m(a,c,d){a[c]=a[c]||0;a[c]+=d?1:-1}function n(){v=!1;var a={"":[]},c=[""],d,l,p,q,u;p=g.$viewValue;q=M(e)||[];var C=G?Object.keys(q).sort():q,x,A,H,D,Q={};u=k(p);var P=!1,V,X;S={};for(D=0;H=C.length,D<H;D++){x=D;if(G&&(x=C[D],"$"===x.charAt(0)))continue;A=q[x];d=h(I,x,A)||"";(l=a[d])||(l=a[d]=[],c.push(d));d=u(x,A);P=P||d;A=h(E,x,A);A=y(A)?A:"";X=K?K(e,U):G?C[D]:D;K&&(S[X]=x);l.push({id:X,label:A,selected:d})}t||(z||null===p?a[""].unshift({id:"",label:"",selected:!P}):P||a[""].unshift({id:"?",
|
||||
label:"",selected:!0}));x=0;for(C=c.length;x<C;x++){d=c[x];l=a[d];R.length<=x?(p={element:F.clone().attr("label",d),label:l.label},q=[p],R.push(q),f.append(p.element)):(q=R[x],p=q[0],p.label!=d&&p.element.attr("label",p.label=d));P=null;D=0;for(H=l.length;D<H;D++)d=l[D],(u=q[D+1])?(P=u.element,u.label!==d.label&&(m(Q,u.label,!1),m(Q,d.label,!0),P.text(u.label=d.label),P.prop("label",u.label)),u.id!==d.id&&P.val(u.id=d.id),P[0].selected!==d.selected&&(P.prop("selected",u.selected=d.selected),Ha&&P.prop("selected",
|
||||
u.selected))):(""===d.id&&z?V=z:(V=w.clone()).val(d.id).prop("selected",d.selected).attr("selected",d.selected).prop("label",d.label).text(d.label),q.push(u={element:V,label:d.label,id:d.id,selected:d.selected}),m(Q,d.label,!0),P?P.after(V):p.element.append(V),P=V);for(D++;q.length>D;)d=q.pop(),m(Q,d.label,!1),d.element.remove();r(Q,function(a,c){0<a?s.addOption(c):0>a&&s.removeOption(c)})}for(;R.length>x;)R.pop()[0].element.remove()}var p;if(!(p=q.match(d)))throw $f("iexp",q,va(f));var E=c(p[2]||
|
||||
p[1]),x=p[4]||p[6],A=/ as /.test(p[0])&&p[1],C=A?c(A):null,G=p[5],I=c(p[3]||""),H=c(p[2]?p[1]:x),M=c(p[7]),K=p[8]?c(p[8]):null,S={},R=[[{element:f,label:""}]],U={};z&&(a(z)(e),z.removeClass("ng-scope"),z.remove());f.empty();f.on("change",function(){e.$apply(function(){var a=M(e)||[],c;if(t)c=[],r(f.val(),function(d){d=K?S[d]:d;c.push("?"===d?u:""===d?null:h(C?C:H,d,a[d]))});else{var d=K?S[f.val()]:f.val();c="?"===d?u:""===d?null:h(C?C:H,d,a[d])}g.$setViewValue(c);n()})});g.$render=n;e.$watchCollection(M,
|
||||
l);e.$watchCollection(function(){var a=M(e),c;if(a&&D(a)){c=Array(a.length);for(var d=0,f=a.length;d<f;d++)c[d]=h(E,d,a[d])}else if(a)for(d in c={},a)a.hasOwnProperty(d)&&(c[d]=h(E,d,a[d]));return c},l);t&&e.$watchCollection(function(){return g.$modelValue},l)}if(k[1]){var s=k[0];k=k[1];var t=h.multiple,q=h.ngOptions,z=!1,n,v=!1,w=A(V.createElement("option")),F=A(V.createElement("optgroup")),E=w.clone();h=0;for(var x=g.children(),C=x.length;h<C;h++)if(""===x[h].value){n=z=x.eq(h);break}s.init(k,z,
|
||||
E);t&&(k.$isEmpty=function(a){return!a||0===a.length});q?p(e,g,k):t?m(e,g,k):l(e,g,k,s)}}}}],Vd=["$interpolate",function(a){var c={addOption:x,removeOption:x};return{restrict:"E",priority:100,compile:function(d,e){if(G(e.value)){var f=a(d.text(),!0);f||e.$set("value",d.text())}return function(a,d,e){var l=d.parent(),m=l.data("$selectController")||l.parent().data("$selectController");m&&m.databound||(m=c);f?a.$watch(f,function(a,c){e.$set("value",a);c!==a&&m.removeOption(c);m.addOption(a,d)}):m.addOption(e.value,
|
||||
d);d.on("$destroy",function(){m.removeOption(e.value)})}}}}],Ud=ca({restrict:"E",terminal:!1});U.angular.bootstrap?console.log("WARNING: Tried to load angular more than once."):(Kd(),Md(ha),A(V).ready(function(){Gd(V,rc)}))})(window,document);!window.angular.$$csp()&&window.angular.element(document).find("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;}</style>');
|
||||
//# sourceMappingURL=angular.min.js.map
|
|
@ -1,783 +0,0 @@
|
|||
(function() {
|
||||
|
||||
angular.module('linuxDash', ['ngRoute']);
|
||||
|
||||
/**
|
||||
* Routes for different tabs on UI
|
||||
*/
|
||||
angular.module('linuxDash').config(['$routeProvider',
|
||||
function($routeProvider) {
|
||||
|
||||
$routeProvider.
|
||||
when('/loading', {
|
||||
templateUrl: 'templates/app/loading.html',
|
||||
controller: function appLoadController ($scope, $location, $rootScope) {
|
||||
|
||||
var loadUrl = localStorage.getItem('currentTab') || 'system-status';
|
||||
|
||||
var loadLinuxDash = function () {
|
||||
$location.path(loadUrl);
|
||||
};
|
||||
|
||||
$rootScope.$on('start-linux-dash', loadLinuxDash);
|
||||
|
||||
},
|
||||
}).
|
||||
when('/system-status', {
|
||||
templateUrl: 'templates/sections/system-status.html',
|
||||
}).
|
||||
when('/basic-info', {
|
||||
templateUrl: 'templates/sections/basic-info.html',
|
||||
}).
|
||||
when('/network', {
|
||||
templateUrl: 'templates/sections/network.html',
|
||||
}).
|
||||
when('/accounts', {
|
||||
templateUrl: 'templates/sections/accounts.html',
|
||||
}).
|
||||
when('/apps', {
|
||||
templateUrl: 'templates/sections/applications.html',
|
||||
}).
|
||||
otherwise({
|
||||
redirectTo: '/loading'
|
||||
});
|
||||
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* Service which gets data from server
|
||||
* via HTTP or Websocket (if supported)
|
||||
*/
|
||||
angular.module('linuxDash').service('server', ['$http', '$rootScope', '$location', function($http, $rootScope, $location) {
|
||||
|
||||
var websocket = {
|
||||
connection: null,
|
||||
onMessageEventHandlers: {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* Establish a websocket connection with server
|
||||
*
|
||||
* @return Null
|
||||
*/
|
||||
var establishWebsocketConnection = function() {
|
||||
|
||||
var websocketUrl = 'ws://' + window.location.hostname + ':' + window.location.port;
|
||||
|
||||
if (websocket.connection === null) {
|
||||
|
||||
websocket.connection = new WebSocket(websocketUrl, 'linux-dash');
|
||||
|
||||
websocket.connection.onopen = function() {
|
||||
$rootScope.$broadcast("start-linux-dash", {});
|
||||
$rootScope.$apply();
|
||||
console.info('Websocket connection is open');
|
||||
};
|
||||
|
||||
websocket.connection.onmessage = function(event) {
|
||||
|
||||
var response = JSON.parse(event.data);
|
||||
var moduleName = response.moduleName;
|
||||
var moduleData = JSON.parse(response.output);
|
||||
|
||||
if (!!websocket.onMessageEventHandlers[moduleName]) {
|
||||
websocket.onMessageEventHandlers[moduleName](moduleData);
|
||||
} else {
|
||||
console.info("Websocket could not find module", moduleName, "in:", websocket.onMessageEventHandlers);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
websocket.connection.onclose = function() {
|
||||
websocket.connection = null;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* Check if websockets are supported
|
||||
* If so, call establishWebsocketConnection()
|
||||
*
|
||||
* @return Null
|
||||
*/
|
||||
this.checkIfWebsocketsAreSupported = function() {
|
||||
|
||||
var websocketSupport = {
|
||||
browser: null,
|
||||
server: null,
|
||||
};
|
||||
|
||||
// does browser support websockets?
|
||||
if (window.WebSocket) {
|
||||
|
||||
websocketSupport.browser = true;
|
||||
|
||||
// does backend support websockets?
|
||||
$http.get("/websocket").then(function(response) {
|
||||
|
||||
// if websocket_support property exists and is trurthy
|
||||
// websocketSupport.server will equal true.
|
||||
websocketSupport.server = !!response.data["websocket_support"];
|
||||
|
||||
}).catch(function websocketNotSupportedByServer() {
|
||||
|
||||
websocketSupport.server = false;
|
||||
$rootScope.$broadcast("start-linux-dash", {});
|
||||
|
||||
}).then(function finalDecisionOnWebsocket() {
|
||||
|
||||
if (websocketSupport.browser && websocketSupport.server) {
|
||||
|
||||
establishWebsocketConnection();
|
||||
|
||||
} else {
|
||||
// rootScope event not propogating from here.
|
||||
// instead, we manually route to url
|
||||
$location.path('/system-status');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles requests from modules for data from server
|
||||
*
|
||||
* @param {String} moduleName
|
||||
* @param {Function} callback
|
||||
* @return {[ Null || callback(server response) ]}
|
||||
*/
|
||||
this.get = function(moduleName, callback) {
|
||||
|
||||
// if we have a websocket connection
|
||||
if (websocket.connection) {
|
||||
|
||||
// and the connection is ready
|
||||
if (websocket.connection.readyState === 1) {
|
||||
|
||||
// set the callback as the event handler
|
||||
// for server response.
|
||||
//
|
||||
// Callback instance needs to be overwritten
|
||||
// each time for this to work. Not sure why.
|
||||
websocket.onMessageEventHandlers[moduleName] = callback;
|
||||
|
||||
//
|
||||
websocket.connection.send(moduleName);
|
||||
|
||||
} else {
|
||||
console.log("Websocket not ready yet.", moduleName);
|
||||
}
|
||||
|
||||
}
|
||||
// otherwise
|
||||
else {
|
||||
|
||||
var moduleAddress = 'server/?module=' + moduleName;
|
||||
|
||||
return $http.get(moduleAddress).then(function(response) {
|
||||
return callback(response.data);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Hook to run websocket support check.
|
||||
*/
|
||||
angular.module('linuxDash').run(function(server, $location, $rootScope) {
|
||||
|
||||
server.checkIfWebsocketsAreSupported();
|
||||
|
||||
var currentRoute = $location.path();
|
||||
var currentTab = (currentRoute === '/loading')? 'system-status': currentRoute;
|
||||
localStorage.setItem('currentTab', currentTab);
|
||||
|
||||
$location.path('/loading');
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* Sidebar for SPA
|
||||
*/
|
||||
angular.module('linuxDash').directive('navBar', function($location) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'templates/app/navbar.html',
|
||||
link: function(scope) {
|
||||
scope.items = [
|
||||
'system-status',
|
||||
'basic-info',
|
||||
'network',
|
||||
'accounts',
|
||||
'apps'
|
||||
];
|
||||
|
||||
scope.getNavItemName = function(url) {
|
||||
return url.replace('-', ' ');
|
||||
};
|
||||
|
||||
scope.isActive = function(route) {
|
||||
return '/' + route === $location.path();
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
////////////////// UI Element Directives ////////////////// //
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Shows loader
|
||||
*/
|
||||
angular.module('linuxDash').directive('loader', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
width: '@'
|
||||
},
|
||||
template: '<div class="spinner">' +
|
||||
' <div class="rect1"></div>' +
|
||||
' <div class="rect2"></div>' +
|
||||
' <div class="rect3"></div>' +
|
||||
' <div class="rect4"></div>' +
|
||||
' <div class="rect5"></div>' +
|
||||
'</div>'
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Top Bar for widget
|
||||
*/
|
||||
angular.module('linuxDash').directive('topBar', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
heading: '=',
|
||||
refresh: '&',
|
||||
lastUpdated: '=',
|
||||
info: '=',
|
||||
},
|
||||
templateUrl: 'templates/app/ui-elements/top-bar.html',
|
||||
link: function(scope, element, attrs) {
|
||||
var $refreshBtn = element.find('refresh-btn').eq(0);
|
||||
|
||||
if (typeof attrs.noRefreshBtn !== 'undefined') {
|
||||
$refreshBtn.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Shows refresh button and calls
|
||||
* provided expression on-click
|
||||
*/
|
||||
angular.module('linuxDash').directive('refreshBtn', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
refresh: '&'
|
||||
},
|
||||
template: '<button ng-click="refresh()">↺</button>'
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Message shown when no data is found from server
|
||||
*/
|
||||
angular.module('linuxDash').directive('noData', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: 'No Data'
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Displays last updated timestamp for widget
|
||||
*/
|
||||
angular.module('linuxDash').directive('lastUpdate', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
timestamp: '='
|
||||
},
|
||||
templateUrl: 'templates/app/ui-elements/last-update.html'
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
////////////////// Plugin Directives //////////////////
|
||||
|
||||
/**
|
||||
* Fetches and displays table data
|
||||
*/
|
||||
angular.module('linuxDash').directive('tableData', ['server', '$rootScope', function(server, $rootScope) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
heading: '@',
|
||||
info: '@',
|
||||
moduleName: '@'
|
||||
},
|
||||
templateUrl: 'templates/app/table-data-plugin.html',
|
||||
link: function(scope, element) {
|
||||
|
||||
scope.sortByColumn = null;
|
||||
scope.sortReverse = null;
|
||||
|
||||
// set the column to sort by
|
||||
scope.setSortColumn = function(column) {
|
||||
|
||||
// if the column is already being sorted
|
||||
// reverse the order
|
||||
if (column === scope.sortByColumn) {
|
||||
scope.sortReverse = !scope.sortReverse;
|
||||
} else {
|
||||
scope.sortByColumn = column;
|
||||
}
|
||||
|
||||
scope.sortTableRows();
|
||||
};
|
||||
|
||||
scope.sortTableRows = function() {
|
||||
scope.tableRows.sort(function(currentRow, nextRow) {
|
||||
|
||||
var sortResult = 0;
|
||||
|
||||
if (currentRow[scope.sortByColumn] < nextRow[scope.sortByColumn]) {
|
||||
sortResult = -1;
|
||||
} else if (currentRow[scope.sortByColumn] === nextRow[scope.sortByColumn]) {
|
||||
sortResult = 0;
|
||||
} else {
|
||||
sortResult = 1;
|
||||
}
|
||||
|
||||
if (scope.sortReverse) {
|
||||
sortResult = -1 * sortResult;
|
||||
}
|
||||
|
||||
return sortResult;
|
||||
});
|
||||
};
|
||||
|
||||
scope.getData = function() {
|
||||
delete scope.tableRows;
|
||||
|
||||
server.get(scope.moduleName, function(serverResponseData) {
|
||||
|
||||
if (serverResponseData.length > 0) {
|
||||
scope.tableHeaders = Object.keys(serverResponseData[0]);
|
||||
}
|
||||
|
||||
scope.tableRows = serverResponseData;
|
||||
|
||||
if (scope.sortByColumn) {
|
||||
scope.sortTableRows();
|
||||
}
|
||||
|
||||
scope.lastGet = new Date().getTime();
|
||||
|
||||
if (serverResponseData.length < 1) {
|
||||
scope.emptyResult = true;
|
||||
}
|
||||
|
||||
if (!scope.$$phase && !$rootScope.$$phase) scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
scope.getData();
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Fetches and displays table data
|
||||
*/
|
||||
angular.module('linuxDash').directive('keyValueList', ['server', '$rootScope', function(server, $rootScope) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
heading: '@',
|
||||
info: '@',
|
||||
moduleName: '@',
|
||||
},
|
||||
templateUrl: 'templates/app/key-value-list-plugin.html',
|
||||
link: function(scope, element) {
|
||||
|
||||
scope.getData = function() {
|
||||
delete scope.tableRows;
|
||||
|
||||
server.get(scope.moduleName, function(serverResponseData) {
|
||||
scope.tableRows = serverResponseData;
|
||||
scope.lastGet = new Date().getTime();
|
||||
|
||||
if (Object.keys(serverResponseData).length === 0) {
|
||||
scope.emptyResult = true;
|
||||
}
|
||||
|
||||
if (!scope.$$phase && !$rootScope.$$phase) scope.$digest();
|
||||
});
|
||||
};
|
||||
|
||||
scope.getData();
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Fetches and displays data as line chart at a certain refresh rate
|
||||
*/
|
||||
angular.module('linuxDash').directive('lineChartPlugin', ['$interval', '$compile', 'server', function($interval, $compile, server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
heading: '@',
|
||||
moduleName: '@',
|
||||
refreshRate: '=',
|
||||
maxValue: '=',
|
||||
minValue: '=',
|
||||
getDisplayValue: '=',
|
||||
metrics: '=',
|
||||
color: '@'
|
||||
},
|
||||
templateUrl: 'templates/app/line-chart-plugin.html',
|
||||
link: function(scope, element) {
|
||||
|
||||
if (!scope.color) scope.color = '0, 255, 0';
|
||||
|
||||
var series;
|
||||
|
||||
// smoothieJS - Create new chart
|
||||
var chart = new SmoothieChart({
|
||||
borderVisible: false,
|
||||
sharpLines: true,
|
||||
grid: {
|
||||
fillStyle: '#ffffff',
|
||||
strokeStyle: 'rgba(232,230,230,0.93)',
|
||||
sharpLines: true,
|
||||
millisPerLine: 3000,
|
||||
borderVisible: false
|
||||
},
|
||||
labels: {
|
||||
fontSize: 11,
|
||||
precision: 0,
|
||||
fillStyle: '#0f0e0e'
|
||||
},
|
||||
maxValue: parseInt(scope.maxValue),
|
||||
minValue: parseInt(scope.minValue),
|
||||
horizontalLines: [{
|
||||
value: 5,
|
||||
color: '#eff',
|
||||
lineWidth: 1
|
||||
}]
|
||||
});
|
||||
|
||||
// smoothieJS - set up canvas element for chart
|
||||
canvas = element.find('canvas')[0];
|
||||
series = new TimeSeries();
|
||||
|
||||
chart.addTimeSeries(series, {
|
||||
strokeStyle: 'rgba(' + scope.color + ', 1)',
|
||||
fillStyle: 'rgba(' + scope.color + ', 0.2)',
|
||||
lineWidth: 2
|
||||
});
|
||||
|
||||
chart.streamTo(canvas, 1000);
|
||||
|
||||
var dataCallInProgress = false;
|
||||
|
||||
// update data on chart
|
||||
scope.getData = function() {
|
||||
|
||||
if (dataCallInProgress) return;
|
||||
|
||||
dataCallInProgress = true;
|
||||
|
||||
server.get(scope.moduleName, function(serverResponseData) {
|
||||
|
||||
dataCallInProgress = false;
|
||||
scope.lastGet = new Date().getTime();
|
||||
|
||||
// change graph colour depending on usage
|
||||
if (scope.maxValue / 4 * 3 < scope.getDisplayValue(serverResponseData)) {
|
||||
chart.seriesSet[0].options.strokeStyle = 'rgba(255, 89, 0, 1)';
|
||||
chart.seriesSet[0].options.fillStyle = 'rgba(255, 89, 0, 0.2)';
|
||||
} else if (scope.maxValue / 3 < scope.getDisplayValue(serverResponseData)) {
|
||||
chart.seriesSet[0].options.strokeStyle = 'rgba(255, 238, 0, 1)';
|
||||
chart.seriesSet[0].options.fillStyle = 'rgba(255, 238, 0, 0.2)';
|
||||
} else {
|
||||
chart.seriesSet[0].options.strokeStyle = 'rgba(' + scope.color + ', 1)';
|
||||
chart.seriesSet[0].options.fillStyle = 'rgba(' + scope.color + ', 0.2)';
|
||||
}
|
||||
|
||||
// update chart with this response
|
||||
series.append(scope.lastGet, scope.getDisplayValue(serverResponseData));
|
||||
|
||||
// update the metrics for this chart
|
||||
scope.metrics.forEach(function(metricObj) {
|
||||
metricObj.data = metricObj.generate(serverResponseData);
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
// set the directive-provided interval
|
||||
// at which to run the chart update
|
||||
var intervalRef = $interval(scope.getData, scope.refreshRate);
|
||||
var removeInterval = function() {
|
||||
$interval.cancel(intervalRef);
|
||||
};
|
||||
|
||||
element.on("$destroy", removeInterval);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Fetches and displays data as line chart at a certain refresh rate
|
||||
*
|
||||
*/
|
||||
angular.module('linuxDash').directive('multiLineChartPlugin', ['$interval', '$compile', 'server', function($interval, $compile, server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
heading: '@',
|
||||
moduleName: '@',
|
||||
refreshRate: '=',
|
||||
getDisplayValue: '=',
|
||||
units: '=',
|
||||
delay: '='
|
||||
},
|
||||
templateUrl: 'templates/app/multi-line-chart-plugin.html',
|
||||
link: function(scope, element) {
|
||||
|
||||
// smoothieJS - Create new chart
|
||||
var chart = new SmoothieChart({
|
||||
borderVisible: false,
|
||||
sharpLines: true,
|
||||
grid: {
|
||||
fillStyle: '#ffffff',
|
||||
strokeStyle: 'rgba(232,230,230,0.93)',
|
||||
sharpLines: true,
|
||||
borderVisible: false
|
||||
},
|
||||
labels: {
|
||||
fontSize: 12,
|
||||
precision: 0,
|
||||
fillStyle: '#0f0e0e'
|
||||
},
|
||||
maxValue: 100,
|
||||
minValue: 0,
|
||||
horizontalLines: [{
|
||||
value: 1,
|
||||
color: '#ecc',
|
||||
lineWidth: 1
|
||||
}]
|
||||
});
|
||||
|
||||
var seriesOptions = [{
|
||||
strokeStyle: 'rgba(255, 0, 0, 1)',
|
||||
lineWidth: 2
|
||||
}, {
|
||||
strokeStyle: 'rgba(0, 255, 0, 1)',
|
||||
lineWidth: 2
|
||||
}, {
|
||||
strokeStyle: 'rgba(0, 0, 255, 1)',
|
||||
lineWidth: 2
|
||||
}, {
|
||||
strokeStyle: 'rgba(255, 255, 0, 1)',
|
||||
lineWidth: 1
|
||||
}];
|
||||
|
||||
// smoothieJS - set up canvas element for chart
|
||||
var canvas = element.find('canvas')[0];
|
||||
scope.seriesArray = [];
|
||||
scope.metricsArray = [];
|
||||
|
||||
// get the data once to set up # of lines on chart
|
||||
server.get(scope.moduleName, function(serverResponseData) {
|
||||
|
||||
var numberOfLines = Object.keys(serverResponseData).length;
|
||||
|
||||
for (var x = 0; x < numberOfLines; x++) {
|
||||
|
||||
var keyForThisLine = Object.keys(serverResponseData)[x];
|
||||
|
||||
scope.seriesArray[x] = new TimeSeries();
|
||||
chart.addTimeSeries(scope.seriesArray[x], seriesOptions[x]);
|
||||
scope.metricsArray[x] = {
|
||||
name: keyForThisLine,
|
||||
color: seriesOptions[x].strokeStyle,
|
||||
};
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var delay = 1000;
|
||||
|
||||
if (angular.isDefined(scope.delay))
|
||||
delay = scope.delay;
|
||||
|
||||
chart.streamTo(canvas, delay);
|
||||
|
||||
var dataCallInProgress = false;
|
||||
|
||||
// update data on chart
|
||||
scope.getData = function() {
|
||||
|
||||
if (dataCallInProgress) return;
|
||||
|
||||
if (!scope.seriesArray.length) return;
|
||||
|
||||
dataCallInProgress = true;
|
||||
|
||||
server.get(scope.moduleName, function(serverResponseData) {
|
||||
|
||||
dataCallInProgress = false;
|
||||
scope.lastGet = new Date().getTime();
|
||||
var keyCount = 0;
|
||||
var maxAvg = 100;
|
||||
|
||||
// update chart with current response
|
||||
for (var key in serverResponseData) {
|
||||
scope.seriesArray[keyCount].append(scope.lastGet, serverResponseData[key]);
|
||||
keyCount++;
|
||||
maxAvg = Math.max(maxAvg, serverResponseData[key]);
|
||||
}
|
||||
|
||||
// update the metrics for this chart
|
||||
scope.metricsArray.forEach(function(metricObj) {
|
||||
metricObj.data = serverResponseData[metricObj.name].toString() + ' ' + scope.units;
|
||||
});
|
||||
|
||||
// round up the average and set the maximum scale
|
||||
var len = parseInt(Math.log(maxAvg) / Math.log(10));
|
||||
var div = Math.pow(10, len);
|
||||
chart.options.maxValue = Math.ceil(maxAvg / div) * div;
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var refreshRate = (angular.isDefined(scope.refreshRate)) ? scope.refreshRate : 1000;
|
||||
var intervalRef = $interval(scope.getData, refreshRate);
|
||||
var removeInterval = function() {
|
||||
$interval.cancel(intervalRef);
|
||||
};
|
||||
|
||||
element.on("$destroy", removeInterval);
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
/**
|
||||
* Base plugin structure
|
||||
*/
|
||||
angular.module('linuxDash').directive('plugin', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
templateUrl: 'templates/app/base-plugin.html'
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Progress bar element
|
||||
*/
|
||||
angular.module('linuxDash').directive('progressBarPlugin', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
width: '@',
|
||||
moduleName: '@',
|
||||
name: '@',
|
||||
value: '@',
|
||||
max: '@'
|
||||
},
|
||||
templateUrl: 'templates/app/progress-bar-plugin.html'
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Theme switcher
|
||||
*/
|
||||
angular.module('linuxDash').directive('themeSwitcher', ['$location', function($location) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
templateUrl: 'templates/app/theme-switcher.html',
|
||||
link: function(scope) {
|
||||
|
||||
// alternate themes available
|
||||
scope.themes = [{
|
||||
name: 'winter',
|
||||
}, {
|
||||
name: 'summer',
|
||||
}, {
|
||||
name: 'spring',
|
||||
}, {
|
||||
name: 'fall',
|
||||
}, {
|
||||
name: 'old',
|
||||
}, ];
|
||||
|
||||
scope.themeSwitcherOpen = false;
|
||||
|
||||
scope.switchTheme = function(theme) {
|
||||
|
||||
if (theme.selected) {
|
||||
scope.setDefaultTheme();
|
||||
return;
|
||||
}
|
||||
|
||||
scope.removeExistingThemes();
|
||||
theme.selected = true;
|
||||
document.getElementsByTagName('html')[0].className = theme.name;
|
||||
localStorage.setItem('theme', theme.name);
|
||||
};
|
||||
|
||||
scope.toggleThemeSwitcher = function() {
|
||||
scope.themeSwitcherOpen = !scope.themeSwitcherOpen;
|
||||
};
|
||||
|
||||
scope.removeExistingThemes = function() {
|
||||
scope.themes.forEach(function(item) {
|
||||
item.selected = false;
|
||||
});
|
||||
};
|
||||
|
||||
scope.setDefaultTheme = function() {
|
||||
scope.removeExistingThemes();
|
||||
document.getElementsByTagName('html')[0].className = '';
|
||||
localStorage.setItem('theme', null);
|
||||
};
|
||||
|
||||
// on load, check if theme was set in localStorage
|
||||
if (localStorage.getItem('theme')) {
|
||||
|
||||
scope.themes.forEach(function(theme) {
|
||||
|
||||
if (theme.name === localStorage.getItem('theme')) {
|
||||
scope.switchTheme(theme);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
}());
|
|
@ -1,284 +0,0 @@
|
|||
(function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
////////////////// Module Directives /////////////////// //
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
angular.module('linuxDash').directive('diskSpace', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/disk-space.html',
|
||||
link: function(scope) {
|
||||
|
||||
scope.heading = "Disk Partitions";
|
||||
|
||||
scope.getData = function() {
|
||||
server.get('disk_partitions', function(serverResponseData) {
|
||||
scope.diskSpaceData = serverResponseData;
|
||||
});
|
||||
|
||||
scope.lastGet = new Date().getTime();
|
||||
};
|
||||
|
||||
scope.getData();
|
||||
|
||||
scope.getKB = function(stringSize) {
|
||||
var lastChar = stringSize.slice(-1),
|
||||
size = parseInt(stringSize);
|
||||
|
||||
switch (lastChar) {
|
||||
case 'M':
|
||||
return size * Math.pow(1024, 1);
|
||||
case 'G':
|
||||
return size * Math.pow(1024, 2);
|
||||
case 'T':
|
||||
return size * Math.pow(1024, 3);
|
||||
case 'P':
|
||||
return size * Math.pow(1024, 4);
|
||||
case 'E':
|
||||
return size * Math.pow(1024, 5);
|
||||
case 'Z':
|
||||
return size * Math.pow(1024, 6);
|
||||
case 'Y':
|
||||
return size * Math.pow(1024, 7);
|
||||
default:
|
||||
return size;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('linuxDash').directive('ramChart', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/ram-chart.html',
|
||||
link: function(scope) {
|
||||
|
||||
// get max ram available on machine before we
|
||||
// can start charting
|
||||
server.get('current_ram', function(resp) {
|
||||
scope.maxRam = resp.total;
|
||||
scope.minRam = 0;
|
||||
});
|
||||
|
||||
scope.ramToDisplay = function(serverResponseData) {
|
||||
return serverResponseData.used;
|
||||
};
|
||||
|
||||
var humanizeRam = function (ramInMB) {
|
||||
var ram = {
|
||||
value: parseInt(ramInMB, 10),
|
||||
unit: 'MB',
|
||||
};
|
||||
|
||||
// if ram > 1,000 MB, use GB
|
||||
if (ram.value > 1000) {
|
||||
ram = {
|
||||
value: (ramInMB/1024).toFixed(2),
|
||||
unit: 'GB',
|
||||
};
|
||||
}
|
||||
|
||||
return ram.value + ' ' + ram.unit;
|
||||
};
|
||||
|
||||
scope.ramMetrics = [{
|
||||
name: 'Used',
|
||||
generate: function(serverResponseData) {
|
||||
var ratio = serverResponseData.used / serverResponseData.total;
|
||||
var percentage = parseInt(ratio * 100);
|
||||
|
||||
var usedRam = humanizeRam(serverResponseData.used);
|
||||
return usedRam + ' (' + percentage.toString() + '%)';
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Free',
|
||||
generate: function(serverResponseData) {
|
||||
|
||||
var freeRam = humanizeRam(serverResponseData.free);
|
||||
var totalRam = humanizeRam(serverResponseData.total);
|
||||
return freeRam + ' of ' + totalRam;
|
||||
}
|
||||
}];
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('linuxDash').directive('cpuAvgLoadChart', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/cpu-load.html',
|
||||
link: function(scope) {
|
||||
scope.units = '%';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('linuxDash').directive('cpuUtilizationChart', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/cpu-utilization-chart.html',
|
||||
link: function(scope) {
|
||||
scope.min = 0;
|
||||
scope.max = 100;
|
||||
|
||||
scope.displayValue = function(serverResponseData) {
|
||||
return serverResponseData;
|
||||
};
|
||||
|
||||
scope.utilMetrics = [{
|
||||
name: 'Usage',
|
||||
generate: function(serverResponseData) {
|
||||
return serverResponseData + ' %';
|
||||
}
|
||||
}];
|
||||
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('linuxDash').directive('uploadTransferRateChart', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/upload-transfer-rate.html',
|
||||
link: function(scope) {
|
||||
scope.delay = 2000;
|
||||
scope.units = 'KB/s';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
angular.module('linuxDash').directive('downloadTransferRateChart', ['server', function(server) {
|
||||
return {
|
||||
restrict: 'E',
|
||||
scope: {},
|
||||
templateUrl: 'templates/modules/download-transfer-rate.html',
|
||||
link: function(scope) {
|
||||
scope.delay = 2000;
|
||||
scope.units = 'KB/s';
|
||||
}
|
||||
};
|
||||
}]);
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
/////////////// Table Data Modules //////////////////// //
|
||||
//////////////////////////////////////////////////////////
|
||||
var simpleTableModules = [
|
||||
{
|
||||
name: 'machineInfo',
|
||||
template: '<key-value-list heading="General Info." module-name="general_info" info="System Information"></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'ipAddresses',
|
||||
template: '<table-data heading="IP Addresses" module-name="ip_addresses" info="IPs assigned to this server"></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'ramIntensiveProcesses',
|
||||
template: '<table-data heading="RAM Intensive Processes" module-name="ram_intensive_processes" info="Processes which are using most RAM."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'cpuIntensiveProcesses',
|
||||
template: '<table-data heading="CPU Intensive Processes" module-name="cpu_intensive_processes" info="Processes which are using most CPU."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'networkConnections',
|
||||
template: '<table-data heading="Network Connections" module-name="network_connections"></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'serverAccounts',
|
||||
template: '<table-data heading="Accounts" module-name="user_accounts" info="User accounts on this server."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'loggedInAccounts',
|
||||
template: '<table-data heading="Logged In Accounts" module-name="logged_in_users" info="Users currently logged in."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'recentLogins',
|
||||
template: '<table-data heading="Recent Logins" module-name="recent_account_logins" info="Recent user sessions."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'arpCacheTable',
|
||||
template: '<table-data heading="ARP Cache Table" module-name="arp_cache"></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'commonApplications',
|
||||
template: '<table-data heading="Common Applications" module-name="common_applications" info="List of commonly installed applications."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'pingSpeeds',
|
||||
template: '<table-data heading="Ping Speeds" module-name="ping" info="Ping speed in milliseconds."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'bandwidth',
|
||||
template: '<table-data heading="Bandwidth" module-name="bandwidth"></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'swapUsage',
|
||||
template: '<table-data heading="Swap Usage" module-name="swap"></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'internetSpeed',
|
||||
template: '<key-value-list heading="Internet Speed" module-name="internet_speed" info="Internet connection speed of server."></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'memcached',
|
||||
template: '<key-value-list heading="Memcached" module-name="memcached"></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'redis',
|
||||
template: '<key-value-list heading="Redis" module-name="redis"></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'memoryInfo',
|
||||
template: '<key-value-list heading="Memory Info" module-name="memory_info" info="/proc/meminfo read-out."></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'cpuInfo',
|
||||
template: '<key-value-list heading="CPU Info" module-name="cpu_info" info="/usr/bin/lscpu read-out."></key-value-list>'
|
||||
},
|
||||
{
|
||||
name: 'ioStats',
|
||||
template: '<table-data heading="IO Stats" module-name="io_stats" info="/proc/diskstats read-out."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'scheduledCrons',
|
||||
template: '<table-data heading="Scheduled Cron Jobs" module-name="scheduled_crons" info="Crons for all users on the server."></table-data>'
|
||||
},
|
||||
{
|
||||
name: 'cronHistory',
|
||||
template: '<table-data heading="Cron Job History" module-name="cron_history" info="Crons which have run recently."></table-data>'
|
||||
}
|
||||
];
|
||||
|
||||
simpleTableModules.forEach(function(module, key) {
|
||||
|
||||
angular.module('linuxDash').directive(module.name, ['server', function(server) {
|
||||
|
||||
var moduleDirective = {
|
||||
restrict: 'E',
|
||||
scope: {}
|
||||
};
|
||||
|
||||
if (module.templateUrl) {
|
||||
moduleDirective['templateUrl'] = 'templates/modules/' + module.templateUrl
|
||||
}
|
||||
|
||||
if (module.template) {
|
||||
moduleDirective['template'] = module.template;
|
||||
}
|
||||
|
||||
return moduleDirective;
|
||||
}]);
|
||||
|
||||
});
|
||||
|
||||
}());
|
1
sources/js/smoothie.min.js
vendored
1
sources/js/smoothie.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"name": "linux-dash",
|
||||
"version": "1.2.0",
|
||||
"description": "A simple, low overhead web dashboard for linux.",
|
||||
"main": "server/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/afaqurk/linux-dash.git"
|
||||
},
|
||||
"keywords": [
|
||||
"linux",
|
||||
"gnu",
|
||||
"dashboard",
|
||||
"monitor",
|
||||
"server"
|
||||
],
|
||||
"author": "Afaq Tariq",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/afaqurk/linux-dash/issues"
|
||||
},
|
||||
"homepage": "https://github.com/afaqurk/linux-dash",
|
||||
"dependencies": {
|
||||
"express": "^4.11.1",
|
||||
"websocket": "^1.0.22"
|
||||
}
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer, test as _test
|
||||
import subprocess
|
||||
from SocketServer import ThreadingMixIn
|
||||
|
||||
modulesSubPath = '/server/modules/shell_files/'
|
||||
serverPath = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
|
||||
pass
|
||||
|
||||
class MainHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
try:
|
||||
data = ''
|
||||
contentType = 'text/html'
|
||||
if self.path.startswith("/server/"):
|
||||
module = self.path.split('=')[1]
|
||||
output = subprocess.Popen(
|
||||
serverPath + modulesSubPath + module + '.sh',
|
||||
shell = True,
|
||||
stdout = subprocess.PIPE)
|
||||
data = output.communicate()[0]
|
||||
else:
|
||||
if self.path == '/':
|
||||
self.path = 'index.html'
|
||||
f = open(os.path.dirname(os.path.realpath(__file__)) + os.sep + self.path)
|
||||
data = f.read()
|
||||
if self.path.startswith('/css/'):
|
||||
contentType = 'text/css'
|
||||
f.close()
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', contentType)
|
||||
self.end_headers()
|
||||
self.wfile.write(data)
|
||||
|
||||
except IOError:
|
||||
self.send_error(404, 'File Not Found: %s' % self.path)
|
||||
|
||||
if __name__ == '__main__':
|
||||
server = ThreadedHTTPServer(('localhost', 8081), MainHandler)
|
||||
print 'Starting server, use <Ctrl-C> to stop'
|
||||
server.serve_forever()
|
|
@ -1,53 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
var (
|
||||
listenAddress = flag.String("listen", "0.0.0.0:80", "Where the server listens for connections. [interface]:port")
|
||||
staticPath = flag.String("static", "../", "Location of static files.")
|
||||
scriptPath = flag.String("scripts", "./modules/shell_files", "Location of shell scripts used to gather stats.")
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.Handle("/", http.FileServer(http.Dir(*staticPath)))
|
||||
http.HandleFunc("/server/", func(w http.ResponseWriter, r *http.Request) {
|
||||
module := r.URL.Query().Get("module")
|
||||
script := filepath.Join(*scriptPath, module+".sh")
|
||||
if module == "" {
|
||||
http.Error(w, "No module specified, or requested module doesn't exist.", 406)
|
||||
return
|
||||
}
|
||||
|
||||
// Execute the command
|
||||
cmd := exec.Command(script)
|
||||
var output bytes.Buffer
|
||||
cmd.Stdout = &output
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
fmt.Printf("Error executing '%s': %s\n\tScript output: %s\n", script, err.Error(), output.String())
|
||||
http.Error(w, "Unable to execute module.", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(output.Bytes())
|
||||
})
|
||||
|
||||
fmt.Println("Starting http server at:", *listenAddress)
|
||||
err := http.ListenAndServe(*listenAddress, nil)
|
||||
if err != nil {
|
||||
fmt.Println("Error starting http server:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
|
@ -1,107 +0,0 @@
|
|||
var express = require('express');
|
||||
var app = require('express')();
|
||||
var server = require('http').Server(app);
|
||||
var path = require('path');
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
var ws = require('websocket').server;
|
||||
|
||||
server.listen(80);
|
||||
console.log('Linux Dash Server Started!');
|
||||
|
||||
app.use(express.static(path.resolve(__dirname + '/../')));
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
res.sendFile(path.resolve(__dirname + '/../index.html'));
|
||||
});
|
||||
|
||||
app.get('/websocket', function (req, res) {
|
||||
|
||||
res.send({
|
||||
websocket_support: true,
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
wsServer = new ws({
|
||||
httpServer: server
|
||||
});
|
||||
|
||||
function getShellFilePath(moduleName) {
|
||||
return __dirname + '/modules/shell_files/' + moduleName + '.sh';
|
||||
}
|
||||
|
||||
function shellPathAndModuleNameAreValid(shellFilePath, moduleName) {
|
||||
|
||||
var moduleInvalidName = moduleName.indexOf('.') > -1;
|
||||
var moduleNameEmpty = !moduleName;
|
||||
var moduleNotFound = !fs.existsSync(shellFilePath);
|
||||
var isValid = true;
|
||||
|
||||
if (moduleInvalidName || moduleNameEmpty || moduleNotFound) {
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
wsServer.on('request', function(request) {
|
||||
|
||||
var wsClient = request.accept('linux-dash', request.origin);
|
||||
|
||||
wsClient.on('message', function(wsReq) {
|
||||
|
||||
var moduleName = wsReq.utf8Data;
|
||||
var shellFile = getShellFilePath(moduleName);
|
||||
|
||||
if (!shellPathAndModuleNameAreValid(shellFile, moduleName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var command = spawn(shellFile, [ wsReq.color || '' ]);
|
||||
var output = [];
|
||||
|
||||
command.stdout.on('data', function(chunk) {
|
||||
output.push(chunk);
|
||||
});
|
||||
|
||||
command.on('close', function(code) {
|
||||
|
||||
if (code === 0) {
|
||||
|
||||
var wsResponse = {
|
||||
moduleName: moduleName,
|
||||
output: output.toString(),
|
||||
};
|
||||
|
||||
wsClient.sendUTF(JSON.stringify(wsResponse));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
app.get('/server/', function (req, res) {
|
||||
|
||||
var shellFile = getShellFilePath(req.query.module);
|
||||
|
||||
if (!shellPathAndModuleNameAreValid(shellFile, req.query.module)) {
|
||||
res.sendStatus(406);
|
||||
return;
|
||||
}
|
||||
|
||||
var command = spawn(shellFile, [ req.query.color || '' ]);
|
||||
var output = [];
|
||||
|
||||
command.stdout.on('data', function(chunk) {
|
||||
output.push(chunk);
|
||||
});
|
||||
|
||||
command.on('close', function(code) {
|
||||
if (code === 0) res.send(output.toString());
|
||||
else res.sendStatus(500);
|
||||
});
|
||||
|
||||
});
|
|
@ -1,8 +0,0 @@
|
|||
<?php
|
||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||
header("Pragma: no-cache");
|
||||
|
||||
$modules_dir = dirname(__FILE__) . '/modules/shell_files/';
|
||||
$module = escapeshellcmd($_GET['module']);
|
||||
|
||||
echo shell_exec( $modules_dir . $module . '.sh' );
|
|
@ -1,3 +0,0 @@
|
|||
google.com
|
||||
yahoo.com
|
||||
twitter.com
|
|
@ -1,694 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2012-2014 Matt Martz
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
__version__ = '0.3.1'
|
||||
|
||||
# Some global variables we use
|
||||
source = None
|
||||
shutdown_event = None
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import math
|
||||
import signal
|
||||
import socket
|
||||
import timeit
|
||||
import threading
|
||||
|
||||
# Used for bound_interface
|
||||
socket_socket = socket.socket
|
||||
|
||||
try:
|
||||
import xml.etree.cElementTree as ET
|
||||
except ImportError:
|
||||
try:
|
||||
import xml.etree.ElementTree as ET
|
||||
except ImportError:
|
||||
from xml.dom import minidom as DOM
|
||||
ET = None
|
||||
|
||||
# Begin import game to handle Python 2 and Python 3
|
||||
try:
|
||||
from urllib2 import urlopen, Request, HTTPError, URLError
|
||||
except ImportError:
|
||||
from urllib.request import urlopen, Request, HTTPError, URLError
|
||||
|
||||
try:
|
||||
from httplib import HTTPConnection, HTTPSConnection
|
||||
except ImportError:
|
||||
from http.client import HTTPConnection, HTTPSConnection
|
||||
|
||||
try:
|
||||
from Queue import Queue
|
||||
except ImportError:
|
||||
from queue import Queue
|
||||
|
||||
try:
|
||||
from urlparse import urlparse
|
||||
except ImportError:
|
||||
from urllib.parse import urlparse
|
||||
|
||||
try:
|
||||
from urlparse import parse_qs
|
||||
except ImportError:
|
||||
try:
|
||||
from urllib.parse import parse_qs
|
||||
except ImportError:
|
||||
from cgi import parse_qs
|
||||
|
||||
try:
|
||||
from hashlib import md5
|
||||
except ImportError:
|
||||
from md5 import md5
|
||||
|
||||
try:
|
||||
from argparse import ArgumentParser as ArgParser
|
||||
except ImportError:
|
||||
from optparse import OptionParser as ArgParser
|
||||
|
||||
try:
|
||||
import builtins
|
||||
except ImportError:
|
||||
def print_(*args, **kwargs):
|
||||
"""The new-style print function taken from
|
||||
https://pypi.python.org/pypi/six/
|
||||
|
||||
"""
|
||||
fp = kwargs.pop("file", sys.stdout)
|
||||
if fp is None:
|
||||
return
|
||||
|
||||
def write(data):
|
||||
if not isinstance(data, basestring):
|
||||
data = str(data)
|
||||
fp.write(data)
|
||||
|
||||
want_unicode = False
|
||||
sep = kwargs.pop("sep", None)
|
||||
if sep is not None:
|
||||
if isinstance(sep, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(sep, str):
|
||||
raise TypeError("sep must be None or a string")
|
||||
end = kwargs.pop("end", None)
|
||||
if end is not None:
|
||||
if isinstance(end, unicode):
|
||||
want_unicode = True
|
||||
elif not isinstance(end, str):
|
||||
raise TypeError("end must be None or a string")
|
||||
if kwargs:
|
||||
raise TypeError("invalid keyword arguments to print()")
|
||||
if not want_unicode:
|
||||
for arg in args:
|
||||
if isinstance(arg, unicode):
|
||||
want_unicode = True
|
||||
break
|
||||
if want_unicode:
|
||||
newline = unicode("\n")
|
||||
space = unicode(" ")
|
||||
else:
|
||||
newline = "\n"
|
||||
space = " "
|
||||
if sep is None:
|
||||
sep = space
|
||||
if end is None:
|
||||
end = newline
|
||||
for i, arg in enumerate(args):
|
||||
if i:
|
||||
write(sep)
|
||||
write(arg)
|
||||
write(end)
|
||||
else:
|
||||
print_ = getattr(builtins, 'print')
|
||||
del builtins
|
||||
|
||||
|
||||
def bound_socket(*args, **kwargs):
|
||||
"""Bind socket to a specified source IP address"""
|
||||
|
||||
global source
|
||||
sock = socket_socket(*args, **kwargs)
|
||||
sock.bind((source, 0))
|
||||
return sock
|
||||
|
||||
|
||||
def distance(origin, destination):
|
||||
"""Determine distance between 2 sets of [lat,lon] in km"""
|
||||
|
||||
lat1, lon1 = origin
|
||||
lat2, lon2 = destination
|
||||
radius = 6371 # km
|
||||
|
||||
dlat = math.radians(lat2 - lat1)
|
||||
dlon = math.radians(lon2 - lon1)
|
||||
a = (math.sin(dlat / 2) * math.sin(dlat / 2) + math.cos(math.radians(lat1))
|
||||
* math.cos(math.radians(lat2)) * math.sin(dlon / 2)
|
||||
* math.sin(dlon / 2))
|
||||
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
|
||||
d = radius * c
|
||||
|
||||
return d
|
||||
|
||||
|
||||
class FileGetter(threading.Thread):
|
||||
"""Thread class for retrieving a URL"""
|
||||
|
||||
def __init__(self, url, start):
|
||||
self.url = url
|
||||
self.result = None
|
||||
self.starttime = start
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
self.result = [0]
|
||||
try:
|
||||
if (timeit.default_timer() - self.starttime) <= 10:
|
||||
f = urlopen(self.url)
|
||||
while 1 and not shutdown_event.isSet():
|
||||
self.result.append(len(f.read(10240)))
|
||||
if self.result[-1] == 0:
|
||||
break
|
||||
f.close()
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
|
||||
def downloadSpeed(files, quiet=False):
|
||||
"""Function to launch FileGetter threads and calculate download speeds"""
|
||||
|
||||
start = timeit.default_timer()
|
||||
|
||||
def producer(q, files):
|
||||
for file in files:
|
||||
thread = FileGetter(file, start)
|
||||
thread.start()
|
||||
q.put(thread, True)
|
||||
if not quiet and not shutdown_event.isSet():
|
||||
sys.stdout.write('.')
|
||||
sys.stdout.flush()
|
||||
|
||||
finished = []
|
||||
|
||||
def consumer(q, total_files):
|
||||
while len(finished) < total_files:
|
||||
thread = q.get(True)
|
||||
while thread.isAlive():
|
||||
thread.join(timeout=0.1)
|
||||
finished.append(sum(thread.result))
|
||||
del thread
|
||||
|
||||
q = Queue(6)
|
||||
prod_thread = threading.Thread(target=producer, args=(q, files))
|
||||
cons_thread = threading.Thread(target=consumer, args=(q, len(files)))
|
||||
start = timeit.default_timer()
|
||||
prod_thread.start()
|
||||
cons_thread.start()
|
||||
while prod_thread.isAlive():
|
||||
prod_thread.join(timeout=0.1)
|
||||
while cons_thread.isAlive():
|
||||
cons_thread.join(timeout=0.1)
|
||||
return (sum(finished) / (timeit.default_timer() - start))
|
||||
|
||||
|
||||
class FilePutter(threading.Thread):
|
||||
"""Thread class for putting a URL"""
|
||||
|
||||
def __init__(self, url, start, size):
|
||||
self.url = url
|
||||
chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
data = chars * (int(round(int(size) / 36.0)))
|
||||
self.data = ('content1=%s' % data[0:int(size) - 9]).encode()
|
||||
del data
|
||||
self.result = None
|
||||
self.starttime = start
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
if ((timeit.default_timer() - self.starttime) <= 10 and
|
||||
not shutdown_event.isSet()):
|
||||
f = urlopen(self.url, self.data)
|
||||
f.read(11)
|
||||
f.close()
|
||||
self.result = len(self.data)
|
||||
else:
|
||||
self.result = 0
|
||||
except IOError:
|
||||
self.result = 0
|
||||
|
||||
|
||||
def uploadSpeed(url, sizes, quiet=False):
|
||||
"""Function to launch FilePutter threads and calculate upload speeds"""
|
||||
|
||||
start = timeit.default_timer()
|
||||
|
||||
def producer(q, sizes):
|
||||
for size in sizes:
|
||||
thread = FilePutter(url, start, size)
|
||||
thread.start()
|
||||
q.put(thread, True)
|
||||
if not quiet and not shutdown_event.isSet():
|
||||
sys.stdout.write('.')
|
||||
sys.stdout.flush()
|
||||
|
||||
finished = []
|
||||
|
||||
def consumer(q, total_sizes):
|
||||
while len(finished) < total_sizes:
|
||||
thread = q.get(True)
|
||||
while thread.isAlive():
|
||||
thread.join(timeout=0.1)
|
||||
finished.append(thread.result)
|
||||
del thread
|
||||
|
||||
q = Queue(6)
|
||||
prod_thread = threading.Thread(target=producer, args=(q, sizes))
|
||||
cons_thread = threading.Thread(target=consumer, args=(q, len(sizes)))
|
||||
start = timeit.default_timer()
|
||||
prod_thread.start()
|
||||
cons_thread.start()
|
||||
while prod_thread.isAlive():
|
||||
prod_thread.join(timeout=0.1)
|
||||
while cons_thread.isAlive():
|
||||
cons_thread.join(timeout=0.1)
|
||||
return (sum(finished) / (timeit.default_timer() - start))
|
||||
|
||||
|
||||
def getAttributesByTagName(dom, tagName):
|
||||
"""Retrieve an attribute from an XML document and return it in a
|
||||
consistent format
|
||||
|
||||
Only used with xml.dom.minidom, which is likely only to be used
|
||||
with python versions older than 2.5
|
||||
"""
|
||||
elem = dom.getElementsByTagName(tagName)[0]
|
||||
return dict(list(elem.attributes.items()))
|
||||
|
||||
|
||||
def getConfig():
|
||||
"""Download the speedtest.net configuration and return only the data
|
||||
we are interested in
|
||||
"""
|
||||
|
||||
uh = urlopen('http://www.speedtest.net/speedtest-config.php')
|
||||
configxml = []
|
||||
while 1:
|
||||
configxml.append(uh.read(10240))
|
||||
if len(configxml[-1]) == 0:
|
||||
break
|
||||
if int(uh.code) != 200:
|
||||
return None
|
||||
uh.close()
|
||||
try:
|
||||
try:
|
||||
root = ET.fromstring(''.encode().join(configxml))
|
||||
config = {
|
||||
'client': root.find('client').attrib,
|
||||
'times': root.find('times').attrib,
|
||||
'download': root.find('download').attrib,
|
||||
'upload': root.find('upload').attrib}
|
||||
except AttributeError:
|
||||
root = DOM.parseString(''.join(configxml))
|
||||
config = {
|
||||
'client': getAttributesByTagName(root, 'client'),
|
||||
'times': getAttributesByTagName(root, 'times'),
|
||||
'download': getAttributesByTagName(root, 'download'),
|
||||
'upload': getAttributesByTagName(root, 'upload')}
|
||||
except SyntaxError:
|
||||
print_('Failed to parse speedtest.net configuration')
|
||||
sys.exit(1)
|
||||
del root
|
||||
del configxml
|
||||
return config
|
||||
|
||||
|
||||
def closestServers(client, all=False):
|
||||
"""Determine the 5 closest speedtest.net servers based on geographic
|
||||
distance
|
||||
"""
|
||||
|
||||
uh = urlopen('http://www.speedtest.net/speedtest-servers-static.php')
|
||||
serversxml = []
|
||||
while 1:
|
||||
serversxml.append(uh.read(10240))
|
||||
if len(serversxml[-1]) == 0:
|
||||
break
|
||||
if int(uh.code) != 200:
|
||||
return None
|
||||
uh.close()
|
||||
try:
|
||||
try:
|
||||
root = ET.fromstring(''.encode().join(serversxml))
|
||||
elements = root.getiterator('server')
|
||||
except AttributeError:
|
||||
root = DOM.parseString(''.join(serversxml))
|
||||
elements = root.getElementsByTagName('server')
|
||||
except SyntaxError:
|
||||
print_('Failed to parse list of speedtest.net servers')
|
||||
sys.exit(1)
|
||||
servers = {}
|
||||
for server in elements:
|
||||
try:
|
||||
attrib = server.attrib
|
||||
except AttributeError:
|
||||
attrib = dict(list(server.attributes.items()))
|
||||
d = distance([float(client['lat']), float(client['lon'])],
|
||||
[float(attrib.get('lat')), float(attrib.get('lon'))])
|
||||
attrib['d'] = d
|
||||
if d not in servers:
|
||||
servers[d] = [attrib]
|
||||
else:
|
||||
servers[d].append(attrib)
|
||||
del root
|
||||
del serversxml
|
||||
del elements
|
||||
|
||||
closest = []
|
||||
for d in sorted(servers.keys()):
|
||||
for s in servers[d]:
|
||||
closest.append(s)
|
||||
if len(closest) == 5 and not all:
|
||||
break
|
||||
else:
|
||||
continue
|
||||
break
|
||||
|
||||
del servers
|
||||
return closest
|
||||
|
||||
|
||||
def getBestServer(servers):
|
||||
"""Perform a speedtest.net latency request to determine which
|
||||
speedtest.net server has the lowest latency
|
||||
"""
|
||||
|
||||
results = {}
|
||||
for server in servers:
|
||||
cum = []
|
||||
url = '%s/latency.txt' % os.path.dirname(server['url'])
|
||||
urlparts = urlparse(url)
|
||||
for i in range(0, 3):
|
||||
try:
|
||||
if urlparts[0] == 'https':
|
||||
h = HTTPSConnection(urlparts[1])
|
||||
else:
|
||||
h = HTTPConnection(urlparts[1])
|
||||
start = timeit.default_timer()
|
||||
h.request("GET", urlparts[2])
|
||||
r = h.getresponse()
|
||||
total = (timeit.default_timer() - start)
|
||||
except (HTTPError, URLError, socket.error):
|
||||
cum.append(3600)
|
||||
continue
|
||||
text = r.read(9)
|
||||
if int(r.status) == 200 and text == 'test=test'.encode():
|
||||
cum.append(total)
|
||||
else:
|
||||
cum.append(3600)
|
||||
h.close()
|
||||
avg = round((sum(cum) / 6) * 1000, 3)
|
||||
results[avg] = server
|
||||
fastest = sorted(results.keys())[0]
|
||||
best = results[fastest]
|
||||
best['latency'] = fastest
|
||||
|
||||
return best
|
||||
|
||||
|
||||
def ctrl_c(signum, frame):
|
||||
"""Catch Ctrl-C key sequence and set a shutdown_event for our threaded
|
||||
operations
|
||||
"""
|
||||
|
||||
global shutdown_event
|
||||
shutdown_event.set()
|
||||
raise SystemExit('\nCancelling...')
|
||||
|
||||
|
||||
def version():
|
||||
"""Print the version"""
|
||||
|
||||
raise SystemExit(__version__)
|
||||
|
||||
|
||||
def speedtest():
|
||||
"""Run the full speedtest.net test"""
|
||||
|
||||
global shutdown_event, source
|
||||
shutdown_event = threading.Event()
|
||||
|
||||
signal.signal(signal.SIGINT, ctrl_c)
|
||||
|
||||
description = (
|
||||
'Command line interface for testing internet bandwidth using '
|
||||
'speedtest.net.\n'
|
||||
'------------------------------------------------------------'
|
||||
'--------------\n'
|
||||
'https://github.com/sivel/speedtest-cli')
|
||||
|
||||
parser = ArgParser(description=description)
|
||||
# Give optparse.OptionParser an `add_argument` method for
|
||||
# compatibility with argparse.ArgumentParser
|
||||
try:
|
||||
parser.add_argument = parser.add_option
|
||||
except AttributeError:
|
||||
pass
|
||||
parser.add_argument('--bytes', dest='units', action='store_const',
|
||||
const=('bytes', 1), default=('bits', 8),
|
||||
help='Display values in bytes instead of bits. Does '
|
||||
'not affect the image generated by --share')
|
||||
parser.add_argument('--share', action='store_true',
|
||||
help='Generate and provide a URL to the speedtest.net '
|
||||
'share results image')
|
||||
parser.add_argument('--simple', action='store_true',
|
||||
help='Suppress verbose output, only show basic '
|
||||
'information')
|
||||
parser.add_argument('--list', action='store_true',
|
||||
help='Display a list of speedtest.net servers '
|
||||
'sorted by distance')
|
||||
parser.add_argument('--server', help='Specify a server ID to test against')
|
||||
parser.add_argument('--mini', help='URL of the Speedtest Mini server')
|
||||
parser.add_argument('--source', help='Source IP address to bind to')
|
||||
parser.add_argument('--version', action='store_true',
|
||||
help='Show the version number and exit')
|
||||
|
||||
options = parser.parse_args()
|
||||
if isinstance(options, tuple):
|
||||
args = options[0]
|
||||
else:
|
||||
args = options
|
||||
del options
|
||||
|
||||
# Print the version and exit
|
||||
if args.version:
|
||||
version()
|
||||
|
||||
# If specified bind to a specific IP address
|
||||
if args.source:
|
||||
source = args.source
|
||||
socket.socket = bound_socket
|
||||
|
||||
if not args.simple:
|
||||
print_('Retrieving speedtest.net configuration...')
|
||||
try:
|
||||
config = getConfig()
|
||||
except URLError:
|
||||
print_('Cannot retrieve speedtest configuration')
|
||||
sys.exit(1)
|
||||
|
||||
if not args.simple:
|
||||
print_('Retrieving speedtest.net server list...')
|
||||
if args.list or args.server:
|
||||
servers = closestServers(config['client'], True)
|
||||
if args.list:
|
||||
serverList = []
|
||||
for server in servers:
|
||||
line = ('%(id)4s) %(sponsor)s (%(name)s, %(country)s) '
|
||||
'[%(d)0.2f km]' % server)
|
||||
serverList.append(line)
|
||||
# Python 2.7 and newer seem to be ok with the resultant encoding
|
||||
# from parsing the XML, but older versions have some issues.
|
||||
# This block should detect whether we need to encode or not
|
||||
try:
|
||||
unicode()
|
||||
print_('\n'.join(serverList).encode('utf-8', 'ignore'))
|
||||
except NameError:
|
||||
print_('\n'.join(serverList))
|
||||
except IOError:
|
||||
pass
|
||||
sys.exit(0)
|
||||
else:
|
||||
servers = closestServers(config['client'])
|
||||
|
||||
if not args.simple:
|
||||
print_('Testing from %(isp)s (%(ip)s)...' % config['client'])
|
||||
|
||||
if args.server:
|
||||
try:
|
||||
best = getBestServer(filter(lambda x: x['id'] == args.server,
|
||||
servers))
|
||||
except IndexError:
|
||||
print_('Invalid server ID')
|
||||
sys.exit(1)
|
||||
elif args.mini:
|
||||
name, ext = os.path.splitext(args.mini)
|
||||
if ext:
|
||||
url = os.path.dirname(args.mini)
|
||||
else:
|
||||
url = args.mini
|
||||
urlparts = urlparse(url)
|
||||
try:
|
||||
f = urlopen(args.mini)
|
||||
except:
|
||||
print_('Invalid Speedtest Mini URL')
|
||||
sys.exit(1)
|
||||
else:
|
||||
text = f.read()
|
||||
f.close()
|
||||
extension = re.findall('upload_extension: "([^"]+)"', text.decode())
|
||||
if not extension:
|
||||
for ext in ['php', 'asp', 'aspx', 'jsp']:
|
||||
try:
|
||||
f = urlopen('%s/speedtest/upload.%s' % (args.mini, ext))
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
data = f.read().strip()
|
||||
if (f.code == 200 and
|
||||
len(data.splitlines()) == 1 and
|
||||
re.match('size=[0-9]', data)):
|
||||
extension = [ext]
|
||||
break
|
||||
if not urlparts or not extension:
|
||||
print_('Please provide the full URL of your Speedtest Mini server')
|
||||
sys.exit(1)
|
||||
servers = [{
|
||||
'sponsor': 'Speedtest Mini',
|
||||
'name': urlparts[1],
|
||||
'd': 0,
|
||||
'url': '%s/speedtest/upload.%s' % (url.rstrip('/'), extension[0]),
|
||||
'latency': 0,
|
||||
'id': 0
|
||||
}]
|
||||
try:
|
||||
best = getBestServer(servers)
|
||||
except:
|
||||
best = servers[0]
|
||||
else:
|
||||
if not args.simple:
|
||||
print_('Selecting best server based on latency...')
|
||||
best = getBestServer(servers)
|
||||
|
||||
if not args.simple:
|
||||
# Python 2.7 and newer seem to be ok with the resultant encoding
|
||||
# from parsing the XML, but older versions have some issues.
|
||||
# This block should detect whether we need to encode or not
|
||||
try:
|
||||
unicode()
|
||||
print_(('Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: '
|
||||
'%(latency)s ms' % best).encode('utf-8', 'ignore'))
|
||||
except NameError:
|
||||
print_('Hosted by %(sponsor)s (%(name)s) [%(d)0.2f km]: '
|
||||
'%(latency)s ms' % best)
|
||||
else:
|
||||
print_('Ping: %(latency)s ms' % best)
|
||||
|
||||
sizes = [350, 500, 750, 1000, 1500, 2000, 2500, 3000, 3500, 4000]
|
||||
urls = []
|
||||
for size in sizes:
|
||||
for i in range(0, 4):
|
||||
urls.append('%s/random%sx%s.jpg' %
|
||||
(os.path.dirname(best['url']), size, size))
|
||||
if not args.simple:
|
||||
print_('Testing download speed', end='')
|
||||
dlspeed = downloadSpeed(urls, args.simple)
|
||||
if not args.simple:
|
||||
print_()
|
||||
print_('Download: %0.2f M%s/s' %
|
||||
((dlspeed / 1000 / 1000) * args.units[1], args.units[0]))
|
||||
|
||||
sizesizes = [int(.25 * 1000 * 1000), int(.5 * 1000 * 1000)]
|
||||
sizes = []
|
||||
for size in sizesizes:
|
||||
for i in range(0, 25):
|
||||
sizes.append(size)
|
||||
if not args.simple:
|
||||
print_('Testing upload speed', end='')
|
||||
ulspeed = uploadSpeed(best['url'], sizes, args.simple)
|
||||
if not args.simple:
|
||||
print_()
|
||||
print_('Upload: %0.2f M%s/s' %
|
||||
((ulspeed / 1000 / 1000) * args.units[1], args.units[0]))
|
||||
|
||||
if args.share and args.mini:
|
||||
print_('Cannot generate a speedtest.net share results image while '
|
||||
'testing against a Speedtest Mini server')
|
||||
elif args.share:
|
||||
dlspeedk = int(round((dlspeed / 1000) * 8, 0))
|
||||
ping = int(round(best['latency'], 0))
|
||||
ulspeedk = int(round((ulspeed / 1000) * 8, 0))
|
||||
|
||||
# Build the request to send results back to speedtest.net
|
||||
# We use a list instead of a dict because the API expects parameters
|
||||
# in a certain order
|
||||
apiData = [
|
||||
'download=%s' % dlspeedk,
|
||||
'ping=%s' % ping,
|
||||
'upload=%s' % ulspeedk,
|
||||
'promo=',
|
||||
'startmode=%s' % 'pingselect',
|
||||
'recommendedserverid=%s' % best['id'],
|
||||
'accuracy=%s' % 1,
|
||||
'serverid=%s' % best['id'],
|
||||
'hash=%s' % md5(('%s-%s-%s-%s' %
|
||||
(ping, ulspeedk, dlspeedk, '297aae72'))
|
||||
.encode()).hexdigest()]
|
||||
|
||||
req = Request('http://www.speedtest.net/api/api.php',
|
||||
data='&'.join(apiData).encode())
|
||||
req.add_header('Referer', 'http://c.speedtest.net/flash/speedtest.swf')
|
||||
f = urlopen(req)
|
||||
response = f.read()
|
||||
code = f.code
|
||||
f.close()
|
||||
|
||||
if int(code) != 200:
|
||||
print_('Could not submit results to speedtest.net')
|
||||
sys.exit(1)
|
||||
|
||||
qsargs = parse_qs(response.decode())
|
||||
resultid = qsargs.get('resultid')
|
||||
if not resultid or len(resultid) != 1:
|
||||
print_('Could not submit results to speedtest.net')
|
||||
sys.exit(1)
|
||||
|
||||
print_('Share results: http://www.speedtest.net/result/%s.png' %
|
||||
resultid[0])
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
speedtest()
|
||||
except KeyboardInterrupt:
|
||||
print_('\nCancelling...')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
# vim:ts=4:sw=4:expandtab
|
|
@ -1,17 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
arpCommand=$(command -v arp)
|
||||
|
||||
result=$($arpCommand | awk 'BEGIN {print "["} NR>1 \
|
||||
{print "{ \"address\": \"" $1 "\", " \
|
||||
"\"hw_type\": \"" $2 "\", " \
|
||||
"\"hw_address\": \"" $3 "\", " \
|
||||
"\"flags\": \"" $4 "\", " \
|
||||
"\"mask\": \"" $5 "\" }, " \
|
||||
} \
|
||||
END {print "]"}' \
|
||||
| /bin/sed 'N;$s/},/}/;P;D')
|
||||
|
||||
if [ -z "$result" ]; then echo {}
|
||||
else echo $result
|
||||
fi
|
|
@ -1,6 +0,0 @@
|
|||
#!/bin/bash
|
||||
/bin/cat /proc/net/dev \
|
||||
| awk 'BEGIN {print "["} NR>2 {print "{ \"interface\": \"" $1 "\"," \
|
||||
" \"tx\": " $2 "," \
|
||||
" \"rx\": " $10 " }," } END {print "]"}' \
|
||||
| /bin/sed 'N;$s/,\n/\n/;P;D'
|
|
@ -1,11 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(whereis php node mysql mongo vim python ruby java apache2 nginx openssl vsftpd make \
|
||||
| awk -F: '{if(length($2)==0) { installed="false"; } else { installed="true"; } \
|
||||
print \
|
||||
"{ \
|
||||
\"binary\": \""$1"\", \
|
||||
\"location\": \""$2"\", \
|
||||
\"installed\": "installed" \
|
||||
},"}')
|
||||
|
||||
echo "[" ${result%?} "]"
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
result=$(/usr/bin/lscpu \
|
||||
| /usr/bin/awk -F: '{print "\""$1"\": \""$2"\"," } '\
|
||||
)
|
||||
|
||||
echo "{" ${result%?} "}"
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
result=$(/bin/ps axo pid,user,pcpu,rss,vsz,comm --sort -pcpu,-rss,-vsz \
|
||||
| head -n 15 \
|
||||
| /usr/bin/awk 'BEGIN{OFS=":"} NR>1 {print "{ \"pid\": " $1 \
|
||||
", \"user\": \"" $2 "\"" \
|
||||
", \"cpu%\": " $3 \
|
||||
", \"rss\": " $4 \
|
||||
", \"vsz\": " $5 \
|
||||
", \"cmd\": \"" $6 "\"" "},"\
|
||||
}')
|
||||
|
||||
echo "[" ${result%?} "]"
|
|
@ -1,33 +0,0 @@
|
|||
#!/bin/bash
|
||||
# by Paul Colby (http://colby.id.au), no rights reserved ;)
|
||||
|
||||
PREV_TOTAL=0
|
||||
PREV_IDLE=0
|
||||
iteration=0
|
||||
|
||||
while [[ iteration -lt 2 ]]; do
|
||||
# Get the total CPU statistics, discarding the 'cpu ' prefix.
|
||||
CPU=(`sed -n 's/^cpu\s//p' /proc/stat`)
|
||||
IDLE=${CPU[3]} # Just the idle CPU time.
|
||||
|
||||
# Calculate the total CPU time.
|
||||
TOTAL=0
|
||||
for VALUE in "${CPU[@]}"; do
|
||||
let "TOTAL=$TOTAL+$VALUE"
|
||||
done
|
||||
|
||||
# Calculate the CPU usage since we last checked.
|
||||
let "DIFF_IDLE=$IDLE-$PREV_IDLE"
|
||||
let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL"
|
||||
let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10"
|
||||
#echo -en "\rCPU: $DIFF_USAGE% \b\b"
|
||||
|
||||
# Remember the total and idle CPU times for the next check.
|
||||
PREV_TOTAL="$TOTAL"
|
||||
PREV_IDLE="$IDLE"
|
||||
|
||||
# Wait before checking again.
|
||||
sleep 1
|
||||
iteration="$iteration+1"
|
||||
done
|
||||
echo -en "$DIFF_USAGE"
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
grepCmd=$(which grep)
|
||||
cronLog='/var/log/syslog'
|
||||
numberOfLines='50'
|
||||
|
||||
# Month, Day, Time, Hostname, tag, user,
|
||||
|
||||
result=$($grepCmd -m$numberOfLines CRON $cronLog \
|
||||
| awk '{ s = ""; for (i = 6; i <= NF; i++) s = s $i " "; \
|
||||
print "{\"time\" : \"" $1" "$2" "$3 "\"," \
|
||||
"\"user\" : \"" $6 "\"," \
|
||||
"\"message\" : \"" $5" "s "\"" \
|
||||
"},"
|
||||
}'
|
||||
)
|
||||
|
||||
echo [${result%?}]
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
awkCmd=`which awk`
|
||||
catCmd=`which cat`
|
||||
grepCmd=`which grep`
|
||||
memInfoFile="/proc/meminfo"
|
||||
|
||||
# References:
|
||||
# Calculations: http://zcentric.com/2012/05/29/mapping-procmeminfo-to-output-of-free-command/
|
||||
# Fields: https://www.kernel.org/doc/Documentation/filesystems/proc.txt
|
||||
|
||||
memInfo=`$catCmd $memInfoFile | $grepCmd 'MemTotal\|MemFree\|Buffers\|Cached'`
|
||||
|
||||
echo $memInfo | $awkCmd '{print "{ \"total\": " ($2/1024) ", \"used\": " ( ($2-($5+$8+$11))/1024 ) ", \"free\": " (($5+$8+$11)/1024) " }" }'
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/bin/df -Ph | awk 'NR>1 {print "{\"file_system\": \"" $1 "\", \"size\": \"" $2 "\", \"used\": \"" $3 "\", \"avail\": \"" $4 "\", \"used%\": \"" $5 "\", \"mounted\": \"" $6 "\"},"}')
|
||||
|
||||
echo [ ${result%?} ]
|
|
@ -1,40 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
files=(/sys/class/net/*)
|
||||
pos=$(( ${#files[*]} - 1 ))
|
||||
last=${files[$pos]}
|
||||
|
||||
json_output="{"
|
||||
|
||||
for interface in "${files[@]}"
|
||||
do
|
||||
basename=$(basename "$interface")
|
||||
|
||||
# find the number of bytes transfered for this interface
|
||||
in1=$(cat /sys/class/net/"$basename"/statistics/rx_bytes)
|
||||
|
||||
# wait a second
|
||||
sleep 1
|
||||
|
||||
# check same interface again
|
||||
in2=$(cat /sys/class/net/"$basename"/statistics/rx_bytes)
|
||||
|
||||
# get the difference (transfer rate)
|
||||
in_bytes=$((in2 - in1))
|
||||
|
||||
# convert transfer rate to KB
|
||||
in_kbytes=$((in_bytes / 1024))
|
||||
|
||||
# convert transfer rate to KB
|
||||
json_output="$json_output \"$basename\": $in_kbytes"
|
||||
|
||||
# if it is not the last line
|
||||
if [[ ! $interface == $last ]]
|
||||
then
|
||||
# add a comma to the line (JSON formatting)
|
||||
json_output="$json_output,"
|
||||
fi
|
||||
done
|
||||
|
||||
# close the JSON object & print to screen
|
||||
echo "$json_output}"
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
function displaytime {
|
||||
local T=$1
|
||||
local D=$((T/60/60/24))
|
||||
local H=$((T/60/60%24))
|
||||
local M=$((T/60%60))
|
||||
local S=$((T%60))
|
||||
[[ $D > 0 ]] && printf '%d days ' $D
|
||||
[[ $H > 0 ]] && printf '%d hours ' $H
|
||||
[[ $M > 0 ]] && printf '%d minutes ' $M
|
||||
[[ $D > 0 || $H > 0 || $M > 0 ]] && printf 'and '
|
||||
printf '%d seconds\n' $S
|
||||
}
|
||||
|
||||
lsbRelease=$(/usr/bin/lsb_release -ds | sed -e 's/^"//' -e 's/"$//')
|
||||
uname=$(/bin/uname -r | sed -e 's/^"//' -e 's/"$//')
|
||||
os=`echo $lsbRelease $uname`
|
||||
hostname=$(/bin/hostname)
|
||||
uptime_seconds=$(/bin/cat /proc/uptime | awk '{print $1}')
|
||||
server_time=$(date)
|
||||
|
||||
echo { \
|
||||
\"OS\": \"$os\", \
|
||||
\"Hostname\": \"$hostname\", \
|
||||
\"Uptime\": \" $(displaytime ${uptime_seconds%.*}) \", \
|
||||
\"Server Time\": \"$server_time\" \
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCRIPTPATH=`dirname $(readlink -f $0)`
|
||||
SPEED_TEST_SCRIPT=$SCRIPTPATH"/../python_files/speedtest_cli.py"
|
||||
|
||||
$SPEED_TEST_SCRIPT \
|
||||
| grep 'Upload\|Download' \
|
||||
| awk 'BEGIN {print "{"} {print "\"" $1 "\": \"" $2 " " $3 "\"," } END {print "}"}' \
|
||||
| /bin/sed 'N;$s/",/"/;P;D'
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/bin/cat /proc/diskstats | /usr/bin/awk \
|
||||
'{ if($4==0 && $8==0 && $12==0 && $13==0) next } \
|
||||
{print "{ \"device\": \"" $3 "\", \"reads\": \""$4"\", \"writes\": \"" $8 "\", \"in_progress\": \"" $12 "\", \"time_in_io\": \"" $13 "\"},"}'
|
||||
)
|
||||
|
||||
echo [ ${result%?} ]
|
|
@ -1,15 +0,0 @@
|
|||
#!/bin/bash
|
||||
awkCmd=`which awk`
|
||||
grepCmd=`which grep`
|
||||
sedCmd=`which sed`
|
||||
ifconfigCmd=`which ifconfig`
|
||||
trCmd=`which tr`
|
||||
digCmd=`which dig`
|
||||
|
||||
externalIp=`$digCmd +short myip.opendns.com @resolver1.opendns.com`
|
||||
|
||||
$ifconfigCmd \
|
||||
| $grepCmd -B1 "inet addr" \
|
||||
| $awkCmd '{ if ( $1 == "inet" ) { print $2 } else if ( $2 == "Link" ) { printf "%s:" ,$1 } }' \
|
||||
| $awkCmd -v exIp="$externalIp" -F: 'BEGIN {print "["} { print "{ \"interface\": \"" $1 "\", \"ip\": \"" $3 "\" },"} END {print "{ \"interface\": \"external\", \"ip\": \""exIp"\" } ]"}' \
|
||||
| $trCmd -d '\r\n'
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
numberOfCores=$(/bin/grep -c 'model name' /proc/cpuinfo)
|
||||
|
||||
if [ $numberOfCores -eq 0 ]; then
|
||||
numberOfCores=1
|
||||
fi
|
||||
|
||||
result=$(/bin/cat /proc/loadavg | /usr/bin/awk '{print "{ \"1_min_avg\": " ($1*100)/'$numberOfCores' ", \"5_min_avg\": " ($2*100)/'$numberOfCores' ", \"15_min_avg\": " ($3*100)/'$numberOfCores' "}," }')
|
||||
|
||||
echo ${result%?}
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(COLUMNS=300 /usr/bin/w -h | /usr/bin/awk '{print "{\"user\": \"" $1 "\", \"from\": \"" $3 "\", \"when\": \"" $4 "\"},"}')
|
||||
|
||||
echo [ ${result%?} ]
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
echo "stats" \
|
||||
| /bin/nc -w 1 127.0.0.1 11211 \
|
||||
| /bin/grep 'bytes' \
|
||||
| /usr/bin/awk 'BEGIN {print "{"} {print "\"" $2 "\": " $3 } END {print "}"}' \
|
||||
| /usr/bin/tr '\r' ',' \
|
||||
| /bin/sed 'N;$s/,\n/\n/;P;D'
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
/bin/cat /proc/meminfo \
|
||||
| /usr/bin/awk -F: 'BEGIN {print "{"} {print "\"" $1 "\": \"" $2 "\"," } END {print "}"}' \
|
||||
| /bin/sed 'N;$s/,\n/\n/;P;D'
|
|
@ -1,13 +0,0 @@
|
|||
#!/bin/bash
|
||||
netstatCmd=`which netstat`
|
||||
awkCmd=`which awk`
|
||||
sortCmd=`which sort`
|
||||
uniqCmd=`which uniq`
|
||||
sedCmd=`which sed`
|
||||
|
||||
$netstatCmd -ntu \
|
||||
| $awkCmd 'NR>2 {print $5}' \
|
||||
| $sortCmd \
|
||||
| $uniqCmd -c \
|
||||
| $awkCmd 'BEGIN {print "["} {print "{ \"connections\": " $1 ", \"address\": \"" $2 "\" }," } END {print "]"}' \
|
||||
| $sedCmd 'N;$s/},/}/;P;D'
|
|
@ -1,7 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
numberOfCores=$(/bin/grep -c 'model name' /proc/cpuinfo)
|
||||
|
||||
if [length($numberOfCores)]; then
|
||||
echo "cannnot be found";
|
||||
fi
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
# http://askubuntu.com/questions/413367/ping-multiple-ips-using-bash
|
||||
|
||||
# get absolute path to config file
|
||||
SCRIPTPATH=`dirname $(readlink -f $0)`
|
||||
CONFIG_PATH=$SCRIPTPATH"/../config/ping_hosts"
|
||||
|
||||
catCmd=`which cat`
|
||||
pingCmd=`which ping`
|
||||
awkCmd=`which awk`
|
||||
sedCmd=`which sed`
|
||||
numOfLinesInConfig=`$sedCmd -n '$=' $CONFIG_PATH`
|
||||
result='['
|
||||
|
||||
{ $catCmd $CONFIG_PATH; echo; } \
|
||||
| while read output
|
||||
do
|
||||
singlePing=$($pingCmd -qc 2 $output \
|
||||
| $awkCmd -F/ 'BEGIN { endLine="}," } /^rtt/ { if ('$numOfLinesInConfig'==1){endLine="}"} print "{" "\"host\": \"'$output'\", \"ping\": " $5 " " endLine }' \
|
||||
)
|
||||
numOfLinesInConfig=$(($numOfLinesInConfig-1))
|
||||
result=$result$singlePing
|
||||
if [ $numOfLinesInConfig -eq 1 ]
|
||||
then
|
||||
echo $result"]"
|
||||
fi
|
||||
done \
|
||||
| $sedCmd 's/\},]/}]/g'
|
|
@ -1,12 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/bin/ps axo pid,user,pmem,rss,vsz,comm --sort -pmem,-rss,-vsz \
|
||||
| head -n 15 \
|
||||
| /usr/bin/awk 'NR>1 {print "{ \"pid\": " $1 \
|
||||
", \"user\": \"" $2 \
|
||||
"\", \"mem%\": " $3 \
|
||||
", \"rss\": " $4 \
|
||||
", \"vsz\": " $5 \
|
||||
", \"cmd\": \"" $6 \
|
||||
"\"},"}')
|
||||
|
||||
echo [ ${result%?} ]
|
|
@ -1,10 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/usr/bin/lastlog -t 365 \
|
||||
| /usr/bin/awk 'NR>1 {\
|
||||
print "{ \
|
||||
\"user\": \"" $1 "\", \
|
||||
\"ip\": \"" $3 "\","" \
|
||||
\"date\": \"" $5" "$6" "$7" "$8" "$9 "\"},"
|
||||
}'
|
||||
)
|
||||
echo [ ${result%?} ]
|
|
@ -1,18 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
########### Enter Your Redis Password HERE #########
|
||||
redisPassword=''
|
||||
########### Enter Your Redis Password HERE #########
|
||||
|
||||
redisCommand=$(which redis-cli);
|
||||
|
||||
if [ -n "$redisPassword" ]; then
|
||||
redisCommand="$redisCommand -a $redisPassword"
|
||||
fi
|
||||
|
||||
result=$($redisCommand INFO \
|
||||
| grep 'redis_version\|connected_clients\|connected_slaves\|used_memory_human\|total_connections_received\|total_commands_processed' \
|
||||
| awk -F: '{print "\"" $1 "\":" "\"" $2 }' \
|
||||
| tr '\r' '"' | tr '\n' ','
|
||||
)
|
||||
echo { ${result%?} }
|
|
@ -1,88 +0,0 @@
|
|||
#!/bin/bash
|
||||
######
|
||||
# Credit: http://stackoverflow.com/questions/134906/how-do-i-list-all-cron-jobs-for-all-users#answer-137173
|
||||
######
|
||||
|
||||
catCmd=`which cat`
|
||||
awkCmd=`which awk`
|
||||
sedCmd=`which sed`
|
||||
egrepCmd=`which egrep`
|
||||
echoCmd=`which echo`
|
||||
crontabCmd=`which crontab`
|
||||
|
||||
# System-wide crontab file and cron job directory. Change these for your system.
|
||||
CRONTAB='/etc/crontab'
|
||||
CRONDIR='/etc/cron.d'
|
||||
|
||||
# Single tab character. Annoyingly necessary.
|
||||
tab=$(echo -en "\t")
|
||||
|
||||
# Given a stream of crontab lines, exclude non-cron job lines, replace
|
||||
# whitespace characters with a single space, and remove any spaces from the
|
||||
# beginning of each line.
|
||||
function clean_cron_lines() {
|
||||
while read line ; do
|
||||
$echoCmd "${line}" |
|
||||
$egrepCmd --invert-match '^($|\s*#|\s*[[:alnum:]_]+=)' |
|
||||
$sedCmd --regexp-extended "s/\s+/ /g" |
|
||||
$sedCmd --regexp-extended "s/^ //"
|
||||
done;
|
||||
}
|
||||
|
||||
# Given a stream of cleaned crontab lines, $echoCmd any that don't include the
|
||||
# run-parts command, and for those that do, show each job file in the run-parts
|
||||
# directory as if it were scheduled explicitly.
|
||||
function lookup_run_parts() {
|
||||
while read line ; do
|
||||
match=$($echoCmd "${line}" | $egrepCmd -o 'run-parts (-{1,2}\S+ )*\S+')
|
||||
|
||||
if [[ -z "${match}" ]] ; then
|
||||
$echoCmd "${line}"
|
||||
else
|
||||
cron_fields=$($echoCmd "${line}" | cut -f1-6 -d' ')
|
||||
cron_job_dir=$($echoCmd "${match}" | awk '{print $NF}')
|
||||
|
||||
if [[ -d "${cron_job_dir}" ]] ; then
|
||||
for cron_job_file in "${cron_job_dir}"/* ; do # */ <not a comment>
|
||||
[[ -f "${cron_job_file}" ]] && $echoCmd "${cron_fields} ${cron_job_file}"
|
||||
done
|
||||
fi
|
||||
fi
|
||||
done;
|
||||
}
|
||||
|
||||
# Temporary file for crontab lines.
|
||||
temp=$(mktemp) || exit 1
|
||||
|
||||
# Add all of the jobs from the system-wide crontab file.
|
||||
$catCmd "${CRONTAB}" | clean_cron_lines | lookup_run_parts >"${temp}"
|
||||
|
||||
# Add all of the jobs from the system-wide cron directory.
|
||||
$catCmd "${CRONDIR}"/* | clean_cron_lines >>"${temp}" # */ <not a comment>
|
||||
|
||||
# Add each user's crontab (if it exists). Insert the user's name between the
|
||||
# five time fields and the command.
|
||||
while read user ; do
|
||||
$crontabCmd -l -u "${user}" 2>/dev/null |
|
||||
clean_cron_lines |
|
||||
$sedCmd --regexp-extended "s/^((\S+ +){5})(.+)$/\1${user} \3/" >>"${temp}"
|
||||
done < <(cut --fields=1 --delimiter=: /etc/passwd)
|
||||
|
||||
# Output the collected crontab lines.
|
||||
|
||||
## Changes: Parses output into JSON
|
||||
|
||||
$catCmd "${temp}" \
|
||||
| awk 'BEGIN {print "["} \
|
||||
{print "{ \"min(s)\": \"" $1 \
|
||||
"\", \"hours(s)\": \"" $2 "\", " \
|
||||
" \"day(s)\": \"" $3 "\", " \
|
||||
" \"month\": \"" $4 "\", " \
|
||||
" \"weekday\": \"" $5 "\", " \
|
||||
" \"user\": \"" $6 "\", " \
|
||||
" \"command\": \"" $7$8$9$10 "\" " \
|
||||
"}," } \
|
||||
END {print "]"}' \
|
||||
| $sedCmd 'N;$s/,\n/\n/;P;D'
|
||||
|
||||
rm --force "${temp}"
|
|
@ -1,5 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/bin/cat /proc/swaps \
|
||||
| /usr/bin/awk 'NR>1 {print "{ \"filename\": \"" $1"\", \"type\": \""$2"\", \"size\": \""$3"\", \"used\": \""$4"\", \"priority\": \""$5"\"}," }'
|
||||
)
|
||||
echo [ ${result%?} ]
|
|
@ -1,40 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
files=(/sys/class/net/*)
|
||||
pos=$(( ${#files[*]} - 1 ))
|
||||
last=${files[$pos]}
|
||||
|
||||
json_output="{"
|
||||
|
||||
for interface in "${files[@]}"
|
||||
do
|
||||
basename=$(basename "$interface")
|
||||
|
||||
# find the number of bytes transfered for this interface
|
||||
out1=$(cat /sys/class/net/"$basename"/statistics/tx_bytes)
|
||||
|
||||
# wait a second
|
||||
sleep 1
|
||||
|
||||
# check same interface again
|
||||
out2=$(cat /sys/class/net/"$basename"/statistics/tx_bytes)
|
||||
|
||||
# get the difference (transfer rate)
|
||||
out_bytes=$((out2 - out1))
|
||||
|
||||
# convert transfer rate to KB
|
||||
out_kbytes=$((out_bytes / 1024))
|
||||
|
||||
# convert transfer rate to KB
|
||||
json_output="$json_output \"$basename\": $out_kbytes"
|
||||
|
||||
# if it is not the last line
|
||||
if [[ ! $interface == $last ]]
|
||||
then
|
||||
# add a comma to the line (JSON formatting)
|
||||
json_output="$json_output,"
|
||||
fi
|
||||
done
|
||||
|
||||
# close the JSON object & print to screen
|
||||
echo "$json_output}"
|
|
@ -1,14 +0,0 @@
|
|||
#!/bin/bash
|
||||
result=$(/usr/bin/awk -F: '{ \
|
||||
if ($3<=499){userType="system";} \
|
||||
else {userType="user";} \
|
||||
print "{ \"type\": \"" userType "\"" ", \"user\": \"" $1 "\", \"home\": \"" $6 "\" }," }' < /etc/passwd
|
||||
)
|
||||
|
||||
length=$(echo ${#result})
|
||||
|
||||
if [ $length -eq 0 ]; then
|
||||
result=$(getent passwd | /usr/bin/awk -F: '{ if ($3<=499){userType="system";} else {userType="user";} print "{ \"type\": \"" userType "\"" ", \"user\": \"" $1 "\", \"home\": \"" $6 "\" }," }')
|
||||
fi
|
||||
|
||||
echo [ ${result%?} ]
|
|
@ -1,10 +0,0 @@
|
|||
<div class="plugin">
|
||||
<top-bar
|
||||
heading="heading"
|
||||
last-updated="lastGet"
|
||||
info="info"
|
||||
refresh="getData()">
|
||||
</top-bar>
|
||||
|
||||
<div class="plugin-body" ng-transclude></div>
|
||||
</div>
|
|
@ -1,22 +0,0 @@
|
|||
<plugin
|
||||
heading="{{ heading }}"
|
||||
last-updated="lastGet"
|
||||
on-refresh="getData()"
|
||||
info="{{ info }}">
|
||||
|
||||
<loader ng-if="!tableRows"></loader>
|
||||
|
||||
<div class="animate" ng-show="tableRows">
|
||||
<table class="key-value-list">
|
||||
<tbody>
|
||||
<tr ng-repeat="(name, value) in tableRows">
|
||||
<td><strong>{{ name }}</strong></td>
|
||||
<td>{{ value }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<no-data ng-show="emptyResult"></no-data>
|
||||
</plugin>
|
|
@ -1,20 +0,0 @@
|
|||
<div class="plugin">
|
||||
|
||||
<top-bar heading="heading" last-updated="lastGet" no-refresh-btn></top-bar>
|
||||
|
||||
<div class="plugin-body no-padding">
|
||||
|
||||
<canvas class="canvas" width="400" height="200"></canvas>
|
||||
|
||||
<table border="0" class="metrics-table">
|
||||
<tbody>
|
||||
<tr ng-repeat="metric in metrics">
|
||||
<td><strong>{{ metric.name }}</strong></td>
|
||||
<td>{{ metric.data }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</plugin>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="lead" style="text-align: center;">
|
||||
<loader></loader>
|
||||
Loading...
|
||||
</div>
|
|
@ -1,26 +0,0 @@
|
|||
<div class="plugin">
|
||||
<top-bar heading="heading" last-updated="lastGet" no-refresh-btn></top-bar>
|
||||
|
||||
<div class="plugin-body no-padding">
|
||||
|
||||
<canvas class="canvas" width="400" height="200"></canvas>
|
||||
|
||||
<table class="metrics-table" border="0">
|
||||
<tbody>
|
||||
<tr ng-repeat="metric in metricsArray">
|
||||
<td>
|
||||
<div
|
||||
class="metric-square"
|
||||
style="display: inline-block; border: 1px solid {{metric.color}}; width: 8px; height: 8px; background: {{metric.color}}">
|
||||
</div>
|
||||
</td>
|
||||
<td>{{ metric.name }}</td>
|
||||
<td>{{ metric.data }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</plugin>
|
|
@ -1,8 +0,0 @@
|
|||
<br>
|
||||
<ul>
|
||||
<li ng-class="{active: isActive(navItem) }" ng-repeat="navItem in items">
|
||||
<a href="#/{{navItem}}">
|
||||
{{getNavItemName(navItem)}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
|
@ -1,5 +0,0 @@
|
|||
<div class="progress-bar-container">
|
||||
<div class="progress-bar" style="width:{{width}};">
|
||||
<div style="width: {{ (value/max) * 100 }}%;"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,40 +0,0 @@
|
|||
<plugin
|
||||
heading="{{ heading }}"
|
||||
last-updated="lastGet"
|
||||
on-refresh="getData()"
|
||||
info="{{ info }}">
|
||||
|
||||
<loader ng-if="!tableRows"></loader>
|
||||
|
||||
<div class="animate" ng-show="tableRows">
|
||||
|
||||
<table class="table-data-plugin">
|
||||
<thead>
|
||||
<tr class="table-data-filter-container" ng-show="tableRows.length">
|
||||
<th colspan="{{ tableHeaders.length }}" class="filter-container">
|
||||
<input class="filter" ng-model="keyword" placeholder="Search">
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th ng-repeat="header in tableHeaders track by $index">
|
||||
<a href="" ng-click="setSortColumn(header)">{{ header }}</a>
|
||||
<span class="column-sort-caret">
|
||||
{{ (header === sortByColumn && !sortReverse) ? '▲': ''; }}
|
||||
{{ (header === sortByColumn && sortReverse) ? '▼': ''; }}
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="row in tableRows | filter:keyword">
|
||||
<td ng-repeat="header in tableHeaders track by $index">
|
||||
{{ row[header] }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<no-data ng-show="emptyResult"></no-data>
|
||||
</plugin>
|
|
@ -1,12 +0,0 @@
|
|||
<div id="theme-switcher" class="{{ (themeSwitcherOpen) ? 'open': '' }}">
|
||||
|
||||
<div class="settings-icon" ng-click="toggleThemeSwitcher()">⚙</div>
|
||||
|
||||
<div
|
||||
class="option {{ (theme.selected) ? 'selected': '' }}"
|
||||
ng-repeat="theme in themes"
|
||||
ng-click="switchTheme(theme)">
|
||||
{{ theme.name }}
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<span ng-hide="timestamp">Loading...</span>
|
||||
<small alt="Last Update Timestamp">
|
||||
<span ng-show="timestamp">{{ timestamp | date:'hh:mm:ss a' }}</span>
|
||||
</small>
|
|
@ -1,10 +0,0 @@
|
|||
<div class="top-bar">
|
||||
<last-update timestamp="lastUpdated"></last-update>
|
||||
<span class="qs">
|
||||
{{ heading }}
|
||||
<span class="popover above" ng-if="info">
|
||||
{{ info }}
|
||||
</span>
|
||||
</span>
|
||||
<refresh-btn refresh="refresh()"></refresh-btn>
|
||||
</div>
|
|
@ -1,5 +0,0 @@
|
|||
<multi-line-chart-plugin
|
||||
heading="CPU Avg Load"
|
||||
module-name="load_avg"
|
||||
units="units">
|
||||
</multi-line-chart-plugin>
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
<line-chart-plugin
|
||||
|
||||
heading="CPU Utilization"
|
||||
module-name="cpu_utilization"
|
||||
color="0,255,0"
|
||||
|
||||
max-value="max"
|
||||
min-value="min"
|
||||
refresh-rate="1500"
|
||||
|
||||
get-display-value="displayValue"
|
||||
metrics="utilMetrics">
|
||||
</line-chart-plugin>
|
|
@ -1,39 +0,0 @@
|
|||
<plugin
|
||||
heading="Disk Partitions"
|
||||
last-updated="lastGet"
|
||||
on-refresh="getData()">
|
||||
|
||||
<loader ng-hide="diskSpaceData"></loader>
|
||||
|
||||
<table ng-show="diskSpaceData">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th></th>
|
||||
<th>Stats</th>
|
||||
<th>Used</th>
|
||||
<th>Mount Path</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="partition in diskSpaceData">
|
||||
<td>{{partition['file_system']}}</td>
|
||||
<td>
|
||||
<progress-bar-plugin
|
||||
width="70px"
|
||||
value="{{ getKB(partition['used']) }}"
|
||||
max="{{ getKB(partition['size']) }}">
|
||||
</progress-bar-plugin>
|
||||
</td>
|
||||
<td>
|
||||
{{ partition['used'] }} / {{ partition['size'] }}
|
||||
</td>
|
||||
<td>
|
||||
{{ partition['used%'] }}
|
||||
</td>
|
||||
<td>{{ partition['mounted'] }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</plugin>
|
|
@ -1,5 +0,0 @@
|
|||
<multi-line-chart-plugin
|
||||
heading="Download Transfer Rate"
|
||||
module-name="download_transfer_rate"
|
||||
units="units">
|
||||
</multi-line-chart-plugin>
|
|
@ -1,14 +0,0 @@
|
|||
<line-chart-plugin
|
||||
ng-if="maxRam"
|
||||
|
||||
heading="RAM Usage"
|
||||
module-name="current_ram"
|
||||
color="0,255,0"
|
||||
|
||||
max-value="maxRam"
|
||||
min-value="minRam"
|
||||
refresh-rate="1000"
|
||||
|
||||
get-display-value="ramToDisplay"
|
||||
metrics="ramMetrics">
|
||||
</line-chart-plugin>
|
|
@ -1,5 +0,0 @@
|
|||
<multi-line-chart-plugin
|
||||
heading="Upload Transfer Rate"
|
||||
module-name="upload_transfer_rate"
|
||||
units="units">
|
||||
</multi-line-chart-plugin>
|
|
@ -1,5 +0,0 @@
|
|||
<table-data-plugin
|
||||
heading="Ping Speeds"
|
||||
module-name="ping"
|
||||
table-headers="pingTableConfig">
|
||||
</table-data-plugin>
|
|
@ -1,3 +0,0 @@
|
|||
<server-accounts></server-accounts>
|
||||
<logged-in-accounts></logged-in-accounts>
|
||||
<recent-logins></recent-logins>
|
|
@ -1,3 +0,0 @@
|
|||
<common-applications></common-applications>
|
||||
<memcached></memcached>
|
||||
<redis></redis>
|
|
@ -1,6 +0,0 @@
|
|||
<machine-info></machine-info>
|
||||
<memory-info></memory-info>
|
||||
<cpu-info></cpu-info>
|
||||
<scheduled-crons></scheduled-crons>
|
||||
<cron-history></cron-history>
|
||||
<io-stats></io-stats>
|
|
@ -1,8 +0,0 @@
|
|||
<upload-transfer-rate-chart></upload-transfer-rate-chart>
|
||||
<download-transfer-rate-chart></download-transfer-rate-chart>
|
||||
<ip-addresses></ip-addresses>
|
||||
<network-connections></network-connections>
|
||||
<arp-cache-table></arp-cache-table>
|
||||
<ping-speeds></ping-speeds>
|
||||
<bandwidth></bandwidth>
|
||||
<internet-speed></internet-speed>
|
|
@ -1,7 +0,0 @@
|
|||
<ram-chart></ram-chart>
|
||||
<cpu-avg-load-chart></cpu-avg-load-chart>
|
||||
<cpu-utilization-chart></cpu-utilization-chart>
|
||||
<ram-intensive-processes></ram-intensive-processes>
|
||||
<cpu-intensive-processes></cpu-intensive-processes>
|
||||
<swap-usage></swap-usage>
|
||||
<disk-space></disk-space>
|
Loading…
Reference in a new issue