From 65636ca4513200d1e7a8ea700b1155b60c2b632c Mon Sep 17 00:00:00 2001 From: Maniack Crudelis Date: Mon, 29 Jan 2018 00:55:27 +0100 Subject: [PATCH 1/3] Global refactoring --- check_process | 33 + conf/app.src | 6 + conf/app.src.2.0 | 6 + conf/nginx.conf | 19 +- conf/supervisor.conf | 6 +- manifest.json | 15 +- scripts/_common.sh | 13 + scripts/backup | 53 + scripts/install | 163 ++- scripts/remove | 77 +- scripts/restore | 95 ++ scripts/upgrade | 136 ++- sources/.editorconfig | 12 - sources/.gitignore | 2 - sources/LICENSE.md | 20 - sources/README.md | 54 - sources/composer.json | 22 - sources/css/animate.css | 6 - sources/css/main.css | 488 --------- sources/css/theme-old.css | 170 --- sources/css/themes.css | 88 -- sources/demo.html | 70 -- sources/favicon.ico | Bin 99678 -> 0 bytes sources/img/themes/congruent_pentagon.png | Bin 28934 -> 0 bytes sources/img/themes/contemporary_china_2.png | Bin 7101 -> 0 bytes sources/img/themes/crossword.png | Bin 43694 -> 0 bytes sources/img/themes/food.png | Bin 5247 -> 0 bytes sources/img/themes/skulls.png | Bin 66703 -> 0 bytes sources/index.html | 45 - sources/js/angular-route.js | 996 ------------------ sources/js/angular.min.js | 250 ----- sources/js/linuxDash.js | 783 -------------- sources/js/modules.js | 284 ----- sources/js/smoothie.min.js | 1 - sources/package.json | 30 - sources/python-server.py | 45 - sources/server/index.go | 53 - sources/server/index.js | 107 -- sources/server/index.php | 8 - sources/server/modules/config/ping_hosts | 3 - .../modules/python_files/speedtest_cli.py | 694 ------------ .../server/modules/shell_files/arp_cache.sh | 17 - .../server/modules/shell_files/bandwidth.sh | 6 - .../shell_files/common_applications.sh | 11 - .../server/modules/shell_files/cpu_info.sh | 7 - .../shell_files/cpu_intensive_processes.sh | 13 - .../modules/shell_files/cpu_utilization.sh | 33 - .../modules/shell_files/cron_history.sh | 18 - .../server/modules/shell_files/current_ram.sh | 14 - .../modules/shell_files/disk_partitions.sh | 4 - .../shell_files/download_transfer_rate.sh | 40 - .../modules/shell_files/general_info.sh | 28 - .../modules/shell_files/internet_speed.sh | 9 - .../server/modules/shell_files/io_stats.sh | 7 - .../modules/shell_files/ip_addresses.sh | 15 - .../server/modules/shell_files/load_avg.sh | 10 - .../modules/shell_files/logged_in_users.sh | 4 - .../server/modules/shell_files/memcached.sh | 7 - .../server/modules/shell_files/memory_info.sh | 4 - .../shell_files/network_connections.sh | 13 - .../shell_files/number_of_cpu_cores.sh | 7 - sources/server/modules/shell_files/ping.sh | 28 - .../shell_files/ram_intensive_processes.sh | 12 - .../shell_files/recent_account_logins.sh | 10 - sources/server/modules/shell_files/redis.sh | 18 - .../modules/shell_files/scheduled_crons.sh | 88 -- sources/server/modules/shell_files/swap.sh | 5 - .../shell_files/upload_transfer_rate.sh | 40 - .../modules/shell_files/user_accounts.sh | 14 - sources/templates/app/base-plugin.html | 10 - .../templates/app/key-value-list-plugin.html | 22 - sources/templates/app/line-chart-plugin.html | 20 - sources/templates/app/loading.html | 4 - .../app/multi-line-chart-plugin.html | 26 - sources/templates/app/navbar.html | 8 - .../templates/app/progress-bar-plugin.html | 5 - sources/templates/app/table-data-plugin.html | 40 - sources/templates/app/theme-switcher.html | 12 - .../app/ui-elements/last-update.html | 4 - .../templates/app/ui-elements/top-bar.html | 10 - sources/templates/modules/cpu-load.html | 5 - .../modules/cpu-utilization-chart.html | 14 - sources/templates/modules/disk-space.html | 39 - .../modules/download-transfer-rate.html | 5 - sources/templates/modules/ram-chart.html | 14 - .../modules/upload-transfer-rate.html | 5 - sources/templates/ping-speeds.html | 5 - sources/templates/sections/accounts.html | 3 - sources/templates/sections/applications.html | 3 - sources/templates/sections/basic-info.html | 6 - sources/templates/sections/network.html | 8 - sources/templates/sections/system-status.html | 7 - 92 files changed, 539 insertions(+), 5071 deletions(-) create mode 100644 check_process create mode 100644 conf/app.src create mode 100644 conf/app.src.2.0 create mode 100644 scripts/_common.sh create mode 100755 scripts/backup create mode 100755 scripts/restore delete mode 100755 sources/.editorconfig delete mode 100644 sources/.gitignore delete mode 100644 sources/LICENSE.md delete mode 100644 sources/README.md delete mode 100644 sources/composer.json delete mode 100644 sources/css/animate.css delete mode 100644 sources/css/main.css delete mode 100644 sources/css/theme-old.css delete mode 100644 sources/css/themes.css delete mode 100644 sources/demo.html delete mode 100644 sources/favicon.ico delete mode 100644 sources/img/themes/congruent_pentagon.png delete mode 100644 sources/img/themes/contemporary_china_2.png delete mode 100644 sources/img/themes/crossword.png delete mode 100644 sources/img/themes/food.png delete mode 100644 sources/img/themes/skulls.png delete mode 100644 sources/index.html delete mode 100644 sources/js/angular-route.js delete mode 100644 sources/js/angular.min.js delete mode 100644 sources/js/linuxDash.js delete mode 100644 sources/js/modules.js delete mode 100644 sources/js/smoothie.min.js delete mode 100644 sources/package.json delete mode 100755 sources/python-server.py delete mode 100644 sources/server/index.go delete mode 100644 sources/server/index.js delete mode 100644 sources/server/index.php delete mode 100644 sources/server/modules/config/ping_hosts delete mode 100755 sources/server/modules/python_files/speedtest_cli.py delete mode 100755 sources/server/modules/shell_files/arp_cache.sh delete mode 100755 sources/server/modules/shell_files/bandwidth.sh delete mode 100755 sources/server/modules/shell_files/common_applications.sh delete mode 100755 sources/server/modules/shell_files/cpu_info.sh delete mode 100755 sources/server/modules/shell_files/cpu_intensive_processes.sh delete mode 100755 sources/server/modules/shell_files/cpu_utilization.sh delete mode 100755 sources/server/modules/shell_files/cron_history.sh delete mode 100755 sources/server/modules/shell_files/current_ram.sh delete mode 100755 sources/server/modules/shell_files/disk_partitions.sh delete mode 100755 sources/server/modules/shell_files/download_transfer_rate.sh delete mode 100755 sources/server/modules/shell_files/general_info.sh delete mode 100755 sources/server/modules/shell_files/internet_speed.sh delete mode 100755 sources/server/modules/shell_files/io_stats.sh delete mode 100755 sources/server/modules/shell_files/ip_addresses.sh delete mode 100755 sources/server/modules/shell_files/load_avg.sh delete mode 100755 sources/server/modules/shell_files/logged_in_users.sh delete mode 100755 sources/server/modules/shell_files/memcached.sh delete mode 100755 sources/server/modules/shell_files/memory_info.sh delete mode 100755 sources/server/modules/shell_files/network_connections.sh delete mode 100755 sources/server/modules/shell_files/number_of_cpu_cores.sh delete mode 100755 sources/server/modules/shell_files/ping.sh delete mode 100755 sources/server/modules/shell_files/ram_intensive_processes.sh delete mode 100755 sources/server/modules/shell_files/recent_account_logins.sh delete mode 100755 sources/server/modules/shell_files/redis.sh delete mode 100755 sources/server/modules/shell_files/scheduled_crons.sh delete mode 100755 sources/server/modules/shell_files/swap.sh delete mode 100755 sources/server/modules/shell_files/upload_transfer_rate.sh delete mode 100755 sources/server/modules/shell_files/user_accounts.sh delete mode 100644 sources/templates/app/base-plugin.html delete mode 100644 sources/templates/app/key-value-list-plugin.html delete mode 100644 sources/templates/app/line-chart-plugin.html delete mode 100644 sources/templates/app/loading.html delete mode 100644 sources/templates/app/multi-line-chart-plugin.html delete mode 100644 sources/templates/app/navbar.html delete mode 100644 sources/templates/app/progress-bar-plugin.html delete mode 100644 sources/templates/app/table-data-plugin.html delete mode 100644 sources/templates/app/theme-switcher.html delete mode 100644 sources/templates/app/ui-elements/last-update.html delete mode 100644 sources/templates/app/ui-elements/top-bar.html delete mode 100644 sources/templates/modules/cpu-load.html delete mode 100644 sources/templates/modules/cpu-utilization-chart.html delete mode 100644 sources/templates/modules/disk-space.html delete mode 100644 sources/templates/modules/download-transfer-rate.html delete mode 100644 sources/templates/modules/ram-chart.html delete mode 100644 sources/templates/modules/upload-transfer-rate.html delete mode 100644 sources/templates/ping-speeds.html delete mode 100644 sources/templates/sections/accounts.html delete mode 100644 sources/templates/sections/applications.html delete mode 100644 sources/templates/sections/basic-info.html delete mode 100644 sources/templates/sections/network.html delete mode 100644 sources/templates/sections/system-status.html diff --git a/check_process b/check_process new file mode 100644 index 0000000..c315f0d --- /dev/null +++ b/check_process @@ -0,0 +1,33 @@ +;; Test complet + ; Manifest + domain="domain.tld" (DOMAIN) + path="/path" (PATH) + user="john" (USER) + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=0 + setup_public=0 + upgrade=1 + backup_restore=1 + multi_instance=0 + incorrect_path=1 + port_already_use=1 (8081) + change_url=0 +;;; Levels + Level 1=auto + Level 2=auto + Level 3=auto +# Level 4: Not relevant + Level 4=na + Level 5=auto + Level 6=auto + Level 7=auto + Level 8=0 + Level 9=0 + Level 10=0 +;;; Options +Email= +Notification=none diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..0a7b75c --- /dev/null +++ b/conf/app.src @@ -0,0 +1,6 @@ +SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/59d4787d3147e79a816a5c88ed8af482a0661e88.zip +SOURCE_SUM=9c3112c93bb20be8b719335b20bf161e11a8095ecf639baab6ea8c95ef289928 +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=zip +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= diff --git a/conf/app.src.2.0 b/conf/app.src.2.0 new file mode 100644 index 0000000..136f8ad --- /dev/null +++ b/conf/app.src.2.0 @@ -0,0 +1,6 @@ +SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/2.0.tar.gz +SOURCE_SUM=f7342807ecadd22410614336378311a356e04a18569f64935ea67b9bc27ccd56 +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= diff --git a/conf/nginx.conf b/conf/nginx.conf index beea8dd..3ad0143 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,9 +1,14 @@ -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__/ { - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + if ($scheme = http) { + rewrite ^ https://$server_name$request_uri? permanent; + } + + proxy_pass http://localhost:__PORT__/; + proxy_set_header Host $host; + proxy_buffering off; + + # Include SSOWAT user panel. + include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/supervisor.conf b/conf/supervisor.conf index 0c0655d..148e08d 100644 --- a/conf/supervisor.conf +++ b/conf/supervisor.conf @@ -1,5 +1,7 @@ -[program:linuxdash] -directory=/var/www/linuxdash/ +[program:__APP__] +directory=__FINALPATH__/ +;command=python app/server/index.py (v2.0) command=python python-server.py autostart=true autorestart=true +user=__USER__ diff --git a/manifest.json b/manifest.json index 733d4f0..a8f2fd4 100644 --- a/manifest.json +++ b/manifest.json @@ -1,18 +1,23 @@ { "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", + "license": "MIT", "maintainer": { "name": "Moul", "email": "moul@moul.re", "url": "https://moul.re" }, - "multi_instance": "false", + "requirements": { + "yunohost": ">= 2.7.2" + }, + "multi_instance": false, "services": [ "nginx" ], @@ -20,7 +25,7 @@ "install" : [ { "name": "domain", - "type": "domain", + "type": "domain", "ask": { "en": "Choose a domain name for Linux-Dash", "fr": "Choisissez un nom de domaine pour Linux-Dash" @@ -29,7 +34,7 @@ }, { "name": "path", - "type": "path", + "type": "path", "ask": { "en": "Choose a path for Linux-Dash", "fr": "Choisissez un chemin pour Linux-Dash" @@ -39,7 +44,7 @@ }, { "name": "user", - "type": "user", + "type": "user", "ask": { "en": "Choose the YunoHost user which have access to Linux-Dash", "fr": "Choisissez l’utilisateur YunoHost qui a accès à Linux-Dash" diff --git a/scripts/_common.sh b/scripts/_common.sh new file mode 100644 index 0000000..24bd7ba --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# ============= FUTURE YUNOHOST HELPER ============= +# Delete a file checksum from the app settings +# +# $app should be defined when calling this helper +# +# usage: ynh_remove_file_checksum file +# | arg: file - The file for which the checksum will be deleted +ynh_delete_file_checksum () { + local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' + ynh_app_setting_delete $app $checksum_setting_name +} diff --git a/scripts/backup b/scripts/backup new file mode 100755 index 0000000..d192288 --- /dev/null +++ b/scripts/backup @@ -0,0 +1,53 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Get the _common.sh file if it's not in the current directory + cp ../settings/scripts/_common.sh ./_common.sh + chmod a+rx _common.sh +fi +source _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 +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get $app final_path) +domain=$(ynh_app_setting_get $app domain) + +#================================================= +# STANDARD BACKUP STEPS +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= + +ynh_backup "$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SUPERVISOR CONFIG +#================================================= + +ynh_backup "/etc/supervisor/conf.d/$app.conf" diff --git a/scripts/install b/scripts/install index 7f6b41b..8b6be88 100755 --- a/scripts/install +++ b/scripts/install @@ -1,48 +1,141 @@ #!/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 +user=$YNH_APP_ARG_USER + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= -# 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 "This path already contains a folder" -# Set permissions -sudo chown -R www-data: $final_path +# Normalize the url path syntax +path_url=$(ynh_normalize_url_path $path_url) + +# Check web path availability +ynh_webpath_available $domain $path_url +# Register (book) web path +ynh_webpath_register $app $domain $path_url + +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= + +ynh_app_setting_set $app domain $domain +ynh_app_setting_set $app path $path_url +ynh_app_setting_set $app user $user + +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# INSTALL DEPENDENCIES +#================================================= + +ynh_install_app_dependencies supervisor + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +ynh_app_setting_set $app final_path $final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source "$final_path" + +#================================================= +# FIND AND OPEN A PORT +#================================================= + +# Find a free port +port=$(ynh_find_port 8081) +# Open this port +yunohost firewall allow --no-upnp TCP $port 2>&1 +ynh_app_setting_set $app port $port + +# For v2.0 only +# ynh_replace_string "default=80" "default=$port" "$final_path/app/server/index.py" +ynh_replace_string "'localhost', 8081" "'localhost', $port" "$final_path/python-server.py" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +# Create a dedicated nginx config +if [ "$path_url" != "/" ] +then + ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf" +fi +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= + +# Create a system user +ynh_system_user_create $app + +#================================================= +# SPECIFIC SETUP +#================================================= +# SET SUPERVISOR +#================================================= # 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 +cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf +ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf" +ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf" +ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf" -# 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 +supervisorctl update +supervisorctl restart $app -# Only give one user access to this app -sudo yunohost app removeaccess $app -sudo yunohost app addaccess $app -u $user +#================================================= +# REMOVE GOOGLE !!! +#================================================= -# Reload web server -sudo service nginx reload +sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set permissions to app files +chown -R root: $final_path + +#================================================= +# SETUP SSOWAT +#================================================= + +# Restrict access to admin only +yunohost app addaccess --users=$user $app + +#================================================= +# RELOAD NGINX +#================================================= + +systemctl reload nginx diff --git a/scripts/remove b/scripts/remove index 6d28ede..97e3c87 100755 --- a/scripts/remove +++ b/scripts/remove @@ -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 + +#================================================= +# LOAD SETTINGS +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get $app domain) +port=$(ynh_app_setting_get $app port) +final_path=$(ynh_app_setting_get $app final_path) + +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE APP MAIN DIR +#================================================= + +# Remove the app directory securely +ynh_secure_remove "$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= + +# Remove the dedicated nginx config +ynh_remove_nginx_config + +#================================================= +# CLOSE A PORT +#================================================= + +if yunohost firewall list | grep -q "\- $port$" +then + echo "Close port $port" + yunohost firewall disallow TCP $port 2>&1 +fi + +#================================================= +# SPECIFIC REMOVE +#================================================= +# REMOVE SUPERVISOR +#================================================= # Remove service -sudo supervisorctl stop $app -sudo rm -f /etc/supervisor/conf.d/$app.conf +supervisorctl stop $app +ynh_secure_remove /etc/supervisor/conf.d/$app.conf -# Remove supervisor package -# Need to be manage with future manifest/moulinette Debian package management -# sudo apt-get -y -qq remove supervisor +#================================================= +# REMOVE DEPENDENCIES +#================================================= -# Reload nginx configuration -sudo service nginx reload +# Remove metapackage and its dependencies +ynh_remove_app_dependencies + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= + +# Delete a system user +ynh_system_user_delete $app diff --git a/scripts/restore b/scripts/restore new file mode 100755 index 0000000..0f7f62b --- /dev/null +++ b/scripts/restore @@ -0,0 +1,95 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +if [ ! -e _common.sh ]; then + # Get the _common.sh file if it's not in the current directory + cp ../settings/scripts/_common.sh ./_common.sh + chmod a+rx _common.sh +fi +source _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 +#================================================= + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get $app domain) +path_url=$(ynh_app_setting_get $app path) +final_path=$(ynh_app_setting_get $app final_path) + +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= + +ynh_webpath_available $domain $path_url \ + || ynh_die "Path not available: ${domain}${path_url}" +test ! -d $final_path \ + || ynh_die "There is already a directory: $final_path " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= + +ynh_restore_file "/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= + +ynh_restore_file "$final_path" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= + +# Create the dedicated user (if not existing) +ynh_system_user_create $app + +#================================================= +# RESTORE USER RIGHTS +#================================================= + +# Restore permissions on app files +chown -R root: $final_path + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= + +# Define and install dependencies +ynh_install_app_dependencies supervisor + +#================================================= +# RESTORE THE SUPERVISOR CONFIGURATION +#================================================= + +ynh_restore_file "/etc/supervisor/conf.d/$app.conf" + +supervisorctl update +supervisorctl restart $app + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= + +systemctl reload nginx diff --git a/scripts/upgrade b/scripts/upgrade index 90d4dca..33445c0 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,30 +1,122 @@ #!/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 +#================================================= -# 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 domain) +path_url=$(ynh_app_setting_get $app path) +user=$(ynh_app_setting_get $app admin) +final_path=$(ynh_app_setting_get $app final_path) +port=$(ynh_app_setting_get $app port) -# Restart Linux-dash service -sudo supervisorctl restart $app +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= -# Reload web server & sso -sudo service nginx reload +# If final_path doesn't exist, create it +if [ -z $final_path ]; then + final_path=/var/www/$app + ynh_app_setting_set $app final_path $final_path +fi + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= + +# 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 + +#================================================= +# CHECK THE PATH +#================================================= + +# Normalize the URL path syntax +path_url=$(ynh_normalize_url_path $path_url) + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source "$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= + +# Create a dedicated nginx config +if [ "$path_url" != "/" ] +then + ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf" +fi +ynh_add_nginx_config + +#================================================= +# CREATE DEDICATED USER +#================================================= + +# Create a system user +ynh_system_user_create $app + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# UPGRADE SUPERVISOR +#================================================= + +# Set as a service with supervisor +cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf +ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf" +ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf" +ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf" + +supervisorctl update +supervisorctl restart $app + +#================================================= +# REMOVE GOOGLE !!! +#================================================= + +sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html" + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SECURE FILES AND DIRECTORIES +#================================================= + +# Set right permissions for curl installation +chown -R root: $final_path + +#================================================= +# SETUP SSOWAT +#================================================= + +# Restrict access to admin only +yunohost app addaccess --users=$user $app + +#================================================= +# RELOAD NGINX +#================================================= + +systemctl reload nginx diff --git a/sources/.editorconfig b/sources/.editorconfig deleted file mode 100755 index 4a7ea30..0000000 --- a/sources/.editorconfig +++ /dev/null @@ -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 diff --git a/sources/.gitignore b/sources/.gitignore deleted file mode 100644 index 91be243..0000000 --- a/sources/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -vendor -node_modules diff --git a/sources/LICENSE.md b/sources/LICENSE.md deleted file mode 100644 index ec1c59a..0000000 --- a/sources/LICENSE.md +++ /dev/null @@ -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. diff --git a/sources/README.md b/sources/README.md deleted file mode 100644 index a6a8a51..0000000 --- a/sources/README.md +++ /dev/null @@ -1,54 +0,0 @@ -
-

Linux Dash

- -
- A simple, low-overhead web dashboard for Linux -
- -

- - Demo  |  - Features  |  - - Installation  |  - Support - -

- -

- - Linux Dash Gitter chat - -

- -
-

- - Linux Dash screenshot - -

- -
- -## 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 diff --git a/sources/composer.json b/sources/composer.json deleted file mode 100644 index 3e62760..0000000 --- a/sources/composer.json +++ /dev/null @@ -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" - } -} diff --git a/sources/css/animate.css b/sources/css/animate.css deleted file mode 100644 index 14afba9..0000000 --- a/sources/css/animate.css +++ /dev/null @@ -1,6 +0,0 @@ -@charset "UTF-8";/*! -Animate.css - http://daneden.me/animate -Licensed under the MIT license - http://opensource.org/licenses/MIT - -Copyright (c) 2015 Daniel Eden -*/.animated{-webkit-animation-duration:1s;animation-duration:1s;-webkit-animation-fill-mode:both;animation-fill-mode:both}.animated.infinite{-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite}.animated.hinge{-webkit-animation-duration:2s;animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{-webkit-animation-duration:.75s;animation-duration:.75s}@-webkit-keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(.755,.050,.855,.060);transition-timing-function:cubic-bezier(.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(.755,.050,.855,.060);transition-timing-function:cubic-bezier(.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}@keyframes bounce{0%,100%,20%,53%,80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1);-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}40%,43%{-webkit-transition-timing-function:cubic-bezier(.755,.050,.855,.060);transition-timing-function:cubic-bezier(.755,.050,.855,.060);-webkit-transform:translate3d(0,-30px,0);transform:translate3d(0,-30px,0)}70%{-webkit-transition-timing-function:cubic-bezier(.755,.050,.855,.060);transition-timing-function:cubic-bezier(.755,.050,.855,.060);-webkit-transform:translate3d(0,-15px,0);transform:translate3d(0,-15px,0)}90%{-webkit-transform:translate3d(0,-4px,0);transform:translate3d(0,-4px,0)}}.bounce{-webkit-animation-name:bounce;animation-name:bounce;-webkit-transform-origin:center bottom;transform-origin:center bottom}@-webkit-keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}@keyframes flash{0%,100%,50%{opacity:1}25%,75%{opacity:0}}.flash{-webkit-animation-name:flash;animation-name:flash}@-webkit-keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes pulse{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}50%{-webkit-transform:scale3d(1.05,1.05,1.05);transform:scale3d(1.05,1.05,1.05)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.pulse{-webkit-animation-name:pulse;animation-name:pulse}@-webkit-keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes rubberBand{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}30%{-webkit-transform:scale3d(1.25,.75,1);transform:scale3d(1.25,.75,1)}40%{-webkit-transform:scale3d(.75,1.25,1);transform:scale3d(.75,1.25,1)}50%{-webkit-transform:scale3d(1.15,.85,1);transform:scale3d(1.15,.85,1)}65%{-webkit-transform:scale3d(.95,1.05,1);transform:scale3d(.95,1.05,1)}75%{-webkit-transform:scale3d(1.05,.95,1);transform:scale3d(1.05,.95,1)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.rubberBand{-webkit-animation-name:rubberBand;animation-name:rubberBand}@-webkit-keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}@keyframes shake{0%,100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}10%,30%,50%,70%,90%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}20%,40%,60%,80%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}}.shake{-webkit-animation-name:shake;animation-name:shake}@-webkit-keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}@keyframes swing{20%{-webkit-transform:rotate3d(0,0,1,15deg);transform:rotate3d(0,0,1,15deg)}40%{-webkit-transform:rotate3d(0,0,1,-10deg);transform:rotate3d(0,0,1,-10deg)}60%{-webkit-transform:rotate3d(0,0,1,5deg);transform:rotate3d(0,0,1,5deg)}80%{-webkit-transform:rotate3d(0,0,1,-5deg);transform:rotate3d(0,0,1,-5deg)}100%{-webkit-transform:rotate3d(0,0,1,0deg);transform:rotate3d(0,0,1,0deg)}}.swing{-webkit-transform-origin:top center;transform-origin:top center;-webkit-animation-name:swing;animation-name:swing}@-webkit-keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes tada{0%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}10%,20%{-webkit-transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg);transform:scale3d(.9,.9,.9) rotate3d(0,0,1,-3deg)}30%,50%,70%,90%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,3deg)}40%,60%,80%{-webkit-transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg);transform:scale3d(1.1,1.1,1.1) rotate3d(0,0,1,-3deg)}100%{-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.tada{-webkit-animation-name:tada;animation-name:tada}@-webkit-keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}@keyframes wobble{0%{-webkit-transform:none;transform:none}15%{-webkit-transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg);transform:translate3d(-25%,0,0) rotate3d(0,0,1,-5deg)}30%{-webkit-transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg);transform:translate3d(20%,0,0) rotate3d(0,0,1,3deg)}45%{-webkit-transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg);transform:translate3d(-15%,0,0) rotate3d(0,0,1,-3deg)}60%{-webkit-transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg);transform:translate3d(10%,0,0) rotate3d(0,0,1,2deg)}75%{-webkit-transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg);transform:translate3d(-5%,0,0) rotate3d(0,0,1,-1deg)}100%{-webkit-transform:none;transform:none}}.wobble{-webkit-animation-name:wobble;animation-name:wobble}@-webkit-keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}@keyframes bounceIn{0%,100%,20%,40%,60%,80%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}20%{-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}40%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}60%{opacity:1;-webkit-transform:scale3d(1.03,1.03,1.03);transform:scale3d(1.03,1.03,1.03)}80%{-webkit-transform:scale3d(.97,.97,.97);transform:scale3d(.97,.97,.97)}100%{opacity:1;-webkit-transform:scale3d(1,1,1);transform:scale3d(1,1,1)}}.bounceIn{-webkit-animation-name:bounceIn;animation-name:bounceIn}@-webkit-keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInDown{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,-3000px,0);transform:translate3d(0,-3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,25px,0);transform:translate3d(0,25px,0)}75%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}90%{-webkit-transform:translate3d(0,5px,0);transform:translate3d(0,5px,0)}100%{-webkit-transform:none;transform:none}}.bounceInDown{-webkit-animation-name:bounceInDown;animation-name:bounceInDown}@-webkit-keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInLeft{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(-3000px,0,0);transform:translate3d(-3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(25px,0,0);transform:translate3d(25px,0,0)}75%{-webkit-transform:translate3d(-10px,0,0);transform:translate3d(-10px,0,0)}90%{-webkit-transform:translate3d(5px,0,0);transform:translate3d(5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInLeft{-webkit-animation-name:bounceInLeft;animation-name:bounceInLeft}@-webkit-keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}@keyframes bounceInRight{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(3000px,0,0);transform:translate3d(3000px,0,0)}60%{opacity:1;-webkit-transform:translate3d(-25px,0,0);transform:translate3d(-25px,0,0)}75%{-webkit-transform:translate3d(10px,0,0);transform:translate3d(10px,0,0)}90%{-webkit-transform:translate3d(-5px,0,0);transform:translate3d(-5px,0,0)}100%{-webkit-transform:none;transform:none}}.bounceInRight{-webkit-animation-name:bounceInRight;animation-name:bounceInRight}@-webkit-keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes bounceInUp{0%,100%,60%,75%,90%{-webkit-transition-timing-function:cubic-bezier(.215,.61,.355,1);transition-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;-webkit-transform:translate3d(0,3000px,0);transform:translate3d(0,3000px,0)}60%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}75%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}90%{-webkit-transform:translate3d(0,-5px,0);transform:translate3d(0,-5px,0)}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.bounceInUp{-webkit-animation-name:bounceInUp;animation-name:bounceInUp}@-webkit-keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}@keyframes bounceOut{20%{-webkit-transform:scale3d(.9,.9,.9);transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;-webkit-transform:scale3d(1.1,1.1,1.1);transform:scale3d(1.1,1.1,1.1)}100%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}}.bounceOut{-webkit-animation-name:bounceOut;animation-name:bounceOut}@-webkit-keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes bounceOutDown{20%{-webkit-transform:translate3d(0,10px,0);transform:translate3d(0,10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.bounceOutDown{-webkit-animation-name:bounceOutDown;animation-name:bounceOutDown}@-webkit-keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes bounceOutLeft{20%{opacity:1;-webkit-transform:translate3d(20px,0,0);transform:translate3d(20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.bounceOutLeft{-webkit-animation-name:bounceOutLeft;animation-name:bounceOutLeft}@-webkit-keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes bounceOutRight{20%{opacity:1;-webkit-transform:translate3d(-20px,0,0);transform:translate3d(-20px,0,0)}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.bounceOutRight{-webkit-animation-name:bounceOutRight;animation-name:bounceOutRight}@-webkit-keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes bounceOutUp{20%{-webkit-transform:translate3d(0,-10px,0);transform:translate3d(0,-10px,0)}40%,45%{opacity:1;-webkit-transform:translate3d(0,20px,0);transform:translate3d(0,20px,0)}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.bounceOutUp{-webkit-animation-name:bounceOutUp;animation-name:bounceOutUp}@-webkit-keyframes fadeIn{0%{opacity:0}100%{opacity:1}}@keyframes fadeIn{0%{opacity:0}100%{opacity:1}}.fadeIn{-webkit-animation-name:fadeIn;animation-name:fadeIn}@-webkit-keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDown{0%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDown{-webkit-animation-name:fadeInDown;animation-name:fadeInDown}@-webkit-keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInDownBig{0%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInDownBig{-webkit-animation-name:fadeInDownBig;animation-name:fadeInDownBig}@-webkit-keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeft{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeft{-webkit-animation-name:fadeInLeft;animation-name:fadeInLeft}@-webkit-keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInLeftBig{0%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInLeftBig{-webkit-animation-name:fadeInLeftBig;animation-name:fadeInLeftBig}@-webkit-keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRight{0%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRight{-webkit-animation-name:fadeInRight;animation-name:fadeInRight}@-webkit-keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInRightBig{0%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInRightBig{-webkit-animation-name:fadeInRightBig;animation-name:fadeInRightBig}@-webkit-keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUp{0%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUp{-webkit-animation-name:fadeInUp;animation-name:fadeInUp}@-webkit-keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes fadeInUpBig{0%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}100%{opacity:1;-webkit-transform:none;transform:none}}.fadeInUpBig{-webkit-animation-name:fadeInUpBig;animation-name:fadeInUpBig}@-webkit-keyframes fadeOut{0%{opacity:1}100%{opacity:0}}@keyframes fadeOut{0%{opacity:1}100%{opacity:0}}.fadeOut{-webkit-animation-name:fadeOut;animation-name:fadeOut}@-webkit-keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes fadeOutDown{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.fadeOutDown{-webkit-animation-name:fadeOutDown;animation-name:fadeOutDown}@-webkit-keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}@keyframes fadeOutDownBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,2000px,0);transform:translate3d(0,2000px,0)}}.fadeOutDownBig{-webkit-animation-name:fadeOutDownBig;animation-name:fadeOutDownBig}@-webkit-keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes fadeOutLeft{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.fadeOutLeft{-webkit-animation-name:fadeOutLeft;animation-name:fadeOutLeft}@-webkit-keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}@keyframes fadeOutLeftBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(-2000px,0,0);transform:translate3d(-2000px,0,0)}}.fadeOutLeftBig{-webkit-animation-name:fadeOutLeftBig;animation-name:fadeOutLeftBig}@-webkit-keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes fadeOutRight{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.fadeOutRight{-webkit-animation-name:fadeOutRight;animation-name:fadeOutRight}@-webkit-keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}@keyframes fadeOutRightBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(2000px,0,0);transform:translate3d(2000px,0,0)}}.fadeOutRightBig{-webkit-animation-name:fadeOutRightBig;animation-name:fadeOutRightBig}@-webkit-keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes fadeOutUp{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.fadeOutUp{-webkit-animation-name:fadeOutUp;animation-name:fadeOutUp}@-webkit-keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}@keyframes fadeOutUpBig{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(0,-2000px,0);transform:translate3d(0,-2000px,0)}}.fadeOutUpBig{-webkit-animation-name:fadeOutUpBig;animation-name:fadeOutUpBig}@-webkit-keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}@keyframes flip{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-360deg);transform:perspective(400px) rotate3d(0,1,0,-360deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}40%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-190deg);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}50%{-webkit-transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);transform:perspective(400px) translate3d(0,0,150px) rotate3d(0,1,0,-170deg);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}80%{-webkit-transform:perspective(400px) scale3d(.95,.95,.95);transform:perspective(400px) scale3d(.95,.95,.95);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}100%{-webkit-transform:perspective(400px);transform:perspective(400px);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}}.animated.flip{-webkit-backface-visibility:visible;backface-visibility:visible;-webkit-animation-name:flip;animation-name:flip}@-webkit-keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInX{0%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(1,0,0,10deg);transform:perspective(400px) rotate3d(1,0,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-5deg);transform:perspective(400px) rotate3d(1,0,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInX{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInX;animation-name:flipInX}@-webkit-keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}@keyframes flipInY{0%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in;opacity:0}40%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-20deg);transform:perspective(400px) rotate3d(0,1,0,-20deg);-webkit-transition-timing-function:ease-in;transition-timing-function:ease-in}60%{-webkit-transform:perspective(400px) rotate3d(0,1,0,10deg);transform:perspective(400px) rotate3d(0,1,0,10deg);opacity:1}80%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-5deg);transform:perspective(400px) rotate3d(0,1,0,-5deg)}100%{-webkit-transform:perspective(400px);transform:perspective(400px)}}.flipInY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipInY;animation-name:flipInY}@-webkit-keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}@keyframes flipOutX{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(1,0,0,-20deg);transform:perspective(400px) rotate3d(1,0,0,-20deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(1,0,0,90deg);transform:perspective(400px) rotate3d(1,0,0,90deg);opacity:0}}.flipOutX{-webkit-animation-name:flipOutX;animation-name:flipOutX;-webkit-backface-visibility:visible!important;backface-visibility:visible!important}@-webkit-keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}@keyframes flipOutY{0%{-webkit-transform:perspective(400px);transform:perspective(400px)}30%{-webkit-transform:perspective(400px) rotate3d(0,1,0,-15deg);transform:perspective(400px) rotate3d(0,1,0,-15deg);opacity:1}100%{-webkit-transform:perspective(400px) rotate3d(0,1,0,90deg);transform:perspective(400px) rotate3d(0,1,0,90deg);opacity:0}}.flipOutY{-webkit-backface-visibility:visible!important;backface-visibility:visible!important;-webkit-animation-name:flipOutY;animation-name:flipOutY}@-webkit-keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}@keyframes lightSpeedIn{0%{-webkit-transform:translate3d(100%,0,0) skewX(-30deg);transform:translate3d(100%,0,0) skewX(-30deg);opacity:0}60%{-webkit-transform:skewX(20deg);transform:skewX(20deg);opacity:1}80%{-webkit-transform:skewX(-5deg);transform:skewX(-5deg);opacity:1}100%{-webkit-transform:none;transform:none;opacity:1}}.lightSpeedIn{-webkit-animation-name:lightSpeedIn;animation-name:lightSpeedIn;-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}@-webkit-keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}@keyframes lightSpeedOut{0%{opacity:1}100%{-webkit-transform:translate3d(100%,0,0) skewX(30deg);transform:translate3d(100%,0,0) skewX(30deg);opacity:0}}.lightSpeedOut{-webkit-animation-name:lightSpeedOut;animation-name:lightSpeedOut;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}@-webkit-keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateIn{0%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,-200deg);transform:rotate3d(0,0,1,-200deg);opacity:0}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:none;transform:none;opacity:1}}.rotateIn{-webkit-animation-name:rotateIn;animation-name:rotateIn}@-webkit-keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownLeft{-webkit-animation-name:rotateInDownLeft;animation-name:rotateInDownLeft}@-webkit-keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInDownRight{-webkit-animation-name:rotateInDownRight;animation-name:rotateInDownRight}@-webkit-keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpLeft{-webkit-animation-name:rotateInUpLeft;animation-name:rotateInUpLeft}@-webkit-keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}@keyframes rotateInUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-90deg);transform:rotate3d(0,0,1,-90deg);opacity:0}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:none;transform:none;opacity:1}}.rotateInUpRight{-webkit-animation-name:rotateInUpRight;animation-name:rotateInUpRight}@-webkit-keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}@keyframes rotateOut{0%{-webkit-transform-origin:center;transform-origin:center;opacity:1}100%{-webkit-transform-origin:center;transform-origin:center;-webkit-transform:rotate3d(0,0,1,200deg);transform:rotate3d(0,0,1,200deg);opacity:0}}.rotateOut{-webkit-animation-name:rotateOut;animation-name:rotateOut}@-webkit-keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}@keyframes rotateOutDownLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,45deg);transform:rotate3d(0,0,1,45deg);opacity:0}}.rotateOutDownLeft{-webkit-animation-name:rotateOutDownLeft;animation-name:rotateOutDownLeft}@-webkit-keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutDownRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutDownRight{-webkit-animation-name:rotateOutDownRight;animation-name:rotateOutDownRight}@-webkit-keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}@keyframes rotateOutUpLeft{0%{-webkit-transform-origin:left bottom;transform-origin:left bottom;opacity:1}100%{-webkit-transform-origin:left bottom;transform-origin:left bottom;-webkit-transform:rotate3d(0,0,1,-45deg);transform:rotate3d(0,0,1,-45deg);opacity:0}}.rotateOutUpLeft{-webkit-animation-name:rotateOutUpLeft;animation-name:rotateOutUpLeft}@-webkit-keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}@keyframes rotateOutUpRight{0%{-webkit-transform-origin:right bottom;transform-origin:right bottom;opacity:1}100%{-webkit-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate3d(0,0,1,90deg);transform:rotate3d(0,0,1,90deg);opacity:0}}.rotateOutUpRight{-webkit-animation-name:rotateOutUpRight;animation-name:rotateOutUpRight}@-webkit-keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}@keyframes hinge{0%{-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}20%,60%{-webkit-transform:rotate3d(0,0,1,80deg);transform:rotate3d(0,0,1,80deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out}40%,80%{-webkit-transform:rotate3d(0,0,1,60deg);transform:rotate3d(0,0,1,60deg);-webkit-transform-origin:top left;transform-origin:top left;-webkit-animation-timing-function:ease-in-out;animation-timing-function:ease-in-out;opacity:1}100%{-webkit-transform:translate3d(0,700px,0);transform:translate3d(0,700px,0);opacity:0}}.hinge{-webkit-animation-name:hinge;animation-name:hinge}@-webkit-keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}@keyframes rollIn{0%{opacity:0;-webkit-transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg);transform:translate3d(-100%,0,0) rotate3d(0,0,1,-120deg)}100%{opacity:1;-webkit-transform:none;transform:none}}.rollIn{-webkit-animation-name:rollIn;animation-name:rollIn}@-webkit-keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}@keyframes rollOut{0%{opacity:1}100%{opacity:0;-webkit-transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg);transform:translate3d(100%,0,0) rotate3d(0,0,1,120deg)}}.rollOut{-webkit-animation-name:rollOut;animation-name:rollOut}@-webkit-keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}@keyframes zoomIn{0%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}50%{opacity:1}}.zoomIn{-webkit-animation-name:zoomIn;animation-name:zoomIn}@-webkit-keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInDown{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInDown{-webkit-animation-name:zoomInDown;animation-name:zoomInDown}@-webkit-keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInLeft{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(-1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(10px,0,0);transform:scale3d(.475,.475,.475) translate3d(10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInLeft{-webkit-animation-name:zoomInLeft;animation-name:zoomInLeft}@-webkit-keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInRight{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);transform:scale3d(.1,.1,.1) translate3d(1000px,0,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);transform:scale3d(.475,.475,.475) translate3d(-10px,0,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInRight{-webkit-animation-name:zoomInRight;animation-name:zoomInRight}@-webkit-keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomInUp{0%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);transform:scale3d(.1,.1,.1) translate3d(0,1000px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}60%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomInUp{-webkit-animation-name:zoomInUp;animation-name:zoomInUp}@-webkit-keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}@keyframes zoomOut{0%{opacity:1}50%{opacity:0;-webkit-transform:scale3d(.3,.3,.3);transform:scale3d(.3,.3,.3)}100%{opacity:0}}.zoomOut{-webkit-animation-name:zoomOut;animation-name:zoomOut}@-webkit-keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutDown{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);transform:scale3d(.475,.475,.475) translate3d(0,-60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutDown{-webkit-animation-name:zoomOutDown;animation-name:zoomOutDown}@-webkit-keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}@keyframes zoomOutLeft{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(42px,0,0);transform:scale3d(.475,.475,.475) translate3d(42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(-2000px,0,0);transform:scale(.1) translate3d(-2000px,0,0);-webkit-transform-origin:left center;transform-origin:left center}}.zoomOutLeft{-webkit-animation-name:zoomOutLeft;animation-name:zoomOutLeft}@-webkit-keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}@keyframes zoomOutRight{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(-42px,0,0);transform:scale3d(.475,.475,.475) translate3d(-42px,0,0)}100%{opacity:0;-webkit-transform:scale(.1) translate3d(2000px,0,0);transform:scale(.1) translate3d(2000px,0,0);-webkit-transform-origin:right center;transform-origin:right center}}.zoomOutRight{-webkit-animation-name:zoomOutRight;animation-name:zoomOutRight}@-webkit-keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}@keyframes zoomOutUp{40%{opacity:1;-webkit-transform:scale3d(.475,.475,.475) translate3d(0,60px,0);transform:scale3d(.475,.475,.475) translate3d(0,60px,0);-webkit-animation-timing-function:cubic-bezier(.55,.055,.675,.19);animation-timing-function:cubic-bezier(.55,.055,.675,.19)}100%{opacity:0;-webkit-transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);transform:scale3d(.1,.1,.1) translate3d(0,-2000px,0);-webkit-transform-origin:center bottom;transform-origin:center bottom;-webkit-animation-timing-function:cubic-bezier(.175,.885,.32,1);animation-timing-function:cubic-bezier(.175,.885,.32,1)}}.zoomOutUp{-webkit-animation-name:zoomOutUp;animation-name:zoomOutUp}@-webkit-keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInDown{0%{-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInDown{-webkit-animation-name:slideInDown;animation-name:slideInDown}@-webkit-keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInLeft{0%{-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInLeft{-webkit-animation-name:slideInLeft;animation-name:slideInLeft}@-webkit-keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInRight{0%{-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInRight{-webkit-animation-name:slideInRight;animation-name:slideInRight}@-webkit-keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}@keyframes slideInUp{0%{-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0);visibility:visible}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}}.slideInUp{-webkit-animation-name:slideInUp;animation-name:slideInUp}@-webkit-keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}@keyframes slideOutDown{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,100%,0);transform:translate3d(0,100%,0)}}.slideOutDown{-webkit-animation-name:slideOutDown;animation-name:slideOutDown}@-webkit-keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}@keyframes slideOutLeft{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(-100%,0,0);transform:translate3d(-100%,0,0)}}.slideOutLeft{-webkit-animation-name:slideOutLeft;animation-name:slideOutLeft}@-webkit-keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}@keyframes slideOutRight{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(100%,0,0);transform:translate3d(100%,0,0)}}.slideOutRight{-webkit-animation-name:slideOutRight;animation-name:slideOutRight}@-webkit-keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}@keyframes slideOutUp{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}100%{visibility:hidden;-webkit-transform:translate3d(0,-100%,0);transform:translate3d(0,-100%,0)}}.slideOutUp{-webkit-animation-name:slideOutUp;animation-name:slideOutUp} \ No newline at end of file diff --git a/sources/css/main.css b/sources/css/main.css deleted file mode 100644 index 2bb5a92..0000000 --- a/sources/css/main.css +++ /dev/null @@ -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; - } -} diff --git a/sources/css/theme-old.css b/sources/css/theme-old.css deleted file mode 100644 index 0e02cdd..0000000 --- a/sources/css/theme-old.css +++ /dev/null @@ -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%; -} diff --git a/sources/css/themes.css b/sources/css/themes.css deleted file mode 100644 index e3a18aa..0000000 --- a/sources/css/themes.css +++ /dev/null @@ -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; -} diff --git a/sources/demo.html b/sources/demo.html deleted file mode 100644 index e228927..0000000 --- a/sources/demo.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - linux-dash : Server Monitoring Web Dashboard - - - - - - - - - - - - - - - - - - - - Fork me on GitHub - - -
-

Linux Dash

- - A simple linux dashboard - - - - - -
- -
-

Setting server...

- -
- - -
- - - - - - - - - - - - diff --git a/sources/favicon.ico b/sources/favicon.ico deleted file mode 100644 index cf41009942d1ecfc1de2ee9d809ef3ec948ff725..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99678 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 diff --git a/sources/img/themes/congruent_pentagon.png b/sources/img/themes/congruent_pentagon.png deleted file mode 100644 index c7126603280255eec0b7784b461f4e4c3f6a9d8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28934 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 VKS%rozu)kVs-otz3I&Vs{{j5Cbi@Dv diff --git a/sources/img/themes/contemporary_china_2.png b/sources/img/themes/contemporary_china_2.png deleted file mode 100644 index 4bd667dfaf79990da351cca89dbde6038e9aa432..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7101 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 diff --git a/sources/img/themes/crossword.png b/sources/img/themes/crossword.png deleted file mode 100644 index 2f9f1ad08473dcf728044895fd7809749e38eb9e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 43694 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
  • vfwTcDjSFU!^0 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 R_gnw~002ovPDHLkV1m#co5lbD diff --git a/sources/index.html b/sources/index.html deleted file mode 100644 index 0c02756..0000000 --- a/sources/index.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - linux-dash : Server Monitoring Web Dashboard - - - - - - - - - - - - - - - - - - -
    -

    Linux Dash

    - A simple linux dashboard - - -
    - - -
    -
    - - - - - - - - diff --git a/sources/js/angular-route.js b/sources/js/angular-route.js deleted file mode 100644 index 6820318..0000000 --- a/sources/js/angular-route.js +++ /dev/null @@ -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`. - * - * - *
    - */ - /* 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.}` - 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.}` - route parameters extracted from the current - * `$location.path()` by applying the current route - * - * - `resolve` - `{Object.=}` - 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.}` - 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. - * - * - * - *
    - * Choose: - * Moby | - * Moby: Ch1 | - * Gatsby | - * Gatsby: Ch4 | - * Scarlet Letter
    - * - *
    - * - *
    - * - *
    $location.path() = {{$location.path()}}
    - *
    $route.current.templateUrl = {{$route.current.templateUrl}}
    - *
    $route.current.params = {{$route.current.params}}
    - *
    $route.current.scope.name = {{$route.current.scope.name}}
    - *
    $routeParams = {{$routeParams}}
    - *
    - *
    - * - * - * controller: {{name}}
    - * Book Id: {{params.bookId}}
    - *
    - * - * - * controller: {{name}}
    - * Book Id: {{params.bookId}}
    - * Chapter Id: {{params.chapterId}} - *
    - * - * - * 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); - * }); - * - * - * - * - * 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/); - * }); - * - *
    - */ - - /** - * @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 - - -
    - Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
    - -
    -
    -
    -
    - -
    $location.path() = {{main.$location.path()}}
    -
    $route.current.templateUrl = {{main.$route.current.templateUrl}}
    -
    $route.current.params = {{main.$route.current.params}}
    -
    $routeParams = {{main.$routeParams}}
    -
    -
    - - -
    - controller: {{book.name}}
    - Book Id: {{book.params.bookId}}
    -
    -
    - - -
    - controller: {{chapter.name}}
    - Book Id: {{chapter.params.bookId}}
    - Chapter Id: {{chapter.params.chapterId}} -
    -
    - - - .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%; - } - - - - 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; - }]); - - - - - 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/); - }); - -
    - */ - - -/** - * @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); diff --git a/sources/js/angular.min.js b/sources/js/angular.min.js deleted file mode 100644 index 836aa1e..0000000 --- a/sources/js/angular.min.js +++ /dev/null @@ -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").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/,">"));}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")+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 4096 bytes)!"));else{if(p.cookie!==y)for(y=p.cookie,d=y.split("; "),aa={},f=0;fl&&this.remove(s.key),b},get:function(a){if(l").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("
    ").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;qJ.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;bq.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+"";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=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=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;1h?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=this.promise.$$state.status&&d&&d.length&&b(function(){for(var b,e,f=0,g=d.length;fa)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=1r&&(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;lHa)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;kb;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)0b&&(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;lb&&(d="-",b=-b);for(b=""+b;b.length-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);0b||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=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(?:<\/\1>|)$/,Pb=/<|&#?\w+;/,af=/<([\w:]+)/,bf=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, -ja={option:[1,'"],thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_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":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=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.indexa){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","<=",">="))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;fa.getHours()?c.AMPMS[0]:c.AMPMS[1]},Z:function(a){a=-1*a.getTimezoneOffset();return a=(0<= -a?"+":"")+(Cb(Math[0=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;ff||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;lD;)d=q.pop(),m(Q,d.label,!1),d.element.remove();r(Q,function(a,c){0a&&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@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;}'); -//# sourceMappingURL=angular.min.js.map diff --git a/sources/js/linuxDash.js b/sources/js/linuxDash.js deleted file mode 100644 index 3316cf4..0000000 --- a/sources/js/linuxDash.js +++ /dev/null @@ -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: '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' - }; - }); - - /** - * 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: '' - }; - }); - - /** - * 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); - } - - }); - } - } - }; - }]); - -}()); diff --git a/sources/js/modules.js b/sources/js/modules.js deleted file mode 100644 index a899d01..0000000 --- a/sources/js/modules.js +++ /dev/null @@ -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: '' - }, - { - name: 'ipAddresses', - template: '' - }, - { - name: 'ramIntensiveProcesses', - template: '' - }, - { - name: 'cpuIntensiveProcesses', - template: '' - }, - { - name: 'networkConnections', - template: '' - }, - { - name: 'serverAccounts', - template: '' - }, - { - name: 'loggedInAccounts', - template: '' - }, - { - name: 'recentLogins', - template: '' - }, - { - name: 'arpCacheTable', - template: '' - }, - { - name: 'commonApplications', - template: '' - }, - { - name: 'pingSpeeds', - template: '' - }, - { - name: 'bandwidth', - template: '' - }, - { - name: 'swapUsage', - template: '' - }, - { - name: 'internetSpeed', - template: '' - }, - { - name: 'memcached', - template: '' - }, - { - name: 'redis', - template: '' - }, - { - name: 'memoryInfo', - template: '' - }, - { - name: 'cpuInfo', - template: '' - }, - { - name: 'ioStats', - template: '' - }, - { - name: 'scheduledCrons', - template: '' - }, - { - name: 'cronHistory', - template: '' - } - ]; - - 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; - }]); - - }); - -}()); diff --git a/sources/js/smoothie.min.js b/sources/js/smoothie.min.js deleted file mode 100644 index 0c7823a..0000000 --- a/sources/js/smoothie.min.js +++ /dev/null @@ -1 +0,0 @@ -(function(e){function n(e){this.options=t.extend({},n.defaultOptions,e);this.clear()}function r(e){this.options=t.extend({},r.defaultChartOptions,e);this.seriesSet=[];this.currentValueRange=1;this.currentVisMinValue=0;this.lastRenderTimeMillis=0}var t={extend:function(){arguments[0]=arguments[0]||{};for(var e=1;ethis.maxValue){this.maxValue=t}if(t=0&&this.data[r][0]>e){r--}if(r===-1){this.data.splice(0,0,[e,t])}else if(this.data.length>0&&this.data[r][0]===e){if(n){this.data[r][1]+=t;t=this.data[r][1]}else{this.data[r][1]=t}}else if(r=t&&this.data[n+1][0]0){e.resetBoundsTimerId=setInterval(function(){e.resetBounds()},e.options.resetBoundsInterval)}};r.prototype.removeTimeSeries=function(e){var t=this.seriesSet.length;for(var n=0;n.1||Math.abs(a)>.1;this.currentValueRange+=e.scaleSmoothing*u;this.currentVisMinValue+=e.scaleSmoothing*a}this.valueRange={min:n,max:t}};r.prototype.render=function(e,t){var n=(new Date).getTime();if(!this.isAnimatingScale){var r=Math.min(1e3/6,this.options.millisPerPixel);if(n-this.lastRenderTimeMillis0){i.beginPath();for(var l=t-t%s.grid.millisPerLine;l>=u;l-=s.grid.millisPerLine){var c=f(l);if(s.grid.sharpLines){c-=.5}i.moveTo(c,0);i.lineTo(c,o.height)}i.stroke();i.closePath()}for(var h=1;h1){if(w.fillStyle){i.lineTo(o.width+w.lineWidth+1,x);i.lineTo(o.width+w.lineWidth+1,o.height+w.lineWidth+1);i.lineTo(E,o.height+w.lineWidth);i.fillStyle=w.fillStyle;i.fill()}if(w.strokeStyle&&w.strokeStyle!=="none"){i.stroke()}i.closePath()}i.restore()}if(!s.labels.disabled&&!isNaN(this.valueRange.min)&&!isNaN(this.valueRange.max)){var k=s.yMaxFormatter(this.valueRange.max,s.labels.precision),L=s.yMinFormatter(this.valueRange.min,s.labels.precision);i.fillStyle=s.labels.fillStyle;i.fillText(k,o.width-i.measureText(k).width-2,s.labels.fontSize);i.fillText(L,o.width-i.measureText(L).width-2,o.height-2)}if(s.timestampFormatter&&s.grid.millisPerLine>0){var A=o.width-i.measureText(L).width+4;for(var l=t-t%s.grid.millisPerLine;l>=u;l-=s.grid.millisPerLine){var c=f(l);if(c to stop' - server.serve_forever() diff --git a/sources/server/index.go b/sources/server/index.go deleted file mode 100644 index 4ec8787..0000000 --- a/sources/server/index.go +++ /dev/null @@ -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) - } -} diff --git a/sources/server/index.js b/sources/server/index.js deleted file mode 100644 index a05d4a0..0000000 --- a/sources/server/index.js +++ /dev/null @@ -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); - }); - -}); diff --git a/sources/server/index.php b/sources/server/index.php deleted file mode 100644 index 296a551..0000000 --- a/sources/server/index.php +++ /dev/null @@ -1,8 +0,0 @@ -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 \ No newline at end of file diff --git a/sources/server/modules/shell_files/bandwidth.sh b/sources/server/modules/shell_files/bandwidth.sh deleted file mode 100755 index 51a2cd7..0000000 --- a/sources/server/modules/shell_files/bandwidth.sh +++ /dev/null @@ -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' diff --git a/sources/server/modules/shell_files/common_applications.sh b/sources/server/modules/shell_files/common_applications.sh deleted file mode 100755 index d9e81bd..0000000 --- a/sources/server/modules/shell_files/common_applications.sh +++ /dev/null @@ -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%?} "]" \ No newline at end of file diff --git a/sources/server/modules/shell_files/cpu_info.sh b/sources/server/modules/shell_files/cpu_info.sh deleted file mode 100755 index c00b603..0000000 --- a/sources/server/modules/shell_files/cpu_info.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -result=$(/usr/bin/lscpu \ - | /usr/bin/awk -F: '{print "\""$1"\": \""$2"\"," } '\ - ) - -echo "{" ${result%?} "}" \ No newline at end of file diff --git a/sources/server/modules/shell_files/cpu_intensive_processes.sh b/sources/server/modules/shell_files/cpu_intensive_processes.sh deleted file mode 100755 index a193bb2..0000000 --- a/sources/server/modules/shell_files/cpu_intensive_processes.sh +++ /dev/null @@ -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%?} "]" \ No newline at end of file diff --git a/sources/server/modules/shell_files/cpu_utilization.sh b/sources/server/modules/shell_files/cpu_utilization.sh deleted file mode 100755 index 7d6c361..0000000 --- a/sources/server/modules/shell_files/cpu_utilization.sh +++ /dev/null @@ -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" diff --git a/sources/server/modules/shell_files/cron_history.sh b/sources/server/modules/shell_files/cron_history.sh deleted file mode 100755 index df5f15d..0000000 --- a/sources/server/modules/shell_files/cron_history.sh +++ /dev/null @@ -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%?}] \ No newline at end of file diff --git a/sources/server/modules/shell_files/current_ram.sh b/sources/server/modules/shell_files/current_ram.sh deleted file mode 100755 index 1a10920..0000000 --- a/sources/server/modules/shell_files/current_ram.sh +++ /dev/null @@ -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) " }" }' diff --git a/sources/server/modules/shell_files/disk_partitions.sh b/sources/server/modules/shell_files/disk_partitions.sh deleted file mode 100755 index d563d19..0000000 --- a/sources/server/modules/shell_files/disk_partitions.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/download_transfer_rate.sh b/sources/server/modules/shell_files/download_transfer_rate.sh deleted file mode 100755 index 68b401a..0000000 --- a/sources/server/modules/shell_files/download_transfer_rate.sh +++ /dev/null @@ -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}" diff --git a/sources/server/modules/shell_files/general_info.sh b/sources/server/modules/shell_files/general_info.sh deleted file mode 100755 index a76b20c..0000000 --- a/sources/server/modules/shell_files/general_info.sh +++ /dev/null @@ -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\" \ - } diff --git a/sources/server/modules/shell_files/internet_speed.sh b/sources/server/modules/shell_files/internet_speed.sh deleted file mode 100755 index fa2478a..0000000 --- a/sources/server/modules/shell_files/internet_speed.sh +++ /dev/null @@ -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' \ No newline at end of file diff --git a/sources/server/modules/shell_files/io_stats.sh b/sources/server/modules/shell_files/io_stats.sh deleted file mode 100755 index 0e14d4e..0000000 --- a/sources/server/modules/shell_files/io_stats.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/ip_addresses.sh b/sources/server/modules/shell_files/ip_addresses.sh deleted file mode 100755 index 1c4e558..0000000 --- a/sources/server/modules/shell_files/ip_addresses.sh +++ /dev/null @@ -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' diff --git a/sources/server/modules/shell_files/load_avg.sh b/sources/server/modules/shell_files/load_avg.sh deleted file mode 100755 index f2afcb0..0000000 --- a/sources/server/modules/shell_files/load_avg.sh +++ /dev/null @@ -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%?} \ No newline at end of file diff --git a/sources/server/modules/shell_files/logged_in_users.sh b/sources/server/modules/shell_files/logged_in_users.sh deleted file mode 100755 index 635163a..0000000 --- a/sources/server/modules/shell_files/logged_in_users.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/memcached.sh b/sources/server/modules/shell_files/memcached.sh deleted file mode 100755 index 88f8516..0000000 --- a/sources/server/modules/shell_files/memcached.sh +++ /dev/null @@ -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' \ No newline at end of file diff --git a/sources/server/modules/shell_files/memory_info.sh b/sources/server/modules/shell_files/memory_info.sh deleted file mode 100755 index 9b2ce6c..0000000 --- a/sources/server/modules/shell_files/memory_info.sh +++ /dev/null @@ -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' diff --git a/sources/server/modules/shell_files/network_connections.sh b/sources/server/modules/shell_files/network_connections.sh deleted file mode 100755 index 9f952f8..0000000 --- a/sources/server/modules/shell_files/network_connections.sh +++ /dev/null @@ -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' diff --git a/sources/server/modules/shell_files/number_of_cpu_cores.sh b/sources/server/modules/shell_files/number_of_cpu_cores.sh deleted file mode 100755 index 42c20e5..0000000 --- a/sources/server/modules/shell_files/number_of_cpu_cores.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -numberOfCores=$(/bin/grep -c 'model name' /proc/cpuinfo) - -if [length($numberOfCores)]; then - echo "cannnot be found"; -fi \ No newline at end of file diff --git a/sources/server/modules/shell_files/ping.sh b/sources/server/modules/shell_files/ping.sh deleted file mode 100755 index 9852b14..0000000 --- a/sources/server/modules/shell_files/ping.sh +++ /dev/null @@ -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' diff --git a/sources/server/modules/shell_files/ram_intensive_processes.sh b/sources/server/modules/shell_files/ram_intensive_processes.sh deleted file mode 100755 index a86e120..0000000 --- a/sources/server/modules/shell_files/ram_intensive_processes.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/recent_account_logins.sh b/sources/server/modules/shell_files/recent_account_logins.sh deleted file mode 100755 index de0b080..0000000 --- a/sources/server/modules/shell_files/recent_account_logins.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/redis.sh b/sources/server/modules/shell_files/redis.sh deleted file mode 100755 index 38bcaf4..0000000 --- a/sources/server/modules/shell_files/redis.sh +++ /dev/null @@ -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%?} } \ No newline at end of file diff --git a/sources/server/modules/shell_files/scheduled_crons.sh b/sources/server/modules/shell_files/scheduled_crons.sh deleted file mode 100755 index d21fdd4..0000000 --- a/sources/server/modules/shell_files/scheduled_crons.sh +++ /dev/null @@ -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 # */ - [[ -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}" # */ - -# 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}" \ No newline at end of file diff --git a/sources/server/modules/shell_files/swap.sh b/sources/server/modules/shell_files/swap.sh deleted file mode 100755 index 4b3bcbf..0000000 --- a/sources/server/modules/shell_files/swap.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/server/modules/shell_files/upload_transfer_rate.sh b/sources/server/modules/shell_files/upload_transfer_rate.sh deleted file mode 100755 index 711521f..0000000 --- a/sources/server/modules/shell_files/upload_transfer_rate.sh +++ /dev/null @@ -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}" diff --git a/sources/server/modules/shell_files/user_accounts.sh b/sources/server/modules/shell_files/user_accounts.sh deleted file mode 100755 index 599d6ba..0000000 --- a/sources/server/modules/shell_files/user_accounts.sh +++ /dev/null @@ -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%?} ] \ No newline at end of file diff --git a/sources/templates/app/base-plugin.html b/sources/templates/app/base-plugin.html deleted file mode 100644 index 1f1a851..0000000 --- a/sources/templates/app/base-plugin.html +++ /dev/null @@ -1,10 +0,0 @@ -
    - - - -
    -
    \ No newline at end of file diff --git a/sources/templates/app/key-value-list-plugin.html b/sources/templates/app/key-value-list-plugin.html deleted file mode 100644 index a5b312a..0000000 --- a/sources/templates/app/key-value-list-plugin.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - -
    - - - - - - - -
    {{ name }}{{ value }}
    - -
    - - -
    diff --git a/sources/templates/app/line-chart-plugin.html b/sources/templates/app/line-chart-plugin.html deleted file mode 100644 index 8849bc1..0000000 --- a/sources/templates/app/line-chart-plugin.html +++ /dev/null @@ -1,20 +0,0 @@ -
    - - - -
    - - - - - - - - - - -
    {{ metric.name }}{{ metric.data }}
    - -
    - - \ No newline at end of file diff --git a/sources/templates/app/loading.html b/sources/templates/app/loading.html deleted file mode 100644 index e6aeacd..0000000 --- a/sources/templates/app/loading.html +++ /dev/null @@ -1,4 +0,0 @@ -
    - - Loading... -
    diff --git a/sources/templates/app/multi-line-chart-plugin.html b/sources/templates/app/multi-line-chart-plugin.html deleted file mode 100644 index 42d9ef2..0000000 --- a/sources/templates/app/multi-line-chart-plugin.html +++ /dev/null @@ -1,26 +0,0 @@ -
    - - -
    - - - - - - - - - - - -
    -
    -
    -
    {{ metric.name }}{{ metric.data }}
    - - -
    - - \ No newline at end of file diff --git a/sources/templates/app/navbar.html b/sources/templates/app/navbar.html deleted file mode 100644 index b1d115b..0000000 --- a/sources/templates/app/navbar.html +++ /dev/null @@ -1,8 +0,0 @@ -
    - diff --git a/sources/templates/app/progress-bar-plugin.html b/sources/templates/app/progress-bar-plugin.html deleted file mode 100644 index 85867ef..0000000 --- a/sources/templates/app/progress-bar-plugin.html +++ /dev/null @@ -1,5 +0,0 @@ -
    -
    -
    -
    -
    \ No newline at end of file diff --git a/sources/templates/app/table-data-plugin.html b/sources/templates/app/table-data-plugin.html deleted file mode 100644 index 0b7d532..0000000 --- a/sources/templates/app/table-data-plugin.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - -
    - - - - - - - - - - - - - - - -
    - -
    - {{ header }} - - {{ (header === sortByColumn && !sortReverse) ? '▲': ''; }} - {{ (header === sortByColumn && sortReverse) ? '▼': ''; }} - -
    - {{ row[header] }} -
    - -
    - - -
    diff --git a/sources/templates/app/theme-switcher.html b/sources/templates/app/theme-switcher.html deleted file mode 100644 index 36ff802..0000000 --- a/sources/templates/app/theme-switcher.html +++ /dev/null @@ -1,12 +0,0 @@ -
    - -
    - -
    - {{ theme.name }} -
    - -
    \ No newline at end of file diff --git a/sources/templates/app/ui-elements/last-update.html b/sources/templates/app/ui-elements/last-update.html deleted file mode 100644 index d8d25cc..0000000 --- a/sources/templates/app/ui-elements/last-update.html +++ /dev/null @@ -1,4 +0,0 @@ -Loading... - - {{ timestamp | date:'hh:mm:ss a' }} - \ No newline at end of file diff --git a/sources/templates/app/ui-elements/top-bar.html b/sources/templates/app/ui-elements/top-bar.html deleted file mode 100644 index 88b5d1d..0000000 --- a/sources/templates/app/ui-elements/top-bar.html +++ /dev/null @@ -1,10 +0,0 @@ -
    - - - {{ heading }} - - {{ info }} - - - -
    \ No newline at end of file diff --git a/sources/templates/modules/cpu-load.html b/sources/templates/modules/cpu-load.html deleted file mode 100644 index e59abbc..0000000 --- a/sources/templates/modules/cpu-load.html +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/sources/templates/modules/cpu-utilization-chart.html b/sources/templates/modules/cpu-utilization-chart.html deleted file mode 100644 index 323976c..0000000 --- a/sources/templates/modules/cpu-utilization-chart.html +++ /dev/null @@ -1,14 +0,0 @@ - - - diff --git a/sources/templates/modules/disk-space.html b/sources/templates/modules/disk-space.html deleted file mode 100644 index 447c739..0000000 --- a/sources/templates/modules/disk-space.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - -
    NameStatsUsedMount Path
    {{partition['file_system']}} - - - - {{ partition['used'] }} / {{ partition['size'] }} - - {{ partition['used%'] }} - {{ partition['mounted'] }}
    - -
    diff --git a/sources/templates/modules/download-transfer-rate.html b/sources/templates/modules/download-transfer-rate.html deleted file mode 100644 index 32fe674..0000000 --- a/sources/templates/modules/download-transfer-rate.html +++ /dev/null @@ -1,5 +0,0 @@ - - diff --git a/sources/templates/modules/ram-chart.html b/sources/templates/modules/ram-chart.html deleted file mode 100644 index 27a00d9..0000000 --- a/sources/templates/modules/ram-chart.html +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/sources/templates/modules/upload-transfer-rate.html b/sources/templates/modules/upload-transfer-rate.html deleted file mode 100644 index 63f267e..0000000 --- a/sources/templates/modules/upload-transfer-rate.html +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/sources/templates/ping-speeds.html b/sources/templates/ping-speeds.html deleted file mode 100644 index df5a9b8..0000000 --- a/sources/templates/ping-speeds.html +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/sources/templates/sections/accounts.html b/sources/templates/sections/accounts.html deleted file mode 100644 index a3a7a33..0000000 --- a/sources/templates/sections/accounts.html +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/sources/templates/sections/applications.html b/sources/templates/sections/applications.html deleted file mode 100644 index 3958e63..0000000 --- a/sources/templates/sections/applications.html +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/sources/templates/sections/basic-info.html b/sources/templates/sections/basic-info.html deleted file mode 100644 index 9c8c7de..0000000 --- a/sources/templates/sections/basic-info.html +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/sources/templates/sections/network.html b/sources/templates/sections/network.html deleted file mode 100644 index e7fbe5f..0000000 --- a/sources/templates/sections/network.html +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/sources/templates/sections/system-status.html b/sources/templates/sections/system-status.html deleted file mode 100644 index cfc03b3..0000000 --- a/sources/templates/sections/system-status.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - From 00ddd5972fc5ea6d618119ca544c8fee425514ed Mon Sep 17 00:00:00 2001 From: yalh76 Date: Fri, 25 Mar 2022 01:09:30 +0100 Subject: [PATCH 2/3] Apply example_ynh --- .github/ISSUE_TEMPLATE.md | 55 ++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 16 ++++ check_process | 26 ++----- conf/app.src | 7 +- conf/app.src.2.0 | 6 -- conf/nginx.conf | 14 ++-- conf/supervisor.conf | 7 +- doc/.gitkeep | 0 doc/DESCRIPTION.md | 1 + doc/DISCLAIMER.md | 0 doc/screenshots/.gitkeep | 0 manifest.json | 26 +++---- scripts/_common.sh | 29 +++++--- scripts/backup | 32 ++++---- scripts/change_url | 113 ++++++++++++++++++++++++++++ scripts/install | 123 +++++++++++++++---------------- scripts/remove | 52 ++++++------- scripts/restore | 60 ++++++++------- scripts/upgrade | 114 +++++++++++++--------------- 19 files changed, 422 insertions(+), 259 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE.md create mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 conf/app.src.2.0 create mode 100644 doc/.gitkeep create mode 100644 doc/DESCRIPTION.md create mode 100644 doc/DISCLAIMER.md create mode 100644 doc/screenshots/.gitkeep create mode 100644 scripts/change_url diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..2729a6b --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -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.* diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..ef70e18 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -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) diff --git a/check_process b/check_process index c315f0d..32cab1f 100644 --- a/check_process +++ b/check_process @@ -1,8 +1,8 @@ ;; Test complet ; Manifest - domain="domain.tld" (DOMAIN) - path="/path" (PATH) - user="john" (USER) + domain="domain.tld" + path="/path" + admin="john" ; Checks pkg_linter=1 setup_sub_dir=1 @@ -11,23 +11,11 @@ setup_private=0 setup_public=0 upgrade=1 + #upgrade=1 from_commit=CommitHash backup_restore=1 - multi_instance=0 - incorrect_path=1 - port_already_use=1 (8081) - change_url=0 -;;; Levels - Level 1=auto - Level 2=auto - Level 3=auto -# Level 4: Not relevant - Level 4=na - Level 5=auto - Level 6=auto - Level 7=auto - Level 8=0 - Level 9=0 - Level 10=0 + multi_instance=1 + port_already_use=0 + change_url=1 ;;; Options Email= Notification=none diff --git a/conf/app.src b/conf/app.src index 0a7b75c..94f96d2 100644 --- a/conf/app.src +++ b/conf/app.src @@ -1,6 +1,7 @@ -SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/59d4787d3147e79a816a5c88ed8af482a0661e88.zip -SOURCE_SUM=9c3112c93bb20be8b719335b20bf161e11a8095ecf639baab6ea8c95ef289928 +SOURCE_URL=https://codeload.github.com/afaqurk/linux-dash/tar.gz/186a802ea76e8bfcab7e8e7ebc533b74f80306fc +SOURCE_SUM=506ae346f69b2002d4e3494d6aaa92104dbc8e50c8740acb2c49bc592a5939ce SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=zip +SOURCE_FORMAT=tar.gz SOURCE_IN_SUBDIR=true SOURCE_FILENAME= +SOURCE_EXTRACT=true diff --git a/conf/app.src.2.0 b/conf/app.src.2.0 deleted file mode 100644 index 136f8ad..0000000 --- a/conf/app.src.2.0 +++ /dev/null @@ -1,6 +0,0 @@ -SOURCE_URL=https://github.com/afaqurk/linux-dash/archive/2.0.tar.gz -SOURCE_SUM=f7342807ecadd22410614336378311a356e04a18569f64935ea67b9bc27ccd56 -SOURCE_SUM_PRG=sha256sum -SOURCE_FORMAT=tar.gz -SOURCE_IN_SUBDIR=true -SOURCE_FILENAME= diff --git a/conf/nginx.conf b/conf/nginx.conf index 3ad0143..3fe2238 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,14 +1,10 @@ #sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; location __PATH__/ { - if ($scheme = http) { - rewrite ^ https://$server_name$request_uri? permanent; - } + proxy_pass http://localhost:__PORT__/; + proxy_redirect off; + proxy_hide_header Content-Type; - proxy_pass http://localhost:__PORT__/; - proxy_set_header Host $host; - proxy_buffering off; - - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + # Include SSOWAT user panel. + #include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/supervisor.conf b/conf/supervisor.conf index 148e08d..a636eb5 100644 --- a/conf/supervisor.conf +++ b/conf/supervisor.conf @@ -1,7 +1,6 @@ [program:__APP__] -directory=__FINALPATH__/ -;command=python app/server/index.py (v2.0) -command=python python-server.py +directory=__FINALPATH__/app/server/ +command=python index.py --port __PORT__ autostart=true autorestart=true -user=__USER__ +user=__APP__ diff --git a/doc/.gitkeep b/doc/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/doc/DESCRIPTION.md b/doc/DESCRIPTION.md new file mode 100644 index 0000000..5ede381 --- /dev/null +++ b/doc/DESCRIPTION.md @@ -0,0 +1 @@ +A beautiful web dashboard for GNU/Linux which display CPU, RAM, memory, network and other usage. diff --git a/doc/DISCLAIMER.md b/doc/DISCLAIMER.md new file mode 100644 index 0000000..e69de29 diff --git a/doc/screenshots/.gitkeep b/doc/screenshots/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/manifest.json b/manifest.json index a8f2fd4..66667a3 100644 --- a/manifest.json +++ b/manifest.json @@ -8,6 +8,13 @@ }, "version": "2.0", "url": "https://github.com/afaqurk/linux-dash", + "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", @@ -15,35 +22,26 @@ "url": "https://moul.re" }, "requirements": { - "yunohost": ">= 2.7.2" + "yunohost": ">= 4.3.0" }, - "multi_instance": false, + "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", diff --git a/scripts/_common.sh b/scripts/_common.sh index 24bd7ba..ea2aadd 100644 --- a/scripts/_common.sh +++ b/scripts/_common.sh @@ -1,13 +1,20 @@ #!/bin/bash -# ============= FUTURE YUNOHOST HELPER ============= -# Delete a file checksum from the app settings -# -# $app should be defined when calling this helper -# -# usage: ynh_remove_file_checksum file -# | arg: file - The file for which the checksum will be deleted -ynh_delete_file_checksum () { - local checksum_setting_name=checksum_${1//[\/ ]/_} # Replace all '/' and ' ' by '_' - ynh_app_setting_delete $app $checksum_setting_name -} +#================================================= +# COMMON VARIABLES +#================================================= + +# dependencies used by the app +pkg_dependencies="supervisor" + +#================================================= +# PERSONAL HELPERS +#================================================= + +#================================================= +# EXPERIMENTAL HELPERS +#================================================= + +#================================================= +# FUTURE OFFICIAL HELPERS +#================================================= diff --git a/scripts/backup b/scripts/backup index d192288..b084c19 100755 --- a/scripts/backup +++ b/scripts/backup @@ -6,12 +6,8 @@ # IMPORT GENERIC HELPERS #================================================= -if [ ! -e _common.sh ]; then - # Get the _common.sh file if it's not in the current directory - cp ../settings/scripts/_common.sh ./_common.sh - chmod a+rx _common.sh -fi -source _common.sh +# 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 #================================================= @@ -24,30 +20,40 @@ 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 final_path) -domain=$(ynh_app_setting_get $app domain) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) #================================================= -# STANDARD BACKUP STEPS +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + #================================================= # BACKUP THE APP MAIN DIR #================================================= -ynh_backup "$final_path" +ynh_backup --src_path="$final_path" #================================================= # BACKUP THE NGINX CONFIGURATION #================================================= -ynh_backup "/etc/nginx/conf.d/$domain.d/$app.conf" +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" #================================================= # SPECIFIC BACKUP #================================================= -# BACKUP SUPERVISOR CONFIG +# BACKUP SUPERVISOR #================================================= -ynh_backup "/etc/supervisor/conf.d/$app.conf" +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)." diff --git a/scripts/change_url b/scripts/change_url new file mode 100644 index 0000000..be378cf --- /dev/null +++ b/scripts/change_url @@ -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" diff --git a/scripts/install b/scripts/install index 8b6be88..da884e5 100755 --- a/scripts/install +++ b/scripts/install @@ -22,120 +22,113 @@ ynh_abort_if_errors domain=$YNH_APP_ARG_DOMAIN path_url=$YNH_APP_ARG_PATH -user=$YNH_APP_ARG_USER +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..." final_path=/var/www/$app -test ! -e "$final_path" || ynh_die "This path already contains a folder" +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -# Normalize the url path syntax -path_url=$(ynh_normalize_url_path $path_url) - -# Check web path availability -ynh_webpath_available $domain $path_url # Register (book) web path -ynh_webpath_register $app $domain $path_url +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url #================================================= # STORE SETTINGS FROM MANIFEST #================================================= +ynh_script_progression --message="Storing installation settings..." -ynh_app_setting_set $app domain $domain -ynh_app_setting_set $app path $path_url -ynh_app_setting_set $app user $user +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 #================================================= # STANDARD MODIFICATIONS -#================================================= -# INSTALL DEPENDENCIES -#================================================= - -ynh_install_app_dependencies supervisor - -#================================================= -# DOWNLOAD, CHECK AND UNPACK SOURCE -#================================================= - -ynh_app_setting_set $app final_path $final_path -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source "$final_path" - #================================================= # FIND AND OPEN A PORT #================================================= +ynh_script_progression --message="Finding an available port..." -# Find a free port -port=$(ynh_find_port 8081) -# Open this port -yunohost firewall allow --no-upnp TCP $port 2>&1 -ynh_app_setting_set $app port $port - -# For v2.0 only -# ynh_replace_string "default=80" "default=$port" "$final_path/app/server/index.py" -ynh_replace_string "'localhost', 8081" "'localhost', $port" "$final_path/python-server.py" +# Find an available port +port=$(ynh_find_port --port=8095) +ynh_app_setting_set --app=$app --key=port --value=$port #================================================= -# NGINX CONFIGURATION +# INSTALL DEPENDENCIES #================================================= +ynh_script_progression --message="Installing dependencies..." -# Create a dedicated nginx config -if [ "$path_url" != "/" ] -then - ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf" -fi -ynh_add_nginx_config +ynh_install_app_dependencies $pkg_dependencies #================================================= # CREATE DEDICATED USER #================================================= +ynh_script_progression --message="Configuring system user..." # Create a system user -ynh_system_user_create $app +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 -#================================================= -# SET SUPERVISOR -#================================================= - -# Set as a service with supervisor -cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf -ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf" -ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf" -ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf" - -supervisorctl update -supervisorctl restart $app - #================================================= # 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 -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -# Set permissions to app files -chown -R root: $final_path - #================================================= # SETUP SSOWAT #================================================= +ynh_script_progression --message="Configuring permissions..." -# Restrict access to admin only -yunohost app addaccess --users=$user $app +# 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..." -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of $app completed" diff --git a/scripts/remove b/scripts/remove index 97e3c87..499b3c8 100755 --- a/scripts/remove +++ b/scripts/remove @@ -12,52 +12,45 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -port=$(ynh_app_setting_get $app port) -final_path=$(ynh_app_setting_get $app final_path) +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 "$final_path" +ynh_secure_remove --file="$final_path" #================================================= # REMOVE NGINX CONFIGURATION #================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." -# Remove the dedicated nginx config +# Remove the dedicated NGINX config ynh_remove_nginx_config -#================================================= -# CLOSE A PORT -#================================================= - -if yunohost firewall list | grep -q "\- $port$" -then - echo "Close port $port" - yunohost firewall disallow TCP $port 2>&1 -fi - -#================================================= -# SPECIFIC REMOVE -#================================================= -# REMOVE SUPERVISOR -#================================================= - -# Remove service -supervisorctl stop $app -ynh_secure_remove /etc/supervisor/conf.d/$app.conf - #================================================= # REMOVE DEPENDENCIES #================================================= +ynh_script_progression --message="Removing dependencies..." # Remove metapackage and its dependencies ynh_remove_app_dependencies @@ -67,6 +60,13 @@ ynh_remove_app_dependencies #================================================= # REMOVE DEDICATED USER #================================================= +ynh_script_progression --message="Removing the dedicated system user..." # Delete a system user -ynh_system_user_delete $app +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" diff --git a/scripts/restore b/scripts/restore index 0f7f62b..b5286da 100755 --- a/scripts/restore +++ b/scripts/restore @@ -6,12 +6,8 @@ # IMPORT GENERIC HELPERS #================================================= -if [ ! -e _common.sh ]; then - # Get the _common.sh file if it's not in the current directory - cp ../settings/scripts/_common.sh ./_common.sh - chmod a+rx _common.sh -fi -source _common.sh +# 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 #================================================= @@ -24,65 +20,66 @@ ynh_abort_if_errors #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -path_url=$(ynh_app_setting_get $app path) -final_path=$(ynh_app_setting_get $app final_path) +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..." -ynh_webpath_available $domain $path_url \ - || ynh_die "Path not available: ${domain}${path_url}" test ! -d $final_path \ - || ynh_die "There is already a directory: $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 "/etc/nginx/conf.d/$domain.d/$app.conf" - -#================================================= -# RESTORE THE APP MAIN DIR -#================================================= - -ynh_restore_file "$final_path" +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 $app +ynh_system_user_create --username=$app --home_dir="$final_path" #================================================= -# RESTORE USER RIGHTS +# RESTORE THE APP MAIN DIR #================================================= +ynh_script_progression --message="Restoring the app main directory..." -# Restore permissions on app files -chown -R root: $final_path +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 supervisor +ynh_install_app_dependencies $pkg_dependencies #================================================= -# RESTORE THE SUPERVISOR CONFIGURATION +# RESTORE SUPERVISOR #================================================= +ynh_script_progression --message="Restoring the supervisor configuration..." -ynh_restore_file "/etc/supervisor/conf.d/$app.conf" - +ynh_restore_file --origin_path="/etc/supervisor/conf.d/$app.conf" supervisorctl update supervisorctl restart $app @@ -91,5 +88,12 @@ supervisorctl restart $app #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading NGINX web server..." -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" diff --git a/scripts/upgrade b/scripts/upgrade index 33445c0..2c7d833 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -12,111 +12,103 @@ source /usr/share/yunohost/helpers #================================================= # LOAD SETTINGS #================================================= +ynh_script_progression --message="Loading installation settings..." app=$YNH_APP_INSTANCE_NAME -domain=$(ynh_app_setting_get $app domain) -path_url=$(ynh_app_setting_get $app path) -user=$(ynh_app_setting_get $app admin) -final_path=$(ynh_app_setting_get $app final_path) -port=$(ynh_app_setting_get $app port) +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) #================================================= -# ENSURE DOWNWARD COMPATIBILITY +# CHECK VERSION #================================================= +ynh_script_progression --message="Checking version..." -# If final_path doesn't exist, create it -if [ -z $final_path ]; then - final_path=/var/www/$app - ynh_app_setting_set $app final_path $final_path -fi +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 + # 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 THE PATH -#================================================= - -# Normalize the URL path syntax -path_url=$(ynh_normalize_url_path $path_url) - #================================================= # 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 #================================================= -# Download, check integrity, uncompress and patch the source from app.src -ynh_setup_source "$final_path" +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 -if [ "$path_url" != "/" ] -then - ynh_replace_string "^#sub_path_only" "" "../conf/nginx.conf" -fi +# Create a dedicated NGINX config ynh_add_nginx_config -#================================================= -# CREATE DEDICATED USER -#================================================= - -# Create a system user -ynh_system_user_create $app - #================================================= # SPECIFIC UPGRADE -#================================================= -# UPGRADE SUPERVISOR -#================================================= - -# Set as a service with supervisor -cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf -ynh_replace_string "__APP__" "$app" "/etc/supervisor/conf.d/$app.conf" -ynh_replace_string "__FINALPATH__" "$final_path" "/etc/supervisor/conf.d/$app.conf" -ynh_replace_string "__USER__" "$app" "/etc/supervisor/conf.d/$app.conf" - -supervisorctl update -supervisorctl restart $app - #================================================= # 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 -#================================================= -# SECURE FILES AND DIRECTORIES -#================================================= - -# Set right permissions for curl installation -chown -R root: $final_path - -#================================================= -# SETUP SSOWAT -#================================================= - -# Restrict access to admin only -yunohost app addaccess --users=$user $app - #================================================= # RELOAD NGINX #================================================= +ynh_script_progression --message="Reloading NGINX web server..." -systemctl reload nginx +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed" From 884ca63ce8982b1ccf705c3b35d9d4565d34f36d Mon Sep 17 00:00:00 2001 From: yunohost-bot Date: Fri, 25 Mar 2022 00:09:35 +0000 Subject: [PATCH 3/3] Auto-update README --- README.md | 48 ++++++++++++++++++++++++++++++++++++++---------- README_fr.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 README_fr.md diff --git a/README.md b/README.md index 2f5a8b8..c340dbb 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,44 @@ -# Linux-Dash package for YunoHost + + +# 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 \ No newline at end of file diff --git a/README_fr.md b/README_fr.md new file mode 100644 index 0000000..0c9a5d2 --- /dev/null +++ b/README_fr.md @@ -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 \ No newline at end of file