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/README.md b/README.md index 2f5a8b8..d90eeca 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~ynh2 + +**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..12439bb --- /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~ynh2 + +**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 diff --git a/check_process b/check_process new file mode 100644 index 0000000..32cab1f --- /dev/null +++ b/check_process @@ -0,0 +1,21 @@ +;; Test complet + ; Manifest + domain="domain.tld" + path="/path" + admin="john" + ; Checks + pkg_linter=1 + setup_sub_dir=1 + setup_root=1 + setup_nourl=0 + setup_private=0 + setup_public=0 + upgrade=1 + #upgrade=1 from_commit=CommitHash + backup_restore=1 + multi_instance=1 + port_already_use=0 + change_url=1 +;;; Options +Email= +Notification=none diff --git a/conf/app.src b/conf/app.src new file mode 100644 index 0000000..94f96d2 --- /dev/null +++ b/conf/app.src @@ -0,0 +1,7 @@ +SOURCE_URL=https://codeload.github.com/afaqurk/linux-dash/tar.gz/186a802ea76e8bfcab7e8e7ebc533b74f80306fc +SOURCE_SUM=506ae346f69b2002d4e3494d6aaa92104dbc8e50c8740acb2c49bc592a5939ce +SOURCE_SUM_PRG=sha256sum +SOURCE_FORMAT=tar.gz +SOURCE_IN_SUBDIR=true +SOURCE_FILENAME= +SOURCE_EXTRACT=true diff --git a/conf/nginx.conf b/conf/nginx.conf index beea8dd..3fe2238 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -1,9 +1,10 @@ -location YNH_WWW_PATH/ { - rewrite ^YNH_WWW_PATH$ YNH_WWW_PATH/ permanent; - proxy_pass http://localhost:8081/; - proxy_set_header Host $host; - proxy_buffering off; +#sub_path_only rewrite ^__PATH__$ __PATH__/ permanent; +location __PATH__/ { - # Include SSOWAT user panel. - include conf.d/yunohost_panel.conf.inc; + proxy_pass http://localhost:__PORT__/; + proxy_redirect off; + proxy_hide_header Content-Type; + + # Include SSOWAT user panel. + #include conf.d/yunohost_panel.conf.inc; } diff --git a/conf/supervisor.conf b/conf/supervisor.conf index 0c0655d..a636eb5 100644 --- a/conf/supervisor.conf +++ b/conf/supervisor.conf @@ -1,5 +1,6 @@ -[program:linuxdash] -directory=/var/www/linuxdash/ -command=python python-server.py +[program:__APP__] +directory=__FINALPATH__/app/server/ +command=python index.py --port __PORT__ autostart=true autorestart=true +user=__APP__ 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 733d4f0..6c2cd06 100644 --- a/manifest.json +++ b/manifest.json @@ -1,45 +1,48 @@ { "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~ynh2", "url": "https://github.com/afaqurk/linux-dash", - "license": "free", + "upstream": { + "license": "MIT", + "website": "https://github.com/afaqurk/linux-dash", + "demo": "https://afaqurk.github.io/linux-dash/", + "admindoc": "https://github.com/afaqurk/linux-dash/wiki", + "code": "https://github.com/afaqurk/linux-dash" + }, + "license": "MIT", "maintainer": { "name": "Moul", "email": "moul@moul.re", "url": "https://moul.re" }, - "multi_instance": "false", + "requirements": { + "yunohost": ">= 4.3.0" + }, + "multi_instance": true, "services": [ "nginx" ], "arguments": { - "install" : [ + "install": [ { "name": "domain", - "type": "domain", - "ask": { - "en": "Choose a domain name for Linux-Dash", - "fr": "Choisissez un nom de domaine pour Linux-Dash" - }, - "example": "domain.org" + "type": "domain" }, { "name": "path", - "type": "path", - "ask": { - "en": "Choose a path for Linux-Dash", - "fr": "Choisissez un chemin pour Linux-Dash" - }, + "type": "path", "example": "/dash", "default": "/dash" }, { - "name": "user", - "type": "user", + "name": "admin", + "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..ea2aadd --- /dev/null +++ b/scripts/_common.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +#================================================= +# 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 new file mode 100755 index 0000000..b084c19 --- /dev/null +++ b/scripts/backup @@ -0,0 +1,59 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_print_info --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +domain=$(ynh_app_setting_get --app=$app --key=domain) + +#================================================= +# DECLARE DATA AND CONF FILES TO BACKUP +#================================================= +ynh_print_info --message="Declaring files to be backed up..." + +#================================================= +# BACKUP THE APP MAIN DIR +#================================================= + +ynh_backup --src_path="$final_path" + +#================================================= +# BACKUP THE NGINX CONFIGURATION +#================================================= + +ynh_backup --src_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# SPECIFIC BACKUP +#================================================= +# BACKUP SUPERVISOR +#================================================= + +ynh_backup --src_path="/etc/supervisor/conf.d/$app.conf" + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_print_info --message="Backup script completed for $app. (YunoHost will then actually copy those files to the archive)." 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 7f6b41b..da884e5 100755 --- a/scripts/install +++ b/scripts/install @@ -1,48 +1,134 @@ #!/bin/bash -app=linuxdash +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Retrieve arguments -domain=$1 -path=$2 -user=$3 +source _common.sh +source /usr/share/yunohost/helpers -# Check domain/path availability -sudo yunohost app checkurl $domain$path -a $app -if [[ ! $? -eq 0 ]]; then - exit 1 -fi +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= -# Check port availability -sudo yunohost app checkport 8081 -if [[ ! $? -eq 0 ]]; then - exit 1 -fi +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# RETRIEVE ARGUMENTS FROM THE MANIFEST +#================================================= + +domain=$YNH_APP_ARG_DOMAIN +path_url=$YNH_APP_ARG_PATH +admin=$YNH_APP_ARG_ADMIN + +app=$YNH_APP_INSTANCE_NAME + +#================================================= +# CHECK IF THE APP CAN BE INSTALLED WITH THESE ARGS +#================================================= +ynh_script_progression --message="Validating installation parameters..." -# Copy files to the right place final_path=/var/www/$app -sudo mkdir -p $final_path -sudo cp -a ../sources/* $final_path +test ! -e "$final_path" || ynh_die --message="This path already contains a folder" -# Set permissions -sudo chown -R www-data: $final_path +# Register (book) web path +ynh_webpath_register --app=$app --domain=$domain --path_url=$path_url -# Set as a service with supervisor -sudo apt-get -y -qq install supervisor -sudo cp ../conf/supervisor.conf /etc/supervisor/conf.d/$app.conf -sudo supervisorctl update -sudo supervisorctl start $app +#================================================= +# STORE SETTINGS FROM MANIFEST +#================================================= +ynh_script_progression --message="Storing installation settings..." -# Modify Nginx configuration file and copy it to Nginx conf directory -sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf -nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf -sudo cp ../conf/nginx.conf $nginxconf -sudo chown root: $nginxconf -sudo chmod 600 $nginxconf +ynh_app_setting_set --app=$app --key=domain --value=$domain +ynh_app_setting_set --app=$app --key=path --value=$path_url +ynh_app_setting_set --app=$app --key=admin --value=$admin -# Only give one user access to this app -sudo yunohost app removeaccess $app -sudo yunohost app addaccess $app -u $user +#================================================= +# STANDARD MODIFICATIONS +#================================================= +# FIND AND OPEN A PORT +#================================================= +ynh_script_progression --message="Finding an available port..." -# Reload web server -sudo service nginx reload +# Find an available port +port=$(ynh_find_port --port=8095) +ynh_app_setting_set --app=$app --key=port --value=$port + +#================================================= +# INSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Installing dependencies..." + +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Configuring system user..." + +# Create a system user +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= +ynh_script_progression --message="Setting up source files..." + +ynh_app_setting_set --app=$app --key=final_path --value=$final_path +# Download, check integrity, uncompress and patch the source from app.src +ynh_setup_source --dest_dir="$final_path" + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Configuring NGINX web server..." + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# SPECIFIC SETUP +#================================================= +# REMOVE GOOGLE !!! +#================================================= + +sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html" + +#================================================= +# SETUP SUPERVISOR +#================================================= +ynh_script_progression --message="Configuring supervisor..." + +ynh_add_config --template="../conf/supervisor.conf" --destination="/etc/supervisor/conf.d/$app.conf" +supervisorctl update +supervisorctl restart $app + +#================================================= +# GENERIC FINALIZATION +#================================================= +# SETUP SSOWAT +#================================================= +ynh_script_progression --message="Configuring permissions..." + +# Only the admin can access the admin panel of the app (if the app has an admin panel) +ynh_permission_create --permission="admin" --url="/admin" --allowed=$admin + +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Installation of $app completed" diff --git a/scripts/remove b/scripts/remove index 6d28ede..499b3c8 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 -# Remove service -sudo supervisorctl stop $app -sudo rm -f /etc/supervisor/conf.d/$app.conf +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." -# Remove supervisor package -# Need to be manage with future manifest/moulinette Debian package management -# sudo apt-get -y -qq remove supervisor +app=$YNH_APP_INSTANCE_NAME -# Reload nginx configuration -sudo service nginx reload +domain=$(ynh_app_setting_get --app=$app --key=domain) +port=$(ynh_app_setting_get --app=$app --key=port) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +#================================================= +# STANDARD REMOVE +#================================================= +# REMOVE SUPERVISOR +#================================================= +ynh_script_progression --message="Removing supervisor configuration..." + +supervisorctl stop $app +ynh_secure_remove --file="/etc/supervisor/conf.d/$app.conf" +supervisorctl update + +#================================================= +# REMOVE APP MAIN DIR +#================================================= +ynh_script_progression --message="Removing app main directory..." + +# Remove the app directory securely +ynh_secure_remove --file="$final_path" + +#================================================= +# REMOVE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Removing NGINX web server configuration..." + +# Remove the dedicated NGINX config +ynh_remove_nginx_config + +#================================================= +# REMOVE DEPENDENCIES +#================================================= +ynh_script_progression --message="Removing dependencies..." + +# Remove metapackage and its dependencies +ynh_remove_app_dependencies + +#================================================= +# GENERIC FINALIZATION +#================================================= +# REMOVE DEDICATED USER +#================================================= +ynh_script_progression --message="Removing the dedicated system user..." + +# Delete a system user +ynh_system_user_delete --username=$app + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Removal of $app completed" diff --git a/scripts/restore b/scripts/restore new file mode 100755 index 0000000..b5286da --- /dev/null +++ b/scripts/restore @@ -0,0 +1,99 @@ +#!/bin/bash + +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= + +# Keep this path for calling _common.sh inside the execution's context of backup and restore scripts +source ../settings/scripts/_common.sh +source /usr/share/yunohost/helpers + +#================================================= +# MANAGE SCRIPT FAILURE +#================================================= + +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." + +app=$YNH_APP_INSTANCE_NAME + +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) + +#================================================= +# CHECK IF THE APP CAN BE RESTORED +#================================================= +ynh_script_progression --message="Validating restoration parameters..." + +test ! -d $final_path \ + || ynh_die --message="There is already a directory: $final_path " + +#================================================= +# STANDARD RESTORATION STEPS +#================================================= +# RESTORE THE NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Restoring the NGINX web server configuration..." + +ynh_restore_file --origin_path="/etc/nginx/conf.d/$domain.d/$app.conf" + +#================================================= +# RECREATE THE DEDICATED USER +#================================================= +ynh_script_progression --message="Recreating the dedicated system user..." + +# Create the dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# RESTORE THE APP MAIN DIR +#================================================= +ynh_script_progression --message="Restoring the app main directory..." + +ynh_restore_file --origin_path="$final_path" + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# SPECIFIC RESTORATION +#================================================= +# REINSTALL DEPENDENCIES +#================================================= +ynh_script_progression --message="Reinstalling dependencies..." + +# Define and install dependencies +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# RESTORE SUPERVISOR +#================================================= +ynh_script_progression --message="Restoring the supervisor configuration..." + +ynh_restore_file --origin_path="/etc/supervisor/conf.d/$app.conf" +supervisorctl update +supervisorctl restart $app + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Restoration completed for $app" diff --git a/scripts/upgrade b/scripts/upgrade index 90d4dca..f341038 100644 --- a/scripts/upgrade +++ b/scripts/upgrade @@ -1,30 +1,121 @@ #!/bin/bash -# Retrieve settings -app=linuxdash -domain=$(sudo yunohost app setting $app domain) -path=$(sudo yunohost app setting $app path) +#================================================= +# GENERIC START +#================================================= +# IMPORT GENERIC HELPERS +#================================================= -# Remove trailing "/" for next commands -path=${path%/} +source _common.sh +source /usr/share/yunohost/helpers -# Copy files to the right place -final_path=/var/www/$app -sudo mkdir -p $final_path -sudo cp -a ../sources/* $final_path +#================================================= +# LOAD SETTINGS +#================================================= +ynh_script_progression --message="Loading installation settings..." -# Set permissions -sudo chown -R www-data: $final_path +app=$YNH_APP_INSTANCE_NAME -# Modify Nginx configuration file and copy it to Nginx conf directory -sed -i "s@YNH_WWW_PATH@$path@g" ../conf/nginx.conf -nginxconf=/etc/nginx/conf.d/$domain.d/$app.conf -sudo cp ../conf/nginx.conf $nginxconf -sudo chown root: $nginxconf -sudo chmod 600 $nginxconf +domain=$(ynh_app_setting_get --app=$app --key=domain) +path_url=$(ynh_app_setting_get --app=$app --key=path) +admin=$(ynh_app_setting_get --app=$app --key=admin) +final_path=$(ynh_app_setting_get --app=$app --key=final_path) +port=$(ynh_app_setting_get --app=$app --key=port) -# Restart Linux-dash service -sudo supervisorctl restart $app +#================================================= +# CHECK VERSION +#================================================= +ynh_script_progression --message="Checking version..." -# Reload web server & sso -sudo service nginx reload +upgrade_type=$(ynh_check_app_version_changed) + +#================================================= +# BACKUP BEFORE UPGRADE THEN ACTIVE TRAP +#================================================= +ynh_script_progression --message="Backing up the app before upgrading (may take a while)..." + +# Backup the current version of the app +ynh_backup_before_upgrade +ynh_clean_setup () { + # Restore it if the upgrade fails + ynh_restore_upgradebackup +} +# Exit if an error occurs during the execution of the script +ynh_abort_if_errors + +#================================================= +# STANDARD UPGRADE STEPS +#================================================= +# ENSURE DOWNWARD COMPATIBILITY +#================================================= +ynh_script_progression --message="Ensuring downward compatibility..." +#================================================= +# CREATE DEDICATED USER +#================================================= +ynh_script_progression --message="Making sure dedicated system user exists..." + +# Create a dedicated user (if not existing) +ynh_system_user_create --username=$app --home_dir="$final_path" + +#================================================= +# DOWNLOAD, CHECK AND UNPACK SOURCE +#================================================= + +if [ "$upgrade_type" == "UPGRADE_APP" ] +then + ynh_script_progression --message="Upgrading source files..." + + # Download, check integrity, uncompress and patch the source from app.src + ynh_setup_source --dest_dir="$final_path" +fi + +chmod 750 "$final_path" +chmod -R o-rwx "$final_path" +chown -R $app:www-data "$final_path" + +#================================================= +# NGINX CONFIGURATION +#================================================= +ynh_script_progression --message="Upgrading NGINX web server configuration..." + +# Create a dedicated NGINX config +ynh_add_nginx_config + +#================================================= +# UPGRADE DEPENDENCIES +#================================================= +ynh_script_progression --message="Upgrading dependencies..." + +ynh_install_app_dependencies $pkg_dependencies + +#================================================= +# SPECIFIC UPGRADE +#================================================= +# REMOVE GOOGLE !!! +#================================================= + +sed --in-place "/googlecode\|googleapis/d" "$final_path/index.html" + +#================================================= +# SETUP SUPERVISOR +#================================================= +ynh_script_progression --message="Configuring supervisor..." + +ynh_add_config --template="../conf/supervisor.conf" --destination="/etc/supervisor/conf.d/$app.conf" +supervisorctl update +supervisorctl restart $app + +#================================================= +# GENERIC FINALIZATION +#================================================= +# RELOAD NGINX +#================================================= +ynh_script_progression --message="Reloading NGINX web server..." + +ynh_systemd_action --service_name=nginx --action=reload + +#================================================= +# END OF SCRIPT +#================================================= + +ynh_script_progression --message="Upgrade of $app completed" 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 cf41009..0000000 Binary files a/sources/favicon.ico and /dev/null differ diff --git a/sources/img/themes/congruent_pentagon.png b/sources/img/themes/congruent_pentagon.png deleted file mode 100644 index c712660..0000000 Binary files a/sources/img/themes/congruent_pentagon.png and /dev/null differ diff --git a/sources/img/themes/contemporary_china_2.png b/sources/img/themes/contemporary_china_2.png deleted file mode 100644 index 4bd667d..0000000 Binary files a/sources/img/themes/contemporary_china_2.png and /dev/null differ diff --git a/sources/img/themes/crossword.png b/sources/img/themes/crossword.png deleted file mode 100644 index 2f9f1ad..0000000 Binary files a/sources/img/themes/crossword.png and /dev/null differ diff --git a/sources/img/themes/food.png b/sources/img/themes/food.png deleted file mode 100644 index 14b6bbc..0000000 Binary files a/sources/img/themes/food.png and /dev/null differ diff --git a/sources/img/themes/skulls.png b/sources/img/themes/skulls.png deleted file mode 100644 index 93508ff..0000000 Binary files a/sources/img/themes/skulls.png and /dev/null differ 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 @@ - - - - - - -