mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-10-06 20:27:12 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
86beba6f5a | ||
|
|
f0d9948aee | ||
|
|
8e3d2f7010 | ||
|
|
fc1c5a505d | ||
|
|
18cb06fbc7 | ||
|
|
1af785a94f | ||
|
|
7626becb38 | ||
|
|
5d5e959729 | ||
|
|
49bbdd064e | ||
|
|
9279ee2e76 | ||
|
|
a76e6b32f7 | ||
|
|
4c6f8c4f60 | ||
|
|
826d32413b | ||
|
|
b6799d9fcb | ||
|
|
8782304e8d | ||
|
|
9c55d46bc6 | ||
|
|
099db33e44 | ||
|
|
152431a7d7 | ||
|
|
36fa5dc633 | ||
|
|
814f4aed15 | ||
|
|
e990856629 | ||
|
|
c97afbfa0b | ||
|
|
93b3e0302a | ||
|
|
27c87de4ed | ||
|
|
028ad4ceb9 | ||
|
|
e501642b8e | ||
|
|
7966f010a2 | ||
|
|
b22f74cb59 | ||
|
|
c928948b15 | ||
|
|
606eaad8f7 | ||
|
|
c44281f62d | ||
|
|
1e98784eee | ||
|
|
dd9296ffc2 | ||
|
|
fc0e6b6efb | ||
|
|
68f5fbf65c | ||
|
|
9727e4084f | ||
|
|
5c2f48e94c | ||
|
|
cb098df743 | ||
|
|
b3c54ed07a | ||
|
|
c601eca25d | ||
|
|
48a13255f3 | ||
|
|
08f93c7d58 | ||
|
|
e5c9752681 | ||
|
|
afa1ed1eff | ||
|
|
072cbe62de | ||
|
|
9fe8bfadf3 | ||
|
|
75e4953070 | ||
|
|
de30650dc7 | ||
|
|
690c34bc1d | ||
|
|
4d2e32ee40 | ||
|
|
02b2988beb | ||
|
|
3f1a5af88b | ||
|
|
850fd85d4d | ||
|
|
24acd42589 | ||
|
|
eaa0dea63b | ||
|
|
dd50bbca9b | ||
|
|
f3f5471ef7 | ||
|
|
516c8ea66c | ||
|
|
48310034e5 | ||
|
|
be35a88f8c | ||
|
|
e67b512499 | ||
|
|
0cf59159cd | ||
|
|
e7a929a947 | ||
|
|
dabf4d4383 | ||
|
|
13bdd4ad0b | ||
|
|
3281b97ea9 | ||
|
|
8070db96e9 | ||
|
|
82c80a9682 | ||
|
|
136cc2e3ff | ||
|
|
eefce62f01 | ||
|
|
240b2c63f6 | ||
|
|
355da03fba | ||
|
|
55d57c552d | ||
|
|
a56e5eb2fe | ||
|
|
e7817fab78 | ||
|
|
714b8417f4 | ||
|
|
ffb68c8848 | ||
|
|
7a5be0ccbf | ||
|
|
c2927af554 | ||
|
|
24cea0cf22 | ||
|
|
f4351c119f | ||
|
|
f40b6b5b65 | ||
|
|
bff96eb1ae | ||
|
|
de9564c4c9 | ||
|
|
614aa1e49e | ||
|
|
b368c299d9 | ||
|
|
01a61d4e62 | ||
|
|
174fcd7167 | ||
|
|
dca85f2ffb | ||
|
|
8ad5acb020 | ||
|
|
287118c3a7 | ||
|
|
78621a1f50 | ||
|
|
116859e0ba | ||
|
|
c4827e908c | ||
|
|
41d56a867a | ||
|
|
9f4dd1d172 | ||
|
|
948d23f56d | ||
|
|
50e9a3ec8a | ||
|
|
0dbd6be010 | ||
|
|
2b4189b1a4 | ||
|
|
4bf81975dc | ||
|
|
ea040f4412 | ||
|
|
c246648949 | ||
|
|
125aaa5b7d | ||
|
|
aa7888c37d | ||
|
|
f1e1232849 | ||
|
|
bb7c7bcff6 | ||
|
|
e5cf35aff8 | ||
|
|
65585e286d | ||
|
|
99bcfb8c4b | ||
|
|
d98fd74968 | ||
|
|
7875185e1f | ||
|
|
a8d50955ee | ||
|
|
bfd5329363 | ||
|
|
ea1eb48596 | ||
|
|
f1bb23ba2a | ||
|
|
5160eff294 | ||
|
|
118984dfff | ||
|
|
a71cc759f6 | ||
|
|
faf8da1365 | ||
|
|
ce546e8a90 | ||
|
|
f4731eecdb | ||
|
|
6704377402 | ||
|
|
827cb00837 | ||
|
|
299a342a62 | ||
|
|
77f04d10c7 | ||
|
|
d55994b66a | ||
|
|
a96b209e1b | ||
|
|
d7323213b8 | ||
|
|
19fabd0e64 | ||
|
|
ef392ef6ba | ||
|
|
a09661fc83 | ||
|
|
f52ab69a5b | ||
|
|
9d1b620dcf | ||
|
|
3ebd801b3d | ||
|
|
0cdb1e638d | ||
|
|
da415e5c6b | ||
|
|
c8f69ffe77 | ||
|
|
79982e0e8d | ||
|
|
8ca028eb2e | ||
|
|
074e3fcd6e | ||
|
|
3f40fada1b | ||
|
|
a9871d05b2 | ||
|
|
39e46d2e0b | ||
|
|
996b2db514 | ||
|
|
177ebe26de | ||
|
|
da72184fda | ||
|
|
a2b31cb28d | ||
|
|
b6760e19b7 | ||
|
|
6ce25f38e1 | ||
|
|
5cb7f726bc | ||
|
|
a334f33b35 | ||
|
|
b503271aba | ||
|
|
008e5651f8 | ||
|
|
5e3aab12a7 | ||
|
|
51b80f6fa1 | ||
|
|
75fdeb2843 | ||
|
|
2b1d927de4 | ||
|
|
e5d788497a | ||
|
|
b173e2ef86 | ||
|
|
3d48c2427a | ||
|
|
a9046d8f35 | ||
|
|
b4a1b81aec | ||
|
|
90eb0ea27a | ||
|
|
4f01b9fd25 | ||
|
|
174b5c8f7f | ||
|
|
3912fcb238 | ||
|
|
ef70457a48 | ||
|
|
8c4dbaec4f | ||
|
|
645e8f426c | ||
|
|
bae1d1c047 | ||
|
|
b8656763ec | ||
|
|
10e560c5b2 | ||
|
|
ba9f2bc376 | ||
|
|
fb7e234120 | ||
|
|
8c80cecdfb | ||
|
|
e53f431273 | ||
|
|
8e0ee67108 | ||
|
|
3d82d9af1b | ||
|
|
8a0bd23985 | ||
|
|
4387e4764f | ||
|
|
3b8e17c21f | ||
|
|
e74af0db89 | ||
|
|
5ff62d8f22 | ||
|
|
4427173a6c | ||
|
|
db66fe33fa | ||
|
|
cf5fa96a93 | ||
|
|
9e76b6ee70 | ||
|
|
45e97b3753 | ||
|
|
ecc16c69e6 | ||
|
|
77e6124b00 | ||
|
|
a3ddb58566 | ||
|
|
be7252f620 | ||
|
|
db8af3d1e0 | ||
|
|
7f70b0f703 | ||
|
|
2e10cc8e79 | ||
|
|
047d9143c0 | ||
|
|
a7a0eef125 | ||
|
|
5d35af9d69 | ||
|
|
ea21bca7df | ||
|
|
a3c0737ba8 | ||
|
|
9747995510 | ||
|
|
ad9112010f | ||
|
|
a4ec2d1d86 | ||
|
|
b7f07951f6 | ||
|
|
0e3363e61c | ||
|
|
e26d5b8ba5 | ||
|
|
8987ebca36 | ||
|
|
d3cd21956a | ||
|
|
b149da28c8 | ||
|
|
e5cb2dd00e | ||
|
|
c9b883dff5 | ||
|
|
ad43253a90 | ||
|
|
979de67c2b | ||
|
|
8416caf798 | ||
|
|
80d9dfe420 | ||
|
|
8a49b50f33 | ||
|
|
cbd8e40f14 | ||
|
|
2d2c033ba7 | ||
|
|
496c68d2af | ||
|
|
c505943e8b | ||
|
|
2841c09c1f | ||
|
|
18444bd284 | ||
|
|
9d3a89d362 | ||
|
|
2d0ab4a1b8 | ||
|
|
2fec7ccd58 | ||
|
|
052959f435 | ||
|
|
560df58bb4 | ||
|
|
5629d47cb6 | ||
|
|
37b4ff811d | ||
|
|
7384aab2f4 | ||
|
|
4ce05d4d4d | ||
|
|
fdb56de0a8 | ||
|
|
df56d73cec | ||
|
|
4ba0e155f3 | ||
|
|
304655f7ff | ||
|
|
6210f06bc0 | ||
|
|
09ae37410e | ||
|
|
351c803623 | ||
|
|
6a027b70e7 | ||
|
|
cdd2adbc73 | ||
|
|
cb6a5d4069 | ||
|
|
f13530d8a1 | ||
|
|
8a86fa491e | ||
|
|
3e6a241c69 | ||
|
|
160dceff3e | ||
|
|
0ece065cb0 | ||
|
|
fb7e00c158 | ||
|
|
a0567beee5 | ||
|
|
96c8e01a3b | ||
|
|
88bd7bff1e | ||
|
|
7075b9f0c0 | ||
|
|
b19666f7e0 | ||
|
|
e663f3db72 | ||
|
|
fd1ffdba80 | ||
|
|
a12538b3a8 | ||
|
|
cdff1ba37b | ||
|
|
f6a51f6b6f | ||
|
|
45dd0611d9 | ||
|
|
e62069d3db | ||
|
|
5088636d5f | ||
|
|
003d70990e | ||
|
|
051d08b499 | ||
|
|
b980e7af29 | ||
|
|
4d0799dead | ||
|
|
d3dca1ddc2 | ||
|
|
9b8039440c | ||
|
|
eea5c9df2f | ||
|
|
aa9aff800c | ||
|
|
0b3b5e230b | ||
|
|
db0d91beb1 | ||
|
|
4758033445 | ||
|
|
1e48fb8cda | ||
|
|
1d8da117d6 | ||
|
|
635fa795d2 | ||
|
|
c1792df819 | ||
|
|
36944f8073 | ||
|
|
4d59cb0351 |
No files matched your search
@@ -26,21 +26,21 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: Description
|
label: Description
|
||||||
description: Please provide a brief description of the bug in 1-2 sentences. If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI.
|
description: Please provide a brief description of the bug in 1-2 sentences. If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI.
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Logs:"
|
label: "Logs:"
|
||||||
description: "Please take a look at the [official documentation](https://docs.mailcow.email/troubleshooting/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks."
|
description: "Please take a look at the [official documentation](https://docs.mailcow.email/troubleshooting/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks."
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Steps to reproduce:"
|
label: "Steps to reproduce:"
|
||||||
description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful."
|
description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful."
|
||||||
render: text
|
render: plain text
|
||||||
placeholder: |-
|
placeholder: |-
|
||||||
1. ...
|
1. ...
|
||||||
2. ...
|
2. ...
|
||||||
@@ -117,41 +117,41 @@ body:
|
|||||||
attributes:
|
attributes:
|
||||||
label: "Logs of git diff:"
|
label: "Logs of git diff:"
|
||||||
description: "#### Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:"
|
description: "#### Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Logs of iptables -L -vn:"
|
label: "Logs of iptables -L -vn:"
|
||||||
description: "#### Output of `iptables -L -vn`"
|
description: "#### Output of `iptables -L -vn`"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Logs of ip6tables -L -vn:"
|
label: "Logs of ip6tables -L -vn:"
|
||||||
description: "#### Output of `ip6tables -L -vn`"
|
description: "#### Output of `ip6tables -L -vn`"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Logs of iptables -L -vn -t nat:"
|
label: "Logs of iptables -L -vn -t nat:"
|
||||||
description: "#### Output of `iptables -L -vn -t nat`"
|
description: "#### Output of `iptables -L -vn -t nat`"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "Logs of ip6tables -L -vn -t nat:"
|
label: "Logs of ip6tables -L -vn -t nat:"
|
||||||
description: "#### Output of `ip6tables -L -vn -t nat`"
|
description: "#### Output of `ip6tables -L -vn -t nat`"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: textarea
|
- type: textarea
|
||||||
attributes:
|
attributes:
|
||||||
label: "DNS check:"
|
label: "DNS check:"
|
||||||
description: "#### Output of `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @172.22.1.254` (set the IP accordingly, if you changed the internal mailcow network)"
|
description: "#### Output of `docker exec -it $(docker ps -qf name=acme-mailcow) dig +short stackoverflow.com @172.22.1.254` (set the IP accordingly, if you changed the internal mailcow network)"
|
||||||
render: text
|
render: plain text
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"timezone": "Europe/Berlin",
|
||||||
|
"dependencyDashboard": true,
|
||||||
|
"dependencyDashboardTitle": "Renovate Dashboard",
|
||||||
|
"commitBody": "Signed-off-by: milkmaker <milkmaker@mailcow.de>",
|
||||||
|
"rebaseWhen": "auto",
|
||||||
|
"labels": ["renovate"],
|
||||||
|
"assignees": [
|
||||||
|
"@magiccc"
|
||||||
|
],
|
||||||
|
"baseBranches": ["staging"],
|
||||||
|
"enabledManagers": ["github-actions", "regex", "docker-compose"],
|
||||||
|
"ignorePaths": [
|
||||||
|
"data\/web\/inc\/lib\/vendor\/matthiasmullie\/minify\/**"
|
||||||
|
],
|
||||||
|
"regexManagers": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["^helper-scripts\/nextcloud.sh$"],
|
||||||
|
"matchStrings": [
|
||||||
|
"#\\srenovate:\\sdatasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?( extractVersion=(?<extractVersion>.*?))?\\s.*?_VERSION=(?<currentValue>.*)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileMatch": ["(^|/)Dockerfile[^/]*$"],
|
||||||
|
"matchStrings": [
|
||||||
|
"#\\srenovate:\\sdatasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?\\s(ENV|ARG) .*?_VERSION=(?<currentValue>.*)\\s"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging
|
if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging
|
||||||
steps:
|
steps:
|
||||||
- name: Send message
|
- name: Send message
|
||||||
uses: thollander/actions-comment-pull-request@main
|
uses: thollander/actions-comment-pull-request@v2.3.1
|
||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }}
|
GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }}
|
||||||
message: |
|
message: |
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- name: Mark/Close Stale Issues and Pull Requests 🗑️
|
- name: Mark/Close Stale Issues and Pull Requests 🗑️
|
||||||
uses: actions/stale@v6.0.1
|
uses: actions/stale@v7.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
||||||
days-before-stale: 60
|
days-before-stale: 60
|
||||||
|
|||||||
@@ -33,13 +33,11 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh
|
curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh
|
||||||
sudo service docker start
|
sudo service docker start
|
||||||
sudo curl -L https://github.com/docker/compose/releases/download/v$(curl -Ls https://www.servercow.de/docker-compose/latest.php)/docker-compose-$(uname -s)-$(uname -m) > /usr/local/bin/docker-compose
|
|
||||||
sudo chmod +x /usr/local/bin/docker-compose
|
|
||||||
- name: Prepair Image Builds
|
- name: Prepair Image Builds
|
||||||
run: |
|
run: |
|
||||||
cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
|
cp helper-scripts/docker-compose.override.yml.d/BUILD_FLAGS/docker-compose.override.yml docker-compose.override.yml
|
||||||
- name: Build Docker Images
|
- name: Build Docker Images
|
||||||
run: |
|
run: |
|
||||||
docker-compose build ${image}
|
docker compose build ${image}
|
||||||
env:
|
env:
|
||||||
image: ${{ matrix.images }}
|
image: ${{ matrix.images }}
|
||||||
@@ -11,7 +11,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
RELEASE_TAG=$(curl https://api.github.com/repos/mailcow/mailcow-dockerized/releases/latest | jq -r '.tag_name')
|
RELEASE_TAG=$(curl https://api.github.com/repos/mailcow/mailcow-dockerized/releases/latest | jq -r '.tag_name')
|
||||||
- name: Tweet-trigger-publish-release
|
- name: Tweet-trigger-publish-release
|
||||||
uses: mugi111/tweet-trigger-release@v1.1
|
uses: mugi111/tweet-trigger-release@v1.2
|
||||||
with:
|
with:
|
||||||
consumer_key: ${{ secrets.CONSUMER_KEY }}
|
consumer_key: ${{ secrets.CONSUMER_KEY }}
|
||||||
consumer_secret: ${{ secrets.CONSUMER_SECRET }}
|
consumer_secret: ${{ secrets.CONSUMER_SECRET }}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
|
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM clamav/clamav:0.105.1_base
|
FROM clamav/clamav:1.0_base
|
||||||
|
|
||||||
LABEL maintainer "André Peters <andre.peters@servercow.de>"
|
LABEL maintainer "André Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
|
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
@@ -8,11 +8,14 @@ RUN apk add --update --no-cache python3 \
|
|||||||
py3-pip \
|
py3-pip \
|
||||||
openssl \
|
openssl \
|
||||||
tzdata \
|
tzdata \
|
||||||
|
py3-psutil \
|
||||||
&& pip3 install --upgrade pip \
|
&& pip3 install --upgrade pip \
|
||||||
docker \
|
fastapi \
|
||||||
flask \
|
uvicorn \
|
||||||
flask-restful
|
aiodocker \
|
||||||
|
redis
|
||||||
|
|
||||||
|
COPY docker-entrypoint.sh /app/
|
||||||
COPY dockerapi.py /app/
|
COPY dockerapi.py /app/
|
||||||
|
|
||||||
CMD ["python3", "-u", "/app/dockerapi.py"]
|
ENTRYPOINT ["/bin/sh", "/app/docker-entrypoint.sh"]
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
`openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes \
|
||||||
|
-keyout /app/dockerapi_key.pem \
|
||||||
|
-out /app/dockerapi_cert.pem \
|
||||||
|
-subj /CN=dockerapi/O=mailcow \
|
||||||
|
-addext subjectAltName=DNS:dockerapi`
|
||||||
|
|
||||||
|
`uvicorn --host 0.0.0.0 --port 443 --ssl-certfile=/app/dockerapi_cert.pem --ssl-keyfile=/app/dockerapi_key.pem dockerapi:app`
|
||||||
@@ -1,419 +1,623 @@
|
|||||||
#!/usr/bin/env python3
|
from fastapi import FastAPI, Response, Request
|
||||||
|
import aiodocker
|
||||||
from flask import Flask
|
import psutil
|
||||||
from flask_restful import Resource, Api
|
import sys
|
||||||
from flask import jsonify
|
import re
|
||||||
from flask import Response
|
|
||||||
from flask import request
|
|
||||||
from threading import Thread
|
|
||||||
import docker
|
|
||||||
import uuid
|
|
||||||
import signal
|
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import re
|
import json
|
||||||
import sys
|
import asyncio
|
||||||
import ssl
|
import redis
|
||||||
import socket
|
from datetime import datetime
|
||||||
import subprocess
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
|
|
||||||
app = Flask(__name__)
|
|
||||||
api = Api(app)
|
|
||||||
|
|
||||||
class containers_get(Resource):
|
containerIds_to_update = []
|
||||||
def get(self):
|
host_stats_isUpdating = False
|
||||||
containers = {}
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/host/stats")
|
||||||
|
async def get_host_update_stats():
|
||||||
|
global host_stats_isUpdating
|
||||||
|
|
||||||
|
if host_stats_isUpdating == False:
|
||||||
|
print("start host stats task")
|
||||||
|
asyncio.create_task(get_host_stats())
|
||||||
|
host_stats_isUpdating = True
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if redis_client.exists('host_stats'):
|
||||||
|
break
|
||||||
|
print("wait for host_stats results")
|
||||||
|
await asyncio.sleep(1.5)
|
||||||
|
|
||||||
|
|
||||||
|
print("host stats pulled")
|
||||||
|
stats = json.loads(redis_client.get('host_stats'))
|
||||||
|
return Response(content=json.dumps(stats, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
@app.get("/containers/{container_id}/json")
|
||||||
|
async def get_container(container_id : str):
|
||||||
|
if container_id and container_id.isalnum():
|
||||||
try:
|
try:
|
||||||
for container in docker_client.containers.list(all=True):
|
for container in (await async_docker_client.containers.list()):
|
||||||
containers.update({container.attrs['Id']: container.attrs})
|
if container._id == container_id:
|
||||||
return containers
|
container_info = await container.show()
|
||||||
|
return Response(content=json.dumps(container_info, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "no container found"
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return jsonify(type='danger', msg=str(e))
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": str(e)
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "no or invalid id defined"
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
class container_get(Resource):
|
@app.get("/containers/json")
|
||||||
def get(self, container_id):
|
async def get_containers():
|
||||||
if container_id and container_id.isalnum():
|
containers = {}
|
||||||
try:
|
try:
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
for container in (await async_docker_client.containers.list()):
|
||||||
return container.attrs
|
container_info = await container.show()
|
||||||
except Exception as e:
|
containers.update({container_info['Id']: container_info})
|
||||||
return jsonify(type='danger', msg=str(e))
|
return Response(content=json.dumps(containers, indent=4), media_type="application/json")
|
||||||
else:
|
except Exception as e:
|
||||||
return jsonify(type='danger', msg='no or invalid id defined')
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": str(e)
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
class container_post(Resource):
|
@app.post("/containers/{container_id}/{post_action}")
|
||||||
def post(self, container_id, post_action):
|
async def post_containers(container_id : str, post_action : str, request: Request):
|
||||||
if container_id and container_id.isalnum() and post_action:
|
try :
|
||||||
try:
|
request_json = await request.json()
|
||||||
"""Dispatch container_post api call"""
|
except Exception as err:
|
||||||
if post_action == 'exec':
|
request_json = {}
|
||||||
if not request.json or not 'cmd' in request.json:
|
|
||||||
return jsonify(type='danger', msg='cmd is missing')
|
|
||||||
if not request.json or not 'task' in request.json:
|
|
||||||
return jsonify(type='danger', msg='task is missing')
|
|
||||||
|
|
||||||
api_call_method_name = '__'.join(['container_post', str(post_action), str(request.json['cmd']), str(request.json['task']) ])
|
if container_id and container_id.isalnum() and post_action:
|
||||||
else:
|
try:
|
||||||
api_call_method_name = '__'.join(['container_post', str(post_action) ])
|
"""Dispatch container_post api call"""
|
||||||
|
if post_action == 'exec':
|
||||||
|
if not request_json or not 'cmd' in request_json:
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "cmd is missing"
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
if not request_json or not 'task' in request_json:
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "task is missing"
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
api_call_method = getattr(self, api_call_method_name, lambda container_id: jsonify(type='danger', msg='container_post - unknown api call'))
|
api_call_method_name = '__'.join(['container_post', str(post_action), str(request_json['cmd']), str(request_json['task']) ])
|
||||||
|
else:
|
||||||
|
api_call_method_name = '__'.join(['container_post', str(post_action) ])
|
||||||
|
|
||||||
|
docker_utils = DockerUtils(async_docker_client)
|
||||||
|
api_call_method = getattr(docker_utils, api_call_method_name, lambda container_id: Response(content=json.dumps({'type': 'danger', 'msg':'container_post - unknown api call' }, indent=4), media_type="application/json"))
|
||||||
|
|
||||||
|
|
||||||
print("api call: %s, container_id: %s" % (api_call_method_name, container_id))
|
print("api call: %s, container_id: %s" % (api_call_method_name, container_id))
|
||||||
return api_call_method(container_id)
|
return await api_call_method(container_id, request_json)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("error - container_post: %s" % str(e))
|
print("error - container_post: %s" % str(e))
|
||||||
return jsonify(type='danger', msg=str(e))
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": str(e)
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return jsonify(type='danger', msg='invalid container id or missing action')
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "invalid container id or missing action"
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
@app.post("/container/{container_id}/stats/update")
|
||||||
|
async def post_container_update_stats(container_id : str):
|
||||||
|
global containerIds_to_update
|
||||||
|
|
||||||
|
# start update task for container if no task is running
|
||||||
|
if container_id not in containerIds_to_update:
|
||||||
|
asyncio.create_task(get_container_stats(container_id))
|
||||||
|
containerIds_to_update.append(container_id)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if redis_client.exists(container_id + '_stats'):
|
||||||
|
break
|
||||||
|
await asyncio.sleep(1.5)
|
||||||
|
|
||||||
|
stats = json.loads(redis_client.get(container_id + '_stats'))
|
||||||
|
return Response(content=json.dumps(stats, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class DockerUtils:
|
||||||
|
def __init__(self, docker_client):
|
||||||
|
self.docker_client = docker_client
|
||||||
|
|
||||||
# api call: container_post - post_action: stop
|
# api call: container_post - post_action: stop
|
||||||
def container_post__stop(self, container_id):
|
async def container_post__stop(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
container.stop()
|
if container._id == container_id:
|
||||||
return jsonify(type='success', msg='command completed successfully')
|
await container.stop()
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'command completed successfully'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
# api call: container_post - post_action: start
|
# api call: container_post - post_action: start
|
||||||
def container_post__start(self, container_id):
|
async def container_post__start(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
container.start()
|
if container._id == container_id:
|
||||||
return jsonify(type='success', msg='command completed successfully')
|
await container.start()
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'command completed successfully'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: restart
|
# api call: container_post - post_action: restart
|
||||||
def container_post__restart(self, container_id):
|
async def container_post__restart(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
container.restart()
|
if container._id == container_id:
|
||||||
return jsonify(type='success', msg='command completed successfully')
|
await container.restart()
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'command completed successfully'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: top
|
# api call: container_post - post_action: top
|
||||||
def container_post__top(self, container_id):
|
async def container_post__top(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
return jsonify(type='success', msg=container.top())
|
if container._id == container_id:
|
||||||
|
ps_exec = await container.exec("ps")
|
||||||
|
async with ps_exec.start(detach=False) as stream:
|
||||||
|
ps_return = await stream.read_out()
|
||||||
|
|
||||||
|
exec_details = await ps_exec.inspect()
|
||||||
# api call: container_post - post_action: stats
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
def container_post__stats(self, container_id):
|
res = {
|
||||||
for container in docker_client.containers.list(all=True, filters={"id": container_id}):
|
'type': 'success',
|
||||||
for stat in container.stats(decode=True, stream=True):
|
'msg': ps_return.data.decode('utf-8')
|
||||||
return jsonify(type='success', msg=stat )
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
'type': 'danger',
|
||||||
|
'msg': ''
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: delete
|
# api call: container_post - post_action: exec - cmd: mailq - task: delete
|
||||||
def container_post__exec__mailq__delete(self, container_id):
|
async def container_post__exec__mailq__delete(self, container_id, request_json):
|
||||||
if 'items' in request.json:
|
if 'items' in request_json:
|
||||||
r = re.compile("^[0-9a-fA-F]+$")
|
r = re.compile("^[0-9a-fA-F]+$")
|
||||||
filtered_qids = filter(r.match, request.json['items'])
|
filtered_qids = filter(r.match, request_json['items'])
|
||||||
if filtered_qids:
|
if filtered_qids:
|
||||||
flagged_qids = ['-d %s' % i for i in filtered_qids]
|
flagged_qids = ['-d %s' % i for i in filtered_qids]
|
||||||
sanitized_string = str(' '.join(flagged_qids));
|
sanitized_string = str(' '.join(flagged_qids))
|
||||||
|
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', postsuper_r)
|
postsuper_r_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
||||||
|
return await exec_run_handler('generic', postsuper_r_exec)
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: hold
|
# api call: container_post - post_action: exec - cmd: mailq - task: hold
|
||||||
def container_post__exec__mailq__hold(self, container_id):
|
async def container_post__exec__mailq__hold(self, container_id, request_json):
|
||||||
if 'items' in request.json:
|
if 'items' in request_json:
|
||||||
r = re.compile("^[0-9a-fA-F]+$")
|
r = re.compile("^[0-9a-fA-F]+$")
|
||||||
filtered_qids = filter(r.match, request.json['items'])
|
filtered_qids = filter(r.match, request_json['items'])
|
||||||
if filtered_qids:
|
if filtered_qids:
|
||||||
flagged_qids = ['-h %s' % i for i in filtered_qids]
|
flagged_qids = ['-h %s' % i for i in filtered_qids]
|
||||||
sanitized_string = str(' '.join(flagged_qids));
|
sanitized_string = str(' '.join(flagged_qids))
|
||||||
|
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', postsuper_r)
|
postsuper_r_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
||||||
|
return await exec_run_handler('generic', postsuper_r_exec)
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: cat
|
# api call: container_post - post_action: exec - cmd: mailq - task: cat
|
||||||
def container_post__exec__mailq__cat(self, container_id):
|
async def container_post__exec__mailq__cat(self, container_id, request_json):
|
||||||
if 'items' in request.json:
|
if 'items' in request_json:
|
||||||
r = re.compile("^[0-9a-fA-F]+$")
|
r = re.compile("^[0-9a-fA-F]+$")
|
||||||
filtered_qids = filter(r.match, request.json['items'])
|
filtered_qids = filter(r.match, request_json['items'])
|
||||||
if filtered_qids:
|
if filtered_qids:
|
||||||
sanitized_string = str(' '.join(filtered_qids));
|
sanitized_string = str(' '.join(filtered_qids))
|
||||||
|
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postcat_return = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postcat -q " + sanitized_string], user='postfix')
|
if container._id == container_id:
|
||||||
if not postcat_return:
|
postcat_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postcat -q " + sanitized_string], user='postfix')
|
||||||
postcat_return = 'err: invalid'
|
return await exec_run_handler('utf8_text_only', postcat_exec)
|
||||||
return exec_run_handler('utf8_text_only', postcat_return)
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: unhold
|
# api call: container_post - post_action: exec - cmd: mailq - task: unhold
|
||||||
def container_post__exec__mailq__unhold(self, container_id):
|
async def container_post__exec__mailq__unhold(self, container_id, request_json):
|
||||||
if 'items' in request.json:
|
if 'items' in request_json:
|
||||||
r = re.compile("^[0-9a-fA-F]+$")
|
r = re.compile("^[0-9a-fA-F]+$")
|
||||||
filtered_qids = filter(r.match, request.json['items'])
|
filtered_qids = filter(r.match, request_json['items'])
|
||||||
if filtered_qids:
|
if filtered_qids:
|
||||||
flagged_qids = ['-H %s' % i for i in filtered_qids]
|
flagged_qids = ['-H %s' % i for i in filtered_qids]
|
||||||
sanitized_string = str(' '.join(flagged_qids));
|
sanitized_string = str(' '.join(flagged_qids))
|
||||||
|
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postsuper_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', postsuper_r)
|
postsuper_r_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postsuper " + sanitized_string])
|
||||||
|
return await exec_run_handler('generic', postsuper_r_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: deliver
|
# api call: container_post - post_action: exec - cmd: mailq - task: deliver
|
||||||
def container_post__exec__mailq__deliver(self, container_id):
|
async def container_post__exec__mailq__deliver(self, container_id, request_json):
|
||||||
if 'items' in request.json:
|
if 'items' in request_json:
|
||||||
r = re.compile("^[0-9a-fA-F]+$")
|
r = re.compile("^[0-9a-fA-F]+$")
|
||||||
filtered_qids = filter(r.match, request.json['items'])
|
filtered_qids = filter(r.match, request_json['items'])
|
||||||
if filtered_qids:
|
if filtered_qids:
|
||||||
flagged_qids = ['-i %s' % i for i in filtered_qids]
|
flagged_qids = ['-i %s' % i for i in filtered_qids]
|
||||||
|
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
for i in flagged_qids:
|
if container._id == container_id:
|
||||||
postqueue_r = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postqueue " + i], user='postfix')
|
for i in flagged_qids:
|
||||||
# todo: check each exit code
|
postsuper_r_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postqueue " + i], user='postfix')
|
||||||
return jsonify(type='success', msg=str("Scheduled immediate delivery"))
|
async with postsuper_r_exec.start(detach=False) as stream:
|
||||||
|
postsuper_r_return = await stream.read_out()
|
||||||
|
# todo: check each exit code
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'Scheduled immediate delivery'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: list
|
# api call: container_post - post_action: exec - cmd: mailq - task: list
|
||||||
def container_post__exec__mailq__list(self, container_id):
|
async def container_post__exec__mailq__list(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
mailq_return = container.exec_run(["/usr/sbin/postqueue", "-j"], user='postfix')
|
if container._id == container_id:
|
||||||
return exec_run_handler('utf8_text_only', mailq_return)
|
mailq_exec = await container.exec(["/usr/sbin/postqueue", "-j"], user='postfix')
|
||||||
|
return await exec_run_handler('utf8_text_only', mailq_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: flush
|
# api call: container_post - post_action: exec - cmd: mailq - task: flush
|
||||||
def container_post__exec__mailq__flush(self, container_id):
|
async def container_post__exec__mailq__flush(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postqueue_r = container.exec_run(["/usr/sbin/postqueue", "-f"], user='postfix')
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', postqueue_r)
|
postsuper_r_exec = await container.exec(["/usr/sbin/postqueue", "-f"], user='postfix')
|
||||||
|
return await exec_run_handler('generic', postsuper_r_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: mailq - task: super_delete
|
# api call: container_post - post_action: exec - cmd: mailq - task: super_delete
|
||||||
def container_post__exec__mailq__super_delete(self, container_id):
|
async def container_post__exec__mailq__super_delete(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
postsuper_r = container.exec_run(["/usr/sbin/postsuper", "-d", "ALL"])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', postsuper_r)
|
postsuper_r_exec = await container.exec(["/usr/sbin/postsuper", "-d", "ALL"])
|
||||||
|
return await exec_run_handler('generic', postsuper_r_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: system - task: fts_rescan
|
# api call: container_post - post_action: exec - cmd: system - task: fts_rescan
|
||||||
def container_post__exec__system__fts_rescan(self, container_id):
|
async def container_post__exec__system__fts_rescan(self, container_id, request_json):
|
||||||
if 'username' in request.json:
|
if 'username' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
rescan_return = container.exec_run(["/bin/bash", "-c", "/usr/bin/doveadm fts rescan -u '" + request.json['username'].replace("'", "'\\''") + "'"], user='vmail')
|
if container._id == container_id:
|
||||||
if rescan_return.exit_code == 0:
|
rescan_exec = await container.exec(["/bin/bash", "-c", "/usr/bin/doveadm fts rescan -u '" + request_json['username'].replace("'", "'\\''") + "'"], user='vmail')
|
||||||
return jsonify(type='success', msg='fts_rescan: rescan triggered')
|
async with rescan_exec.start(detach=False) as stream:
|
||||||
else:
|
rescan_return = await stream.read_out()
|
||||||
return jsonify(type='warning', msg='fts_rescan error')
|
|
||||||
|
|
||||||
if 'all' in request.json:
|
exec_details = await rescan_exec.inspect()
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
rescan_return = container.exec_run(["/bin/bash", "-c", "/usr/bin/doveadm fts rescan -A"], user='vmail')
|
res = {
|
||||||
if rescan_return.exit_code == 0:
|
'type': 'success',
|
||||||
return jsonify(type='success', msg='fts_rescan: rescan triggered')
|
'msg': 'fts_rescan: rescan triggered'
|
||||||
else:
|
}
|
||||||
return jsonify(type='warning', msg='fts_rescan error')
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
'type': 'warning',
|
||||||
|
'msg': 'fts_rescan error'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
if 'all' in request_json:
|
||||||
|
for container in (await self.docker_client.containers.list()):
|
||||||
|
if container._id == container_id:
|
||||||
|
rescan_exec = await container.exec(["/bin/bash", "-c", "/usr/bin/doveadm fts rescan -A"], user='vmail')
|
||||||
|
async with rescan_exec.start(detach=False) as stream:
|
||||||
|
rescan_return = await stream.read_out()
|
||||||
|
|
||||||
|
exec_details = await rescan_exec.inspect()
|
||||||
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'fts_rescan: rescan triggered'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
'type': 'warning',
|
||||||
|
'msg': 'fts_rescan error'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: system - task: df
|
# api call: container_post - post_action: exec - cmd: system - task: df
|
||||||
def container_post__exec__system__df(self, container_id):
|
async def container_post__exec__system__df(self, container_id, request_json):
|
||||||
if 'dir' in request.json:
|
if 'dir' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
df_return = container.exec_run(["/bin/bash", "-c", "/bin/df -H '" + request.json['dir'].replace("'", "'\\''") + "' | /usr/bin/tail -n1 | /usr/bin/tr -s [:blank:] | /usr/bin/tr ' ' ','"], user='nobody')
|
if container._id == container_id:
|
||||||
if df_return.exit_code == 0:
|
df_exec = await container.exec(["/bin/bash", "-c", "/bin/df -H '" + request_json['dir'].replace("'", "'\\''") + "' | /usr/bin/tail -n1 | /usr/bin/tr -s [:blank:] | /usr/bin/tr ' ' ','"], user='nobody')
|
||||||
return df_return.output.decode('utf-8').rstrip()
|
async with df_exec.start(detach=False) as stream:
|
||||||
else:
|
df_return = await stream.read_out()
|
||||||
return "0,0,0,0,0,0"
|
|
||||||
|
print(df_return)
|
||||||
|
print(await df_exec.inspect())
|
||||||
|
exec_details = await df_exec.inspect()
|
||||||
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
|
return df_return.data.decode('utf-8').rstrip()
|
||||||
|
else:
|
||||||
|
return "0,0,0,0,0,0"
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: system - task: mysql_upgrade
|
# api call: container_post - post_action: exec - cmd: system - task: mysql_upgrade
|
||||||
def container_post__exec__system__mysql_upgrade(self, container_id):
|
async def container_post__exec__system__mysql_upgrade(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
sql_return = container.exec_run(["/bin/bash", "-c", "/usr/bin/mysql_upgrade -uroot -p'" + os.environ['DBROOT'].replace("'", "'\\''") + "'\n"], user='mysql')
|
if container._id == container_id:
|
||||||
if sql_return.exit_code == 0:
|
sql_exec = await container.exec(["/bin/bash", "-c", "/usr/bin/mysql_upgrade -uroot -p'" + os.environ['DBROOT'].replace("'", "'\\''") + "'\n"], user='mysql')
|
||||||
matched = False
|
async with sql_exec.start(detach=False) as stream:
|
||||||
for line in sql_return.output.decode('utf-8').split("\n"):
|
sql_return = await stream.read_out()
|
||||||
if 'is already upgraded to' in line:
|
|
||||||
matched = True
|
exec_details = await sql_exec.inspect()
|
||||||
if matched:
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
return jsonify(type='success', msg='mysql_upgrade: already upgraded', text=sql_return.output.decode('utf-8'))
|
matched = False
|
||||||
|
for line in sql_return.data.decode('utf-8').split("\n"):
|
||||||
|
if 'is already upgraded to' in line:
|
||||||
|
matched = True
|
||||||
|
if matched:
|
||||||
|
res = {
|
||||||
|
'type': 'success',
|
||||||
|
'msg': 'mysql_upgrade: already upgraded',
|
||||||
|
'text': sql_return.data.decode('utf-8')
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
await container.restart()
|
||||||
|
res = {
|
||||||
|
'type': 'warning',
|
||||||
|
'msg': 'mysql_upgrade: upgrade was applied',
|
||||||
|
'text': sql_return.data.decode('utf-8')
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
else:
|
else:
|
||||||
container.restart()
|
res = {
|
||||||
return jsonify(type='warning', msg='mysql_upgrade: upgrade was applied', text=sql_return.output.decode('utf-8'))
|
'type': 'error',
|
||||||
else:
|
'msg': 'mysql_upgrade: error running command',
|
||||||
return jsonify(type='error', msg='mysql_upgrade: error running command', text=sql_return.output.decode('utf-8'))
|
'text': sql_return.data.decode('utf-8')
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: system - task: mysql_tzinfo_to_sql
|
# api call: container_post - post_action: exec - cmd: system - task: mysql_tzinfo_to_sql
|
||||||
def container_post__exec__system__mysql_tzinfo_to_sql(self, container_id):
|
async def container_post__exec__system__mysql_tzinfo_to_sql(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
sql_return = container.exec_run(["/bin/bash", "-c", "/usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | /bin/sed 's/Local time zone must be set--see zic manual page/FCTY/' | /usr/bin/mysql -uroot -p'" + os.environ['DBROOT'].replace("'", "'\\''") + "' mysql \n"], user='mysql')
|
if container._id == container_id:
|
||||||
if sql_return.exit_code == 0:
|
sql_exec = await container.exec(["/bin/bash", "-c", "/usr/bin/mysql_tzinfo_to_sql /usr/share/zoneinfo | /bin/sed 's/Local time zone must be set--see zic manual page/FCTY/' | /usr/bin/mysql -uroot -p'" + os.environ['DBROOT'].replace("'", "'\\''") + "' mysql \n"], user='mysql')
|
||||||
return jsonify(type='info', msg='mysql_tzinfo_to_sql: command completed successfully', text=sql_return.output.decode('utf-8'))
|
async with sql_exec.start(detach=False) as stream:
|
||||||
else:
|
sql_return = await stream.read_out()
|
||||||
return jsonify(type='error', msg='mysql_tzinfo_to_sql: error running command', text=sql_return.output.decode('utf-8'))
|
|
||||||
|
exec_details = await sql_exec.inspect()
|
||||||
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
|
res = {
|
||||||
|
'type': 'info',
|
||||||
|
'msg': 'mysql_tzinfo_to_sql: command completed successfully',
|
||||||
|
'text': sql_return.data.decode('utf-8')
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
'type': 'error',
|
||||||
|
'msg': 'mysql_tzinfo_to_sql: error running command',
|
||||||
|
'text': sql_return.data.decode('utf-8')
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: reload - task: dovecot
|
# api call: container_post - post_action: exec - cmd: reload - task: dovecot
|
||||||
def container_post__exec__reload__dovecot(self, container_id):
|
async def container_post__exec__reload__dovecot(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
reload_return = container.exec_run(["/bin/bash", "-c", "/usr/sbin/dovecot reload"])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', reload_return)
|
reload_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/dovecot reload"])
|
||||||
|
return await exec_run_handler('generic', reload_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: reload - task: postfix
|
# api call: container_post - post_action: exec - cmd: reload - task: postfix
|
||||||
def container_post__exec__reload__postfix(self, container_id):
|
async def container_post__exec__reload__postfix(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
reload_return = container.exec_run(["/bin/bash", "-c", "/usr/sbin/postfix reload"])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', reload_return)
|
reload_exec = await container.exec(["/bin/bash", "-c", "/usr/sbin/postfix reload"])
|
||||||
|
return await exec_run_handler('generic', reload_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: reload - task: nginx
|
# api call: container_post - post_action: exec - cmd: reload - task: nginx
|
||||||
def container_post__exec__reload__nginx(self, container_id):
|
async def container_post__exec__reload__nginx(self, container_id, request_json):
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
reload_return = container.exec_run(["/bin/sh", "-c", "/usr/sbin/nginx -s reload"])
|
if container._id == container_id:
|
||||||
return exec_run_handler('generic', reload_return)
|
reload_exec = await container.exec(["/bin/sh", "-c", "/usr/sbin/nginx -s reload"])
|
||||||
|
return await exec_run_handler('generic', reload_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: sieve - task: list
|
# api call: container_post - post_action: exec - cmd: sieve - task: list
|
||||||
def container_post__exec__sieve__list(self, container_id):
|
async def container_post__exec__sieve__list(self, container_id, request_json):
|
||||||
if 'username' in request.json:
|
if 'username' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
sieve_return = container.exec_run(["/bin/bash", "-c", "/usr/bin/doveadm sieve list -u '" + request.json['username'].replace("'", "'\\''") + "'"])
|
if container._id == container_id:
|
||||||
return exec_run_handler('utf8_text_only', sieve_return)
|
sieve_exec = await container.exec(["/bin/bash", "-c", "/usr/bin/doveadm sieve list -u '" + request_json['username'].replace("'", "'\\''") + "'"])
|
||||||
|
return await exec_run_handler('utf8_text_only', sieve_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: sieve - task: print
|
# api call: container_post - post_action: exec - cmd: sieve - task: print
|
||||||
def container_post__exec__sieve__print(self, container_id):
|
async def container_post__exec__sieve__print(self, container_id, request_json):
|
||||||
if 'username' in request.json and 'script_name' in request.json:
|
if 'username' in request_json and 'script_name' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
cmd = ["/bin/bash", "-c", "/usr/bin/doveadm sieve get -u '" + request.json['username'].replace("'", "'\\''") + "' '" + request.json['script_name'].replace("'", "'\\''") + "'"]
|
if container._id == container_id:
|
||||||
sieve_return = container.exec_run(cmd)
|
cmd = ["/bin/bash", "-c", "/usr/bin/doveadm sieve get -u '" + request_json['username'].replace("'", "'\\''") + "' '" + request_json['script_name'].replace("'", "'\\''") + "'"]
|
||||||
return exec_run_handler('utf8_text_only', sieve_return)
|
sieve_exec = await container.exec(cmd)
|
||||||
|
return await exec_run_handler('utf8_text_only', sieve_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: maildir - task: cleanup
|
# api call: container_post - post_action: exec - cmd: maildir - task: cleanup
|
||||||
def container_post__exec__maildir__cleanup(self, container_id):
|
async def container_post__exec__maildir__cleanup(self, container_id, request_json):
|
||||||
if 'maildir' in request.json:
|
if 'maildir' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
sane_name = re.sub(r'\W+', '', request.json['maildir'])
|
if container._id == container_id:
|
||||||
cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"]
|
sane_name = re.sub(r'\W+', '', request_json['maildir'])
|
||||||
maildir_cleanup = container.exec_run(cmd, user='vmail')
|
cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"]
|
||||||
return exec_run_handler('generic', maildir_cleanup)
|
maildir_cleanup_exec = await container.exec(cmd, user='vmail')
|
||||||
|
return await exec_run_handler('generic', maildir_cleanup_exec)
|
||||||
|
|
||||||
|
|
||||||
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
|
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
|
||||||
def container_post__exec__rspamd__worker_password(self, container_id):
|
async def container_post__exec__rspamd__worker_password(self, container_id, request_json):
|
||||||
if 'raw' in request.json:
|
if 'raw' in request_json:
|
||||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
for container in (await self.docker_client.containers.list()):
|
||||||
cmd = "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null"
|
if container._id == container_id:
|
||||||
cmd_response = exec_cmd_container(container, cmd, user="_rspamd")
|
|
||||||
matched = False
|
cmd = "./set_worker_password.sh '" + request_json['raw'].replace("'", "'\\''") + "' 2> /dev/null"
|
||||||
for line in cmd_response.split("\n"):
|
rspamd_password_exec = await container.exec(cmd, user='_rspamd')
|
||||||
if '$2$' in line:
|
async with rspamd_password_exec.start(detach=False) as stream:
|
||||||
hash = line.strip()
|
rspamd_password_return = await stream.read_out()
|
||||||
hash_out = re.search('\$2\$.+$', hash).group(0)
|
|
||||||
rspamd_passphrase_hash = re.sub('[^0-9a-zA-Z\$]+', '', hash_out.rstrip())
|
|
||||||
|
|
||||||
rspamd_password_filename = "/etc/rspamd/override.d/worker-controller-password.inc"
|
matched = False
|
||||||
cmd = '''/bin/echo 'enable_password = "%s";' > %s && cat %s''' % (rspamd_passphrase_hash, rspamd_password_filename, rspamd_password_filename)
|
if "OK" in rspamd_password_return.data.decode('utf-8'):
|
||||||
cmd_response = exec_cmd_container(container, cmd, user="_rspamd")
|
matched = True
|
||||||
|
await container.restart()
|
||||||
|
|
||||||
if rspamd_passphrase_hash.startswith("$2$") and rspamd_passphrase_hash in cmd_response:
|
if matched:
|
||||||
container.restart()
|
res = {
|
||||||
matched = True
|
'type': 'success',
|
||||||
|
'msg': 'command completed successfully'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
'type': 'danger',
|
||||||
|
'msg': 'command did not complete'
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
|
|
||||||
if matched:
|
|
||||||
return jsonify(type='success', msg='command completed successfully')
|
|
||||||
else:
|
|
||||||
return jsonify(type='danger', msg='command did not complete')
|
|
||||||
|
|
||||||
def exec_cmd_container(container, cmd, user, timeout=2, shell_cmd="/bin/bash"):
|
|
||||||
|
|
||||||
def recv_socket_data(c_socket, timeout):
|
async def exec_run_handler(type, exec_obj):
|
||||||
c_socket.setblocking(0)
|
async with exec_obj.start(detach=False) as stream:
|
||||||
total_data=[];
|
exec_return = await stream.read_out()
|
||||||
data='';
|
|
||||||
begin=time.time()
|
|
||||||
while True:
|
|
||||||
if total_data and time.time()-begin > timeout:
|
|
||||||
break
|
|
||||||
elif time.time()-begin > timeout*2:
|
|
||||||
break
|
|
||||||
try:
|
|
||||||
data = c_socket.recv(8192)
|
|
||||||
if data:
|
|
||||||
total_data.append(data.decode('utf-8'))
|
|
||||||
#change the beginning time for measurement
|
|
||||||
begin=time.time()
|
|
||||||
else:
|
|
||||||
#sleep for sometime to indicate a gap
|
|
||||||
time.sleep(0.1)
|
|
||||||
break
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return ''.join(total_data)
|
|
||||||
|
|
||||||
try :
|
if exec_return == None:
|
||||||
socket = container.exec_run([shell_cmd], stdin=True, socket=True, user=user).output._sock
|
exec_return = ""
|
||||||
if not cmd.endswith("\n"):
|
else:
|
||||||
cmd = cmd + "\n"
|
exec_return = exec_return.data.decode('utf-8')
|
||||||
socket.send(cmd.encode('utf-8'))
|
|
||||||
data = recv_socket_data(socket, timeout)
|
|
||||||
socket.close()
|
|
||||||
return data
|
|
||||||
|
|
||||||
except Exception as e:
|
if type == 'generic':
|
||||||
print("error - exec_cmd_container: %s" % str(e))
|
exec_details = await exec_obj.inspect()
|
||||||
traceback.print_exc(file=sys.stdout)
|
if exec_details["ExitCode"] == None or exec_details["ExitCode"] == 0:
|
||||||
|
res = {
|
||||||
def exec_run_handler(type, output):
|
"type": "success",
|
||||||
if type == 'generic':
|
"msg": "command completed successfully"
|
||||||
if output.exit_code == 0:
|
}
|
||||||
return jsonify(type='success', msg='command completed successfully')
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
else:
|
else:
|
||||||
return jsonify(type='danger', msg='command failed: ' + output.output.decode('utf-8'))
|
res = {
|
||||||
|
"type": "success",
|
||||||
|
"msg": "'command failed: " + exec_return
|
||||||
|
}
|
||||||
|
return Response(content=json.dumps(res, indent=4), media_type="application/json")
|
||||||
if type == 'utf8_text_only':
|
if type == 'utf8_text_only':
|
||||||
r = Response(response=output.output.decode('utf-8'), status=200, mimetype="text/plain")
|
return Response(content=exec_return, media_type="text/plain")
|
||||||
r.headers["Content-Type"] = "text/plain; charset=utf-8"
|
|
||||||
return r
|
|
||||||
|
|
||||||
class GracefulKiller:
|
async def get_host_stats(wait=5):
|
||||||
kill_now = False
|
global host_stats_isUpdating
|
||||||
def __init__(self):
|
|
||||||
signal.signal(signal.SIGINT, self.exit_gracefully)
|
|
||||||
signal.signal(signal.SIGTERM, self.exit_gracefully)
|
|
||||||
|
|
||||||
def exit_gracefully(self, signum, frame):
|
|
||||||
self.kill_now = True
|
|
||||||
|
|
||||||
def create_self_signed_cert():
|
|
||||||
process = subprocess.Popen(
|
|
||||||
"openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /app/dockerapi_key.pem -out /app/dockerapi_cert.pem -subj /CN=dockerapi/O=mailcow -addext subjectAltName=DNS:dockerapi".split(),
|
|
||||||
stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell=False
|
|
||||||
)
|
|
||||||
process.wait()
|
|
||||||
|
|
||||||
def startFlaskAPI():
|
|
||||||
create_self_signed_cert()
|
|
||||||
try:
|
try:
|
||||||
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
system_time = datetime.now()
|
||||||
ctx.check_hostname = False
|
host_stats = {
|
||||||
ctx.load_cert_chain(certfile='/app/dockerapi_cert.pem', keyfile='/app/dockerapi_key.pem')
|
"cpu": {
|
||||||
except:
|
"cores": psutil.cpu_count(),
|
||||||
print ("Cannot initialize TLS, retrying in 5s...")
|
"usage": psutil.cpu_percent()
|
||||||
time.sleep(5)
|
},
|
||||||
app.run(debug=False, host='0.0.0.0', port=443, threaded=True, ssl_context=ctx)
|
"memory": {
|
||||||
|
"total": psutil.virtual_memory().total,
|
||||||
|
"usage": psutil.virtual_memory().percent,
|
||||||
|
"swap": psutil.swap_memory()
|
||||||
|
},
|
||||||
|
"uptime": time.time() - psutil.boot_time(),
|
||||||
|
"system_time": system_time.strftime("%d.%m.%Y %H:%M:%S")
|
||||||
|
}
|
||||||
|
|
||||||
api.add_resource(containers_get, '/containers/json')
|
redis_client.set('host_stats', json.dumps(host_stats), ex=10)
|
||||||
api.add_resource(container_get, '/containers/<string:container_id>/json')
|
except Exception as e:
|
||||||
api.add_resource(container_post, '/containers/<string:container_id>/<string:post_action>')
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": str(e)
|
||||||
|
}
|
||||||
|
print(json.dumps(res, indent=4))
|
||||||
|
|
||||||
if __name__ == '__main__':
|
await asyncio.sleep(wait)
|
||||||
api_thread = Thread(target=startFlaskAPI)
|
host_stats_isUpdating = False
|
||||||
api_thread.daemon = True
|
|
||||||
api_thread.start()
|
|
||||||
killer = GracefulKiller()
|
async def get_container_stats(container_id, wait=5, stop=False):
|
||||||
while True:
|
global containerIds_to_update
|
||||||
time.sleep(1)
|
|
||||||
if killer.kill_now:
|
if container_id and container_id.isalnum():
|
||||||
break
|
try:
|
||||||
print ("Stopping dockerapi-mailcow")
|
for container in (await async_docker_client.containers.list()):
|
||||||
|
if container._id == container_id:
|
||||||
|
res = await container.stats(stream=False)
|
||||||
|
|
||||||
|
if redis_client.exists(container_id + '_stats'):
|
||||||
|
stats = json.loads(redis_client.get(container_id + '_stats'))
|
||||||
|
else:
|
||||||
|
stats = []
|
||||||
|
stats.append(res[0])
|
||||||
|
if len(stats) > 3:
|
||||||
|
del stats[0]
|
||||||
|
redis_client.set(container_id + '_stats', json.dumps(stats), ex=60)
|
||||||
|
except Exception as e:
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": str(e)
|
||||||
|
}
|
||||||
|
print(json.dumps(res, indent=4))
|
||||||
|
else:
|
||||||
|
res = {
|
||||||
|
"type": "danger",
|
||||||
|
"msg": "no or invalid id defined"
|
||||||
|
}
|
||||||
|
print(json.dumps(res, indent=4))
|
||||||
|
|
||||||
|
await asyncio.sleep(wait)
|
||||||
|
if stop == True:
|
||||||
|
# update task was called second time, stop
|
||||||
|
containerIds_to_update.remove(container_id)
|
||||||
|
else:
|
||||||
|
# call update task a second time
|
||||||
|
await get_container_stats(container_id, wait=0, stop=True)
|
||||||
|
|
||||||
|
|
||||||
|
if os.environ['REDIS_SLAVEOF_IP'] != "":
|
||||||
|
redis_client = redis.Redis(host=os.environ['REDIS_SLAVEOF_IP'], port=os.environ['REDIS_SLAVEOF_PORT'], db=0)
|
||||||
|
else:
|
||||||
|
redis_client = redis.Redis(host='redis-mailcow', port=6379, db=0)
|
||||||
|
|
||||||
|
async_docker_client = aiodocker.Docker(url='unix:///var/run/docker.sock')
|
||||||
@@ -2,9 +2,12 @@ FROM debian:bullseye-slim
|
|||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG DOVECOT=2.3.19.1
|
# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced
|
||||||
|
ARG DOVECOT=2.3.20
|
||||||
|
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced
|
||||||
|
ARG GOSU_VERSION=1.16
|
||||||
ENV LC_ALL C
|
ENV LC_ALL C
|
||||||
ENV GOSU_VERSION 1.14
|
|
||||||
|
|
||||||
# Add groups and users before installing Dovecot to not break compatibility
|
# Add groups and users before installing Dovecot to not break compatibility
|
||||||
RUN groupadd -g 5000 vmail \
|
RUN groupadd -g 5000 vmail \
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
ENV XTABLES_LIBDIR /usr/lib/xtables
|
ENV XTABLES_LIBDIR /usr/lib/xtables
|
||||||
|
|||||||
@@ -97,9 +97,9 @@ def refreshF2bregex():
|
|||||||
f2bregex[3] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+'
|
f2bregex[3] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+'
|
||||||
f2bregex[4] = 'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+'
|
f2bregex[4] = 'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+'
|
||||||
f2bregex[5] = 'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
|
f2bregex[5] = 'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
|
||||||
f2bregex[6] = '-login: Disconnected \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),'
|
f2bregex[6] = '-login: Disconnected.+ \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),'
|
||||||
f2bregex[7] = '-login: Aborted login \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
f2bregex[7] = '-login: Aborted login.+ \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||||
f2bregex[8] = '-login: Aborted login \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
f2bregex[8] = '-login: Aborted login.+ \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+'
|
||||||
f2bregex[9] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
|
f2bregex[9] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
|
||||||
f2bregex[10] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
|
f2bregex[10] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
|
||||||
r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False))
|
r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@@ -1,12 +1,18 @@
|
|||||||
FROM php:8.1-fpm-alpine3.16
|
FROM php:8.1-fpm-alpine3.17
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
ENV APCU_PECL 5.1.22
|
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced
|
||||||
ENV IMAGICK_PECL 3.7.0
|
ARG APCU_PECL_VERSION=5.1.22
|
||||||
ENV MAILPARSE_PECL 3.1.4
|
# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced
|
||||||
ENV MEMCACHED_PECL 3.2.0
|
ARG IMAGICK_PECL_VERSION=3.7.0
|
||||||
ENV REDIS_PECL 5.3.7
|
# renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced
|
||||||
ENV COMPOSER 2.4.4
|
ARG MAILPARSE_PECL_VERSION=3.1.4
|
||||||
|
# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced
|
||||||
|
ARG MEMCACHED_PECL_VERSION=3.2.0
|
||||||
|
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced
|
||||||
|
ARG REDIS_PECL_VERSION=5.3.7
|
||||||
|
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced
|
||||||
|
ARG COMPOSER_VERSION=2.5.1
|
||||||
|
|
||||||
RUN apk add -U --no-cache autoconf \
|
RUN apk add -U --no-cache autoconf \
|
||||||
aspell-dev \
|
aspell-dev \
|
||||||
@@ -55,11 +61,11 @@ RUN apk add -U --no-cache autoconf \
|
|||||||
samba-client \
|
samba-client \
|
||||||
zlib-dev \
|
zlib-dev \
|
||||||
tzdata \
|
tzdata \
|
||||||
&& pecl install mailparse-${MAILPARSE_PECL} \
|
&& pecl install APCu-${APCU_PECL_VERSION} \
|
||||||
&& pecl install redis-${REDIS_PECL} \
|
&& pecl install imagick-${IMAGICK_PECL_VERSION} \
|
||||||
&& pecl install memcached-${MEMCACHED_PECL} \
|
&& pecl install mailparse-${MAILPARSE_PECL_VERSION} \
|
||||||
&& pecl install APCu-${APCU_PECL} \
|
&& pecl install memcached-${MEMCACHED_PECL_VERSION} \
|
||||||
&& pecl install imagick-${IMAGICK_PECL} \
|
&& pecl install redis-${REDIS_PECL_VERSION} \
|
||||||
&& docker-php-ext-enable apcu imagick memcached mailparse redis \
|
&& docker-php-ext-enable apcu imagick memcached mailparse redis \
|
||||||
&& pecl clear-cache \
|
&& pecl clear-cache \
|
||||||
&& docker-php-ext-configure intl \
|
&& docker-php-ext-configure intl \
|
||||||
@@ -72,7 +78,7 @@ RUN apk add -U --no-cache autoconf \
|
|||||||
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
|
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
|
||||||
&& docker-php-ext-configure imap --with-imap --with-imap-ssl \
|
&& docker-php-ext-configure imap --with-imap --with-imap-ssl \
|
||||||
&& docker-php-ext-install -j 4 imap \
|
&& docker-php-ext-install -j 4 imap \
|
||||||
&& curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER} \
|
&& curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \
|
||||||
&& mv composer.phar /usr/local/bin/composer \
|
&& mv composer.phar /usr/local/bin/composer \
|
||||||
&& chmod +x /usr/local/bin/composer \
|
&& chmod +x /usr/local/bin/composer \
|
||||||
&& apk del --purge autoconf \
|
&& apk del --purge autoconf \
|
||||||
@@ -102,4 +108,4 @@ COPY ./docker-entrypoint.sh /
|
|||||||
|
|
||||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
|
||||||
CMD ["php-fpm"]
|
CMD ["php-fpm"]
|
||||||
@@ -26,6 +26,7 @@ RUN apt-get update && apt-get install -y \
|
|||||||
|
|
||||||
COPY settings.conf /etc/rspamd/settings.conf
|
COPY settings.conf /etc/rspamd/settings.conf
|
||||||
COPY metadata_exporter.lua /usr/share/rspamd/plugins/metadata_exporter.lua
|
COPY metadata_exporter.lua /usr/share/rspamd/plugins/metadata_exporter.lua
|
||||||
|
COPY set_worker_password.sh /set_worker_password.sh
|
||||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
|
||||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
password_file='/etc/rspamd/override.d/worker-controller-password.inc'
|
||||||
|
password_hash=`/usr/bin/rspamadm pw -e -p $1`
|
||||||
|
|
||||||
|
echo 'enable_password = "'$password_hash'";' > $password_file
|
||||||
|
|
||||||
|
if grep -q "$password_hash" "$password_file"; then
|
||||||
|
echo "OK"
|
||||||
|
else
|
||||||
|
echo "ERROR"
|
||||||
|
fi
|
||||||
@@ -3,8 +3,9 @@ LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
|||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/
|
ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/
|
||||||
|
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced
|
||||||
|
ARG GOSU_VERSION=1.16
|
||||||
ENV LC_ALL C
|
ENV LC_ALL C
|
||||||
ENV GOSU_VERSION 1.14
|
|
||||||
|
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
|
RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ FROM solr:7.7-slim
|
|||||||
|
|
||||||
USER root
|
USER root
|
||||||
|
|
||||||
ENV GOSU_VERSION 1.11
|
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced
|
||||||
|
ARG GOSU_VERSION=1.16
|
||||||
|
|
||||||
COPY solr.sh /
|
COPY solr.sh /
|
||||||
COPY solr-config-7.7.0.xml /
|
COPY solr-config-7.7.0.xml /
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
|
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM alpine:3.16
|
FROM alpine:3.17
|
||||||
LABEL maintainer "André Peters <andre.peters@servercow.de>"
|
LABEL maintainer "André Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
# Installation
|
# Installation
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
/.*episerver.*/i
|
/.*episerver.*/i
|
||||||
/.*supergewinne.*/i
|
/.*supergewinne.*/i
|
||||||
/List-Unsubscribe.*nbps\.eu/i
|
/List-Unsubscribe.*nbps\.eu/i
|
||||||
/X-Mailer: AWeber.*/i
|
|
||||||
/.*regiofinder.*/i
|
/.*regiofinder.*/i
|
||||||
/.*EmailSocket.*/i
|
/.*EmailSocket.*/i
|
||||||
/List-Unsubscribe:.*respread.*/i
|
/List-Unsubscribe:.*respread.*/i
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ $rcpts = $headers['X-Rspamd-Rcpt'];
|
|||||||
$sender = $headers['X-Rspamd-From'];
|
$sender = $headers['X-Rspamd-From'];
|
||||||
$ip = $headers['X-Rspamd-Ip'];
|
$ip = $headers['X-Rspamd-Ip'];
|
||||||
$subject = $headers['X-Rspamd-Subject'];
|
$subject = $headers['X-Rspamd-Subject'];
|
||||||
|
$messageid= $json_body->message_id;
|
||||||
$priority = 0;
|
$priority = 0;
|
||||||
|
|
||||||
$symbols_array = json_decode($headers['X-Rspamd-Symbols'], true);
|
$symbols_array = json_decode($headers['X-Rspamd-Symbols'], true);
|
||||||
@@ -245,13 +246,13 @@ foreach ($rcpt_final_mailboxes as $rcpt_final) {
|
|||||||
"token" => $api_data['token'],
|
"token" => $api_data['token'],
|
||||||
"user" => $api_data['key'],
|
"user" => $api_data['key'],
|
||||||
"title" => sprintf("%s", str_replace(
|
"title" => sprintf("%s", str_replace(
|
||||||
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}'),
|
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}'),
|
||||||
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address), $title)
|
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid), $title)
|
||||||
),
|
),
|
||||||
"priority" => $priority,
|
"priority" => $priority,
|
||||||
"message" => sprintf("%s", str_replace(
|
"message" => sprintf("%s", str_replace(
|
||||||
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '\n'),
|
array('{SUBJECT}', '{SENDER}', '{SENDER_NAME}', '{SENDER_ADDRESS}', '{TO_NAME}', '{TO_ADDRESS}', '{MSG_ID}', '\n'),
|
||||||
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, PHP_EOL), $text)
|
array($subject, $sender, $sender_name, $sender_address, $to_name, $to_address, $messageid, PHP_EOL), $text)
|
||||||
),
|
),
|
||||||
"sound" => $attributes['sound'] ?? "pushover"
|
"sound" => $attributes['sound'] ?? "pushover"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
Please check the logs or contact support if the error persists.</p>
|
Please check the logs or contact support if the error persists.</p>
|
||||||
<h2>Quick debugging</h2>
|
<h2>Quick debugging</h2>
|
||||||
<p>Check Nginx and PHP logs:</p>
|
<p>Check Nginx and PHP logs:</p>
|
||||||
<pre>docker-compose logs --tail=200 php-fpm-mailcow nginx-mailcow</pre>
|
<pre>docker compose logs --tail=200 php-fpm-mailcow nginx-mailcow</pre>
|
||||||
<p>Make sure your SQL credentials in mailcow.conf (a link to .env) do fit your initialized SQL volume. If you see an access denied, you might have the wrong mailcow.conf:</p>
|
<p>Make sure your SQL credentials in mailcow.conf (a link to .env) do fit your initialized SQL volume. If you see an access denied, you might have the wrong mailcow.conf:</p>
|
||||||
<pre>source mailcow.conf ; docker-compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}</pre>
|
<pre>source mailcow.conf ; docker compose exec mysql-mailcow mysql -u${DBUSER} -p${DBPASS} ${DBNAME}</pre>
|
||||||
<p>In case of a previous failed installation, create a backup of your existing data, followed by removing all volumes and starting over (<b>NEVER</b> do this with a production system, it will remove <b>ALL</b> data):</p>
|
<p>In case of a previous failed installation, create a backup of your existing data, followed by removing all volumes and starting over (<b>NEVER</b> do this with a production system, it will remove <b>ALL</b> data):</p>
|
||||||
<pre>BACKUP_LOCATION=/tmp/ ./helper-scripts/backup_and_restore.sh backup all</pre>
|
<pre>BACKUP_LOCATION=/tmp/ ./helper-scripts/backup_and_restore.sh backup all</pre>
|
||||||
<pre>docker-compose down --volumes ; docker-compose up -d</pre>
|
<pre>docker compose down --volumes ; docker compose up -d</pre>
|
||||||
<p>Make sure your timezone is correct. Use "America/New_York" for example, do not use spaces. Check <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">here</a> for a list.</p>
|
<p>Make sure your timezone is correct. Use "America/New_York" for example, do not use spaces. Check <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">here</a> for a list.</p>
|
||||||
<br>Click to learn more about <a style="color:red;text-decoration:none;" href="https://mailcow.github.io/mailcow-dockerized-docs/#get-support" target="_blank">getting support.</a>
|
<br>Click to learn more about <a style="color:red;text-decoration:none;" href="https://mailcow.github.io/mailcow-dockerized-docs/#get-support" target="_blank">getting support.</a>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
+2
-6
@@ -10,9 +10,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
|
|||||||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||||
$tfa_data = get_tfa();
|
$tfa_data = get_tfa();
|
||||||
$fido2_data = fido2(array("action" => "get_friendly_names"));
|
$fido2_data = fido2(array("action" => "get_friendly_names"));
|
||||||
if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CACHE')) {
|
|
||||||
$_SESSION['gal'] = json_decode($license_cache, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$js_minifier->add('/web/js/site/admin.js');
|
$js_minifier->add('/web/js/site/admin.js');
|
||||||
$js_minifier->add('/web/js/presets/rspamd.js');
|
$js_minifier->add('/web/js/presets/rspamd.js');
|
||||||
@@ -83,15 +80,12 @@ foreach ($RSPAMD_MAPS['regex'] as $rspamd_regex_desc => $rspamd_regex_map) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$template = 'admin.twig';
|
$template = 'admin.twig';
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'tfa_data' => $tfa_data,
|
'tfa_data' => $tfa_data,
|
||||||
'tfa_id' => @$_SESSION['tfa_id'],
|
'tfa_id' => @$_SESSION['tfa_id'],
|
||||||
'fido2_cid' => @$_SESSION['fido2_cid'],
|
'fido2_cid' => @$_SESSION['fido2_cid'],
|
||||||
'fido2_data' => $fido2_data,
|
'fido2_data' => $fido2_data,
|
||||||
'gal' => @$_SESSION['gal'],
|
|
||||||
'license_guid' => license('guid'),
|
|
||||||
'api' => [
|
'api' => [
|
||||||
'ro' => admin_api('ro', 'get'),
|
'ro' => admin_api('ro', 'get'),
|
||||||
'rw' => admin_api('rw', 'get'),
|
'rw' => admin_api('rw', 'get'),
|
||||||
@@ -109,9 +103,11 @@ $template_data = [
|
|||||||
'rsettings' => $rsettings,
|
'rsettings' => $rsettings,
|
||||||
'rspamd_regex_maps' => $rspamd_regex_maps,
|
'rspamd_regex_maps' => $rspamd_regex_maps,
|
||||||
'logo_specs' => customize('get', 'main_logo_specs'),
|
'logo_specs' => customize('get', 'main_logo_specs'),
|
||||||
|
'ip_check' => customize('get', 'ip_check'),
|
||||||
'password_complexity' => password_complexity('get'),
|
'password_complexity' => password_complexity('get'),
|
||||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||||
'lang_admin' => json_encode($lang['admin']),
|
'lang_admin' => json_encode($lang['admin']),
|
||||||
|
'lang_datatables' => json_encode($lang['datatables'])
|
||||||
];
|
];
|
||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
/*!
|
|
||||||
* bootswatch v3.4.1
|
|
||||||
* Homepage: http://bootswatch.com
|
|
||||||
* Copyright 2012-2019 Thomas Park
|
|
||||||
* Licensed under MIT
|
|
||||||
* Based on Bootstrap
|
|
||||||
*//*!
|
|
||||||
* Bootstrap v3.4.1 (https://getbootstrap.com/)
|
|
||||||
* Copyright 2011-2019 Twitter, Inc.
|
|
||||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
|
||||||
*//*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */@media print{*,:after,:before{color:#000!important;text-shadow:none!important;background:0 0!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}a[href^="#"]:after,a[href^="javascript:"]:after{content:""}blockquote,pre{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}img,tr{page-break-inside:avoid}img{max-width:100%!important}h2,h3,p{orphans:3;widows:3}h2,h3{page-break-after:avoid}.navbar{display:none}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table td,.table th{background-color:#fff!important}.table-bordered td,.table-bordered th{border:1px solid #ddd!important}}*{box-sizing:border-box}:after,:before{box-sizing:border-box}html{font-size:10px;-webkit-tap-highlight-color:transparent}body{font-family:"Source Sans Pro","Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.42857143;color:#555;background-color:#fff}button,input,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#158cba;text-decoration:none}a:focus,a:hover{color:#158cba;text-decoration:underline}a:focus{outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.carousel-inner>.item>a>img,.carousel-inner>.item>img,.img-responsive,.thumbnail a>img,.thumbnail>img{display:block;max-width:100%;height:auto}.img-rounded{border-radius:5px}.img-thumbnail{padding:4px;line-height:1.42857143;background-color:#fff;border:1px solid #eee;border-radius:4px;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}[role=button]{cursor:pointer}.h1,.h2,.h3,.h4,.h5,.h6,h1,h2,h3,h4,h5,h6{font-family:inherit;font-weight:400;line-height:1.1;color:#333}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-weight:400;line-height:1;color:#999}.h1,.h2,.h3,h1,h2,h3{margin-top:20px;margin-bottom:10px}.h1 .small,.h1 small,.h2 .small,.h2 small,.h3 .small,.h3 small,h1 .small,h1 small,h2 .small,h2 small,h3 .small,h3 small{font-size:65%}.h4,.h5,.h6,h4,h5,h6{margin-top:10px;margin-bottom:10px}.h4 .small,.h4 small,.h5 .small,.h5 small,.h6 .small,.h6 small,h4 .small,h4 small,h5 .small,h5 small,h6 .small,h6 small{font-size:75%}.h1,h1{font-size:36px}.h2,h2{font-size:30px}.h3,h3{font-size:24px}.h4,h4{font-Line truncated
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
@media (max-width:1050px){.navbar-header{float:none}.navbar-left,.navbar-nav,.navbar-right{float:none!important}.navbar-toggle{display:block}.navbar-collapse{border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-collapse.collapse{display:none!important}.navbar-nav{margin-top:7.5px}.navbar-nav>li{float:none}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.collapse.in{display:block!important}.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}}
|
@media (max-width:1050px){.navbar-header{float:none}.navbar-left,.navbar-nav,.navbar-right{float:none!important}.navbar-toggle{display:block}.navbar-collapse{border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1)}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-nav{margin-top:7.5px}.navbar-nav>li{float:none}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px}.collapse.in{display:block!important}.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;-webkit-box-shadow:none;box-shadow:none}}
|
||||||
@@ -0,0 +1,487 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap-select v1.14.0-beta2 (https://developer.snapappointments.com/bootstrap-select)
|
||||||
|
*
|
||||||
|
* Copyright 2012-2021 SnapAppointments, LLC
|
||||||
|
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
|
||||||
|
*/
|
||||||
|
|
||||||
|
@-webkit-keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-o-keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes bs-notify-fadeOut {
|
||||||
|
0% {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select.bs-select-hidden,
|
||||||
|
.bootstrap-select > select.bs-select-hidden,
|
||||||
|
select.selectpicker {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select {
|
||||||
|
width: 220px \0;
|
||||||
|
/*IE9 and below*/
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
display: -webkit-inline-box;
|
||||||
|
display: -webkit-inline-flex;
|
||||||
|
display: -ms-inline-flexbox;
|
||||||
|
display: inline-flex;
|
||||||
|
-webkit-box-align: center;
|
||||||
|
-webkit-align-items: center;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-webkit-box-pack: justify;
|
||||||
|
-webkit-justify-content: space-between;
|
||||||
|
-ms-flex-pack: justify;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle:after {
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
|
||||||
|
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
.bootstrap-select > select {
|
||||||
|
position: absolute !important;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
display: block !important;
|
||||||
|
width: 0.5px !important;
|
||||||
|
height: 100% !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
opacity: 0 !important;
|
||||||
|
border: none;
|
||||||
|
z-index: 0 !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select > select.mobile-device {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
display: block !important;
|
||||||
|
width: 100% !important;
|
||||||
|
z-index: 2 !important;
|
||||||
|
}
|
||||||
|
.has-error .bootstrap-select .dropdown-toggle,
|
||||||
|
.error .bootstrap-select .dropdown-toggle,
|
||||||
|
.bootstrap-select.is-invalid .dropdown-toggle,
|
||||||
|
.was-validated .bootstrap-select select:invalid + .dropdown-toggle {
|
||||||
|
border-color: #b94a48;
|
||||||
|
}
|
||||||
|
.bootstrap-select.is-valid .dropdown-toggle,
|
||||||
|
.was-validated .bootstrap-select select:valid + .dropdown-toggle {
|
||||||
|
border-color: #28a745;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
|
||||||
|
width: 220px;
|
||||||
|
}
|
||||||
|
.bootstrap-select > select.mobile-device:focus + .dropdown-toggle,
|
||||||
|
.bootstrap-select .dropdown-toggle:focus {
|
||||||
|
outline: thin dotted #333333 !important;
|
||||||
|
outline: 5px auto -webkit-focus-ring-color !important;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control {
|
||||||
|
margin-bottom: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: none;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control.input-group-btn {
|
||||||
|
float: none;
|
||||||
|
z-index: auto;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select,
|
||||||
|
.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select:not(.input-group-btn),
|
||||||
|
.bootstrap-select[class*="col-"] {
|
||||||
|
float: none;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.dropdown-menu-right,
|
||||||
|
.bootstrap-select[class*="col-"].dropdown-menu-right,
|
||||||
|
.row .bootstrap-select[class*="col-"].dropdown-menu-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select,
|
||||||
|
.form-horizontal .bootstrap-select,
|
||||||
|
.form-group .bootstrap-select {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
.form-group-lg .bootstrap-select.form-control,
|
||||||
|
.form-group-sm .bootstrap-select.form-control {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
|
||||||
|
.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
|
||||||
|
height: 100%;
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-sm .dropdown-toggle,
|
||||||
|
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-sm .dropdown-toggle {
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
.bootstrap-select.form-control-lg .dropdown-toggle {
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
.form-inline .bootstrap-select .form-control {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select.disabled,
|
||||||
|
.bootstrap-select > .disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.bootstrap-select.disabled:focus,
|
||||||
|
.bootstrap-select > .disabled:focus {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select.bs-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 0 !important;
|
||||||
|
padding: 0 !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select.bs-container .dropdown-menu {
|
||||||
|
z-index: 1060;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
position: static;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
float: left;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
text-align: left;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-box-flex: 0;
|
||||||
|
-webkit-flex: 0 1 auto;
|
||||||
|
-ms-flex: 0 1 auto;
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
.bs3.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
padding-right: inherit;
|
||||||
|
}
|
||||||
|
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
|
||||||
|
position: absolute;
|
||||||
|
padding-top: inherit;
|
||||||
|
padding-bottom: inherit;
|
||||||
|
padding-left: inherit;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
|
||||||
|
padding-right: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .filter-expand {
|
||||||
|
width: 0 !important;
|
||||||
|
float: left;
|
||||||
|
opacity: 0 !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .caret {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
right: 12px;
|
||||||
|
margin-top: -2px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .bs-select-clear-selected {
|
||||||
|
position: relative;
|
||||||
|
display: block;
|
||||||
|
margin-right: 5px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected {
|
||||||
|
padding-right: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle .bs-select-clear-selected span {
|
||||||
|
position: relative;
|
||||||
|
top: -webkit-calc(((-1em / 1.5) + 1ex) / 2);
|
||||||
|
top: calc(((-1em / 1.5) + 1ex) / 2);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.bs3.bootstrap-select .dropdown-toggle .bs-select-clear-selected span {
|
||||||
|
top: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-toggle.bs-placeholder .bs-select-clear-selected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.input-group .bootstrap-select.form-control .dropdown-toggle {
|
||||||
|
border-radius: inherit;
|
||||||
|
}
|
||||||
|
.bootstrap-select[class*="col-"] .dropdown-toggle {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu {
|
||||||
|
min-width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu > .inner:focus {
|
||||||
|
outline: none !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu.inner {
|
||||||
|
position: static;
|
||||||
|
float: none;
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
-webkit-box-shadow: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li.active small {
|
||||||
|
color: rgba(255, 255, 255, 0.5) !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li.disabled a {
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a {
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a.opt {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 2.25em;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a span.check-mark {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li a span.text {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu li small {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu .notify {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 5px;
|
||||||
|
width: 96%;
|
||||||
|
margin: 0 2%;
|
||||||
|
min-height: 26px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border: 1px solid #e3e3e3;
|
||||||
|
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
|
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.9;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bootstrap-select .dropdown-menu .notify.fadeOut {
|
||||||
|
-webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
-o-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
animation: 300ms linear 750ms forwards bs-notify-fadeOut;
|
||||||
|
}
|
||||||
|
.bootstrap-select .no-results {
|
||||||
|
padding: 3px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
margin: 0 5px;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option {
|
||||||
|
position: static;
|
||||||
|
display: inline;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
|
||||||
|
content: '\00a0';
|
||||||
|
}
|
||||||
|
.bootstrap-select.fit-width .dropdown-toggle .caret {
|
||||||
|
position: static;
|
||||||
|
top: auto;
|
||||||
|
margin-top: -1px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
right: 15px;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-tick .dropdown-menu li a span.text {
|
||||||
|
margin-right: 34px;
|
||||||
|
}
|
||||||
|
.bootstrap-select .bs-ok-default:after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
width: 0.5em;
|
||||||
|
height: 1em;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0 0.26em 0.26em 0;
|
||||||
|
-webkit-transform-style: preserve-3d;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
-webkit-transform: rotate(45deg);
|
||||||
|
-ms-transform: rotate(45deg);
|
||||||
|
-o-transform: rotate(45deg);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
|
||||||
|
z-index: 1061;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
|
||||||
|
content: '';
|
||||||
|
border-left: 7px solid transparent;
|
||||||
|
border-right: 7px solid transparent;
|
||||||
|
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 9px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
|
||||||
|
content: '';
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid white;
|
||||||
|
position: absolute;
|
||||||
|
bottom: -4px;
|
||||||
|
left: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
|
||||||
|
bottom: auto;
|
||||||
|
top: -4px;
|
||||||
|
border-top: 7px solid rgba(204, 204, 204, 0.2);
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
|
||||||
|
bottom: auto;
|
||||||
|
top: -4px;
|
||||||
|
border-top: 6px solid white;
|
||||||
|
border-bottom: 0;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
|
||||||
|
right: 12px;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
|
||||||
|
right: 13px;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
|
||||||
|
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
|
||||||
|
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bs-searchbox,
|
||||||
|
.bs-actionsbox,
|
||||||
|
.bs-donebutton {
|
||||||
|
padding: 4px 8px;
|
||||||
|
}
|
||||||
|
.bs-actionsbox {
|
||||||
|
width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bs-actionsbox .btn-group {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bs-actionsbox .btn-group button {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.bs-donebutton {
|
||||||
|
float: left;
|
||||||
|
width: 100%;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.bs-donebutton .btn-group {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.bs-donebutton .btn-group button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.bs-searchbox + .bs-actionsbox {
|
||||||
|
padding: 0 8px 4px;
|
||||||
|
}
|
||||||
|
.bs-searchbox .form-control {
|
||||||
|
margin-bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=bootstrap-select.css.map */
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap-select v1.12.2 (http://silviomoreto.github.io/bootstrap-select)
|
|
||||||
*
|
|
||||||
* Copyright 2013-2017 bootstrap-select
|
|
||||||
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
|
|
||||||
*/select.bs-select-hidden,select.selectpicker{display:none!important}.bootstrap-select{width:220px\9}.bootstrap-select>.dropdown-toggle{width:100%;padding-right:25px;z-index:1}.bootstrap-select>.dropdown-toggle.bs-placeholder,.bootstrap-select>.dropdown-toggle.bs-placeholder:active,.bootstrap-select>.dropdown-toggle.bs-placeholder:focus,.bootstrap-select>.dropdown-toggle.bs-placeholder:hover{color:#999}.bootstrap-select>select{position:absolute!important;bottom:0;left:50%;display:block!important;width:.5px!important;height:100%!important;padding:0!important;opacity:0!important;border:none}.bootstrap-select>select.mobile-device{top:0;left:0;display:block!important;width:100%!important;z-index:2}.error .bootstrap-select .dropdown-toggle,.has-error .bootstrap-select .dropdown-toggle{border-color:#b94a48}.bootstrap-select.fit-width{width:auto!important}.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn){width:220px}.bootstrap-select .dropdown-toggle:focus{outline:thin dotted #333!important;outline:5px auto -webkit-focus-ring-color!important;outline-offset:-2px}.bootstrap-select.form-control{margin-bottom:0;padding:0;border:none}.bootstrap-select.form-control:not([class*=col-]){width:100%}.bootstrap-select.form-control.input-group-btn{z-index:auto}.bootstrap-select.form-control.input-group-btn:not(:first-child):not(:last-child)>.btn{border-radius:0}.bootstrap-select.btn-group:not(.input-group-btn),.bootstrap-select.btn-group[class*=col-]{float:none;display:inline-block;margin-left:0}.bootstrap-select.btn-group.dropdown-menu-right,.bootstrap-select.btn-group[class*=col-].dropdown-menu-right,.row .bootstrap-select.btn-group[class*=col-].dropdown-menu-right{float:right}.form-group .bootstrap-select.btn-group,.form-horizontal .bootstrap-select.btn-group,.form-inline .bootstrap-select.btn-group{margin-bottom:0}.form-group-lg .bootstrap-select.btn-group.form-control,.form-group-sm .bootstrap-select.btn-group.form-control{padding:0}.form-group-lg .bootstrap-select.btn-group.form-control .dropdown-toggle,.form-group-sm .bootstrap-select.btn-group.form-control .dropdown-toggle{height:100%;font-size:inherit;line-height:inherit;border-radius:inherit}.form-inline .bootstrap-select.btn-group .form-control{width:100%}.bootstrap-select.btn-group.disabled,.bootstrap-select.btn-group>.disabled{cursor:not-allowed}.bootstrap-select.btn-group.disabled:focus,.bootstrap-select.btn-group>.disabled:focus{outline:0!important}.bootstrap-select.btn-group.bs-container{position:absolute;height:0!important;padding:0!important}.bootstrap-select.btn-group.bs-container .dropdown-menu{z-index:1060}.bootstrap-select.btn-group .dropdown-toggle .filter-option{display:inline-block;overflow:hidden;width:100%;text-align:left}.bootstrap-select.btn-group .dropdown-toggle .caret{position:absolute;top:50%;right:12px;margin-top:-2px;vertical-align:middle}.bootstrap-select.btn-group[class*=col-] .dropdown-toggle{width:100%}.bootstrap-select.btn-group .dropdown-menu{min-width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .dropdown-menu.inner{position:static;float:none;border:0;padding:0;margin:0;border-radius:0;-webkit-box-shadow:none;box-shadow:none}.bootstrap-select.btn-group .dropdown-menu li{position:relative}.bootstrap-select.btn-group .dropdown-menu li.active small{color:#fff}.bootstrap-select.btn-group .dropdown-menu li.disabled a{cursor:not-allowed}.bootstrap-select.btn-group .dropdown-menu li a{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.bootstrap-select.btn-group .dropdown-menu li a.opt{position:relative;padding-left:2.25em}.bootstrap-select.btn-group .dropdown-menu li a span.check-mark{display:none}.bootstrap-select.btn-group .dropdown-menu li a span.text{display:inline-block}.bootstrap-select.btn-group .dropdown-menu li small{padding-left:.5em}.bootstrap-select.btn-group .dropdown-menu .notify{position:absolute;bottom:5px;width:96%;margin:0 2%;min-height:26px;padding:3px 5px;background:#f5f5f5;border:1px solid #e3e3e3;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05);pointer-events:none;opacity:.9;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.bootstrap-select.btn-group .no-results{padding:3px;background:#f5f5f5;margin:0 5px;white-space:nowrap}.bootstrap-select.btn-group.fit-width .dropdown-toggle .filter-option{position:static}.bootstrap-select.btn-group.fit-width .dropdown-toggle .caret{position:static;top:auto;margin-top:-1px}.bootstrap-select.btn-group.show-tick .dropdown-menu li.selected a span.check-mark{position:absolute;display:inline-block;right:15px;margin-top:5px}.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text{margin-right:34px}.bootstrap-select.show-menu-arrow.open>.dropdown-toggle{z-index:1061}.bootstrap-select.show-menu-arrow .dropdown-toggle:before{content:'';border-left:7px solidLine truncated
|
|
||||||
-323
@@ -1,323 +0,0 @@
|
|||||||
table.footable-details,
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
table.footable,
|
|
||||||
table.footable-details {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
border-spacing: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
table.footable-hide-fouc {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
table > tbody > tr > td > span.footable-toggle {
|
|
||||||
margin-right: 8px;
|
|
||||||
opacity: 0.3;
|
|
||||||
}
|
|
||||||
table > tbody > tr > td > span.footable-toggle.last-column {
|
|
||||||
margin-left: 8px;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
table.table-condensed > tbody > tr > td > span.footable-toggle {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
table.footable-details > tbody > tr > th:nth-child(1) {
|
|
||||||
min-width: 40px;
|
|
||||||
width: 120px;
|
|
||||||
}
|
|
||||||
table.footable-details > tbody > tr > td:nth-child(2) {
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
table.footable-details > tbody > tr:first-child > td,
|
|
||||||
table.footable-details > tbody > tr:first-child > th,
|
|
||||||
table.footable-details > tfoot > tr:first-child > td,
|
|
||||||
table.footable-details > tfoot > tr:first-child > th,
|
|
||||||
table.footable-details > thead > tr:first-child > td,
|
|
||||||
table.footable-details > thead > tr:first-child > th {
|
|
||||||
border-top-width: 0;
|
|
||||||
}
|
|
||||||
table.footable-details.table-bordered > tbody > tr:first-child > td,
|
|
||||||
table.footable-details.table-bordered > tbody > tr:first-child > th,
|
|
||||||
table.footable-details.table-bordered > tfoot > tr:first-child > td,
|
|
||||||
table.footable-details.table-bordered > tfoot > tr:first-child > th,
|
|
||||||
table.footable-details.table-bordered > thead > tr:first-child > td,
|
|
||||||
table.footable-details.table-bordered > thead > tr:first-child > th {
|
|
||||||
border-top-width: 1px;
|
|
||||||
}
|
|
||||||
div.footable-loader {
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
|
||||||
height: 300px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
div.footable-loader > span.fooicon {
|
|
||||||
display: inline-block;
|
|
||||||
opacity: 0.3;
|
|
||||||
font-size: 30px;
|
|
||||||
line-height: 32px;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
margin-top: -16px;
|
|
||||||
margin-left: -16px;
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
-webkit-animation: fooicon-spin-r 2s infinite linear;
|
|
||||||
animation: fooicon-spin-r 2s infinite linear;
|
|
||||||
}
|
|
||||||
table.footable > tbody > tr.footable-empty > td {
|
|
||||||
vertical-align: middle;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
table.footable > tbody > tr > td,
|
|
||||||
table.footable > tbody > tr > th {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
table.footable > tbody > tr.footable-detail-row > td,
|
|
||||||
table.footable > tbody > tr.footable-detail-row > th,
|
|
||||||
table.footable > tbody > tr.footable-empty > td,
|
|
||||||
table.footable > tbody > tr.footable-empty > th {
|
|
||||||
display: table-cell;
|
|
||||||
}
|
|
||||||
@-webkit-keyframes fooicon-spin-r {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
-webkit-transform: rotate(359deg);
|
|
||||||
transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes fooicon-spin-r {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: rotate(0);
|
|
||||||
transform: rotate(0);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
-webkit-transform: rotate(359deg);
|
|
||||||
transform: rotate(359deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fooicon {
|
|
||||||
position: relative;
|
|
||||||
top: 0px;
|
|
||||||
display: inline-block;
|
|
||||||
font-family: "bootstrap-icons" !important;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 400;
|
|
||||||
line-height: 1;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
@-moz-document url-prefix() {
|
|
||||||
.fooicon {
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fooicon:after,
|
|
||||||
.fooicon:before {
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.fooicon-loader:before {
|
|
||||||
content: "\f130";
|
|
||||||
}
|
|
||||||
.fooicon-plus:before {
|
|
||||||
content: "\f4fd";
|
|
||||||
}
|
|
||||||
.fooicon-minus:before {
|
|
||||||
content: "\f2e9";
|
|
||||||
}
|
|
||||||
.fooicon-search:before {
|
|
||||||
content: "\f52a";
|
|
||||||
}
|
|
||||||
.fooicon-remove:before {
|
|
||||||
content: "\f62a";
|
|
||||||
}
|
|
||||||
.fooicon-sort:before {
|
|
||||||
content: "\f3c6";
|
|
||||||
}
|
|
||||||
.fooicon-sort-asc:before {
|
|
||||||
content: "\f575";
|
|
||||||
}
|
|
||||||
.fooicon-sort-desc:before {
|
|
||||||
content: "\f57b";
|
|
||||||
}
|
|
||||||
.fooicon-pencil:before {
|
|
||||||
content: "\f4c9";
|
|
||||||
}
|
|
||||||
.fooicon-trash:before {
|
|
||||||
content: "\f62a";
|
|
||||||
}
|
|
||||||
.fooicon-eye-close:before {
|
|
||||||
content: "\f33f";
|
|
||||||
}
|
|
||||||
.fooicon-flash:before {
|
|
||||||
content: "\f46e";
|
|
||||||
}
|
|
||||||
.fooicon-cog:before {
|
|
||||||
content: "\f3e2";
|
|
||||||
}
|
|
||||||
.fooicon-stats:before {
|
|
||||||
content: "\f359";
|
|
||||||
}
|
|
||||||
table.footable > thead > tr.footable-filtering > th {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
.footable-filtering-external.footable-filtering-right,
|
|
||||||
table.footable.footable-filtering-right > thead > tr.footable-filtering > th,
|
|
||||||
table.footable > thead > tr.footable-filtering > th {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
.footable-filtering-external.footable-filtering-left,
|
|
||||||
table.footable.footable-filtering-left > thead > tr.footable-filtering > th {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.footable-filtering-external.footable-filtering-center,
|
|
||||||
.footable-paging-external.footable-paging-center,
|
|
||||||
table.footable-paging-center > tfoot > tr.footable-paging > td,
|
|
||||||
table.footable.footable-filtering-center > thead > tr.footable-filtering > th,
|
|
||||||
table.footable > tfoot > tr.footable-paging > td {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.form-group + div.form-group {
|
|
||||||
margin-top: 5px;
|
|
||||||
}
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox,
|
|
||||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox {
|
|
||||||
margin: 0;
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox > label,
|
|
||||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox > label {
|
|
||||||
display: block;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.footable-filtering-external ul.dropdown-menu > li > a.checkbox input[type="checkbox"],
|
|
||||||
table.footable > thead > tr.footable-filtering > th ul.dropdown-menu > li > a.checkbox input[type="checkbox"] {
|
|
||||||
position: absolute;
|
|
||||||
margin-left: -20px;
|
|
||||||
}
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.input-group {
|
|
||||||
width: auto;
|
|
||||||
}
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.form-group {
|
|
||||||
margin-left: 2px;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
table.footable > thead > tr.footable-filtering > th div.form-group + div.form-group {
|
|
||||||
margin-top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.footable > tbody > tr > td.footable-sortable,
|
|
||||||
table.footable > tbody > tr > th.footable-sortable,
|
|
||||||
table.footable > tfoot > tr > td.footable-sortable,
|
|
||||||
table.footable > tfoot > tr > th.footable-sortable,
|
|
||||||
table.footable > thead > tr > td.footable-sortable,
|
|
||||||
table.footable > thead > tr > th.footable-sortable {
|
|
||||||
position: relative;
|
|
||||||
padding-right: 30px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
td.footable-sortable > span.fooicon,
|
|
||||||
th.footable-sortable > span.fooicon {
|
|
||||||
position: absolute;
|
|
||||||
right: 6px;
|
|
||||||
top: 50%;
|
|
||||||
margin-top: -7px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease-in;
|
|
||||||
}
|
|
||||||
td.footable-sortable.footable-asc > span.fooicon,
|
|
||||||
td.footable-sortable.footable-desc > span.fooicon,
|
|
||||||
td.footable-sortable:hover > span.fooicon,
|
|
||||||
th.footable-sortable.footable-asc > span.fooicon,
|
|
||||||
th.footable-sortable.footable-desc > span.fooicon,
|
|
||||||
th.footable-sortable:hover > span.fooicon {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
table.footable-sorting-disabled td.footable-sortable.footable-asc > span.fooicon,
|
|
||||||
table.footable-sorting-disabled td.footable-sortable.footable-desc > span.fooicon,
|
|
||||||
table.footable-sorting-disabled td.footable-sortable:hover > span.fooicon,
|
|
||||||
table.footable-sorting-disabled th.footable-sortable.footable-asc > span.fooicon,
|
|
||||||
table.footable-sorting-disabled th.footable-sortable.footable-desc > span.fooicon,
|
|
||||||
table.footable-sorting-disabled th.footable-sortable:hover > span.fooicon {
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
.footable-paging-external ul.pagination,
|
|
||||||
table.footable > tfoot > tr.footable-paging > td > ul.pagination {
|
|
||||||
margin: 10px 0 0;
|
|
||||||
}
|
|
||||||
.footable-paging-external span.label,
|
|
||||||
table.footable > tfoot > tr.footable-paging > td > span.label {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 0 10px;
|
|
||||||
padding: 4px 10px;
|
|
||||||
}
|
|
||||||
.footable-paging-external.footable-paging-left,
|
|
||||||
table.footable-paging-left > tfoot > tr.footable-paging > td {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.footable-paging-external.footable-paging-right,
|
|
||||||
table.footable-editing-right td.footable-editing,
|
|
||||||
table.footable-editing-right tr.footable-editing,
|
|
||||||
table.footable-paging-right > tfoot > tr.footable-paging > td {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
ul.pagination > li.footable-page {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
ul.pagination > li.footable-page.visible {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
td.footable-editing {
|
|
||||||
width: 90px;
|
|
||||||
max-width: 90px;
|
|
||||||
}
|
|
||||||
table.footable-editing-no-delete td.footable-editing,
|
|
||||||
table.footable-editing-no-edit td.footable-editing,
|
|
||||||
table.footable-editing-no-view td.footable-editing {
|
|
||||||
width: 70px;
|
|
||||||
max-width: 70px;
|
|
||||||
}
|
|
||||||
table.footable-editing-no-delete.footable-editing-no-view td.footable-editing,
|
|
||||||
table.footable-editing-no-edit.footable-editing-no-delete td.footable-editing,
|
|
||||||
table.footable-editing-no-edit.footable-editing-no-view td.footable-editing {
|
|
||||||
width: 50px;
|
|
||||||
max-width: 50px;
|
|
||||||
}
|
|
||||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view td.footable-editing,
|
|
||||||
table.footable-editing-no-edit.footable-editing-no-delete.footable-editing-no-view th.footable-editing {
|
|
||||||
width: 0;
|
|
||||||
max-width: 0;
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
table.footable-editing-left td.footable-editing,
|
|
||||||
table.footable-editing-left tr.footable-editing {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
table.footable-editing button.footable-add,
|
|
||||||
table.footable-editing button.footable-hide,
|
|
||||||
table.footable-editing-show button.footable-show,
|
|
||||||
table.footable-editing.footable-editing-always-show button.footable-hide,
|
|
||||||
table.footable-editing.footable-editing-always-show button.footable-show,
|
|
||||||
table.footable-editing.footable-editing-always-show.footable-editing-no-add tr.footable-editing {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
table.footable-editing.footable-editing-always-show button.footable-add,
|
|
||||||
table.footable-editing.footable-editing-show button.footable-add,
|
|
||||||
table.footable-editing.footable-editing-show button.footable-hide {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
.flag-icon-background{background-size:contain;background-position:50%;background-repeat:no-repeat}.flag-icon{background-size:contain;background-position:50%;background-repeat:no-repeat;position:relative;display:inline-block;width:1.33333333em;line-height:1em}.flag-icon:before{content:'\00a0'}.flag-icon.flag-icon-squared{width:1em}.flag-icon-ad{background-image:url(../flags/4x3/ad.svg)}.flag-icon-ad.flag-icon-squared{background-image:url(../flags/1x1/ad.svg)}.flag-icon-ae{background-image:url(../flags/4x3/ae.svg)}.flag-icon-ae.flag-icon-squared{background-image:url(../flags/1x1/ae.svg)}.flag-icon-af{background-image:url(../flags/4x3/af.svg)}.flag-icon-af.flag-icon-squared{background-image:url(../flags/1x1/af.svg)}.flag-icon-ag{background-image:url(../flags/4x3/ag.svg)}.flag-icon-ag.flag-icon-squared{background-image:url(../flags/1x1/ag.svg)}.flag-icon-ai{background-image:url(../flags/4x3/ai.svg)}.flag-icon-ai.flag-icon-squared{background-image:url(../flags/1x1/ai.svg)}.flag-icon-al{background-image:url(../flags/4x3/al.svg)}.flag-icon-al.flag-icon-squared{background-image:url(../flags/1x1/al.svg)}.flag-icon-am{background-image:url(../flags/4x3/am.svg)}.flag-icon-am.flag-icon-squared{background-image:url(../flags/1x1/am.svg)}.flag-icon-ao{background-image:url(../flags/4x3/ao.svg)}.flag-icon-ao.flag-icon-squared{background-image:url(../flags/1x1/ao.svg)}.flag-icon-aq{background-image:url(../flags/4x3/aq.svg)}.flag-icon-aq.flag-icon-squared{background-image:url(../flags/1x1/aq.svg)}.flag-icon-ar{background-image:url(../flags/4x3/ar.svg)}.flag-icon-ar.flag-icon-squared{background-image:url(../flags/1x1/ar.svg)}.flag-icon-as{background-image:url(../flags/4x3/as.svg)}.flag-icon-as.flag-icon-squared{background-image:url(../flags/1x1/as.svg)}.flag-icon-at{background-image:url(../flags/4x3/at.svg)}.flag-icon-at.flag-icon-squared{background-image:url(../flags/1x1/at.svg)}.flag-icon-au{background-image:url(../flags/4x3/au.svg)}.flag-icon-au.flag-icon-squared{background-image:url(../flags/1x1/au.svg)}.flag-icon-aw{background-image:url(../flags/4x3/aw.svg)}.flag-icon-aw.flag-icon-squared{background-image:url(../flags/1x1/aw.svg)}.flag-icon-ax{background-image:url(../flags/4x3/ax.svg)}.flag-icon-ax.flag-icon-squared{background-image:url(../flags/1x1/ax.svg)}.flag-icon-az{background-image:url(../flags/4x3/az.svg)}.flag-icon-az.flag-icon-squared{background-image:url(../flags/1x1/az.svg)}.flag-icon-ba{background-image:url(../flags/4x3/ba.svg)}.flag-icon-ba.flag-icon-squared{background-image:url(../flags/1x1/ba.svg)}.flag-icon-bb{background-image:url(../flags/4x3/bb.svg)}.flag-icon-bb.flag-icon-squared{background-image:url(../flags/1x1/bb.svg)}.flag-icon-bd{background-image:url(../flags/4x3/bd.svg)}.flag-icon-bd.flag-icon-squared{background-image:url(../flags/1x1/bd.svg)}.flag-icon-be{background-image:url(../flags/4x3/be.svg)}.flag-icon-be.flag-icon-squared{background-image:url(../flags/1x1/be.svg)}.flag-icon-bf{background-image:url(../flags/4x3/bf.svg)}.flag-icon-bf.flag-icon-squared{background-image:url(../flags/1x1/bf.svg)}.flag-icon-bg{background-image:url(../flags/4x3/bg.svg)}.flag-icon-bg.flag-icon-squared{background-image:url(../flags/1x1/bg.svg)}.flag-icon-bh{background-image:url(../flags/4x3/bh.svg)}.flag-icon-bh.flag-icon-squared{background-image:url(../flags/1x1/bh.svg)}.flag-icon-bi{background-image:url(../flags/4x3/bi.svg)}.flag-icon-bi.flag-icon-squared{background-image:url(../flags/1x1/bi.svg)}.flag-icon-bj{background-image:url(../flags/4x3/bj.svg)}.flag-icon-bj.flag-icon-squared{background-image:url(../flags/1x1/bj.svg)}.flag-icon-bl{background-image:url(../flags/4x3/bl.svg)}.flag-icon-bl.flag-icon-squared{background-image:url(../flags/1x1/bl.svg)}.flag-icon-bm{background-image:url(../flags/4x3/bm.svg)}.flag-icon-bm.flag-icon-squared{background-image:url(../flags/1x1/bm.svg)}.flag-icon-bn{background-image:url(../flags/4x3/bn.svg)}.flag-icon-bn.flag-icon-squared{background-image:url(../flags/1x1/bn.svg)}.flag-icon-bo{background-image:url(../flags/4x3/bo.svg)}.flag-icon-bo.flag-icon-squared{background-image:url(../flags/1x1/bo.svg)}.flag-icon-bq{background-image:url(../flags/4x3/bq.svg)}.flag-icon-bq.flag-icon-squared{background-image:url(../flags/1x1/bq.svg)}.flag-icon-br{background-image:url(../flags/4x3/br.svg)}.flag-icon-br.flag-icon-squared{background-image:url(../flags/1x1/br.svg)}.flag-icon-bs{background-image:url(../flags/4x3/bs.svg)}.flag-icon-bs.flag-icon-squared{background-image:url(../flags/1x1/bs.svg)}.flag-icon-bt{background-image:url(../flags/4x3/bt.svg)}.flag-icon-bt.flag-icon-squared{background-image:url(../flags/1x1/bt.svg)}.flag-icon-bv{background-image:url(../flags/4x3/bv.svg)}.flag-icon-bv.flag-icon-squared{background-image:url(../flags/1x1/bv.svg)}.flag-icon-bw{background-image:url(../flags/4x3/bw.svg)}.flag-icon-bw.flag-icon-squared{background-image:url(../flags/1x1/bw.svg)}.flag-icon-by{background-image:url(../flags/4x3/by.svg)}.flag-icon-by.flag-icon-squared{background-image:url(../flagsLine truncated
|
.flag-icon-background{background-size:contain;background-position:50%;background-repeat:no-repeat}.flag-icon{background-size:contain;background-position:50%;background-repeat:no-repeat;position:relative;display:inline-block;width:1.33333333em;line-height:1em}.flag-icon:before{content:'\00a0'}.flag-icon.flag-icon-squared{width:1em}.flag-icon-ad{background-image:url(../flags/4x3/ad.svg)}.flag-icon-ad.flag-icon-squared{background-image:url(../flags/1x1/ad.svg)}.flag-icon-ae{background-image:url(../flags/4x3/ae.svg)}.flag-icon-ae.flag-icon-squared{background-image:url(../flags/1x1/ae.svg)}.flag-icon-af{background-image:url(../flags/4x3/af.svg)}.flag-icon-af.flag-icon-squared{background-image:url(../flags/1x1/af.svg)}.flag-icon-ag{background-image:url(../flags/4x3/ag.svg)}.flag-icon-ag.flag-icon-squared{background-image:url(../flags/1x1/ag.svg)}.flag-icon-ai{background-image:url(../flags/4x3/ai.svg)}.flag-icon-ai.flag-icon-squared{background-image:url(../flags/1x1/ai.svg)}.flag-icon-al{background-image:url(../flags/4x3/al.svg)}.flag-icon-al.flag-icon-squared{background-image:url(../flags/1x1/al.svg)}.flag-icon-am{background-image:url(../flags/4x3/am.svg)}.flag-icon-am.flag-icon-squared{background-image:url(../flags/1x1/am.svg)}.flag-icon-ao{background-image:url(../flags/4x3/ao.svg)}.flag-icon-ao.flag-icon-squared{background-image:url(../flags/1x1/ao.svg)}.flag-icon-aq{background-image:url(../flags/4x3/aq.svg)}.flag-icon-aq.flag-icon-squared{background-image:url(../flags/1x1/aq.svg)}.flag-icon-ar{background-image:url(../flags/4x3/ar.svg)}.flag-icon-ar.flag-icon-squared{background-image:url(../flags/1x1/ar.svg)}.flag-icon-as{background-image:url(../flags/4x3/as.svg)}.flag-icon-as.flag-icon-squared{background-image:url(../flags/1x1/as.svg)}.flag-icon-at{background-image:url(../flags/4x3/at.svg)}.flag-icon-at.flag-icon-squared{background-image:url(../flags/1x1/at.svg)}.flag-icon-au{background-image:url(../flags/4x3/au.svg)}.flag-icon-au.flag-icon-squared{background-image:url(../flags/1x1/au.svg)}.flag-icon-aw{background-image:url(../flags/4x3/aw.svg)}.flag-icon-aw.flag-icon-squared{background-image:url(../flags/1x1/aw.svg)}.flag-icon-ax{background-image:url(../flags/4x3/ax.svg)}.flag-icon-ax.flag-icon-squared{background-image:url(../flags/1x1/ax.svg)}.flag-icon-az{background-image:url(../flags/4x3/az.svg)}.flag-icon-az.flag-icon-squared{background-image:url(../flags/1x1/az.svg)}.flag-icon-ba{background-image:url(../flags/4x3/ba.svg)}.flag-icon-ba.flag-icon-squared{background-image:url(../flags/1x1/ba.svg)}.flag-icon-bb{background-image:url(../flags/4x3/bb.svg)}.flag-icon-bb.flag-icon-squared{background-image:url(../flags/1x1/bb.svg)}.flag-icon-bd{background-image:url(../flags/4x3/bd.svg)}.flag-icon-bd.flag-icon-squared{background-image:url(../flags/1x1/bd.svg)}.flag-icon-be{background-image:url(../flags/4x3/be.svg)}.flag-icon-be.flag-icon-squared{background-image:url(../flags/1x1/be.svg)}.flag-icon-bf{background-image:url(../flags/4x3/bf.svg)}.flag-icon-bf.flag-icon-squared{background-image:url(../flags/1x1/bf.svg)}.flag-icon-bg{background-image:url(../flags/4x3/bg.svg)}.flag-icon-bg.flag-icon-squared{background-image:url(../flags/1x1/bg.svg)}.flag-icon-bh{background-image:url(../flags/4x3/bh.svg)}.flag-icon-bh.flag-icon-squared{background-image:url(../flags/1x1/bh.svg)}.flag-icon-bi{background-image:url(../flags/4x3/bi.svg)}.flag-icon-bi.flag-icon-squared{background-image:url(../flags/1x1/bi.svg)}.flag-icon-bj{background-image:url(../flags/4x3/bj.svg)}.flag-icon-bj.flag-icon-squared{background-image:url(../flags/1x1/bj.svg)}.flag-icon-bl{background-image:url(../flags/4x3/bl.svg)}.flag-icon-bl.flag-icon-squared{background-image:url(../flags/1x1/bl.svg)}.flag-icon-bm{background-image:url(../flags/4x3/bm.svg)}.flag-icon-bm.flag-icon-squared{background-image:url(../flags/1x1/bm.svg)}.flag-icon-bn{background-image:url(../flags/4x3/bn.svg)}.flag-icon-bn.flag-icon-squared{background-image:url(../flags/1x1/bn.svg)}.flag-icon-bo{background-image:url(../flags/4x3/bo.svg)}.flag-icon-bo.flag-icon-squared{background-image:url(../flags/1x1/bo.svg)}.flag-icon-bq{background-image:url(../flags/4x3/bq.svg)}.flag-icon-bq.flag-icon-squared{background-image:url(../flags/1x1/bq.svg)}.flag-icon-br{background-image:url(../flags/4x3/br.svg)}.flag-icon-br.flag-icon-squared{background-image:url(../flags/1x1/br.svg)}.flag-icon-bs{background-image:url(../flags/4x3/bs.svg)}.flag-icon-bs.flag-icon-squared{background-image:url(../flags/1x1/bs.svg)}.flag-icon-bt{background-image:url(../flags/4x3/bt.svg)}.flag-icon-bt.flag-icon-squared{background-image:url(../flags/1x1/bt.svg)}.flag-icon-bv{background-image:url(../flags/4x3/bv.svg)}.flag-icon-bv.flag-icon-squared{background-image:url(../flags/1x1/bv.svg)}.flag-icon-bw{background-image:url(../flags/4x3/bw.svg)}.flag-icon-bw.flag-icon-squared{background-image:url(../flags/1x1/bw.svg)}.flag-icon-by{background-image:url(../flags/4x3/by.svg)}.flag-icon-by.flag-icon-squared{background-image:url(../flagsLine truncated
|
||||||
+10
-10
@@ -1,11 +1,11 @@
|
|||||||
@charset "UTF-8";
|
@charset "UTF-8";
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* animate.css -http://daneden.me/animate
|
* animate.css -http://daneden.me/animate
|
||||||
* Version - 3.5.2
|
* Version - 3.5.2
|
||||||
* Licensed under the MIT license - http://opensource.org/licenses/MIT
|
* Licensed under the MIT license - http://opensource.org/licenses/MIT
|
||||||
*
|
*
|
||||||
* Copyright (c) 2017 Daniel Eden
|
* Copyright (c) 2017 Daniel Eden
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.animated{animation-duration:1s;animation-fill-mode:both}.animated.infinite{animation-iteration-count:infinite}.animated.hinge{animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{animation-duration:.75s}@keyframes bounce{0%,20%,53%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0)}70%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0)}90%{transform:translate3d(0,-4px,0)}}.bounce{animation-name:bounce;transform-origin:center bottom}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.flash{animation-name:flash}@keyframes pulse{0%{transform:scaleX(1)}50%{transform:scale3d(1.05,1.05,1.05)}to{transform:scaleX(1)}}.pulse{animation-name:pulse}@keyframes rubberBand{0%{transform:scaleX(1)}30%{transform:scale3d(1.25,.75,1)}40%{transform:scale3d(.75,1.25,1)}50%{transform:scale3d(1.15,.85,1)}65%{transform:scale3d(.95,1.05,1)}75%{transform:scale3d(1.05,.95,1)}to{transform:scaleX(1)}}.rubberBand{animation-name:rubberBand}@keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}.shake{animation-name:shake}@keyframes headShake{0%{transform:translateX(0)}6.5%{transform:translateX(-6px) rotateY(-9deg)}18.5%{transform:translateX(5px) rotateY(7deg)}31.5%{transform:translateX(-3px) rotateY(-5deg)}43.5%{transform:translateX(2px) rotateY(3deg)}50%{transform:translateX(0)}}.headShake{animation-timing-function:ease-in-out;animation-name:headShake}@keyframes swing{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}to{transform:rotate(0deg)}}.swing{transform-origin:top center;animation-name:swing}@keyframes tada{0%{transform:scaleX(1)}10%,20%{transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{transform:scaleX(1)}}.tada{animation-name:tada}@keyframes wobble{0%{transform:none}15%{transform:translate3d(-25%,0,0) rotate(-5deg)}30%{transform:translate3d(20%,0,0) rotate(3deg)}45%{transform:translate3d(-15%,0,0) rotate(-3deg)}60%{transform:translate3d(10%,0,0) rotate(2deg)}75%{transform:translate3d(-5%,0,0) rotate(-1deg)}to{transform:none}}.wobble{animation-name:wobble}@keyframes jello{0%,11.1%,to{transform:none}22.2%{transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{transform:skewX(6.25deg) skewY(6.25deg)}44.4%{transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{transform:skewX(.390625deg) skewY(.390625deg)}88.8%{transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.jello{animation-name:jello;transform-origin:center}@keyframes bounceIn{0%,20%,40%,60%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:scale3d(.3,.3,.3)}20%{transform:scale3d(1.1,1.1,1.1)}40%{transform:scale3d(.9,.9,.9)}60%{opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{transform:scale3d(.97,.97,.97)}to{opacity:1;transform:scaleX(1)}}.bounceIn{animation-name:bounceIn}@keyframes bounceInDown{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}.bounceInDown{animation-name:bounceInDown}@keyframes bounceInLeft{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}.bounceInLeft{animation-name:bounceInLeft}@keyframes bounceInRight{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}.bounceInRight{animation-name:bounceInRight}@keyframes bounceInUp{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}.bounceInUp{animation-name:bounceInUp}@keyframes bounceOut{20%{transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;transform:scale3d(1.1,1.1,1.1)}to{opacity:0;transform:scale3d(.3,.3,.3)}}.bounceOut{animation-name:bounceOut}@keyframes bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.bounceOutDown{animation-name:bounceOutDown}@keyframes bounceOutLeft{20%{opacity:1;Line truncated
|
.animated{animation-duration:1s;animation-fill-mode:both}.animated.infinite{animation-iteration-count:infinite}.animated.hinge{animation-duration:2s}.animated.bounceIn,.animated.bounceOut,.animated.flipOutX,.animated.flipOutY{animation-duration:.75s}@keyframes bounce{0%,20%,53%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1);transform:translateZ(0)}40%,43%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-30px,0)}70%{animation-timing-function:cubic-bezier(.755,.05,.855,.06);transform:translate3d(0,-15px,0)}90%{transform:translate3d(0,-4px,0)}}.bounce{animation-name:bounce;transform-origin:center bottom}@keyframes flash{0%,50%,to{opacity:1}25%,75%{opacity:0}}.flash{animation-name:flash}@keyframes pulse{0%{transform:scaleX(1)}50%{transform:scale3d(1.05,1.05,1.05)}to{transform:scaleX(1)}}.pulse{animation-name:pulse}@keyframes rubberBand{0%{transform:scaleX(1)}30%{transform:scale3d(1.25,.75,1)}40%{transform:scale3d(.75,1.25,1)}50%{transform:scale3d(1.15,.85,1)}65%{transform:scale3d(.95,1.05,1)}75%{transform:scale3d(1.05,.95,1)}to{transform:scaleX(1)}}.rubberBand{animation-name:rubberBand}@keyframes shake{0%,to{transform:translateZ(0)}10%,30%,50%,70%,90%{transform:translate3d(-10px,0,0)}20%,40%,60%,80%{transform:translate3d(10px,0,0)}}.shake{animation-name:shake}@keyframes headShake{0%{transform:translateX(0)}6.5%{transform:translateX(-6px) rotateY(-9deg)}18.5%{transform:translateX(5px) rotateY(7deg)}31.5%{transform:translateX(-3px) rotateY(-5deg)}43.5%{transform:translateX(2px) rotateY(3deg)}50%{transform:translateX(0)}}.headShake{animation-timing-function:ease-in-out;animation-name:headShake}@keyframes swing{20%{transform:rotate(15deg)}40%{transform:rotate(-10deg)}60%{transform:rotate(5deg)}80%{transform:rotate(-5deg)}to{transform:rotate(0deg)}}.swing{transform-origin:top center;animation-name:swing}@keyframes tada{0%{transform:scaleX(1)}10%,20%{transform:scale3d(.9,.9,.9) rotate(-3deg)}30%,50%,70%,90%{transform:scale3d(1.1,1.1,1.1) rotate(3deg)}40%,60%,80%{transform:scale3d(1.1,1.1,1.1) rotate(-3deg)}to{transform:scaleX(1)}}.tada{animation-name:tada}@keyframes wobble{0%{transform:none}15%{transform:translate3d(-25%,0,0) rotate(-5deg)}30%{transform:translate3d(20%,0,0) rotate(3deg)}45%{transform:translate3d(-15%,0,0) rotate(-3deg)}60%{transform:translate3d(10%,0,0) rotate(2deg)}75%{transform:translate3d(-5%,0,0) rotate(-1deg)}to{transform:none}}.wobble{animation-name:wobble}@keyframes jello{0%,11.1%,to{transform:none}22.2%{transform:skewX(-12.5deg) skewY(-12.5deg)}33.3%{transform:skewX(6.25deg) skewY(6.25deg)}44.4%{transform:skewX(-3.125deg) skewY(-3.125deg)}55.5%{transform:skewX(1.5625deg) skewY(1.5625deg)}66.6%{transform:skewX(-.78125deg) skewY(-.78125deg)}77.7%{transform:skewX(.390625deg) skewY(.390625deg)}88.8%{transform:skewX(-.1953125deg) skewY(-.1953125deg)}}.jello{animation-name:jello;transform-origin:center}@keyframes bounceIn{0%,20%,40%,60%,80%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:scale3d(.3,.3,.3)}20%{transform:scale3d(1.1,1.1,1.1)}40%{transform:scale3d(.9,.9,.9)}60%{opacity:1;transform:scale3d(1.03,1.03,1.03)}80%{transform:scale3d(.97,.97,.97)}to{opacity:1;transform:scaleX(1)}}.bounceIn{animation-name:bounceIn}@keyframes bounceInDown{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,-3000px,0)}60%{opacity:1;transform:translate3d(0,25px,0)}75%{transform:translate3d(0,-10px,0)}90%{transform:translate3d(0,5px,0)}to{transform:none}}.bounceInDown{animation-name:bounceInDown}@keyframes bounceInLeft{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(-3000px,0,0)}60%{opacity:1;transform:translate3d(25px,0,0)}75%{transform:translate3d(-10px,0,0)}90%{transform:translate3d(5px,0,0)}to{transform:none}}.bounceInLeft{animation-name:bounceInLeft}@keyframes bounceInRight{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(3000px,0,0)}60%{opacity:1;transform:translate3d(-25px,0,0)}75%{transform:translate3d(10px,0,0)}90%{transform:translate3d(-5px,0,0)}to{transform:none}}.bounceInRight{animation-name:bounceInRight}@keyframes bounceInUp{0%,60%,75%,90%,to{animation-timing-function:cubic-bezier(.215,.61,.355,1)}0%{opacity:0;transform:translate3d(0,3000px,0)}60%{opacity:1;transform:translate3d(0,-20px,0)}75%{transform:translate3d(0,10px,0)}90%{transform:translate3d(0,-5px,0)}to{transform:translateZ(0)}}.bounceInUp{animation-name:bounceInUp}@keyframes bounceOut{20%{transform:scale3d(.9,.9,.9)}50%,55%{opacity:1;transform:scale3d(1.1,1.1,1.1)}to{opacity:0;transform:scale3d(.3,.3,.3)}}.bounceOut{animation-name:bounceOut}@keyframes bounceOutDown{20%{transform:translate3d(0,10px,0)}40%,45%{opacity:1;transform:translate3d(0,-20px,0)}to{opacity:0;transform:translate3d(0,2000px,0)}}.bounceOutDown{animation-name:bounceOutDown}@keyframes bounceOutLeft{20%{opacity:1;Line truncated
|
||||||
Vendored
File renamed without changes.
Vendored
File renamed without changes.
@@ -0,0 +1,687 @@
|
|||||||
|
/*
|
||||||
|
* This combined file was created by the DataTables downloader builder:
|
||||||
|
* https://datatables.net/download
|
||||||
|
*
|
||||||
|
* To rebuild or modify this file with the latest versions of the included
|
||||||
|
* software please visit:
|
||||||
|
* https://datatables.net/download/#bs5/dt-1.13.1/r-2.4.0/sl-1.5.0
|
||||||
|
*
|
||||||
|
* Included libraries:
|
||||||
|
* DataTables 1.13.1, Responsive 2.4.0, Select 1.5.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
@charset "UTF-8";
|
||||||
|
table.dataTable td.dt-control {
|
||||||
|
text-align: center;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
table.dataTable td.dt-control:before {
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
margin-top: -9px;
|
||||||
|
display: inline-block;
|
||||||
|
color: white;
|
||||||
|
border: 0.15em solid white;
|
||||||
|
border-radius: 1em;
|
||||||
|
box-shadow: 0 0 0.2em #444;
|
||||||
|
box-sizing: content-box;
|
||||||
|
text-align: center;
|
||||||
|
text-indent: 0 !important;
|
||||||
|
font-family: "Courier New", Courier, monospace;
|
||||||
|
line-height: 1em;
|
||||||
|
content: "+";
|
||||||
|
background-color: #31b131;
|
||||||
|
}
|
||||||
|
table.dataTable tr.dt-hasChild td.dt-control:before {
|
||||||
|
content: "-";
|
||||||
|
background-color: #d33333;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.dataTable thead > tr > th.sorting, table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting_asc_disabled, table.dataTable thead > tr > th.sorting_desc_disabled,
|
||||||
|
table.dataTable thead > tr > td.sorting,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
padding-right: 26px;
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:after,
|
||||||
|
table.dataTable thead > tr > td.sorting:before,
|
||||||
|
table.dataTable thead > tr > td.sorting:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled:after {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
opacity: 0.125;
|
||||||
|
right: 10px;
|
||||||
|
line-height: 9px;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th.sorting:before, table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:before, table.dataTable thead > tr > th.sorting_asc_disabled:before, table.dataTable thead > tr > th.sorting_desc_disabled:before,
|
||||||
|
table.dataTable thead > tr > td.sorting:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled:before {
|
||||||
|
bottom: 50%;
|
||||||
|
content: "▲";
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th.sorting:after, table.dataTable thead > tr > th.sorting_asc:after, table.dataTable thead > tr > th.sorting_desc:after, table.dataTable thead > tr > th.sorting_asc_disabled:after, table.dataTable thead > tr > th.sorting_desc_disabled:after,
|
||||||
|
table.dataTable thead > tr > td.sorting:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled:after {
|
||||||
|
top: 50%;
|
||||||
|
content: "▼";
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th.sorting_asc:before, table.dataTable thead > tr > th.sorting_desc:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc:after {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th.sorting_desc_disabled:after, table.dataTable thead > tr > th.sorting_asc_disabled:before,
|
||||||
|
table.dataTable thead > tr > td.sorting_desc_disabled:after,
|
||||||
|
table.dataTable thead > tr > td.sorting_asc_disabled:before {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
table.dataTable thead > tr > th:active,
|
||||||
|
table.dataTable thead > tr > td:active {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollBody table.dataTable thead > tr > th:before, div.dataTables_scrollBody table.dataTable thead > tr > th:after,
|
||||||
|
div.dataTables_scrollBody table.dataTable thead > tr > td:before,
|
||||||
|
div.dataTables_scrollBody table.dataTable thead > tr > td:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_processing {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 200px;
|
||||||
|
margin-left: -100px;
|
||||||
|
margin-top: -26px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child {
|
||||||
|
position: relative;
|
||||||
|
width: 80px;
|
||||||
|
height: 15px;
|
||||||
|
margin: 1em auto;
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child > div {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 13px;
|
||||||
|
height: 13px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(13, 110, 253, 0.9);
|
||||||
|
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child > div:nth-child(1) {
|
||||||
|
left: 8px;
|
||||||
|
animation: datatables-loader-1 0.6s infinite;
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child > div:nth-child(2) {
|
||||||
|
left: 8px;
|
||||||
|
animation: datatables-loader-2 0.6s infinite;
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child > div:nth-child(3) {
|
||||||
|
left: 32px;
|
||||||
|
animation: datatables-loader-2 0.6s infinite;
|
||||||
|
}
|
||||||
|
div.dataTables_processing > div:last-child > div:nth-child(4) {
|
||||||
|
left: 56px;
|
||||||
|
animation: datatables-loader-3 0.6s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes datatables-loader-1 {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes datatables-loader-3 {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes datatables-loader-2 {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(24px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.dataTable.nowrap th, table.dataTable.nowrap td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
table.dataTable th.dt-left,
|
||||||
|
table.dataTable td.dt-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
table.dataTable th.dt-center,
|
||||||
|
table.dataTable td.dt-center,
|
||||||
|
table.dataTable td.dataTables_empty {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
table.dataTable th.dt-right,
|
||||||
|
table.dataTable td.dt-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
table.dataTable th.dt-justify,
|
||||||
|
table.dataTable td.dt-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
table.dataTable th.dt-nowrap,
|
||||||
|
table.dataTable td.dt-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
table.dataTable thead th,
|
||||||
|
table.dataTable thead td,
|
||||||
|
table.dataTable tfoot th,
|
||||||
|
table.dataTable tfoot td {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
table.dataTable thead th.dt-head-left,
|
||||||
|
table.dataTable thead td.dt-head-left,
|
||||||
|
table.dataTable tfoot th.dt-head-left,
|
||||||
|
table.dataTable tfoot td.dt-head-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
table.dataTable thead th.dt-head-center,
|
||||||
|
table.dataTable thead td.dt-head-center,
|
||||||
|
table.dataTable tfoot th.dt-head-center,
|
||||||
|
table.dataTable tfoot td.dt-head-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
table.dataTable thead th.dt-head-right,
|
||||||
|
table.dataTable thead td.dt-head-right,
|
||||||
|
table.dataTable tfoot th.dt-head-right,
|
||||||
|
table.dataTable tfoot td.dt-head-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
table.dataTable thead th.dt-head-justify,
|
||||||
|
table.dataTable thead td.dt-head-justify,
|
||||||
|
table.dataTable tfoot th.dt-head-justify,
|
||||||
|
table.dataTable tfoot td.dt-head-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
table.dataTable thead th.dt-head-nowrap,
|
||||||
|
table.dataTable thead td.dt-head-nowrap,
|
||||||
|
table.dataTable tfoot th.dt-head-nowrap,
|
||||||
|
table.dataTable tfoot td.dt-head-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
table.dataTable tbody th.dt-body-left,
|
||||||
|
table.dataTable tbody td.dt-body-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
table.dataTable tbody th.dt-body-center,
|
||||||
|
table.dataTable tbody td.dt-body-center {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
table.dataTable tbody th.dt-body-right,
|
||||||
|
table.dataTable tbody td.dt-body-right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
table.dataTable tbody th.dt-body-justify,
|
||||||
|
table.dataTable tbody td.dt-body-justify {
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
table.dataTable tbody th.dt-body-nowrap,
|
||||||
|
table.dataTable tbody td.dt-body-nowrap {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Bootstrap 5 integration for DataTables
|
||||||
|
*
|
||||||
|
* ©2020 SpryMedia Ltd, all rights reserved.
|
||||||
|
* License: MIT datatables.net/license/mit
|
||||||
|
*/
|
||||||
|
table.dataTable {
|
||||||
|
clear: both;
|
||||||
|
margin-top: 6px !important;
|
||||||
|
margin-bottom: 6px !important;
|
||||||
|
max-width: none !important;
|
||||||
|
border-collapse: separate !important;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
||||||
|
table.dataTable td,
|
||||||
|
table.dataTable th {
|
||||||
|
-webkit-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
table.dataTable td.dataTables_empty,
|
||||||
|
table.dataTable th.dataTables_empty {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
table.dataTable.nowrap th,
|
||||||
|
table.dataTable.nowrap td {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
table.dataTable.table-striped > tbody > tr:nth-of-type(2n+1) > * {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.selected > * {
|
||||||
|
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.9);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.selected a {
|
||||||
|
color: #090a0b;
|
||||||
|
}
|
||||||
|
table.dataTable.table-striped > tbody > tr.odd > * {
|
||||||
|
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
table.dataTable.table-striped > tbody > tr.odd.selected > * {
|
||||||
|
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.95);
|
||||||
|
}
|
||||||
|
table.dataTable.table-hover > tbody > tr:hover > * {
|
||||||
|
box-shadow: inset 0 0 0 9999px rgba(0, 0, 0, 0.075);
|
||||||
|
}
|
||||||
|
table.dataTable.table-hover > tbody > tr.selected:hover > * {
|
||||||
|
box-shadow: inset 0 0 0 9999px rgba(13, 110, 253, 0.975);
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_wrapper div.dataTables_length label {
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: left;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_length select {
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_filter {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_filter label {
|
||||||
|
font-weight: normal;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_filter input {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
display: inline-block;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_info {
|
||||||
|
padding-top: 0.85em;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_paginate {
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
|
||||||
|
margin: 2px 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dt-row {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollHead table.dataTable {
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollBody > table {
|
||||||
|
border-top: none;
|
||||||
|
margin-top: 0 !important;
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting:before,
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting_asc:before,
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting_desc:before,
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting:after,
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting_asc:after,
|
||||||
|
div.dataTables_scrollBody > table > thead .sorting_desc:after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
div.dataTables_scrollBody > table > tbody tr:first-child th,
|
||||||
|
div.dataTables_scrollBody > table > tbody tr:first-child td {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollFoot > .dataTables_scrollFootInner {
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
div.dataTables_wrapper div.dataTables_length,
|
||||||
|
div.dataTables_wrapper div.dataTables_filter,
|
||||||
|
div.dataTables_wrapper div.dataTables_info,
|
||||||
|
div.dataTables_wrapper div.dataTables_paginate {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_paginate ul.pagination {
|
||||||
|
justify-content: center !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.dataTable.table-sm > thead > tr > th:not(.sorting_disabled) {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.table-bordered.dataTable {
|
||||||
|
border-right-width: 0;
|
||||||
|
}
|
||||||
|
table.table-bordered.dataTable thead tr:first-child th,
|
||||||
|
table.table-bordered.dataTable thead tr:first-child td {
|
||||||
|
border-top-width: 1px;
|
||||||
|
}
|
||||||
|
table.table-bordered.dataTable th,
|
||||||
|
table.table-bordered.dataTable td {
|
||||||
|
border-left-width: 0;
|
||||||
|
}
|
||||||
|
table.table-bordered.dataTable th:first-child, table.table-bordered.dataTable th:first-child,
|
||||||
|
table.table-bordered.dataTable td:first-child,
|
||||||
|
table.table-bordered.dataTable td:first-child {
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
|
||||||
|
table.table-bordered.dataTable td:last-child,
|
||||||
|
table.table-bordered.dataTable td:last-child {
|
||||||
|
border-right-width: 1px;
|
||||||
|
}
|
||||||
|
table.table-bordered.dataTable th,
|
||||||
|
table.table-bordered.dataTable td {
|
||||||
|
border-bottom-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_scrollHead table.table-bordered {
|
||||||
|
border-bottom-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.table-responsive > div.dataTables_wrapper > div.row {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:first-child {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
div.table-responsive > div.dataTables_wrapper > div.row > div[class^=col-]:last-child {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty {
|
||||||
|
cursor: default !important;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.child:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > th.child:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dataTables_empty:before {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr > th.dtr-control:before {
|
||||||
|
top: 50%;
|
||||||
|
left: 5px;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
margin-top: -9px;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
border: 0.15em solid white;
|
||||||
|
border-radius: 1em;
|
||||||
|
box-shadow: 0 0 0.2em #444;
|
||||||
|
box-sizing: content-box;
|
||||||
|
text-align: center;
|
||||||
|
text-indent: 0 !important;
|
||||||
|
font-family: "Courier New", Courier, monospace;
|
||||||
|
line-height: 1em;
|
||||||
|
content: "+";
|
||||||
|
background-color: #0d6efd;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th.dtr-control:before {
|
||||||
|
content: "-";
|
||||||
|
background-color: #d33333;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td.dtr-control,
|
||||||
|
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th.dtr-control {
|
||||||
|
padding-left: 27px;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th.dtr-control:before {
|
||||||
|
left: 4px;
|
||||||
|
height: 14px;
|
||||||
|
width: 14px;
|
||||||
|
border-radius: 14px;
|
||||||
|
line-height: 14px;
|
||||||
|
text-indent: 3px;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-column > tbody > tr > td.dtr-control,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > th.dtr-control,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > td.control,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > th.control {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-column > tbody > tr > td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > th.dtr-control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > td.control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr > th.control:before {
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
height: 0.8em;
|
||||||
|
width: 0.8em;
|
||||||
|
margin-top: -0.5em;
|
||||||
|
margin-left: -0.5em;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
color: white;
|
||||||
|
border: 0.15em solid white;
|
||||||
|
border-radius: 1em;
|
||||||
|
box-shadow: 0 0 0.2em #444;
|
||||||
|
box-sizing: content-box;
|
||||||
|
text-align: center;
|
||||||
|
text-indent: 0 !important;
|
||||||
|
font-family: "Courier New", Courier, monospace;
|
||||||
|
line-height: 1em;
|
||||||
|
content: "+";
|
||||||
|
background-color: #0d6efd;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-column > tbody > tr.parent td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr.parent th.dtr-control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
|
||||||
|
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
|
||||||
|
content: "-";
|
||||||
|
background-color: #d33333;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child {
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child:hover {
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child ul.dtr-details {
|
||||||
|
display: inline-block;
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child ul.dtr-details > li {
|
||||||
|
border-bottom: 1px solid #efefef;
|
||||||
|
padding: 0.5em 0;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child ul.dtr-details > li:first-child {
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child ul.dtr-details > li:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.child span.dtr-title {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 75px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
div.dtr-modal {
|
||||||
|
position: fixed;
|
||||||
|
box-sizing: border-box;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 100;
|
||||||
|
padding: 10em 1em;
|
||||||
|
}
|
||||||
|
div.dtr-modal div.dtr-modal-display {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
overflow: auto;
|
||||||
|
margin: auto;
|
||||||
|
z-index: 102;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: #f5f5f7;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
div.dtr-modal div.dtr-modal-content {
|
||||||
|
position: relative;
|
||||||
|
padding: 1em;
|
||||||
|
}
|
||||||
|
div.dtr-modal div.dtr-modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 6px;
|
||||||
|
width: 22px;
|
||||||
|
height: 22px;
|
||||||
|
border: 1px solid #eaeaea;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 12;
|
||||||
|
}
|
||||||
|
div.dtr-modal div.dtr-modal-close:hover {
|
||||||
|
background-color: #eaeaea;
|
||||||
|
}
|
||||||
|
div.dtr-modal div.dtr-modal-background {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 101;
|
||||||
|
background: rgba(0, 0, 0, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
div.dtr-modal div.dtr-modal-display {
|
||||||
|
width: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div.dtr-bs-modal table.table tr:first-child td {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table.dataTable.table-bordered th.dtr-control.dtr-hidden + *,
|
||||||
|
table.dataTable.table-bordered td.dtr-control.dtr-hidden + * {
|
||||||
|
border-left-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.dataTable > tbody > tr > .selected {
|
||||||
|
background-color: rgba(13, 110, 253, 0.9);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr > td.select-checkbox,
|
||||||
|
table.dataTable > tbody > tr > th.select-checkbox {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr > td.select-checkbox:before, table.dataTable > tbody > tr > td.select-checkbox:after,
|
||||||
|
table.dataTable > tbody > tr > th.select-checkbox:before,
|
||||||
|
table.dataTable > tbody > tr > th.select-checkbox:after {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 1.2em;
|
||||||
|
left: 50%;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr > td.select-checkbox:before,
|
||||||
|
table.dataTable > tbody > tr > th.select-checkbox:before {
|
||||||
|
content: " ";
|
||||||
|
margin-top: -5px;
|
||||||
|
margin-left: -6px;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.selected > td.select-checkbox:before,
|
||||||
|
table.dataTable > tbody > tr.selected > th.select-checkbox:before {
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
table.dataTable > tbody > tr.selected > td.select-checkbox:after,
|
||||||
|
table.dataTable > tbody > tr.selected > th.select-checkbox:after {
|
||||||
|
content: "✓";
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: -19px;
|
||||||
|
margin-left: -6px;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: 1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9;
|
||||||
|
}
|
||||||
|
table.dataTable.compact > tbody > tr > td.select-checkbox:before,
|
||||||
|
table.dataTable.compact > tbody > tr > th.select-checkbox:before {
|
||||||
|
margin-top: -12px;
|
||||||
|
}
|
||||||
|
table.dataTable.compact > tbody > tr.selected > td.select-checkbox:after,
|
||||||
|
table.dataTable.compact > tbody > tr.selected > th.select-checkbox:after {
|
||||||
|
margin-top: -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_wrapper span.select-info,
|
||||||
|
div.dataTables_wrapper span.select-item {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 640px) {
|
||||||
|
div.dataTables_wrapper span.select-info,
|
||||||
|
div.dataTables_wrapper span.select-item {
|
||||||
|
margin-left: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
table.dataTable.table-sm tbody td.select-checkbox::before {
|
||||||
|
margin-top: -9px;
|
||||||
|
}
|
||||||
|
|
||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
@keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}
|
|
||||||
+279
-2
@@ -1,7 +1,7 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "bootstrap-icons";
|
font-family: "bootstrap-icons";
|
||||||
src: url("/fonts/bootstrap-icons.woff2?45695e8b569b2b0178db2713ca47065c") format("woff2"),
|
src: url("/fonts/bootstrap-icons.woff2?524846017b983fc8ded9325d94ed40f3") format("woff2"),
|
||||||
url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff");
|
url("/fonts/bootstrap-icons.woff?524846017b983fc8ded9325d94ed40f3") format("woff");
|
||||||
}
|
}
|
||||||
|
|
||||||
.bi::before,
|
.bi::before,
|
||||||
@@ -19,6 +19,7 @@ url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bi-123::before { content: "\f67f"; }
|
||||||
.bi-alarm-fill::before { content: "\f101"; }
|
.bi-alarm-fill::before { content: "\f101"; }
|
||||||
.bi-alarm::before { content: "\f102"; }
|
.bi-alarm::before { content: "\f102"; }
|
||||||
.bi-align-bottom::before { content: "\f103"; }
|
.bi-align-bottom::before { content: "\f103"; }
|
||||||
@@ -1425,3 +1426,279 @@ url("/fonts/bootstrap-icons.woff?45695e8b569b2b0178db2713ca47065c") format("woff
|
|||||||
.bi-webcam-fill::before { content: "\f67c"; }
|
.bi-webcam-fill::before { content: "\f67c"; }
|
||||||
.bi-webcam::before { content: "\f67d"; }
|
.bi-webcam::before { content: "\f67d"; }
|
||||||
.bi-yin-yang::before { content: "\f67e"; }
|
.bi-yin-yang::before { content: "\f67e"; }
|
||||||
|
.bi-bandaid-fill::before { content: "\f680"; }
|
||||||
|
.bi-bandaid::before { content: "\f681"; }
|
||||||
|
.bi-bluetooth::before { content: "\f682"; }
|
||||||
|
.bi-body-text::before { content: "\f683"; }
|
||||||
|
.bi-boombox::before { content: "\f684"; }
|
||||||
|
.bi-boxes::before { content: "\f685"; }
|
||||||
|
.bi-dpad-fill::before { content: "\f686"; }
|
||||||
|
.bi-dpad::before { content: "\f687"; }
|
||||||
|
.bi-ear-fill::before { content: "\f688"; }
|
||||||
|
.bi-ear::before { content: "\f689"; }
|
||||||
|
.bi-envelope-check-1::before { content: "\f68a"; }
|
||||||
|
.bi-envelope-check-fill::before { content: "\f68b"; }
|
||||||
|
.bi-envelope-check::before { content: "\f68c"; }
|
||||||
|
.bi-envelope-dash-1::before { content: "\f68d"; }
|
||||||
|
.bi-envelope-dash-fill::before { content: "\f68e"; }
|
||||||
|
.bi-envelope-dash::before { content: "\f68f"; }
|
||||||
|
.bi-envelope-exclamation-1::before { content: "\f690"; }
|
||||||
|
.bi-envelope-exclamation-fill::before { content: "\f691"; }
|
||||||
|
.bi-envelope-exclamation::before { content: "\f692"; }
|
||||||
|
.bi-envelope-plus-fill::before { content: "\f693"; }
|
||||||
|
.bi-envelope-plus::before { content: "\f694"; }
|
||||||
|
.bi-envelope-slash-1::before { content: "\f695"; }
|
||||||
|
.bi-envelope-slash-fill::before { content: "\f696"; }
|
||||||
|
.bi-envelope-slash::before { content: "\f697"; }
|
||||||
|
.bi-envelope-x-1::before { content: "\f698"; }
|
||||||
|
.bi-envelope-x-fill::before { content: "\f699"; }
|
||||||
|
.bi-envelope-x::before { content: "\f69a"; }
|
||||||
|
.bi-explicit-fill::before { content: "\f69b"; }
|
||||||
|
.bi-explicit::before { content: "\f69c"; }
|
||||||
|
.bi-git::before { content: "\f69d"; }
|
||||||
|
.bi-infinity::before { content: "\f69e"; }
|
||||||
|
.bi-list-columns-reverse::before { content: "\f69f"; }
|
||||||
|
.bi-list-columns::before { content: "\f6a0"; }
|
||||||
|
.bi-meta::before { content: "\f6a1"; }
|
||||||
|
.bi-mortorboard-fill::before { content: "\f6a2"; }
|
||||||
|
.bi-mortorboard::before { content: "\f6a3"; }
|
||||||
|
.bi-nintendo-switch::before { content: "\f6a4"; }
|
||||||
|
.bi-pc-display-horizontal::before { content: "\f6a5"; }
|
||||||
|
.bi-pc-display::before { content: "\f6a6"; }
|
||||||
|
.bi-pc-horizontal::before { content: "\f6a7"; }
|
||||||
|
.bi-pc::before { content: "\f6a8"; }
|
||||||
|
.bi-playstation::before { content: "\f6a9"; }
|
||||||
|
.bi-plus-slash-minus::before { content: "\f6aa"; }
|
||||||
|
.bi-projector-fill::before { content: "\f6ab"; }
|
||||||
|
.bi-projector::before { content: "\f6ac"; }
|
||||||
|
.bi-qr-code-scan::before { content: "\f6ad"; }
|
||||||
|
.bi-qr-code::before { content: "\f6ae"; }
|
||||||
|
.bi-quora::before { content: "\f6af"; }
|
||||||
|
.bi-quote::before { content: "\f6b0"; }
|
||||||
|
.bi-robot::before { content: "\f6b1"; }
|
||||||
|
.bi-send-check-fill::before { content: "\f6b2"; }
|
||||||
|
.bi-send-check::before { content: "\f6b3"; }
|
||||||
|
.bi-send-dash-fill::before { content: "\f6b4"; }
|
||||||
|
.bi-send-dash::before { content: "\f6b5"; }
|
||||||
|
.bi-send-exclamation-1::before { content: "\f6b6"; }
|
||||||
|
.bi-send-exclamation-fill::before { content: "\f6b7"; }
|
||||||
|
.bi-send-exclamation::before { content: "\f6b8"; }
|
||||||
|
.bi-send-fill::before { content: "\f6b9"; }
|
||||||
|
.bi-send-plus-fill::before { content: "\f6ba"; }
|
||||||
|
.bi-send-plus::before { content: "\f6bb"; }
|
||||||
|
.bi-send-slash-fill::before { content: "\f6bc"; }
|
||||||
|
.bi-send-slash::before { content: "\f6bd"; }
|
||||||
|
.bi-send-x-fill::before { content: "\f6be"; }
|
||||||
|
.bi-send-x::before { content: "\f6bf"; }
|
||||||
|
.bi-send::before { content: "\f6c0"; }
|
||||||
|
.bi-steam::before { content: "\f6c1"; }
|
||||||
|
.bi-terminal-dash-1::before { content: "\f6c2"; }
|
||||||
|
.bi-terminal-dash::before { content: "\f6c3"; }
|
||||||
|
.bi-terminal-plus::before { content: "\f6c4"; }
|
||||||
|
.bi-terminal-split::before { content: "\f6c5"; }
|
||||||
|
.bi-ticket-detailed-fill::before { content: "\f6c6"; }
|
||||||
|
.bi-ticket-detailed::before { content: "\f6c7"; }
|
||||||
|
.bi-ticket-fill::before { content: "\f6c8"; }
|
||||||
|
.bi-ticket-perforated-fill::before { content: "\f6c9"; }
|
||||||
|
.bi-ticket-perforated::before { content: "\f6ca"; }
|
||||||
|
.bi-ticket::before { content: "\f6cb"; }
|
||||||
|
.bi-tiktok::before { content: "\f6cc"; }
|
||||||
|
.bi-window-dash::before { content: "\f6cd"; }
|
||||||
|
.bi-window-desktop::before { content: "\f6ce"; }
|
||||||
|
.bi-window-fullscreen::before { content: "\f6cf"; }
|
||||||
|
.bi-window-plus::before { content: "\f6d0"; }
|
||||||
|
.bi-window-split::before { content: "\f6d1"; }
|
||||||
|
.bi-window-stack::before { content: "\f6d2"; }
|
||||||
|
.bi-window-x::before { content: "\f6d3"; }
|
||||||
|
.bi-xbox::before { content: "\f6d4"; }
|
||||||
|
.bi-ethernet::before { content: "\f6d5"; }
|
||||||
|
.bi-hdmi-fill::before { content: "\f6d6"; }
|
||||||
|
.bi-hdmi::before { content: "\f6d7"; }
|
||||||
|
.bi-usb-c-fill::before { content: "\f6d8"; }
|
||||||
|
.bi-usb-c::before { content: "\f6d9"; }
|
||||||
|
.bi-usb-fill::before { content: "\f6da"; }
|
||||||
|
.bi-usb-plug-fill::before { content: "\f6db"; }
|
||||||
|
.bi-usb-plug::before { content: "\f6dc"; }
|
||||||
|
.bi-usb-symbol::before { content: "\f6dd"; }
|
||||||
|
.bi-usb::before { content: "\f6de"; }
|
||||||
|
.bi-boombox-fill::before { content: "\f6df"; }
|
||||||
|
.bi-displayport-1::before { content: "\f6e0"; }
|
||||||
|
.bi-displayport::before { content: "\f6e1"; }
|
||||||
|
.bi-gpu-card::before { content: "\f6e2"; }
|
||||||
|
.bi-memory::before { content: "\f6e3"; }
|
||||||
|
.bi-modem-fill::before { content: "\f6e4"; }
|
||||||
|
.bi-modem::before { content: "\f6e5"; }
|
||||||
|
.bi-motherboard-fill::before { content: "\f6e6"; }
|
||||||
|
.bi-motherboard::before { content: "\f6e7"; }
|
||||||
|
.bi-optical-audio-fill::before { content: "\f6e8"; }
|
||||||
|
.bi-optical-audio::before { content: "\f6e9"; }
|
||||||
|
.bi-pci-card::before { content: "\f6ea"; }
|
||||||
|
.bi-router-fill::before { content: "\f6eb"; }
|
||||||
|
.bi-router::before { content: "\f6ec"; }
|
||||||
|
.bi-ssd-fill::before { content: "\f6ed"; }
|
||||||
|
.bi-ssd::before { content: "\f6ee"; }
|
||||||
|
.bi-thunderbolt-fill::before { content: "\f6ef"; }
|
||||||
|
.bi-thunderbolt::before { content: "\f6f0"; }
|
||||||
|
.bi-usb-drive-fill::before { content: "\f6f1"; }
|
||||||
|
.bi-usb-drive::before { content: "\f6f2"; }
|
||||||
|
.bi-usb-micro-fill::before { content: "\f6f3"; }
|
||||||
|
.bi-usb-micro::before { content: "\f6f4"; }
|
||||||
|
.bi-usb-mini-fill::before { content: "\f6f5"; }
|
||||||
|
.bi-usb-mini::before { content: "\f6f6"; }
|
||||||
|
.bi-cloud-haze2::before { content: "\f6f7"; }
|
||||||
|
.bi-device-hdd-fill::before { content: "\f6f8"; }
|
||||||
|
.bi-device-hdd::before { content: "\f6f9"; }
|
||||||
|
.bi-device-ssd-fill::before { content: "\f6fa"; }
|
||||||
|
.bi-device-ssd::before { content: "\f6fb"; }
|
||||||
|
.bi-displayport-fill::before { content: "\f6fc"; }
|
||||||
|
.bi-mortarboard-fill::before { content: "\f6fd"; }
|
||||||
|
.bi-mortarboard::before { content: "\f6fe"; }
|
||||||
|
.bi-terminal-x::before { content: "\f6ff"; }
|
||||||
|
.bi-arrow-through-heart-fill::before { content: "\f700"; }
|
||||||
|
.bi-arrow-through-heart::before { content: "\f701"; }
|
||||||
|
.bi-badge-sd-fill::before { content: "\f702"; }
|
||||||
|
.bi-badge-sd::before { content: "\f703"; }
|
||||||
|
.bi-bag-heart-fill::before { content: "\f704"; }
|
||||||
|
.bi-bag-heart::before { content: "\f705"; }
|
||||||
|
.bi-balloon-fill::before { content: "\f706"; }
|
||||||
|
.bi-balloon-heart-fill::before { content: "\f707"; }
|
||||||
|
.bi-balloon-heart::before { content: "\f708"; }
|
||||||
|
.bi-balloon::before { content: "\f709"; }
|
||||||
|
.bi-box2-fill::before { content: "\f70a"; }
|
||||||
|
.bi-box2-heart-fill::before { content: "\f70b"; }
|
||||||
|
.bi-box2-heart::before { content: "\f70c"; }
|
||||||
|
.bi-box2::before { content: "\f70d"; }
|
||||||
|
.bi-braces-asterisk::before { content: "\f70e"; }
|
||||||
|
.bi-calendar-heart-fill::before { content: "\f70f"; }
|
||||||
|
.bi-calendar-heart::before { content: "\f710"; }
|
||||||
|
.bi-calendar2-heart-fill::before { content: "\f711"; }
|
||||||
|
.bi-calendar2-heart::before { content: "\f712"; }
|
||||||
|
.bi-chat-heart-fill::before { content: "\f713"; }
|
||||||
|
.bi-chat-heart::before { content: "\f714"; }
|
||||||
|
.bi-chat-left-heart-fill::before { content: "\f715"; }
|
||||||
|
.bi-chat-left-heart::before { content: "\f716"; }
|
||||||
|
.bi-chat-right-heart-fill::before { content: "\f717"; }
|
||||||
|
.bi-chat-right-heart::before { content: "\f718"; }
|
||||||
|
.bi-chat-square-heart-fill::before { content: "\f719"; }
|
||||||
|
.bi-chat-square-heart::before { content: "\f71a"; }
|
||||||
|
.bi-clipboard-check-fill::before { content: "\f71b"; }
|
||||||
|
.bi-clipboard-data-fill::before { content: "\f71c"; }
|
||||||
|
.bi-clipboard-fill::before { content: "\f71d"; }
|
||||||
|
.bi-clipboard-heart-fill::before { content: "\f71e"; }
|
||||||
|
.bi-clipboard-heart::before { content: "\f71f"; }
|
||||||
|
.bi-clipboard-minus-fill::before { content: "\f720"; }
|
||||||
|
.bi-clipboard-plus-fill::before { content: "\f721"; }
|
||||||
|
.bi-clipboard-pulse::before { content: "\f722"; }
|
||||||
|
.bi-clipboard-x-fill::before { content: "\f723"; }
|
||||||
|
.bi-clipboard2-check-fill::before { content: "\f724"; }
|
||||||
|
.bi-clipboard2-check::before { content: "\f725"; }
|
||||||
|
.bi-clipboard2-data-fill::before { content: "\f726"; }
|
||||||
|
.bi-clipboard2-data::before { content: "\f727"; }
|
||||||
|
.bi-clipboard2-fill::before { content: "\f728"; }
|
||||||
|
.bi-clipboard2-heart-fill::before { content: "\f729"; }
|
||||||
|
.bi-clipboard2-heart::before { content: "\f72a"; }
|
||||||
|
.bi-clipboard2-minus-fill::before { content: "\f72b"; }
|
||||||
|
.bi-clipboard2-minus::before { content: "\f72c"; }
|
||||||
|
.bi-clipboard2-plus-fill::before { content: "\f72d"; }
|
||||||
|
.bi-clipboard2-plus::before { content: "\f72e"; }
|
||||||
|
.bi-clipboard2-pulse-fill::before { content: "\f72f"; }
|
||||||
|
.bi-clipboard2-pulse::before { content: "\f730"; }
|
||||||
|
.bi-clipboard2-x-fill::before { content: "\f731"; }
|
||||||
|
.bi-clipboard2-x::before { content: "\f732"; }
|
||||||
|
.bi-clipboard2::before { content: "\f733"; }
|
||||||
|
.bi-emoji-kiss-fill::before { content: "\f734"; }
|
||||||
|
.bi-emoji-kiss::before { content: "\f735"; }
|
||||||
|
.bi-envelope-heart-fill::before { content: "\f736"; }
|
||||||
|
.bi-envelope-heart::before { content: "\f737"; }
|
||||||
|
.bi-envelope-open-heart-fill::before { content: "\f738"; }
|
||||||
|
.bi-envelope-open-heart::before { content: "\f739"; }
|
||||||
|
.bi-envelope-paper-fill::before { content: "\f73a"; }
|
||||||
|
.bi-envelope-paper-heart-fill::before { content: "\f73b"; }
|
||||||
|
.bi-envelope-paper-heart::before { content: "\f73c"; }
|
||||||
|
.bi-envelope-paper::before { content: "\f73d"; }
|
||||||
|
.bi-filetype-aac::before { content: "\f73e"; }
|
||||||
|
.bi-filetype-ai::before { content: "\f73f"; }
|
||||||
|
.bi-filetype-bmp::before { content: "\f740"; }
|
||||||
|
.bi-filetype-cs::before { content: "\f741"; }
|
||||||
|
.bi-filetype-css::before { content: "\f742"; }
|
||||||
|
.bi-filetype-csv::before { content: "\f743"; }
|
||||||
|
.bi-filetype-doc::before { content: "\f744"; }
|
||||||
|
.bi-filetype-docx::before { content: "\f745"; }
|
||||||
|
.bi-filetype-exe::before { content: "\f746"; }
|
||||||
|
.bi-filetype-gif::before { content: "\f747"; }
|
||||||
|
.bi-filetype-heic::before { content: "\f748"; }
|
||||||
|
.bi-filetype-html::before { content: "\f749"; }
|
||||||
|
.bi-filetype-java::before { content: "\f74a"; }
|
||||||
|
.bi-filetype-jpg::before { content: "\f74b"; }
|
||||||
|
.bi-filetype-js::before { content: "\f74c"; }
|
||||||
|
.bi-filetype-jsx::before { content: "\f74d"; }
|
||||||
|
.bi-filetype-key::before { content: "\f74e"; }
|
||||||
|
.bi-filetype-m4p::before { content: "\f74f"; }
|
||||||
|
.bi-filetype-md::before { content: "\f750"; }
|
||||||
|
.bi-filetype-mdx::before { content: "\f751"; }
|
||||||
|
.bi-filetype-mov::before { content: "\f752"; }
|
||||||
|
.bi-filetype-mp3::before { content: "\f753"; }
|
||||||
|
.bi-filetype-mp4::before { content: "\f754"; }
|
||||||
|
.bi-filetype-otf::before { content: "\f755"; }
|
||||||
|
.bi-filetype-pdf::before { content: "\f756"; }
|
||||||
|
.bi-filetype-php::before { content: "\f757"; }
|
||||||
|
.bi-filetype-png::before { content: "\f758"; }
|
||||||
|
.bi-filetype-ppt-1::before { content: "\f759"; }
|
||||||
|
.bi-filetype-ppt::before { content: "\f75a"; }
|
||||||
|
.bi-filetype-psd::before { content: "\f75b"; }
|
||||||
|
.bi-filetype-py::before { content: "\f75c"; }
|
||||||
|
.bi-filetype-raw::before { content: "\f75d"; }
|
||||||
|
.bi-filetype-rb::before { content: "\f75e"; }
|
||||||
|
.bi-filetype-sass::before { content: "\f75f"; }
|
||||||
|
.bi-filetype-scss::before { content: "\f760"; }
|
||||||
|
.bi-filetype-sh::before { content: "\f761"; }
|
||||||
|
.bi-filetype-svg::before { content: "\f762"; }
|
||||||
|
.bi-filetype-tiff::before { content: "\f763"; }
|
||||||
|
.bi-filetype-tsx::before { content: "\f764"; }
|
||||||
|
.bi-filetype-ttf::before { content: "\f765"; }
|
||||||
|
.bi-filetype-txt::before { content: "\f766"; }
|
||||||
|
.bi-filetype-wav::before { content: "\f767"; }
|
||||||
|
.bi-filetype-woff::before { content: "\f768"; }
|
||||||
|
.bi-filetype-xls-1::before { content: "\f769"; }
|
||||||
|
.bi-filetype-xls::before { content: "\f76a"; }
|
||||||
|
.bi-filetype-xml::before { content: "\f76b"; }
|
||||||
|
.bi-filetype-yml::before { content: "\f76c"; }
|
||||||
|
.bi-heart-arrow::before { content: "\f76d"; }
|
||||||
|
.bi-heart-pulse-fill::before { content: "\f76e"; }
|
||||||
|
.bi-heart-pulse::before { content: "\f76f"; }
|
||||||
|
.bi-heartbreak-fill::before { content: "\f770"; }
|
||||||
|
.bi-heartbreak::before { content: "\f771"; }
|
||||||
|
.bi-hearts::before { content: "\f772"; }
|
||||||
|
.bi-hospital-fill::before { content: "\f773"; }
|
||||||
|
.bi-hospital::before { content: "\f774"; }
|
||||||
|
.bi-house-heart-fill::before { content: "\f775"; }
|
||||||
|
.bi-house-heart::before { content: "\f776"; }
|
||||||
|
.bi-incognito::before { content: "\f777"; }
|
||||||
|
.bi-magnet-fill::before { content: "\f778"; }
|
||||||
|
.bi-magnet::before { content: "\f779"; }
|
||||||
|
.bi-person-heart::before { content: "\f77a"; }
|
||||||
|
.bi-person-hearts::before { content: "\f77b"; }
|
||||||
|
.bi-phone-flip::before { content: "\f77c"; }
|
||||||
|
.bi-plugin::before { content: "\f77d"; }
|
||||||
|
.bi-postage-fill::before { content: "\f77e"; }
|
||||||
|
.bi-postage-heart-fill::before { content: "\f77f"; }
|
||||||
|
.bi-postage-heart::before { content: "\f780"; }
|
||||||
|
.bi-postage::before { content: "\f781"; }
|
||||||
|
.bi-postcard-fill::before { content: "\f782"; }
|
||||||
|
.bi-postcard-heart-fill::before { content: "\f783"; }
|
||||||
|
.bi-postcard-heart::before { content: "\f784"; }
|
||||||
|
.bi-postcard::before { content: "\f785"; }
|
||||||
|
.bi-search-heart-fill::before { content: "\f786"; }
|
||||||
|
.bi-search-heart::before { content: "\f787"; }
|
||||||
|
.bi-sliders2-vertical::before { content: "\f788"; }
|
||||||
|
.bi-sliders2::before { content: "\f789"; }
|
||||||
|
.bi-trash3-fill::before { content: "\f78a"; }
|
||||||
|
.bi-trash3::before { content: "\f78b"; }
|
||||||
|
.bi-valentine::before { content: "\f78c"; }
|
||||||
|
.bi-valentine2::before { content: "\f78d"; }
|
||||||
|
.bi-wrench-adjustable-circle-fill::before { content: "\f78e"; }
|
||||||
|
.bi-wrench-adjustable-circle::before { content: "\f78f"; }
|
||||||
|
.bi-wrench-adjustable::before { content: "\f790"; }
|
||||||
|
.bi-filetype-json::before { content: "\f791"; }
|
||||||
|
.bi-filetype-pptx::before { content: "\f792"; }
|
||||||
|
.bi-filetype-xlsx::before { content: "\f793"; }
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
.dataTables_info {
|
||||||
|
margin: 15px 0 !important;
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
.dataTables_paginate, .dataTables_length, .dataTables_filter {
|
||||||
|
margin: 15px 0 !important;
|
||||||
|
}
|
||||||
|
.dtr-details {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.table-striped>tbody>tr:nth-of-type(odd) {
|
||||||
|
background-color: #F2F2F2;
|
||||||
|
}
|
||||||
|
td.child>ul>li {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
table.dataTable>tbody>tr.child ul.dtr-details>li {
|
||||||
|
border-bottom: 1px solid rgba(0, 0, 0, 0.129);
|
||||||
|
padding: 0.5em 0;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover {
|
||||||
|
background-color: #5e5e5e;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before,
|
||||||
|
table.dataTable td.dt-control:before {
|
||||||
|
background-color: #979797 !important;
|
||||||
|
border: 1.5px solid #616161 !important;
|
||||||
|
border-radius: 2px !important;
|
||||||
|
color: #fff;
|
||||||
|
height: 1em;
|
||||||
|
width: 1em;
|
||||||
|
line-height: 1.25em;
|
||||||
|
border-radius: 0px;
|
||||||
|
box-shadow: none;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: 0.5s all;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before,
|
||||||
|
table.dataTable td.dt-control:before {
|
||||||
|
background-color: #979797 !important;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty {
|
||||||
|
background-color: #fbfbfb;
|
||||||
|
}
|
||||||
|
table.dataTable.table-striped>tbody>tr>td {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
table.dataTable.table-striped>tbody>tr>td>input[type="checkbox"] {
|
||||||
|
margin-top: 7px;
|
||||||
|
}
|
||||||
|
td.dtr-col-lg {
|
||||||
|
min-width: 350px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
td.dtr-col-md {
|
||||||
|
min-width: 250px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
td.dtr-col-sm {
|
||||||
|
min-width: 125px;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
.dt-data-w100 .dtr-data {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
li .dtr-data {
|
||||||
|
word-break: break-all;
|
||||||
|
flex: 1;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
}
|
||||||
|
table.dataTable>tbody>tr.child span.dtr-title {
|
||||||
|
width: 30%;
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
@@ -63,6 +63,17 @@
|
|||||||
.navbar-nav {
|
.navbar-nav {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
.navbar-nav .nav-item {
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 10px !important;
|
||||||
|
}
|
||||||
|
.navbar-nav .nav-link {
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 10px !important;
|
||||||
|
}
|
||||||
.navbar-fixed-bottom .navbar-collapse,
|
.navbar-fixed-bottom .navbar-collapse,
|
||||||
.navbar-fixed-top .navbar-collapse {
|
.navbar-fixed-top .navbar-collapse {
|
||||||
max-height: 1000px
|
max-height: 1000px
|
||||||
@@ -75,6 +86,12 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
.btn-group-xs > .btn, .btn-xs {
|
||||||
|
padding: .25rem .4rem;
|
||||||
|
font-size: .875rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
border-radius: .2rem;
|
||||||
|
}
|
||||||
.icon-spin {
|
.icon-spin {
|
||||||
animation-name: spin;
|
animation-name: spin;
|
||||||
animation-duration: 2000ms;
|
animation-duration: 2000ms;
|
||||||
@@ -105,13 +122,22 @@
|
|||||||
transform: rotate(359deg);
|
transform: rotate(359deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}
|
@keyframes blink {
|
||||||
.footable-sortable {
|
50% {
|
||||||
-webkit-user-select: none;
|
color: transparent
|
||||||
-moz-user-select: none;
|
}
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
.loader-dot {
|
||||||
|
animation: 1s blink infinite
|
||||||
|
}
|
||||||
|
.loader-dot:nth-child(2) {
|
||||||
|
animation-delay: 250ms
|
||||||
|
}
|
||||||
|
.loader-dot:nth-child(3) {
|
||||||
|
animation-delay: 500ms
|
||||||
|
}
|
||||||
|
|
||||||
|
pre{white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}
|
||||||
/* Fix modal moving content left */
|
/* Fix modal moving content left */
|
||||||
body.modal-open {
|
body.modal-open {
|
||||||
overflow: inherit;
|
overflow: inherit;
|
||||||
@@ -166,19 +192,11 @@ legend {
|
|||||||
top: 0; right: 0; bottom: 0; left: 0;
|
top: 0; right: 0; bottom: 0; left: 0;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
#top {
|
|
||||||
padding-top: 70px;
|
|
||||||
}
|
|
||||||
.bootstrap-select.btn-group .no-results {
|
.bootstrap-select.btn-group .no-results {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.dropdown-desc {
|
.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary {
|
||||||
display: block;
|
color: rgb(197, 197, 197) !important;
|
||||||
padding: 3px 10px;
|
|
||||||
clear: both;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #5a5a5a;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
}
|
||||||
.haveibeenpwned {
|
.haveibeenpwned {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -206,7 +224,7 @@ legend {
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.footer .version {
|
.footer .version {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.slave-info {
|
.slave-info {
|
||||||
@@ -225,15 +243,8 @@ legend {
|
|||||||
.btn-input-missing:active:hover,
|
.btn-input-missing:active:hover,
|
||||||
.btn-input-missing:active:focus {
|
.btn-input-missing:active:focus {
|
||||||
color: #000 !important;
|
color: #000 !important;
|
||||||
background-color: #ff4136;
|
background-color: #ff2f24 !important;
|
||||||
border-color: #ff291c;
|
border-color: #e21207 !important;
|
||||||
}
|
|
||||||
table.footable>tbody>tr.footable-empty>td {
|
|
||||||
font-style:italic;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
table>tbody>tr>td>span.footable-toggle {
|
|
||||||
opacity: 0.75;
|
|
||||||
}
|
}
|
||||||
.navbar-nav > li {
|
.navbar-nav > li {
|
||||||
font-size: 1rem !important;
|
font-size: 1rem !important;
|
||||||
@@ -260,18 +271,11 @@ code {
|
|||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-group-item.webauthn-authenticator-selection,
|
.dropdown-header {
|
||||||
.list-group-item.totp-authenticator-selection,
|
font-weight: 600;
|
||||||
.list-group-item.yubi_otp-authenticator-selection {
|
|
||||||
border-radius: 0px !important;
|
|
||||||
}
|
|
||||||
.pending-tfa-collapse {
|
|
||||||
padding: 10px;
|
|
||||||
background: #fbfbfb;
|
|
||||||
border: 1px solid #ededed;
|
|
||||||
min-height: 110px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.tag-box {
|
.tag-box {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
@@ -295,7 +299,7 @@ code {
|
|||||||
}
|
}
|
||||||
.tag-input {
|
.tag-input {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
border: 0;
|
border: 0 !important;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
@@ -308,3 +312,72 @@ code {
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#dnstable {
|
||||||
|
overflow-x: auto!important;
|
||||||
|
}
|
||||||
|
.well {
|
||||||
|
border: 1px solid #dfdfdf;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-check-label {
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
.caret {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
a[aria-expanded='true'] > .caret,
|
||||||
|
button[aria-expanded='true'] > .caret {
|
||||||
|
transform: rotate(-180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-details {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.list-group-header {
|
||||||
|
background: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.bg-primary, .alert-primary, .btn-primary {
|
||||||
|
background-color: #0F688D !important;
|
||||||
|
border-color: #0d526d !important;
|
||||||
|
}
|
||||||
|
.bg-info, .alert-info, .btn-info {
|
||||||
|
background-color: #148DBC !important;
|
||||||
|
border-color: #127ea8 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary {
|
||||||
|
color: rgb(137 137 137)!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
background-color: #d5d5d5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn-outline-secondary:hover {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
}
|
||||||
|
.btn.btn-outline-secondary {
|
||||||
|
border-color: #cfcfcf !important;
|
||||||
|
}
|
||||||
|
.btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show {
|
||||||
|
background-color: #f0f0f0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
div.dataTables_wrapper div.dataTables_filter {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
div.dataTables_wrapper div.dataTables_length {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.dataTables_paginate, .dataTables_length, .dataTables_filter {
|
||||||
|
margin: 10px 0!important;
|
||||||
|
}
|
||||||
@@ -1,308 +0,0 @@
|
|||||||
.space20 {
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-xs-lg>.lang-sm:after {
|
|
||||||
margin-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.bootstrap-select {
|
|
||||||
max-width: 350px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-login .apps .btn {
|
|
||||||
width: auto;
|
|
||||||
float: left;
|
|
||||||
margin-right: 10px;
|
|
||||||
margin-top: auto;
|
|
||||||
}
|
|
||||||
.panel-login .apps .btn:hover {
|
|
||||||
margin-top: 1px !important;
|
|
||||||
border-bottom-width: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.panel-login .apps .btn {
|
|
||||||
width: 100%;
|
|
||||||
float: none;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel-login .apps .btn {
|
|
||||||
border-bottom-width: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-clearfix::after {
|
|
||||||
clear: both;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-clearfix::before {
|
|
||||||
display: table;
|
|
||||||
content: " ";
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xs-show {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-group .panel{
|
|
||||||
border: none;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-group .panel-body {
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-group .js-tabcollapse-panel-body .panel-body {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-body .panel-heading {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-body .well,
|
|
||||||
.panel-body .form-inline.well {
|
|
||||||
border: none;
|
|
||||||
padding: 0;
|
|
||||||
margin: 0;
|
|
||||||
box-shadow: none;
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.js-tabcollapse-panel-heading {
|
|
||||||
display: block;
|
|
||||||
height: 37px;
|
|
||||||
line-height: 37px;
|
|
||||||
text-indent: 15px;
|
|
||||||
}
|
|
||||||
.js-tabcollapse-panel-heading:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.js-tabcollapse-panel-heading {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.js-tabcollapse-panel-heading:after {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
top: 17px;
|
|
||||||
right: 17px;
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
margin-left: 2px;
|
|
||||||
vertical-align: middle;
|
|
||||||
border-bottom: 4px dashed;
|
|
||||||
border-right: 4px solid transparent;
|
|
||||||
border-left: 4px solid transparent;
|
|
||||||
}
|
|
||||||
.js-tabcollapse-panel-heading.collapsed:after {
|
|
||||||
border-bottom: none;
|
|
||||||
border-top: 4px dashed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.recent-login-success {
|
|
||||||
font-size: 14px;
|
|
||||||
margin-top: 10px !important;
|
|
||||||
}
|
|
||||||
.pull-xs-right {
|
|
||||||
float: right !important;
|
|
||||||
}
|
|
||||||
.pull-xs-right .dropdown-menu {
|
|
||||||
right: 0;
|
|
||||||
left: auto;
|
|
||||||
}
|
|
||||||
.text-xs-left {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.text-xs-bold {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.text-xs-bold .small {
|
|
||||||
font-weight: normal;
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
.help-block {
|
|
||||||
text-align: justify;
|
|
||||||
}
|
|
||||||
.btn.visible-xs-block {
|
|
||||||
width: 100%;
|
|
||||||
float: none;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions .btn.btn-xs-half,
|
|
||||||
.btn.visible-xs-block.btn-xs-half {
|
|
||||||
width: 50%;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions .btn.btn-xs-third,
|
|
||||||
.btn.visible-xs-block.btn-xs-third {
|
|
||||||
width: 33.33%;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions .btn.btn-xs-quart,
|
|
||||||
.btn.visible-xs-block.btn-xs-quart {
|
|
||||||
width: 25%;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
.btn.visible-xs-block.btn-sm,
|
|
||||||
.btn-xs-lg {
|
|
||||||
padding: 15px 16px 13px;
|
|
||||||
line-height: 15px;
|
|
||||||
}
|
|
||||||
.input-xs-lg {
|
|
||||||
height: 47px;
|
|
||||||
padding: 13px 16px;
|
|
||||||
}
|
|
||||||
.btn-group:not(.input-group-btn) {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
.btn-group.nowrap {
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
}
|
|
||||||
.btn-group.nowrap .dropdown-menu {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.panel-login .btn-group {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.mass-actions-user .btn-group {
|
|
||||||
float: none;
|
|
||||||
}
|
|
||||||
div[class^='mass-actions'] .dropdown-menu,
|
|
||||||
.panel-xs-lg .dropdown-menu,
|
|
||||||
.dropdown-menu.login {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
div[class^='mass-actions'] .btn-group .dropdown-menu {
|
|
||||||
top: 50%;
|
|
||||||
}
|
|
||||||
div[class^='mass-actions'] .btn-group .btn-group .dropdown-menu,
|
|
||||||
div.mass-actions-quarantine .btn-group .dropdown-menu,
|
|
||||||
.panel-xs-lg .dropdown-menu {
|
|
||||||
top: 100%;
|
|
||||||
}
|
|
||||||
div[class^='mass-actions'] .dropdown-menu>li>a,
|
|
||||||
.panel-xs-lg .dropdown-menu>li>a,
|
|
||||||
.dropdown-menu.login>li>a {
|
|
||||||
padding: 8px 20px;
|
|
||||||
}
|
|
||||||
div[class^='mass-actions'] .dropdown-header {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
.space20 {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.top100 {
|
|
||||||
top: 100% !important;
|
|
||||||
}
|
|
||||||
.top33 {
|
|
||||||
top: 33% !important;
|
|
||||||
}
|
|
||||||
.footable-filtering .form {
|
|
||||||
width: 65%;
|
|
||||||
}
|
|
||||||
.btn-xs-lg>.lang-sm:after {
|
|
||||||
top: 1px;
|
|
||||||
}
|
|
||||||
table.footable>tfoot>tr.footable-paging>td {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.footable-first-visible {
|
|
||||||
min-width: 55px;
|
|
||||||
}
|
|
||||||
table>tbody>tr>td>span.footable-toggle {
|
|
||||||
font-size: 24px;
|
|
||||||
margin-right: 14px !important;
|
|
||||||
}
|
|
||||||
table>tbody>tr>td>span.footable-toggle + input {
|
|
||||||
position: absolute;
|
|
||||||
left: 38px;
|
|
||||||
}
|
|
||||||
.pagination {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
tr.footable-filtering>th>form {
|
|
||||||
width: 270px;
|
|
||||||
}
|
|
||||||
.mass-actions-mailbox {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
.panel-xs-lg .panel-heading {
|
|
||||||
height: 66px;
|
|
||||||
line-height: 47px;
|
|
||||||
}
|
|
||||||
.panel-xs-lg .btn-group .btn {
|
|
||||||
padding-right: 5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn) {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.btn-group:not(.bootstrap-select) {
|
|
||||||
width: auto !important;
|
|
||||||
}
|
|
||||||
.bootstrap-select {
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
.img-responsive {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions {
|
|
||||||
position: absolute;
|
|
||||||
width: 90vw !important;
|
|
||||||
left: 0;
|
|
||||||
height: 36px;
|
|
||||||
margin-top: -8px;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions .btn {
|
|
||||||
padding: 10px 16px 7px;
|
|
||||||
line-height: 15px;
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.btn-group.footable-actions:after {
|
|
||||||
content: "";
|
|
||||||
display: block;
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text {
|
|
||||||
margin-right: 14px;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
.clearfix {
|
|
||||||
flex-basis: 100%;
|
|
||||||
height: 0;
|
|
||||||
}
|
|
||||||
.btn-group > .btn-group {
|
|
||||||
flex-basis: 100%;
|
|
||||||
}
|
|
||||||
.btn-group .btn {
|
|
||||||
display: flex !important;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
.btn-group .btn i {
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
.btn-group .btn .caret {
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
.panel-login .btn-group .btn {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
.panel-login .clearfix {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 350px) {
|
|
||||||
.mailcow-logo img {
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
.btn-xs-lg>.lang-sm:after {
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-select {
|
||||||
|
max-width: 350px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-login .apps .btn {
|
||||||
|
width: auto;
|
||||||
|
float: left;
|
||||||
|
margin-right: 10px;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
.card-login .apps .btn:hover {
|
||||||
|
margin-top: 1px !important;
|
||||||
|
border-bottom-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-tabs .nav-tabs {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dataTables_paginate.paging_simple_numbers .pagination {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.responsive-tabs .nav-tabs {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-tabs .card .card-body.collapse {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.responsive-tabs .tab-pane {
|
||||||
|
display: block !important;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-login .apps .btn {
|
||||||
|
width: 100%;
|
||||||
|
float: none;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-login .apps .btn {
|
||||||
|
border-bottom-width: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xs-show {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recent-login-success {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-top: 10px !important;
|
||||||
|
}
|
||||||
|
.pull-xs-right {
|
||||||
|
float: right !important;
|
||||||
|
}
|
||||||
|
.pull-xs-right .dropdown-menu {
|
||||||
|
right: 0;
|
||||||
|
left: auto;
|
||||||
|
}
|
||||||
|
.text-xs-left {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
.text-xs-bold {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.text-xs-bold .small {
|
||||||
|
font-weight: normal;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
.btn.d-block {
|
||||||
|
width: 100%;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
.btn.btn-xs-half,
|
||||||
|
.btn.d-block.btn-xs-half {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.btn.btn-xs-third,
|
||||||
|
.btn.d-block.btn-xs-third {
|
||||||
|
width: 33.33%;
|
||||||
|
}
|
||||||
|
.btn.btn-xs-quart,
|
||||||
|
.btn.d-block.btn-xs-quart {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
.btn.d-block.btn-sm,
|
||||||
|
.btn-xs-lg {
|
||||||
|
padding: .5rem 1rem;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
.input-xs-lg {
|
||||||
|
height: 47px;
|
||||||
|
padding: 13px 16px;
|
||||||
|
}
|
||||||
|
.btn-group:not(.input-group-btn) {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
.btn-group.nowrap {
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
}
|
||||||
|
.btn-group.nowrap .dropdown-menu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.card-login .btn-group {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.mass-actions-user .btn-group {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
div[class^='mass-actions'] .dropdown-menu,
|
||||||
|
.card-xs-lg .dropdown-menu,
|
||||||
|
.dropdown-menu.login {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
div[class^='mass-actions'] .btn-group .dropdown-menu {
|
||||||
|
top: 50%;
|
||||||
|
}
|
||||||
|
div[class^='mass-actions'] .btn-group .btn-group .dropdown-menu,
|
||||||
|
div.mass-actions-quarantine .btn-group .dropdown-menu,
|
||||||
|
.card-xs-lg .dropdown-menu {
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
div[class^='mass-actions'] .dropdown-menu>li>a,
|
||||||
|
.card-xs-lg .dropdown-menu>li>a,
|
||||||
|
.dropdown-menu.login>li>a {
|
||||||
|
padding: 8px 20px;
|
||||||
|
}
|
||||||
|
div[class^='mass-actions'] .dropdown-header {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.top100 {
|
||||||
|
top: 100% !important;
|
||||||
|
}
|
||||||
|
.top33 {
|
||||||
|
top: 33% !important;
|
||||||
|
}
|
||||||
|
.footable-filtering .form {
|
||||||
|
width: 65%;
|
||||||
|
}
|
||||||
|
.btn-xs-lg>.lang-sm:after {
|
||||||
|
top: 1px;
|
||||||
|
}
|
||||||
|
.pagination {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
.mass-actions-mailbox {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.card-xs-lg .card-header {
|
||||||
|
height: 66px;
|
||||||
|
line-height: 47px;
|
||||||
|
}
|
||||||
|
.card-xs-lg .btn-group .btn {
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-left: 5px;
|
||||||
|
}
|
||||||
|
.bootstrap-select:not([class*=col-]):not([class*=form-control]):not(.input-group-btn) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.btn-group:not(.bootstrap-select) {
|
||||||
|
width: auto !important;
|
||||||
|
}
|
||||||
|
.bootstrap-select {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.bootstrap-select.btn-group.show-tick .dropdown-menu li a span.text {
|
||||||
|
margin-right: 14px;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
.btn-group > .btn-group {
|
||||||
|
flex-basis: 100%;
|
||||||
|
}
|
||||||
|
.btn-group .btn {
|
||||||
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.btn-group .btn i {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.card-login .btn-group .btn {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dt-sm-head-hidden .dtr-title {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.dataTables_wrapper div.dataTables_length {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 350px) {
|
||||||
|
.mailcow-logo img {
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1400px) {
|
||||||
|
.container-xxl, .container-xl, .container-lg, .container-md, .container-sm, .container {
|
||||||
|
max-width: 1600px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,6 @@ body.modal-open {
|
|||||||
}
|
}
|
||||||
.mass-actions-admin {
|
.mass-actions-admin {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding:10px 0 10px 0;
|
|
||||||
}
|
}
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
border-color: #FF4136;
|
border-color: #FF4136;
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
}
|
}
|
||||||
.mass-actions-debug {
|
.mass-actions-debug {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding:10px 0 10px 10px;
|
|
||||||
}
|
}
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
border-color: #FF4136;
|
border-color: #FF4136;
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
}
|
}
|
||||||
.mass-actions-user {
|
.mass-actions-user {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding:10px 0 10px 0;
|
|
||||||
}
|
}
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
border-color: #FF4136;
|
border-color: #FF4136;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
}
|
}
|
||||||
.mass-actions-mailbox {
|
.mass-actions-mailbox {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding:10px 0 10px 10px;
|
|
||||||
}
|
}
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
border-color: #FF4136;
|
border-color: #FF4136;
|
||||||
|
|||||||
@@ -35,7 +35,6 @@
|
|||||||
|
|
||||||
.mass-actions-quarantine {
|
.mass-actions-quarantine {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
}
|
}
|
||||||
.mass-actions-user {
|
.mass-actions-user {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
padding:10px 0;
|
|
||||||
}
|
}
|
||||||
.inputMissingAttr {
|
.inputMissingAttr {
|
||||||
border-color: #FF4136;
|
border-color: #FF4136;
|
||||||
|
|||||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,368 @@
|
|||||||
|
body {
|
||||||
|
background-color: #414141;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: 1px solid #1c1c1c;
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
}
|
||||||
|
legend {
|
||||||
|
color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.card-header {
|
||||||
|
color: #bbb;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
.btn-secondary, .paginate_button, .page-link, .btn-light {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
border-color: #5c5c5c !important;
|
||||||
|
}
|
||||||
|
.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle {
|
||||||
|
border-color: #7a7a7a !important;
|
||||||
|
}
|
||||||
|
.alert-secondary {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
border-color: #5c5c5c !important;
|
||||||
|
}
|
||||||
|
.bg-secondary {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
}
|
||||||
|
.alert-secondary, .alert-secondary a, .alert-secondary .alert-link {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.page-item.active .page-link {
|
||||||
|
background-color: #158cba !important;
|
||||||
|
border-color: #127ba3 !important;
|
||||||
|
}
|
||||||
|
.btn-secondary:focus, .btn-secondary:hover, .btn-group.open .dropdown-toggle.btn-secondary {
|
||||||
|
background-color: #7a7a7a;
|
||||||
|
border-color: #5c5c5c !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.btn-secondary:disabled, .btn-secondary.disabled {
|
||||||
|
border-color: #7a7a7a !important;
|
||||||
|
}
|
||||||
|
.modal-content {
|
||||||
|
background-color: #414141;
|
||||||
|
}
|
||||||
|
.modal-header {
|
||||||
|
border-bottom: 1px solid #161616;
|
||||||
|
}
|
||||||
|
.modal-title {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.modal .btn-close {
|
||||||
|
filter: invert(1) grayscale(100%) brightness(200%);
|
||||||
|
}
|
||||||
|
.navbar.bg-light {
|
||||||
|
background-color: #222222 !important;
|
||||||
|
border-color: #181818;
|
||||||
|
}
|
||||||
|
.nav-link {
|
||||||
|
color: #ccc !important;
|
||||||
|
}
|
||||||
|
.nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.nav-tabs .nav-link:not(.disabled):hover, .nav-tabs .nav-link:not(.disabled):focus, .nav-tabs .nav-link.active {
|
||||||
|
border-bottom-color: #414141;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table, .table-striped>tbody>tr:nth-of-type(odd)>*, tbody tr {
|
||||||
|
color: #ccc !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown-menu {
|
||||||
|
background-color: #585858;
|
||||||
|
border: 1px solid #333;
|
||||||
|
}
|
||||||
|
.dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover {
|
||||||
|
color: #fafafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bootstrap-select>.dropdown-toggle.bs-placeholder, .bootstrap-select>.dropdown-toggle.bs-placeholder:active, .bootstrap-select>.dropdown-toggle.bs-placeholder:focus, .bootstrap-select>.dropdown-toggle.bs-placeholder:hover {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.bootstrap-select>.dropdown-toggle.bs-placeholder, .bootstrap-select>.dropdown-toggle.bs-placeholder.btn-secondary {
|
||||||
|
color: #d4d4d4 !important;
|
||||||
|
}
|
||||||
|
tbody tr {
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:focus, .navbar-default .navbar-nav>.active>a:hover {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.list-group-item {
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
.table-striped>tbody>tr:nth-of-type(odd) {
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
table.dataTable>tbody>tr.child ul.dtr-details>li {
|
||||||
|
border-bottom: 1px solid rgba(255, 255, 255, 0.13);
|
||||||
|
}
|
||||||
|
tbody tr {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.label.label-last-login {
|
||||||
|
color: #ccc !important;
|
||||||
|
background-color: #555 !important;
|
||||||
|
}
|
||||||
|
.progress {
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
.h1, .h2, .h3, .h4, .h5, .h6, h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
div.numberedtextarea-number {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
.well {
|
||||||
|
border: 1px solid #555;
|
||||||
|
background-color: #333;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
color: #ccc;
|
||||||
|
background-color: #333;
|
||||||
|
border: 1px solid #555;
|
||||||
|
}
|
||||||
|
input.form-control, textarea.form-control {
|
||||||
|
color: #e2e2e2 !important;
|
||||||
|
background-color: #555 !important;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
input.form-control:focus, textarea.form-control {
|
||||||
|
background-color: #555 !important;
|
||||||
|
}
|
||||||
|
input.form-control:disabled, textarea.form-disabled {
|
||||||
|
color: #a8a8a8 !important;
|
||||||
|
background-color: #6e6e6e !important;
|
||||||
|
}
|
||||||
|
.input-group-addon {
|
||||||
|
color: #ccc;
|
||||||
|
background-color: #555 !important;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
.input-group-text {
|
||||||
|
color: #ccc;
|
||||||
|
background-color: #242424;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.dropdown-item {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.dropdown-item:hover {
|
||||||
|
color: #616161 !important;
|
||||||
|
}
|
||||||
|
.dropdown-item.active:hover {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #31b1e4;
|
||||||
|
}
|
||||||
|
.form-select {
|
||||||
|
color: #e2e2e2!important;
|
||||||
|
background-color: #555!important;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.responsive-tabs .card-header button[data-bs-toggle="collapse"] {
|
||||||
|
color: #c7c7c7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-toggler {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.table-secondary {
|
||||||
|
--bs-table-bg: #7a7a7a;
|
||||||
|
--bs-table-striped-bg: #e4e4e4;
|
||||||
|
--bs-table-striped-color: #000;
|
||||||
|
--bs-table-active-bg: #d8d8d8;
|
||||||
|
--bs-table-active-color: #000;
|
||||||
|
--bs-table-hover-bg: #dedede;
|
||||||
|
--bs-table-hover-color: #000;
|
||||||
|
color: #000;
|
||||||
|
border-color: #d8d8d8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-light {
|
||||||
|
--bs-table-bg: #f6f6f6;
|
||||||
|
--bs-table-striped-bg: #eaeaea;
|
||||||
|
--bs-table-striped-color: #000;
|
||||||
|
--bs-table-active-bg: #dddddd;
|
||||||
|
--bs-table-active-color: #000;
|
||||||
|
--bs-table-hover-bg: #e4e4e4;
|
||||||
|
--bs-table-hover-color: #000;
|
||||||
|
color: #000;
|
||||||
|
border-color: #dddddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control-plaintext {
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
border-color: #5c5c5c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #6fc7e9;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #3daedb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-item.active {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.list-group-item.disabled, .list-group-item:disabled {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #a8a8a8 !important;
|
||||||
|
border-color: #a8a8a8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.bg-light .card-title {
|
||||||
|
color: #000 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card.bg-light .card-text {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.accordion-item {
|
||||||
|
background-color: #3a3a3a;
|
||||||
|
}
|
||||||
|
.accordion-button {
|
||||||
|
color: #bbb;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
}
|
||||||
|
.accordion-button:not(.collapsed) {
|
||||||
|
color: #6fc7e9;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
}
|
||||||
|
.accordion-button::after {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
.accordion-button:not(.collapsed)::after {
|
||||||
|
background-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.toast-header {
|
||||||
|
background-color: #4c4c4c;
|
||||||
|
}
|
||||||
|
.toast-body {
|
||||||
|
background-color: #626262;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-pills .nav-link.active, .nav-pills .show > .nav-link {
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-box {
|
||||||
|
background-color: #555;
|
||||||
|
border: 1px solid #999;
|
||||||
|
}
|
||||||
|
.tag-input {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #555;
|
||||||
|
}
|
||||||
|
.tag-add {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
.tag-add:hover {
|
||||||
|
color: #d1d1d1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover {
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before {
|
||||||
|
background-color: #7a7a7a !important;
|
||||||
|
border: 1.5px solid #5c5c5c !important;
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before {
|
||||||
|
background-color: #949494;
|
||||||
|
}
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>th.child,
|
||||||
|
table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty {
|
||||||
|
background-color: #444444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-check-label {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.btn-outline-secondary:hover {
|
||||||
|
background-color: #c3c3c3;
|
||||||
|
}
|
||||||
|
.btn.btn-outline-secondary {
|
||||||
|
color: #fff !important;
|
||||||
|
border-color: #7a7a7a !important;
|
||||||
|
}
|
||||||
|
.btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show {
|
||||||
|
background-color: #9b9b9b !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.btn-input-missing,
|
||||||
|
.btn-input-missing:hover,
|
||||||
|
.btn-input-missing:active,
|
||||||
|
.btn-input-missing:focus,
|
||||||
|
.btn-input-missing:active:hover,
|
||||||
|
.btn-input-missing:active:focus {
|
||||||
|
color: #fff !important;
|
||||||
|
background-color: #ff2f24 !important;
|
||||||
|
border-color: #e21207 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputMissingAttr {
|
||||||
|
border-color: #FF4136 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.list-group-details {
|
||||||
|
background: #444444;
|
||||||
|
}
|
||||||
|
.list-group-header {
|
||||||
|
background: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.mail-address-item {
|
||||||
|
background-color: #333;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #555;
|
||||||
|
padding: 2px 7px;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 2px 6px 2px 0;
|
||||||
|
}
|
||||||
@@ -11,6 +11,11 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||||||
$solr_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_SOLR"])) ? false : solr_status();
|
$solr_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_SOLR"])) ? false : solr_status();
|
||||||
$clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true;
|
$clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true;
|
||||||
|
|
||||||
|
|
||||||
|
if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CACHE')) {
|
||||||
|
$_SESSION['gal'] = json_decode($license_cache, true);
|
||||||
|
}
|
||||||
|
|
||||||
$js_minifier->add('/web/js/site/debug.js');
|
$js_minifier->add('/web/js/site/debug.js');
|
||||||
|
|
||||||
// vmail df
|
// vmail df
|
||||||
@@ -44,15 +49,26 @@ foreach ($containers as $container => $container_info) {
|
|||||||
$containers[$container]['State']['StartedAtHR'] = $started;
|
$containers[$container]['State']['StartedAtHR'] = $started;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get mailcow data
|
||||||
|
$hostname = getenv('MAILCOW_HOSTNAME');
|
||||||
|
$timezone = getenv('TZ');
|
||||||
|
|
||||||
$template = 'debug.twig';
|
$template = 'debug.twig';
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'log_lines' => getenv('LOG_LINES'),
|
'log_lines' => getenv('LOG_LINES'),
|
||||||
'vmail_df' => $vmail_df,
|
'vmail_df' => $vmail_df,
|
||||||
|
'hostname' => $hostname,
|
||||||
|
'timezone' => $timezone,
|
||||||
|
'gal' => @$_SESSION['gal'],
|
||||||
|
'license_guid' => license('guid'),
|
||||||
'solr_status' => $solr_status,
|
'solr_status' => $solr_status,
|
||||||
'solr_uptime' => round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60),
|
'solr_uptime' => round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60),
|
||||||
'clamd_status' => $clamd_status,
|
'clamd_status' => $clamd_status,
|
||||||
'containers' => $containers,
|
'containers' => $containers,
|
||||||
|
'ip_check' => customize('get', 'ip_check'),
|
||||||
'lang_admin' => json_encode($lang['admin']),
|
'lang_admin' => json_encode($lang['admin']),
|
||||||
|
'lang_debug' => json_encode($lang['debug']),
|
||||||
|
'lang_datatables' => json_encode($lang['datatables']),
|
||||||
];
|
];
|
||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||||
|
|||||||
+65
-39
@@ -38,24 +38,46 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||||||
$template = 'edit/admin.twig';
|
$template = 'edit/admin.twig';
|
||||||
$template_data = ['admin' => $admin];
|
$template_data = ['admin' => $admin];
|
||||||
}
|
}
|
||||||
elseif (isset($_GET['domain']) &&
|
elseif (isset($_GET['domain'])) {
|
||||||
is_valid_domain_name($_GET["domain"]) &&
|
if (is_valid_domain_name($_GET["domain"]) &&
|
||||||
!empty($_GET["domain"])) {
|
!empty($_GET["domain"])) {
|
||||||
$domain = $_GET["domain"];
|
// edit domain
|
||||||
$result = mailbox('get', 'domain_details', $domain);
|
$domain = $_GET["domain"];
|
||||||
$quota_notification_bcc = quota_notification_bcc('get', $domain);
|
$result = mailbox('get', 'domain_details', $domain);
|
||||||
$rl = ratelimit('get', 'domain', $domain);
|
$quota_notification_bcc = quota_notification_bcc('get', $domain);
|
||||||
$rlyhosts = relayhost('get');
|
$rl = ratelimit('get', 'domain', $domain);
|
||||||
$template = 'edit/domain.twig';
|
$rlyhosts = relayhost('get');
|
||||||
|
$template = 'edit/domain.twig';
|
||||||
|
$template_data = [
|
||||||
|
'acl' => $_SESSION['acl'],
|
||||||
|
'domain' => $domain,
|
||||||
|
'quota_notification_bcc' => $quota_notification_bcc,
|
||||||
|
'rl' => $rl,
|
||||||
|
'rlyhosts' => $rlyhosts,
|
||||||
|
'dkim' => dkim('details', $domain),
|
||||||
|
'domain_details' => $result,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif (isset($_GET["template"])){
|
||||||
|
$domain_template = mailbox('get', 'domain_templates', $_GET["template"]);
|
||||||
|
if ($domain_template){
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'acl' => $_SESSION['acl'],
|
'template' => $domain_template
|
||||||
'domain' => $domain,
|
|
||||||
'quota_notification_bcc' => $quota_notification_bcc,
|
|
||||||
'rl' => $rl,
|
|
||||||
'rlyhosts' => $rlyhosts,
|
|
||||||
'dkim' => dkim('details', $domain),
|
|
||||||
'domain_details' => $result,
|
|
||||||
];
|
];
|
||||||
|
$template = 'edit/domain-templates.twig';
|
||||||
|
$result = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$mailbox_template = mailbox('get', 'mailbox_templates', $_GET["template"]);
|
||||||
|
if ($mailbox_template){
|
||||||
|
$template_data = [
|
||||||
|
'template' => $mailbox_template
|
||||||
|
];
|
||||||
|
$template = 'edit/mailbox-templates.twig';
|
||||||
|
$result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elseif (isset($_GET['oauth2client']) &&
|
elseif (isset($_GET['oauth2client']) &&
|
||||||
is_numeric($_GET["oauth2client"]) &&
|
is_numeric($_GET["oauth2client"]) &&
|
||||||
@@ -79,29 +101,32 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||||||
'dkim' => dkim('details', $alias_domain),
|
'dkim' => dkim('details', $alias_domain),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
elseif (isset($_GET['mailbox']) && filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) {
|
elseif (isset($_GET['mailbox'])){
|
||||||
$mailbox = html_entity_decode(rawurldecode($_GET["mailbox"]));
|
if(filter_var(html_entity_decode(rawurldecode($_GET["mailbox"])), FILTER_VALIDATE_EMAIL) && !empty($_GET["mailbox"])) {
|
||||||
$result = mailbox('get', 'mailbox_details', $mailbox);
|
// edit mailbox
|
||||||
$rl = ratelimit('get', 'mailbox', $mailbox);
|
$mailbox = html_entity_decode(rawurldecode($_GET["mailbox"]));
|
||||||
$pushover_data = pushover('get', $mailbox);
|
$result = mailbox('get', 'mailbox_details', $mailbox);
|
||||||
$quarantine_notification = mailbox('get', 'quarantine_notification', $mailbox);
|
$rl = ratelimit('get', 'mailbox', $mailbox);
|
||||||
$quarantine_category = mailbox('get', 'quarantine_category', $mailbox);
|
$pushover_data = pushover('get', $mailbox);
|
||||||
$get_tls_policy = mailbox('get', 'tls_policy', $mailbox);
|
$quarantine_notification = mailbox('get', 'quarantine_notification', $mailbox);
|
||||||
$rlyhosts = relayhost('get');
|
$quarantine_category = mailbox('get', 'quarantine_category', $mailbox);
|
||||||
$template = 'edit/mailbox.twig';
|
$get_tls_policy = mailbox('get', 'tls_policy', $mailbox);
|
||||||
$template_data = [
|
$rlyhosts = relayhost('get');
|
||||||
'acl' => $_SESSION['acl'],
|
$template = 'edit/mailbox.twig';
|
||||||
'mailbox' => $mailbox,
|
$template_data = [
|
||||||
'rl' => $rl,
|
'acl' => $_SESSION['acl'],
|
||||||
'pushover_data' => $pushover_data,
|
'mailbox' => $mailbox,
|
||||||
'quarantine_notification' => $quarantine_notification,
|
'rl' => $rl,
|
||||||
'quarantine_category' => $quarantine_category,
|
'pushover_data' => $pushover_data,
|
||||||
'get_tls_policy' => $get_tls_policy,
|
'quarantine_notification' => $quarantine_notification,
|
||||||
'rlyhosts' => $rlyhosts,
|
'quarantine_category' => $quarantine_category,
|
||||||
'sender_acl_handles' => mailbox('get', 'sender_acl_handles', $mailbox),
|
'get_tls_policy' => $get_tls_policy,
|
||||||
'user_acls' => acl('get', 'user', $mailbox),
|
'rlyhosts' => $rlyhosts,
|
||||||
'mailbox_details' => $result
|
'sender_acl_handles' => mailbox('get', 'sender_acl_handles', $mailbox),
|
||||||
];
|
'user_acls' => acl('get', 'user', $mailbox),
|
||||||
|
'mailbox_details' => $result
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
elseif (isset($_GET['relayhost']) && is_numeric($_GET["relayhost"]) && !empty($_GET["relayhost"])) {
|
elseif (isset($_GET['relayhost']) && is_numeric($_GET["relayhost"]) && !empty($_GET["relayhost"])) {
|
||||||
$relayhost = intval($_GET["relayhost"]);
|
$relayhost = intval($_GET["relayhost"]);
|
||||||
@@ -189,5 +214,6 @@ $js_minifier->add('/web/js/site/pwgen.js');
|
|||||||
$template_data['result'] = $result;
|
$template_data['result'] = $result;
|
||||||
$template_data['return_to'] = $_SESSION['return_to'];
|
$template_data['return_to'] = $_SESSION['return_to'];
|
||||||
$template_data['lang_user'] = json_encode($lang['user']);
|
$template_data['lang_user'] = json_encode($lang['user']);
|
||||||
|
$template_data['lang_datatables'] = json_encode($lang['datatables']);
|
||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File renamed without changes.
Binary file not shown.
|
After Width: | Height: | Size: 7.4 KiB |
@@ -436,7 +436,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</table>
|
</table>
|
||||||
<a id='download-zonefile' class="btn btn-sm btn-default visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline" style="margin-top:10px" data-zonefile="<?=base64_encode($dns_data);?>" download='<?=$_GET['domain'];?>.txt' type='text/csv'>Download</a>
|
<a id='download-zonefile' class="btn btn-sm btn-secondary visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline mb-4" style="margin-top:10px" data-zonefile="<?=base64_encode($dns_data);?>" download='<?=$_GET['domain'];?>.txt' type='text/csv'>Download</a>
|
||||||
<script>
|
<script>
|
||||||
var zonefile_dl_link = document.getElementById('download-zonefile');
|
var zonefile_dl_link = document.getElementById('download-zonefile');
|
||||||
var zonefile = atob(zonefile_dl_link.getAttribute('data-zonefile'));
|
var zonefile = atob(zonefile_dl_link.getAttribute('data-zonefile'));
|
||||||
|
|||||||
@@ -2,8 +2,18 @@
|
|||||||
function customize($_action, $_item, $_data = null) {
|
function customize($_action, $_item, $_data = null) {
|
||||||
global $redis;
|
global $redis;
|
||||||
global $lang;
|
global $lang;
|
||||||
|
|
||||||
switch ($_action) {
|
switch ($_action) {
|
||||||
case 'add':
|
case 'add':
|
||||||
|
// disable functionality when demo mode is enabled
|
||||||
|
if ($GLOBALS["DEMO_MODE"]) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => 'demo_mode_enabled'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
@@ -72,6 +82,15 @@ function customize($_action, $_item, $_data = null) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'edit':
|
case 'edit':
|
||||||
|
// disable functionality when demo mode is enabled
|
||||||
|
if ($GLOBALS["DEMO_MODE"]) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => 'demo_mode_enabled'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
@@ -116,6 +135,7 @@ function customize($_action, $_item, $_data = null) {
|
|||||||
$ui_announcement_text = $_data['ui_announcement_text'];
|
$ui_announcement_text = $_data['ui_announcement_text'];
|
||||||
$ui_announcement_type = (in_array($_data['ui_announcement_type'], array('info', 'warning', 'danger'))) ? $_data['ui_announcement_type'] : false;
|
$ui_announcement_type = (in_array($_data['ui_announcement_type'], array('info', 'warning', 'danger'))) ? $_data['ui_announcement_type'] : false;
|
||||||
$ui_announcement_active = (!empty($_data['ui_announcement_active']) ? 1 : 0);
|
$ui_announcement_active = (!empty($_data['ui_announcement_active']) ? 1 : 0);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
|
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
|
||||||
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
|
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
|
||||||
@@ -140,9 +160,37 @@ function customize($_action, $_item, $_data = null) {
|
|||||||
'msg' => 'ui_texts'
|
'msg' => 'ui_texts'
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'ip_check':
|
||||||
|
$ip_check = ($_data['ip_check_opt_in'] == "1") ? 1 : 0;
|
||||||
|
try {
|
||||||
|
$redis->set('IP_CHECK', $ip_check);
|
||||||
|
}
|
||||||
|
catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => 'ip_check_opt_in_modified'
|
||||||
|
);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'delete':
|
case 'delete':
|
||||||
|
// disable functionality when demo mode is enabled
|
||||||
|
if ($GLOBALS["DEMO_MODE"]) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => 'demo_mode_enabled'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
@@ -247,6 +295,20 @@ function customize($_action, $_item, $_data = null) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'ip_check':
|
||||||
|
try {
|
||||||
|
$ip_check = ($ip_check = $redis->get('IP_CHECK')) ? $ip_check : 0;
|
||||||
|
return $ip_check;
|
||||||
|
}
|
||||||
|
catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_item, $_data),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $extra_headers = null) {
|
function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $extra_headers = null) {
|
||||||
global $DOCKER_TIMEOUT;
|
global $DOCKER_TIMEOUT;
|
||||||
|
global $redis;
|
||||||
$curl = curl_init();
|
$curl = curl_init();
|
||||||
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: application/json' ));
|
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: application/json' ));
|
||||||
// We are using our mail certificates for dockerapi, the names will not match, the certs are trusted anyway
|
// We are using our mail certificates for dockerapi, the names will not match, the certs are trusted anyway
|
||||||
@@ -32,6 +33,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
break;
|
||||||
case 'containers':
|
case 'containers':
|
||||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json');
|
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json');
|
||||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||||
@@ -51,6 +53,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||||||
if (strtolower($container['Config']['Labels']['com.docker.compose.project']) == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
|
if (strtolower($container['Config']['Labels']['com.docker.compose.project']) == strtolower(getenv('COMPOSE_PROJECT_NAME'))) {
|
||||||
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
|
||||||
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
|
||||||
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['Id'] = trim($container['Id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +97,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||||||
unset($container['Config']['Env']);
|
unset($container['Config']['Env']);
|
||||||
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['State'] = $container['State'];
|
||||||
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['Config'] = $container['Config'];
|
||||||
|
$out[$container['Config']['Labels']['com.docker.compose.service']]['Id'] = trim($container['Id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,6 +107,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||||||
unset($container['Config']['Env']);
|
unset($container['Config']['Env']);
|
||||||
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['State'] = $decoded_response['State'];
|
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['State'] = $decoded_response['State'];
|
||||||
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['Config'] = $decoded_response['Config'];
|
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['Config'] = $decoded_response['Config'];
|
||||||
|
$out[$decoded_response['Config']['Labels']['com.docker.compose.service']]['Id'] = trim($decoded_response['Id']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,5 +151,46 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'container_stats':
|
||||||
|
if (empty($service_name)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$container_id = $service_name;
|
||||||
|
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/container/' . $container_id . '/stats/update');
|
||||||
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($curl, CURLOPT_POST, 1);
|
||||||
|
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||||
|
$response = curl_exec($curl);
|
||||||
|
if ($response === false) {
|
||||||
|
$err = curl_error($curl);
|
||||||
|
curl_close($curl);
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
curl_close($curl);
|
||||||
|
$stats = json_decode($response, true);
|
||||||
|
if (!empty($stats)) return $stats;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case 'host_stats':
|
||||||
|
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/host/stats');
|
||||||
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||||
|
curl_setopt($curl, CURLOPT_POST, 0);
|
||||||
|
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||||
|
$response = curl_exec($curl);
|
||||||
|
if ($response === false) {
|
||||||
|
$err = curl_error($curl);
|
||||||
|
curl_close($curl);
|
||||||
|
return $err;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
curl_close($curl);
|
||||||
|
$stats = json_decode($response, true);
|
||||||
|
if (!empty($stats)) return $stats;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ function password_check($password1, $password2) {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
function last_login($action, $username, $sasl_limit_days = 7) {
|
function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
global $redis;
|
global $redis;
|
||||||
$sasl_limit_days = intval($sasl_limit_days);
|
$sasl_limit_days = intval($sasl_limit_days);
|
||||||
@@ -319,8 +319,11 @@ function last_login($action, $username, $sasl_limit_days = 7) {
|
|||||||
$stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs`
|
$stmt = $pdo->prepare('SELECT `remote`, `time` FROM `logs`
|
||||||
WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
|
WHERE JSON_EXTRACT(`call`, "$[0]") = "check_login"
|
||||||
AND JSON_EXTRACT(`call`, "$[1]") = :username
|
AND JSON_EXTRACT(`call`, "$[1]") = :username
|
||||||
AND `type` = "success" ORDER BY `time` DESC LIMIT 1 OFFSET 1');
|
AND `type` = "success" ORDER BY `time` DESC LIMIT 1 OFFSET :offset');
|
||||||
$stmt->execute(array(':username' => $username));
|
$stmt->execute(array(
|
||||||
|
':username' => $username,
|
||||||
|
':offset' => $ui_offset
|
||||||
|
));
|
||||||
$ui = $stmt->fetch(PDO::FETCH_ASSOC);
|
$ui = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -1020,6 +1020,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
if (empty($name)) {
|
if (empty($name)) {
|
||||||
$name = $local_part;
|
$name = $local_part;
|
||||||
}
|
}
|
||||||
|
if (isset($_data['protocol_access'])) {
|
||||||
|
$_data['protocol_access'] = (array)$_data['protocol_access'];
|
||||||
|
$_data['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$_data['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$_data['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$_data['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
}
|
||||||
$active = intval($_data['active']);
|
$active = intval($_data['active']);
|
||||||
$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
|
$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
|
||||||
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
||||||
@@ -1200,10 +1207,63 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
':domain' => $domain,
|
':domain' => $domain,
|
||||||
':active' => $active
|
':active' => $active
|
||||||
));
|
));
|
||||||
$stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");
|
|
||||||
$stmt->execute(array(
|
|
||||||
':username' => $username
|
if (isset($_data['acl'])) {
|
||||||
));
|
$_data['acl'] = (array)$_data['acl'];
|
||||||
|
$_data['spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||||
|
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `user_acl`
|
||||||
|
(`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`,
|
||||||
|
`pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`)
|
||||||
|
VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset,
|
||||||
|
:pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) ");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':username' => $username,
|
||||||
|
':spam_alias' => $_data['spam_alias'],
|
||||||
|
':tls_policy' => $_data['tls_policy'],
|
||||||
|
':spam_score' => $_data['spam_score'],
|
||||||
|
':spam_policy' => $_data['spam_policy'],
|
||||||
|
':delimiter_action' => $_data['delimiter_action'],
|
||||||
|
':syncjobs' => $_data['syncjobs'],
|
||||||
|
':eas_reset' => $_data['eas_reset'],
|
||||||
|
':sogo_profile_reset' => $_data['sogo_profile_reset'],
|
||||||
|
':pushover' => $_data['pushover'],
|
||||||
|
':quarantine' => $_data['quarantine'],
|
||||||
|
':quarantine_attachments' => $_data['quarantine_attachments'],
|
||||||
|
':quarantine_notification' => $_data['quarantine_notification'],
|
||||||
|
':quarantine_category' => $_data['quarantine_category'],
|
||||||
|
':app_passwds' => $_data['app_passwds']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':username' => $username
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($_data['rl_frame']) && isset($_data['rl_value'])){
|
||||||
|
ratelimit('edit', 'mailbox', array(
|
||||||
|
'object' => $username,
|
||||||
|
'rl_frame' => $_data['rl_frame'],
|
||||||
|
'rl_value' => $_data['rl_value']
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
@@ -1322,6 +1382,190 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
'msg' => array('resource_added', htmlspecialchars($name))
|
'msg' => array('resource_added', htmlspecialchars($name))
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'domain_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (empty($_data["template"])){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'template_name_invalid'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if template name exists, return false
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "domain",
|
||||||
|
":template" => $_data["template"]
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (!empty($row)){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => array('template_exists', $_data["template"])
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check attributes
|
||||||
|
$attr = array();
|
||||||
|
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
|
||||||
|
$attr['max_num_aliases_for_domain'] = (!empty($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 400;
|
||||||
|
$attr['max_num_mboxes_for_domain'] = (!empty($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 10;
|
||||||
|
$attr['def_quota_for_mbox'] = (!empty($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 3072 * 1048576;
|
||||||
|
$attr['max_quota_for_mbox'] = (!empty($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 10240 * 1048576;
|
||||||
|
$attr['max_quota_for_domain'] = (!empty($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 10240 * 1048576;
|
||||||
|
$attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
|
||||||
|
$attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
|
||||||
|
$attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1;
|
||||||
|
$attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1;
|
||||||
|
$attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0;
|
||||||
|
$attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0;
|
||||||
|
$attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0;
|
||||||
|
$attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim";
|
||||||
|
$attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048;
|
||||||
|
|
||||||
|
// save template
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
|
||||||
|
VALUES (:type, :template, :attributes)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "domain",
|
||||||
|
":template" => $_data["template"],
|
||||||
|
":attributes" => json_encode($attr)
|
||||||
|
));
|
||||||
|
|
||||||
|
// success
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('template_added', $_data["template"])
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case 'mailbox_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (empty($_data["template"])){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'template_name_invalid'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if template name exists, return false
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "mailbox",
|
||||||
|
":template" => $_data["template"]
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if (!empty($row)){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => array('template_exists', $_data["template"])
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check attributes
|
||||||
|
$attr = array();
|
||||||
|
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
|
||||||
|
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
|
||||||
|
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
|
||||||
|
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
|
||||||
|
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
|
||||||
|
$attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
|
||||||
|
$attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
|
||||||
|
$attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']);
|
||||||
|
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : 1;
|
||||||
|
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
||||||
|
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
|
||||||
|
if (isset($_data['protocol_access'])) {
|
||||||
|
$_data['protocol_access'] = (array)$_data['protocol_access'];
|
||||||
|
$attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
|
||||||
|
$attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
|
||||||
|
$attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
|
||||||
|
$attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$attr['imap_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
|
||||||
|
$attr['pop3_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
|
||||||
|
$attr['smtp_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
|
||||||
|
$attr['sieve_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['sieve_access']);
|
||||||
|
}
|
||||||
|
if (isset($_data['acl'])) {
|
||||||
|
$_data['acl'] = (array)$_data['acl'];
|
||||||
|
$attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
$_data['acl'] = (array)$_data['acl'];
|
||||||
|
$attr['acl_spam_alias'] = 1;
|
||||||
|
$attr['acl_tls_policy'] = 1;
|
||||||
|
$attr['acl_spam_score'] = 1;
|
||||||
|
$attr['acl_spam_policy'] = 1;
|
||||||
|
$attr['acl_delimiter_action'] = 1;
|
||||||
|
$attr['acl_syncjobs'] = 0;
|
||||||
|
$attr['acl_eas_reset'] = 1;
|
||||||
|
$attr['acl_sogo_profile_reset'] = 0;
|
||||||
|
$attr['acl_pushover'] = 1;
|
||||||
|
$attr['acl_quarantine'] = 1;
|
||||||
|
$attr['acl_quarantine_attachments'] = 1;
|
||||||
|
$attr['acl_quarantine_notification'] = 1;
|
||||||
|
$attr['acl_quarantine_category'] = 1;
|
||||||
|
$attr['acl_app_passwds'] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// save template
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
|
||||||
|
VALUES (:type, :template, :attributes)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "mailbox",
|
||||||
|
":template" => $_data["template"],
|
||||||
|
":attributes" => json_encode($attr)
|
||||||
|
));
|
||||||
|
|
||||||
|
// success
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('template_added', $_data["template"])
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'edit':
|
case 'edit':
|
||||||
@@ -2472,6 +2716,79 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'domain_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_array($_data['ids'])) {
|
||||||
|
$ids = array();
|
||||||
|
$ids[] = $_data['ids'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ids = $_data['ids'];
|
||||||
|
}
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$is_now = mailbox("get", "domain_templates", $id);
|
||||||
|
if (empty($is_now) ||
|
||||||
|
$is_now["type"] != "domain"){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'template_id_invalid'
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check name
|
||||||
|
if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){
|
||||||
|
// keep template name of Default template
|
||||||
|
$_data["template"] = $is_now["template"];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"];
|
||||||
|
}
|
||||||
|
// check attributes
|
||||||
|
$attr = array();
|
||||||
|
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
|
||||||
|
$attr['max_num_aliases_for_domain'] = (isset($_data['max_num_aliases_for_domain'])) ? intval($_data['max_num_aliases_for_domain']) : 0;
|
||||||
|
$attr['max_num_mboxes_for_domain'] = (isset($_data['max_num_mboxes_for_domain'])) ? intval($_data['max_num_mboxes_for_domain']) : 0;
|
||||||
|
$attr['def_quota_for_mbox'] = (isset($_data['def_quota_for_mbox'])) ? intval($_data['def_quota_for_mbox']) * 1048576 : 0;
|
||||||
|
$attr['max_quota_for_mbox'] = (isset($_data['max_quota_for_mbox'])) ? intval($_data['max_quota_for_mbox']) * 1048576 : 0;
|
||||||
|
$attr['max_quota_for_domain'] = (isset($_data['max_quota_for_domain'])) ? intval($_data['max_quota_for_domain']) * 1048576 : 0;
|
||||||
|
$attr['rl_frame'] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
|
||||||
|
$attr['rl_value'] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
|
||||||
|
$attr['active'] = isset($_data['active']) ? intval($_data['active']) : 1;
|
||||||
|
$attr['gal'] = (isset($_data['gal'])) ? intval($_data['gal']) : 1;
|
||||||
|
$attr['backupmx'] = (isset($_data['backupmx'])) ? intval($_data['backupmx']) : 0;
|
||||||
|
$attr['relay_all_recipients'] = (isset($_data['relay_all_recipients'])) ? intval($_data['relay_all_recipients']) : 0;
|
||||||
|
$attr['relay_unknown_only'] = (isset($_data['relay_unknown_only'])) ? intval($_data['relay_unknown_only']) : 0;
|
||||||
|
$attr['dkim_selector'] = (isset($_data['dkim_selector'])) ? $_data['dkim_selector'] : "dkim";
|
||||||
|
$attr['key_size'] = isset($_data['key_size']) ? intval($_data['key_size']) : 2048;
|
||||||
|
|
||||||
|
// update template
|
||||||
|
$stmt = $pdo->prepare("UPDATE `templates`
|
||||||
|
SET `template` = :template, `attributes` = :attributes
|
||||||
|
WHERE id = :id");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $id ,
|
||||||
|
":template" => $_data["template"] ,
|
||||||
|
":attributes" => json_encode($attr)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('template_modified', $_data["template"])
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
case 'mailbox':
|
case 'mailbox':
|
||||||
if (!is_array($_data['username'])) {
|
if (!is_array($_data['username'])) {
|
||||||
$usernames = array();
|
$usernames = array();
|
||||||
@@ -2562,67 +2879,68 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
'msg' => 'access_denied'
|
'msg' => 'extended_sender_acl_denied'
|
||||||
);
|
);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
$extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));
|
else {
|
||||||
foreach ($extra_acls as $i => &$extra_acl) {
|
$extra_acls = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['extended_sender_acl']));
|
||||||
if (empty($extra_acl)) {
|
foreach ($extra_acls as $i => &$extra_acl) {
|
||||||
continue;
|
if (empty($extra_acl)) {
|
||||||
}
|
continue;
|
||||||
if (substr($extra_acl, 0, 1) === "@") {
|
}
|
||||||
$extra_acl = ltrim($extra_acl, '@');
|
if (substr($extra_acl, 0, 1) === "@") {
|
||||||
}
|
$extra_acl = ltrim($extra_acl, '@');
|
||||||
if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {
|
}
|
||||||
$_SESSION['return'][] = array(
|
if (!filter_var($extra_acl, FILTER_VALIDATE_EMAIL) && !is_valid_domain_name($extra_acl)) {
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
|
||||||
'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))
|
|
||||||
);
|
|
||||||
unset($extra_acls[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
|
|
||||||
if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {
|
|
||||||
$extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
|
|
||||||
if (in_array($extra_acl_domain, $domains)) {
|
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
|
'msg' => array('extra_acl_invalid', htmlspecialchars($extra_acl))
|
||||||
);
|
);
|
||||||
unset($extra_acls[$i]);
|
unset($extra_acls[$i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
$domains = array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains'));
|
||||||
else {
|
if (filter_var($extra_acl, FILTER_VALIDATE_EMAIL)) {
|
||||||
if (in_array($extra_acl, $domains)) {
|
$extra_acl_domain = idn_to_ascii(substr(strstr($extra_acl, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
|
||||||
$_SESSION['return'][] = array(
|
if (in_array($extra_acl_domain, $domains)) {
|
||||||
'type' => 'danger',
|
$_SESSION['return'][] = array(
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'type' => 'danger',
|
||||||
'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
);
|
'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
|
||||||
unset($extra_acls[$i]);
|
);
|
||||||
continue;
|
unset($extra_acls[$i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (in_array($extra_acl, $domains)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('extra_acl_invalid_domain', $extra_acl_domain)
|
||||||
|
);
|
||||||
|
unset($extra_acls[$i]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$extra_acl = '@' . $extra_acl;
|
||||||
}
|
}
|
||||||
$extra_acl = '@' . $extra_acl;
|
|
||||||
}
|
}
|
||||||
}
|
$extra_acls = array_filter($extra_acls);
|
||||||
$extra_acls = array_filter($extra_acls);
|
$extra_acls = array_values($extra_acls);
|
||||||
$extra_acls = array_values($extra_acls);
|
$extra_acls = array_unique($extra_acls);
|
||||||
$extra_acls = array_unique($extra_acls);
|
$stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");
|
||||||
$stmt = $pdo->prepare("DELETE FROM `sender_acl` WHERE `external` = 1 AND `logged_in_as` = :username");
|
|
||||||
$stmt->execute(array(
|
|
||||||
':username' => $username
|
|
||||||
));
|
|
||||||
foreach ($extra_acls as $sender_acl_external) {
|
|
||||||
$stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)
|
|
||||||
VALUES (:sender_acl, :username, 1)");
|
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
':sender_acl' => $sender_acl_external,
|
|
||||||
':username' => $username
|
':username' => $username
|
||||||
));
|
));
|
||||||
|
foreach ($extra_acls as $sender_acl_external) {
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `sender_acl` (`send_as`, `logged_in_as`, `external`)
|
||||||
|
VALUES (:sender_acl, :username, 1)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
':sender_acl' => $sender_acl_external,
|
||||||
|
':username' => $username
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isset($_data['sender_acl'])) {
|
if (isset($_data['sender_acl'])) {
|
||||||
@@ -2814,6 +3132,110 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'mailbox_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_array($_data['ids'])) {
|
||||||
|
$ids = array();
|
||||||
|
$ids[] = $_data['ids'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ids = $_data['ids'];
|
||||||
|
}
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
$is_now = mailbox("get", "mailbox_templates", $id);
|
||||||
|
if (empty($is_now) ||
|
||||||
|
$is_now["type"] != "mailbox"){
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
|
||||||
|
'msg' => 'template_id_invalid'
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check name
|
||||||
|
if ($is_now["template"] == "Default" && $is_now["template"] != $_data["template"]){
|
||||||
|
// keep template name of Default template
|
||||||
|
$_data["template"] = $is_now["template"];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$_data["template"] = (isset($_data["template"])) ? $_data["template"] : $is_now["template"];
|
||||||
|
}
|
||||||
|
// check attributes
|
||||||
|
$attr = array();
|
||||||
|
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
|
||||||
|
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags'];
|
||||||
|
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
|
||||||
|
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
|
||||||
|
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];
|
||||||
|
$attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value'];
|
||||||
|
$attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update'];
|
||||||
|
$attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access'];
|
||||||
|
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active'];
|
||||||
|
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
|
||||||
|
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
|
||||||
|
if (isset($_data['protocol_access'])) {
|
||||||
|
$_data['protocol_access'] = (array)$_data['protocol_access'];
|
||||||
|
$attr['imap_access'] = (in_array('imap', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$attr['pop3_access'] = (in_array('pop3', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$attr['smtp_access'] = (in_array('smtp', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
$attr['sieve_access'] = (in_array('sieve', $_data['protocol_access'])) ? 1 : 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
foreach ($is_now as $key => $value){
|
||||||
|
$attr[$key] = $is_now[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isset($_data['acl'])) {
|
||||||
|
$_data['acl'] = (array)$_data['acl'];
|
||||||
|
$attr['acl_spam_alias'] = (in_array('spam_alias', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_tls_policy'] = (in_array('tls_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_spam_score'] = (in_array('spam_score', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_spam_policy'] = (in_array('spam_policy', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_delimiter_action'] = (in_array('delimiter_action', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_notification'] = (in_array('quarantine_notification', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_quarantine_category'] = (in_array('quarantine_category', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0;
|
||||||
|
} else {
|
||||||
|
foreach ($is_now as $key => $value){
|
||||||
|
$attr[$key] = $is_now[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// update template
|
||||||
|
$stmt = $pdo->prepare("UPDATE `templates`
|
||||||
|
SET `template` = :template, `attributes` = :attributes
|
||||||
|
WHERE id = :id");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $id ,
|
||||||
|
":template" => $_data["template"] ,
|
||||||
|
":attributes" => json_encode($attr)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('template_modified', $_data["template"])
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
case 'resource':
|
case 'resource':
|
||||||
if (!is_array($_data['name'])) {
|
if (!is_array($_data['name'])) {
|
||||||
$names = array();
|
$names = array();
|
||||||
@@ -3606,6 +4028,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
`mailboxes`,
|
`mailboxes`,
|
||||||
`defquota`,
|
`defquota`,
|
||||||
`maxquota`,
|
`maxquota`,
|
||||||
|
`created`,
|
||||||
|
`modified`,
|
||||||
`quota`,
|
`quota`,
|
||||||
`relayhost`,
|
`relayhost`,
|
||||||
`relay_all_recipients`,
|
`relay_all_recipients`,
|
||||||
@@ -3678,6 +4102,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$domaindata['relay_all_recipients_int'] = $row['relay_all_recipients'];
|
$domaindata['relay_all_recipients_int'] = $row['relay_all_recipients'];
|
||||||
$domaindata['relay_unknown_only'] = $row['relay_unknown_only'];
|
$domaindata['relay_unknown_only'] = $row['relay_unknown_only'];
|
||||||
$domaindata['relay_unknown_only_int'] = $row['relay_unknown_only'];
|
$domaindata['relay_unknown_only_int'] = $row['relay_unknown_only'];
|
||||||
|
$domaindata['created'] = $row['created'];
|
||||||
|
$domaindata['modified'] = $row['modified'];
|
||||||
$stmt = $pdo->prepare("SELECT COUNT(`address`) AS `alias_count` FROM `alias`
|
$stmt = $pdo->prepare("SELECT COUNT(`address`) AS `alias_count` FROM `alias`
|
||||||
WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2))
|
WHERE (`domain`= :domain OR `domain` IN (SELECT `alias_domain` FROM `alias_domain` WHERE `target_domain` = :domain2))
|
||||||
AND `address` NOT IN (
|
AND `address` NOT IN (
|
||||||
@@ -3711,6 +4137,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
|
|
||||||
return $domaindata;
|
return $domaindata;
|
||||||
break;
|
break;
|
||||||
|
case 'domain_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_data = (isset($_data)) ? intval($_data) : null;
|
||||||
|
|
||||||
|
if (isset($_data)){
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM `templates`
|
||||||
|
WHERE `id` = :id AND type = :type");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $_data,
|
||||||
|
":type" => "domain"
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (empty($row)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row["attributes"] = json_decode($row["attributes"], true);
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'domain'");
|
||||||
|
$stmt->execute();
|
||||||
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (empty($rows)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($rows as $key => $row){
|
||||||
|
$rows[$key]["attributes"] = json_decode($row["attributes"], true);
|
||||||
|
}
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'mailbox_details':
|
case 'mailbox_details':
|
||||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -3725,6 +4188,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
`mailbox`.`domain`,
|
`mailbox`.`domain`,
|
||||||
`mailbox`.`local_part`,
|
`mailbox`.`local_part`,
|
||||||
`mailbox`.`quota`,
|
`mailbox`.`quota`,
|
||||||
|
`mailbox`.`created`,
|
||||||
|
`mailbox`.`modified`,
|
||||||
`quota2`.`bytes`,
|
`quota2`.`bytes`,
|
||||||
`attributes`,
|
`attributes`,
|
||||||
`quota2`.`messages`
|
`quota2`.`messages`
|
||||||
@@ -3743,6 +4208,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
`mailbox`.`domain`,
|
`mailbox`.`domain`,
|
||||||
`mailbox`.`local_part`,
|
`mailbox`.`local_part`,
|
||||||
`mailbox`.`quota`,
|
`mailbox`.`quota`,
|
||||||
|
`mailbox`.`created`,
|
||||||
|
`mailbox`.`modified`,
|
||||||
`quota2replica`.`bytes`,
|
`quota2replica`.`bytes`,
|
||||||
`attributes`,
|
`attributes`,
|
||||||
`quota2replica`.`messages`
|
`quota2replica`.`messages`
|
||||||
@@ -3769,6 +4236,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$mailboxdata['attributes'] = json_decode($row['attributes'], true);
|
$mailboxdata['attributes'] = json_decode($row['attributes'], true);
|
||||||
$mailboxdata['quota_used'] = intval($row['bytes']);
|
$mailboxdata['quota_used'] = intval($row['bytes']);
|
||||||
$mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
|
$mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100);
|
||||||
|
$mailboxdata['created'] = $row['created'];
|
||||||
|
$mailboxdata['modified'] = $row['modified'];
|
||||||
|
|
||||||
if ($mailboxdata['percent_in_use'] === '- ') {
|
if ($mailboxdata['percent_in_use'] === '- ') {
|
||||||
$mailboxdata['percent_class'] = "info";
|
$mailboxdata['percent_class'] = "info";
|
||||||
@@ -3856,6 +4325,43 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
|
|
||||||
return $mailboxdata;
|
return $mailboxdata;
|
||||||
break;
|
break;
|
||||||
|
case 'mailbox_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin" && $_SESSION['mailcow_cc_role'] != "domainadmin") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$_data = (isset($_data)) ? intval($_data) : null;
|
||||||
|
|
||||||
|
if (isset($_data)){
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM `templates`
|
||||||
|
WHERE `id` = :id AND type = :type");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $_data,
|
||||||
|
":type" => "mailbox"
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (empty($row)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row["attributes"] = json_decode($row["attributes"], true);
|
||||||
|
return $row;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$stmt = $pdo->prepare("SELECT * FROM `templates` WHERE `type` = 'mailbox'");
|
||||||
|
$stmt->execute();
|
||||||
|
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
if (empty($rows)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($rows as $key => $row){
|
||||||
|
$rows[$key]["attributes"] = json_decode($row["attributes"], true);
|
||||||
|
}
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'resource_details':
|
case 'resource_details':
|
||||||
$resourcedata = array();
|
$resourcedata = array();
|
||||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
||||||
@@ -4224,6 +4730,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'domain_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_array($_data['ids'])) {
|
||||||
|
$ids = array();
|
||||||
|
$ids[] = $_data['ids'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ids = $_data['ids'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
// delete template
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM `templates`
|
||||||
|
WHERE id = :id AND type = :type AND NOT template = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $id,
|
||||||
|
":type" => "domain",
|
||||||
|
":template" => "Default"
|
||||||
|
));
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => array('template_removed', htmlspecialchars($id))
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'alias':
|
case 'alias':
|
||||||
if (!is_array($_data['id'])) {
|
if (!is_array($_data['id'])) {
|
||||||
$ids = array();
|
$ids = array();
|
||||||
@@ -4518,6 +5060,42 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'mailbox_templates':
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_array($_data['ids'])) {
|
||||||
|
$ids = array();
|
||||||
|
$ids[] = $_data['ids'];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ids = $_data['ids'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($ids as $id) {
|
||||||
|
// delete template
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM `templates`
|
||||||
|
WHERE id = :id AND type = :type AND NOT template = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":id" => $id,
|
||||||
|
":type" => "mailbox",
|
||||||
|
":template" => "Default"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => 'template_removed'
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
case 'resource':
|
case 'resource':
|
||||||
if (!is_array($_data['name'])) {
|
if (!is_array($_data['name'])) {
|
||||||
$names = array();
|
$names = array();
|
||||||
@@ -4593,15 +5171,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$tags = $_data['tags'];
|
$tags = $_data['tags'];
|
||||||
if (!is_array($tags)) $tags = array();
|
if (!is_array($tags)) $tags = array();
|
||||||
|
|
||||||
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
|
||||||
'msg' => 'access_denied'
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$wasModified = false;
|
$wasModified = false;
|
||||||
foreach ($domains as $domain) {
|
foreach ($domains as $domain) {
|
||||||
@@ -4613,7 +5182,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
foreach($tags as $tag){
|
foreach($tags as $tag){
|
||||||
// delete tag
|
// delete tag
|
||||||
$wasModified = true;
|
$wasModified = true;
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ $globalVariables = [
|
|||||||
'dual_login' => @$_SESSION['dual-login'],
|
'dual_login' => @$_SESSION['dual-login'],
|
||||||
'ui_texts' => $UI_TEXTS,
|
'ui_texts' => $UI_TEXTS,
|
||||||
'css_path' => '/cache/'.basename($CSSPath),
|
'css_path' => '/cache/'.basename($CSSPath),
|
||||||
'theme' => strtolower(trim($DEFAULT_THEME)),
|
|
||||||
'logo' => customize('get', 'main_logo'),
|
'logo' => customize('get', 'main_logo'),
|
||||||
'available_languages' => $AVAILABLE_LANGUAGES,
|
'available_languages' => $AVAILABLE_LANGUAGES,
|
||||||
'lang' => $lang,
|
'lang' => $lang,
|
||||||
@@ -49,6 +48,7 @@ $globalVariables = [
|
|||||||
'app_links' => customize('get', 'app_links'),
|
'app_links' => customize('get', 'app_links'),
|
||||||
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
|
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
|
||||||
'uri' => $_SERVER['REQUEST_URI'],
|
'uri' => $_SERVER['REQUEST_URI'],
|
||||||
|
'last_login' => last_login('get', $_SESSION['mailcow_cc_username'], 7, 0)['ui']['time']
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($globalVariables as $globalVariableName => $globalVariableValue) {
|
foreach ($globalVariables as $globalVariableName => $globalVariableValue) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ function init_db_schema() {
|
|||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "17112022_2115";
|
$db_version = "23122022_1445";
|
||||||
|
|
||||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
@@ -225,6 +225,22 @@ function init_db_schema() {
|
|||||||
),
|
),
|
||||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||||
),
|
),
|
||||||
|
"templates" => array(
|
||||||
|
"cols" => array(
|
||||||
|
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||||
|
"template" => "VARCHAR(255) NOT NULL",
|
||||||
|
"type" => "VARCHAR(255) NOT NULL",
|
||||||
|
"attributes" => "JSON",
|
||||||
|
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||||
|
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP"
|
||||||
|
),
|
||||||
|
"keys" => array(
|
||||||
|
"primary" => array(
|
||||||
|
"" => array("id")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||||
|
),
|
||||||
"domain" => array(
|
"domain" => array(
|
||||||
// Todo: Move some attributes to json
|
// Todo: Move some attributes to json
|
||||||
"cols" => array(
|
"cols" => array(
|
||||||
@@ -1293,6 +1309,95 @@ function init_db_schema() {
|
|||||||
// Fix domain_admins
|
// Fix domain_admins
|
||||||
$pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
|
$pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
|
||||||
|
|
||||||
|
// add default templates
|
||||||
|
$default_domain_template = array(
|
||||||
|
"template" => "Default",
|
||||||
|
"type" => "domain",
|
||||||
|
"attributes" => array(
|
||||||
|
"tags" => array(),
|
||||||
|
"max_num_aliases_for_domain" => 400,
|
||||||
|
"max_num_mboxes_for_domain" => 10,
|
||||||
|
"def_quota_for_mbox" => 3072 * 1048576,
|
||||||
|
"max_quota_for_mbox" => 10240 * 1048576,
|
||||||
|
"max_quota_for_domain" => 10240 * 1048576,
|
||||||
|
"rl_frame" => "s",
|
||||||
|
"rl_value" => "",
|
||||||
|
"active" => 1,
|
||||||
|
"gal" => 1,
|
||||||
|
"backupmx" => 0,
|
||||||
|
"relay_all_recipients" => 0,
|
||||||
|
"relay_unknown_only" => 0,
|
||||||
|
"dkim_selector" => "dkim",
|
||||||
|
"key_size" => 2048,
|
||||||
|
"max_quota_for_domain" => 10240 * 1048576,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$default_mailbox_template = array(
|
||||||
|
"template" => "Default",
|
||||||
|
"type" => "mailbox",
|
||||||
|
"attributes" => array(
|
||||||
|
"tags" => array(),
|
||||||
|
"quota" => 0,
|
||||||
|
"quarantine_notification" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_notification']),
|
||||||
|
"quarantine_category" => strval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['quarantine_category']),
|
||||||
|
"rl_frame" => "s",
|
||||||
|
"rl_value" => "",
|
||||||
|
"force_pw_update" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_pw_update']),
|
||||||
|
"sogo_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sogo_access']),
|
||||||
|
"active" => 1,
|
||||||
|
"tls_enforce_in" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_in']),
|
||||||
|
"tls_enforce_out" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_out']),
|
||||||
|
"imap_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['imap_access']),
|
||||||
|
"pop3_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['pop3_access']),
|
||||||
|
"smtp_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['smtp_access']),
|
||||||
|
"sieve_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sieve_access']),
|
||||||
|
"acl_spam_alias" => 1,
|
||||||
|
"acl_tls_policy" => 1,
|
||||||
|
"acl_spam_score" => 1,
|
||||||
|
"acl_spam_policy" => 1,
|
||||||
|
"acl_delimiter_action" => 1,
|
||||||
|
"acl_syncjobs" => 0,
|
||||||
|
"acl_eas_reset" => 1,
|
||||||
|
"acl_sogo_profile_reset" => 0,
|
||||||
|
"acl_pushover" => 1,
|
||||||
|
"acl_quarantine" => 1,
|
||||||
|
"acl_quarantine_attachments" => 1,
|
||||||
|
"acl_quarantine_notification" => 1,
|
||||||
|
"acl_quarantine_category" => 1,
|
||||||
|
"acl_app_passwds" => 1,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "domain",
|
||||||
|
":template" => $default_domain_template["template"]
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if (empty($row)){
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
|
||||||
|
VALUES (:type, :template, :attributes)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "domain",
|
||||||
|
":template" => $default_domain_template["template"],
|
||||||
|
":attributes" => json_encode($default_domain_template["attributes"])
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$stmt = $pdo->prepare("SELECT id FROM `templates` WHERE `type` = :type AND `template` = :template");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "mailbox",
|
||||||
|
":template" => $default_mailbox_template["template"]
|
||||||
|
));
|
||||||
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if (empty($row)){
|
||||||
|
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
|
||||||
|
VALUES (:type, :template, :attributes)");
|
||||||
|
$stmt->execute(array(
|
||||||
|
":type" => "mailbox",
|
||||||
|
":template" => $default_mailbox_template["template"],
|
||||||
|
":attributes" => json_encode($default_mailbox_template["attributes"])
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if (php_sapi_name() == "cli") {
|
if (php_sapi_name() == "cli") {
|
||||||
echo "DB initialization completed" . PHP_EOL;
|
echo "DB initialization completed" . PHP_EOL;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
// check for development mode
|
// check for development mode
|
||||||
$DEV_MODE = (getenv('DEV_MODE') == 'y');
|
$DEV_MODE = (getenv('DEV_MODE') == 'y');
|
||||||
|
// check for demo mode
|
||||||
|
$DEMO_MODE = (getenv('DEMO_MODE') == 'y');
|
||||||
|
|
||||||
// Slave does not serve UI
|
// Slave does not serve UI
|
||||||
/* if (!preg_match('/y|yes/i', getenv('MASTER'))) {
|
/* if (!preg_match('/y|yes/i', getenv('MASTER'))) {
|
||||||
@@ -44,21 +46,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/CSSminifierExtended.php';
|
|||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/array_merge_real.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/array_merge_real.php';
|
||||||
|
|
||||||
// Minify JS
|
|
||||||
use MatthiasMullie\Minify;
|
|
||||||
$js_minifier = new JSminifierExtended();
|
|
||||||
$js_dir = array_diff(scandir('/web/js/build'), array('..', '.'));
|
|
||||||
foreach ($js_dir as $js_file) {
|
|
||||||
$js_minifier->add('/web/js/build/' . $js_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Minify CSS
|
|
||||||
$css_minifier = new CSSminifierExtended();
|
|
||||||
$css_dir = array_diff(scandir('/web/css/build'), array('..', '.'));
|
|
||||||
foreach ($css_dir as $css_file) {
|
|
||||||
$css_minifier->add('/web/css/build/' . $css_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// U2F API + T/HOTP API
|
// U2F API + T/HOTP API
|
||||||
// u2f - deprecated, should be removed
|
// u2f - deprecated, should be removed
|
||||||
$u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
|
$u2f = new u2flib_server\U2F('https://' . $_SERVER['HTTP_HOST']);
|
||||||
@@ -247,7 +234,7 @@ if (!isset($_SESSION['mailcow_locale']) && !isset($_COOKIE['mailcow_locale'])) {
|
|||||||
|
|
||||||
// Try suggest match
|
// Try suggest match
|
||||||
// e.g. suggest en-gb when only en-us is provided
|
// e.g. suggest en-gb when only en-us is provided
|
||||||
if (!isset($_COOKIE['mailcow_locale'])) {
|
if (!isset($_SESSION['mailcow_locale'])) {
|
||||||
foreach ($lang2pref as $lang => $q) {
|
foreach ($lang2pref as $lang => $q) {
|
||||||
if (array_key_exists(substr($lang, 0, 2), $AVAILABLE_BASE_LANGUAGES)) {
|
if (array_key_exists(substr($lang, 0, 2), $AVAILABLE_BASE_LANGUAGES)) {
|
||||||
$_SESSION['mailcow_locale'] = $AVAILABLE_BASE_LANGUAGES[substr($lang, 0, 2)];
|
$_SESSION['mailcow_locale'] = $AVAILABLE_BASE_LANGUAGES[substr($lang, 0, 2)];
|
||||||
@@ -278,6 +265,7 @@ if(file_exists($langFile)) {
|
|||||||
$lang = array_merge_real($lang, json_decode(file_get_contents($langFile), true));
|
$lang = array_merge_real($lang, json_decode(file_get_contents($langFile), true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.admin.inc.php';
|
||||||
@@ -312,4 +300,29 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||||||
// }
|
// }
|
||||||
acl('to_session');
|
acl('to_session');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init frontend
|
||||||
|
// Minify JS
|
||||||
|
use MatthiasMullie\Minify;
|
||||||
|
$js_minifier = new JSminifierExtended();
|
||||||
|
$js_dir = array_diff(scandir('/web/js/build'), array('..', '.'));
|
||||||
|
// Minify CSS
|
||||||
|
$css_minifier = new CSSminifierExtended();
|
||||||
|
$css_dir = array_diff(scandir('/web/css/build'), array('..', '.'));
|
||||||
|
// get customized ui data
|
||||||
$UI_TEXTS = customize('get', 'ui_texts');
|
$UI_TEXTS = customize('get', 'ui_texts');
|
||||||
|
|
||||||
|
|
||||||
|
// minify bootstrap theme
|
||||||
|
if (file_exists('/web/css/themes/'.$UI_THEME.'-bootstrap.css'))
|
||||||
|
$css_minifier->add('/web/css/themes/'.$UI_THEME.'-bootstrap.css');
|
||||||
|
else
|
||||||
|
$css_minifier->add('/web/css/themes/lumen-bootstrap.css');
|
||||||
|
// minify css build files
|
||||||
|
foreach ($css_dir as $css_file) {
|
||||||
|
$css_minifier->add('/web/css/build/' . $css_file);
|
||||||
|
}
|
||||||
|
// minify js build files
|
||||||
|
foreach ($js_dir as $js_file) {
|
||||||
|
$js_minifier->add('/web/js/build/' . $js_file);
|
||||||
|
}
|
||||||
@@ -107,12 +107,10 @@ $AVAILABLE_LANGUAGES = array(
|
|||||||
'zh-tw' => '繁體中文 (Traditional Chinese)',
|
'zh-tw' => '繁體中文 (Traditional Chinese)',
|
||||||
);
|
);
|
||||||
|
|
||||||
// Change theme (default: lumen)
|
// default theme is lumen
|
||||||
// Needs to be one of those: cerulean, cosmo, cyborg, darkly, flatly, journal, lumen, paper, readable, sandstone,
|
// additional themes can be found here: https://bootswatch.com/
|
||||||
// simplex, slate, spacelab, superhero, united, yeti
|
// copy them to data/web/css/themes/{THEME-NAME}-bootstrap.css
|
||||||
// See https://bootswatch.com/
|
$UI_THEME = "lumen";
|
||||||
// WARNING: Only lumen is loaded locally. Enabling any other theme, will download external sources.
|
|
||||||
$DEFAULT_THEME = 'lumen';
|
|
||||||
|
|
||||||
// Show DKIM private keys - false by default
|
// Show DKIM private keys - false by default
|
||||||
$SHOW_DKIM_PRIV_KEYS = false;
|
$SHOW_DKIM_PRIV_KEYS = false;
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ if (isset($_SESSION['mailcow_cc_role']) && isset($_SESSION['oauth2_request'])) {
|
|||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||||
header('Location: /admin');
|
header('Location: /debug');
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||||
|
|||||||
+2
@@ -0,0 +1,2 @@
|
|||||||
|
/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
||||||
|
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),j=function(e,t){return e===t&&(l=!0),0},D={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^Line truncated
|
||||||
Vendored
-4
@@ -1,4 +0,0 @@
|
|||||||
/*! jQuery v3.4.1 | (c) JS Foundation and other contributors | jquery.org/license */
|
|
||||||
!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],E=C.document,r=Object.getPrototypeOf,s=t.slice,g=t.concat,u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.4.1",k=function(e,t){return new k.fn.init(e,t)},p=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;function d(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}k.fn=k.prototype={jquery:f,constructor:k,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=k.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return k.each(this,e)},map:function(n){return this.pushStack(k.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},k.extend=k.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(k.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||k.isPlainObject(n)?n:{},i=!1,a[t]=k.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},k.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t){b(e,{nonce:t&&t.nonce})},each:function(e,t){var n,r=0;if(d(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},trim:function(e){return null==e?"":(e+"").replace(p,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(d(Object(e))?k.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(d(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g.apply([],a)},guid:1,support:y}),"function"==typeof Symbol&&(k.fn[Symbol.iterator]=t[Symbol.iterator]),k.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var h=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,k="sizzle"+1*new Date,m=n.document,S=0,r=0,p=ue(),x=ue(),N=ue(),A=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\.|[\\w-]|[^\0-\\xa0])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",$=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",F=new RegExp(M+"+","g"),B=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp($),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+$),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+Line truncated
|
|
||||||
/*! jQuery Migrate v3.1.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */
|
|
||||||
"undefined"==typeof jQuery.migrateMute&&(jQuery.migrateMute=!0),function(t){"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e,window)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery"),window):t(jQuery,window)}(function(s,n){"use strict";function e(e){return 0<=function(e,t){for(var r=/^(\d+)\.(\d+)\.(\d+)/,n=r.exec(e)||[],o=r.exec(t)||[],i=1;i<=3;i++){if(+n[i]>+o[i])return 1;if(+n[i]<+o[i])return-1}return 0}(s.fn.jquery,e)}s.migrateVersion="3.1.0",n.console&&n.console.log&&(s&&e("3.0.0")||n.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED"),s.migrateWarnings&&n.console.log("JQMIGRATE: Migrate plugin loaded multiple times"),n.console.log("JQMIGRATE: Migrate is installed"+(s.migrateMute?"":" with logging active")+", version "+s.migrateVersion));var r={};function u(e){var t=n.console;r[e]||(r[e]=!0,s.migrateWarnings.push(e),t&&t.warn&&!s.migrateMute&&(t.warn("JQMIGRATE: "+e),s.migrateTrace&&t.trace&&t.trace()))}function t(e,t,r,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!0,get:function(){return u(n),r},set:function(e){u(n),r=e}})}function o(e,t,r,n){e[t]=function(){return u(n),r.apply(this,arguments)}}s.migrateWarnings=[],void 0===s.migrateTrace&&(s.migrateTrace=!0),s.migrateReset=function(){r={},s.migrateWarnings.length=0},"BackCompat"===n.document.compatMode&&u("jQuery is not compatible with Quirks Mode");var i,a=s.fn.init,c=s.isNumeric,d=s.find,l=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,p=/\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;for(i in s.fn.init=function(e){var t=Array.prototype.slice.call(arguments);return"string"==typeof e&&"#"===e&&(u("jQuery( '#' ) is not a valid selector"),t[0]=[]),a.apply(this,t)},s.fn.init.prototype=s.fn,s.find=function(t){var r=Array.prototype.slice.call(arguments);if("string"==typeof t&&l.test(t))try{n.document.querySelector(t)}catch(e){t=t.replace(p,function(e,t,r,n){return"["+t+r+'"'+n+'"]'});try{n.document.querySelector(t),u("Attribute selector with '#' must be quoted: "+r[0]),r[0]=t}catch(e){u("Attribute selector with '#' was not fixed: "+r[0])}}return d.apply(this,r)},d)Object.prototype.hasOwnProperty.call(d,i)&&(s.find[i]=d[i]);s.fn.size=function(){return u("jQuery.fn.size() is deprecated and removed; use the .length property"),this.length},s.parseJSON=function(){return u("jQuery.parseJSON is deprecated; use JSON.parse"),JSON.parse.apply(null,arguments)},s.isNumeric=function(e){var t,r,n=c(e),o=(r=(t=e)&&t.toString(),!s.isArray(t)&&0<=r-parseFloat(r)+1);return n!==o&&u("jQuery.isNumeric() should not be called on constructed objects"),o},e("3.3.0")&&o(s,"isWindow",function(e){return null!=e&&e===e.window},"jQuery.isWindow() is deprecated"),o(s,"holdReady",s.holdReady,"jQuery.holdReady is deprecated"),o(s,"unique",s.uniqueSort,"jQuery.unique is deprecated; use jQuery.uniqueSort"),t(s.expr,"filters",s.expr.pseudos,"jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"),t(s.expr,":",s.expr.pseudos,"jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos"),e("3.2.0")&&o(s,"nodeName",s.nodeName,"jQuery.nodeName is deprecated");var f=s.ajax;s.ajax=function(){var e=f.apply(this,arguments);return e.promise&&(o(e,"success",e.done,"jQXHR.success is deprecated and removed"),o(e,"error",e.fail,"jQXHR.error is deprecated and removed"),o(e,"complete",e.always,"jQXHR.complete is deprecated and removed")),e};var y=s.fn.removeAttr,m=s.fn.toggleClass,h=/\S+/g;s.fn.removeAttr=function(e){var r=this;return s.each(e.match(h),function(e,t){s.expr.match.bool.test(t)&&(u("jQuery.fn.removeAttr no longer sets boolean properties: "+t),r.prop(t,!1))}),y.apply(this,arguments)};var g=!(s.fn.toggleClass=function(t){return void 0!==t&&"boolean"!=typeof t?m.apply(this,arguments):(u("jQuery.fn.toggleClass( boolean ) is deprecated"),this.each(function(){var e=this.getAttribute&&this.getAttribute("class")||"";e&&s.data(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===t?"":s.data(this,"__className__")||"")}))});s.swap&&s.each(["height","width","reliableMarginRight"],function(e,t){var r=s.cssHooks[t]&&s.cssHooks[t].get;r&&(s.cssHooks[t].get=function(){var e;return g=!0,e=r.apply(this,arguments),g=!1,e})}),s.swap=function(e,t,r,n){var o,i,a={};for(i in g||u("jQuery.swap() is undocumented and deprecated"),t)a[i]=e.style[i],e.style[i]=t[i];for(i in o=r.apply(e,n||[]),t)e.style[i]=a[i];return o};var v=s.data;s.data=function(e,t,r){var n;if(t&&"object"==typeof t&&2===arguments.length){n=s.hasData(e)&&v.call(this,e);var o={};for(var i in t)i!==s.camelCase(i)?(u("jQuery.data() always sets/gets camelCased names: "+i),n[i]=t[i]):o[i]=t[i];return v.call(this,e,o),t}return t&&"string"==typeof t&&t!==s.camelCase(t)&&(n=s.hasData(e)&&v.call(this,e))&&t in n?(u("jQuery.data() always sets/gets camelCased names: "+t),2<arguments.length&&(n[t]=r),n[t]):v.apply(this,arguments)};function j(e){return e}var Q=s.Tween.prototype.run;s.Tween.prototype.run=function(){1<s.easing[this.easing].length&&(u("'jLine truncated
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/*!
|
||||||
|
* Bootstrap v5.1.3 (https://getbootstrap.com/)
|
||||||
|
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||||
|
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||||
|
*/
|
||||||
|
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=(t,e,i)=>{Object.keys(i).forEach((n=>{const s=i[n],r=e[n],a=r&&o(r)?"element":null==(l=r)?`${l}`:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(s).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}))},l=t=>!(!o(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",(()=>{p.forEach((t=>t()))})),p.push(e)):e()},_=t=>{"function"==typeof t&&t()},b=(e,i,n=!0)=>{if(!n)return void _(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),_(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},v=(t,e,i,n)=>{let s=t.indexOf(e);if(-1===s)return t[!i&&n?t.length-1:0];const o=t.length;return s+=i?1:-1,n&&(s=(s+o)%o),t[Math.max(0,Math.min(s,o-1))]},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,E=/::\d+$/,A={};let T=1;const O={mouseenter:"mouseover",mouseleave:"mouseout"},C=/^(mouseenter|mouseleave)/i,k=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function L(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function x(t){const e=L(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function D(t,e,i=null){const n=Object.keys(t);for(let s=0,o=n.length;s<o;s++){const o=t[n[s]];if(o.originalHandler===e&&o.delegationSelector===i)return o}return null}function S(t,e,i){const n="string"==typeof e,s=n?i:e;let o=P(t);return k.has(o)||(o=t),[n,s,o]}function N(t,e,i,n,s){if("string"!=typeof e||!t)return;if(i||(i=n,n=null),C.test(e)){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};n?n=t(n):i=t(i)}const[o,r,a]=S(e,i,n),l=x(t),c=l[a]||(l[a]={}),h=D(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=L(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return s.delegateTarget=r,n.oneOff&&j.off(t,s.type,e,i),i.apply(r,[s]);return null}}(t,i,n):function(t,e){return function i(n){return n.delegateTarget=t,i.oneOff&&j.off(t,n.type,e),e.apply(t,[n])}}(t,i);u.delegationSelector=o?i:null,u.originalHandler=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function I(t,e,i,n,s){const o=D(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function P(t){return t=t.replace(w,""),O[t]||t}const j={on(t,e,i,n){N(t,e,i,n,!1)},one(t,e,i,n){N(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=x(t),c=e.startsWith(".");if(void 0!==o){if(!Line truncated
|
||||||
|
//# sourceMappingURL=bootstrap.bundle.min.js.map
|
||||||
-7
@@ -1,7 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap v3.3.7 (http://getbootstrap.com)
|
|
||||||
* Copyright 2011-2016 Twitter, Inc.
|
|
||||||
* Licensed under the MIT license
|
|
||||||
*/
|
|
||||||
if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){"use strict";var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>3)throw new Error("Bootstrap's JavaScript requires jQuery version 1.9.1 or higher, but lower than version 4")}(jQuery),+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]};return!1}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one("bsTransitionEnd",function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b(),a.support.transition&&(a.event.special.bsTransitionEnd={bindType:a.support.transition.end,delegateType:a.support.transition.end,handle:function(b){if(a(b.target).is(this))return b.handleObj.handler.apply(this,arguments)}})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var c=a(this),e=c.data("bs.alert");e||c.data("bs.alert",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var c='[data-dismiss="alert"]',d=function(b){a(b).on("click",c,this.close)};d.VERSION="3.3.7",d.TRANSITION_DURATION=150,d.prototype.close=function(b){function c(){g.detach().trigger("closed.bs.alert").remove()}var e=a(this),f=e.attr("data-target");f||(f=e.attr("href"),f=f&&f.replace(/.*(?=#[^\s]*$)/,""));var g=a("#"===f?[]:f);b&&b.preventDefault(),g.length||(g=e.closest(".alert")),g.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(g.removeClass("in"),a.support.transition&&g.hasClass("fade")?g.one("bsTransitionEnd",c).emulateTransitionEnd(d.TRANSITION_DURATION):c())};var e=a.fn.alert;a.fn.alert=b,a.fn.alert.Constructor=d,a.fn.alert.noConflict=function(){return a.fn.alert=e,this},a(document).on("click.bs.alert.data-api",c,d.prototype.close)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof b&&b;e||d.data("bs.button",e=new c(this,f)),"toggle"==b?e.toggle():b&&e.setState(b)})}var c=function(b,d){this.$element=a(b),this.options=a.extend({},c.DEFAULTS,d),this.isLoading=!1};c.VERSION="3.3.7",c.DEFAULTS={loadingText:"loading..."},c.prototype.setState=function(b){var c="disabled",d=this.$element,e=d.is("input")?"val":"html",f=d.data();b+="Text",null==f.resetText&&d.data("resetText",d[e]()),setTimeout(a.proxy(function(){d[e](null==f[b]?this.options[b]:f[b]),"loadingText"==b?(this.isLoading=!0,d.addClass(c).attr(c,c).prop(c,!0)):this.isLoading&&(this.isLoading=!1,d.removeClass(c).removeAttr(c).prop(c,!1))},this),0)},c.prototype.toggle=function(){var a=!0,b=this.$element.closest('[data-toggle="buttons"]');if(b.length){var c=this.$element.find("input");"radio"==c.prop("type")?(c.prop("checked")&&(a=!1),b.find(".active").removeClass("active"),this.$element.addClass("active")):"checkbox"==c.prop("type")&&(c.prop("checked")!==this.$element.hasClass("active")&&(a=!1),this.$element.toggleClass("active")),c.prop("checked",this.$element.hasClass("active")),a&&c.trigger("change")}else this.$element.attr("aria-pressed",!this.$element.hasClass("active")),this.$element.toggleClass("active")};var d=a.fn.button;a.fn.button=b,a.fn.button.Constructor=c,a.fn.button.noConflict=function(){return a.fn.button=d,this},a(document).on("click.bs.button.data-api",'[data-toggle^="button"]',function(c){var d=a(c.target).closest(".btn");b.call(d,"toggle"),a(c.target).is('input[type="radio"], input[type="checkbox"]')||(c.preventDefault(),d.is("input,button")?d.trigger("focus"):d.find("input:visible,button:visible").first().trigger("focus"))}).on("focus.bs.button.data-api blur.bs.button.data-api",'[data-toggle^="button"]',function(b){a(b.target).closest(".btn").toggleClass("focus",/^focus(in)?$/.test(b.type))})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},c.DEFAULTS,d.data(),"object"==typeof b&&b),g="string"==typeof b?b:f.slide;e||d.data("bs.carousel",e=new c(this,f)),"number"==typeof b?e.to(b):g?e[g]():f.interval&&e.pause().cycle()})}var c=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=null,this.sliding=null,this.interval=null,this.$active=null,this.$items=null,this.options.keyboard&&this.$element.on("keydown.bs.carousel",a.proxy(this.keydown,this)),"hover"==this.options.pause&&!("ontouchstart"in document.documentElement)&&this.$element.on("mouseenter.bs.carousel",a.proxy(this.pause,this)).on("mouseleave.bs.carousel",a.proxy(this.cycle,this))};c.VERSION="3.3.7",c.TRANSITION_DURATION=600,c.DEFAULTS={interval:5e3,pause:"hover",wrap:!0,keyboard:!0},c.prototype.keydown=function(a){if(!/input|textarea/i.test(a.target.tagName)){switch(a.which){case 37:this.prev();break;case 39:tLine truncated
|
|
||||||
this.activeTarget=b,this.clear();var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate.bs.scrollspy")},b.prototype.clear=function(){a(this.selector).parentsUntil(this.options.target,".active").removeClass("active")};var d=a.fn.scrollspy;a.fn.scrollspy=c,a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=d,this},a(window).on("load.bs.scrollspy.data-api",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);c.call(b,b.data())})})}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new c(this)),"string"==typeof b&&e[b]()})}var c=function(b){this.element=a(b)};c.VERSION="3.3.7",c.TRANSITION_DURATION=150,c.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.data("target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a"),f=a.Event("hide.bs.tab",{relatedTarget:b[0]}),g=a.Event("show.bs.tab",{relatedTarget:e[0]});if(e.trigger(f),b.trigger(g),!g.isDefaultPrevented()&&!f.isDefaultPrevented()){var h=a(d);this.activate(b.closest("li"),c),this.activate(h,h.parent(),function(){e.trigger({type:"hidden.bs.tab",relatedTarget:b[0]}),b.trigger({type:"shown.bs.tab",relatedTarget:e[0]})})}}},c.prototype.activate=function(b,d,e){function f(){g.removeClass("active").find("> .dropdown-menu > .active").removeClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!1),b.addClass("active").find('[data-toggle="tab"]').attr("aria-expanded",!0),h?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu").length&&b.closest("li.dropdown").addClass("active").end().find('[data-toggle="tab"]').attr("aria-expanded",!0),e&&e()}var g=d.find("> .active"),h=e&&a.support.transition&&(g.length&&g.hasClass("fade")||!!d.find("> .fade").length);g.length&&h?g.one("bsTransitionEnd",f).emulateTransitionEnd(c.TRANSITION_DURATION):f(),g.removeClass("in")};var d=a.fn.tab;a.fn.tab=b,a.fn.tab.Constructor=c,a.fn.tab.noConflict=function(){return a.fn.tab=d,this};var e=function(c){c.preventDefault(),b.call(a(this),"show")};a(document).on("click.bs.tab.data-api",'[data-toggle="tab"]',e).on("click.bs.tab.data-api",'[data-toggle="pill"]',e)}(jQuery),+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof b&&b;e||d.data("bs.affix",e=new c(this,f)),"string"==typeof b&&e[b]()})}var c=function(b,d){this.options=a.extend({},c.DEFAULTS,d),this.$target=a(this.options.target).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(b),this.affixed=null,this.unpin=null,this.pinnedOffset=null,this.checkPosition()};c.VERSION="3.3.7",c.RESET="affix affix-top affix-bottom",c.DEFAULTS={offset:0,target:window},c.prototype.getState=function(a,b,c,d){var e=this.$target.scrollTop(),f=this.$element.offset(),g=this.$target.height();if(null!=c&&"top"==this.affixed)return e<c&&"top";if("bottom"==this.affixed)return null!=c?!(e+this.unpin<=f.top)&&"bottom":!(e+g<=a-d)&&"bottom";var h=null==this.affixed,i=h?e:f.top,j=h?g:b;return null!=c&&e<=c?"top":null!=d&&i+j>=a-d&&"bottom"},c.prototype.getPinnedOffset=function(){if(this.pinnedOffset)return this.pinnedOffset;this.$element.removeClass(c.RESET).addClass("affix");var a=this.$target.scrollTop(),b=this.$element.offset();return this.pinnedOffset=b.top-a},c.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},c.prototype.checkPosition=function(){if(this.$element.is(":visible")){var b=this.$element.height(),d=this.options.offset,e=d.top,f=d.bottom,g=Math.max(a(document).height(),a(document.body).height());"object"!=typeof d&&(f=e=d),"function"==typeof e&&(e=d.top(this.$element)),"function"==typeof f&&(f=d.bottom(this.$element));var h=this.getState(g,b,e,f);if(this.affixed!=h){null!=this.unpin&&this.$element.css("top","");var i="affix"+(h?"-"+h:""),j=a.Event(i+".bs.affix");if(this.$element.trigger(j),j.isDefaultPrevented())return;this.affixed=h,this.unpin="bottom"==h?this.getPinnedOffset():null,this.$element.removeClass(c.RESET).addClass(i).trigger(i.replace("affix","affixed")+".bs.affix")}"bottom"==h&&this.$element.offset({top:g-b-f})}};var d=a.fn.affix;a.fn.affix=b,a.fn.affix.Constructor=c,a.fn.affix.noConflict=function(){return a.fn.affix=d,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var c=a(this),d=c.data();d.offset=d.offset||{},null!=d.offsetBottom&&(d.offset.bottom=d.offsetBottom),null!=d.offsetTop&&(d.offset.top=d.offsetTop),b.call(c,d)})})}(jQuery);
|
|
||||||
File renamed without changes.
File diff suppressed because it is too large.
Load diff
@@ -1,8 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Bootstrap-select v1.12.2 (http://silviomoreto.github.io/bootstrap-select)
|
|
||||||
*
|
|
||||||
* Copyright 2013-2017 bootstrap-select
|
|
||||||
* Licensed under MIT (https://github.com/silviomoreto/bootstrap-select/blob/master/LICENSE)
|
|
||||||
*/
|
|
||||||
!function(a,b){"function"==typeof define&&define.amd?define(["jquery"],function(a){return b(a)}):"object"==typeof module&&module.exports?module.exports=b(require("jquery")):b(a.jQuery)}(this,function(a){!function(a){"use strict";function b(b){var c=[{re:/[\xC0-\xC6]/g,ch:"A"},{re:/[\xE0-\xE6]/g,ch:"a"},{re:/[\xC8-\xCB]/g,ch:"E"},{re:/[\xE8-\xEB]/g,ch:"e"},{re:/[\xCC-\xCF]/g,ch:"I"},{re:/[\xEC-\xEF]/g,ch:"i"},{re:/[\xD2-\xD6]/g,ch:"O"},{re:/[\xF2-\xF6]/g,ch:"o"},{re:/[\xD9-\xDC]/g,ch:"U"},{re:/[\xF9-\xFC]/g,ch:"u"},{re:/[\xC7-\xE7]/g,ch:"c"},{re:/[\xD1]/g,ch:"N"},{re:/[\xF1]/g,ch:"n"}];return a.each(c,function(){b=b?b.replace(this.re,this.ch):""}),b}function c(b){var c=arguments,d=b;[].shift.apply(c);var e,f=this.each(function(){var b=a(this);if(b.is("select")){var f=b.data("selectpicker"),g="object"==typeof d&&d;if(f){if(g)for(var h in g)g.hasOwnProperty(h)&&(f.options[h]=g[h])}else{var i=a.extend({},k.DEFAULTS,a.fn.selectpicker.defaults||{},b.data(),g);i.template=a.extend({},k.DEFAULTS.template,a.fn.selectpicker.defaults?a.fn.selectpicker.defaults.template:{},b.data().template,g.template),b.data("selectpicker",f=new k(this,i))}"string"==typeof d&&(e=f[d]instanceof Function?f[d].apply(f,c):f.options[d])}});return"undefined"!=typeof e?e:f}String.prototype.includes||!function(){var a={}.toString,b=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(a){}return c}(),c="".indexOf,d=function(b){if(null==this)throw new TypeError;var d=String(this);if(b&&"[object RegExp]"==a.call(b))throw new TypeError;var e=d.length,f=String(b),g=f.length,h=arguments.length>1?arguments[1]:void 0,i=h?Number(h):0;i!=i&&(i=0);var j=Math.min(Math.max(i,0),e);return!(g+j>e)&&c.call(d,f,i)!=-1};b?b(String.prototype,"includes",{value:d,configurable:!0,writable:!0}):String.prototype.includes=d}(),String.prototype.startsWith||!function(){var a=function(){try{var a={},b=Object.defineProperty,c=b(a,a,a)&&b}catch(a){}return c}(),b={}.toString,c=function(a){if(null==this)throw new TypeError;var c=String(this);if(a&&"[object RegExp]"==b.call(a))throw new TypeError;var d=c.length,e=String(a),f=e.length,g=arguments.length>1?arguments[1]:void 0,h=g?Number(g):0;h!=h&&(h=0);var i=Math.min(Math.max(h,0),d);if(f+i>d)return!1;for(var j=-1;++j<f;)if(c.charCodeAt(i+j)!=e.charCodeAt(j))return!1;return!0};a?a(String.prototype,"startsWith",{value:c,configurable:!0,writable:!0}):String.prototype.startsWith=c}(),Object.keys||(Object.keys=function(a,b,c){c=[];for(b in a)c.hasOwnProperty.call(a,b)&&c.push(b);return c});var d={useDefault:!1,_set:a.valHooks.select.set};a.valHooks.select.set=function(b,c){return c&&!d.useDefault&&a(b).data("selected",!0),d._set.apply(this,arguments)};var e=null;a.fn.triggerNative=function(a){var b,c=this[0];c.dispatchEvent?("function"==typeof Event?b=new Event(a,{bubbles:!0}):(b=document.createEvent("Event"),b.initEvent(a,!0,!1)),c.dispatchEvent(b)):c.fireEvent?(b=document.createEventObject(),b.eventType=a,c.fireEvent("on"+a,b)):this.trigger(a)},a.expr.pseudos.icontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toString().toUpperCase();return f.includes(d[3].toUpperCase())},a.expr.pseudos.ibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.text()).toString().toUpperCase();return f.startsWith(d[3].toUpperCase())},a.expr.pseudos.aicontains=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toString().toUpperCase();return f.includes(d[3].toUpperCase())},a.expr.pseudos.aibegins=function(b,c,d){var e=a(b),f=(e.data("tokens")||e.data("normalizedText")||e.text()).toString().toUpperCase();return f.startsWith(d[3].toUpperCase())};var f={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"},g={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"},h=function(a){var b=function(b){return a[b]},c="(?:"+Object.keys(a).join("|")+")",d=RegExp(c),e=RegExp(c,"g");return function(a){return a=null==a?"":""+a,d.test(a)?a.replace(e,b):a}},i=h(f),j=h(g),k=function(b,c){d.useDefault||(a.valHooks.select.set=d._set,d.useDefault=!0),this.$element=a(b),this.$newElement=null,this.$button=null,this.$menu=null,this.$lis=null,this.options=c,null===this.options.title&&(this.options.title=this.$element.attr("title"));var e=this.options.windowPadding;"number"==typeof e&&(this.options.windowPadding=[e,e,e,e]),this.val=k.prototype.val,this.render=k.prototype.render,this.refresh=k.prototype.refresh,this.setStyle=k.prototype.setStyle,this.selectAll=k.prototype.selectAll,this.deselectAll=k.prototype.deselectAll,this.destroy=k.prototype.destroy,this.remove=k.prototype.remove,this.show=k.prototype.show,this.hide=k.prototype.hide,this.init()};k.VERSION="1.12.2",k.DEFAULTS={noneSelectedText:"Nothing selected",noneResultsText:"No results matched {0}",countSelectedText:function(a,b){return 1==a?"{0} item selected":"{0} items selected"},maxOptionsText:function(a,b){return[1==a?"Limit reached ({n} item max)":"Limit reached ({n} items max)",1==b?"Group limit reached ({nLine truncated
|
|
||||||
m.focus());else{var u=a(":focus");u.click(),u.focus(),c.preventDefault(),a(document).data("spaceSelect",!0)}a(document).data("keycount",0)}(/(^9$|27)/.test(c.keyCode.toString(10))&&l&&(o.multiple||o.options.liveSearch)||/(27)/.test(c.keyCode.toString(10))&&!l)&&(o.$menu.parent().removeClass("open"),o.options.container&&o.$newElement.removeClass("open"),o.$button.focus())}},mobile:function(){this.$element.addClass("mobile-device")},refresh:function(){this.$lis=null,this.liObj={},this.reloadLi(),this.render(),this.checkDisabled(),this.liHeight(!0),this.setStyle(),this.setWidth(),this.$lis&&this.$searchbox.trigger("propertychange"),this.$element.trigger("refreshed.bs.select")},hide:function(){this.$newElement.hide()},show:function(){this.$newElement.show()},remove:function(){this.$newElement.remove(),this.$element.remove()},destroy:function(){this.$newElement.before(this.$element).remove(),this.$bsContainer?this.$bsContainer.remove():this.$menu.remove(),this.$element.off(".bs.select").removeData("selectpicker").removeClass("bs-select-hidden selectpicker")}};var l=a.fn.selectpicker;a.fn.selectpicker=c,a.fn.selectpicker.Constructor=k,a.fn.selectpicker.noConflict=function(){return a.fn.selectpicker=l,this},a(document).data("keycount",0).on("keydown.bs.select",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',k.prototype.keydown).on("focusin.modal",'.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input',function(a){a.stopPropagation()}),a(window).on("load.bs.select.data-api",function(){a(".selectpicker").each(function(){var b=a(this);c.call(b,b.data())})})}(a)});
|
|
||||||
File diff suppressed because it is too large.
Load diff
+1
@@ -0,0 +1 @@
|
|||||||
|
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports?require("jquery"):jQuery)}(function(a){function b(h,b,d){var f,e,g={content:{message:"object"==typeof b?b.message:b,title:b.title?b.title:"",icon:b.icon?b.icon:"",url:b.url?b.url:"#",target:b.target?b.target:"-"}};d=a.extend(!0,{},g,d),this.settings=a.extend(!0,{},c,d),this._defaults=c,"-"===this.settings.content.target&&(this.settings.content.target=this.settings.url_target),this.animations={start:"webkitAnimationStart oanimationstart MSAnimationStart animationstart",end:"webkitAnimationEnd oanimationend MSAnimationEnd animationend"},"number"==typeof this.settings.offset&&(this.settings.offset={x:this.settings.offset,y:this.settings.offset}),!this.settings.allow_duplicates&&(this.settings.allow_duplicates||(f=this,e=!1,a('[data-notify="container"]').each(function(k,c){var b=a(c),d=b.find('[data-notify="title"]').text().trim(),g=b.find('[data-notify="message"]').html().trim(),h=d===a("<div>"+f.settings.content.title+"</div>").html().trim(),i=g===a("<div>"+f.settings.content.message+"</div>").html().trim(),j=b.hasClass("alert-"+f.settings.type);return h&&i&&j&&(e=!0),!e}),e))||this.init()}var c={element:"body",position:null,type:"info",allow_dismiss:!0,allow_duplicates:!0,newest_on_top:!1,showProgressbar:!1,placement:{from:"top",align:"right"},offset:20,spacing:10,z_index:1031,delay:5e3,timer:1e3,url_target:"_blank",mouse_over:null,animate:{enter:"animated fadeInDown",exit:"animated fadeOutUp"},onShow:null,onShown:null,onClose:null,onClosed:null,icon_type:"class",template:'<div data-notify="container" class="col-xs-11 col-sm-4 alert alert-{0}" role="alert"><button type="button" aria-hidden="true" class="btn-close" data-notify="dismiss"></button><span data-notify="icon"></span> <span data-notify="title">{1}</span> <span data-notify="message">{2}</span><div class="progress" data-notify="progressbar"><div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div></div><a href="{3}" target="{4}" data-notify="url"></a></div>'};String.format=function(){for(var b=arguments[0],a=1;a<arguments.length;a++)b=b.replace(RegExp("\\{"+(a-1)+"\\}","gm"),arguments[a]);return b},a.extend(b.prototype,{init:function(){var a=this;this.buildNotify(),this.settings.content.icon&&this.setIcon(),"#"!=this.settings.content.url&&this.styleURL(),this.styleDismiss(),this.placement(),this.bind(),this.notify={$ele:this.$ele,update:function(e,f){var b={};for(var c in"string"==typeof e?b[e]=f:b=e,b)switch(c){case"type":this.$ele.removeClass("alert-"+a.settings.type),this.$ele.find('[data-notify="progressbar"] > .progress-bar').removeClass("progress-bar-"+a.settings.type),a.settings.type=b[c],this.$ele.addClass("alert-"+b[c]).find('[data-notify="progressbar"] > .progress-bar').addClass("progress-bar-"+b[c]);break;case"icon":var d=this.$ele.find('[data-notify="icon"]');"class"===a.settings.icon_type.toLowerCase()?d.removeClass(a.settings.content.icon).addClass(b[c]):(d.is("img")||d.find("img"),d.attr("src",b[c]));break;case"progress":var g=a.settings.delay-a.settings.delay*(b[c]/100);this.$ele.data("notify-delay",g),this.$ele.find('[data-notify="progressbar"] > div').attr("aria-valuenow",b[c]).css("width",b[c]+"%");break;case"url":this.$ele.find('[data-notify="url"]').attr("href",b[c]);break;case"target":this.$ele.find('[data-notify="url"]').attr("target",b[c]);break;default:this.$ele.find('[data-notify="'+c+'"]').html(b[c])}var h=this.$ele.outerHeight()+parseInt(a.settings.spacing)+parseInt(a.settings.offset.y);a.reposition(h)},close:function(){a.close()}}},buildNotify:function(){var b=this.settings.content;this.$ele=a(String.format(this.settings.template,this.settings.type,b.title,b.message,b.url,b.target)),this.$ele.attr("data-notify-position",this.settings.placement.from+"-"+this.settings.placement.align),this.settings.allow_dismiss||this.$ele.find('[data-notify="dismiss"]').css("display","none"),(!(this.settings.delay<=0)||this.settings.showProgressbar)&&this.settings.showProgressbar||this.$ele.find('[data-notify="progressbar"]').remove()},setIcon:function(){"class"===this.settings.icon_type.toLowerCase()?this.$ele.find('[data-notify="icon"]').addClass(this.settings.content.icon):this.$ele.find('[data-notify="icon"]').is("img")?this.$ele.find('[data-notify="icon"]').attr("src",this.settings.content.icon):this.$ele.find('[data-notify="icon"]').append('<img src="'+this.settings.content.icon+'" alt="Notify Icon" />')},styleDismiss:function(){this.$ele.find('[data-notify="dismiss"]').css({position:"absolute",right:"10px",top:"5px",zIndex:this.settings.z_index+2})},styleURL:function(){this.$ele.find('[data-notify="url"]').css({backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)",height:"100%",left:0,position:"absolute",top:0,width:"100%",zIndex:this.settings.z_index+1})},placement:function(){var d=this,b=this.settings.Line truncated
|
||||||
File renamed without changes.
-1
@@ -1 +0,0 @@
|
|||||||
!function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){function s(s){var e=!1;return t('[data-notify="container"]').each(function(i,n){var a=t(n),o=a.find('[data-notify="title"]').text().trim(),r=a.find('[data-notify="message"]').html().trim(),l=o===t("<div>"+s.settings.content.title+"</div>").html().trim(),d=r===t("<div>"+s.settings.content.message+"</div>").html().trim(),g=a.hasClass("alert-"+s.settings.type);return l&&d&&g&&(e=!0),!e}),e}function e(e,n,a){var o={content:{message:"object"==typeof n?n.message:n,title:n.title?n.title:"",icon:n.icon?n.icon:"",url:n.url?n.url:"#",target:n.target?n.target:"-"}};a=t.extend(!0,{},o,a),this.settings=t.extend(!0,{},i,a),this._defaults=i,"-"===this.settings.content.target&&(this.settings.content.target=this.settings.url_target),this.animations={start:"webkitAnimationStart oanimationstart MSAnimationStart animationstart",end:"webkitAnimationEnd oanimationend MSAnimationEnd animationend"},"number"==typeof this.settings.offset&&(this.settings.offset={x:this.settings.offset,y:this.settings.offset}),(this.settings.allow_duplicates||!this.settings.allow_duplicates&&!s(this))&&this.init()}var i={element:"body",position:null,type:"info",allow_dismiss:!0,allow_duplicates:!0,newest_on_top:!1,showProgressbar:!1,placement:{from:"top",align:"right"},offset:20,spacing:10,z_index:1031,delay:5e3,timer:1e3,url_target:"_blank",mouse_over:null,animate:{enter:"animated fadeInDown",exit:"animated fadeOutUp"},onShow:null,onShown:null,onClose:null,onClosed:null,icon_type:"class",template:'<div data-notify="container" class="col-xs-11 col-sm-4 alert alert-{0}" role="alert"><button type="button" aria-hidden="true" class="close" data-notify="dismiss">×</button><span data-notify="icon"></span> <span data-notify="title">{1}</span> <span data-notify="message">{2}</span><div class="progress" data-notify="progressbar"><div class="progress-bar progress-bar-{0}" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 0%;"></div></div><a href="{3}" target="{4}" data-notify="url"></a></div>'};String.format=function(){for(var t=arguments[0],s=1;s<arguments.length;s++)t=t.replace(RegExp("\\{"+(s-1)+"\\}","gm"),arguments[s]);return t},t.extend(e.prototype,{init:function(){var t=this;this.buildNotify(),this.settings.content.icon&&this.setIcon(),"#"!=this.settings.content.url&&this.styleURL(),this.styleDismiss(),this.placement(),this.bind(),this.notify={$ele:this.$ele,update:function(s,e){var i={};"string"==typeof s?i[s]=e:i=s;for(var n in i)switch(n){case"type":this.$ele.removeClass("alert-"+t.settings.type),this.$ele.find('[data-notify="progressbar"] > .progress-bar').removeClass("progress-bar-"+t.settings.type),t.settings.type=i[n],this.$ele.addClass("alert-"+i[n]).find('[data-notify="progressbar"] > .progress-bar').addClass("progress-bar-"+i[n]);break;case"icon":var a=this.$ele.find('[data-notify="icon"]');"class"===t.settings.icon_type.toLowerCase()?a.removeClass(t.settings.content.icon).addClass(i[n]):(a.is("img")||a.find("img"),a.attr("src",i[n]));break;case"progress":var o=t.settings.delay-t.settings.delay*(i[n]/100);this.$ele.data("notify-delay",o),this.$ele.find('[data-notify="progressbar"] > div').attr("aria-valuenow",i[n]).css("width",i[n]+"%");break;case"url":this.$ele.find('[data-notify="url"]').attr("href",i[n]);break;case"target":this.$ele.find('[data-notify="url"]').attr("target",i[n]);break;default:this.$ele.find('[data-notify="'+n+'"]').html(i[n])}var r=this.$ele.outerHeight()+parseInt(t.settings.spacing)+parseInt(t.settings.offset.y);t.reposition(r)},close:function(){t.close()}}},buildNotify:function(){var s=this.settings.content;this.$ele=t(String.format(this.settings.template,this.settings.type,s.title,s.message,s.url,s.target)),this.$ele.attr("data-notify-position",this.settings.placement.from+"-"+this.settings.placement.align),this.settings.allow_dismiss||this.$ele.find('[data-notify="dismiss"]').css("display","none"),(this.settings.delay<=0&&!this.settings.showProgressbar||!this.settings.showProgressbar)&&this.$ele.find('[data-notify="progressbar"]').remove()},setIcon:function(){"class"===this.settings.icon_type.toLowerCase()?this.$ele.find('[data-notify="icon"]').addClass(this.settings.content.icon):this.$ele.find('[data-notify="icon"]').is("img")?this.$ele.find('[data-notify="icon"]').attr("src",this.settings.content.icon):this.$ele.find('[data-notify="icon"]').append('<img src="'+this.settings.content.icon+'" alt="Notify Icon" />')},styleDismiss:function(){this.$ele.find('[data-notify="dismiss"]').css({position:"absolute",right:"10px",top:"5px",zIndex:this.settings.z_index+2})},styleURL:function(){this.$ele.find('[data-notify="url"]').css({backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)",height:"100%",left:0,position:"absolute",top:0,width:"100%",zIndex:this.settings.z_index+1})},placement:function(){varLine truncated
|
|
||||||
File diff suppressed because it is too large.
Load diff
Vendored
-7
@@ -1,7 +0,0 @@
|
|||||||
/*!
|
|
||||||
* Chart.js v2.9.2
|
|
||||||
* https://www.chartjs.org
|
|
||||||
* (c) 2019 Chart.js Contributors
|
|
||||||
* Released under the MIT License
|
|
||||||
*/
|
|
||||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(function(){try{return require("moment")}catch(t){}}()):"function"==typeof define&&define.amd?define(["require"],(function(t){return e(function(){try{return t("moment")}catch(t){}}())})):(t=t||self).Chart=e(t.moment)}(this,(function(t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var e={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]},n=function(t,e){return t(e={exports:{}},e.exports),e.exports}((function(t){var n={};for(var i in e)e.hasOwnProperty(i)&&(n[e[i]]=i);var a=t.exports={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};for(var r in a)if(a.hasOwnProperty(r)){if(!("channels"in a[r]))throw new Error("missing channels property: "+r);if(!("labels"in a[r]))throw new Error("missing channel labels property: "+r);if(a[r].labels.length!==a[r].channels)throw new Error("channel and label counts mismatch: "+r);var o=a[r].channels,s=a[r].labels;delete a[r].channels,delete a[r].labels,Object.defineProperty(a[r],"channels",{value:o}),Object.defineProperty(a[r],"labels",{value:s})}a.rgb.hsl=function(t){var e,n,i=t[0]/255,a=t[1]/255,r=t[2]/255,o=Math.min(i,a,r),s=Math.max(i,a,r),l=s-o;Line truncated
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
/*!
|
|
||||||
* chartjs-plugin-datalabels v0.7.0
|
|
||||||
* https://chartjs-plugin-datalabels.netlify.com
|
|
||||||
* (c) 2019 Chart.js Contributors
|
|
||||||
* Released under the MIT license
|
|
||||||
*/
|
|
||||||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("chart.js")):"function"==typeof define&&define.amd?define(["chart.js"],e):(t=t||self).ChartDataLabels=e(t.Chart)}(this,function(t){"use strict";var e=(t=t&&t.hasOwnProperty("default")?t.default:t).helpers,r=function(){if("undefined"!=typeof window){if(window.devicePixelRatio)return window.devicePixelRatio;var t=window.screen;if(t)return(t.deviceXDPI||1)/(t.logicalXDPI||1)}return 1}(),n={toTextLines:function(t){var r,n=[];for(t=[].concat(t);t.length;)"string"==typeof(r=t.pop())?n.unshift.apply(n,r.split("\n")):Array.isArray(r)?t.push.apply(t,r):e.isNullOrUndef(t)||n.unshift(""+r);return n},toFontString:function(t){return!t||e.isNullOrUndef(t.size)||e.isNullOrUndef(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family},textSize:function(t,e,r){var n,i=[].concat(e),o=i.length,a=t.font,l=0;for(t.font=r.string,n=0;n<o;++n)l=Math.max(t.measureText(i[n]).width,l);return t.font=a,{height:o*r.lineHeight,width:l}},parseFont:function(r){var i=t.defaults.global,o=e.valueOrDefault(r.size,i.defaultFontSize),a={family:e.valueOrDefault(r.family,i.defaultFontFamily),lineHeight:e.options.toLineHeight(r.lineHeight,o),size:o,style:e.valueOrDefault(r.style,i.defaultFontStyle),weight:e.valueOrDefault(r.weight,null),string:""};return a.string=n.toFontString(a),a},bound:function(t,e,r){return Math.max(t,Math.min(e,r))},arrayDiff:function(t,e){var r,n,i,o,a=t.slice(),l=[];for(r=0,i=e.length;r<i;++r)o=e[r],-1===(n=a.indexOf(o))?l.push([o,1]):a.splice(n,1);for(r=0,i=a.length;r<i;++r)l.push([a[r],-1]);return l},rasterize:function(t){return Math.round(t*r)/r}};function i(t,e){var r=e.x,n=e.y;if(null===r)return{x:0,y:-1};if(null===n)return{x:1,y:0};var i=t.x-r,o=t.y-n,a=Math.sqrt(i*i+o*o);return{x:a?i/a:0,y:a?o/a:-1}}var o=0,a=1,l=2,s=4,u=8;function f(t,e,r){var n=o;return t<r.left?n|=a:t>r.right&&(n|=l),e<r.top?n|=u:e>r.bottom&&(n|=s),n}function d(t,e){var r,n,i=e.anchor,o=t;return e.clamp&&(o=function(t,e){for(var r,n,i,o=t.x0,d=t.y0,c=t.x1,h=t.y1,x=f(o,d,e),y=f(c,h,e);x|y&&!(x&y);)(r=x||y)&u?(n=o+(c-o)*(e.top-d)/(h-d),i=e.top):r&s?(n=o+(c-o)*(e.bottom-d)/(h-d),i=e.bottom):r&l?(i=d+(h-d)*(e.right-o)/(c-o),n=e.right):r&a&&(i=d+(h-d)*(e.left-o)/(c-o),n=e.left),r===x?x=f(o=n,d=i,e):y=f(c=n,h=i,e);return{x0:o,x1:c,y0:d,y1:h}}(o,e.area)),"start"===i?(r=o.x0,n=o.y0):"end"===i?(r=o.x1,n=o.y1):(r=(o.x0+o.x1)/2,n=(o.y0+o.y1)/2),function(t,e,r,n,i){switch(i){case"center":r=n=0;break;case"bottom":r=0,n=1;break;case"right":r=1,n=0;break;case"left":r=-1,n=0;break;case"top":r=0,n=-1;break;case"start":r=-r,n=-n;break;case"end":break;default:i*=Math.PI/180,r=Math.cos(i),n=Math.sin(i)}return{x:t,y:e,vx:r,vy:n}}(r,n,t.vx,t.vy,e.align)}var c={arc:function(t,e){var r=(t.startAngle+t.endAngle)/2,n=Math.cos(r),i=Math.sin(r),o=t.innerRadius,a=t.outerRadius;return d({x0:t.x+n*o,y0:t.y+i*o,x1:t.x+n*a,y1:t.y+i*a,vx:n,vy:i},e)},point:function(t,e){var r=i(t,e.origin),n=r.x*t.radius,o=r.y*t.radius;return d({x0:t.x-n,y0:t.y-o,x1:t.x+n,y1:t.y+o,vx:r.x,vy:r.y},e)},rect:function(t,e){var r=i(t,e.origin),n=t.x,o=t.y,a=0,l=0;return t.horizontal?(n=Math.min(t.x,t.base),a=Math.abs(t.base-t.x)):(o=Math.min(t.y,t.base),l=Math.abs(t.base-t.y)),d({x0:n,y0:o+l,x1:n+a,y1:o,vx:r.x,vy:r.y},e)},fallback:function(t,e){var r=i(t,e.origin);return d({x0:t.x,y0:t.y,x1:t.x,y1:t.y,vx:r.x,vy:r.y},e)}},h=t.helpers,x=n.rasterize;function y(t){var e=t._model.horizontal,r=t._scale||e&&t._xScale||t._yScale;if(!r)return null;if(void 0!==r.xCenter&&void 0!==r.yCenter)return{x:r.xCenter,y:r.yCenter};var n=r.getBasePixel();return e?{x:n,y:null}:{x:null,y:n}}function v(t,e,r){var n=t.shadowBlur,i=r.stroked,o=x(r.x),a=x(r.y),l=x(r.w);i&&t.strokeText(e,o,a,l),r.filled&&(n&&i&&(t.shadowBlur=0),t.fillText(e,o,a,l),n&&i&&(t.shadowBlur=n))}var _=function(t,e,r,n){var i=this;i._config=t,i._index=n,i._model=null,i._rects=null,i._ctx=e,i._el=r};h.extend(_.prototype,{_modelize:function(e,r,i,o){var a,l=this._index,s=h.options.resolve,u=n.parseFont(s([i.font,{}],o,l)),f=s([i.color,t.defaults.global.defaultFontColor],o,l);return{align:s([i.align,"center"],o,l),anchor:s([i.anchor,"center"],o,l),area:o.chart.chartArea,backgroundColor:s([i.backgroundColor,null],o,l),borderColor:s([i.borderColor,null],o,l),borderRadius:s([i.borderRadius,0],o,l),borderWidth:s([i.borderWidth,0],o,l),clamp:s([i.clamp,!1],o,l),clip:s([i.clip,!1],o,l),color:f,display:e,font:u,lines:r,offset:s([i.offset,0],o,l),opacity:s([i.opacity,1],o,l),origin:y(this._el),padding:h.options.toPadding(s([i.padding,0],o,l)),positioner:(a=this._el,a instanceof t.elements.Arc?c.arc:a instanceof t.elements.Point?c.point:a instanceof t.elements.Rectangle?c.rect:c.fallback),rotation:s([i.rotation,0],o,l)*(Math.PI/180),size:n.textSize(this._ctx,r,u),textAlign:s([i.textAlign,"start"],o,l),textShadowBlur:s([i.textShadowBlur,0],o,l),textShadowColor:s([i.textShadowColor,f],o,l),textStrokeColor:s([i.textStrokeColor,f],o,l),textStrokeWiLine truncated
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
/*!
|
||||||
|
* chartjs-plugin-datalabels v2.0.0
|
||||||
|
* https://chartjs-plugin-datalabels.netlify.app
|
||||||
|
* (c) 2017-2021 chartjs-plugin-datalabels contributors
|
||||||
|
* Released under the MIT license
|
||||||
|
*/
|
||||||
|
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("chart.js/helpers"),require("chart.js")):"function"==typeof define&&define.amd?define(["chart.js/helpers","chart.js"],e):(t="undefined"!=typeof globalThis?globalThis:t||self).ChartDataLabels=e(t.Chart.helpers,t.Chart)}(this,(function(t,e){"use strict";var r=function(){if("undefined"!=typeof window){if(window.devicePixelRatio)return window.devicePixelRatio;var t=window.screen;if(t)return(t.deviceXDPI||1)/(t.logicalXDPI||1)}return 1}(),a=function(e){var r,a=[];for(e=[].concat(e);e.length;)"string"==typeof(r=e.pop())?a.unshift.apply(a,r.split("\n")):Array.isArray(r)?e.push.apply(e,r):t.isNullOrUndef(e)||a.unshift(""+r);return a},o=function(t,e,r){var a,o=[].concat(e),n=o.length,i=t.font,l=0;for(t.font=r.string,a=0;a<n;++a)l=Math.max(t.measureText(o[a]).width,l);return t.font=i,{height:n*r.lineHeight,width:l}},n=function(t,e,r){return Math.max(t,Math.min(e,r))},i=function(t,e){var r,a,o,n,i=t.slice(),l=[];for(r=0,o=e.length;r<o;++r)n=e[r],-1===(a=i.indexOf(n))?l.push([n,1]):i.splice(a,1);for(r=0,o=i.length;r<o;++r)l.push([i[r],-1]);return l};function l(t,e){var r=e.x,a=e.y;if(null===r)return{x:0,y:-1};if(null===a)return{x:1,y:0};var o=t.x-r,n=t.y-a,i=Math.sqrt(o*o+n*n);return{x:i?o/i:0,y:i?n/i:-1}}function s(t,e,r){var a=0;return t<r.left?a|=1:t>r.right&&(a|=2),e<r.top?a|=8:e>r.bottom&&(a|=4),a}function u(t,e){var r,a,o=e.anchor,n=t;return e.clamp&&(n=function(t,e){for(var r,a,o,n=t.x0,i=t.y0,l=t.x1,u=t.y1,d=s(n,i,e),c=s(l,u,e);d|c&&!(d&c);)8&(r=d||c)?(a=n+(l-n)*(e.top-i)/(u-i),o=e.top):4&r?(a=n+(l-n)*(e.bottom-i)/(u-i),o=e.bottom):2&r?(o=i+(u-i)*(e.right-n)/(l-n),a=e.right):1&r&&(o=i+(u-i)*(e.left-n)/(l-n),a=e.left),r===d?d=s(n=a,i=o,e):c=s(l=a,u=o,e);return{x0:n,x1:l,y0:i,y1:u}}(n,e.area)),"start"===o?(r=n.x0,a=n.y0):"end"===o?(r=n.x1,a=n.y1):(r=(n.x0+n.x1)/2,a=(n.y0+n.y1)/2),function(t,e,r,a,o){switch(o){case"center":r=a=0;break;case"bottom":r=0,a=1;break;case"right":r=1,a=0;break;case"left":r=-1,a=0;break;case"top":r=0,a=-1;break;case"start":r=-r,a=-a;break;case"end":break;default:o*=Math.PI/180,r=Math.cos(o),a=Math.sin(o)}return{x:t,y:e,vx:r,vy:a}}(r,a,t.vx,t.vy,e.align)}var d=function(t,e){var r=(t.startAngle+t.endAngle)/2,a=Math.cos(r),o=Math.sin(r),n=t.innerRadius,i=t.outerRadius;return u({x0:t.x+a*n,y0:t.y+o*n,x1:t.x+a*i,y1:t.y+o*i,vx:a,vy:o},e)},c=function(t,e){var r=l(t,e.origin),a=r.x*t.options.radius,o=r.y*t.options.radius;return u({x0:t.x-a,y0:t.y-o,x1:t.x+a,y1:t.y+o,vx:r.x,vy:r.y},e)},h=function(t,e){var r=l(t,e.origin),a=t.x,o=t.y,n=0,i=0;return t.horizontal?(a=Math.min(t.x,t.base),n=Math.abs(t.base-t.x)):(o=Math.min(t.y,t.base),i=Math.abs(t.base-t.y)),u({x0:a,y0:o+i,x1:a+n,y1:o,vx:r.x,vy:r.y},e)},f=function(t,e){var r=l(t,e.origin);return u({x0:t.x,y0:t.y,x1:t.x,y1:t.y,vx:r.x,vy:r.y},e)},x=function(t){return Math.round(t*r)/r};function y(t,e){var r=e.chart.getDatasetMeta(e.datasetIndex).vScale;if(!r)return null;if(void 0!==r.xCenter&&void 0!==r.yCenter)return{x:r.xCenter,y:r.yCenter};var a=r.getBasePixel();return t.horizontal?{x:a,y:null}:{x:null,y:a}}function v(t,e,r){var a=r.backgroundColor,o=r.borderColor,n=r.borderWidth;(a||o&&n)&&(t.beginPath(),function(t,e,r,a,o,n){var i=Math.PI/2;if(n){var l=Math.min(n,o/2,a/2),s=e+l,u=r+l,d=e+a-l,c=r+o-l;t.moveTo(e,u),s<d&&u<c?(t.arc(s,u,l,-Math.PI,-i),t.arc(d,u,l,-i,0),t.arc(d,c,l,0,i),t.arc(s,c,l,i,Math.PI)):s<d?(t.moveTo(s,r),t.arc(d,u,l,-i,i),t.arc(s,u,l,i,Math.PI+i)):u<c?(t.arc(s,u,l,-Math.PI,0),t.arc(s,c,l,0,Math.PI)):t.arc(s,u,l,-Math.PI,Math.PI),t.closePath(),t.moveTo(e,r)}else t.rect(e,r,a,o)}(t,x(e.x)+n/2,x(e.y)+n/2,x(e.w)-n,x(e.h)-n,r.borderRadius),t.closePath(),a&&(t.fillStyle=a,t.fill()),o&&n&&(t.strokeStyle=o,t.lineWidth=n,t.lineJoin="miter",t.stroke()))}function b(t,e,r){var a=t.shadowBlur,o=r.stroked,n=x(r.x),i=x(r.y),l=x(r.w);o&&t.strokeText(e,n,i,l),r.filled&&(a&&o&&(t.shadowBlur=0),t.fillText(e,n,i,l),a&&o&&(t.shadowBlur=a))}var _=function(t,e,r,a){var o=this;o._config=t,o._index=a,o._model=null,o._rects=null,o._ctx=e,o._el=r};t.merge(_.prototype,{_modelize:function(r,a,n,i){var l,s=this,u=s._index,x=t.toFont(t.resolve([n.font,{}],i,u)),v=t.resolve([n.color,e.defaults.color],i,u);return{align:t.resolve([n.align,"center"],i,u),anchor:t.resolve([n.anchor,"center"],i,u),area:i.chart.chartArea,backgroundColor:t.resolve([n.backgroundColor,null],i,u),borderColor:t.resolve([n.borderColor,null],i,u),borderRadius:t.resolve([n.borderRadius,0],i,u),borderWidth:t.resolve([n.borderWidth,0],i,u),clamp:t.resolve([n.clamp,!1],i,u),clip:t.resolve([n.clip,!1],i,u),color:v,display:r,font:x,lines:a,offset:t.resolve([n.offset,0],i,u),opacity:t.resolve([n.opacity,1],i,u),origin:y(s._el,i),padding:t.toPadding(t.resolve([n.padding,0],i,u)),positioner:(l=s._el,l instanceof e.ArcElement?d:l instanceof e.PointElement?c:l instanceof e.BarElement?h:f),rotation:t.resolve([n.rotation,0],i,u)*(Math.PI/180),size:o(s._ctx,a,x),textAlign:t.resolve([n.textAlign,"start"],i,u),teLine truncated
|
||||||
@@ -11,7 +11,7 @@ $(document).ready(function() {
|
|||||||
} else {
|
} else {
|
||||||
var parent_btn_grp = $(elem).parentsUntil(".btn-group").parent();
|
var parent_btn_grp = $(elem).parentsUntil(".btn-group").parent();
|
||||||
if (parent_btn_grp.hasClass('btn-group')) {
|
if (parent_btn_grp.hasClass('btn-group')) {
|
||||||
parent_btn_grp.replaceWith('<button class="btn btn-default btn-sm" disabled>' + lang_footer.loading + '</a>');
|
parent_btn_grp.replaceWith('<button class="btn btn-secondary btn-sm" disabled>' + lang_footer.loading + '</a>');
|
||||||
}
|
}
|
||||||
$(elem).text(lang_footer.loading);
|
$(elem).text(lang_footer.loading);
|
||||||
$(elem).attr('data-submitted', '1');
|
$(elem).attr('data-submitted', '1');
|
||||||
@@ -355,11 +355,8 @@ $(document).ready(function() {
|
|||||||
data_array[i] = decodeURIComponent(data_array[i]);
|
data_array[i] = decodeURIComponent(data_array[i]);
|
||||||
$("#ItemsToDelete").append("<li>" + escapeHtml(data_array[i]) + "</li>");
|
$("#ItemsToDelete").append("<li>" + escapeHtml(data_array[i]) + "</li>");
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
$('#ConfirmDeleteModal').modal({
|
$('#ConfirmDeleteModal').modal('show')
|
||||||
backdrop: 'static',
|
|
||||||
keyboard: false
|
|
||||||
})
|
|
||||||
.one('click', '#IsConfirmed', function(e) {
|
.one('click', '#IsConfirmed', function(e) {
|
||||||
if (is_active($('#IsConfirmed'))) { return false; }
|
if (is_active($('#IsConfirmed'))) { return false; }
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@@ -383,4 +380,18 @@ $(document).ready(function() {
|
|||||||
$('#ConfirmDeleteModal').modal('hide');
|
$('#ConfirmDeleteModal').modal('hide');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// toggle jquery datatables child rows
|
||||||
|
$('button[data-datatables-expand], a[data-datatables-expand]').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var tableId = e.target.getAttribute("data-datatables-expand");
|
||||||
|
var table = $("#" + tableId).DataTable();
|
||||||
|
table.rows(':not(.parent)').nodes().to$().find('td:first-child').trigger('click');
|
||||||
|
});
|
||||||
|
$('button[data-datatables-collapse], a[data-datatables-collapse]').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var tableId = e.target.getAttribute("data-datatables-collapse");
|
||||||
|
var table = $("#" + tableId).DataTable();
|
||||||
|
table.rows('.parent').nodes().to$().find('td:first-child').trigger('click');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
@@ -1,778 +0,0 @@
|
|||||||
//Copyright 2014-2015 Google Inc. All rights reserved.
|
|
||||||
|
|
||||||
//Use of this source code is governed by a BSD-style
|
|
||||||
//license that can be found in the LICENSE file or at
|
|
||||||
//https://developers.google.com/open-source/licenses/bsd
|
|
||||||
|
|
||||||
// ref: https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @fileoverview The U2F api.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modification:
|
|
||||||
* Wrap implementation so that we can exit if window.u2f is already supplied by the browser (see below).
|
|
||||||
*/
|
|
||||||
(function (root) {
|
|
||||||
/**
|
|
||||||
* Modification:
|
|
||||||
* Only continue load this library if window.u2f is not already supplied by the browser.
|
|
||||||
*/
|
|
||||||
var browserImplementsU2f = !!((typeof root.u2f !== 'undefined') && root.u2f.register);
|
|
||||||
|
|
||||||
if (browserImplementsU2f) {
|
|
||||||
root.u2f.isSupported = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Namespace for the U2F api.
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
var u2f = root.u2f || {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modification:
|
|
||||||
* Check if browser supports U2F API before this wrapper was added.
|
|
||||||
*/
|
|
||||||
u2f.isSupported = !!(((typeof u2f !== 'undefined') && u2f.register) || ((typeof chrome !== 'undefined') && chrome.runtime));
|
|
||||||
|
|
||||||
/**
|
|
||||||
* FIDO U2F Javascript API Version
|
|
||||||
* @number
|
|
||||||
*/
|
|
||||||
var js_api_version;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The U2F extension id
|
|
||||||
* @const {string}
|
|
||||||
*/
|
|
||||||
// The Chrome packaged app extension ID.
|
|
||||||
// Uncomment this if you want to deploy a server instance that uses
|
|
||||||
// the package Chrome app and does not require installing the U2F Chrome extension.
|
|
||||||
u2f.EXTENSION_ID = 'kmendfapggjehodndflmmgagdbamhnfd';
|
|
||||||
// The U2F Chrome extension ID.
|
|
||||||
// Uncomment this if you want to deploy a server instance that uses
|
|
||||||
// the U2F Chrome extension to authenticate.
|
|
||||||
// u2f.EXTENSION_ID = 'pfboblefjcgdjicmnffhdgionmgcdmne';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Message types for messsages to/from the extension
|
|
||||||
* @const
|
|
||||||
* @enum {string}
|
|
||||||
*/
|
|
||||||
u2f.MessageTypes = {
|
|
||||||
'U2F_REGISTER_REQUEST': 'u2f_register_request',
|
|
||||||
'U2F_REGISTER_RESPONSE': 'u2f_register_response',
|
|
||||||
'U2F_SIGN_REQUEST': 'u2f_sign_request',
|
|
||||||
'U2F_SIGN_RESPONSE': 'u2f_sign_response',
|
|
||||||
'U2F_GET_API_VERSION_REQUEST': 'u2f_get_api_version_request',
|
|
||||||
'U2F_GET_API_VERSION_RESPONSE': 'u2f_get_api_version_response'
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Response status codes
|
|
||||||
* @const
|
|
||||||
* @enum {number}
|
|
||||||
*/
|
|
||||||
u2f.ErrorCodes = {
|
|
||||||
'OK': 0,
|
|
||||||
'OTHER_ERROR': 1,
|
|
||||||
'BAD_REQUEST': 2,
|
|
||||||
'CONFIGURATION_UNSUPPORTED': 3,
|
|
||||||
'DEVICE_INELIGIBLE': 4,
|
|
||||||
'TIMEOUT': 5
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A message for registration requests
|
|
||||||
* @typedef {{
|
|
||||||
* type: u2f.MessageTypes,
|
|
||||||
* appId: ?string,
|
|
||||||
* timeoutSeconds: ?number,
|
|
||||||
* requestId: ?number
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.U2fRequest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A message for registration responses
|
|
||||||
* @typedef {{
|
|
||||||
* type: u2f.MessageTypes,
|
|
||||||
* responseData: (u2f.Error | u2f.RegisterResponse | u2f.SignResponse),
|
|
||||||
* requestId: ?number
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.U2fResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An error object for responses
|
|
||||||
* @typedef {{
|
|
||||||
* errorCode: u2f.ErrorCodes,
|
|
||||||
* errorMessage: ?string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.Error;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a single sign request.
|
|
||||||
* @typedef {enum {BLUETOOTH_RADIO, BLUETOOTH_LOW_ENERGY, USB, NFC}}
|
|
||||||
*/
|
|
||||||
u2f.Transport;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a single sign request.
|
|
||||||
* @typedef {Array<u2f.Transport>}
|
|
||||||
*/
|
|
||||||
u2f.Transports;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a single sign request.
|
|
||||||
* @typedef {{
|
|
||||||
* version: string,
|
|
||||||
* challenge: string,
|
|
||||||
* keyHandle: string,
|
|
||||||
* appId: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.SignRequest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a sign response.
|
|
||||||
* @typedef {{
|
|
||||||
* keyHandle: string,
|
|
||||||
* signatureData: string,
|
|
||||||
* clientData: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.SignResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a registration request.
|
|
||||||
* @typedef {{
|
|
||||||
* version: string,
|
|
||||||
* challenge: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.RegisterRequest;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a registration response.
|
|
||||||
* @typedef {{
|
|
||||||
* version: string,
|
|
||||||
* keyHandle: string,
|
|
||||||
* transports: Transports,
|
|
||||||
* appId: string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.RegisterResponse;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a registered key.
|
|
||||||
* @typedef {{
|
|
||||||
* version: string,
|
|
||||||
* keyHandle: string,
|
|
||||||
* transports: ?Transports,
|
|
||||||
* appId: ?string
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.RegisteredKey;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Data object for a get API register response.
|
|
||||||
* @typedef {{
|
|
||||||
* js_api_version: number
|
|
||||||
* }}
|
|
||||||
*/
|
|
||||||
u2f.GetJsApiVersionResponse;
|
|
||||||
|
|
||||||
|
|
||||||
//Low level MessagePort API support
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up a MessagePort to the U2F extension using the
|
|
||||||
* available mechanisms.
|
|
||||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
|
||||||
*/
|
|
||||||
u2f.getMessagePort = function (callback) {
|
|
||||||
if (typeof chrome != 'undefined' && chrome.runtime) {
|
|
||||||
// The actual message here does not matter, but we need to get a reply
|
|
||||||
// for the callback to run. Thus, send an empty signature request
|
|
||||||
// in order to get a failure response.
|
|
||||||
var msg = {
|
|
||||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
|
||||||
signRequests: []
|
|
||||||
};
|
|
||||||
chrome.runtime.sendMessage(u2f.EXTENSION_ID, msg, function () {
|
|
||||||
if (!chrome.runtime.lastError) {
|
|
||||||
// We are on a whitelisted origin and can talk directly
|
|
||||||
// with the extension.
|
|
||||||
u2f.getChromeRuntimePort_(callback);
|
|
||||||
} else {
|
|
||||||
// chrome.runtime was available, but we couldn't message
|
|
||||||
// the extension directly, use iframe
|
|
||||||
u2f.getIframePort_(callback);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (u2f.isAndroidChrome_()) {
|
|
||||||
u2f.getAuthenticatorPort_(callback);
|
|
||||||
} else if (u2f.isIosChrome_()) {
|
|
||||||
u2f.getIosPort_(callback);
|
|
||||||
} else {
|
|
||||||
// chrome.runtime was not available at all, which is normal
|
|
||||||
// when this origin doesn't have access to any extensions.
|
|
||||||
u2f.getIframePort_(callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect chrome running on android based on the browser's useragent.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.isAndroidChrome_ = function () {
|
|
||||||
var userAgent = navigator.userAgent;
|
|
||||||
return userAgent.indexOf('Chrome') != -1 &&
|
|
||||||
userAgent.indexOf('Android') != -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Detect chrome running on iOS based on the browser's platform.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.isIosChrome_ = function () {
|
|
||||||
return ["iPhone", "iPad", "iPod"].indexOf(navigator.platform) > -1;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Connects directly to the extension via chrome.runtime.connect.
|
|
||||||
* @param {function(u2f.WrappedChromeRuntimePort_)} callback
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.getChromeRuntimePort_ = function (callback) {
|
|
||||||
var port = chrome.runtime.connect(u2f.EXTENSION_ID,
|
|
||||||
{ 'includeTlsChannelId': true });
|
|
||||||
setTimeout(function () {
|
|
||||||
callback(new u2f.WrappedChromeRuntimePort_(port));
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a 'port' abstraction to the Authenticator app.
|
|
||||||
* @param {function(u2f.WrappedAuthenticatorPort_)} callback
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.getAuthenticatorPort_ = function (callback) {
|
|
||||||
setTimeout(function () {
|
|
||||||
callback(new u2f.WrappedAuthenticatorPort_());
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a 'port' abstraction to the iOS client app.
|
|
||||||
* @param {function(u2f.WrappedIosPort_)} callback
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.getIosPort_ = function (callback) {
|
|
||||||
setTimeout(function () {
|
|
||||||
callback(new u2f.WrappedIosPort_());
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A wrapper for chrome.runtime.Port that is compatible with MessagePort.
|
|
||||||
* @param {Port} port
|
|
||||||
* @constructor
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.WrappedChromeRuntimePort_ = function (port) {
|
|
||||||
this.port_ = port;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format and return a sign request compliant with the JS API version supported by the extension.
|
|
||||||
* @param {Array<u2f.SignRequest>} signRequests
|
|
||||||
* @param {number} timeoutSeconds
|
|
||||||
* @param {number} reqId
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
u2f.formatSignRequest_ =
|
|
||||||
function (appId, challenge, registeredKeys, timeoutSeconds, reqId) {
|
|
||||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
|
||||||
// Adapt request to the 1.0 JS API
|
|
||||||
var signRequests = [];
|
|
||||||
for (var i = 0; i < registeredKeys.length; i++) {
|
|
||||||
signRequests[i] = {
|
|
||||||
version: registeredKeys[i].version,
|
|
||||||
challenge: challenge,
|
|
||||||
keyHandle: registeredKeys[i].keyHandle,
|
|
||||||
appId: appId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
|
||||||
signRequests: signRequests,
|
|
||||||
timeoutSeconds: timeoutSeconds,
|
|
||||||
requestId: reqId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// JS 1.1 API
|
|
||||||
return {
|
|
||||||
type: u2f.MessageTypes.U2F_SIGN_REQUEST,
|
|
||||||
appId: appId,
|
|
||||||
challenge: challenge,
|
|
||||||
registeredKeys: registeredKeys,
|
|
||||||
timeoutSeconds: timeoutSeconds,
|
|
||||||
requestId: reqId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format and return a register request compliant with the JS API version supported by the extension..
|
|
||||||
* @param {Array<u2f.SignRequest>} signRequests
|
|
||||||
* @param {Array<u2f.RegisterRequest>} signRequests
|
|
||||||
* @param {number} timeoutSeconds
|
|
||||||
* @param {number} reqId
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
u2f.formatRegisterRequest_ =
|
|
||||||
function (appId, registeredKeys, registerRequests, timeoutSeconds, reqId) {
|
|
||||||
if (js_api_version === undefined || js_api_version < 1.1) {
|
|
||||||
// Adapt request to the 1.0 JS API
|
|
||||||
for (var i = 0; i < registerRequests.length; i++) {
|
|
||||||
registerRequests[i].appId = appId;
|
|
||||||
}
|
|
||||||
var signRequests = [];
|
|
||||||
for (var i = 0; i < registeredKeys.length; i++) {
|
|
||||||
signRequests[i] = {
|
|
||||||
version: registeredKeys[i].version,
|
|
||||||
challenge: registerRequests[0],
|
|
||||||
keyHandle: registeredKeys[i].keyHandle,
|
|
||||||
appId: appId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
|
||||||
signRequests: signRequests,
|
|
||||||
registerRequests: registerRequests,
|
|
||||||
timeoutSeconds: timeoutSeconds,
|
|
||||||
requestId: reqId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// JS 1.1 API
|
|
||||||
return {
|
|
||||||
type: u2f.MessageTypes.U2F_REGISTER_REQUEST,
|
|
||||||
appId: appId,
|
|
||||||
registerRequests: registerRequests,
|
|
||||||
registeredKeys: registeredKeys,
|
|
||||||
timeoutSeconds: timeoutSeconds,
|
|
||||||
requestId: reqId
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Posts a message on the underlying channel.
|
|
||||||
* @param {Object} message
|
|
||||||
*/
|
|
||||||
u2f.WrappedChromeRuntimePort_.prototype.postMessage = function (message) {
|
|
||||||
this.port_.postMessage(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emulates the HTML 5 addEventListener interface. Works only for the
|
|
||||||
* onmessage event, which is hooked up to the chrome.runtime.Port.onMessage.
|
|
||||||
* @param {string} eventName
|
|
||||||
* @param {function({data: Object})} handler
|
|
||||||
*/
|
|
||||||
u2f.WrappedChromeRuntimePort_.prototype.addEventListener =
|
|
||||||
function (eventName, handler) {
|
|
||||||
var name = eventName.toLowerCase();
|
|
||||||
if (name == 'message' || name == 'onmessage') {
|
|
||||||
this.port_.onMessage.addListener(function (message) {
|
|
||||||
// Emulate a minimal MessageEvent object
|
|
||||||
handler({ 'data': message });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('WrappedChromeRuntimePort only supports onMessage');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the Authenticator app with a MessagePort interface.
|
|
||||||
* @constructor
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_ = function () {
|
|
||||||
this.requestId_ = -1;
|
|
||||||
this.requestObject_ = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch the Authenticator intent.
|
|
||||||
* @param {Object} message
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_.prototype.postMessage = function (message) {
|
|
||||||
var intentUrl =
|
|
||||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ +
|
|
||||||
';S.request=' + encodeURIComponent(JSON.stringify(message)) +
|
|
||||||
';end';
|
|
||||||
document.location = intentUrl;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells what type of port this is.
|
|
||||||
* @return {String} port type
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_.prototype.getPortType = function () {
|
|
||||||
return "WrappedAuthenticatorPort_";
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emulates the HTML 5 addEventListener interface.
|
|
||||||
* @param {string} eventName
|
|
||||||
* @param {function({data: Object})} handler
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_.prototype.addEventListener = function (eventName, handler) {
|
|
||||||
var name = eventName.toLowerCase();
|
|
||||||
if (name == 'message') {
|
|
||||||
var self = this;
|
|
||||||
/* Register a callback to that executes when
|
|
||||||
* chrome injects the response. */
|
|
||||||
window.addEventListener(
|
|
||||||
'message', self.onRequestUpdate_.bind(self, handler), false);
|
|
||||||
} else {
|
|
||||||
console.error('WrappedAuthenticatorPort only supports message');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback invoked when a response is received from the Authenticator.
|
|
||||||
* @param function({data: Object}) callback
|
|
||||||
* @param {Object} message message Object
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_.prototype.onRequestUpdate_ =
|
|
||||||
function (callback, message) {
|
|
||||||
var messageObject = JSON.parse(message.data);
|
|
||||||
var intentUrl = messageObject['intentURL'];
|
|
||||||
|
|
||||||
var errorCode = messageObject['errorCode'];
|
|
||||||
var responseObject = null;
|
|
||||||
if (messageObject.hasOwnProperty('data')) {
|
|
||||||
responseObject = /** @type {Object} */ (
|
|
||||||
JSON.parse(messageObject['data']));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback({ 'data': responseObject });
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base URL for intents to Authenticator.
|
|
||||||
* @const
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.WrappedAuthenticatorPort_.INTENT_URL_BASE_ =
|
|
||||||
'intent:#Intent;action=com.google.android.apps.authenticator.AUTHENTICATE';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the iOS client app with a MessagePort interface.
|
|
||||||
* @constructor
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.WrappedIosPort_ = function () { };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch the iOS client app request
|
|
||||||
* @param {Object} message
|
|
||||||
*/
|
|
||||||
u2f.WrappedIosPort_.prototype.postMessage = function (message) {
|
|
||||||
var str = JSON.stringify(message);
|
|
||||||
var url = "u2f://auth?" + encodeURI(str);
|
|
||||||
location.replace(url);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells what type of port this is.
|
|
||||||
* @return {String} port type
|
|
||||||
*/
|
|
||||||
u2f.WrappedIosPort_.prototype.getPortType = function () {
|
|
||||||
return "WrappedIosPort_";
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Emulates the HTML 5 addEventListener interface.
|
|
||||||
* @param {string} eventName
|
|
||||||
* @param {function({data: Object})} handler
|
|
||||||
*/
|
|
||||||
u2f.WrappedIosPort_.prototype.addEventListener = function (eventName, handler) {
|
|
||||||
var name = eventName.toLowerCase();
|
|
||||||
if (name !== 'message') {
|
|
||||||
console.error('WrappedIosPort only supports message');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets up an embedded trampoline iframe, sourced from the extension.
|
|
||||||
* @param {function(MessagePort)} callback
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.getIframePort_ = function (callback) {
|
|
||||||
// Create the iframe
|
|
||||||
var iframeOrigin = 'chrome-extension://' + u2f.EXTENSION_ID;
|
|
||||||
var iframe = document.createElement('iframe');
|
|
||||||
iframe.src = iframeOrigin + '/u2f-comms.html';
|
|
||||||
iframe.setAttribute('style', 'display:none');
|
|
||||||
document.body.appendChild(iframe);
|
|
||||||
|
|
||||||
var channel = new MessageChannel();
|
|
||||||
var ready = function (message) {
|
|
||||||
if (message.data == 'ready') {
|
|
||||||
channel.port1.removeEventListener('message', ready);
|
|
||||||
callback(channel.port1);
|
|
||||||
} else {
|
|
||||||
console.error('First event on iframe port was not "ready"');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
channel.port1.addEventListener('message', ready);
|
|
||||||
channel.port1.start();
|
|
||||||
|
|
||||||
iframe.addEventListener('load', function () {
|
|
||||||
// Deliver the port to the iframe and initialize
|
|
||||||
iframe.contentWindow.postMessage('init', iframeOrigin, [channel.port2]);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
//High-level JS API
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Default extension response timeout in seconds.
|
|
||||||
* @const
|
|
||||||
*/
|
|
||||||
u2f.EXTENSION_TIMEOUT_SEC = 30;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A singleton instance for a MessagePort to the extension.
|
|
||||||
* @type {MessagePort|u2f.WrappedChromeRuntimePort_}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.port_ = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callbacks waiting for a port
|
|
||||||
* @type {Array<function((MessagePort|u2f.WrappedChromeRuntimePort_))>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.waitingForPort_ = [];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A counter for requestIds.
|
|
||||||
* @type {number}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.reqCounter_ = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A map from requestIds to client callbacks
|
|
||||||
* @type {Object.<number,(function((u2f.Error|u2f.RegisterResponse))
|
|
||||||
* |function((u2f.Error|u2f.SignResponse)))>}
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.callbackMap_ = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates or retrieves the MessagePort singleton to use.
|
|
||||||
* @param {function((MessagePort|u2f.WrappedChromeRuntimePort_))} callback
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.getPortSingleton_ = function (callback) {
|
|
||||||
if (u2f.port_) {
|
|
||||||
callback(u2f.port_);
|
|
||||||
} else {
|
|
||||||
if (u2f.waitingForPort_.length == 0) {
|
|
||||||
u2f.getMessagePort(function (port) {
|
|
||||||
u2f.port_ = port;
|
|
||||||
u2f.port_.addEventListener('message',
|
|
||||||
/** @type {function(Event)} */(u2f.responseHandler_));
|
|
||||||
|
|
||||||
// Careful, here be async callbacks. Maybe.
|
|
||||||
while (u2f.waitingForPort_.length)
|
|
||||||
u2f.waitingForPort_.shift()(u2f.port_);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
u2f.waitingForPort_.push(callback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles response messages from the extension.
|
|
||||||
* @param {MessageEvent.<u2f.Response>} message
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
u2f.responseHandler_ = function (message) {
|
|
||||||
var response = message.data;
|
|
||||||
var reqId = response['requestId'];
|
|
||||||
if (!reqId || !u2f.callbackMap_[reqId]) {
|
|
||||||
console.error('Unknown or missing requestId in response.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var cb = u2f.callbackMap_[reqId];
|
|
||||||
delete u2f.callbackMap_[reqId];
|
|
||||||
cb(response['responseData']);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an array of sign requests to available U2F tokens.
|
|
||||||
* If the JS API version supported by the extension is unknown, it first sends a
|
|
||||||
* message to the extension to find out the supported API version and then it sends
|
|
||||||
* the sign request.
|
|
||||||
* @param {string=} appId
|
|
||||||
* @param {string=} challenge
|
|
||||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
|
||||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
|
||||||
* @param {number=} opt_timeoutSeconds
|
|
||||||
*/
|
|
||||||
u2f.sign = function (appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
|
||||||
if (js_api_version === undefined) {
|
|
||||||
// Send a message to get the extension to JS API version, then send the actual sign request.
|
|
||||||
u2f.getApiVersion(
|
|
||||||
function (response) {
|
|
||||||
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
|
|
||||||
console.log("Extension JS API Version: ", js_api_version);
|
|
||||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// We know the JS API version. Send the actual sign request in the supported API version.
|
|
||||||
u2f.sendSignRequest(appId, challenge, registeredKeys, callback, opt_timeoutSeconds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an array of sign requests to available U2F tokens.
|
|
||||||
* @param {string=} appId
|
|
||||||
* @param {string=} challenge
|
|
||||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
|
||||||
* @param {function((u2f.Error|u2f.SignResponse))} callback
|
|
||||||
* @param {number=} opt_timeoutSeconds
|
|
||||||
*/
|
|
||||||
u2f.sendSignRequest = function (appId, challenge, registeredKeys, callback, opt_timeoutSeconds) {
|
|
||||||
u2f.getPortSingleton_(function (port) {
|
|
||||||
var reqId = ++u2f.reqCounter_;
|
|
||||||
u2f.callbackMap_[reqId] = callback;
|
|
||||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
|
||||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
|
||||||
var req = u2f.formatSignRequest_(appId, challenge, registeredKeys, timeoutSeconds, reqId);
|
|
||||||
port.postMessage(req);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches register requests to available U2F tokens. An array of sign
|
|
||||||
* requests identifies already registered tokens.
|
|
||||||
* If the JS API version supported by the extension is unknown, it first sends a
|
|
||||||
* message to the extension to find out the supported API version and then it sends
|
|
||||||
* the register request.
|
|
||||||
* @param {string=} appId
|
|
||||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
|
||||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
|
||||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
|
||||||
* @param {number=} opt_timeoutSeconds
|
|
||||||
*/
|
|
||||||
u2f.register = function (appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
|
||||||
if (js_api_version === undefined) {
|
|
||||||
// Send a message to get the extension to JS API version, then send the actual register request.
|
|
||||||
u2f.getApiVersion(
|
|
||||||
function (response) {
|
|
||||||
js_api_version = response['js_api_version'] === undefined ? 0 : response['js_api_version'];
|
|
||||||
console.log("Extension JS API Version: ", js_api_version);
|
|
||||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
|
||||||
callback, opt_timeoutSeconds);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// We know the JS API version. Send the actual register request in the supported API version.
|
|
||||||
u2f.sendRegisterRequest(appId, registerRequests, registeredKeys,
|
|
||||||
callback, opt_timeoutSeconds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches register requests to available U2F tokens. An array of sign
|
|
||||||
* requests identifies already registered tokens.
|
|
||||||
* @param {string=} appId
|
|
||||||
* @param {Array<u2f.RegisterRequest>} registerRequests
|
|
||||||
* @param {Array<u2f.RegisteredKey>} registeredKeys
|
|
||||||
* @param {function((u2f.Error|u2f.RegisterResponse))} callback
|
|
||||||
* @param {number=} opt_timeoutSeconds
|
|
||||||
*/
|
|
||||||
u2f.sendRegisterRequest = function (appId, registerRequests, registeredKeys, callback, opt_timeoutSeconds) {
|
|
||||||
u2f.getPortSingleton_(function (port) {
|
|
||||||
var reqId = ++u2f.reqCounter_;
|
|
||||||
u2f.callbackMap_[reqId] = callback;
|
|
||||||
var timeoutSeconds = (typeof opt_timeoutSeconds !== 'undefined' ?
|
|
||||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC);
|
|
||||||
var req = u2f.formatRegisterRequest_(
|
|
||||||
appId, registeredKeys, registerRequests, timeoutSeconds, reqId);
|
|
||||||
port.postMessage(req);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches a message to the extension to find out the supported
|
|
||||||
* JS API version.
|
|
||||||
* If the user is on a mobile phone and is thus using Google Authenticator instead
|
|
||||||
* of the Chrome extension, don't send the request and simply return 0.
|
|
||||||
* @param {function((u2f.Error|u2f.GetJsApiVersionResponse))} callback
|
|
||||||
* @param {number=} opt_timeoutSeconds
|
|
||||||
*/
|
|
||||||
u2f.getApiVersion = function (callback, opt_timeoutSeconds) {
|
|
||||||
u2f.getPortSingleton_(function (port) {
|
|
||||||
// If we are using Android Google Authenticator or iOS client app,
|
|
||||||
// do not fire an intent to ask which JS API version to use.
|
|
||||||
if (port.getPortType) {
|
|
||||||
var apiVersion;
|
|
||||||
switch (port.getPortType()) {
|
|
||||||
case 'WrappedIosPort_':
|
|
||||||
case 'WrappedAuthenticatorPort_':
|
|
||||||
apiVersion = 1.1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
apiVersion = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
callback({ 'js_api_version': apiVersion });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var reqId = ++u2f.reqCounter_;
|
|
||||||
u2f.callbackMap_[reqId] = callback;
|
|
||||||
var req = {
|
|
||||||
type: u2f.MessageTypes.U2F_GET_API_VERSION_REQUEST,
|
|
||||||
timeoutSeconds: (typeof opt_timeoutSeconds !== 'undefined' ?
|
|
||||||
opt_timeoutSeconds : u2f.EXTENSION_TIMEOUT_SEC),
|
|
||||||
requestId: reqId
|
|
||||||
};
|
|
||||||
port.postMessage(req);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Modification:
|
|
||||||
* Assign u2f back to window (root) scope.
|
|
||||||
*/
|
|
||||||
root.u2f = u2f;
|
|
||||||
}(this));
|
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
/*! markdown-it 13.0.1 https://github.com/markdown-it/markdown-it @license MIT */
|
||||||
|
!function(e,r){"object"==typeof exports&&"undefined"!=typeof module?module.exports=r():"function"==typeof define&&define.amd?define(r):(e="undefined"!=typeof globalThis?globalThis:e||self).markdownit=r()}(this,(function(){"use strict";function e(e){if(e.__esModule)return e;var r=Object.defineProperty({},"__esModule",{value:!0});return Object.keys(e).forEach((function(t){var n=Object.getOwnPropertyDescriptor(e,t);Object.defineProperty(r,t,n.get?n:{enumerable:!0,get:function(){return e[t]}})})),r}var r={Aacute:"\xc1",aacute:"\xe1",Abreve:"\u0102",abreve:"\u0103",ac:"\u223e",acd:"\u223f",acE:"\u223e\u0333",Acirc:"\xc2",acirc:"\xe2",acute:"\xb4",Acy:"\u0410",acy:"\u0430",AElig:"\xc6",aelig:"\xe6",af:"\u2061",Afr:"\ud835\udd04",afr:"\ud835\udd1e",Agrave:"\xc0",agrave:"\xe0",alefsym:"\u2135",aleph:"\u2135",Alpha:"\u0391",alpha:"\u03b1",Amacr:"\u0100",amacr:"\u0101",amalg:"\u2a3f",amp:"&",AMP:"&",andand:"\u2a55",And:"\u2a53",and:"\u2227",andd:"\u2a5c",andslope:"\u2a58",andv:"\u2a5a",ang:"\u2220",ange:"\u29a4",angle:"\u2220",angmsdaa:"\u29a8",angmsdab:"\u29a9",angmsdac:"\u29aa",angmsdad:"\u29ab",angmsdae:"\u29ac",angmsdaf:"\u29ad",angmsdag:"\u29ae",angmsdah:"\u29af",angmsd:"\u2221",angrt:"\u221f",angrtvb:"\u22be",angrtvbd:"\u299d",angsph:"\u2222",angst:"\xc5",angzarr:"\u237c",Aogon:"\u0104",aogon:"\u0105",Aopf:"\ud835\udd38",aopf:"\ud835\udd52",apacir:"\u2a6f",ap:"\u2248",apE:"\u2a70",ape:"\u224a",apid:"\u224b",apos:"'",ApplyFunction:"\u2061",approx:"\u2248",approxeq:"\u224a",Aring:"\xc5",aring:"\xe5",Ascr:"\ud835\udc9c",ascr:"\ud835\udcb6",Assign:"\u2254",ast:"*",asymp:"\u2248",asympeq:"\u224d",Atilde:"\xc3",atilde:"\xe3",Auml:"\xc4",auml:"\xe4",awconint:"\u2233",awint:"\u2a11",backcong:"\u224c",backepsilon:"\u03f6",backprime:"\u2035",backsim:"\u223d",backsimeq:"\u22cd",Backslash:"\u2216",Barv:"\u2ae7",barvee:"\u22bd",barwed:"\u2305",Barwed:"\u2306",barwedge:"\u2305",bbrk:"\u23b5",bbrktbrk:"\u23b6",bcong:"\u224c",Bcy:"\u0411",bcy:"\u0431",bdquo:"\u201e",becaus:"\u2235",because:"\u2235",Because:"\u2235",bemptyv:"\u29b0",bepsi:"\u03f6",bernou:"\u212c",Bernoullis:"\u212c",Beta:"\u0392",beta:"\u03b2",beth:"\u2136",between:"\u226c",Bfr:"\ud835\udd05",bfr:"\ud835\udd1f",bigcap:"\u22c2",bigcirc:"\u25ef",bigcup:"\u22c3",bigodot:"\u2a00",bigoplus:"\u2a01",bigotimes:"\u2a02",bigsqcup:"\u2a06",bigstar:"\u2605",bigtriangledown:"\u25bd",bigtriangleup:"\u25b3",biguplus:"\u2a04",bigvee:"\u22c1",bigwedge:"\u22c0",bkarow:"\u290d",blacklozenge:"\u29eb",blacksquare:"\u25aa",blacktriangle:"\u25b4",blacktriangledown:"\u25be",blacktriangleleft:"\u25c2",blacktriangleright:"\u25b8",blank:"\u2423",blk12:"\u2592",blk14:"\u2591",blk34:"\u2593",block:"\u2588",bne:"=\u20e5",bnequiv:"\u2261\u20e5",bNot:"\u2aed",bnot:"\u2310",Bopf:"\ud835\udd39",bopf:"\ud835\udd53",bot:"\u22a5",bottom:"\u22a5",bowtie:"\u22c8",boxbox:"\u29c9",boxdl:"\u2510",boxdL:"\u2555",boxDl:"\u2556",boxDL:"\u2557",boxdr:"\u250c",boxdR:"\u2552",boxDr:"\u2553",boxDR:"\u2554",boxh:"\u2500",boxH:"\u2550",boxhd:"\u252c",boxHd:"\u2564",boxhD:"\u2565",boxHD:"\u2566",boxhu:"\u2534",boxHu:"\u2567",boxhU:"\u2568",boxHU:"\u2569",boxminus:"\u229f",boxplus:"\u229e",boxtimes:"\u22a0",boxul:"\u2518",boxuL:"\u255b",boxUl:"\u255c",boxUL:"\u255d",boxur:"\u2514",boxuR:"\u2558",boxUr:"\u2559",boxUR:"\u255a",boxv:"\u2502",boxV:"\u2551",boxvh:"\u253c",boxvH:"\u256a",boxVh:"\u256b",boxVH:"\u256c",boxvl:"\u2524",boxvL:"\u2561",boxVl:"\u2562",boxVL:"\u2563",boxvr:"\u251c",boxvR:"\u255e",boxVr:"\u255f",boxVR:"\u2560",bprime:"\u2035",breve:"\u02d8",Breve:"\u02d8",brvbar:"\xa6",bscr:"\ud835\udcb7",Bscr:"\u212c",bsemi:"\u204f",bsim:"\u223d",bsime:"\u22cd",bsolb:"\u29c5",bsol:"\\",bsolhsub:"\u27c8",bull:"\u2022",bullet:"\u2022",bump:"\u224e",bumpE:"\u2aae",bumpe:"\u224f",Bumpeq:"\u224e",bumpeq:"\u224f",Cacute:"\u0106",cacute:"\u0107",capand:"\u2a44",capbrcup:"\u2a49",capcap:"\u2a4b",cap:"\u2229",Cap:"\u22d2",capcup:"\u2a47",capdot:"\u2a40",CapitalDifferentialD:"\u2145",caps:"\u2229\ufe00",caret:"\u2041",caron:"\u02c7",Cayleys:"\u212d",ccaps:"\u2a4d",Ccaron:"\u010c",ccaron:"\u010d",Ccedil:"\xc7",ccedil:"\xe7",Ccirc:"\u0108",ccirc:"\u0109",Cconint:"\u2230",ccups:"\u2a4c",ccupssm:"\u2a50",Cdot:"\u010a",cdot:"\u010b",cedil:"\xb8",Cedilla:"\xb8",cemptyv:"\u29b2",cent:"\xa2",centerdot:"\xb7",CenterDot:"\xb7",cfr:"\ud835\udd20",Cfr:"\u212d",CHcy:"\u0427",chcy:"\u0447",check:"\u2713",checkmark:"\u2713",Chi:"\u03a7",chi:"\u03c7",circ:"\u02c6",circeq:"\u2257",circlearrowleft:"\u21ba",circlearrowright:"\u21bb",circledast:"\u229b",circledcirc:"\u229a",circleddash:"\u229d",CircleDot:"\u2299",circledR:"\xae",circledS:"\u24c8",CircleMinus:"\u2296",CirclePlus:"\u2295",CircleTimes:"\u2297",cir:"\u25cb",cirE:"\u29c3",cire:"\u2257",cirfnint:"\u2a10",cirmid:"\u2aef",cirscir:"\u29c2",ClockwiseContourIntegral:"\u2232",CloseCurlyDoubleQuote:"\u201d",CloseCurlyQuote:"\u2019",clubs:"\u2663",clubsuit:"\u2663",colon:":",Colon:"\u2237",Colone:"\u2a74",colone:"\u2254",coloneq:"\u2254",comma:",",commat:"@",comp:"\u2201",compfn:"\u22Line truncated
|
||||||
|
/*! https://mths.be/punycode v1.4.1 by @mathias */function Lr(e){throw new RangeError(qr[e])}function zr(e,r){for(var t=e.length,n=[];t--;)n[t]=r(e[t]);return n}function Tr(e,r){var t=e.split("@"),n="";return t.length>1&&(n=t[0]+"@",e=t[1]),n+zr((e=e.replace(Er,".")).split("."),r).join(".")}function Ir(e){for(var r,t,n=[],s=0,o=e.length;s<o;)(r=e.charCodeAt(s++))>=55296&&r<=56319&&s<o?56320==(64512&(t=e.charCodeAt(s++)))?n.push(((1023&r)<<10)+(1023&t)+65536):(n.push(r),s--):n.push(r);return n}function Mr(e){return zr(e,(function(e){var r="";return e>65535&&(r+=Fr((e-=65536)>>>10&1023|55296),e=56320|1023&e),r+=Fr(e)})).join("")}function Rr(e,r){return e+22+75*(e<26)-((0!=r)<<5)}function Br(e,r,t){var n=0;for(e=t?Sr(e/700):e>>1,e+=Sr(e/r);e>455;n+=xr)e=Sr(e/35);return Sr(n+36*e/(e+38))}function Nr(e){var r,t,n,s,o,i,a,c,l,u,p,h=[],f=e.length,d=0,m=128,g=72;for((t=e.lastIndexOf("-"))<0&&(t=0),n=0;n<t;++n)e.charCodeAt(n)>=128&&Lr("not-basic"),h.push(e.charCodeAt(n));for(s=t>0?t+1:0;s<f;){for(o=d,i=1,a=xr;s>=f&&Lr("invalid-input"),((c=(p=e.charCodeAt(s++))-48<10?p-22:p-65<26?p-65:p-97<26?p-97:xr)>=xr||c>Sr((Ar-d)/i))&&Lr("overflow"),d+=c*i,!(c<(l=a<=g?1:a>=g+26?26:a-g));a+=xr)i>Sr(Ar/(u=xr-l))&&Lr("overflow"),i*=u;g=Br(d-o,r=h.length+1,0==o),Sr(d/r)>Ar-m&&Lr("overflow"),m+=Sr(d/r),d%=r,h.splice(d++,0,m)}return Mr(h)}function Or(e){var r,t,n,s,o,i,a,c,l,u,p,h,f,d,m,g=[];for(h=(e=Ir(e)).length,r=128,t=0,o=72,i=0;i<h;++i)(p=e[i])<128&&g.push(Fr(p));for(n=s=g.length,s&&g.push("-");n<h;){for(a=Ar,i=0;i<h;++i)(p=e[i])>=r&&p<a&&(a=p);for(a-r>Sr((Ar-t)/(f=n+1))&&Lr("overflow"),t+=(a-r)*f,r=a,i=0;i<h;++i)if((p=e[i])<r&&++t>Ar&&Lr("overflow"),p==r){for(c=t,l=xr;!(c<(u=l<=o?1:l>=o+26?26:l-o));l+=xr)m=c-u,d=xr-u,g.push(Fr(Rr(u+m%d,0))),c=Sr(m/d);g.push(Fr(Rr(c,0))),o=Br(t,f,n==s),t=0,++n}++t,++r}return g.join("")}function Pr(e){return Tr(e,(function(e){return Dr.test(e)?Nr(e.slice(4).toLowerCase()):e}))}function jr(e){return Tr(e,(function(e){return wr.test(e)?"xn--"+Or(e):e}))}var Ur="1.4.1",Vr={decode:Ir,encode:Mr},Zr={version:Ur,ucs2:Vr,toASCII:jr,toUnicode:Pr,encode:Or,decode:Nr},$r=e(Object.freeze({__proto__:null,decode:Nr,encode:Or,toUnicode:Pr,toASCII:jr,version:Ur,ucs2:Vr,default:Zr})),Gr={default:{options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201c\u201d\u2018\u2019",highlight:null,maxNesting:100},components:{core:{},block:{},inline:{}}},zero:{options:{html:!1,xhtmlOut:!1,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201c\u201d\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["paragraph"]},inline:{rules:["text"],rules2:["balance_pairs","fragments_join"]}}},commonmark:{options:{html:!0,xhtmlOut:!0,breaks:!1,langPrefix:"language-",linkify:!1,typographer:!1,quotes:"\u201c\u201d\u2018\u2019",highlight:null,maxNesting:20},components:{core:{rules:["normalize","block","inline","text_join"]},block:{rules:["blockquote","code","fence","heading","hr","html_block","lheading","list","reference","paragraph"]},inline:{rules:["autolink","backticks","emphasis","entity","escape","html_inline","image","link","newline","text"],rules2:["balance_pairs","emphasis","fragments_join"]}}}},Hr=/^(vbscript|javascript|file|data):/,Jr=/^data:image\/(gif|png|jpeg|webp);/;function Wr(e){var r=e.trim().toLowerCase();return!Hr.test(r)||!!Jr.test(r)}var Yr=["http:","https:","mailto:"];function Kr(e){var r=C.parse(e,!0);if(r.hostname&&(!r.protocol||Yr.indexOf(r.protocol)>=0))try{r.hostname=$r.toASCII(r.hostname)}catch(e){}return C.encode(C.format(r))}function Qr(e){var r=C.parse(e,!0);if(r.hostname&&(!r.protocol||Yr.indexOf(r.protocol)>=0))try{r.hostname=$r.toUnicode(r.hostname)}catch(e){}return C.decode(C.format(r),C.decode.defaultChars+"%")}function Xr(e,r){if(!(this instanceof Xr))return new Xr(e,r);r||w.isString(e)||(r=e||{},e="default"),this.inline=new ur,this.block=new ze,this.core=new ue,this.renderer=new B,this.linkify=new yr,this.validateLink=Wr,this.normalizeLink=Kr,this.normalizeLinkText=Qr,this.utils=w,this.helpers=w.assign({},L),this.options={},this.configure(e),r&&this.set(r)}return Xr.prototype.set=function(e){return w.assign(this.options,e),this},Xr.prototype.configure=function(e){var r,t=this;if(w.isString(e)&&!(e=Gr[r=e]))throw new Error('Wrong `markdown-it` preset "'+r+'", check name');if(!e)throw new Error("Wrong `markdown-it` preset, can't be empty");return e.options&&t.set(e.options),e.components&&Object.keys(e.components).forEach((function(r){e.components[r].rules&&t[r].ruler.enableOnly(e.components[r].rules),e.components[r].rules2&&t[r].ruler2.enableOnly(e.components[r].rules2)})),this},Xr.prototype.enable=function(e,r){var t=[];Array.isArray(e)||(e=[e]),["core","block","inline"].forEach((function(r){t=t.concat(this[r].ruler.enable(e,!0))}),this),t=t.concat(this.inline.ruler2.enable(e,!0));var n=e.filter((function(e){return t.indexOf(e)<0}));if(n.length&&!r)throw new Error("MarkdLine truncated
|
||||||
@@ -1,239 +0,0 @@
|
|||||||
!function ($) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
// TABCOLLAPSE CLASS DEFINITION
|
|
||||||
// ======================
|
|
||||||
|
|
||||||
var TabCollapse = function (el, options) {
|
|
||||||
this.options = options;
|
|
||||||
this.$tabs = $(el);
|
|
||||||
|
|
||||||
this._accordionVisible = false; //content is attached to tabs at first
|
|
||||||
this._initAccordion();
|
|
||||||
this._checkStateOnResize();
|
|
||||||
|
|
||||||
|
|
||||||
// checkState() has gone to setTimeout for making it possible to attach listeners to
|
|
||||||
// shown-accordion.bs.tabcollapse event on page load.
|
|
||||||
// See https://github.com/flatlogic/bootstrap-tabcollapse/issues/23
|
|
||||||
var that = this;
|
|
||||||
setTimeout(function() {
|
|
||||||
that.checkState();
|
|
||||||
}, 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.DEFAULTS = {
|
|
||||||
accordionClass: 'visible-xs',
|
|
||||||
tabsClass: 'hidden-xs',
|
|
||||||
accordionTemplate: function(heading, groupId, parentId, active) {
|
|
||||||
return '<div class="panel panel-default">' +
|
|
||||||
' <div class="panel-heading">' +
|
|
||||||
' <h4 class="panel-title">' +
|
|
||||||
' </h4>' +
|
|
||||||
' </div>' +
|
|
||||||
' <div id="' + groupId + '" class="panel-collapse collapse ' + (active ? 'in' : '') + '">' +
|
|
||||||
' <div class="panel-body js-tabcollapse-panel-body">' +
|
|
||||||
' </div>' +
|
|
||||||
' </div>' +
|
|
||||||
'</div>'
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype.checkState = function(){
|
|
||||||
if (this.$tabs.is(':visible') && this._accordionVisible){
|
|
||||||
this.showTabs();
|
|
||||||
this._accordionVisible = false;
|
|
||||||
} else if (this.$accordion.is(':visible') && !this._accordionVisible){
|
|
||||||
this.showAccordion();
|
|
||||||
this._accordionVisible = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype.showTabs = function(){
|
|
||||||
var view = this;
|
|
||||||
this.$tabs.trigger($.Event('show-tabs.bs.tabcollapse'));
|
|
||||||
|
|
||||||
var $panelHeadings = this.$accordion.find('.js-tabcollapse-panel-heading').detach();
|
|
||||||
|
|
||||||
$panelHeadings.each(function() {
|
|
||||||
var $panelHeading = $(this),
|
|
||||||
$parentLi = $panelHeading.data('bs.tabcollapse.parentLi');
|
|
||||||
|
|
||||||
var $oldHeading = view._panelHeadingToTabHeading($panelHeading);
|
|
||||||
|
|
||||||
$parentLi.removeClass('active');
|
|
||||||
if ($parentLi.parent().hasClass('dropdown-menu') && !$parentLi.siblings('li').hasClass('active')) {
|
|
||||||
$parentLi.parent().parent().removeClass('active');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$oldHeading.hasClass('collapsed')) {
|
|
||||||
$parentLi.addClass('active');
|
|
||||||
$('.tab-pane').removeClass('active');
|
|
||||||
$($panelHeading.attr('href')).addClass('active');
|
|
||||||
if ($parentLi.parent().hasClass('dropdown-menu')) {
|
|
||||||
$parentLi.parent().parent().addClass('active');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$oldHeading.removeClass('collapsed');
|
|
||||||
}
|
|
||||||
|
|
||||||
$parentLi.append($panelHeading);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!$('li').hasClass('active')) {
|
|
||||||
$('li').first().addClass('active')
|
|
||||||
}
|
|
||||||
|
|
||||||
var $panelBodies = this.$accordion.find('.js-tabcollapse-panel-body');
|
|
||||||
$panelBodies.each(function(){
|
|
||||||
var $panelBody = $(this),
|
|
||||||
$tabPane = $panelBody.data('bs.tabcollapse.tabpane');
|
|
||||||
$tabPane.append($panelBody.contents().detach());
|
|
||||||
});
|
|
||||||
this.$accordion.html('');
|
|
||||||
|
|
||||||
if(this.options.updateLinks) {
|
|
||||||
var $tabContents = this.getTabContentElement();
|
|
||||||
$tabContents.find('[data-toggle-was="tab"], [data-toggle-was="pill"]').each(function() {
|
|
||||||
var $el = $(this);
|
|
||||||
var href = $el.attr('href').replace(/-collapse$/g, '');
|
|
||||||
$el.attr({
|
|
||||||
'data-toggle': $el.attr('data-toggle-was'),
|
|
||||||
'data-toggle-was': '',
|
|
||||||
'data-parent': '',
|
|
||||||
href: href
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$tabs.trigger($.Event('shown-tabs.bs.tabcollapse'));
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype.getTabContentElement = function(){
|
|
||||||
var $tabContents = $(this.options.tabContentSelector);
|
|
||||||
if($tabContents.length === 0) {
|
|
||||||
$tabContents = this.$tabs.siblings('.tab-content');
|
|
||||||
}
|
|
||||||
return $tabContents;
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype.showAccordion = function(){
|
|
||||||
this.$tabs.trigger($.Event('show-accordion.bs.tabcollapse'));
|
|
||||||
|
|
||||||
var $headings = this.$tabs.find('li:not(.dropdown) [data-toggle="tab"], li:not(.dropdown) [data-toggle="pill"]'),
|
|
||||||
view = this;
|
|
||||||
$headings.each(function(){
|
|
||||||
var $heading = $(this),
|
|
||||||
$parentLi = $heading.parent();
|
|
||||||
$heading.data('bs.tabcollapse.parentLi', $parentLi);
|
|
||||||
view.$accordion.append(view._createAccordionGroup(view.$accordion.attr('id'), $heading.detach()));
|
|
||||||
});
|
|
||||||
|
|
||||||
if(this.options.updateLinks) {
|
|
||||||
var parentId = this.$accordion.attr('id');
|
|
||||||
var $selector = this.$accordion.find('.js-tabcollapse-panel-body');
|
|
||||||
$selector.find('[data-toggle="tab"], [data-toggle="pill"]').each(function() {
|
|
||||||
var $el = $(this);
|
|
||||||
var href = $el.attr('href') + '-collapse';
|
|
||||||
$el.attr({
|
|
||||||
'data-toggle-was': $el.attr('data-toggle'),
|
|
||||||
'data-toggle': 'collapse',
|
|
||||||
'data-parent': '#' + parentId,
|
|
||||||
href: href
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$tabs.trigger($.Event('shown-accordion.bs.tabcollapse'));
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype._panelHeadingToTabHeading = function($heading) {
|
|
||||||
var href = $heading.attr('href').replace(/-collapse$/g, '');
|
|
||||||
$heading.attr({
|
|
||||||
'data-toggle': 'tab',
|
|
||||||
'href': href,
|
|
||||||
'data-parent': ''
|
|
||||||
});
|
|
||||||
return $heading;
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype._tabHeadingToPanelHeading = function($heading, groupId, parentId, active) {
|
|
||||||
$heading.addClass('js-tabcollapse-panel-heading ' + (active ? '' : 'collapsed'));
|
|
||||||
$heading.attr({
|
|
||||||
'data-toggle': 'collapse',
|
|
||||||
'data-parent': '#' + parentId,
|
|
||||||
'href': '#' + groupId
|
|
||||||
});
|
|
||||||
return $heading;
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype._checkStateOnResize = function(){
|
|
||||||
var view = this;
|
|
||||||
$(window).resize(function(){
|
|
||||||
clearTimeout(view._resizeTimeout);
|
|
||||||
view._resizeTimeout = setTimeout(function(){
|
|
||||||
view.checkState();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
TabCollapse.prototype._initAccordion = function(){
|
|
||||||
var randomString = function() {
|
|
||||||
var result = "",
|
|
||||||
possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
||||||
for( var i=0; i < 5; i++ ) {
|
|
||||||
result += possible.charAt(Math.floor(Math.random() * possible.length));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
var srcId = this.$tabs.attr('id'),
|
|
||||||
accordionId = (srcId ? srcId : randomString()) + '-accordion';
|
|
||||||
|
|
||||||
this.$accordion = $('<div class="panel-group ' + this.options.accordionClass + '" id="' + accordionId +'"></div>');
|
|
||||||
this.$tabs.after(this.$accordion);
|
|
||||||
this.$tabs.addClass(this.options.tabsClass);
|
|
||||||
this.getTabContentElement().addClass(this.options.tabsClass);
|
|
||||||
};
|
|
||||||
|
|
||||||
TabCollapse.prototype._createAccordionGroup = function(parentId, $heading){
|
|
||||||
var tabSelector = $heading.attr('data-target'),
|
|
||||||
active = $heading.data('bs.tabcollapse.parentLi').is('.active');
|
|
||||||
|
|
||||||
if (!tabSelector) {
|
|
||||||
tabSelector = $heading.attr('href');
|
|
||||||
tabSelector = tabSelector && tabSelector.replace(/.*(?=#[^\s]*$)/, ''); //strip for ie7
|
|
||||||
}
|
|
||||||
|
|
||||||
var $tabPane = $(tabSelector),
|
|
||||||
groupId = $tabPane.attr('id') + '-collapse',
|
|
||||||
$panel = $(this.options.accordionTemplate($heading, groupId, parentId, active));
|
|
||||||
$panel.find('.panel-heading > .panel-title').append(this._tabHeadingToPanelHeading($heading, groupId, parentId, active));
|
|
||||||
$panel.find('.panel-body').append($tabPane.contents().detach())
|
|
||||||
.data('bs.tabcollapse.tabpane', $tabPane);
|
|
||||||
|
|
||||||
return $panel;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TABCOLLAPSE PLUGIN DEFINITION
|
|
||||||
// =======================
|
|
||||||
|
|
||||||
$.fn.tabCollapse = function (option) {
|
|
||||||
return this.each(function () {
|
|
||||||
var $this = $(this);
|
|
||||||
var data = $this.data('bs.tabcollapse');
|
|
||||||
var options = $.extend({}, TabCollapse.DEFAULTS, $this.data(), typeof option === 'object' && option);
|
|
||||||
|
|
||||||
if (!data) $this.data('bs.tabcollapse', new TabCollapse(this, options));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.tabCollapse.Constructor = TabCollapse;
|
|
||||||
|
|
||||||
|
|
||||||
}(window.jQuery);
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
/*
|
|
||||||
* FooTable v3 - FooTable is a jQuery plugin that aims to make HTML tables on smaller devices look awesome.
|
|
||||||
* @version 3.1.6
|
|
||||||
* @link http://fooplugins.com
|
|
||||||
* @copyright Steven Usher & Brad Vincent 2015
|
|
||||||
* @license Released under the GPLv3 license.
|
|
||||||
*/
|
|
||||||
!function(a,b){window.console=window.console||{log:function(){},error:function(){}},a.fn.footable=function(a,c){return a=a||{},this.filter("table").each(function(d,e){b.init(e,a,c)})};var c={events:[]};b.__debug__=JSON.parse(localStorage.getItem("footable_debug"))||!1,b.__debug_options__=JSON.parse(localStorage.getItem("footable_debug_options"))||c,b.debug=function(d,e){return b.is["boolean"](d)?(b.__debug__=d,void(b.__debug__?(localStorage.setItem("footable_debug",JSON.stringify(b.__debug__)),b.__debug_options__=a.extend(!0,{},c,e||{}),b.is.hash(e)&&localStorage.setItem("footable_debug_options",JSON.stringify(b.__debug_options__))):(localStorage.removeItem("footable_debug"),localStorage.removeItem("footable_debug_options")))):b.__debug__},b.get=function(b){return a(b).first().data("__FooTable__")},b.init=function(a,c,d){var e=b.get(a);return e instanceof b.Table&&e.destroy(),new b.Table(a,c,d)},b.getRow=function(b){var c=a(b).closest("tr");return c.hasClass("footable-detail-row")&&(c=c.prev()),c.data("__FooTableRow__")}}(jQuery,FooTable=window.FooTable||{}),function(a){var b=function(){return!0};a.arr={},a.arr.each=function(b,c){if(a.is.array(b)&&a.is.fn(c))for(var d=0,e=b.length;e>d&&c(b[d],d)!==!1;d++);},a.arr.get=function(b,c){var d=[];if(!a.is.array(b))return d;if(!a.is.fn(c))return b;for(var e=0,f=b.length;f>e;e++)c(b[e],e)&&d.push(b[e]);return d},a.arr.any=function(c,d){if(!a.is.array(c))return!1;d=a.is.fn(d)?d:b;for(var e=0,f=c.length;f>e;e++)if(d(c[e],e))return!0;return!1},a.arr.contains=function(b,c){if(!a.is.array(b)||a.is.undef(c))return!1;for(var d=0,e=b.length;e>d;d++)if(b[d]==c)return!0;return!1},a.arr.first=function(c,d){if(!a.is.array(c))return null;d=a.is.fn(d)?d:b;for(var e=0,f=c.length;f>e;e++)if(d(c[e],e))return c[e];return null},a.arr.map=function(b,c){var d=[],e=null;if(!a.is.array(b)||!a.is.fn(c))return d;for(var f=0,g=b.length;g>f;f++)null!=(e=c(b[f],f))&&d.push(e);return d},a.arr.remove=function(b,c){var d=[],e=[];if(!a.is.array(b)||!a.is.fn(c))return e;for(var f=0,g=b.length;g>f;f++)c(b[f],f,e)&&(d.push(f),e.push(b[f]));for(d.sort(function(a,b){return b-a}),f=0,g=d.length;g>f;f++){var h=d[f]-f;b.splice(h,1)}return e},a.arr["delete"]=function(b,c){var d=-1,e=null;if(!a.is.array(b)||a.is.undef(c))return e;for(var f=0,g=b.length;g>f;f++)if(b[f]==c){d=f,e=b[f];break}return-1!=d&&b.splice(d,1),e},a.arr.replace=function(a,b,c){var d=a.indexOf(b);-1!==d&&(a[d]=c)}}(FooTable),function(a){a.is={},a.is.type=function(a,b){return typeof a===b},a.is.defined=function(a){return"undefined"!=typeof a},a.is.undef=function(a){return"undefined"==typeof a},a.is.array=function(a){return"[object Array]"===Object.prototype.toString.call(a)},a.is.date=function(a){return"[object Date]"===Object.prototype.toString.call(a)&&!isNaN(a.getTime())},a.is["boolean"]=function(a){return"[object Boolean]"===Object.prototype.toString.call(a)},a.is.string=function(a){return"[object String]"===Object.prototype.toString.call(a)},a.is.number=function(a){return"[object Number]"===Object.prototype.toString.call(a)&&!isNaN(a)},a.is.fn=function(b){return a.is.defined(window)&&b===window.alert||"[object Function]"===Object.prototype.toString.call(b)},a.is.error=function(a){return"[object Error]"===Object.prototype.toString.call(a)},a.is.object=function(a){return"[object Object]"===Object.prototype.toString.call(a)},a.is.hash=function(b){return a.is.object(b)&&b.constructor===Object&&!b.nodeType&&!b.setInterval},a.is.element=function(a){return"object"==typeof HTMLElement?a instanceof HTMLElement:a&&"object"==typeof a&&null!==a&&1===a.nodeType&&"string"==typeof a.nodeName},a.is.promise=function(b){return a.is.object(b)&&a.is.fn(b.then)&&a.is.fn(b.promise)},a.is.jq=function(b){return a.is.defined(window.jQuery)&&b instanceof jQuery&&b.length>0},a.is.moment=function(b){return a.is.defined(window.moment)&&a.is.object(b)&&a.is["boolean"](b._isAMomentObject)},a.is.emptyObject=function(b){if(!a.is.hash(b))return!1;for(var c in b)if(b.hasOwnProperty(c))return!1;return!0},a.is.emptyArray=function(b){return a.is.array(b)?0===b.length:!0},a.is.emptyString=function(b){return a.is.string(b)?0===b.length:!0}}(FooTable),function(a){a.str={},a.str.contains=function(b,c,d){return a.is.emptyString(b)||a.is.emptyString(c)?!1:c.length<=b.length&&-1!==(d?b.toUpperCase().indexOf(c.toUpperCase()):b.indexOf(c))},a.str.containsExact=function(b,c,d){return a.is.emptyString(b)||a.is.emptyString(c)||c.length>b.length?!1:new RegExp("\\b"+a.str.escapeRegExp(c)+"\\b",d?"i":"").test(b)},a.str.containsWord=function(b,c,d){if(a.is.emptyString(b)||a.is.emptyString(c)||b.length<c.length)return!1;for(var e=b.split(/\W/),f=0,g=e.length;g>f;f++)if(d?e[f].toUpperCase()==c.toUpperCase():e[f]==c)return!0;return!1},a.str.from=function(b,c){return a.is.emptyString(b)?b:a.str.contains(b,c)?b.substring(b.indexOf(c)+1):b},a.str.startsWith=function(b,c){return a.is.emptyString(b)?b==c:b.slice(0,c.length)==c},a.str.toCamelCase=function(b){return a.is.emptyString(b)?b:b.toUppLine truncated
|
|
||||||
return a.index-b.index}),a.resolve(f))},preinit:function(a){var c=this;return c.ft.raise("preinit.ft.columns",[a]).then(function(){return c.parse(a).then(function(d){c.array=d,c.showHeader=b.is["boolean"](a.showHeader)?a.showHeader:c.showHeader})})},init:function(){var a=this;return this.ft.raise("init.ft.columns",[a.array]).then(function(){a.$create()})},destroy:function(){var a=this;this.ft.raise("destroy.ft.columns").then(function(){a._fromHTML||a.$header.remove()})},predraw:function(){var a=this,c=!0;a.visibleColspan=0,a.firstVisibleIndex=0,a.lastVisibleIndex=0,a.hasHidden=!1,b.arr.each(a.array,function(b){b.hidden=!a.ft.breakpoints.visible(b.breakpoints),!b.hidden&&b.visible&&(c&&(a.firstVisibleIndex=b.index,c=!1),a.lastVisibleIndex=b.index,a.visibleColspan++),b.hidden&&(a.hasHidden=!0)}),a.ft.$el.toggleClass("breakpoint",a.hasHidden)},draw:function(){b.arr.each(this.array,function(a){a.$el.css("display",a.hidden||!a.visible?"none":"table-cell")}),!this.showHeader&&b.is.jq(this.$header.parent())&&this.$header.detach()},$create:function(){var c=this;c.$header=b.is.jq(c.$header)?c.$header:a("<tr/>",{"class":"footable-header"}),c.$header.children("th,td").detach(),b.arr.each(c.array,function(a){c.$header.append(a.$el)}),c.showHeader&&!b.is.jq(c.$header.parent())&&c.ft.$el.children("thead").append(c.$header)},get:function(a){return a instanceof b.Column?a:b.is.string(a)?b.arr.first(this.array,function(b){return b.name==a}):b.is.number(a)?b.arr.first(this.array,function(b){return b.index==a}):b.is.fn(a)?b.arr.get(this.array,a):null},ensure:function(a){var c=this,d=[];return b.is.array(a)?(b.arr.each(a,function(a){d.push(c.get(a))}),d):d}}),b.components.register("columns",b.Columns,900)}(jQuery,FooTable),function(a){a.Defaults.prototype.columns=[],a.Defaults.prototype.showHeader=!0}(FooTable),function(a,b){b.Rows=b.Component.extend({construct:function(a){this._super(a,!0),this.o=a.o,this.array=[],this.all=[],this.showToggle=a.o.showToggle,this.toggleSelector=a.o.toggleSelector,this.toggleColumn=a.o.toggleColumn,this.emptyString=a.o.empty,this.expandFirst=a.o.expandFirst,this.expandAll=a.o.expandAll,this.$empty=null,this._fromHTML=b.is.emptyArray(a.o.rows)&&!b.is.promise(a.o.rows)},parse:function(){var c=this;return a.Deferred(function(a){var d=c.ft.$el.children("tbody").children("tr");b.is.array(c.o.rows)&&c.o.rows.length>0?c.parseFinalize(a,c.o.rows):b.is.promise(c.o.rows)?c.o.rows.then(function(b){c.parseFinalize(a,b)},function(b){a.reject(Error("Rows ajax request error: "+b.status+" ("+b.statusText+")"))}):b.is.jq(d)?(c.parseFinalize(a,d),d.detach()):c.parseFinalize(a,[])})},parseFinalize:function(c,d){var e=this,f=a.map(d,function(a){return new b.Row(e.ft,e.ft.columns.array,a)});c.resolve(f)},preinit:function(a){var c=this;return c.ft.raise("preinit.ft.rows",[a]).then(function(){return c.parse().then(function(d){c.all=d,c.array=c.all.slice(0),c.showToggle=b.is["boolean"](a.showToggle)?a.showToggle:c.showToggle,c.toggleSelector=b.is.string(a.toggleSelector)?a.toggleSelector:c.toggleSelector,c.toggleColumn=b.is.string(a.toggleColumn)?a.toggleColumn:c.toggleColumn,"first"!=c.toggleColumn&&"last"!=c.toggleColumn&&(c.toggleColumn="first"),c.emptyString=b.is.string(a.empty)?a.empty:c.emptyString,c.expandFirst=b.is["boolean"](a.expandFirst)?a.expandFirst:c.expandFirst,c.expandAll=b.is["boolean"](a.expandAll)?a.expandAll:c.expandAll})})},init:function(){var a=this;return a.ft.raise("init.ft.rows",[a.all]).then(function(){a.$create()})},destroy:function(){var a=this;this.ft.raise("destroy.ft.rows").then(function(){b.arr.each(a.array,function(b){b.predraw(!a._fromHTML)}),a.all=a.array=[]})},predraw:function(){b.arr.each(this.array,function(a){a.predraw()}),this.array=this.all.slice(0)},$create:function(){this.$empty=a("<tr/>",{"class":"footable-empty"}).append(a("<td/>").text(this.emptyString))},draw:function(){var a=this,c=a.ft.$el.children("tbody"),d=!0;a.array.length>0?(a.$empty.detach(),b.arr.each(a.array,function(b){(a.expandFirst&&d||a.expandAll)&&(b.expanded=!0,d=!1),b.draw(c)})):(a.$empty.children("td").attr("colspan",a.ft.columns.visibleColspan),c.append(a.$empty))},load:function(c,d){var e=this,f=a.map(c,function(a){return new b.Row(e.ft,e.ft.columns.array,a)});b.arr.each(this.array,function(a){a.predraw()}),this.all=(b.is["boolean"](d)?d:!1)?this.all.concat(f):f,this.array=this.all.slice(0),this.ft.draw()},expand:function(){b.arr.each(this.array,function(a){a.expand()})},collapse:function(){b.arr.each(this.array,function(a){a.collapse()})}}),b.components.register("rows",b.Rows,800)}(jQuery,FooTable),function(a){a.Defaults.prototype.rows=[],a.Defaults.prototype.empty="No results",a.Defaults.prototype.showToggle=!0,a.Defaults.prototype.toggleSelector="tr,td,.footable-toggle",a.Defaults.prototype.toggleColumn="first",a.Defaults.prototype.expandFirst=!1,a.Defaults.prototype.expandAll=!1}(FooTable),function(a){a.Table.prototype.loadRows=function(a,b){this.rows.load(a,b)}}(FooTable),function(a){a.Filter=a.ClLine truncated
|
|
||||||
a&&this.$pagination.children("li.footable-page").removeClass("active").filter('li[data-page="'+this.current+'"]').addClass("active")},_setVisible:function(a,b){if(this.limit>0&&this.total>this.limit){if(!this.$pagination.children('li.footable-page[data-page="'+a+'"]').hasClass("visible")){var c=0,d=0;1==b?(d=a>this.total?this.total:a,c=d-this.limit):(c=1>a?0:a-1,d=c+this.limit),0>c&&(c=0,d=this.limit>this.total?this.total:this.limit),d>this.total&&(d=this.total,c=this.total-this.limit<0?0:this.total-this.limit),this.$pagination.children("li.footable-page").removeClass("visible").slice(c,d).addClass("visible")}}else this.$pagination.children("li.footable-page").removeClass("visible").slice(0,this.total).addClass("visible")},_onPageClicked:function(b){if(b.preventDefault(),!a(b.target).closest("li").is(".active,.disabled")){var c=b.data.self,d=a(this).data("page");switch(d){case"first":return void c.first();case"prev":return void c.prev();case"next":return void c.next();case"last":return void c.last();case"prev-limit":return void c.prevPages();case"next-limit":return void c.nextPages();default:return void c._set(d)}}}}),b.components.register("paging",b.Paging,400)}(jQuery,FooTable),function(a){a.Defaults.prototype.paging={enabled:!1,countFormat:"{CP} of {TP}",current:1,limit:5,position:"center",size:10,container:null,strings:{first:"«",prev:"‹",next:"›",last:"»",prevPages:"...",nextPages:"..."}}}(FooTable),function(a){a.Table.prototype.gotoPage=function(b){return this.use(a.Paging)["goto"](b)},a.Table.prototype.nextPage=function(){return this.use(a.Paging).next()},a.Table.prototype.prevPage=function(){return this.use(a.Paging).prev()},a.Table.prototype.firstPage=function(){return this.use(a.Paging).first()},a.Table.prototype.lastPage=function(){return this.use(a.Paging).last()},a.Table.prototype.nextPages=function(){return this.use(a.Paging).nextPages()},a.Table.prototype.prevPages=function(){return this.use(a.Paging).prevPages()},a.Table.prototype.pageSize=function(b){return this.use(a.Paging).pageSize(b)}}(FooTable),function(a,b){b.Editing=b.Component.extend({construct:function(c){this._super(c,c.o.editing.enabled),this.pageToNew=c.o.editing.pageToNew,this.alwaysShow=c.o.editing.alwaysShow,this.column=a.extend(!0,{},c.o.editing.column,{visible:this.alwaysShow}),this.position=c.o.editing.position,this.showText=c.o.editing.showText,this.hideText=c.o.editing.hideText,this.addText=c.o.editing.addText,this.editText=c.o.editing.editText,this.deleteText=c.o.editing.deleteText,this.viewText=c.o.editing.viewText,this.allowAdd=c.o.editing.allowAdd,this.allowEdit=c.o.editing.allowEdit,this.allowDelete=c.o.editing.allowDelete,this.allowView=c.o.editing.allowView,this._$buttons=null,this.callbacks={addRow:b.checkFnValue(this,c.o.editing.addRow),editRow:b.checkFnValue(this,c.o.editing.editRow),deleteRow:b.checkFnValue(this,c.o.editing.deleteRow),viewRow:b.checkFnValue(this,c.o.editing.viewRow)}},preinit:function(c){var d=this;this.ft.raise("preinit.ft.editing",[c]).then(function(){if(d.ft.$el.hasClass("footable-editing")&&(d.enabled=!0),d.enabled=b.is["boolean"](c.editing)?c.editing:d.enabled,d.enabled){if(d.pageToNew=b.is["boolean"](c.editingPageToNew)?c.editingPageToNew:d.pageToNew,d.alwaysShow=b.is["boolean"](c.editingAlwaysShow)?c.editingAlwaysShow:d.alwaysShow,d.position=b.is.string(c.editingPosition)?c.editingPosition:d.position,d.showText=b.is.string(c.editingShowText)?c.editingShowText:d.showText,d.hideText=b.is.string(c.editingHideText)?c.editingHideText:d.hideText,d.addText=b.is.string(c.editingAddText)?c.editingAddText:d.addText,d.editText=b.is.string(c.editingEditText)?c.editingEditText:d.editText,d.deleteText=b.is.string(c.editingDeleteText)?c.editingDeleteText:d.deleteText,d.viewText=b.is.string(c.editingViewText)?c.editingViewText:d.viewText,d.allowAdd=b.is["boolean"](c.editingAllowAdd)?c.editingAllowAdd:d.allowAdd,d.allowEdit=b.is["boolean"](c.editingAllowEdit)?c.editingAllowEdit:d.allowEdit,d.allowDelete=b.is["boolean"](c.editingAllowDelete)?c.editingAllowDelete:d.allowDelete,d.allowView=b.is["boolean"](c.editingAllowView)?c.editingAllowView:d.allowView,d.column=new b.EditingColumn(d.ft,d,a.extend(!0,{},d.column,c.editingColumn,{visible:d.alwaysShow})),d.ft.$el.hasClass("footable-editing-left")&&(d.position="left"),d.ft.$el.hasClass("footable-editing-right")&&(d.position="right"),"right"===d.position)d.column.index=d.ft.columns.array.length;else{d.column.index=0;for(var e=0,f=d.ft.columns.array.length;f>e;e++)d.ft.columns.array[e].index+=1}d.ft.columns.array.push(d.column),d.ft.columns.array.sort(function(a,b){return a.index-b.index}),d.callbacks.addRow=b.checkFnValue(d,c.editingAddRow,d.callbacks.addRow),d.callbacks.editRow=b.checkFnValue(d,c.editingEditRow,d.callbacks.editRow),d.callbacks.deleteRow=b.checkFnValue(d,c.editingDeleteRow,d.callbacks.deleteRow),d.callbacks.viewRow=b.checkFnValue(d,c.editingViewRow,d.callbacks.viewRow)}},function(){d.enabled=!1})},init:function(){vLine truncated
|
|
||||||
@@ -1,323 +1,363 @@
|
|||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
// mailcow alert box generator
|
// mailcow alert box generator
|
||||||
window.mailcow_alert_box = function(message, type) {
|
window.mailcow_alert_box = function(message, type) {
|
||||||
msg = $('<span/>').text(message).text();
|
msg = $('<span/>').text(message).text();
|
||||||
if (type == 'danger' || type == 'info') {
|
if (type == 'danger' || type == 'info') {
|
||||||
auto_hide = 0;
|
auto_hide = 0;
|
||||||
$('#' + localStorage.getItem("add_modal")).modal('show');
|
$('#' + localStorage.getItem("add_modal")).modal('show');
|
||||||
localStorage.removeItem("add_modal");
|
localStorage.removeItem("add_modal");
|
||||||
} else {
|
} else {
|
||||||
auto_hide = 5000;
|
auto_hide = 5000;
|
||||||
}
|
}
|
||||||
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
|
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
|
||||||
}
|
}
|
||||||
|
|
||||||
$(".generate_password").click(function( event ) {
|
$(".generate_password").click(async function( event ) {
|
||||||
event.preventDefault();
|
try {
|
||||||
$('[data-hibp]').trigger('input');
|
var password_policy = await window.fetch("/api/v1/get/passwordpolicy", { method:'GET', cache:'no-cache' });
|
||||||
if (typeof($(this).closest("form").data('pwgen-length')) == "number") {
|
var password_policy = await password_policy.json();
|
||||||
var random_passwd = GPW.pronounceable($(this).closest("form").data('pwgen-length'))
|
random_passwd_length = password_policy.length;
|
||||||
}
|
} catch(err) {
|
||||||
else {
|
var random_passwd_length = 8;
|
||||||
var random_passwd = GPW.pronounceable(8)
|
}
|
||||||
}
|
|
||||||
$(this).closest("form").find('[data-pwgen-field]').attr('type', 'text');
|
event.preventDefault();
|
||||||
$(this).closest("form").find('[data-pwgen-field]').val(random_passwd);
|
$('[data-hibp]').trigger('input');
|
||||||
});
|
if (typeof($(this).closest("form").data('pwgen-length')) == "number") {
|
||||||
function str_rot13(str) {
|
var random_passwd = GPW.pronounceable($(this).closest("form").data('pwgen-length'))
|
||||||
return (str + '').replace(/[a-z]/gi, function(s){
|
}
|
||||||
return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13))
|
else {
|
||||||
})
|
var random_passwd = GPW.pronounceable(random_passwd_length)
|
||||||
}
|
}
|
||||||
$(".rot-enc").html(function(){
|
$(this).closest("form").find('[data-pwgen-field]').attr('type', 'text');
|
||||||
return str_rot13($(this).html())
|
$(this).closest("form").find('[data-pwgen-field]').val(random_passwd);
|
||||||
});
|
});
|
||||||
// https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate
|
function str_rot13(str) {
|
||||||
function shake(div,interval,distance,times) {
|
return (str + '').replace(/[a-z]/gi, function(s){
|
||||||
if(typeof interval === 'undefined') {
|
return String.fromCharCode(s.charCodeAt(0) + (s.toLowerCase() < 'n' ? 13 : -13))
|
||||||
interval = 100;
|
})
|
||||||
}
|
}
|
||||||
if(typeof distance === 'undefined') {
|
$(".rot-enc").html(function(){
|
||||||
distance = 10;
|
return str_rot13($(this).html())
|
||||||
}
|
});
|
||||||
if(typeof times === 'undefined') {
|
// https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate
|
||||||
times = 4;
|
function shake(div,interval,distance,times) {
|
||||||
}
|
if(typeof interval === 'undefined') {
|
||||||
$(div).css('position','relative');
|
interval = 100;
|
||||||
for(var iter=0;iter<(times+1);iter++){
|
}
|
||||||
$(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval);
|
if(typeof distance === 'undefined') {
|
||||||
}
|
distance = 10;
|
||||||
$(div).animate({ left: 0},interval);
|
}
|
||||||
}
|
if(typeof times === 'undefined') {
|
||||||
|
times = 4;
|
||||||
// form cache
|
}
|
||||||
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
|
$(div).css('position','relative');
|
||||||
|
for(var iter=0;iter<(times+1);iter++){
|
||||||
// tooltips
|
$(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval);
|
||||||
$(function () {
|
}
|
||||||
$('[data-toggle="tooltip"]').tooltip()
|
$(div).animate({ left: 0},interval);
|
||||||
});
|
}
|
||||||
|
|
||||||
// remember last navigation pill
|
// form cache
|
||||||
(function () {
|
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
|
||||||
'use strict';
|
|
||||||
if ($('a[data-toggle="tab"]').length) {
|
// tooltips
|
||||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
$(function () {
|
||||||
if ($(this).data('dont-remember') == 1) {
|
$('[data-bs-toggle="tooltip"]').tooltip()
|
||||||
return true;
|
});
|
||||||
}
|
|
||||||
var id = $(this).parents('[role="tablist"]').attr('id');
|
// remember last navigation pill
|
||||||
var key = 'lastTag';
|
(function () {
|
||||||
if (id) {
|
'use strict';
|
||||||
key += ':' + id;
|
// remember desktop tabs
|
||||||
}
|
$('button[data-bs-toggle="tab"]').on('click', function (e) {
|
||||||
localStorage.setItem(key, $(e.target).attr('href'));
|
if ($(this).data('dont-remember') == 1) {
|
||||||
});
|
return true;
|
||||||
$('[role="tablist"]').each(function (idx, elem) {
|
}
|
||||||
var id = $(elem).attr('id');
|
var id = $(this).parents('[role="tablist"]').attr('id');
|
||||||
var key = 'lastTag';
|
var key = 'lastTag';
|
||||||
if (id) {
|
if (id) {
|
||||||
key += ':' + id;
|
key += ':' + id;
|
||||||
}
|
}
|
||||||
var lastTab = localStorage.getItem(key);
|
|
||||||
if (lastTab) {
|
var tab_id = $(e.target).attr('data-bs-target').substring(1);
|
||||||
$('[href="' + lastTab + '"]').tab('show');
|
localStorage.setItem(key, tab_id);
|
||||||
}
|
});
|
||||||
});
|
// remember mobile tabs
|
||||||
}
|
$('button[data-bs-target^="#collapse-tab-"]').on('click', function (e) {
|
||||||
})();
|
// only remember tab if its being opened
|
||||||
|
if ($(this).hasClass('collapsed')) return false;
|
||||||
// IE fix to hide scrollbars when table body is empty
|
var tab_id = $(this).closest('div[role="tabpanel"]').attr('id');
|
||||||
$('tbody').filter(function (index) {
|
|
||||||
return $(this).children().length < 1;
|
if ($(this).data('dont-remember') == 1) {
|
||||||
}).remove();
|
return true;
|
||||||
|
}
|
||||||
// selectpicker
|
var id = $(this).parents('[role="tablist"]').attr('id');;
|
||||||
$('select').selectpicker({
|
var key = 'lastTag';
|
||||||
'styleBase': 'btn btn-xs-lg',
|
if (id) {
|
||||||
'noneSelectedText': lang_footer.nothing_selected
|
key += ':' + id;
|
||||||
});
|
}
|
||||||
|
|
||||||
// haveibeenpwned and passwd policy
|
localStorage.setItem(key, tab_id);
|
||||||
$.ajax({
|
});
|
||||||
url: '/api/v1/get/passwordpolicy/html',
|
// open last tab
|
||||||
type: 'GET',
|
$('[role="tablist"]').each(function (idx, elem) {
|
||||||
success: function(res) {
|
var id = $(elem).attr('id');
|
||||||
$(".hibp-out").after(res);
|
var key = 'lastTag';
|
||||||
}
|
if (id) {
|
||||||
});
|
key += ':' + id;
|
||||||
$('[data-hibp]').after('<p class="small haveibeenpwned"><i class="bi bi-shield-fill-exclamation"></i> ' + lang_footer.hibp_check + '</p><span class="hibp-out"></span>');
|
}
|
||||||
$('[data-hibp]').on('input', function() {
|
var lastTab = localStorage.getItem(key);
|
||||||
out_field = $(this).next('.haveibeenpwned').next('.hibp-out').text('').attr('class', 'hibp-out');
|
if (lastTab) {
|
||||||
});
|
$('[data-bs-target="#' + lastTab + '"]').click();
|
||||||
$('.haveibeenpwned:not(.task-running)').on('click', function() {
|
var tab = $('[id^="' + lastTab + '"]');
|
||||||
var hibp_field = $(this)
|
$(tab).find('.card-body.collapse').collapse('show');
|
||||||
$(hibp_field).addClass('task-running');
|
}
|
||||||
var hibp_result = $(hibp_field).next('.hibp-out')
|
});
|
||||||
var password_field = $(this).prev('[data-hibp]')
|
})();
|
||||||
if ($(password_field).val() == '') {
|
|
||||||
shake(password_field);
|
// IE fix to hide scrollbars when table body is empty
|
||||||
}
|
$('tbody').filter(function (index) {
|
||||||
else {
|
return $(this).children().length < 1;
|
||||||
$(hibp_result).attr('class', 'hibp-out label label-info');
|
}).remove();
|
||||||
$(hibp_result).text(lang_footer.loading);
|
|
||||||
var password_digest = $.sha1($(password_field).val())
|
// selectpicker
|
||||||
var digest_five = password_digest.substring(0, 5).toUpperCase();
|
$('select').selectpicker({
|
||||||
var queryURL = "https://api.pwnedpasswords.com/range/" + digest_five;
|
'styleBase': 'btn btn-xs-lg',
|
||||||
var compl_digest = password_digest.substring(5, 41).toUpperCase();
|
'noneSelectedText': lang_footer.nothing_selected
|
||||||
$.ajax({
|
});
|
||||||
url: queryURL,
|
|
||||||
type: 'GET',
|
// haveibeenpwned and passwd policy
|
||||||
success: function(res) {
|
$.ajax({
|
||||||
if (res.search(compl_digest) > -1){
|
url: '/api/v1/get/passwordpolicy/html',
|
||||||
$(hibp_result).removeClass('label label-info').addClass('label label-danger');
|
type: 'GET',
|
||||||
$(hibp_result).text(lang_footer.hibp_nok)
|
success: function(res) {
|
||||||
} else {
|
$(".hibp-out").after(res);
|
||||||
$(hibp_result).removeClass('label label-info').addClass('label label-success');
|
}
|
||||||
$(hibp_result).text(lang_footer.hibp_ok)
|
});
|
||||||
}
|
$('[data-hibp]').after('<p class="small haveibeenpwned"><i class="bi bi-shield-fill-exclamation"></i> ' + lang_footer.hibp_check + '</p><span class="hibp-out"></span>');
|
||||||
$(hibp_field).removeClass('task-running');
|
$('[data-hibp]').on('input', function() {
|
||||||
},
|
out_field = $(this).next('.haveibeenpwned').next('.hibp-out').text('').attr('class', 'hibp-out');
|
||||||
error: function(xhr, status, error) {
|
});
|
||||||
$(hibp_result).removeClass('label label-info').addClass('label label-warning');
|
$('.haveibeenpwned:not(.task-running)').on('click', function() {
|
||||||
$(hibp_result).text('API error: ' + xhr.responseText)
|
var hibp_field = $(this)
|
||||||
$(hibp_field).removeClass('task-running');
|
$(hibp_field).addClass('task-running');
|
||||||
}
|
var hibp_result = $(hibp_field).next('.hibp-out')
|
||||||
});
|
var password_field = $(this).prev('[data-hibp]')
|
||||||
}
|
if ($(password_field).val() == '') {
|
||||||
});
|
shake(password_field);
|
||||||
|
}
|
||||||
// Disable disallowed inputs
|
else {
|
||||||
$('[data-acl="0"]').each(function(event){
|
$(hibp_result).attr('class', 'hibp-out badge fs-5 bg-info');
|
||||||
if ($(this).is("a")) {
|
$(hibp_result).text(lang_footer.loading);
|
||||||
$(this).removeAttr("data-toggle");
|
var password_digest = $.sha1($(password_field).val())
|
||||||
$(this).removeAttr("data-target");
|
var digest_five = password_digest.substring(0, 5).toUpperCase();
|
||||||
$(this).removeAttr("data-action");
|
var queryURL = "https://api.pwnedpasswords.com/range/" + digest_five;
|
||||||
$(this).click(function(event) {
|
var compl_digest = password_digest.substring(5, 41).toUpperCase();
|
||||||
event.preventDefault();
|
$.ajax({
|
||||||
});
|
url: queryURL,
|
||||||
}
|
type: 'GET',
|
||||||
if ($(this).is("select")) {
|
success: function(res) {
|
||||||
$(this).selectpicker('destroy');
|
if (res.search(compl_digest) > -1){
|
||||||
$(this).replaceWith(function() {
|
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-danger');
|
||||||
return '<label class="control-label"><b>' + this.innerText + '</b></label>';
|
$(hibp_result).text(lang_footer.hibp_nok)
|
||||||
});
|
} else {
|
||||||
}
|
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-success');
|
||||||
if ($(this).hasClass('btn-group')) {
|
$(hibp_result).text(lang_footer.hibp_ok)
|
||||||
$(this).find('a').each(function(){
|
}
|
||||||
$(this).removeClass('dropdown-toggle')
|
$(hibp_field).removeClass('task-running');
|
||||||
.removeAttr('data-toggle')
|
},
|
||||||
.removeAttr('data-target')
|
error: function(xhr, status, error) {
|
||||||
.removeAttr('data-action')
|
$(hibp_result).removeClass('badge fs-5 bg-info').addClass('badge fs-5 bg-warning');
|
||||||
.removeAttr('id')
|
$(hibp_result).text('API error: ' + xhr.responseText)
|
||||||
.attr("disabled", true);
|
$(hibp_field).removeClass('task-running');
|
||||||
$(this).click(function(event) {
|
}
|
||||||
event.preventDefault();
|
});
|
||||||
return;
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
$(this).find('button').each(function() {
|
// Disable disallowed inputs
|
||||||
$(this).attr("disabled", true);
|
$('[data-acl="0"]').each(function(event){
|
||||||
});
|
if ($(this).is("a")) {
|
||||||
} else if ($(this).hasClass('input-group')) {
|
$(this).removeAttr("data-bs-toggle");
|
||||||
$(this).find('input').each(function() {
|
$(this).removeAttr("data-bs-target");
|
||||||
$(this).removeClass('dropdown-toggle')
|
$(this).removeAttr("data-action");
|
||||||
.removeAttr('data-toggle')
|
$(this).click(function(event) {
|
||||||
.attr("disabled", true);
|
event.preventDefault();
|
||||||
$(this).click(function(event) {
|
});
|
||||||
event.preventDefault();
|
}
|
||||||
});
|
if ($(this).is("select")) {
|
||||||
});
|
$(this).selectpicker('destroy');
|
||||||
$(this).find('button').each(function() {
|
$(this).replaceWith(function() {
|
||||||
$(this).attr("disabled", true);
|
return '<label class="control-label"><b>' + this.innerText + '</b></label>';
|
||||||
});
|
});
|
||||||
} else if ($(this).hasClass('form-group')) {
|
}
|
||||||
$(this).find('input').each(function() {
|
if ($(this).hasClass('btn-group')) {
|
||||||
$(this).attr("disabled", true);
|
$(this).find('a').each(function(){
|
||||||
});
|
$(this).removeClass('dropdown-toggle')
|
||||||
} else if ($(this).hasClass('btn')) {
|
.removeAttr('data-bs-toggle')
|
||||||
$(this).attr("disabled", true);
|
.removeAttr('data-bs-target')
|
||||||
} else if ($(this).attr('data-provide') == 'slider') {
|
.removeAttr('data-action')
|
||||||
$(this).attr('disabled', true);
|
.removeAttr('id')
|
||||||
} else if ($(this).is(':checkbox')) {
|
.attr("disabled", true);
|
||||||
$(this).attr("disabled", true);
|
$(this).click(function(event) {
|
||||||
}
|
event.preventDefault();
|
||||||
$(this).data("toggle", "tooltip");
|
return;
|
||||||
$(this).attr("title", lang_acl.prohibited);
|
});
|
||||||
$(this).tooltip();
|
});
|
||||||
});
|
$(this).find('button').each(function() {
|
||||||
|
$(this).attr("disabled", true);
|
||||||
// disable submit after submitting form (not API driven buttons)
|
});
|
||||||
$('form').submit(function() {
|
} else if ($(this).hasClass('input-group')) {
|
||||||
if ($('form button[type="submit"]').data('submitted') == '1') {
|
$(this).find('input').each(function() {
|
||||||
return false;
|
$(this).removeClass('dropdown-toggle')
|
||||||
} else {
|
.removeAttr('data-bs-toggle')
|
||||||
$(this).find('button[type="submit"]').first().text(lang_footer.loading);
|
.attr("disabled", true);
|
||||||
$('form button[type="submit"]').attr('data-submitted', '1');
|
$(this).click(function(event) {
|
||||||
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
|
event.preventDefault();
|
||||||
$(document).on("keydown", disableF5);
|
});
|
||||||
}
|
});
|
||||||
});
|
$(this).find('button').each(function() {
|
||||||
// Textarea line numbers
|
$(this).attr("disabled", true);
|
||||||
$(".textarea-code").numberedtextarea({allowTabChar: true});
|
});
|
||||||
// trigger container restart
|
} else if ($(this).hasClass('form-group')) {
|
||||||
$('#RestartContainer').on('show.bs.modal', function(e) {
|
$(this).find('input').each(function() {
|
||||||
var container = $(e.relatedTarget).data('container');
|
$(this).attr("disabled", true);
|
||||||
$('#containerName').text(container);
|
});
|
||||||
$('#triggerRestartContainer').click(function(){
|
} else if ($(this).hasClass('btn')) {
|
||||||
$(this).prop("disabled",true);
|
$(this).attr("disabled", true);
|
||||||
$(this).html('<i class="bi bi-arrow-repeat icon-spin"></i> ');
|
} else if ($(this).attr('data-provide') == 'slider') {
|
||||||
$('#statusTriggerRestartContainer').html(lang_footer.restarting_container);
|
$(this).attr('disabled', true);
|
||||||
$.ajax({
|
} else if ($(this).is(':checkbox')) {
|
||||||
method: 'get',
|
$(this).attr("disabled", true);
|
||||||
url: '/inc/ajax/container_ctrl.php',
|
}
|
||||||
timeout: docker_timeout,
|
$(this).data("toggle", "tooltip");
|
||||||
data: {
|
$(this).attr("title", lang_acl.prohibited);
|
||||||
'service': container,
|
$(this).tooltip();
|
||||||
'action': 'restart'
|
});
|
||||||
}
|
|
||||||
})
|
// disable submit after submitting form (not API driven buttons)
|
||||||
.always( function (data, status) {
|
$('form').submit(function() {
|
||||||
$('#statusTriggerRestartContainer').append(data);
|
if ($('form button[type="submit"]').data('submitted') == '1') {
|
||||||
var htmlResponse = $.parseHTML(data)
|
return false;
|
||||||
if ($(htmlResponse).find('span').hasClass('text-success')) {
|
} else {
|
||||||
$('#triggerRestartContainer').html('<i class="bi bi-check-lg"></i> ');
|
$(this).find('button[type="submit"]').first().text(lang_footer.loading);
|
||||||
setTimeout(function(){
|
$('form button[type="submit"]').attr('data-submitted', '1');
|
||||||
$('#RestartContainer').modal('toggle');
|
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
|
||||||
window.location = window.location.href.split("#")[0];
|
$(document).on("keydown", disableF5);
|
||||||
}, 1200);
|
}
|
||||||
} else {
|
});
|
||||||
$('#triggerRestartContainer').html('<i class="bi bi-slash-lg"></i> ');
|
// Textarea line numbers
|
||||||
}
|
$(".textarea-code").numberedtextarea({allowTabChar: true});
|
||||||
})
|
// trigger container restart
|
||||||
});
|
$('#RestartContainer').on('show.bs.modal', function(e) {
|
||||||
})
|
var container = $(e.relatedTarget).data('container');
|
||||||
|
$('#containerName').text(container);
|
||||||
// responsive tabs
|
$('#triggerRestartContainer').click(function(){
|
||||||
$('.responsive-tabs').tabCollapse({
|
$(this).prop("disabled",true);
|
||||||
tabsClass: 'hidden-xs',
|
$(this).html('<div class="spinner-border text-white" role="status"><span class="visually-hidden">Loading...</span></div>');
|
||||||
accordionClass: 'js-tabcollapse-panel-group visible-xs'
|
$('#statusTriggerRestartContainer').html(lang_footer.restarting_container);
|
||||||
});
|
$.ajax({
|
||||||
$(document).on("shown.bs.collapse shown.bs.tab", function (e) {
|
method: 'get',
|
||||||
var target = $(e.target);
|
url: '/inc/ajax/container_ctrl.php',
|
||||||
if($(window).width() <= 767) {
|
timeout: docker_timeout,
|
||||||
var offset = target.offset().top - 112;
|
data: {
|
||||||
$("html, body").stop().animate({
|
'service': container,
|
||||||
scrollTop: offset
|
'action': 'restart'
|
||||||
}, 100);
|
}
|
||||||
}
|
})
|
||||||
if(target.hasClass('panel-collapse')){
|
.always( function (data, status) {
|
||||||
var id = e.target.id.replace(/-collapse$/g, '');
|
$('#statusTriggerRestartContainer').append(data);
|
||||||
if(id){
|
var htmlResponse = $.parseHTML(data)
|
||||||
localStorage.setItem('lastTag', '#'+id);
|
if ($(htmlResponse).find('span').hasClass('text-success')) {
|
||||||
}
|
$('#triggerRestartContainer').html('<i class="bi bi-check-lg"></i> ');
|
||||||
}
|
setTimeout(function(){
|
||||||
});
|
$('#RestartContainer').modal('toggle');
|
||||||
|
window.location = window.location.href.split("#")[0];
|
||||||
// tag boxes
|
}, 1200);
|
||||||
$('.tag-box .tag-add').click(function(){
|
} else {
|
||||||
addTag(this);
|
$('#triggerRestartContainer').html('<i class="bi bi-slash-lg"></i> ');
|
||||||
});
|
}
|
||||||
$(".tag-box .tag-input").keydown(function (e) {
|
})
|
||||||
if (e.which == 13){
|
});
|
||||||
e.preventDefault();
|
})
|
||||||
addTag(this);
|
|
||||||
}
|
// Jquery Datatables, enable responsive plugin
|
||||||
});
|
$.extend($.fn.dataTable.defaults, {
|
||||||
function addTag(tagAddElem){
|
responsive: true
|
||||||
var tagboxElem = $(tagAddElem).parent();
|
});
|
||||||
var tagInputElem = $(tagboxElem).find(".tag-input")[0];
|
// disable default datatable click listener
|
||||||
var tagValuesElem = $(tagboxElem).find(".tag-values")[0];
|
$(document).off('click', 'tbody>tr');
|
||||||
|
|
||||||
var tag = escapeHtml($(tagInputElem).val());
|
// tag boxes
|
||||||
if (!tag) return;
|
$('.tag-box .tag-add').click(function(){
|
||||||
var value_tags = [];
|
addTag(this);
|
||||||
try {
|
});
|
||||||
value_tags = JSON.parse($(tagValuesElem).val());
|
$(".tag-box .tag-input").keydown(function (e) {
|
||||||
} catch {}
|
if (e.which == 13){
|
||||||
if (!Array.isArray(value_tags)) value_tags = [];
|
e.preventDefault();
|
||||||
if (value_tags.includes(tag)) return;
|
addTag(this);
|
||||||
|
}
|
||||||
$('<span class="badge badge-primary tag-badge btn-badge"><i class="bi bi-tag-fill"></i> ' + tag + '</span>').insertBefore('.tag-input').click(function(){
|
});
|
||||||
var del_tag = unescapeHtml($(this).text());
|
|
||||||
var del_tags = [];
|
// Dark Mode Loader
|
||||||
try {
|
$('#dark-mode-toggle').click(toggleDarkMode);
|
||||||
del_tags = JSON.parse($(tagValuesElem).val());
|
if ($('#dark-mode-theme').length) {
|
||||||
} catch {}
|
$('#dark-mode-toggle').prop('checked', true);
|
||||||
if (Array.isArray(del_tags)){
|
if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png');
|
||||||
del_tags.splice(del_tags.indexOf(del_tag), 1);
|
if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png');
|
||||||
$(tagValuesElem).val(JSON.stringify(del_tags));
|
}
|
||||||
}
|
function toggleDarkMode(){
|
||||||
$(this).remove();
|
if($('#dark-mode-theme').length){
|
||||||
});
|
$('#dark-mode-theme').remove();
|
||||||
|
$('#dark-mode-toggle').prop('checked', false);
|
||||||
value_tags.push($(tagInputElem).val());
|
if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png');
|
||||||
$(tagValuesElem).val(JSON.stringify(value_tags));
|
if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png');
|
||||||
$(tagInputElem).val('');
|
localStorage.setItem('theme', 'light');
|
||||||
}
|
}else{
|
||||||
});
|
$('head').append('<link id="dark-mode-theme" rel="stylesheet" type="text/css" href="/css/themes/mailcow-darkmode.css">');
|
||||||
|
$('#dark-mode-toggle').prop('checked', true);
|
||||||
|
if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png');
|
||||||
// http://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
|
if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png');
|
||||||
function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
|
localStorage.setItem('theme', 'dark');
|
||||||
function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/24816/escaping-html-strings-with-jquery
|
||||||
|
function escapeHtml(n){var entityMap={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="}; return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
|
||||||
|
function unescapeHtml(t){var n={"&":"&","<":"<",">":">",""":'"',"'":"'","/":"/","`":"`","=":"="};return String(t).replace(/&|<|>|"|'|/|`|=/g,function(t){return n[t]})}
|
||||||
|
|
||||||
|
function addTag(tagAddElem, tag = null){
|
||||||
|
var tagboxElem = $(tagAddElem).parent();
|
||||||
|
var tagInputElem = $(tagboxElem).find(".tag-input")[0];
|
||||||
|
var tagValuesElem = $(tagboxElem).find(".tag-values")[0];
|
||||||
|
|
||||||
|
if (!tag)
|
||||||
|
tag = $(tagInputElem).val();
|
||||||
|
if (!tag) return;
|
||||||
|
var value_tags = [];
|
||||||
|
try {
|
||||||
|
value_tags = JSON.parse($(tagValuesElem).val());
|
||||||
|
} catch {}
|
||||||
|
if (!Array.isArray(value_tags)) value_tags = [];
|
||||||
|
if (value_tags.includes(tag)) return;
|
||||||
|
|
||||||
|
$('<span class="badge bg-primary tag-badge btn-badge"><i class="bi bi-tag-fill"></i> ' + escapeHtml(tag) + '</span>').insertBefore('.tag-input').click(function(){
|
||||||
|
var del_tag = unescapeHtml($(this).text());
|
||||||
|
var del_tags = [];
|
||||||
|
try {
|
||||||
|
del_tags = JSON.parse($(tagValuesElem).val());
|
||||||
|
} catch {}
|
||||||
|
if (Array.isArray(del_tags)){
|
||||||
|
del_tags.splice(del_tags.indexOf(del_tag), 1);
|
||||||
|
$(tagValuesElem).val(JSON.stringify(del_tags));
|
||||||
|
}
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
value_tags.push(tag);
|
||||||
|
$(tagValuesElem).val(JSON.stringify(value_tags));
|
||||||
|
$(tagInputElem).val('');
|
||||||
|
}
|
||||||
+457
-236
@@ -53,237 +53,459 @@ jQuery(function($){
|
|||||||
$("#show_rspamd_global_filters").click(function() {
|
$("#show_rspamd_global_filters").click(function() {
|
||||||
$.get("inc/ajax/show_rspamd_global_filters.php");
|
$.get("inc/ajax/show_rspamd_global_filters.php");
|
||||||
$("#confirm_show_rspamd_global_filters").hide();
|
$("#confirm_show_rspamd_global_filters").hide();
|
||||||
$("#rspamd_global_filters").removeClass("hidden");
|
$("#rspamd_global_filters").removeClass("d-none");
|
||||||
});
|
});
|
||||||
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
$("#super_delete").click(function() { return confirm(lang.queue_ays); });
|
||||||
|
|
||||||
$(".refresh_table").on('click', function(e) {
|
$(".refresh_table").on('click', function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var table_name = $(this).data('table');
|
var table_name = $(this).data('table');
|
||||||
$('#' + table_name).find("tr.footable-empty").remove();
|
$('#' + table_name).DataTable().ajax.reload();
|
||||||
draw_table = $(this).data('draw');
|
|
||||||
eval(draw_table + '()');
|
|
||||||
});
|
});
|
||||||
function table_admin_ready(ft, name) {
|
|
||||||
heading = ft.$el.parents('.panel').find('.panel-heading')
|
|
||||||
var ft_paging = ft.use(FooTable.Paging)
|
|
||||||
$(heading).children('.table-lines').text(function(){
|
|
||||||
return ft_paging.totalRows;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function draw_domain_admins() {
|
function draw_domain_admins() {
|
||||||
ft_domainadmins = FooTable.init('#domainadminstable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#domainadminstable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#domainadminstable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
|
return;
|
||||||
{"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
|
}
|
||||||
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
|
||||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
$('#domainadminstable').DataTable({
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
responsive: true,
|
||||||
],
|
processing: true,
|
||||||
"rows": $.ajax({
|
serverSide: false,
|
||||||
dataType: 'json',
|
stateSave: true,
|
||||||
url: '/api/v1/get/domain-admin/all',
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
jsonp: false,
|
"tr" +
|
||||||
error: function () {
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
console.log('Cannot draw domain admin table');
|
language: lang_datatables,
|
||||||
},
|
ajax: {
|
||||||
success: function (data) {
|
type: "GET",
|
||||||
|
url: "/api/v1/get/domain-admin/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'domainadminstable');
|
return process_table_data(data, 'domainadminstable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"state": {"enabled": true},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"filtering": {"enabled": true,"delay": 1200,"position": "left","connectors": false,"placeholder": lang.filter_table},
|
title: '',
|
||||||
"sorting": {"enabled": true},
|
data: null,
|
||||||
"toggleSelector": "table tbody span.footable-toggle"
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
data: 'chkbox',
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.username,
|
||||||
|
data: 'username',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.admin_domains,
|
||||||
|
data: 'selected_domains',
|
||||||
|
defaultContent: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "TFA",
|
||||||
|
data: 'tfa_active',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function (data, type) {
|
||||||
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.active,
|
||||||
|
data: 'active',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function (data, type) {
|
||||||
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
],
|
||||||
|
initComplete: function(settings, json){
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function draw_oauth2_clients() {
|
function draw_oauth2_clients() {
|
||||||
ft_oauth2clientstable = FooTable.init('#oauth2clientstable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#oauth2clientstable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#oauth2clientstable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
return;
|
||||||
{"name":"client_id","type":"text","title":lang.oauth2_client_id,"style":{"width":"200px"}},
|
}
|
||||||
{"name":"client_secret","title":lang.oauth2_client_secret,"breakpoints":"xs sm md","style":{"width":"200px"}},
|
|
||||||
{"name":"redirect_uri","title":lang.oauth2_redirect_uri, "type": "text"},
|
$('#oauth2clientstable').DataTable({
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
responsive: true,
|
||||||
],
|
processing: true,
|
||||||
"rows": $.ajax({
|
serverSide: false,
|
||||||
dataType: 'json',
|
stateSave: true,
|
||||||
url: '/api/v1/get/oauth2-client/all',
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
jsonp: false,
|
"tr" +
|
||||||
error: function () {
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
console.log('Cannot draw oauth2 clients table');
|
language: lang_datatables,
|
||||||
},
|
ajax: {
|
||||||
success: function (data) {
|
type: "GET",
|
||||||
|
url: "/api/v1/get/oauth2-client/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'oauth2clientstable');
|
return process_table_data(data, 'oauth2clientstable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"sorting": {"enabled": true},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"toggleSelector": "table tbody span.footable-toggle"
|
title: '',
|
||||||
|
data: null,
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
data: 'chkbox',
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
data: 'id',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.oauth2_client_id,
|
||||||
|
data: 'client_id',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.oauth2_client_secret,
|
||||||
|
data: 'client_secret',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.oauth2_redirect_uri,
|
||||||
|
data: 'redirect_uri',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function draw_admins() {
|
function draw_admins() {
|
||||||
ft_admins = FooTable.init('#adminstable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#adminstable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#adminstable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"sorted": true,"name":"usr","title":lang.username,"style":{"width":"250px"}},
|
return;
|
||||||
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
}
|
||||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
$('#adminstable').DataTable({
|
||||||
],
|
responsive: true,
|
||||||
"rows": $.ajax({
|
processing: true,
|
||||||
dataType: 'json',
|
serverSide: false,
|
||||||
url: '/api/v1/get/admin/all',
|
stateSave: true,
|
||||||
jsonp: false,
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
error: function () {
|
"tr" +
|
||||||
console.log('Cannot draw admin table');
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
},
|
language: lang_datatables,
|
||||||
success: function (data) {
|
ajax: {
|
||||||
|
type: "GET",
|
||||||
|
url: "/api/v1/get/admin/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'adminstable');
|
return process_table_data(data, 'adminstable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"filtering": {"enabled": false},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"state": {"enabled": true},
|
title: '',
|
||||||
"sorting": {"enabled": true},
|
data: null,
|
||||||
"toggleSelector": "table tbody span.footable-toggle"
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
data: 'chkbox',
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.username,
|
||||||
|
data: 'username',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "TFA",
|
||||||
|
data: 'tfa_active',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function (data, type) {
|
||||||
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.active,
|
||||||
|
data: 'active',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function (data, type) {
|
||||||
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
defaultContent: '',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right'
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function draw_fwd_hosts() {
|
function draw_fwd_hosts() {
|
||||||
ft_forwardinghoststable = FooTable.init('#forwardinghoststable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#forwardinghoststable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#forwardinghoststable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
|
return;
|
||||||
{"name":"source","title":lang.source,"breakpoints":"xs sm"},
|
}
|
||||||
{"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 'yes'==value?'<i class="bi bi-x-lg"></i>':'no'==value&&'<i class="bi bi-check-lg"></i>';}},
|
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
$('#forwardinghoststable').DataTable({
|
||||||
],
|
responsive: true,
|
||||||
"rows": $.ajax({
|
processing: true,
|
||||||
dataType: 'json',
|
serverSide: false,
|
||||||
url: '/api/v1/get/fwdhost/all',
|
stateSave: true,
|
||||||
jsonp: false,
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
error: function () {
|
"tr" +
|
||||||
console.log('Cannot draw forwarding hosts table');
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
},
|
language: lang_datatables,
|
||||||
success: function (data) {
|
ajax: {
|
||||||
|
type: "GET",
|
||||||
|
url: "/api/v1/get/fwdhost/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'forwardinghoststable');
|
return process_table_data(data, 'forwardinghoststable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"sorting": {"enabled": true},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"toggleSelector": "table tbody span.footable-toggle"
|
title: '',
|
||||||
|
data: null,
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
data: 'chkbox',
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.host,
|
||||||
|
data: 'host',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.source,
|
||||||
|
data: 'source',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.spamfilter,
|
||||||
|
data: 'keep_spam',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function(data, type){
|
||||||
|
return 'yes'==data?'<i class="bi bi-x-lg"></i>':'no'==data&&'<i class="bi bi-check-lg"></i>';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function draw_relayhosts() {
|
function draw_relayhosts() {
|
||||||
ft_relayhoststable = FooTable.init('#relayhoststable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#relayhoststable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#relayhoststable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
return;
|
||||||
{"name":"hostname","type":"text","title":lang.host,"style":{"width":"250px"}},
|
}
|
||||||
{"name":"username","title":lang.username,"breakpoints":"xs sm"},
|
|
||||||
{"name":"in_use_by","title":lang.in_use_by,"style":{"min-width":"200px","width":"200px"}, "type": "text","breakpoints":"xs sm"},
|
$('#relayhoststable').DataTable({
|
||||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
responsive: true,
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
processing: true,
|
||||||
],
|
serverSide: false,
|
||||||
"rows": $.ajax({
|
stateSave: true,
|
||||||
dataType: 'json',
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
url: '/api/v1/get/relayhost/all',
|
"tr" +
|
||||||
jsonp: false,
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
error: function () {
|
language: lang_datatables,
|
||||||
console.log('Cannot draw forwarding hosts table');
|
ajax: {
|
||||||
},
|
type: "GET",
|
||||||
success: function (data) {
|
url: "/api/v1/get/relayhost/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'relayhoststable');
|
return process_table_data(data, 'relayhoststable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"sorting": {"enabled": true},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"toggleSelector": "table tbody span.footable-toggle"
|
title: '',
|
||||||
|
data: null,
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '',
|
||||||
|
data: 'chkbox',
|
||||||
|
searchable: false,
|
||||||
|
orderable: false,
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ID',
|
||||||
|
data: 'id',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.host,
|
||||||
|
data: 'hostname',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.username,
|
||||||
|
data: 'username',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.in_use_by,
|
||||||
|
data: 'in_use_by',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.active,
|
||||||
|
data: 'active',
|
||||||
|
defaultContent: '',
|
||||||
|
render: function (data, type) {
|
||||||
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function draw_transport_maps() {
|
function draw_transport_maps() {
|
||||||
ft_transportstable = FooTable.init('#transportstable', {
|
// just recalc width if instance already exists
|
||||||
"columns": [
|
if ($.fn.DataTable.isDataTable('#transportstable') ) {
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
$('#transportstable').DataTable().columns.adjust().responsive.recalc();
|
||||||
{"name":"id","type":"text","title":"ID","style":{"width":"50px"}},
|
return;
|
||||||
{"name":"destination","type":"text","title":lang.destination,"style":{"min-width":"300px","width":"300px"}},
|
}
|
||||||
{"name":"nexthop","type":"text","title":lang.nexthop,"style":{"min-width":"200px","width":"200px"}},
|
|
||||||
{"name":"username","title":lang.username,"breakpoints":"xs sm"},
|
$('#transportstable').DataTable({
|
||||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
|
responsive: true,
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","min-width":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
processing: true,
|
||||||
],
|
serverSide: false,
|
||||||
"rows": $.ajax({
|
stateSave: true,
|
||||||
dataType: 'json',
|
dom: "<'row'<'col-sm-12 col-md-6'f><'col-sm-12 col-md-6'l>>" +
|
||||||
url: '/api/v1/get/transport/all',
|
"tr" +
|
||||||
jsonp: false,
|
"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
|
||||||
error: function () {
|
language: lang_datatables,
|
||||||
console.log('Cannot draw transports table');
|
ajax: {
|
||||||
},
|
type: "GET",
|
||||||
success: function (data) {
|
url: "/api/v1/get/transport/all",
|
||||||
|
dataSrc: function(data){
|
||||||
return process_table_data(data, 'transportstable');
|
return process_table_data(data, 'transportstable');
|
||||||
}
|
}
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
columns: [
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
{
|
||||||
"sorting": {"enabled": true},
|
// placeholder, so checkbox will not block child row toggle
|
||||||
"toggleSelector": "table tbody span.footable-toggle",
|
title: '',
|
||||||
"on": {
|
data: null,
|
||||||
"ready.ft.table": function(e, ft){
|
searchable: false,
|
||||||
$('.mx-info').tooltip();
|
orderable: false,
|
||||||
}
|
defaultContent: ''
|
||||||
}
|
},
|
||||||
});
|
{
|
||||||
}
|
title: '',
|
||||||
function draw_queue() {
|
data: 'chkbox',
|
||||||
ft_queuetable = FooTable.init('#queuetable', {
|
searchable: false,
|
||||||
"columns": [
|
orderable: false,
|
||||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
defaultContent: ''
|
||||||
{"name":"queue_id","type":"text","title":"QID","style":{"width":"50px"}},
|
},
|
||||||
{"name":"queue_name","type":"text","title":"Queue","style":{"width":"120px"}},
|
{
|
||||||
{"name":"arrival_time","sorted": true,"direction": "DESC","formatter":function unix_time_format(tm) { var date = new Date(tm ? tm * 1000 : 0); return date.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});},"title":lang.arrival_time,"style":{"width":"170px"}},
|
title: 'ID',
|
||||||
{"name":"message_size","style":{"whiteSpace":"nowrap"},"title":lang.message_size,"formatter": function(value){
|
data: 'id',
|
||||||
return humanFileSize(value);
|
defaultContent: ''
|
||||||
}},
|
},
|
||||||
{"name":"sender","title":lang.sender, "type": "text","breakpoints":"xs sm"},
|
{
|
||||||
{"name":"recipients","title":lang.recipients, "type": "text","style":{"word-break":"break-all","min-width":"300px"},"breakpoints":"xs sm md"},
|
title: lang.destination,
|
||||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
data: 'destination',
|
||||||
],
|
defaultContent: ''
|
||||||
"rows": $.ajax({
|
},
|
||||||
dataType: 'json',
|
{
|
||||||
url: '/api/v1/get/mailq/all',
|
title: lang.nexthop,
|
||||||
jsonp: false,
|
data: 'nexthop',
|
||||||
error: function () {
|
defaultContent: ''
|
||||||
console.log('Cannot draw forwarding hosts table');
|
},
|
||||||
},
|
{
|
||||||
success: function (data) {
|
title: lang.username,
|
||||||
return process_table_data(data, 'queuetable');
|
data: 'username',
|
||||||
}
|
defaultContent: ''
|
||||||
}),
|
},
|
||||||
"empty": lang.empty,
|
{
|
||||||
"paging": {"enabled": true,"limit": 5,"size": log_pagination_size},
|
title: lang.active,
|
||||||
"sorting": {"enabled": true},
|
data: 'active',
|
||||||
"toggleSelector": "table tbody span.footable-toggle",
|
defaultContent: '',
|
||||||
"on": {
|
render: function (data, type) {
|
||||||
"ready.ft.table": function(e, ft){
|
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
||||||
table_admin_ready(ft, 'queuetable');
|
else return '<i class="bi bi-x-lg"></i>'
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
title: lang.action,
|
||||||
|
data: 'action',
|
||||||
|
className: 'text-md-end dt-sm-head-hidden dt-body-right',
|
||||||
|
defaultContent: ''
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function process_table_data(data, table) {
|
function process_table_data(data, table) {
|
||||||
if (table == 'relayhoststable') {
|
if (table == 'relayhoststable') {
|
||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
'<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="sender-dependent" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||||
'<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-rlyhost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-rlyhost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; }
|
if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; }
|
||||||
@@ -294,14 +516,14 @@ jQuery(function($){
|
|||||||
} else if (table == 'transportstable') {
|
} else if (table == 'transportstable') {
|
||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
if (item.is_mx_based) {
|
if (item.is_mx_based) {
|
||||||
item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
|
item.destination = '<i class="bi bi-info-circle-fill text-info mx-info" data-bs-toggle="tooltip" title="' + lang.is_mx_based + '"></i> <code>' + item.destination + '</code>';
|
||||||
}
|
}
|
||||||
if (item.username) {
|
if (item.username) {
|
||||||
item.username = '<i style="color:#' + intToRGB(hashCode(item.nexthop)) + ';" class="bi bi-square-fill"></i> ' + item.username;
|
item.username = '<i style="color:#' + intToRGB(hashCode(item.nexthop)) + ';" class="bi bi-square-fill"></i> ' + item.username;
|
||||||
}
|
}
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="#" data-toggle="modal" data-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
'<a href="#" data-bs-toggle="modal" data-bs-target="#testTransportModal" data-transport-id="' + encodeURI(item.id) + '" data-transport-type="transport-map" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-caret-right-fill"></i> Test</a>' +
|
||||||
'<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit/transport/' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-transport" data-api-url="delete/transport" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-transport" data-api-url="delete/transport" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
item.chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item.id + '" />';
|
item.chkbox = '<input type="checkbox" data-id="transports" name="multi_select" value="' + item.id + '" />';
|
||||||
@@ -313,21 +535,21 @@ jQuery(function($){
|
|||||||
return escapeHtml(i);
|
return escapeHtml(i);
|
||||||
});
|
});
|
||||||
item.recipients = rcpts.join('<hr style="margin:1px!important">');
|
item.recipients = rcpts.join('<hr style="margin:1px!important">');
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="#" data-toggle="modal" data-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-default">' + lang.queue_show_message + '</a>' +
|
'<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.queue_show_message + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
} else if (table == 'forwardinghoststable') {
|
} else if (table == 'forwardinghoststable') {
|
||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
|
item.chkbox = '<input type="checkbox" data-id="fwdhosts" name="multi_select" value="' + item.host + '" />';
|
||||||
});
|
});
|
||||||
} else if (table == 'oauth2clientstable') {
|
} else if (table == 'oauth2clientstable') {
|
||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit.php?oauth2client=' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-oauth2-client" data-api-url="delete/oauth2-client" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-oauth2-client" data-api-url="delete/oauth2-client" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
item.scope = "profile";
|
item.scope = "profile";
|
||||||
@@ -339,8 +561,8 @@ jQuery(function($){
|
|||||||
item.selected_domains = escapeHtml(item.selected_domains);
|
item.selected_domains = escapeHtml(item.selected_domains);
|
||||||
item.selected_domains = item.selected_domains.toString().replace(/,/g, "<br>");
|
item.selected_domains = item.selected_domains.toString().replace(/,/g, "<br>");
|
||||||
item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
|
item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-third btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-xs-third btn-success"><i class="bi bi-person-fill"></i> Login</a>' +
|
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-xs-third btn-success"><i class="bi bi-person-fill"></i> Login</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
@@ -353,22 +575,38 @@ jQuery(function($){
|
|||||||
item.usr = item.username;
|
item.usr = item.username;
|
||||||
}
|
}
|
||||||
item.chkbox = '<input type="checkbox" data-id="admins" name="multi_select" value="' + item.username + '" />';
|
item.chkbox = '<input type="checkbox" data-id="admins" name="multi_select" value="' + item.username + '" />';
|
||||||
item.action = '<div class="btn-group footable-actions">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-default"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit/admin/' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
'<a href="#" data-action="delete_selected" data-id="single-admin" data-api-url="delete/admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
'<a href="#" data-action="delete_selected" data-id="single-admin" data-api-url="delete/admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-xs-half btn-danger"><i class="bi bi-trash"></i> ' + lang.remove + '</a>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
};
|
};
|
||||||
// Initial table drawings
|
|
||||||
draw_domain_admins();
|
// detect element visibility changes
|
||||||
draw_admins();
|
function onVisible(element, callback) {
|
||||||
draw_fwd_hosts();
|
$(document).ready(function() {
|
||||||
draw_relayhosts();
|
element_object = document.querySelector(element);
|
||||||
draw_oauth2_clients();
|
if (element_object === null) return;
|
||||||
draw_transport_maps();
|
|
||||||
draw_queue();
|
new IntersectionObserver((entries, observer) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if(entry.intersectionRatio > 0) {
|
||||||
|
callback(element_object);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).observe(element_object);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Draw Table if tab is active
|
||||||
|
onVisible("[id^=adminstable]", () => draw_admins());
|
||||||
|
onVisible("[id^=domainadminstable]", () => draw_domain_admins());
|
||||||
|
onVisible("[id^=oauth2clientstable]", () => draw_oauth2_clients());
|
||||||
|
onVisible("[id^=forwardinghoststable]", () => draw_fwd_hosts());
|
||||||
|
onVisible("[id^=relayhoststable]", () => draw_relayhosts());
|
||||||
|
onVisible("[id^=transportstable]", () => draw_transport_maps());
|
||||||
|
|
||||||
|
|
||||||
$('body').on('click', 'span.footable-toggle', function () {
|
$('body').on('click', 'span.footable-toggle', function () {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -427,27 +665,11 @@ jQuery(function($){
|
|||||||
$('#transport_type').val(button.data('transport-type'));
|
$('#transport_type').val(button.data('transport-type'));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// Queue item
|
|
||||||
$('#showQueuedMsg').on('show.bs.modal', function (e) {
|
|
||||||
$('#queue_msg_content').text(lang.loading);
|
|
||||||
button = $(e.relatedTarget)
|
|
||||||
if (button != null) {
|
|
||||||
$('#queue_id').text(button.data('queue-id'));
|
|
||||||
}
|
|
||||||
$.ajax({
|
|
||||||
type: 'GET',
|
|
||||||
url: '/api/v1/get/postcat/' + button.data('queue-id'),
|
|
||||||
dataType: 'text',
|
|
||||||
complete: function (data) {
|
|
||||||
$('#queue_msg_content').text(data.responseText);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
$('#test_transport').on('click', function (e) {
|
$('#test_transport').on('click', function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
prev = $('#test_transport').text();
|
prev = $('#test_transport').text();
|
||||||
$(this).prop("disabled",true);
|
$(this).prop("disabled",true);
|
||||||
$(this).html('<i class="bi bi-arrow-repeat icon-spin"></i> ');
|
$(this).html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div> ');
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'GET',
|
||||||
url: 'inc/ajax/transport_check.php',
|
url: 'inc/ajax/transport_check.php',
|
||||||
@@ -481,13 +703,13 @@ jQuery(function($){
|
|||||||
function add_table_row(table_id, type) {
|
function add_table_row(table_id, type) {
|
||||||
var row = $('<tr />');
|
var row = $('<tr />');
|
||||||
if (type == "app_link") {
|
if (type == "app_link") {
|
||||||
cols = '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required></td>';
|
cols = '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="app" required></td>';
|
||||||
cols += '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required></td>';
|
cols += '<td><input class="input-sm input-xs-lg form-control" data-id="app_links" type="text" name="href" required></td>';
|
||||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button">' + lang.remove_row + '</a></td>';
|
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
|
||||||
} else if (type == "f2b_regex") {
|
} else if (type == "f2b_regex") {
|
||||||
cols = '<td><input style="text-align:center" class="input-sm input-xs-lg form-control" data-id="f2b_regex" type="text" value="+" disabled></td>';
|
cols = '<td><input style="text-align:center" class="input-sm input-xs-lg form-control" data-id="f2b_regex" type="text" value="+" disabled></td>';
|
||||||
cols += '<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required></td>';
|
cols += '<td><input class="input-sm input-xs-lg form-control regex-input" data-id="f2b_regex" type="text" name="regex" required></td>';
|
||||||
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-default" type="button">' + lang.remove_row + '</a></td>';
|
cols += '<td><a href="#" role="button" class="btn btn-sm btn-xs-lg btn-secondary h-100 w-100" type="button">' + lang.remove_row + '</a></td>';
|
||||||
}
|
}
|
||||||
row.append(cols);
|
row.append(cols);
|
||||||
table_id.append(row);
|
table_id.append(row);
|
||||||
@@ -507,4 +729,3 @@ jQuery(function($){
|
|||||||
add_table_row($('#f2b_regex_table'), "f2b_regex");
|
add_table_row($('#f2b_regex_table'), "f2b_regex");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Loaded 100 of 216 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user