Compare commits
175 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8fcf6227e | ||
|
|
310b6de2cc | ||
|
|
306535a2a6 | ||
|
|
5944b1b6f5 | ||
|
|
6de9e1d4bd | ||
|
|
4bf6ab9c8c | ||
|
|
1e93dfa35e | ||
|
|
7f2567264c | ||
|
|
d9a9246f1b | ||
|
|
aa8fb62f15 | ||
|
|
6d5eeb88d3 | ||
|
|
ea1d710209 | ||
|
|
032b787b66 | ||
|
|
7024cd22de | ||
|
|
b9b66d5af1 | ||
|
|
b73a0d6347 | ||
|
|
a0bc318ff9 | ||
|
|
642e8464cd | ||
|
|
63a9e55d4e | ||
|
|
a07c73155f | ||
|
|
efbc32d3ed | ||
|
|
83f50bd0d8 | ||
|
|
87cb0f50b5 | ||
|
|
73c779c238 | ||
|
|
40615cf17a | ||
|
|
6dd1448667 | ||
|
|
d8b4091043 | ||
|
|
7ea920efa9 | ||
|
|
7306dfbdd3 | ||
|
|
53c8c41133 | ||
|
|
395dfe5fe7 | ||
|
|
2ec0074a45 | ||
|
|
93dce378ea | ||
|
|
df6fae7aa5 | ||
|
|
57e0705e64 | ||
|
|
f3b31479c4 | ||
|
|
b914be9f0e | ||
|
|
2d0a4b79d8 | ||
|
|
d090b29c55 | ||
|
|
5a8be94cdc | ||
|
|
176a436ad4 | ||
|
|
1a05435691 | ||
|
|
49ce3edbdb | ||
|
|
51df759e25 | ||
|
|
992aa00c3c | ||
|
|
d87d933058 | ||
|
|
e0d639cba0 | ||
|
|
1cbbfb25cc | ||
|
|
f205e6f5c1 | ||
|
|
5e67ea22f5 | ||
|
|
99f522e625 | ||
|
|
f04cd7e28b | ||
|
|
3392a1f17c | ||
|
|
d0d9a1a65d | ||
|
|
16d04fe485 | ||
|
|
43d5c51e7c | ||
|
|
647013f3ff | ||
|
|
2ef631a440 | ||
|
|
86315a245b | ||
|
|
b0ce1b87a9 | ||
|
|
541c16aea6 | ||
|
|
ee1a3fc683 | ||
|
|
b90edcccbd | ||
|
|
4614b93780 | ||
|
|
4f548803cb | ||
|
|
d16dd95d65 | ||
|
|
97f7494c34 | ||
|
|
6179dabfa6 | ||
|
|
05ca683f91 | ||
|
|
170e61e73f | ||
|
|
33f0356ca7 | ||
|
|
4b9117dcb4 | ||
|
|
ec274c90da | ||
|
|
e7a1f013df | ||
|
|
c287bc2f22 | ||
|
|
5b8f8f2c5d | ||
|
|
887c2d0f42 | ||
|
|
06d7aa6623 | ||
|
|
5ed142a6b8 | ||
|
|
da9ca8a1f4 | ||
|
|
1cb5375a92 | ||
|
|
fd11cc30f5 | ||
|
|
a1bfdc0f18 | ||
|
|
e88362ce80 | ||
|
|
b5f0a64e7c | ||
|
|
e3623420b0 | ||
|
|
3344ed4b99 | ||
|
|
b0c91f7804 | ||
|
|
f8cf7f0717 | ||
|
|
29a6b78f27 | ||
|
|
388370b49d | ||
|
|
4d67c25e5a | ||
|
|
eec0dcca82 | ||
|
|
f1dc33761d | ||
|
|
7ea74d0fe3 | ||
|
|
0c635534a1 | ||
|
|
f70a3a4207 | ||
|
|
0fc174b5b3 | ||
|
|
d4eddf042d | ||
|
|
a4210c7e6b | ||
|
|
106438d61d | ||
|
|
94365d2cc9 | ||
|
|
b633c43078 | ||
|
|
84c3f1d786 | ||
|
|
1c963e9aff | ||
|
|
a2fe7f79cc | ||
|
|
8dabdb3f11 | ||
|
|
b9f2957104 | ||
|
|
bdeda87600 | ||
|
|
e98a538f53 | ||
|
|
2e0cb923db | ||
|
|
2e532abf6b | ||
|
|
51e865c98d | ||
|
|
2c27248aa1 | ||
|
|
43c2084e15 | ||
|
|
14cb0f46f3 | ||
|
|
162d507468 | ||
|
|
8624851cf5 | ||
|
|
2d92e93b7b | ||
|
|
78f9018083 | ||
|
|
ecb8a01aaa | ||
|
|
cca2c99f6b | ||
|
|
028d0dd7d8 | ||
|
|
7753e0481c | ||
|
|
5b35e68cf2 | ||
|
|
8b4115fe48 | ||
|
|
8bc1c3e0ed | ||
|
|
69061ed537 | ||
|
|
f151b1268d | ||
|
|
35d9c0e548 | ||
|
|
7baae289d1 | ||
|
|
a33c50361f | ||
|
|
ecc4920b04 | ||
|
|
1f3e28fe83 | ||
|
|
a9132d7b46 | ||
|
|
f54929c6cb | ||
|
|
1a181d08b9 | ||
|
|
94b32f0f73 | ||
|
|
ab98382984 | ||
|
|
5498035ca9 | ||
|
|
a1444659ea | ||
|
|
b9d65ea0e2 | ||
|
|
aac35294b5 | ||
|
|
fef33d652d | ||
|
|
8ef6f420e4 | ||
|
|
7675ebc7d3 | ||
|
|
90e4b36106 | ||
|
|
e7ac2321f2 | ||
|
|
e0d8ade2d0 | ||
|
|
f5546b6a49 | ||
|
|
3c13f82d61 | ||
|
|
121b5cdf32 | ||
|
|
593c03b035 | ||
|
|
3a4e3fa22a | ||
|
|
098b87d09e | ||
|
|
8783b89f21 | ||
|
|
a29d0a6cf6 | ||
|
|
4d0d62a00b | ||
|
|
d951e26fa8 | ||
|
|
52e2c2ccd2 | ||
|
|
87cb5a5c24 | ||
|
|
59967dd1f0 | ||
|
|
46e57af6dd | ||
|
|
9ec69d895c | ||
|
|
c20b239351 | ||
|
|
09d9491354 | ||
|
|
68bc03d6a5 | ||
|
|
95e6b1a59c | ||
|
|
b2fb0b2130 | ||
|
|
b5e90f63a3 | ||
|
|
566a5904a6 | ||
|
|
7678a1a88b | ||
|
|
8490540384 | ||
|
|
2aabae6faa | ||
|
|
d9c841842e |
0
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file → Executable file
0
.github/ISSUE_TEMPLATE/i-have-an-issue.md
vendored
Normal file → Executable file
114
.github/workflows/docker.yml
vendored
@@ -1,114 +0,0 @@
|
||||
---
|
||||
name: docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags:
|
||||
- '*.*.*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.head_commit.message, 'PUSHPROD')
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Set up dynamic build ARGs
|
||||
id: getargs
|
||||
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
jokobsk/pi.alert
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
docker_dev:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.head_commit.message, 'PUSHPROD') != 'True'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Set up dynamic build ARGs
|
||||
id: getargs
|
||||
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
jokobsk/pi.alert_dev
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
64
.github/workflows/docker_dev.yml
vendored
Executable file
@@ -0,0 +1,64 @@
|
||||
---
|
||||
name: docker
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
tags:
|
||||
- '*.*.*'
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
docker_dev:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.head_commit.message, 'PUSHPROD') != 'True'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Set up dynamic build ARGs
|
||||
id: getargs
|
||||
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
jokobsk/pi.alert_dev
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=latest
|
||||
type=schedule
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
type=sha
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
63
.github/workflows/docker_prod.yml
vendored
Executable file
@@ -0,0 +1,63 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
|
||||
# GitHub recommends pinning actions to a commit SHA.
|
||||
# To get a newer version, you will need to update the SHA.
|
||||
# You can also reference a tag or branch, but the action may change without warning.
|
||||
|
||||
name: Publish Docker image
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
tags:
|
||||
- '*.*.*'
|
||||
jobs:
|
||||
docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Set up dynamic build ARGs
|
||||
id: getargs
|
||||
run: echo "version=$(cat ./stable/VERSION)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
# list of Docker images to use as base name for tags
|
||||
images: |
|
||||
jokobsk/pi.alert
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=semver,pattern={{version}},value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}}.{{minor}},value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}},value=${{ inputs.version }}
|
||||
type=ref,event=branch,suffix=-{{ sha }}
|
||||
type=ref,event=pr
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }}
|
||||
- name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
4
.gitignore
vendored
@@ -1,4 +1,8 @@
|
||||
.vscode
|
||||
.DS_Store
|
||||
config/pialert.conf
|
||||
db/*
|
||||
front/log/*
|
||||
front/plugins/**/*.log
|
||||
**/%40eaDir/
|
||||
**/@eaDir/
|
||||
|
||||
0
CONTRIBUTING
Normal file → Executable file
@@ -8,8 +8,7 @@ ENV USER=pi USER_ID=1000 USER_GID=1000 TZ=Europe/London PORT=20211
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install --no-install-recommends tini ca-certificates curl libwww-perl arp-scan perl apt-utils cron sudo nginx-light php php-cgi php-fpm php-sqlite3 php-curl sqlite3 dnsutils net-tools python3 iproute2 nmap python3-pip zip -y \
|
||||
&& pip3 install requests paho-mqtt scapy cron-converter pytz \
|
||||
# && pip3 install requests paho-mqtt ssdpy upnpclient \
|
||||
&& pip3 install requests paho-mqtt scapy cron-converter pytz json2table dhcp-leases pyunifi \
|
||||
&& update-alternatives --install /usr/bin/python python /usr/bin/python3 10 \
|
||||
&& apt-get clean autoclean \
|
||||
&& apt-get autoremove \
|
||||
@@ -40,7 +39,9 @@ RUN rm /etc/nginx/sites-available/default \
|
||||
# Create a backup of the pialert.conf to be used if the user didn't supply a configuration file
|
||||
&& cp /home/pi/pialert/config/pialert.conf /home/pi/pialert/back/pialert.conf_bak \
|
||||
# Create a backup of the pialert.db to be used if the user didn't supply a database
|
||||
&& cp /home/pi/pialert/db/pialert.db /home/pi/pialert/back/pialert.db_bak
|
||||
&& cp /home/pi/pialert/db/pialert.db /home/pi/pialert/back/pialert.db_bak \
|
||||
# Create a buildtimestamp.txt to later check if a new version was released
|
||||
&& date +%s > /home/pi/pialert/front/buildtimestamp.txt
|
||||
|
||||
ENTRYPOINT ["tini", "--"]
|
||||
|
||||
|
||||
0
FUNDING.yml
Normal file → Executable file
98
README.md
@@ -7,15 +7,14 @@ Scans for devices connected to your WIFI / LAN and alerts you if new and unknown
|
||||
|
||||
![Main screen][main]
|
||||
|
||||
|
||||
# 🐳 Docker image
|
||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker.yml)
|
||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
|
||||
[](https://github.com/jokob-sk/Pi.Alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
|
||||
🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) | 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md) | 🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/issues/138)
|
||||
🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) | 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) | 🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/releases)
|
||||
|
||||
## 🔍 Scan Methods
|
||||
The system continuously scans the network for, **New devices**, **New connections** (re-connections), **Disconnections**, **"Always Connected" devices down**, Devices **IP changes** and **Internet IP address changes**. Scanning methods are:
|
||||
@@ -30,67 +29,53 @@ The system continuously scans the network for, **New devices**, **New connection
|
||||
examines the DHCP leases (addresses assigned) to find active devices
|
||||
that were not discovered by the other methods.
|
||||
|
||||
|
||||
## 🧩 Notification Integrations
|
||||
## 🧩 Integrations
|
||||
- [Apprise](https://hub.docker.com/r/caronc/apprise), [Pushsafer](https://www.pushsafer.com/), [NTFY](https://ntfy.sh/)
|
||||
- Webhooks ([sample JSON](docs/webhook_json_sample.json))
|
||||
- Home Assistant via [MQTT](https://www.home-assistant.io/integrations/mqtt/)
|
||||
- discovery ~10s per device, deleting not supported, use [MQTT Explorer](https://mqtt-explorer.com/) for now
|
||||
|
||||
|
||||
## 🔐 Security
|
||||
|
||||
- Configurable login to prevent unauthorized use.
|
||||
|
||||
## 📑 Features
|
||||
- Display:
|
||||
- Sessions, Connected devices, Favorites, Events, Presence, Concurrent devices, Down alerts, IP's
|
||||
- Manual Nmap scans, Optional speedtest for Device "Internet"
|
||||
- Simple Network relationship display
|
||||
- Maintenance tasks and Settings like:
|
||||
- Status Infos (active scans, database size, backup counter)
|
||||
- Theme Selection (blue, red, green, yellow, black, purple) and Light/Dark-Mode Switch
|
||||
- Language Selection (English, German, Spanish)
|
||||
- Pause arp-scan
|
||||
- DB maintenance, Backup, Restore tools and CSV Export / Import
|
||||
- Help/FAQ Section
|
||||
|
||||
| ![Screen 1][screen1] | ![Screen 2][screen2] |
|
||||
|----------------------|----------------------|
|
||||
| ![Screen 3][screen3] | ![Screen 4][screen4] |
|
||||
| ![Screen 5][screen5] | ![Screen 6][screen6] |
|
||||
| ![Report 1][report1] | ![Report 2][report2] |
|
||||
|
||||
- [Webhooks](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md) ([sample JSON](docs/webhook_json_sample.json))
|
||||
- Home Assistant via [MQTT](https://www.home-assistant.io/integrations/mqtt/) - discovery ~10s per device, use [MQTT Explorer](https://mqtt-explorer.com/) to delete devices
|
||||
- [API endpoint](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md)
|
||||
- [Plugin system](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins) for custom script monitoring
|
||||
|
||||
# 📥 Installation
|
||||
<!--- --------------------------------------------------------------------- --->
|
||||
|
||||
⚠ This [fork (jokob-sk)](https://github.com/jokob-sk/Pi.Alert) is only tested as a [docker container](dockerfiles/README.md). Check out [leiweibau's fork](https://github.com/leiweibau/Pi.Alert/) if you want to install Pi.Alert on the server directly.
|
||||
⚠ Only tested as a [docker container - follow these instructions here](dockerfiles/README.md).
|
||||
> Check out [leiweibau's fork](https://github.com/leiweibau/Pi.Alert/) if you want to install Pi.Alert on the server directly or original instructions for [pucherot's original code](https://github.com/pucherot/Pi.Alert/)
|
||||
|
||||
Instructions for [pucherot's original code can be found here](https://github.com/pucherot/Pi.Alert/)
|
||||
# 📑 Features
|
||||
- Display:
|
||||
- Sessions, Connected devices, Favorites, Events, Presence, Concurrent devices, Down alerts, IP's
|
||||
- Manual Nmap scans, Optional speedtest for Device "Internet"
|
||||
- Simple Network relationship display
|
||||
- Maintenance tasks and Settings like:
|
||||
- Theme Selection (blue, red, green, yellow, black, purple) and Light/Dark-Mode Switch
|
||||
- DB maintenance, Backup, Restore tools and CSV Export / Import
|
||||
- Simple login Support
|
||||
- 🌟(Experimental) [Plugin system](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins)
|
||||
- Create custom plugins with automatically generated settings and UI.
|
||||
- Monitor anything for changes
|
||||
- Check the instructions carefully if you are up for a challenge! Current plugins include:
|
||||
- Detecting Rogue DHCP servers
|
||||
- Monitoring HTTP status changes of domains/URLs
|
||||
- Import devices from DHCP.leases files or a UniFi controller
|
||||
|
||||
| ![Screen 1][screen1] | ![Screen 2][screen2] | ![Screen 5][screen5] |
|
||||
|----------------------|----------------------| ----------------------|
|
||||
| ![Screen 3][screen3] | ![Screen 4][screen4] | ![Screen 6][screen6] |
|
||||
| ![Screen 8][screen8] | ![Report 2][report2] | ![Screen 9][screen9] |
|
||||
|
||||
|
||||
## 🔗 Other
|
||||
|
||||
|
||||
<!--- --------------------------------------------------------------------- --->
|
||||
|
||||
<!--- --------------------------------------------------------------------- --->
|
||||
### Alternatives
|
||||
### 🔗 Other Alternatives
|
||||
|
||||
- [WatchYourLAN](https://github.com/aceberg/WatchYourLAN) - Lightweight network IP scanner with web GUI (Open source)
|
||||
- [Fing](https://www.fing.com/) - Network scanner app for your Internet security (Commercial, Phone App, Proprietary hardware)
|
||||
|
||||
### Old docs
|
||||
|
||||
- [Device Management instructions](docs/DEVICE_MANAGEMENT.md)
|
||||
- [Versions History](docs/VERSIONS_HISTORY.md)
|
||||
Device Management [instructions](docs/DEVICE_MANAGEMENT.md) | Old Versions [History](docs/VERSIONS_HISTORY.md)
|
||||
|
||||
### License
|
||||
GPL 3.0
|
||||
- [Read more here](LICENSE.txt)
|
||||
- Source of the [animated GIF (Loading Animation)](https://commons.wikimedia.org/wiki/File:Loading_Animation.gif)
|
||||
- Source of the [selfhosted Fonts](https://github.com/adobe-fonts/source-sans)
|
||||
GPL 3.0 | [Read more here](LICENSE.txt) | Source of the [animated GIF (Loading Animation)](https://commons.wikimedia.org/wiki/File:Loading_Animation.gif) | Source of the [selfhosted Fonts](https://github.com/adobe-fonts/source-sans)
|
||||
|
||||
### 🥇 Special thanks
|
||||
|
||||
@@ -100,9 +85,16 @@ Instructions for [pucherot's original code can be found here](https://github.com
|
||||
- [leiweibau](https://github.com/leiweibau/Pi.Alert): Dark mode (and much more)
|
||||
- [Macleykun](https://github.com/Macleykun): Help with Dockerfile clean-up
|
||||
- [Final-Hawk](https://github.com/Final-Hawk): Help with NTFY, styling and other fixes
|
||||
- [TeroRERO](https://github.com/terorero): Spanish translation
|
||||
- [jokob-sk](https://github.com/jokob-sk/Pi.Alert): DB Maintenance tools
|
||||
- Please see the [Git commit history](https://github.com/jokob-sk/Pi.Alert/commits/main) for a full list of people and their contributions to the project
|
||||
- [TeroRERO](https://github.com/terorero): Spanish translation
|
||||
- Please see the [Git contributors](https://github.com/jokob-sk/Pi.Alert/graphs/contributors) for a full list of people and their contributions to the project
|
||||
|
||||
## ☕ Support me
|
||||
|
||||
<a href="https://github.com/sponsors/jokob-sk" target="_blank"><img src="https://i.imgur.com/X6p5ACK.png" alt="Sponsor Me on GitHub" style="height: 30px !important;width: 117px !important;" width="150px" ></a>
|
||||
<a href="https://www.buymeacoffee.com/jokobsk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 117px !important;" width="117px" height="30px" ></a>
|
||||
<a href="https://www.patreon.com/user?u=84385063" target="_blank"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" alt="Support me on patreon" style="height: 30px !important;width: 117px !important;" width="117px" ></a>
|
||||
|
||||
BTC: 1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM
|
||||
|
||||
<!--- --------------------------------------------------------------------- --->
|
||||
[main]: ./docs/img/devices_split.png "Main screen"
|
||||
@@ -112,7 +104,9 @@ Instructions for [pucherot's original code can be found here](https://github.com
|
||||
[screen4]: ./docs/img/maintenance.png "Screen 4"
|
||||
[screen5]: ./docs/img/network.png "Screen 5"
|
||||
[screen6]: ./docs/img/settings.png "Screen 6"
|
||||
[screen7]: ./docs/img/help_faq.png "Screen 6"
|
||||
[screen7]: ./docs/img/help_faq.png "Screen 7"
|
||||
[screen8]: ./docs/img/plugins_webmon.png "Screen 8"
|
||||
[screen9]: ./docs/img/device_nmap.png "Screen 9"
|
||||
[report1]: ./docs/img/4_report_1.jpg "Report sample 1"
|
||||
[report2]: ./docs/img/4_report_2.jpg "Report sample 2"
|
||||
[main_dark]: /docs/img/1_devices_dark.jpg "Main screen dark"
|
||||
|
||||
2805
back/pialert.py
173
back/report_sample.html
Executable file
@@ -0,0 +1,173 @@
|
||||
<!-- ---------------------------------------------------------------------------
|
||||
# Pi.Alert
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
#
|
||||
# repot_template.html - Back module. Template to email reporting in HTML format
|
||||
#-------------------------------------------------------------------------------
|
||||
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
|
||||
#--------------------------------------------------------------------------- -->
|
||||
<html>
|
||||
<head></head>
|
||||
<body>
|
||||
<font face=sans-serif>
|
||||
<table align=center width=100% cellpadding=0 cellspacing=0 style="border-radius: 5px;">
|
||||
<tr>
|
||||
<td bgcolor=#EFB956 align=center style="padding: 20px 10px 10px 10px; font-size: 30px; font-weight: bold; color:#000000; border-top-right-radius: 5px; border-top-left-radius: 5px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
Pi.Alert Report
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor=#2656f1 width=100% align=center style="padding: 20px 10px 10px 10px; font-size: 20px; font-weight: bold; color:#ffffff; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<a style="color:#ffffff;cursor:pointer;" href="https://github.com/jokob-sk/Pi.Alert/releases">🆕 New version available 🆕</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#FFD966 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 15px; text-align:center; color:#404040">
|
||||
<tr>
|
||||
<td width=100%> Report Date: <b>2023-01-30 22:17</b> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor=#F5F5F5 height=200 valign=top style="padding: 10px">
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:blue; font-size: 12px;' bgcolor='#909090' >New devices</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >MAC</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Datetime</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >IP</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Event Type</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Device name</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Comments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://192.168.1.1:20211/deviceDetails.php?mac=00:00:00:ef:a5:6c">00:00:00:ef:a5:6c</a></td>
|
||||
<td>2023-01-30 22:15:09</td>
|
||||
<td>192.168.1.1</td>
|
||||
<td>New Device</td>
|
||||
<td>(name not found)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://192.168.1.1:20211/deviceDetails.php?mac=00:00:00:ef:a5:6c">00:00:00:ef:a5:6c</a></td>
|
||||
<td>2023-01-30 22:17:59</td>
|
||||
<td>192.168.1.82</td>
|
||||
<td>New Device</td>
|
||||
<td>(name not found)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:blue; font-size: 12px;' bgcolor='#909090' >Events</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<ul>
|
||||
<li>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >MAC</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Datetime</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >IP</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Event Type</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Device name</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Comments</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://192.168.1.1:20211/deviceDetails.php?mac=00:00:00:ef:a5:6c">00:00:00:ef:a5:6c</a></td>
|
||||
<td>2023-01-30 22:15:09</td>
|
||||
<td>192.168.1.92</td>
|
||||
<td>Disconnected</td>
|
||||
<td>(name not found)</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:blue; font-size: 12px;' bgcolor='#909090' >Changed or new ports</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th>new</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Name</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >MAC</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Port</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >State</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Service</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Extra</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New device</td>
|
||||
<td><a href="http://192.168.1.1:20211/deviceDetails.php?mac=00:00:00:ef:a5:6c">00:00:00:ef:a5:6c</a></td>
|
||||
<td>3263/tcp</td>
|
||||
<td>open</td>
|
||||
<td>ecolor-imager</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table style="border-collapse: collapse; font-size: 12px; color:#70707" width="100%" cellspacing="0" cellpadding="3px" bordercolor="#C0C0C0" border="1">
|
||||
<tr>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Name</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >MAC</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Port</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >State</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Service</th>
|
||||
<th width='120px' style='color:#F0F0F0' bgcolor='#909090' >Extra</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New device</td>
|
||||
<td><a href="http://192.168.1.1:20211/deviceDetails.php?mac=00:00:00:ef:a5:6c">00:00:00:ef:a5:6c</a></td>
|
||||
<td>3264/tcp</td>
|
||||
<td>open</td>
|
||||
<td>ccmail</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% bgcolor=#46802e cellpadding=5px cellspacing=0 style="font-size: 13px; font-weight: bold; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px;">
|
||||
<tr>
|
||||
<td width=50% style="text-align:center"> Pi.Alert - Synology-NAS</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
50
back/report_sample.txt
Executable file
@@ -0,0 +1,50 @@
|
||||
Report Date: 2021-12-08 12:30
|
||||
Server: Synology-NAS
|
||||
|
||||
New Devices
|
||||
----------------------
|
||||
Name: (name not found)
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.121
|
||||
Time: 2021-12-08 12:30
|
||||
More Info: Micro-Star INTL CO., LTD.
|
||||
|
||||
Name: (name not found)
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.151
|
||||
Time: 2021-12-08 12:30
|
||||
More Info: Espressif Inc.
|
||||
|
||||
|
||||
|
||||
Events
|
||||
----------------------
|
||||
Name: Samsung
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.27
|
||||
Time: 2021-12-08 12:30
|
||||
Event: Connected
|
||||
More Info:
|
||||
|
||||
Name: (name not found)
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.6
|
||||
Time: 2021-12-08 12:30
|
||||
Event: Disconnected
|
||||
More Info:
|
||||
|
||||
Name: Google-Home-Mini
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.16
|
||||
Time: 2021-12-08 12:30
|
||||
Event: Disconnected
|
||||
More Info:
|
||||
|
||||
Name: (name not found)
|
||||
MAC: 2c:2c:2c:2c:2c:2c
|
||||
IP: 192.168.1.119
|
||||
Time: 2021-12-08 12:30
|
||||
Event: Disconnected
|
||||
More Info:
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
Pi.Alert Report
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#FFD966 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 15px; text-align:center; color:#404040"> <tr>
|
||||
@@ -32,74 +32,13 @@
|
||||
|
||||
<tr>
|
||||
<td bgcolor=#F5F5F5 height=200 valign=top style="padding: 10px">
|
||||
<SECTION_INTERNET>
|
||||
<p style="font-size: 24px; font-weight: bold; color:#C04040"> Internet: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> Event Type </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th> Additional Info </th>
|
||||
</tr>
|
||||
|
||||
<TABLE_INTERNET>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
</SECTION_INTERNET>
|
||||
|
||||
<SECTION_NEW_DEVICES>
|
||||
<p style="font-size: 14px; font-weight: bold; color:#C04040"> New Devices: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=150> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th width=140> Device Name </th>
|
||||
<th> Vendor </th>
|
||||
</tr>
|
||||
|
||||
<TABLE_NEW_DEVICES>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
</SECTION_NEW_DEVICES>
|
||||
|
||||
<SECTION_DEVICES_DOWN>
|
||||
<p style="font-size: 14px; font-weight: bold; color:#C04040"> Devices Down: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th> Device Name </th>
|
||||
</tr>
|
||||
|
||||
<TABLE_DEVICES_DOWN>
|
||||
</table>
|
||||
|
||||
<br>
|
||||
</SECTION_DEVICES_DOWN>
|
||||
|
||||
<SECTION_EVENTS>
|
||||
<p style="font-size: 14px; font-weight: bold; color:#409040"> Events: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th width=100> Event Type </th>
|
||||
<th width=140> Device Name </th>
|
||||
<th> Additional Info </th>
|
||||
</tr>
|
||||
|
||||
<TABLE_EVENTS>
|
||||
</table>
|
||||
</SECTION_EVENTS>
|
||||
|
||||
<INTERNET_TABLE>
|
||||
<NEW_DEVICES_TABLE>
|
||||
<DOWN_DEVICES_TABLE>
|
||||
<EVENTS_TABLE>
|
||||
<PORTS_TABLE>
|
||||
<PLUGINS_TABLE>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
Report Date: <REPORT_DATE>
|
||||
Server: <SERVER_NAME>
|
||||
|
||||
<SECTION_NEW_DEVICES>
|
||||
New Devices
|
||||
----------------------
|
||||
<TABLE_NEW_DEVICES>
|
||||
</SECTION_NEW_DEVICES><SECTION_DEVICES_DOWN>
|
||||
Devices Down
|
||||
----------------------
|
||||
<TABLE_DEVICES_DOWN>
|
||||
</SECTION_DEVICES_DOWN><SECTION_EVENTS>
|
||||
Events
|
||||
----------------------
|
||||
<TABLE_EVENTS>
|
||||
</SECTION_EVENTS><SECTION_INTERNET>
|
||||
Internet
|
||||
----------------------
|
||||
<TABLE_INTERNET>
|
||||
</SECTION_INTERNET>
|
||||
<SECTION_DEVICES_DOWN>
|
||||
<SECTION_EVENTS>
|
||||
<SECTION_INTERNET>
|
||||
<PORTS_TABLE>
|
||||
<PLUGINS_TABLE>
|
||||
|
||||
61
back/report_template_new_version.html
Executable file
@@ -0,0 +1,61 @@
|
||||
<!-- ---------------------------------------------------------------------------
|
||||
# Pi.Alert
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
#
|
||||
# repot_template.html - Back module. Template to email reporting in HTML format
|
||||
#-------------------------------------------------------------------------------
|
||||
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
|
||||
#--------------------------------------------------------------------------- -->
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<font face=sans-serif>
|
||||
<table align=center width=100% cellpadding=0 cellspacing=0 style="border-radius: 5px;">
|
||||
<tr>
|
||||
<td bgcolor=#EFB956 align=center style="padding: 20px 10px 10px 10px; font-size: 30px; font-weight: bold; color:#000000; border-top-right-radius: 5px; border-top-left-radius: 5px; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
Pi.Alert Report
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td bgcolor=#2656f1 width=100% align=center style="padding: 20px 10px 10px 10px; font-size: 20px; font-weight: bold; color:#ffffff; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<a style="color:#ffffff;cursor:pointer;" href="https://github.com/jokob-sk/Pi.Alert/releases">🆕 New version available 🆕</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#FFD966 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 15px; text-align:center; color:#404040"> <tr>
|
||||
<td width=100%> Report Date: <b><REPORT_DATE></b> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td bgcolor=#F5F5F5 height=200 valign=top style="padding: 10px">
|
||||
|
||||
<INTERNET_TABLE>
|
||||
<NEW_DEVICES_TABLE>
|
||||
<DOWN_DEVICES_TABLE>
|
||||
<EVENTS_TABLE>
|
||||
<PORTS_TABLE>
|
||||
<PLUGINS_TABLE>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% bgcolor=#46802e cellpadding=5px cellspacing=0 style="font-size: 13px; font-weight: bold; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px;">
|
||||
<tr>
|
||||
<td width=50% style="text-align:center"> Pi.Alert - <SERVER_NAME></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -26,16 +26,16 @@ sudo cp *.csv 2_backup
|
||||
echo ""
|
||||
echo Download Start
|
||||
echo ""
|
||||
sudo curl $1 -O https://standards-oui.ieee.org/iab/iab.csv \
|
||||
-O https://standards-oui.ieee.org/iab/iab.txt \
|
||||
-O https://standards-oui.ieee.org/oui28/mam.csv \
|
||||
-O https://standards-oui.ieee.org/iab/iab.txt \
|
||||
-O https://standards-oui.ieee.org/oui28/mam.csv \
|
||||
-O https://standards-oui.ieee.org/oui28/mam.txt \
|
||||
-O https://standards-oui.ieee.org/oui36/oui36.csv \
|
||||
-O https://standards-oui.ieee.org/oui36/oui36.txt \
|
||||
-O https://standards-oui.ieee.org/oui/oui.csv \
|
||||
-O https://standards-oui.ieee.org/oui/oui.txt
|
||||
sudo curl $1 -LO https://standards-oui.ieee.org/iab/iab.csv \
|
||||
-LO https://standards-oui.ieee.org/iab/iab.txt \
|
||||
-LO https://standards-oui.ieee.org/oui28/mam.csv \
|
||||
-LO https://standards-oui.ieee.org/iab/iab.txt \
|
||||
-LO https://standards-oui.ieee.org/oui28/mam.csv \
|
||||
-LO https://standards-oui.ieee.org/oui28/mam.txt \
|
||||
-LO https://standards-oui.ieee.org/oui36/oui36.csv \
|
||||
-LO https://standards-oui.ieee.org/oui36/oui36.txt \
|
||||
-LO https://standards-oui.ieee.org/oui/oui.csv \
|
||||
-LO https://standards-oui.ieee.org/oui/oui.txt
|
||||
echo ""
|
||||
echo Download Finished
|
||||
|
||||
|
||||
87
back/webhook_json_sample.json
Executable file
@@ -0,0 +1,87 @@
|
||||
[
|
||||
{
|
||||
"headers": {
|
||||
"host": "192.168.1.82:5678",
|
||||
"user-agent": "curl/7.74.0",
|
||||
"accept": "*/*",
|
||||
"content-type": "application/json",
|
||||
"content-length": "872"
|
||||
},
|
||||
"params": {},
|
||||
"query": {},
|
||||
"body": {
|
||||
"username": "Pi.Alert",
|
||||
"text": "There are new notifications",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Pi.Alert Notifications",
|
||||
"title_link": "",
|
||||
"text": {
|
||||
"internet": [],
|
||||
"new_devices": [{
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Datetime": "2023-01-30 22:15:09",
|
||||
"IP": "192.168.1.1",
|
||||
"Event Type": "New Device",
|
||||
"Device name": "(name not found)",
|
||||
"Comments": null
|
||||
}],
|
||||
"down_devices": [],
|
||||
"events": [{
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Datetime": "2023-01-30 22:15:09",
|
||||
"IP": "192.168.1.92",
|
||||
"Event Type": "Disconnected",
|
||||
"Device name": "(name not found)",
|
||||
"Comments": null
|
||||
}, {
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Datetime": "2023-01-30 22:15:09",
|
||||
"IP": "192.168.1.150",
|
||||
"Event Type": "Disconnected",
|
||||
"Device name": "(name not found)",
|
||||
"Comments": null
|
||||
}],
|
||||
"ports": [{
|
||||
"new": {
|
||||
"Name": "New device",
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Port": "22/tcp",
|
||||
"State": "open",
|
||||
"Service": "ssh",
|
||||
"Extra": ""
|
||||
}
|
||||
}, {
|
||||
"new": {
|
||||
"Name": "New device",
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Port": "53/tcp",
|
||||
"State": "open",
|
||||
"Service": "domain",
|
||||
"Extra": ""
|
||||
}
|
||||
}, {
|
||||
"new": {
|
||||
"Name": "New device",
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Port": "80/tcp",
|
||||
"State": "open",
|
||||
"Service": "http",
|
||||
"Extra": ""
|
||||
}
|
||||
}, {
|
||||
"new": {
|
||||
"Name": "New device",
|
||||
"MAC": "74:ac:74:ac:74:ac",
|
||||
"Port": "443/tcp",
|
||||
"State": "open",
|
||||
"Service": "https",
|
||||
"Extra": ""
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -23,7 +23,8 @@ PIALERT_WEB_PASSWORD='8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923a
|
||||
INCLUDED_SECTIONS=['internet','new_devices','down_devices','events']
|
||||
SCAN_CYCLE_MINUTES=5
|
||||
DAYS_TO_KEEP_EVENTS=90
|
||||
REPORT_DASHBOARD_URL='http://pi.alert/'
|
||||
# Used for generating links in emails. Make sure not to add a trailing slash!
|
||||
REPORT_DASHBOARD_URL='http://pi.alert'
|
||||
|
||||
|
||||
# Email
|
||||
@@ -103,15 +104,15 @@ DHCP_ACTIVE=False
|
||||
# Pholus
|
||||
#---------------------------
|
||||
PHOLUS_ACTIVE=False
|
||||
PHOLUS_TIMEOUT=20
|
||||
PHOLUS_TIMEOUT=120
|
||||
PHOLUS_FORCE=False
|
||||
PHOLUS_DAYS_DATA=7
|
||||
PHOLUS_RUN='once'
|
||||
PHOLUS_RUN_TIMEOUT=300
|
||||
PHOLUS_RUN_TIMEOUT=600
|
||||
PHOLUS_RUN_SCHD='0 4 * * *'
|
||||
|
||||
|
||||
#-------------------IMPORTANT INFO-------------------#
|
||||
# This file is ingested by a python script, so if #
|
||||
# modified it needs to use python syntax #
|
||||
#-------------------IMPORTANT INFO-------------------#
|
||||
#-------------------IMPORTANT INFO-------------------#
|
||||
|
||||
@@ -1,36 +1,43 @@
|
||||
version: "3"
|
||||
services:
|
||||
pialert:
|
||||
privileged: true
|
||||
build: .
|
||||
container_name: pialert
|
||||
network_mode: "host"
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
|
||||
- ${APP_DATA_LOCATION}/pialert2/config:/home/pi/pialert/config
|
||||
# - ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
||||
- ${APP_DATA_LOCATION}/pialert/db:/home/pi/pialert/db
|
||||
# (optional) map an empty file with the name 'setting_darkmode' if you want to force the dark mode on container rebuilt
|
||||
- ${APP_DATA_LOCATION}/pialert/db/setting_darkmode:/home/pi/pialert/db/setting_darkmode
|
||||
- ${APP_DATA_LOCATION}/pialert2/db:/home/pi/pialert/db
|
||||
# (optional) useful for debugging if you have issues setting up the container
|
||||
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
||||
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
||||
# DELETE START anyone trying to use this file: comment out / delete BELOW lines, they are only for development purposes
|
||||
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp1.leases:/mnt/dhcp1.leases
|
||||
- ${APP_DATA_LOCATION}/pialert/dhcp_samples/dhcp2.leases:/mnt/dhcp2.leases
|
||||
- ${DEV_LOCATION}/back/pialert.py:/home/pi/pialert/back/pialert.py
|
||||
- ${DEV_LOCATION}/back/update_vendors.sh:/home/pi/pialert/back/update_vendors.sh
|
||||
- ${DEV_LOCATION}/back/report_template.html:/home/pi/pialert/back/report_template.html
|
||||
- ${DEV_LOCATION}/back/report_template_new_version.html:/home/pi/pialert/back/report_template_new_version.html
|
||||
- ${DEV_LOCATION}/back/report_template.txt:/home/pi/pialert/back/report_template.txt
|
||||
- ${DEV_LOCATION}/pholus:/home/pi/pialert/pholus
|
||||
- ${DEV_LOCATION}/dockerfiles:/home/pi/pialert/dockerfiles
|
||||
- ${APP_DATA_LOCATION}/pialert/php.ini:/etc/php/7.4/fpm/php.ini
|
||||
# - ${DEV_LOCATION}/front/api:/home/pi/pialert/front/api
|
||||
- ${DEV_LOCATION}/front/css:/home/pi/pialert/front/css
|
||||
- ${DEV_LOCATION}/front/lib/AdminLTE:/home/pi/pialert/front/lib/AdminLTE
|
||||
- ${DEV_LOCATION}/front/js:/home/pi/pialert/front/js
|
||||
- ${DEV_LOCATION}/front/php:/home/pi/pialert/front/php
|
||||
- ${DEV_LOCATION}/front/deviceDetails.php:/home/pi/pialert/front/deviceDetails.php
|
||||
- ${DEV_LOCATION}/front/devices.php:/home/pi/pialert/front/devices.php
|
||||
- ${DEV_LOCATION}/front/events.php:/home/pi/pialert/front/events.php
|
||||
- ${DEV_LOCATION}/front/plugins.php:/home/pi/pialert/front/plugins.php
|
||||
- ${DEV_LOCATION}/front/help_faq.php:/home/pi/pialert/front/help_faq.php
|
||||
- ${DEV_LOCATION}/front/index.php:/home/pi/pialert/front/index.php
|
||||
- ${DEV_LOCATION}/front/maintenance.php:/home/pi/pialert/front/maintenance.php
|
||||
- ${DEV_LOCATION}/front/network.php:/home/pi/pialert/front/network.php
|
||||
- ${DEV_LOCATION}/front/presence.php:/home/pi/pialert/front/presence.php
|
||||
- ${DEV_LOCATION}/front/settings.php:/home/pi/pialert/front/settings.php
|
||||
- ${DEV_LOCATION}/front/plugins:/home/pi/pialert/front/plugins
|
||||
# DELETE END anyone trying to use this file: comment out / delete ABOVE lines, they are only for development purposes
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker.yml)
|
||||
[](https://github.com/jokob-sk/Pi.Alert/actions/workflows/docker_prod.yml)
|
||||
[](https://github.com/jokob-sk/Pi.Alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
[](https://hub.docker.com/r/jokobsk/pi.alert)
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
# 🐳 A docker image for Pi.Alert
|
||||
|
||||
🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) | 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main//dockerfiles/README.md) | 🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/issues/138)
|
||||
🐳 [Docker hub](https://registry.hub.docker.com/r/jokobsk/pi.alert) | 📄 [Dockerfile](https://github.com/jokob-sk/Pi.Alert/blob/main/Dockerfile) | 📚 [Docker instructions](https://github.com/jokob-sk/Pi.Alert/blob/main/dockerfiles/README.md) | 🆕 [Release notes](https://github.com/jokob-sk/Pi.Alert/releases)
|
||||
|
||||
<a href="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" target="_blank">
|
||||
<img src="https://raw.githubusercontent.com/jokob-sk/Pi.Alert/main/docs/img/devices_split.png" width="300px" />
|
||||
@@ -45,21 +45,23 @@ docker run -d --rm --network=host \
|
||||
| :------------- | :------------- |:-------------|
|
||||
| **Required** | `:/home/pi/pialert/config` | Folder which will contain the `pialert.conf` file (see below for details) |
|
||||
| **Required** | `:/home/pi/pialert/db` | Folder which will contain the `pialert.db` file |
|
||||
|Optional| `:/home/pi/pialert/db/setting_darkmode` | Map an empty file with the name `setting_darkmode` if you want to force the dark mode on container rebuilt |
|
||||
|Optional| `:/home/pi/pialert/front/log` | Logs folder useful for debugging if you have issues setting up the container |
|
||||
|Optional| `:/etc/pihole/pihole-FTL.db` | PiHole's `pihole-FTL.db` database file. Required if you want to use PiHole |
|
||||
|Optional| `:/etc/pihole/dhcp.leases` | PiHole's `dhcp.leases` file. Required if you want to use PiHole |
|
||||
|Optional| `:/home/pi/pialert/front/api` | A simple [API endpoint](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/API.md) containing static (but regularly updated) json and other files. |
|
||||
|
||||
|
||||
### Config (`pialert.conf`)
|
||||
|
||||
- Modify [pialert.conf](https://github.com/jokob-sk/Pi.Alert/tree/main/config) or manage the configuration via Settings.
|
||||
- ❗ Set the `SCAN_SUBNETS` variable.
|
||||
- The preferred wy is to manage the configuration via Settings
|
||||
- YOu can modify [pialert.conf](https://github.com/jokob-sk/Pi.Alert/tree/main/config) directly if needed
|
||||
- ❗ To use the arp-scan method, you need to set the `SCAN_SUBNETS` variable. ()
|
||||
* The adapter will probably be `eth0` or `eth1`. (Run `iwconfig` to find your interface name(s))
|
||||
* Specify the network filter (which **significantly** speeds up the scan process). For example, the filter `192.168.1.0/24` covers IP ranges 192.168.1.0 to 192.168.1.255.
|
||||
* Examples for one and two subnets (❗ Note the `['...', '...']` format for two or more subnets):
|
||||
* Examples for one and two subnets (❗ Note the `['...', '...']` format):
|
||||
* One subnet: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0']`
|
||||
* Two subnets: `SCAN_SUBNETS = ['192.168.1.0/24 --interface=eth0', '192.168.1.0/24 --interface=eth1']`
|
||||
* More documentation on how to [setup vlans](https://github.com/jokob-sk/Pi.Alert/blob/main/docs/SUBNETS.md)
|
||||
|
||||
|
||||
### 🛑 **Common issues**
|
||||
@@ -99,9 +101,7 @@ services:
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- local/path/pialert/config:/home/pi/pialert/config
|
||||
- local/path/pialert/db:/home/pi/pialert/db
|
||||
# (optional) map an empty file with the name 'setting_darkmode' if you want to force the dark mode on container rebuilt
|
||||
- local/path/pialert/db/setting_darkmode:/home/pi/pialert/db/setting_darkmode
|
||||
- local/path/pialert/db:/home/pi/pialert/db
|
||||
# (optional) useful for debugging if you have issues setting up the container
|
||||
- local/path/logs:/home/pi/pialert/front/log
|
||||
environment:
|
||||
@@ -115,6 +115,27 @@ To run the container execute: `sudo docker-compose up -d`
|
||||
|
||||
### Example 2
|
||||
|
||||
Example by [SeimuS](https://github.com/SeimusS).
|
||||
|
||||
```yaml
|
||||
pialert:
|
||||
container_name: PiAlert
|
||||
hostname: PiAlert
|
||||
privileged: true
|
||||
image: jokobsk/pi.alert:latest
|
||||
environment:
|
||||
- TZ=Europe/Bratislava
|
||||
restart: always
|
||||
volumes:
|
||||
- ./pialert/pialert_db:/home/pi/pialert/db
|
||||
- ./pialert/pialert_config:/home/pi/pialert/config
|
||||
network_mode: host
|
||||
```
|
||||
|
||||
To run the container execute: `sudo docker-compose up -d`
|
||||
|
||||
### Example 3
|
||||
|
||||
`docker-compose.yml`
|
||||
|
||||
```yaml
|
||||
@@ -127,9 +148,7 @@ services:
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ${APP_DATA_LOCATION}/pialert/config:/home/pi/pialert/config
|
||||
- ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
||||
# (optional) map an empty file with the name 'setting_darkmode' if you want to force the dark mode on container rebuilt
|
||||
- ${APP_DATA_LOCATION}/pialert/db/setting_darkmode:/home/pi/pialert/db/setting_darkmode
|
||||
- ${APP_DATA_LOCATION}/pialert/db/pialert.db:/home/pi/pialert/db/pialert.db
|
||||
# (optional) useful for debugging if you have issues setting up the container
|
||||
- ${LOGS_LOCATION}:/home/pi/pialert/front/log
|
||||
environment:
|
||||
@@ -162,7 +181,7 @@ DEV_LOCATION=/path/to/local/source/code
|
||||
|
||||
To run the container execute: `sudo docker-compose --env-file /path/to/.env up`
|
||||
|
||||
### Example 3
|
||||
### Example 4
|
||||
|
||||
Courtesy of [pbek](https://github.com/pbek). The volume `pialert_db` is used by the db directory. The two config files are mounted directly from a local folder to their places in the config folder. You can backup the `docker-compose.yaml` folder and the docker volumes folder.
|
||||
|
||||
@@ -192,8 +211,8 @@ Big thanks to <a href="https://github.com/Macleykun">@Macleykun</a> for help and
|
||||
|
||||
## ☕ Support me
|
||||
|
||||
Disclaimer: Please only donate if you don't have any debt yourself. Support yourself first, then others.
|
||||
|
||||
<a href="https://github.com/sponsors/jokob-sk" target="_blank"><img src="https://i.imgur.com/X6p5ACK.png" alt="Sponsor Me on GitHub" style="height: 30px !important;width: 117px !important;" width="150px" ></a>
|
||||
<a href="https://www.buymeacoffee.com/jokobsk" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 30px !important;width: 117px !important;" width="117px" height="30px" ></a>
|
||||
<a href="https://www.patreon.com/user?u=84385063" target="_blank"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Patreon_logo_with_wordmark.svg/512px-Patreon_logo_with_wordmark.svg.png" alt="Support me on patreon" style="height: 30px !important;width: 117px !important;" width="117px" ></a>
|
||||
|
||||
BTC: 1N8tupjeCK12qRVU2XrV17WvKK7LCawyZM
|
||||
|
||||
103
docs/API.md
Executable file
@@ -0,0 +1,103 @@
|
||||
## API endpoints
|
||||
|
||||
PiAlert comes with a simple API. These API endpoints are static files, that are periodically updated based on your settings.
|
||||
|
||||
|
||||
### When are the endpoints updated
|
||||
|
||||
Once you enable the API (`ENABLE_API` setting), the endpoints are updated during these events:
|
||||
|
||||
1) Always during a notification event.
|
||||
2) (optional) If `API_RUN` is set to `schedule` on a specified cron-like schedule specified by the `API_RUN_SCHD` setting.
|
||||
3) (optional) If `API_RUN` is set to `interval` every N seconds specified by the `API_RUN_INTERVAL` setting (minimum 5).
|
||||
|
||||
|
||||
### Location of the endpoints
|
||||
|
||||
In the container, these files are located under the `/home/pi/pialert/front/api/` folder and thus on the `<pialert_url>/api/<File name>` url.
|
||||
|
||||
### Available endpoints
|
||||
|
||||
You can access the following files:
|
||||
|
||||
| File name | Description |
|
||||
|----------------------|----------------------|
|
||||
| `notification_text.txt` | The plain text version of the last notification. |
|
||||
| `notification_text.html` | The full HTML of the last email notification. |
|
||||
| `notification_json_final.json` | The json version of the last notification (e.g. used for webhooks - [sample JSON](https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json)). |
|
||||
| `table_devices.json` | The current (at the time of the last update as mentioned above on this page) state of all of the available Devices detected by the app. |
|
||||
| `table_nmap_scan.json` | The current state of the discovered ports by the regular NMAP scans. |
|
||||
| `table_pholus_scan.json` | The latest state of the [pholus](https://github.com/jokob-sk/Pi.Alert/tree/main/pholus) (A multicast DNS and DNS Service Discovery Security Assessment Tool) scan results. |
|
||||
| `table_plugins_events.json` | The list of the unprocessed (pending) notification events (plugins_events DB table). |
|
||||
| `table_plugins_history.json` | The list of notification events history. |
|
||||
| `table_plugins_objects.json` | The content of the plugins_objects table. Find more info on the [Plugin system here](https://github.com/jokob-sk/Pi.Alert/tree/main/front/plugins)|
|
||||
| `language_strings.json` | The content of the language_strings table, which in turn is loaded from the plugins `config.json` definitions. |
|
||||
| `table_custom_endpoint.json` | A custom endpoint generated by the SQL query specified by the `API_CUSTOM_SQL` setting. |
|
||||
| `table_settings.json` | The content of the settings table. |
|
||||
|
||||
Current/latest state of the aforementioned files depends on your settings.
|
||||
|
||||
### JSON Data format
|
||||
|
||||
The endpoints starting with the `table_` prefix contain most, if not all, data contained in the corresponding database table. The common format for those is:
|
||||
|
||||
```JSON
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"db_column_name": "data",
|
||||
"db_column_name2": "data2"
|
||||
},
|
||||
{
|
||||
"db_column_name": "data3",
|
||||
"db_column_name2": "data4"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Example JSON of the `table_devices.json` endpoint with two Devices (database rows):
|
||||
|
||||
```JSON
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"dev_MAC": "Internet",
|
||||
"dev_Name": "Net - Huawei",
|
||||
"dev_DeviceType": "Router",
|
||||
"dev_Vendor": null,
|
||||
"dev_Group": "Always on",
|
||||
"dev_FirstConnection": "2021-01-01 00:00:00",
|
||||
"dev_LastConnection": "2021-01-28 22:22:11",
|
||||
"dev_LastIP": "192.168.1.24",
|
||||
"dev_StaticIP": 0,
|
||||
"dev_PresentLastScan": 1,
|
||||
"dev_LastNotification": "2023-01-28 22:22:28.998715",
|
||||
"dev_NewDevice": 0,
|
||||
"dev_Network_Node_MAC_ADDR": "",
|
||||
"dev_Network_Node_port": "",
|
||||
"dev_Icon": "globe"
|
||||
},
|
||||
{
|
||||
"dev_MAC": "a4:8f:ff:aa:ba:1f",
|
||||
"dev_Name": "Net - USG",
|
||||
"dev_DeviceType": "Firewall",
|
||||
"dev_Vendor": "Ubiquiti Inc",
|
||||
"dev_Group": "",
|
||||
"dev_FirstConnection": "2021-02-12 22:05:00",
|
||||
"dev_LastConnection": "2021-07-17 15:40:00",
|
||||
"dev_LastIP": "192.168.1.1",
|
||||
"dev_StaticIP": 1,
|
||||
"dev_PresentLastScan": 1,
|
||||
"dev_LastNotification": "2021-07-17 15:40:10.667717",
|
||||
"dev_NewDevice": 0,
|
||||
"dev_Network_Node_MAC_ADDR": "Internet",
|
||||
"dev_Network_Node_port": 1,
|
||||
"dev_Icon": "shield-halved"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
31
docs/DEBUG_INVALID_JSON.md
Executable file
@@ -0,0 +1,31 @@
|
||||
# How to debug the Invalid JSON response error
|
||||
|
||||
Check the the HTTP response of the failing backend call by following these steps:
|
||||
|
||||
- Open developer console in your browser (usually, e. g. for Chrome, key F12 on the keyboard).
|
||||
- Follow the steps in this screenshot:
|
||||
|
||||
![F12DeveloperConsole][F12DeveloperConsole]
|
||||
|
||||
- Copy the URL causing the error and enter it in the address bar of your browser directly and hit enter. The copied URLs could look something like this (notice the query strings at the end):
|
||||
- `http://<pialert URL>:20211/php/server/devices.php?action=getDevicesTotals`
|
||||
- `http://<pialert URL>:20211/php/server/devices.php?action=getDevicesList&status=all`
|
||||
|
||||
- Post the error response in the existing issue thread on GitHub or create a new issue and include the redacted response of the failing query.
|
||||
|
||||
For reference, the above queries should return results in the following format:
|
||||
|
||||
First URL:
|
||||
|
||||
![array][array]
|
||||
|
||||
Second URL:
|
||||
|
||||
![json][json]
|
||||
|
||||
You can copy and paste any JSON result (result of the second query) into an online JSON checker, such as [this one](https://jsonchecker.com/) to check if it's valid.
|
||||
|
||||
|
||||
[F12DeveloperConsole]: ./img/DEBUG/Invalid_JSON_repsonse_debug.png "F12DeveloperConsole"
|
||||
[array]: ./img/DEBUG/array_result_example.png "array"
|
||||
[json]: ./img/DEBUG/JSON_result_example.png "json"
|
||||
43
docs/NETWORK_TREE.md
Executable file
@@ -0,0 +1,43 @@
|
||||
## How to setup your Network page
|
||||
|
||||
Make sure you have a root device with the MAC `Internet` (No other MAC addresses are currently support as root)
|
||||
|
||||
To setup a device named `rapberrypi` as a `Switch` in our network.
|
||||
|
||||
### 1) Device details page
|
||||
|
||||
- Go to the `Devices` (1) page:
|
||||
|
||||

|
||||
|
||||
- In the (2) `Details` tab navigate to the the `Type` (3) dropdown and select the type `Switch` (4).
|
||||
|
||||
> Note: Only the following device types will show up as selectable Network nodes ( = devices you can connect other devices to):
|
||||
> AP, Firewall, Gateway, PLC, Powerline, Router, Switch, USB LAN Adapter, USB WIFI Adapter and WLAN.
|
||||
|
||||
- Assign a device to your root device from the `Node` (5) dropdown which has the MAC `Internet` (6) (Your name may differ, but the MAC needs to be set to `Internet` - this is done by default).
|
||||
|
||||
- Save your changes (7)
|
||||
|
||||
### 1) Network page
|
||||
|
||||
- Navigate to your `Network` (1) page:
|
||||
|
||||

|
||||
|
||||
- Notice the newly added `raspberrypi` (2) tab which now represents a network node, also showing up in the tree (3).
|
||||
- As we asssigned the `raspberrypi` in the previous 1) Device details page section to the `Internet` parent network node in step (6), the link is also showing up in the tree diagram (4)
|
||||
- We can now assign the device `(AppleTV)` (5) to this `raspberrypi` node, representing a network Switch in this example
|
||||
|
||||
### 1) Network page with 2 levels
|
||||
|
||||
- After clicking the `Assign` button in the previous section, the `(AppleTV)` (1) device is now connected to our `raspberrypi` (2).
|
||||
|
||||

|
||||
|
||||
- You can see the `raspberrypi` represents the Network node type `Switch` (3)
|
||||
- The `(AppleTV)` to `raspberrypi` connection is also displayed in the table of `Connected devices` (4).
|
||||
- You can also see that our `raspberrypi` node is connected to it's Parent network device node with the MAC `Internet` (5). This connection again shows up in the tree (6) as well.
|
||||
|
||||
|
||||
|
||||
15
docs/SMTP_GMAIL.md
Executable file
@@ -0,0 +1,15 @@
|
||||
## Use the Gmail SMTP server
|
||||
|
||||
1) Create an app password by following the instructions from Google, you need to Enable 2FA for this to work.
|
||||
[https://support.google.com/accounts/answer/185833](https://support.google.com/accounts/answer/185833)
|
||||
|
||||
2) Specify the following settings:
|
||||
|
||||
```python
|
||||
SMTP_SKIP_TLS=True
|
||||
SMTP_FORCE_SSL=True
|
||||
SMTP_PORT=465
|
||||
SMTP_SERVER='smtp.gmail.com'
|
||||
SMTP_PASS='16-digit passcode from google'
|
||||
```
|
||||
|
||||
21
docs/SUBNETS.md
Executable file
@@ -0,0 +1,21 @@
|
||||
## Subnets configuration
|
||||
|
||||
The arp-scan time itself depends on the number of IP addresses to check.
|
||||
The number of IPs to check depends on the [network mask](https://www.calculator.net/ip-subnet-calculator.html) you set on the `SCAN_SUBNETS` setting.
|
||||
|
||||
For example, a `/24` mask results in 256 IPs to check, where as a `/16` mask checks around 65,536. Every IP takes a couple seconds. This means that with an incorrect configuration the arp-scan will take hours to complete instead of seconds.
|
||||
|
||||
- Specify the network mask. For example, the filter `192.168.1.0/24` covers IP ranges 192.168.1.0 to 192.168.1.255
|
||||
- Run `iwconfig` in your container to find your interface name(s) (e.g.: `eth0`, `eth1`).
|
||||
- Append e.g.: ` -vlan=107` to the interface field (e.g.: `eth0 -vlan=107`) for multiple vlans. More details in this [comment in this issue](https://github.com/jokob-sk/Pi.Alert/issues/170#issuecomment-1419902988)
|
||||
|
||||
### Example:
|
||||
|
||||

|
||||
|
||||
### Support for VLANS
|
||||
|
||||
Please note about the accessibility of the macvlans when they are configured on the same computer. My understanding this is a general networking behavior, but feel free to clarify via a PR/issue.
|
||||
|
||||
- Pi.Alert does not detect the macvlan container when it is running on the same computer.
|
||||
- Pi.Alert recognizes the macvlan container when it is running on a different computer.
|
||||
18
docs/WEBHOOK_N8N.md
Executable file
@@ -0,0 +1,18 @@
|
||||
### Create a simple n8n workflow
|
||||
|
||||

|
||||
|
||||
### Specify your email template
|
||||
See [sample JSON](https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json) if you want to see the JSON paths used in the email template below
|
||||

|
||||
|
||||
```
|
||||
Events count: {{ $json["body"]["attachments"][0]["text"]["events"].length }}
|
||||
New devices count: {{ $json["body"]["attachments"][0]["text"]["new_devices"].length }}
|
||||
```
|
||||
|
||||
### Get your webhook in n8n
|
||||

|
||||
|
||||
### Configure PiAlert to point to the above URL
|
||||

|
||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 32 KiB |
BIN
docs/img/DEBUG/Invalid_JSON_repsonse_debug.png
Executable file
|
After Width: | Height: | Size: 197 KiB |
BIN
docs/img/DEBUG/JSON_result_example.png
Executable file
|
After Width: | Height: | Size: 54 KiB |
BIN
docs/img/DEBUG/array_result_example.png
Executable file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
docs/img/NETWORK_TREE/Device_Details_Network_Type.png
Executable file
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/img/NETWORK_TREE/Network_Page.png
Executable file
|
After Width: | Height: | Size: 185 KiB |
BIN
docs/img/NETWORK_TREE/Network_Page_2_Levels.png
Executable file
|
After Width: | Height: | Size: 89 KiB |
BIN
docs/img/SUBNETS/subnets_vlan.png
Executable file
|
After Width: | Height: | Size: 20 KiB |
BIN
docs/img/WEBHOOK_N8N/Webhook_settings.png
Executable file
|
After Width: | Height: | Size: 61 KiB |
BIN
docs/img/WEBHOOK_N8N/n8n_send_email_settings.png
Executable file
|
After Width: | Height: | Size: 38 KiB |
BIN
docs/img/WEBHOOK_N8N/n8n_webhook_settings.png
Executable file
|
After Width: | Height: | Size: 31 KiB |
BIN
docs/img/WEBHOOK_N8N/n8n_workflow.png
Executable file
|
After Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 132 KiB |
BIN
docs/img/device_nmap.png
Executable file
|
After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 141 KiB |
BIN
docs/img/plugins.png
Executable file
|
After Width: | Height: | Size: 218 KiB |
BIN
docs/img/plugins_json_settings.png
Executable file
|
After Width: | Height: | Size: 185 KiB |
BIN
docs/img/plugins_json_ui.png
Executable file
|
After Width: | Height: | Size: 173 KiB |
BIN
docs/img/plugins_settings.png
Executable file
|
After Width: | Height: | Size: 158 KiB |
BIN
docs/img/plugins_webmon.png
Executable file
|
After Width: | Height: | Size: 92 KiB |
0
docs/img/size_h_1250_w_1000.txt
Normal file → Executable file
@@ -1,80 +0,0 @@
|
||||
<!-- ---------------------------------------------------------------------------
|
||||
# Pi.Alert
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
#
|
||||
# repot_sample.html - Back module. Sample email reporting in HTML format
|
||||
#-------------------------------------------------------------------------------
|
||||
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
|
||||
#--------------------------------------------------------------------------- -->
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<font face=sans-serif>
|
||||
<table align=center width=80% border=1 bordercolor=#909090 cellpadding=0 cellspacing=0 style="border-collapse: collapse; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.5)">
|
||||
<tr>
|
||||
<td bgcolor=#EFB956 align=center style="padding: 20px 10px 10px 10px; font-size: 36px; font-weight: bold; color:#7F6000; text-shadow: 4px 4px 6px #909090">
|
||||
Pi.Alert Report
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#FFD966 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 16px; text-align:center; color:#5F5000">
|
||||
<tr>
|
||||
<td width=33%> Report Date: <b>2021-01-01 08:00</b> </td>
|
||||
<td width=34%> Scan Cycle: <b>Internet</b> </td>
|
||||
<td width=33%> Server: <b>pi4</b> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td bgcolor=#F5F5F5 valign=top height=400 style="padding: 20px">
|
||||
|
||||
<p style="font-size: 24px; font-weight: bold; color:#C04040; text-shadow: 2px 2px 4px #A0A0A0"> Internet: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> Event Type </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th> Additional Info </th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> Internet IP Changed </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td style="font-size: 24px; color:#D02020"> 1.1.1.0 </td>
|
||||
<td> Previous Internet IP: 1.1.0.0 </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#70AD47 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 12px; font-weight: bold; color:#385723">
|
||||
<tr>
|
||||
<td width=25% style="text-align:Left"> Puche 2021</td>
|
||||
<td width=50% style="text-align:center"> Pi.Alert 2.50 / 2021-01-01 </td>
|
||||
<td width=25% style="text-align:right"> GNU GPLv3</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,143 +0,0 @@
|
||||
<!-- ---------------------------------------------------------------------------
|
||||
# Pi.Alert
|
||||
# Open Source Network Guard / WIFI & LAN intrusion detector
|
||||
#
|
||||
# repot_sample.html - Back module. Sample email reporting in HTML format
|
||||
#-------------------------------------------------------------------------------
|
||||
# Puche 2021 pi.alert.application@gmail.com GNU GPLv3
|
||||
#--------------------------------------------------------------------------- -->
|
||||
|
||||
<html>
|
||||
|
||||
<head>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<font face=sans-serif>
|
||||
<table align=center width=80% border=1 bordercolor=#909090 cellpadding=0 cellspacing=0 style="border-collapse: collapse; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.5)">
|
||||
<tr>
|
||||
<td bgcolor=#EFB956 align=center style="padding: 20px 10px 10px 10px; font-size: 36px; font-weight: bold; color:#7F6000; text-shadow: 4px 4px 6px #909090">
|
||||
Pi.Alert Report
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#FFD966 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 16px; text-align:center; color:#5F5000">
|
||||
<tr>
|
||||
<td width=33%> Report Date: <b>2021-01-01 08:00</b> </td>
|
||||
<td width=34%> Scan Cycle: <b>1</b> </td>
|
||||
<td width=33%> Server: <b>pi4</b> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
||||
<tr>
|
||||
<td bgcolor=#F5F5F5 height=400 valign=top style="padding: 20px">
|
||||
|
||||
|
||||
|
||||
<p style="font-size: 14px; font-weight: bold; color:#C04040; text-shadow: 2px 2px 4px #A0A0A0"> New Devices: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th> Vendor </th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> f8:d0:27:00:00:00 </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td> 192.168.1.20 </td>
|
||||
<td> Seiko Epson Corporation </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> c8:6c:3d:00:00:00 </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td> 192.168.1.181 </td>
|
||||
<td> Amazon Technologies Inc. </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
<p style="font-size: 14px; font-weight: bold; color:#C04040; text-shadow: 2px 2px 4px #A0A0A0"> Devices Down: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th> Device Name </th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 0c:ee:99:00:00:00 </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td> 192.168.1.171 </td>
|
||||
<td> Alexa - Echo </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<br>
|
||||
|
||||
|
||||
|
||||
<p style="font-size: 14px; font-weight: bold; color:#409040; text-shadow: 2px 2px 4px #A0A0A0"> Events: </p>
|
||||
|
||||
<table width=100% border=1 bordercolor=#C0C0C0 cellpadding=3px cellspacing=0 style="border-collapse: collapse; font-size: 12px; color:#707070; box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2)">
|
||||
<tr bgcolor=#909090 style="color:#F0F0F0">
|
||||
<th width=140> MAC </th>
|
||||
<th width=130> Datetime </th>
|
||||
<th width=100> IP </th>
|
||||
<th width=100> Event Type </th>
|
||||
<th width=140> Device Name </th>
|
||||
<th> Additional Info </th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td> 94:0c:98:00:00:00 </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td> 192.168.1.132 </td>
|
||||
<td> Connected </td>
|
||||
<td> Person 1 - iPhone 11 </td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> 5c:41:5a:00:00:00 </td>
|
||||
<td> 2021-01-01 08:00:00 </td>
|
||||
<td> 192.168.1.170 </td>
|
||||
<td> IP Changed </td>
|
||||
<td> Alexa Dot </td>
|
||||
<td> Previous IP: 192.168.1.243 </td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>
|
||||
<table width=100% border=0 bgcolor=#70AD47 cellpadding=5px cellspacing=0 style="border-collapse: collapse; font-size: 12px; font-weight: bold; color:#385723">
|
||||
<tr>
|
||||
<td width=25% style="text-align:Left"> Puche 2021</td>
|
||||
<td width=50% style="text-align:center"> Pi.Alert 2.50 / 2021-01-01 </td>
|
||||
<td width=25% style="text-align:right"> GNU GPLv3</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</font>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,96 +0,0 @@
|
||||
[
|
||||
{
|
||||
"headers": {
|
||||
"host": "192.168.1.82:5678",
|
||||
"user-agent": "curl/7.74.0",
|
||||
"accept": "*/*",
|
||||
"content-type": "application/json",
|
||||
"content-length": "872"
|
||||
},
|
||||
"params": {},
|
||||
"query": {},
|
||||
"body": {
|
||||
"username": "Pi.Alert",
|
||||
"text": "There are new notifications",
|
||||
"attachments": [
|
||||
{
|
||||
"title": "Pi.Alert Notifications",
|
||||
"title_link": "",
|
||||
"text": {
|
||||
"internet": [],
|
||||
"new_devices": [],
|
||||
"down_devices": [],
|
||||
"events": [
|
||||
[
|
||||
"aa:77:aa:77:aa:77",
|
||||
"192.168.1.151",
|
||||
"2022-08-12 21:48:00",
|
||||
"Connected",
|
||||
"",
|
||||
1,
|
||||
null,
|
||||
"aa:77:aa:77:aa:77",
|
||||
"ESP32 - display",
|
||||
"House",
|
||||
"",
|
||||
"Espressif Inc.",
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
"2022-07-21 20:35:00",
|
||||
"2022-08-12 21:48:00",
|
||||
"192.168.1.151",
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
"2022-08-12 21:42:47.937413",
|
||||
1,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
"aa:77:aa:77:aa:77",
|
||||
""
|
||||
],
|
||||
[
|
||||
"aa:77:aa:77:aa:77",
|
||||
"192.168.1.149",
|
||||
"2022-08-12 21:48:00",
|
||||
"Connected",
|
||||
"",
|
||||
1,
|
||||
null,
|
||||
"aa:77:aa:77:aa:77",
|
||||
"ESP32 - 1",
|
||||
"House",
|
||||
"Singleboard Computer (SBC)",
|
||||
"Espressif Inc.",
|
||||
0,
|
||||
"",
|
||||
"",
|
||||
"2022-07-15 05:30:00",
|
||||
"2022-08-12 21:48:00",
|
||||
"192.168.1.149",
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
"2022-08-12 21:42:47.937413",
|
||||
1,
|
||||
1,
|
||||
"",
|
||||
0,
|
||||
"aa:77:aa:77:aa:77",
|
||||
""
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
2
front/api/.gitignore
vendored
Executable file
@@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
||||
@@ -591,7 +591,14 @@ height: 50px;
|
||||
}
|
||||
|
||||
.nav-tabs-custom .tab-content {
|
||||
background-color: white;
|
||||
background-color: white;
|
||||
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.nav-tabs-custom .tab-content {
|
||||
overflow: scroll;
|
||||
}
|
||||
}
|
||||
|
||||
.top_small_box_gray_text {
|
||||
@@ -623,20 +630,21 @@ height: 50px;
|
||||
width:30%;
|
||||
}
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.setting_description {
|
||||
/* color: green; */
|
||||
display: block;
|
||||
}
|
||||
.setting_input{
|
||||
width:35%;
|
||||
/* background-color: green; */
|
||||
}
|
||||
.setting_name
|
||||
{
|
||||
width:19%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.setting_description {
|
||||
/* color: green; */
|
||||
display: block;
|
||||
}
|
||||
.setting_input{
|
||||
width:40%;
|
||||
/* background-color: green; */
|
||||
}
|
||||
.setting_name
|
||||
{
|
||||
width:19%;
|
||||
}
|
||||
}
|
||||
|
||||
.table_row {
|
||||
padding: 3px;
|
||||
@@ -663,13 +671,13 @@ height: 50px;
|
||||
|
||||
.setting_description
|
||||
{
|
||||
width:46%;
|
||||
width:40%;
|
||||
}
|
||||
|
||||
/* .setting_input
|
||||
.myhidden
|
||||
{
|
||||
width:35%;
|
||||
} */
|
||||
display:none;
|
||||
}
|
||||
|
||||
.center
|
||||
{
|
||||
@@ -690,6 +698,16 @@ height: 50px;
|
||||
/* background-color: #272c30; */
|
||||
margin: 10px;
|
||||
|
||||
}
|
||||
#settingsPage .panel-heading:hover{
|
||||
background-color: #272c30;
|
||||
}
|
||||
|
||||
.settings-expand-icon {
|
||||
font-size: medium;
|
||||
/* background-color: #272c30; */
|
||||
margin: 10px;
|
||||
|
||||
}
|
||||
|
||||
.settings_content input[type=checkbox]
|
||||
@@ -702,4 +720,122 @@ height: 50px;
|
||||
.drp-edit
|
||||
{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.new-version
|
||||
{
|
||||
top: -6px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
left: 0px;
|
||||
font-size: large;
|
||||
}
|
||||
|
||||
.pointer
|
||||
{
|
||||
cursor:pointer;
|
||||
}
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple .select2-selection__choice
|
||||
{
|
||||
background-color:#258744;
|
||||
}
|
||||
.db_info_table_row .select2-container--default .select2-selection--multiple
|
||||
{
|
||||
background-color:#606060;
|
||||
}
|
||||
|
||||
.select2-container .select2-dropdown
|
||||
{
|
||||
background-color:#606060;
|
||||
}
|
||||
|
||||
.networkPageHelp{
|
||||
position: absolute;
|
||||
font-size: x-small;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.pageHelp{
|
||||
position: absolute;
|
||||
font-size: x-small;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
|
||||
#networkTree .box
|
||||
{
|
||||
padding:2px;
|
||||
margin:2px;
|
||||
}
|
||||
#networkTree .netNodeText
|
||||
{
|
||||
top: 2px;
|
||||
margin: 2px;
|
||||
position: absolute;
|
||||
}
|
||||
#networkTree
|
||||
{
|
||||
margin-left: 16px;
|
||||
/* border: solid;
|
||||
border-color:#606060; */
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
}
|
||||
#networkTree .netIcon
|
||||
{
|
||||
width: 25px;;
|
||||
float:left;
|
||||
display:inline;
|
||||
}
|
||||
#networkTree .netCollapse
|
||||
{
|
||||
display: block;
|
||||
position: absolute;
|
||||
margin-left: 156px;
|
||||
top: -3px;
|
||||
font-size: large;
|
||||
left: -15px;
|
||||
}
|
||||
#networkTree .highlightedNode
|
||||
{
|
||||
border: solid;
|
||||
border-color:cyan;
|
||||
}
|
||||
#networkTree .netStatus-Off-line i
|
||||
{
|
||||
color: #dd4b39;
|
||||
}
|
||||
|
||||
.spanNetworkTree {
|
||||
display: inline-block;
|
||||
width: 120px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.plugin-content
|
||||
{
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
.plugin-content #tabs-content-location
|
||||
{
|
||||
margin-top: 20px;
|
||||
margin-left: 7px;
|
||||
margin-right: 7px;
|
||||
margin-bottom: 9px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.plugins-description
|
||||
{
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.login-page .login-custom
|
||||
{
|
||||
width:480px;
|
||||
|
||||
}
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
require 'php/templates/header.php';
|
||||
require 'php/templates/graph.php';
|
||||
require 'php/server/util.php';
|
||||
|
||||
|
||||
// check permissions
|
||||
@@ -27,7 +26,7 @@
|
||||
<!-- Content header--------------------------------------------------------- -->
|
||||
<section class="content-header">
|
||||
<h1 id="pageTitle">
|
||||
<?php echo lang('Device_Title');?>
|
||||
<?= lang('Device_Title');?>
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
@@ -40,7 +39,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('all');">
|
||||
<div class="small-box bg-aqua">
|
||||
<div class="inner"><h3 id="devicesAll"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_AllDevices');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_AllDevices');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="fa fa-laptop text-aqua-40"></i></div>
|
||||
</div>
|
||||
@@ -52,7 +51,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('connected');">
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner"><h3 id="devicesConnected"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_Connected');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_Connected');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="fa fa-plug text-green-40"></i></div>
|
||||
</div>
|
||||
@@ -64,7 +63,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('favorites');">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner"><h3 id="devicesFavorites"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_Favorites');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_Favorites');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="fa fa-star text-yellow-40"></i></div>
|
||||
</div>
|
||||
@@ -76,7 +75,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('new');">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner"><h3 id="devicesNew"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_NewDevices');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_NewDevices');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="ion ion-plus-round text-yellow-40"></i></div>
|
||||
</div>
|
||||
@@ -88,7 +87,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('down');">
|
||||
<div class="small-box bg-red">
|
||||
<div class="inner"><h3 id="devicesDown"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_DownAlerts');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_DownAlerts');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="fa fa-warning text-red-40"></i></div>
|
||||
</div>
|
||||
@@ -100,7 +99,7 @@
|
||||
<a href="#" onclick="javascript: getDevicesList('archived');">
|
||||
<div class="small-box bg-gray top_small_box_gray_text">
|
||||
<div class="inner"><h3 id="devicesArchived"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Device_Shortcut_Archived');?></p>
|
||||
<p class="infobox_label"><?= lang('Device_Shortcut_Archived');?></p>
|
||||
</div>
|
||||
<div class="icon"><i class="fa fa-eye-slash text-gray-40"></i></div>
|
||||
</div>
|
||||
@@ -115,7 +114,7 @@
|
||||
<div class="col-md-12">
|
||||
<div class="box" id="clients">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title"><?php echo lang('Device_Shortcut_OnlineChart');?> </h3>
|
||||
<h3 class="box-title"><?= lang('Device_Shortcut_OnlineChart');?> </h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="chart">
|
||||
@@ -150,20 +149,8 @@
|
||||
<div class="box-body table-responsive">
|
||||
<table id="tableDevices" class="table table-bordered table-hover table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo lang('Device_TableHead_Name');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Owner');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Type');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Favorite');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Group');?></th>
|
||||
<th><?php echo lang('Device_TableHead_FirstSession');?></th>
|
||||
<th><?php echo lang('Device_TableHead_LastSession');?></th>
|
||||
<th><?php echo lang('Device_TableHead_LastIP');?></th>
|
||||
<th><?php echo lang('Device_TableHead_MAC');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Status');?></th>
|
||||
<th><?php echo lang('Device_TableHead_MAC');?></th>
|
||||
<th><?php echo lang('Device_TableHead_LastIPOrder');?></th>
|
||||
<th><?php echo lang('Device_TableHead_Rowid');?></th>
|
||||
<tr>
|
||||
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
@@ -204,6 +191,10 @@
|
||||
var parTableOrder = 'Front_Devices_Order';
|
||||
var tableRows = 10;
|
||||
var tableOrder = [[3,'desc'], [0,'asc']];
|
||||
|
||||
var columnsStr = '[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]';
|
||||
var tableColumnOrder = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] ;
|
||||
var tableColumnVisible = tableColumnOrder;
|
||||
|
||||
// Read parameters & Initialize components
|
||||
main();
|
||||
@@ -211,48 +202,132 @@
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function main () {
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get¶meter='+ parTableRows, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
|
||||
result = parseInt(result, 10)
|
||||
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
|
||||
cookieColumnsVisibleStr = decodeURI(getCookie("Front_Devices_Columns_Visible")).replaceAll('%2C',',')
|
||||
|
||||
if (Number.isInteger (result) ) {
|
||||
tableRows = result;
|
||||
}
|
||||
defaultValue = cookieColumnsVisibleStr == "" ? columnsStr : cookieColumnsVisibleStr;
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get¶meter='+ parTableOrder, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
result = JSON.parse(result);
|
||||
if (Array.isArray (result) ) {
|
||||
tableOrder = result;
|
||||
// get visible columns
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Visible&skipcache', function(data) {
|
||||
|
||||
// save which columns are in the Devices page visible
|
||||
tableColumnVisible = numberArrayFromString(data);
|
||||
|
||||
// get from cookie if available (need to use decodeURI as saved as part of URI in PHP)
|
||||
cookieColumnsOrderStr = decodeURI(getCookie("Front_Devices_Columns_Order")).replaceAll('%2C',',')
|
||||
|
||||
defaultValue = cookieColumnsOrderStr == "" ? columnsStr : cookieColumnsOrderStr;
|
||||
|
||||
// get the custom order specified by the user
|
||||
$.get('php/server/parameters.php?action=get&expireMinutes=525600&defaultValue='+defaultValue+'¶meter=Front_Devices_Columns_Order&skipcache', function(data) {
|
||||
|
||||
// save the columns order in the Devices page
|
||||
tableColumnOrder = numberArrayFromString(data);
|
||||
|
||||
//initialize the table headers in the correct order
|
||||
var headersDefaultOrder = [ '<?= lang('Device_TableHead_Name');?>',
|
||||
'<?= lang('Device_TableHead_Owner');?>',
|
||||
'<?= lang('Device_TableHead_Type');?>',
|
||||
'<?= lang('Device_TableHead_Icon');?>',
|
||||
'<?= lang('Device_TableHead_Favorite');?>',
|
||||
'<?= lang('Device_TableHead_Group');?>',
|
||||
'<?= lang('Device_TableHead_FirstSession');?>',
|
||||
'<?= lang('Device_TableHead_LastSession');?>',
|
||||
'<?= lang('Device_TableHead_LastIP');?>',
|
||||
'<?= lang('Device_TableHead_MAC');?>',
|
||||
'<?= lang('Device_TableHead_Status');?>',
|
||||
'<?= lang('Device_TableHead_MAC_full');?>',
|
||||
'<?= lang('Device_TableHead_LastIPOrder');?>',
|
||||
'<?= lang('Device_TableHead_Rowid');?>',
|
||||
'<?= lang('Device_TableHead_Parent_MAC');?>',
|
||||
'<?= lang('Device_TableHead_Connected_Devices');?>',
|
||||
'<?= lang('Device_TableHead_Location');?>',
|
||||
'<?= lang('Device_TableHead_Vendor');?>'
|
||||
];
|
||||
|
||||
html = '';
|
||||
|
||||
for(index = 0; index < tableColumnOrder.length; index++)
|
||||
{
|
||||
html += '<th>' + headersDefaultOrder[tableColumnOrder[index]] + '</th>';
|
||||
}
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeDatatable();
|
||||
$('#tableDevices tr').html(html);
|
||||
|
||||
// query data
|
||||
getDevicesTotals();
|
||||
getDevicesList (deviceStatus);
|
||||
});
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=50¶meter='+ parTableRows, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
|
||||
result = parseInt(result, 10)
|
||||
|
||||
if (Number.isInteger (result) ) {
|
||||
tableRows = result;
|
||||
}
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=[[3,"desc"],[0,"asc"]]¶meter='+ parTableOrder, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
result = JSON.parse(result);
|
||||
|
||||
|
||||
|
||||
if (Array.isArray (result) ) {
|
||||
tableOrder = result;
|
||||
}
|
||||
|
||||
// Initialize components with parameters
|
||||
initializeDatatable();
|
||||
|
||||
// query data
|
||||
getDevicesTotals();
|
||||
getDevicesList (deviceStatus);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
var tableColumnHide = [];
|
||||
|
||||
// mapping the default order to the user specified one
|
||||
function mapIndx(oldIndex)
|
||||
{
|
||||
for(i=0;i<tableColumnOrder.length;i++)
|
||||
{
|
||||
if(tableColumnOrder[i] == oldIndex)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function initializeDatatable () {
|
||||
for(i = 0; i < tableColumnOrder.length; i++)
|
||||
{
|
||||
// hide this column if not in the tableColumnVisible variable
|
||||
if(tableColumnVisible.includes(tableColumnOrder[i]) == false)
|
||||
{
|
||||
tableColumnHide.push(mapIndx(tableColumnOrder[i]));
|
||||
}
|
||||
}
|
||||
|
||||
// If the device has a small width (mobile) only show name, ip, and status columns.
|
||||
if (window.screen.width < 400) {
|
||||
var tableColumnShow = [10,11,12,1,2,3,4,5,6,8];
|
||||
} else {
|
||||
var tableColumnShow = [10, 11, 12];
|
||||
};
|
||||
if (window.screen.width < 400) {
|
||||
tableColumnHide = [11,12,13,1,2,4,5,6,7,9];
|
||||
}
|
||||
// else {
|
||||
// // var tableColumnHide = [11, 12, 13];
|
||||
// tableColumnHide = [11, 12, 13];
|
||||
// };
|
||||
var table=
|
||||
$('#tableDevices').DataTable({
|
||||
'paging' : true,
|
||||
'lengthChange' : true,
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, '<?php echo lang('Device_Tablelenght_all');?>']],
|
||||
'lengthMenu' : [[10, 25, 50, 100, 500, -1], [10, 25, 50, 100, 500, '<?= lang('Device_Tablelenght_all');?>']],
|
||||
'searching' : true,
|
||||
|
||||
'ordering' : true,
|
||||
@@ -265,20 +340,56 @@ function initializeDatatable () {
|
||||
// 'order' : [[3,'desc'], [0,'asc']],
|
||||
|
||||
'columnDefs' : [
|
||||
{visible: false, targets: tableColumnShow },
|
||||
{className: 'text-center', targets: [3, 8, 9] },
|
||||
{width: '80px', targets: [5, 6] },
|
||||
{width: '0px', targets: 9 },
|
||||
{orderData: [11], targets: 7 },
|
||||
{visible: false, targets: tableColumnHide },
|
||||
{className: 'text-center', targets: [mapIndx(3), mapIndx(4), mapIndx(9), mapIndx(10), mapIndx(15)] },
|
||||
{width: '80px', targets: [mapIndx(6), mapIndx(7), mapIndx(15)] },
|
||||
{width: '30px', targets: [mapIndx(10), mapIndx(13)] },
|
||||
{orderData: [mapIndx(12)], targets: mapIndx(8) },
|
||||
|
||||
// Device Name
|
||||
{targets: [0],
|
||||
{targets: [mapIndx(0)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
$(td).html ('<b><a href="deviceDetails.php?mac='+ rowData[10] +'" class="">'+ cellData +'</a></b>');
|
||||
$(td).html ('<b class="anonymizeDev"><a href="deviceDetails.php?mac='+ rowData[mapIndx(11)] +'" class="">'+ cellData +'</a></b>');
|
||||
} },
|
||||
|
||||
// Favorite
|
||||
{targets: [3],
|
||||
// Connected Devices
|
||||
{targets: [mapIndx(15)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
$(td).html ('<b><a href="./network.php?mac='+ rowData[mapIndx(11)] +'" class="">'+ cellData +'</a></b>');
|
||||
} },
|
||||
|
||||
// Icon
|
||||
{targets: [mapIndx(3)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (!emptyArr.includes(cellData)){
|
||||
$(td).html ('<i class="fa fa-'+cellData+' " style="font-size:16px"></i>');
|
||||
} else {
|
||||
$(td).html ('');
|
||||
}
|
||||
} },
|
||||
|
||||
// Full MAC
|
||||
{targets: [mapIndx(11)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (!emptyArr.includes(cellData)){
|
||||
$(td).html ('<span class="anonymizeMac">'+cellData+'</span>');
|
||||
} else {
|
||||
$(td).html ('');
|
||||
}
|
||||
} },
|
||||
|
||||
// IP address
|
||||
{targets: [mapIndx(12)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (!emptyArr.includes(cellData)){
|
||||
$(td).html ('<span class="anonymizeIp">'+cellData+'</span>');
|
||||
} else {
|
||||
$(td).html ('');
|
||||
}
|
||||
} },
|
||||
|
||||
// Favorite
|
||||
{targets: [mapIndx(4)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (cellData == 1){
|
||||
$(td).html ('<i class="fa fa-star text-yellow" style="font-size:16px"></i>');
|
||||
@@ -287,14 +398,14 @@ function initializeDatatable () {
|
||||
}
|
||||
} },
|
||||
|
||||
// Dates
|
||||
{targets: [5, 6],
|
||||
// Dates
|
||||
{targets: [mapIndx(6), mapIndx(7)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
$(td).html (translateHTMLcodes (cellData));
|
||||
} },
|
||||
|
||||
// Random MAC
|
||||
{targets: [8],
|
||||
// Random MAC
|
||||
{targets: [mapIndx(9)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
if (cellData == 1){
|
||||
$(td).html ('<i data-toggle="tooltip" data-placement="right" title="Random MAC" style="font-size: 16px;" class="text-yellow glyphicon glyphicon-random"></i>');
|
||||
@@ -303,8 +414,8 @@ function initializeDatatable () {
|
||||
}
|
||||
} },
|
||||
|
||||
// Status color
|
||||
{targets: [9],
|
||||
// Status color
|
||||
{targets: [mapIndx(10)],
|
||||
'createdCell': function (td, cellData, rowData, row, col) {
|
||||
switch (cellData) {
|
||||
case 'Down': color='red'; break;
|
||||
@@ -324,13 +435,13 @@ function initializeDatatable () {
|
||||
'language' : {
|
||||
processing: '<table> <td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td> </table>',
|
||||
emptyTable: 'No data',
|
||||
"lengthMenu": "<?php echo lang('Device_Tablelenght');?>",
|
||||
"search": "<?php echo lang('Device_Searchbox');?>: ",
|
||||
"lengthMenu": "<?= lang('Device_Tablelenght');?>",
|
||||
"search": "<?= lang('Device_Searchbox');?>: ",
|
||||
"paginate": {
|
||||
"next": "<?php echo lang('Device_Table_nav_next');?>",
|
||||
"previous": "<?php echo lang('Device_Table_nav_prev');?>"
|
||||
"next": "<?= lang('Device_Table_nav_next');?>",
|
||||
"previous": "<?= lang('Device_Table_nav_prev');?>"
|
||||
},
|
||||
"info": "<?php echo lang('Device_Table_info');?>",
|
||||
"info": "<?= lang('Device_Table_info');?>",
|
||||
}
|
||||
});
|
||||
|
||||
@@ -341,11 +452,11 @@ function initializeDatatable () {
|
||||
|
||||
$('#tableDevices').on( 'order.dt', function () {
|
||||
setParameter (parTableOrder, JSON.stringify (table.order()) );
|
||||
setCookie ('devicesList', getDevicesFromTable(table) );
|
||||
setCache ('devicesList', getDevicesFromTable(table) );
|
||||
} );
|
||||
|
||||
$('#tableDevices').on( 'search.dt', function () {
|
||||
setCookie ('devicesList', getDevicesFromTable(table) );
|
||||
setCache ('devicesList', getDevicesFromTable(table) );
|
||||
} );
|
||||
|
||||
};
|
||||
@@ -354,18 +465,27 @@ function initializeDatatable () {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Gets a JSON list of rowID and mac from the displayed table in the UI
|
||||
function getDevicesFromTable(table)
|
||||
{
|
||||
rowIDs = table.column(12, { 'search': 'applied' }).data().toArray() // rowID is in hidden column 12
|
||||
rowMACs = table.column(10, { 'search': 'applied' }).data().toArray() // MAC is in hidden column 10
|
||||
{
|
||||
rowIDs = table.column(mapIndx(13), { 'search': 'applied' }).data().toArray() //
|
||||
rowMACs = table.column(mapIndx(11), { 'search': 'applied' }).data().toArray() //
|
||||
rowNames = table.column(mapIndx(0), { 'search': 'applied' }).data().toArray() //
|
||||
rowTypes = table.column(mapIndx(2), { 'search': 'applied' }).data().toArray() //
|
||||
rowIcons = table.column(mapIndx(3), { 'search': 'applied' }).data().toArray() //
|
||||
rowParentMAC = table.column(mapIndx(14), { 'search': 'applied' }).data().toArray() //
|
||||
rowStatus = table.column(mapIndx(10), { 'search': 'applied' }).data().toArray() //
|
||||
|
||||
result = []
|
||||
|
||||
rowIDs.map(function(rowID, index){
|
||||
result.push({"rowid": rowID, "mac":rowMACs[index]})
|
||||
result.push({
|
||||
"rowid": rowID,
|
||||
"mac" : rowMACs[index],
|
||||
"name" : rowNames[index],
|
||||
"type" : rowTypes[index],
|
||||
"icon" : rowIcons[index],
|
||||
"parentMac" : rowParentMAC[index],
|
||||
"status" : rowStatus[index] })
|
||||
})
|
||||
|
||||
// console.log(rowIDs)
|
||||
// console.log(result)
|
||||
|
||||
return JSON.stringify (result)
|
||||
}
|
||||
@@ -392,6 +512,10 @@ function getDevicesTotals () {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function getDeviceColumns () {
|
||||
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
function getDevicesList (status) {
|
||||
// Save status selected
|
||||
@@ -399,13 +523,13 @@ function getDevicesList (status) {
|
||||
|
||||
// Define color & title for the status selected
|
||||
switch (deviceStatus) {
|
||||
case 'all': tableTitle = '<?php echo lang('Device_Shortcut_AllDevices');?>'; color = 'aqua'; break;
|
||||
case 'connected': tableTitle = '<?php echo lang('Device_Shortcut_Connected');?>'; color = 'green'; break;
|
||||
case 'favorites': tableTitle = '<?php echo lang('Device_Shortcut_Favorites');?>'; color = 'yellow'; break;
|
||||
case 'new': tableTitle = '<?php echo lang('Device_Shortcut_NewDevices');?>'; color = 'yellow'; break;
|
||||
case 'down': tableTitle = '<?php echo lang('Device_Shortcut_DownAlerts');?>'; color = 'red'; break;
|
||||
case 'archived': tableTitle = '<?php echo lang('Device_Shortcut_Archived');?>'; color = 'gray'; break;
|
||||
default: tableTitle = '<?php echo lang('Device_Shortcut_Devices');?>'; color = 'gray'; break;
|
||||
case 'all': tableTitle = '<?= lang('Device_Shortcut_AllDevices');?>'; color = 'aqua'; break;
|
||||
case 'connected': tableTitle = '<?= lang('Device_Shortcut_Connected');?>'; color = 'green'; break;
|
||||
case 'favorites': tableTitle = '<?= lang('Device_Shortcut_Favorites');?>'; color = 'yellow'; break;
|
||||
case 'new': tableTitle = '<?= lang('Device_Shortcut_NewDevices');?>'; color = 'yellow'; break;
|
||||
case 'down': tableTitle = '<?= lang('Device_Shortcut_DownAlerts');?>'; color = 'red'; break;
|
||||
case 'archived': tableTitle = '<?= lang('Device_Shortcut_Archived');?>'; color = 'gray'; break;
|
||||
default: tableTitle = '<?= lang('Device_Shortcut_Devices');?>'; color = 'gray'; break;
|
||||
}
|
||||
|
||||
// Set title and color
|
||||
@@ -419,3 +543,5 @@ function getDevicesList (status) {
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<script src="js/pialert_common.js"></script>
|
||||
|
||||
@@ -17,17 +17,17 @@
|
||||
<!-- Content header--------------------------------------------------------- -->
|
||||
<section class="content-header">
|
||||
<h1 id="pageTitle">
|
||||
<?php echo lang('Events_Title');?>
|
||||
<?= lang('Events_Title');?>
|
||||
</h1>
|
||||
|
||||
<!-- period selector -->
|
||||
<span class="breadcrumb" style="top: 0px;">
|
||||
<select class="form-control" id="period" onchange="javascript: periodChanged();">
|
||||
<option value="1 day"><?php echo lang('Events_Periodselect_today');?></option>
|
||||
<option value="7 days"><?php echo lang('Events_Periodselect_LastWeek');?></option>
|
||||
<option value="1 month" selected><?php echo lang('Events_Periodselect_LastMonth');?></option>
|
||||
<option value="1 year"><?php echo lang('Events_Periodselect_LastYear');?></option>
|
||||
<option value="100 years"><?php echo lang('Events_Periodselect_All');?></option>
|
||||
<option value="1 day"><?= lang('Events_Periodselect_today');?></option>
|
||||
<option value="7 days"><?= lang('Events_Periodselect_LastWeek');?></option>
|
||||
<option value="1 month" selected><?= lang('Events_Periodselect_LastMonth');?></option>
|
||||
<option value="1 year"><?= lang('Events_Periodselect_LastYear');?></option>
|
||||
<option value="100 years"><?= lang('Events_Periodselect_All');?></option>
|
||||
</select>
|
||||
</span>
|
||||
</section>
|
||||
@@ -42,7 +42,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('all');">
|
||||
<div class="small-box bg-aqua">
|
||||
<div class="inner"> <h3 id="eventsAll"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_AllEvents');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_AllEvents');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="fa fa-bolt text-aqua-40"></i> </div>
|
||||
</div>
|
||||
@@ -54,7 +54,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('sessions');">
|
||||
<div class="small-box bg-green">
|
||||
<div class="inner"> <h3 id="eventsSessions"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_Sessions');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_Sessions');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="fa fa-plug text-green-40"></i> </div>
|
||||
</div>
|
||||
@@ -66,7 +66,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('missing');">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner"> <h3 id="eventsMissing"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_MissSessions');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_MissSessions');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="fa fa-exchange text-yellow-40"></i> </div>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('voided');">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner"> <h3 id="eventsVoided"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_VoidSessions');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_VoidSessions');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="fa fa-exclamation-circle text-yellow-40"></i> </div>
|
||||
</div>
|
||||
@@ -90,7 +90,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('new');">
|
||||
<div class="small-box bg-yellow">
|
||||
<div class="inner"> <h3 id="eventsNewDevices"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_NewDevices');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_NewDevices');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="ion ion-plus-round text-yellow-40"></i> </div>
|
||||
</div>
|
||||
@@ -102,7 +102,7 @@
|
||||
<a href="#" onclick="javascript: getEvents('down');">
|
||||
<div class="small-box bg-red">
|
||||
<div class="inner"> <h3 id="eventsDown"> -- </h3>
|
||||
<p class="infobox_label"><?php echo lang('Events_Shortcut_DownAlerts');?></p>
|
||||
<p class="infobox_label"><?= lang('Events_Shortcut_DownAlerts');?></p>
|
||||
</div>
|
||||
<div class="icon"> <i class="fa fa-warning text-red-40"></i> </div>
|
||||
</div>
|
||||
@@ -127,18 +127,18 @@
|
||||
<table id="tableEvents" class="table table-bordered table-hover table-striped ">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php echo lang('Events_TableHead_Order');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Device');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Owner');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Date');?></th>
|
||||
<th><?php echo lang('Events_TableHead_EventType');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Connection');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Disconnection');?></th>
|
||||
<th><?php echo lang('Events_TableHead_Duration');?></th>
|
||||
<th><?php echo lang('Events_TableHead_DurationOrder');?></th>
|
||||
<th><?php echo lang('Events_TableHead_IP');?></th>
|
||||
<th><?php echo lang('Events_TableHead_IPOrder');?></th>
|
||||
<th><?php echo lang('Events_TableHead_AdditionalInfo');?></th>
|
||||
<th><?= lang('Events_TableHead_Order');?></th>
|
||||
<th><?= lang('Events_TableHead_Device');?></th>
|
||||
<th><?= lang('Events_TableHead_Owner');?></th>
|
||||
<th><?= lang('Events_TableHead_Date');?></th>
|
||||
<th><?= lang('Events_TableHead_EventType');?></th>
|
||||
<th><?= lang('Events_TableHead_Connection');?></th>
|
||||
<th><?= lang('Events_TableHead_Disconnection');?></th>
|
||||
<th><?= lang('Events_TableHead_Duration');?></th>
|
||||
<th><?= lang('Events_TableHead_DurationOrder');?></th>
|
||||
<th><?= lang('Events_TableHead_IP');?></th>
|
||||
<th><?= lang('Events_TableHead_IPOrder');?></th>
|
||||
<th><?= lang('Events_TableHead_AdditionalInfo');?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
@@ -188,7 +188,7 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
function main () {
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get¶meter='+ parPeriod, function(data) {
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=1 day¶meter='+ parPeriod, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
if (result) {
|
||||
period = result;
|
||||
@@ -196,7 +196,7 @@ function main () {
|
||||
}
|
||||
|
||||
// get parameter value
|
||||
$.get('php/server/parameters.php?action=get¶meter='+ parTableRows, function(data) {
|
||||
$.get('php/server/parameters.php?action=get&defaultValue=50¶meter='+ parTableRows, function(data) {
|
||||
var result = JSON.parse(data);
|
||||
result = parseInt(result, 10)
|
||||
if (Number.isInteger (result) ) {
|
||||
@@ -253,13 +253,13 @@ function initializeDatatable () {
|
||||
'language' : {
|
||||
processing: '<table><td width="130px" align="middle">Loading...</td><td><i class="ion ion-ios-loop-strong fa-spin fa-2x fa-fw"></td></table>',
|
||||
emptyTable: 'No data',
|
||||
"lengthMenu": "<?php echo lang('Events_Tablelenght');?>",
|
||||
"search": "<?php echo lang('Events_Searchbox');?>: ",
|
||||
"lengthMenu": "<?= lang('Events_Tablelenght');?>",
|
||||
"search": "<?= lang('Events_Searchbox');?>: ",
|
||||
"paginate": {
|
||||
"next": "<?php echo lang('Events_Table_nav_next');?>",
|
||||
"previous": "<?php echo lang('Events_Table_nav_prev');?>"
|
||||
"next": "<?= lang('Events_Table_nav_next');?>",
|
||||
"previous": "<?= lang('Events_Table_nav_prev');?>"
|
||||
},
|
||||
"info": "<?php echo lang('Events_Table_info');?>",
|
||||
"info": "<?= lang('Events_Table_info');?>",
|
||||
}
|
||||
});
|
||||
|
||||
@@ -311,13 +311,13 @@ function getEvents (p_eventsType) {
|
||||
|
||||
// Define color & title for the status selected
|
||||
switch (eventsType) {
|
||||
case 'all': tableTitle = '<?php echo lang('Events_Shortcut_AllEvents');?>'; color = 'aqua'; sesionCols = false; break;
|
||||
case 'sessions': tableTitle = '<?php echo lang('Events_Shortcut_Sessions');?>'; color = 'green'; sesionCols = true; break;
|
||||
case 'missing': tableTitle = '<?php echo lang('Events_Shortcut_MissSessions');?>'; color = 'yellow'; sesionCols = true; break;
|
||||
case 'voided': tableTitle = '<?php echo lang('Events_Shortcut_VoidSessions');?>'; color = 'yellow'; sesionCols = false; break;
|
||||
case 'new': tableTitle = '<?php echo lang('Events_Shortcut_NewDevices');?>'; color = 'yellow'; sesionCols = false; break;
|
||||
case 'down': tableTitle = '<?php echo lang('Events_Shortcut_DownAlerts');?>'; color = 'red'; sesionCols = false; break;
|
||||
default: tableTitle = '<?php echo lang('Events_Shortcut_Events');?>'; boxClass = ''; sesionCols = false; break;
|
||||
case 'all': tableTitle = '<?= lang('Events_Shortcut_AllEvents');?>'; color = 'aqua'; sesionCols = false; break;
|
||||
case 'sessions': tableTitle = '<?= lang('Events_Shortcut_Sessions');?>'; color = 'green'; sesionCols = true; break;
|
||||
case 'missing': tableTitle = '<?= lang('Events_Shortcut_MissSessions');?>'; color = 'yellow'; sesionCols = true; break;
|
||||
case 'voided': tableTitle = '<?= lang('Events_Shortcut_VoidSessions');?>'; color = 'yellow'; sesionCols = false; break;
|
||||
case 'new': tableTitle = '<?= lang('Events_Shortcut_NewDevices');?>'; color = 'yellow'; sesionCols = false; break;
|
||||
case 'down': tableTitle = '<?= lang('Events_Shortcut_DownAlerts');?>'; color = 'red'; sesionCols = false; break;
|
||||
default: tableTitle = '<?= lang('Events_Shortcut_Events');?>'; boxClass = ''; sesionCols = false; break;
|
||||
}
|
||||
|
||||
// Set title and color
|
||||
|
||||
@@ -8,39 +8,46 @@
|
||||
<section class="content-header">
|
||||
<?php require 'php/templates/notification.php'; ?>
|
||||
<h1 id="pageTitle">
|
||||
<?php echo lang('HelpFAQ_Title');?>
|
||||
<?= lang('HelpFAQ_Title');?>
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<!-- Main content ---------------------------------------------------------- -->
|
||||
<section class="content">
|
||||
<h4><?php echo lang('HelpFAQ_Cat_General');?></h4>
|
||||
<h4><?= lang('HelpFAQ_Cat_General');?></h4>
|
||||
|
||||
<div class="panel-group" id="accordion_gen">
|
||||
<div class="panel panel-default">
|
||||
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse100">
|
||||
<?php echo lang('HelpFAQ_Cat_General_100_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_General_100_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
|
||||
<div id="collapse100" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body"><?php echo lang('HelpFAQ_Cat_General_100_text_a');?>
|
||||
<div class="panel-body"><?= lang('HelpFAQ_Cat_General_100_text_a');?>
|
||||
<span class="text-danger help_faq_code"><?php echo date_default_timezone_get(); ?></span><br>
|
||||
<?php echo lang('HelpFAQ_Cat_General_100_text_b');?>
|
||||
<?= lang('HelpFAQ_Cat_General_100_text_b');?>
|
||||
<span class="text-danger help_faq_code"><?php echo php_ini_loaded_file(); ?></span><br>
|
||||
<?php echo lang('HelpFAQ_Cat_General_100_text_c');?></div>
|
||||
<?= lang('HelpFAQ_Cat_General_100_text_c');?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse101">
|
||||
<?php echo lang('HelpFAQ_Cat_General_101_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_General_101_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse101" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_General_101_text');?>
|
||||
<?= lang('HelpFAQ_Cat_General_101_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,12 +55,12 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse102">
|
||||
<?php echo lang('HelpFAQ_Cat_General_102_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_General_102_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse102" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_General_102_text');?>
|
||||
<?= lang('HelpFAQ_Cat_General_102_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -61,12 +68,12 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse102docker">
|
||||
<?php echo lang('HelpFAQ_Cat_General_102docker_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_General_102docker_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse102docker" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_General_102docker_text');?>
|
||||
<?= lang('HelpFAQ_Cat_General_102docker_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,48 +81,48 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_gen" href="#collapse103">
|
||||
<?php echo lang('HelpFAQ_Cat_General_103_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_General_103_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse103" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_General_103_text');?>
|
||||
<?= lang('HelpFAQ_Cat_General_103_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4><?php echo lang('Navigation_Devices');?></h4>
|
||||
<h4><?= lang('Navigation_Devices');?></h4>
|
||||
<div class="panel-group" id="accordion_dev">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_dev" href="#collapse200">
|
||||
<?php echo lang('HelpFAQ_Cat_Device_200_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Device_200_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse200" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Device_200_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Device_200_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<h4><?php echo lang('HelpFAQ_Cat_Detail');?></h4>
|
||||
<h4><?= lang('HelpFAQ_Cat_Detail');?></h4>
|
||||
<div class="panel-group" id="accordion_det">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse300">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_300_head');?> "<?php echo lang('DevDetail_MainInfo_Network');?>" / "<?php echo lang('DevDetail_MainInfo_Network_Port');?>"?</a>
|
||||
<?= lang('HelpFAQ_Cat_Detail_300_head');?> "<?= lang('DevDetail_MainInfo_Network');?>" / "<?= lang('DevDetail_MainInfo_Network_Port');?>"?</a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse300" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
"<?php echo lang('DevDetail_MainInfo_Network');?>" <?php echo lang('HelpFAQ_Cat_Detail_300_text_a');?><br>
|
||||
"<?php echo lang('DevDetail_MainInfo_Network_Port');?>" <?php echo lang('HelpFAQ_Cat_Detail_300_text_b');?>
|
||||
"<?= lang('DevDetail_MainInfo_Network');?>" <?= lang('HelpFAQ_Cat_Detail_300_text_a');?><br>
|
||||
"<?= lang('DevDetail_MainInfo_Network_Port');?>" <?= lang('HelpFAQ_Cat_Detail_300_text_b');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -123,12 +130,12 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse301">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_301_head_a');?> "<?php echo lang('DevDetail_EveandAl_ScanCycle');?>" <?php echo lang('HelpFAQ_Cat_Detail_301_head_b');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Detail_301_head_a');?> "<?= lang('DevDetail_EveandAl_ScanCycle');?>" <?= lang('HelpFAQ_Cat_Detail_301_head_b');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse301" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_301_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Detail_301_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -136,12 +143,12 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse302">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_302_head_a');?> "<?php echo lang('DevDetail_EveandAl_RandomMAC');?>" <?php echo lang('HelpFAQ_Cat_Detail_302_head_b');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Detail_302_head_a');?> "<?= lang('DevDetail_EveandAl_RandomMAC');?>" <?= lang('HelpFAQ_Cat_Detail_302_head_b');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse302" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_302_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Detail_302_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -149,29 +156,29 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_det" href="#collapse303">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_303_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Detail_303_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse303" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Detail_303_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Detail_303_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4><?php echo lang('Navigation_Presence');?></h4>
|
||||
<h4><?= lang('Navigation_Presence');?></h4>
|
||||
<div class="panel-group" id="accordion_pre">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_pre" href="#collapse400">
|
||||
<?php echo lang('HelpFAQ_Cat_Presence_400_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Presence_400_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse400" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Presence_400_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Presence_400_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -179,29 +186,29 @@
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_pre" href="#collapse401">
|
||||
<?php echo lang('HelpFAQ_Cat_Presence_401_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Presence_401_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse401" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Presence_401_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Presence_401_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h4><?php echo lang('Navigation_Network');?></h4>
|
||||
<h4><?= lang('Navigation_Network');?></h4>
|
||||
<div class="panel-group" id="accordion_net">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">
|
||||
<a data-toggle="collapse" data-parent="#accordion_net" href="#collapse600">
|
||||
<?php echo lang('HelpFAQ_Cat_Network_600_head');?></a>
|
||||
<?= lang('HelpFAQ_Cat_Network_600_head');?></a>
|
||||
</h4>
|
||||
</div>
|
||||
<div id="collapse600" class="panel-collapse collapse" style="font-size: 16px;">
|
||||
<div class="panel-body">
|
||||
<?php echo lang('HelpFAQ_Cat_Network_600_text');?>
|
||||
<?= lang('HelpFAQ_Cat_Network_600_text');?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,32 +1,43 @@
|
||||
<!-- Pi.Alert CSS -->
|
||||
<link rel="stylesheet" href="css/pialert.css">
|
||||
|
||||
<?php
|
||||
|
||||
|
||||
require 'php/templates/language/lang.php';
|
||||
require 'php/templates/skinUI.php';
|
||||
require dirname(__FILE__).'/php/server/init.php';
|
||||
require 'php/templates/security.php';
|
||||
|
||||
|
||||
|
||||
if ($Pia_WebProtection != 'true')
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
exit;
|
||||
}
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
exit;
|
||||
}
|
||||
|
||||
// Logout
|
||||
if (isset ($_GET["action"]) && $_GET["action"] == 'logout')
|
||||
{
|
||||
setcookie("PiAlert_SaveLogin", '', time()+1); // reset cookie
|
||||
$_SESSION["login"] = 0;
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Password without Cookie check -> pass and set initial cookie
|
||||
if (isset ($_POST["loginpassword"]) && $Pia_Password == hash('sha256',$_POST["loginpassword"]))
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
|
||||
}
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
|
||||
}
|
||||
|
||||
// active Session or valid cookie (cookie not extends)
|
||||
if (( isset ($_SESSION["login"]) && ($_SESSION["login"] == 1)) || (isset ($_COOKIE["PiAlert_SaveLogin"]) && $Pia_Password == $_COOKIE["PiAlert_SaveLogin"]))
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
|
||||
}
|
||||
{
|
||||
header('Location: devices.php');
|
||||
$_SESSION["login"] = 1;
|
||||
if (isset($_POST['PWRemember'])) {setcookie("PiAlert_SaveLogin", hash('sha256',$_POST["loginpassword"]), time()+604800);}
|
||||
}
|
||||
|
||||
$login_headline = lang('Login_Toggle_Info_headline');
|
||||
$login_info = "";
|
||||
@@ -36,22 +47,22 @@ $login_icon = 'fa-info';
|
||||
|
||||
// no active session, cookie not checked
|
||||
if (isset ($_SESSION["login"]) == FALSE || $_SESSION["login"] != 1)
|
||||
{
|
||||
if ($Pia_Password == '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92')
|
||||
{
|
||||
if ($Pia_Password == '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92')
|
||||
{
|
||||
$login_info = lang('Login_Default_PWD');
|
||||
$login_mode = 'danger';
|
||||
$login_display_mode = 'display: block;';
|
||||
$login_headline = lang('Login_Toggle_Alert_headline');
|
||||
$login_icon = 'fa-ban';
|
||||
}
|
||||
else
|
||||
{
|
||||
$login_mode = 'info';
|
||||
$login_display_mode = 'display: none;';
|
||||
$login_headline = lang('Login_Toggle_Info_headline');
|
||||
$login_icon = 'fa-info';
|
||||
}
|
||||
$login_info = lang('Login_Default_PWD');
|
||||
$login_mode = 'danger';
|
||||
$login_display_mode = 'display: block;';
|
||||
$login_headline = lang('Login_Toggle_Alert_headline');
|
||||
$login_icon = 'fa-ban';
|
||||
}
|
||||
else
|
||||
{
|
||||
$login_mode = 'info';
|
||||
$login_display_mode = 'display: none;';
|
||||
$login_headline = lang('Login_Toggle_Info_headline');
|
||||
$login_icon = 'fa-info';
|
||||
}
|
||||
}
|
||||
|
||||
// ##################################################
|
||||
@@ -92,16 +103,16 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<link rel="stylesheet" href="/front/css/offline-font.css">
|
||||
</head>
|
||||
<body class="hold-transition login-page">
|
||||
<div class="login-box">
|
||||
<div class="login-box login-custom">
|
||||
<div class="login-logo">
|
||||
<a href="/index2.php">Pi.<b>Alert</b></a>
|
||||
</div>
|
||||
<!-- /.login-logo -->
|
||||
<div class="login-box-body">
|
||||
<p class="login-box-msg"><?php echo lang('Login_Box');?></p>
|
||||
<p class="login-box-msg"><?= lang('Login_Box');?></p>
|
||||
<form action="index.php" method="post">
|
||||
<div class="form-group has-feedback">
|
||||
<input type="password" class="form-control" placeholder="<?php echo lang('Login_Psw-box');?>" name="loginpassword">
|
||||
<input type="password" class="form-control" placeholder="<?= lang('Login_Psw-box');?>" name="loginpassword">
|
||||
<span class="glyphicon glyphicon-lock form-control-feedback"></span>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -110,21 +121,21 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<label>
|
||||
<input type="checkbox" name="PWRemember">
|
||||
<div style="margin-left: 10px; display: inline-block; vertical-align: top;">
|
||||
<?php echo lang('Login_Remember');?><br><span style="font-size: smaller"><?php echo lang('Login_Remember_small');?></span>
|
||||
<?= lang('Login_Remember');?><br><span style="font-size: smaller"><?= lang('Login_Remember_small');?></span>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
<div class="col-xs-4" style="padding-top: 10px;">
|
||||
<button type="submit" class="btn btn-primary btn-block btn-flat"><?php echo lang('Login_Submit');?></button>
|
||||
<button type="submit" class="btn btn-primary btn-block btn-flat"><?= lang('Login_Submit');?></button>
|
||||
</div>
|
||||
<!-- /.col -->
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div style="padding-top: 10px;">
|
||||
<button class="btn btn-xs btn-primary btn-block btn-flat" onclick="Passwordhinfo()"><?php echo lang('Login_Toggle_Info');?></button>
|
||||
<button class="btn btn-xs btn-primary btn-block btn-flat" onclick="Passwordhinfo()"><?= lang('Login_Toggle_Info');?></button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -137,7 +148,7 @@ if ($ENABLED_DARKMODE === True) {
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true"><3E></button>
|
||||
<h4><i class="icon fa <?php echo $login_icon;?>"></i><?php echo $login_headline;?></h4>
|
||||
<p><?php echo $login_info;?></p>
|
||||
<p><?php echo lang('Login_Psw_run');?><br><span style="border: solid 1px yellow; padding: 2px;">./reset_password.sh <?php echo lang('Login_Psw_new');?></span><br><?php echo lang('Login_Psw_folder');?></p>
|
||||
<p><?= lang('Login_Psw_run');?><br><span style="border: solid 1px yellow; padding: 2px;"> /home/pi/pialert/back/pialert-cli set_password <?= lang('Login_Psw_new');?></span><br><?= lang('Login_Psw_folder');?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
68
front/js/handle_version.js
Executable file
@@ -0,0 +1,68 @@
|
||||
function handleVersion(){
|
||||
|
||||
release_timestamp = getCookie("release_timestamp")
|
||||
|
||||
if(release_timestamp != "")
|
||||
{
|
||||
|
||||
build_timestamp = parseInt($('#version').attr("data-build-time").match( /\d+/g ).join(''))
|
||||
|
||||
// if the release_timestamp is older by 10 min or more as the build timestamp then there is a new release available
|
||||
if(release_timestamp > build_timestamp + 600 )
|
||||
{
|
||||
console.log("New release!")
|
||||
// handling the navigation menu icon
|
||||
$('#version').attr("class", $('#version').attr("class").replace("myhidden", ""))
|
||||
|
||||
maintenanceDiv = $('#new-version-text')
|
||||
}
|
||||
else{
|
||||
console.log("All up-to-date!")
|
||||
|
||||
maintenanceDiv = $('#current-version-text')
|
||||
}
|
||||
|
||||
// handling the maintenance section message
|
||||
if(emptyArr.includes(maintenanceDiv) == false && $(maintenanceDiv).length != 0)
|
||||
{
|
||||
$(maintenanceDiv).attr("class", $(maintenanceDiv).attr("class").replace("myhidden", ""))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------
|
||||
|
||||
function getVersion()
|
||||
{
|
||||
release_timestamp = getCookie("release_timestamp")
|
||||
|
||||
// no cached value available
|
||||
if(release_timestamp == "")
|
||||
{
|
||||
// get parameter value
|
||||
$.get('https://api.github.com/repos/jokob-sk/Pi.Alert/releases', function(data) {
|
||||
|
||||
var releases = data;
|
||||
|
||||
if(releases.length > 0)
|
||||
{
|
||||
release_datetime = releases[0].published_at;
|
||||
release_timestamp = new Date(release_datetime).getTime() / 1000;
|
||||
|
||||
// cache value
|
||||
setCookie("release_timestamp", release_timestamp, 30);
|
||||
|
||||
handleVersion();
|
||||
}
|
||||
});
|
||||
} else
|
||||
{
|
||||
// cache is available, just call the handler
|
||||
handleVersion()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// handle the dispaly of the NEW icon
|
||||
getVersion()
|
||||
@@ -10,36 +10,46 @@
|
||||
// -----------------------------------------------------------------------------
|
||||
var timerRefreshData = ''
|
||||
var modalCallbackFunction = '';
|
||||
var emptyArr = ['undefined', "", undefined, null, 'null'];
|
||||
|
||||
// urlParams = new Proxy(new URLSearchParams(window.location.search), {
|
||||
// get: (searchParams, prop) => searchParams.get(prop.toString()),
|
||||
// });
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Simple session cache withe expiration managed via cookies
|
||||
// -----------------------------------------------------------------------------
|
||||
function getCache(key)
|
||||
{
|
||||
// check cache
|
||||
if(sessionStorage.getItem(key))
|
||||
{
|
||||
return sessionStorage.getItem(key);
|
||||
} else
|
||||
{
|
||||
return "";
|
||||
// check if not expired
|
||||
if(getCookie(key + '_session_expiry') != "")
|
||||
{
|
||||
return sessionStorage.getItem(key);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
function setCache(key, data)
|
||||
// -----------------------------------------------------------------------------
|
||||
function setCache(key, data, expirationMinutes='')
|
||||
{
|
||||
sessionStorage.setItem(key, data);
|
||||
setCookie (key + '_session_expiry', 'OK', expirationMinutes='')
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function setCookie (cookie, value, expirationHours='') {
|
||||
function setCookie (cookie, value, expirationMinutes='') {
|
||||
// Calc expiration date
|
||||
var expires = '';
|
||||
if (typeof expirationHours === 'number') {
|
||||
expires = ';expires=' + new Date(Date.now() + expirationHours *60*60*1000).toUTCString();
|
||||
}
|
||||
if (typeof expirationMinutes === 'number') {
|
||||
expires = ';expires=' + new Date(Date.now() + expirationMinutes *60*1000).toUTCString();
|
||||
}
|
||||
|
||||
// Save Cookie
|
||||
document.cookie = cookie + "=" + value + expires;
|
||||
@@ -86,7 +96,8 @@ function deleteAllCookies() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Modal dialog handling
|
||||
// -----------------------------------------------------------------------------
|
||||
function showModalOk (title, message, callbackFunction = null) {
|
||||
// set captions
|
||||
@@ -116,6 +127,24 @@ function showModalDefault (title, message, btnCancel, btnOK, callbackFunction) {
|
||||
$('#modal-default').modal('show');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function showModalDefaultStrParam (title, message, btnCancel, btnOK, callbackFunction, param='') {
|
||||
// set captions
|
||||
$('#modal-str-title').html (title);
|
||||
$('#modal-str-message').html (message);
|
||||
$('#modal-str-cancel').html (btnCancel);
|
||||
$('#modal-str-OK').html (btnOK);
|
||||
$("#modal-str-OK").off("click"); //remove existing handlers
|
||||
$('#modal-str-OK').on('click', function (){
|
||||
$('#modal-str').modal('hide');
|
||||
callbackFunction(param)
|
||||
})
|
||||
|
||||
// Show modal
|
||||
$('#modal-str').modal('show');
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function showModalWarning (title, message, btnCancel, btnOK, callbackFunction) {
|
||||
// set captions
|
||||
@@ -151,13 +180,6 @@ function modalWarningOK () {
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
function sanitize(data)
|
||||
{
|
||||
return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function showMessage (textMessage="") {
|
||||
if (textMessage.toLowerCase().includes("error") ) {
|
||||
@@ -175,6 +197,22 @@ function showMessage (textMessage="") {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// General utilities
|
||||
// -----------------------------------------------------------------------------
|
||||
// remove unnecessary lines from the result
|
||||
function sanitize(data)
|
||||
{
|
||||
return data.replace(/(\r\n|\n|\r)/gm,"").replace(/[^\x00-\x7F]/g, "")
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function numberArrayFromString(data)
|
||||
{
|
||||
data = JSON.parse(sanitize(data));
|
||||
return data.replace(/\[|\]/g, '').split(',').map(Number);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function setParameter (parameter, value) {
|
||||
// Retry
|
||||
@@ -186,18 +224,52 @@ function setParameter (parameter, value) {
|
||||
sleep (200);
|
||||
$.get('php/server/parameters.php?action=set¶meter=' + parameter +
|
||||
'&value='+ value,
|
||||
function(data) {
|
||||
if (data != "OK") {
|
||||
// alert (data);
|
||||
} else {
|
||||
// alert ("OK. Second attempt");
|
||||
};
|
||||
function(data) {
|
||||
if (data != "OK") {
|
||||
// alert (data);
|
||||
} else {
|
||||
// alert ("OK. Second attempt");
|
||||
};
|
||||
} );
|
||||
};
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function saveData(functionName, id, value) {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
url: "php/server/devices.php",
|
||||
data: { action: functionName, id: id, value:value },
|
||||
success: function(data) {
|
||||
|
||||
if(sanitize(data) == 'OK')
|
||||
{
|
||||
showMessage("Saved")
|
||||
// Remove navigation prompt "Are you sure you want to leave..."
|
||||
window.onbeforeunload = null;
|
||||
} else
|
||||
{
|
||||
showMessage("ERROR")
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// remove an item from an array
|
||||
function removeItemFromArray(arr, value) {
|
||||
var index = arr.indexOf(value);
|
||||
if (index > -1) {
|
||||
arr.splice(index, 1);
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function sleep(milliseconds) {
|
||||
const date = Date.now();
|
||||
@@ -207,15 +279,41 @@ function sleep(milliseconds) {
|
||||
} while (currentDate - date < milliseconds);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
somethingChanged = false;
|
||||
function settingsChanged()
|
||||
{
|
||||
somethingChanged = true;
|
||||
// Enable navigation prompt ... "Are you sure you want to leave..."
|
||||
window.onbeforeunload = function() {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function getQueryString(key){
|
||||
params = new Proxy(new URLSearchParams(window.location.search), {
|
||||
get: (searchParams, prop) => searchParams.get(prop),
|
||||
});
|
||||
|
||||
tmp = params[key]
|
||||
|
||||
result = emptyArr.includes(tmp) ? "" : tmp;
|
||||
|
||||
return result
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
function translateHTMLcodes (text) {
|
||||
if (text == null) {
|
||||
if (text == null || emptyArr.includes(text)) {
|
||||
return null;
|
||||
} else if (typeof text === 'string' || text instanceof String)
|
||||
{
|
||||
var text2 = text.replace(new RegExp(' ', 'g'), " ");
|
||||
text2 = text2.replace(new RegExp('<', 'g'), "<");
|
||||
return text2;
|
||||
}
|
||||
var text2 = text.replace(new RegExp(' ', 'g'), " ");
|
||||
text2 = text2.replace(new RegExp('<', 'g'), "<");
|
||||
return text2;
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
@@ -247,4 +345,30 @@ function openInNewTab (url) {
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
function navigateToDeviceWithIp (ip) {
|
||||
|
||||
$.get('api/table_devices.json', function(res) {
|
||||
|
||||
devices = res["data"];
|
||||
|
||||
mac = ""
|
||||
|
||||
$.each(devices, function(index, obj) {
|
||||
|
||||
if(obj.dev_LastIP.trim() == ip.trim())
|
||||
{
|
||||
mac = obj.dev_MAC;
|
||||
|
||||
window.open(window.location.origin +'/deviceDetails.php?mac=' + mac , "_blank");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "font-awesome",
|
||||
"description": "Font Awesome",
|
||||
"keywords": [],
|
||||
"homepage": "http://fontawesome.io",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"license": [
|
||||
"OFL-1.1",
|
||||
"MIT",
|
||||
"CC-BY-3.0"
|
||||
],
|
||||
"main": [
|
||||
"less/font-awesome.less",
|
||||
"scss/font-awesome.scss"
|
||||
],
|
||||
"ignore": [
|
||||
"*/.*",
|
||||
"*.json",
|
||||
"src",
|
||||
"*.yml",
|
||||
"Gemfile",
|
||||
"Gemfile.lock",
|
||||
"*.md"
|
||||
],
|
||||
"version": "4.7.0",
|
||||
"_release": "4.7.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v4.7.0",
|
||||
"commit": "a3fe90fa5f6fac55d197f9cbd18e3f57dafb716c"
|
||||
},
|
||||
"_source": "https://github.com/FortAwesome/Font-Awesome.git",
|
||||
"_target": "^4.7",
|
||||
"_originalSource": "font-awesome"
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
*.pyc
|
||||
*.egg-info
|
||||
*.db
|
||||
*.db.old
|
||||
*.swp
|
||||
*.db-journal
|
||||
|
||||
.coverage
|
||||
.DS_Store
|
||||
.installed.cfg
|
||||
_gh_pages/*
|
||||
|
||||
.idea/*
|
||||
.svn/*
|
||||
src/website/static/*
|
||||
src/website/media/*
|
||||
|
||||
bin
|
||||
cfcache
|
||||
develop-eggs
|
||||
dist
|
||||
downloads
|
||||
eggs
|
||||
parts
|
||||
tmp
|
||||
.sass-cache
|
||||
node_modules
|
||||
|
||||
src/website/settingslocal.py
|
||||
stunnel.log
|
||||
|
||||
.ruby-version
|
||||
|
||||
# don't need these in the npm package.
|
||||
src/
|
||||
_config.yml
|
||||
bower.json
|
||||
component.json
|
||||
composer.json
|
||||
CONTRIBUTING.md
|
||||
Gemfile
|
||||
Gemfile.lock
|
||||
@@ -1,7 +0,0 @@
|
||||
I hope you love Font Awesome. If you've found it useful, please do me a favor and check out my latest project,
|
||||
Fort Awesome (https://fortawesome.com). It makes it easy to put the perfect icons on your website. Choose from our awesome,
|
||||
comprehensive icon sets or copy and paste your own.
|
||||
|
||||
Please. Check it out.
|
||||
|
||||
-Dave Gandy
|
||||
165
front/lib/AdminLTE/bower_components/font-awesome/LICENSE.txt
vendored
Executable file
@@ -0,0 +1,165 @@
|
||||
Fonticons, Inc. (https://fontawesome.com)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Font Awesome Free License
|
||||
|
||||
Font Awesome Free is free, open source, and GPL friendly. You can use it for
|
||||
commercial projects, open source projects, or really almost whatever you want.
|
||||
Full Font Awesome Free license: https://fontawesome.com/license/free.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Icons: CC BY 4.0 License (https://creativecommons.org/licenses/by/4.0/)
|
||||
|
||||
The Font Awesome Free download is licensed under a Creative Commons
|
||||
Attribution 4.0 International License and applies to all icons packaged
|
||||
as SVG and JS file types.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Fonts: SIL OFL 1.1 License
|
||||
|
||||
In the Font Awesome Free download, the SIL OFL license applies to all icons
|
||||
packaged as web and desktop font files.
|
||||
|
||||
Copyright (c) 2022 Fonticons, Inc. (https://fontawesome.com)
|
||||
with Reserved Font Name: "Font Awesome".
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
SIL OPEN FONT LICENSE
|
||||
Version 1.1 - 26 February 2007
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting — in part or in whole — any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Code: MIT License (https://opensource.org/licenses/MIT)
|
||||
|
||||
In the Font Awesome Free download, the MIT license applies to all non-font and
|
||||
non-icon files.
|
||||
|
||||
Copyright 2022 Fonticons, Inc.
|
||||
|
||||
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.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Attribution
|
||||
|
||||
Attribution is required by MIT, SIL OFL, and CC BY licenses. Downloaded Font
|
||||
Awesome Free files already contain embedded comments with sufficient
|
||||
attribution, so you shouldn't need to do anything additional when using these
|
||||
files normally.
|
||||
|
||||
We've kept attribution comments terse, so we ask that you do not actively work
|
||||
to remove them from files, especially code. They're a great way for folks to
|
||||
learn about Font Awesome.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
# Brand Icons
|
||||
|
||||
All brand icons are trademarks of their respective owners. The use of these
|
||||
trademarks does not indicate endorsement of the trademark holder by Font
|
||||
Awesome, nor vice versa. **Please do not use brand logos for any purpose except
|
||||
to represent the company, product, or service to which they refer.**
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "font-awesome",
|
||||
"description": "Font Awesome",
|
||||
"keywords": [],
|
||||
"homepage": "http://fontawesome.io",
|
||||
"dependencies": {},
|
||||
"devDependencies": {},
|
||||
"license": ["OFL-1.1", "MIT", "CC-BY-3.0"],
|
||||
"main": [
|
||||
"less/font-awesome.less",
|
||||
"scss/font-awesome.scss"
|
||||
],
|
||||
"ignore": [
|
||||
"*/.*",
|
||||
"*.json",
|
||||
"src",
|
||||
"*.yml",
|
||||
"Gemfile",
|
||||
"Gemfile.lock",
|
||||
"*.md"
|
||||
]
|
||||
}
|
||||
7946
front/lib/AdminLTE/bower_components/font-awesome/css/all.css
vendored
Executable file
6
front/lib/AdminLTE/bower_components/font-awesome/css/all.min.css
vendored
Executable file
1516
front/lib/AdminLTE/bower_components/font-awesome/css/brands.css
vendored
Executable file
6
front/lib/AdminLTE/bower_components/font-awesome/css/brands.min.css
vendored
Executable file
6369
front/lib/AdminLTE/bower_components/font-awesome/css/fontawesome.css
vendored
Executable file
6
front/lib/AdminLTE/bower_components/font-awesome/css/fontawesome.min.css
vendored
Executable file
19
front/lib/AdminLTE/bower_components/font-awesome/css/regular.css
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
||||
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Free'; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
|
||||
|
||||
.far,
|
||||
.fa-regular {
|
||||
font-weight: 400; }
|
||||
6
front/lib/AdminLTE/bower_components/font-awesome/css/regular.min.css
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-regular:normal 400 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}.fa-regular,.far{font-weight:400}
|
||||
19
front/lib/AdminLTE/bower_components/font-awesome/css/solid.css
vendored
Executable file
@@ -0,0 +1,19 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-style-family-classic: 'Font Awesome 6 Free';
|
||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Free'; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
.fas,
|
||||
.fa-solid {
|
||||
font-weight: 900; }
|
||||
6
front/lib/AdminLTE/bower_components/font-awesome/css/solid.min.css
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}
|
||||
635
front/lib/AdminLTE/bower_components/font-awesome/css/svg-with-js.css
vendored
Executable file
@@ -0,0 +1,635 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
:root, :host {
|
||||
--fa-font-solid: normal 900 1em/1 'Font Awesome 6 Solid';
|
||||
--fa-font-regular: normal 400 1em/1 'Font Awesome 6 Regular';
|
||||
--fa-font-light: normal 300 1em/1 'Font Awesome 6 Light';
|
||||
--fa-font-thin: normal 100 1em/1 'Font Awesome 6 Thin';
|
||||
--fa-font-duotone: normal 900 1em/1 'Font Awesome 6 Duotone';
|
||||
--fa-font-sharp-solid: normal 900 1em/1 'Font Awesome 6 Sharp';
|
||||
--fa-font-brands: normal 400 1em/1 'Font Awesome 6 Brands'; }
|
||||
|
||||
svg:not(:root).svg-inline--fa, svg:not(:host).svg-inline--fa {
|
||||
overflow: visible;
|
||||
box-sizing: content-box; }
|
||||
|
||||
.svg-inline--fa {
|
||||
display: var(--fa-display, inline-block);
|
||||
height: 1em;
|
||||
overflow: visible;
|
||||
vertical-align: -.125em; }
|
||||
.svg-inline--fa.fa-2xs {
|
||||
vertical-align: 0.1em; }
|
||||
.svg-inline--fa.fa-xs {
|
||||
vertical-align: 0em; }
|
||||
.svg-inline--fa.fa-sm {
|
||||
vertical-align: -0.07143em; }
|
||||
.svg-inline--fa.fa-lg {
|
||||
vertical-align: -0.2em; }
|
||||
.svg-inline--fa.fa-xl {
|
||||
vertical-align: -0.25em; }
|
||||
.svg-inline--fa.fa-2xl {
|
||||
vertical-align: -0.3125em; }
|
||||
.svg-inline--fa.fa-pull-left {
|
||||
margin-right: var(--fa-pull-margin, 0.3em);
|
||||
width: auto; }
|
||||
.svg-inline--fa.fa-pull-right {
|
||||
margin-left: var(--fa-pull-margin, 0.3em);
|
||||
width: auto; }
|
||||
.svg-inline--fa.fa-li {
|
||||
width: var(--fa-li-width, 2em);
|
||||
top: 0.25em; }
|
||||
.svg-inline--fa.fa-fw {
|
||||
width: var(--fa-fw-width, 1.25em); }
|
||||
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0; }
|
||||
|
||||
.fa-layers-text, .fa-layers-counter {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
text-align: center; }
|
||||
|
||||
.fa-layers {
|
||||
display: inline-block;
|
||||
height: 1em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
vertical-align: -.125em;
|
||||
width: 1em; }
|
||||
.fa-layers svg.svg-inline--fa {
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center; }
|
||||
|
||||
.fa-layers-text {
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
transform: translate(-50%, -50%);
|
||||
-webkit-transform-origin: center center;
|
||||
transform-origin: center center; }
|
||||
|
||||
.fa-layers-counter {
|
||||
background-color: var(--fa-counter-background-color, #ff253a);
|
||||
border-radius: var(--fa-counter-border-radius, 1em);
|
||||
box-sizing: border-box;
|
||||
color: var(--fa-inverse, #fff);
|
||||
line-height: var(--fa-counter-line-height, 1);
|
||||
max-width: var(--fa-counter-max-width, 5em);
|
||||
min-width: var(--fa-counter-min-width, 1.5em);
|
||||
overflow: hidden;
|
||||
padding: var(--fa-counter-padding, 0.25em 0.5em);
|
||||
right: var(--fa-right, 0);
|
||||
text-overflow: ellipsis;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-counter-scale, 0.25));
|
||||
transform: scale(var(--fa-counter-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right; }
|
||||
|
||||
.fa-layers-bottom-right {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
right: var(--fa-right, 0);
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom right;
|
||||
transform-origin: bottom right; }
|
||||
|
||||
.fa-layers-bottom-left {
|
||||
bottom: var(--fa-bottom, 0);
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: auto;
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: bottom left;
|
||||
transform-origin: bottom left; }
|
||||
|
||||
.fa-layers-top-right {
|
||||
top: var(--fa-top, 0);
|
||||
right: var(--fa-right, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top right;
|
||||
transform-origin: top right; }
|
||||
|
||||
.fa-layers-top-left {
|
||||
left: var(--fa-left, 0);
|
||||
right: auto;
|
||||
top: var(--fa-top, 0);
|
||||
-webkit-transform: scale(var(--fa-layers-scale, 0.25));
|
||||
transform: scale(var(--fa-layers-scale, 0.25));
|
||||
-webkit-transform-origin: top left;
|
||||
transform-origin: top left; }
|
||||
|
||||
.fa-1x {
|
||||
font-size: 1em; }
|
||||
|
||||
.fa-2x {
|
||||
font-size: 2em; }
|
||||
|
||||
.fa-3x {
|
||||
font-size: 3em; }
|
||||
|
||||
.fa-4x {
|
||||
font-size: 4em; }
|
||||
|
||||
.fa-5x {
|
||||
font-size: 5em; }
|
||||
|
||||
.fa-6x {
|
||||
font-size: 6em; }
|
||||
|
||||
.fa-7x {
|
||||
font-size: 7em; }
|
||||
|
||||
.fa-8x {
|
||||
font-size: 8em; }
|
||||
|
||||
.fa-9x {
|
||||
font-size: 9em; }
|
||||
|
||||
.fa-10x {
|
||||
font-size: 10em; }
|
||||
|
||||
.fa-2xs {
|
||||
font-size: 0.625em;
|
||||
line-height: 0.1em;
|
||||
vertical-align: 0.225em; }
|
||||
|
||||
.fa-xs {
|
||||
font-size: 0.75em;
|
||||
line-height: 0.08333em;
|
||||
vertical-align: 0.125em; }
|
||||
|
||||
.fa-sm {
|
||||
font-size: 0.875em;
|
||||
line-height: 0.07143em;
|
||||
vertical-align: 0.05357em; }
|
||||
|
||||
.fa-lg {
|
||||
font-size: 1.25em;
|
||||
line-height: 0.05em;
|
||||
vertical-align: -0.075em; }
|
||||
|
||||
.fa-xl {
|
||||
font-size: 1.5em;
|
||||
line-height: 0.04167em;
|
||||
vertical-align: -0.125em; }
|
||||
|
||||
.fa-2xl {
|
||||
font-size: 2em;
|
||||
line-height: 0.03125em;
|
||||
vertical-align: -0.1875em; }
|
||||
|
||||
.fa-fw {
|
||||
text-align: center;
|
||||
width: 1.25em; }
|
||||
|
||||
.fa-ul {
|
||||
list-style-type: none;
|
||||
margin-left: var(--fa-li-margin, 2.5em);
|
||||
padding-left: 0; }
|
||||
.fa-ul > li {
|
||||
position: relative; }
|
||||
|
||||
.fa-li {
|
||||
left: calc(var(--fa-li-width, 2em) * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: var(--fa-li-width, 2em);
|
||||
line-height: inherit; }
|
||||
|
||||
.fa-border {
|
||||
border-color: var(--fa-border-color, #eee);
|
||||
border-radius: var(--fa-border-radius, 0.1em);
|
||||
border-style: var(--fa-border-style, solid);
|
||||
border-width: var(--fa-border-width, 0.08em);
|
||||
padding: var(--fa-border-padding, 0.2em 0.25em 0.15em); }
|
||||
|
||||
.fa-pull-left {
|
||||
float: left;
|
||||
margin-right: var(--fa-pull-margin, 0.3em); }
|
||||
|
||||
.fa-pull-right {
|
||||
float: right;
|
||||
margin-left: var(--fa-pull-margin, 0.3em); }
|
||||
|
||||
.fa-beat {
|
||||
-webkit-animation-name: fa-beat;
|
||||
animation-name: fa-beat;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
|
||||
|
||||
.fa-bounce {
|
||||
-webkit-animation-name: fa-bounce;
|
||||
animation-name: fa-bounce;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.28, 0.84, 0.42, 1)); }
|
||||
|
||||
.fa-fade {
|
||||
-webkit-animation-name: fa-fade;
|
||||
animation-name: fa-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
|
||||
|
||||
.fa-beat-fade {
|
||||
-webkit-animation-name: fa-beat-fade;
|
||||
animation-name: fa-beat-fade;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1));
|
||||
animation-timing-function: var(--fa-animation-timing, cubic-bezier(0.4, 0, 0.6, 1)); }
|
||||
|
||||
.fa-flip {
|
||||
-webkit-animation-name: fa-flip;
|
||||
animation-name: fa-flip;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, ease-in-out);
|
||||
animation-timing-function: var(--fa-animation-timing, ease-in-out); }
|
||||
|
||||
.fa-shake {
|
||||
-webkit-animation-name: fa-shake;
|
||||
animation-name: fa-shake;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear); }
|
||||
|
||||
.fa-spin {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-delay: var(--fa-animation-delay, 0s);
|
||||
animation-delay: var(--fa-animation-delay, 0s);
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 2s);
|
||||
animation-duration: var(--fa-animation-duration, 2s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, linear);
|
||||
animation-timing-function: var(--fa-animation-timing, linear); }
|
||||
|
||||
.fa-spin-reverse {
|
||||
--fa-animation-direction: reverse; }
|
||||
|
||||
.fa-pulse,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-name: fa-spin;
|
||||
animation-name: fa-spin;
|
||||
-webkit-animation-direction: var(--fa-animation-direction, normal);
|
||||
animation-direction: var(--fa-animation-direction, normal);
|
||||
-webkit-animation-duration: var(--fa-animation-duration, 1s);
|
||||
animation-duration: var(--fa-animation-duration, 1s);
|
||||
-webkit-animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
animation-iteration-count: var(--fa-animation-iteration-count, infinite);
|
||||
-webkit-animation-timing-function: var(--fa-animation-timing, steps(8));
|
||||
animation-timing-function: var(--fa-animation-timing, steps(8)); }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.fa-beat,
|
||||
.fa-bounce,
|
||||
.fa-fade,
|
||||
.fa-beat-fade,
|
||||
.fa-flip,
|
||||
.fa-pulse,
|
||||
.fa-shake,
|
||||
.fa-spin,
|
||||
.fa-spin-pulse {
|
||||
-webkit-animation-delay: -1ms;
|
||||
animation-delay: -1ms;
|
||||
-webkit-animation-duration: 1ms;
|
||||
animation-duration: 1ms;
|
||||
-webkit-animation-iteration-count: 1;
|
||||
animation-iteration-count: 1;
|
||||
transition-delay: 0s;
|
||||
transition-duration: 0s; } }
|
||||
|
||||
@-webkit-keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25)); } }
|
||||
|
||||
@keyframes fa-beat {
|
||||
0%, 90% {
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
45% {
|
||||
-webkit-transform: scale(var(--fa-beat-scale, 1.25));
|
||||
transform: scale(var(--fa-beat-scale, 1.25)); } }
|
||||
|
||||
@-webkit-keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); } }
|
||||
|
||||
@keyframes fa-bounce {
|
||||
0% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
10% {
|
||||
-webkit-transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-start-scale-x, 1.1), var(--fa-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% {
|
||||
-webkit-transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em));
|
||||
transform: scale(var(--fa-bounce-jump-scale-x, 0.9), var(--fa-bounce-jump-scale-y, 1.1)) translateY(var(--fa-bounce-height, -0.5em)); }
|
||||
50% {
|
||||
-webkit-transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0);
|
||||
transform: scale(var(--fa-bounce-land-scale-x, 1.05), var(--fa-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% {
|
||||
-webkit-transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em));
|
||||
transform: scale(1, 1) translateY(var(--fa-bounce-rebound, -0.125em)); }
|
||||
64% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); }
|
||||
100% {
|
||||
-webkit-transform: scale(1, 1) translateY(0);
|
||||
transform: scale(1, 1) translateY(0); } }
|
||||
|
||||
@-webkit-keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4); } }
|
||||
|
||||
@keyframes fa-fade {
|
||||
50% {
|
||||
opacity: var(--fa-fade-opacity, 0.4); } }
|
||||
|
||||
@-webkit-keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
|
||||
|
||||
@keyframes fa-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--fa-beat-fade-opacity, 0.4);
|
||||
-webkit-transform: scale(1);
|
||||
transform: scale(1); }
|
||||
50% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(var(--fa-beat-fade-scale, 1.125));
|
||||
transform: scale(var(--fa-beat-fade-scale, 1.125)); } }
|
||||
|
||||
@-webkit-keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
|
||||
|
||||
@keyframes fa-flip {
|
||||
50% {
|
||||
-webkit-transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg));
|
||||
transform: rotate3d(var(--fa-flip-x, 0), var(--fa-flip-y, 1), var(--fa-flip-z, 0), var(--fa-flip-angle, -180deg)); } }
|
||||
|
||||
@-webkit-keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg); }
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg); }
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg); }
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg); }
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg); }
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg); }
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg); }
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg); }
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); } }
|
||||
|
||||
@keyframes fa-shake {
|
||||
0% {
|
||||
-webkit-transform: rotate(-15deg);
|
||||
transform: rotate(-15deg); }
|
||||
4% {
|
||||
-webkit-transform: rotate(15deg);
|
||||
transform: rotate(15deg); }
|
||||
8%, 24% {
|
||||
-webkit-transform: rotate(-18deg);
|
||||
transform: rotate(-18deg); }
|
||||
12%, 28% {
|
||||
-webkit-transform: rotate(18deg);
|
||||
transform: rotate(18deg); }
|
||||
16% {
|
||||
-webkit-transform: rotate(-22deg);
|
||||
transform: rotate(-22deg); }
|
||||
20% {
|
||||
-webkit-transform: rotate(22deg);
|
||||
transform: rotate(22deg); }
|
||||
32% {
|
||||
-webkit-transform: rotate(-12deg);
|
||||
transform: rotate(-12deg); }
|
||||
36% {
|
||||
-webkit-transform: rotate(12deg);
|
||||
transform: rotate(12deg); }
|
||||
40%, 100% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); } }
|
||||
|
||||
@-webkit-keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg); } }
|
||||
|
||||
@keyframes fa-spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg); }
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
transform: rotate(360deg); } }
|
||||
|
||||
.fa-rotate-90 {
|
||||
-webkit-transform: rotate(90deg);
|
||||
transform: rotate(90deg); }
|
||||
|
||||
.fa-rotate-180 {
|
||||
-webkit-transform: rotate(180deg);
|
||||
transform: rotate(180deg); }
|
||||
|
||||
.fa-rotate-270 {
|
||||
-webkit-transform: rotate(270deg);
|
||||
transform: rotate(270deg); }
|
||||
|
||||
.fa-flip-horizontal {
|
||||
-webkit-transform: scale(-1, 1);
|
||||
transform: scale(-1, 1); }
|
||||
|
||||
.fa-flip-vertical {
|
||||
-webkit-transform: scale(1, -1);
|
||||
transform: scale(1, -1); }
|
||||
|
||||
.fa-flip-both,
|
||||
.fa-flip-horizontal.fa-flip-vertical {
|
||||
-webkit-transform: scale(-1, -1);
|
||||
transform: scale(-1, -1); }
|
||||
|
||||
.fa-rotate-by {
|
||||
-webkit-transform: rotate(var(--fa-rotate-angle, none));
|
||||
transform: rotate(var(--fa-rotate-angle, none)); }
|
||||
|
||||
.fa-stack {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 2em;
|
||||
position: relative;
|
||||
width: 2.5em; }
|
||||
|
||||
.fa-stack-1x,
|
||||
.fa-stack-2x {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin: auto;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: var(--fa-stack-z-index, auto); }
|
||||
|
||||
.svg-inline--fa.fa-stack-1x {
|
||||
height: 1em;
|
||||
width: 1.25em; }
|
||||
|
||||
.svg-inline--fa.fa-stack-2x {
|
||||
height: 2em;
|
||||
width: 2.5em; }
|
||||
|
||||
.fa-inverse {
|
||||
color: var(--fa-inverse, #fff); }
|
||||
|
||||
.sr-only,
|
||||
.fa-sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0; }
|
||||
|
||||
.sr-only-focusable:not(:focus),
|
||||
.fa-sr-only-focusable:not(:focus) {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0; }
|
||||
|
||||
.svg-inline--fa .fa-primary {
|
||||
fill: var(--fa-primary-color, currentColor);
|
||||
opacity: var(--fa-primary-opacity, 1); }
|
||||
|
||||
.svg-inline--fa .fa-secondary {
|
||||
fill: var(--fa-secondary-color, currentColor);
|
||||
opacity: var(--fa-secondary-opacity, 0.4); }
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-primary {
|
||||
opacity: var(--fa-secondary-opacity, 0.4); }
|
||||
|
||||
.svg-inline--fa.fa-swap-opacity .fa-secondary {
|
||||
opacity: var(--fa-primary-opacity, 1); }
|
||||
|
||||
.svg-inline--fa mask .fa-primary,
|
||||
.svg-inline--fa mask .fa-secondary {
|
||||
fill: black; }
|
||||
|
||||
.fad.fa-inverse,
|
||||
.fa-duotone.fa-inverse {
|
||||
color: var(--fa-inverse, #fff); }
|
||||
6
front/lib/AdminLTE/bower_components/font-awesome/css/svg-with-js.min.css
vendored
Executable file
26
front/lib/AdminLTE/bower_components/font-awesome/css/v4-font-face.css
vendored
Executable file
@@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype");
|
||||
unicode-range: U+F003,U+F006,U+F014,U+F016-F017,U+F01A-F01B,U+F01D,U+F022,U+F03E,U+F044,U+F046,U+F05C-F05D,U+F06E,U+F070,U+F087-F088,U+F08A,U+F094,U+F096-F097,U+F09D,U+F0A0,U+F0A2,U+F0A4-F0A7,U+F0C5,U+F0C7,U+F0E5-F0E6,U+F0EB,U+F0F6-F0F8,U+F10C,U+F114-F115,U+F118-F11A,U+F11C-F11D,U+F133,U+F147,U+F14E,U+F150-F152,U+F185-F186,U+F18E,U+F190-F192,U+F196,U+F1C1-F1C9,U+F1D9,U+F1DB,U+F1E3,U+F1EA,U+F1F7,U+F1F9,U+F20A,U+F247-F248,U+F24A,U+F24D,U+F255-F25B,U+F25D,U+F271-F274,U+F278,U+F27B,U+F28C,U+F28E,U+F29C,U+F2B5,U+F2B7,U+F2BA,U+F2BC,U+F2BE,U+F2C0-F2C1,U+F2C3,U+F2D0,U+F2D2,U+F2D4,U+F2DC; }
|
||||
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
font-display: block;
|
||||
src: url("../webfonts/fa-v4compatibility.woff2") format("woff2"), url("../webfonts/fa-v4compatibility.ttf") format("truetype");
|
||||
unicode-range: U+F041,U+F047,U+F065-F066,U+F07D-F07E,U+F080,U+F08B,U+F08E,U+F090,U+F09A,U+F0AC,U+F0AE,U+F0B2,U+F0D0,U+F0D6,U+F0E4,U+F0EC,U+F10A-F10B,U+F123,U+F13E,U+F148-F149,U+F14C,U+F156,U+F15E,U+F160-F161,U+F163,U+F175-F178,U+F195,U+F1F8,U+F219,U+F27A; }
|
||||
6
front/lib/AdminLTE/bower_components/font-awesome/css/v4-font-face.min.css
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a}
|
||||
2194
front/lib/AdminLTE/bower_components/font-awesome/css/v4-shims.css
vendored
Executable file
6
front/lib/AdminLTE/bower_components/font-awesome/css/v4-shims.min.css
vendored
Executable file
22
front/lib/AdminLTE/bower_components/font-awesome/css/v5-font-face.css
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Brands';
|
||||
font-display: block;
|
||||
font-weight: 400;
|
||||
src: url("../webfonts/fa-brands-400.woff2") format("woff2"), url("../webfonts/fa-brands-400.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-display: block;
|
||||
font-weight: 900;
|
||||
src: url("../webfonts/fa-solid-900.woff2") format("woff2"), url("../webfonts/fa-solid-900.ttf") format("truetype"); }
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 5 Free';
|
||||
font-display: block;
|
||||
font-weight: 400;
|
||||
src: url("../webfonts/fa-regular-400.woff2") format("woff2"), url("../webfonts/fa-regular-400.ttf") format("truetype"); }
|
||||
6
front/lib/AdminLTE/bower_components/font-awesome/css/v5-font-face.min.css
vendored
Executable file
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* Font Awesome Free 6.2.1 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Brands";font-display:block;font-weight:400;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:900;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"Font Awesome 5 Free";font-display:block;font-weight:400;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype")}
|
||||
|
Before Width: | Height: | Size: 434 KiB |
152
front/lib/AdminLTE/bower_components/font-awesome/less/_animated.less
vendored
Executable file
@@ -0,0 +1,152 @@
|
||||
// animating icons
|
||||
// --------------------------
|
||||
|
||||
.@{fa-css-prefix}-beat {
|
||||
animation-name: ~'@{fa-css-prefix}-beat';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, ease-in-out)';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-bounce {
|
||||
animation-name: ~'@{fa-css-prefix}-beat';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1))';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-fade {
|
||||
animation-name: ~'@{fa-css-prefix}-fade';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1))';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-beat-fade {
|
||||
animation-name: ~'@{fa-css-prefix}-beat-fade';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1))';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-flip {
|
||||
animation-name: ~'@{fa-css-prefix}-flip';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, ease-in-out)';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-shake {
|
||||
animation-name: ~'@{fa-css-prefix}-shake';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, ease-in-out)';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-spin {
|
||||
animation-name: ~'@{fa-css-prefix}-spin';
|
||||
animation-delay: ~'var(--@{fa-css-prefix}-animation-delay, 0s)';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 2s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, linear)';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-spin-reverse {
|
||||
--@{fa-css-prefix}-animation-direction: reverse;
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pulse,
|
||||
.@{fa-css-prefix}-spin-pulse {
|
||||
animation-name: ~'@{fa-css-prefix}-spin';
|
||||
animation-direction: ~'var(--@{fa-css-prefix}-animation-direction, normal)';
|
||||
animation-duration: ~'var(--@{fa-css-prefix}-animation-duration, 1s)';
|
||||
animation-iteration-count: ~'var(--@{fa-css-prefix}-animation-iteration-count, infinite)';
|
||||
animation-timing-function: ~'var(--@{fa-css-prefix}-animation-timing, steps(8));';
|
||||
}
|
||||
|
||||
// if agent or operating system prefers reduced motion, disable animations
|
||||
// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/
|
||||
// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.@{fa-css-prefix}-beat,
|
||||
.@{fa-css-prefix}-bounce,
|
||||
.@{fa-css-prefix}-fade,
|
||||
.@{fa-css-prefix}-beat-fade,
|
||||
.@{fa-css-prefix}-flip,
|
||||
.@{fa-css-prefix}-pulse,
|
||||
.@{fa-css-prefix}-shake,
|
||||
.@{fa-css-prefix}-spin,
|
||||
.@{fa-css-prefix}-spin-pulse {
|
||||
animation-delay: -1ms;
|
||||
animation-duration: 1ms;
|
||||
animation-iteration-count: 1;
|
||||
transition-delay: 0s;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-beat' {
|
||||
0%, 90% { transform: scale(1); }
|
||||
45% { transform: ~'scale(var(--@{fa-css-prefix}-beat-scale, 1.25))'; }
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-bounce' {
|
||||
0% { transform: scale(1,1) translateY(0); }
|
||||
10% { transform: ~'scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9))' translateY(0); }
|
||||
30% { transform: ~'scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1))' ~'translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em))'; }
|
||||
50% { transform: ~'scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95))' translateY(0); }
|
||||
57% { transform: ~'scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em))'; }
|
||||
64% { transform: scale(1,1) translateY(0); }
|
||||
100% { transform: scale(1,1) translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-fade' {
|
||||
50% { opacity: ~'var(--@{fa-css-prefix}-fade-opacity, 0.4)'; }
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-beat-fade' {
|
||||
0%, 100% {
|
||||
opacity: ~'var(--@{fa-css-prefix}-beat-fade-opacity, 0.4)';
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: ~'scale(var(--@{fa-css-prefix}-beat-fade-scale, 1.125))';
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-flip' {
|
||||
50% {
|
||||
transform: ~'rotate3d(var(--@{fa-css-prefix}-flip-x, 0), var(--@{fa-css-prefix}-flip-y, 1), var(--@{fa-css-prefix}-flip-z, 0), var(--@{fa-css-prefix}-flip-angle, -180deg))';
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-shake' {
|
||||
0% { transform: rotate(-15deg); }
|
||||
4% { transform: rotate(15deg); }
|
||||
8%, 24% { transform: rotate(-18deg); }
|
||||
12%, 28% { transform: rotate(18deg); }
|
||||
16% { transform: rotate(-22deg); }
|
||||
20% { transform: rotate(22deg); }
|
||||
32% { transform: rotate(-12deg); }
|
||||
36% { transform: rotate(12deg); }
|
||||
40%, 100% { transform: rotate(0deg); }
|
||||
}
|
||||
|
||||
@keyframes ~'@{fa-css-prefix}-spin' {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
20
front/lib/AdminLTE/bower_components/font-awesome/less/_bordered-pulled.less
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
// bordered + pulled icons
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-border {
|
||||
border-color: ~'var(--@{fa-css-prefix}-border-color, @{fa-border-color})';
|
||||
border-radius: ~'var(--@{fa-css-prefix}-border-radius, @{fa-border-radius})';
|
||||
border-style: ~'var(--@{fa-css-prefix}-border-style, @{fa-border-style})';
|
||||
border-width: ~'var(--@{fa-css-prefix}-border-width, @{fa-border-width})';
|
||||
padding: ~'var(--@{fa-css-prefix}-border-padding, @{fa-border-padding})';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pull-left {
|
||||
float: left;
|
||||
margin-right: ~'var(--@{fa-css-prefix}-pull-margin, @{fa-pull-margin})';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-pull-right {
|
||||
float: right;
|
||||
margin-left: ~'var(--@{fa-css-prefix}-pull-margin, @{fa-pull-margin})';
|
||||
}
|
||||
38
front/lib/AdminLTE/bower_components/font-awesome/less/_core.less
vendored
Executable file
@@ -0,0 +1,38 @@
|
||||
// base icon class definition
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix} {
|
||||
font-family: ~"var(--@{fa-css-prefix}-style-family, '@{fa-style-family}')";
|
||||
font-weight: ~'var(--@{fa-css-prefix}-style, @{fa-style})';
|
||||
}
|
||||
|
||||
.@{fa-css-prefix},
|
||||
.fas,
|
||||
.@{fa-css-prefix}-solid,
|
||||
.fass,
|
||||
.@{fa-css-prefix}-sharp,
|
||||
.far,
|
||||
.@{fa-css-prefix}-regular,
|
||||
.fab,
|
||||
.@{fa-css-prefix}-brands {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: ~'var(--@{fa-css-prefix}-display, @{fa-display})';
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
}
|
||||
|
||||
.fas,
|
||||
.@{fa-css-prefix}-classic,
|
||||
.@{fa-css-prefix}-solid,
|
||||
.far,
|
||||
.@{fa-css-prefix}-regular {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
}
|
||||
|
||||
.fab,
|
||||
.@{fa-css-prefix}-brands {
|
||||
font-family: 'Font Awesome 6 Brands';
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Fixed Width Icons
|
||||
// fixed-width icons
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-fw {
|
||||
width: (18em / 14);
|
||||
text-align: center;
|
||||
width: @fa-fw-width;
|
||||
}
|
||||
9
front/lib/AdminLTE/bower_components/font-awesome/less/_icons.less
vendored
Executable file
@@ -0,0 +1,9 @@
|
||||
// specific icon class definition
|
||||
// -------------------------
|
||||
|
||||
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
|
||||
readers do not read off random characters that represent icons */
|
||||
|
||||
each(.fa-icons(), {
|
||||
.@{fa-css-prefix}-@{key}::before { content: @value; }
|
||||
});
|
||||
18
front/lib/AdminLTE/bower_components/font-awesome/less/_list.less
vendored
Executable file
@@ -0,0 +1,18 @@
|
||||
// icons in a list
|
||||
// -------------------------
|
||||
|
||||
.@{fa-css-prefix}-ul {
|
||||
list-style-type: none;
|
||||
margin-left: ~'var(--@{fa-css-prefix}-li-margin, @{fa-li-margin})';
|
||||
padding-left: 0;
|
||||
|
||||
> li { position: relative; }
|
||||
}
|
||||
|
||||
.@{fa-css-prefix}-li {
|
||||
left: calc(~'var(--@{fa-css-prefix}-li-width, @{fa-li-width})' * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: ~'var(--@{fa-css-prefix}-li-width, @{fa-li-width})';
|
||||
line-height: inherit;
|
||||
}
|
||||