Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| faef228db5 | |||
| f9352be97e | |||
| 7440254c7b |
@ -1,27 +1,17 @@
|
|||||||
.DS_Store
|
|
||||||
.idea
|
.idea
|
||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
out/
|
out/
|
||||||
/data/uploads/*
|
data/uploads/*
|
||||||
!/data/uploads/.gitkeep
|
!data/uploads/sample.jpg
|
||||||
/data/db/*
|
data/db/*
|
||||||
!/data/db/.gitkeep
|
!data/db/slideshow.json.dist
|
||||||
/plugins/user/*
|
/plugins/user/*
|
||||||
!/plugins/user/.gitkeep
|
!/plugins/user/.gitkeep
|
||||||
*.lock
|
*.lock
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.log
|
*.log
|
||||||
/var/run/*
|
var/run/*
|
||||||
!/var/run/.gitkeep
|
!var/run/.gitkeep
|
||||||
*.swp
|
|
||||||
.env
|
.env
|
||||||
venv/
|
|
||||||
node_modules
|
|
||||||
tmp.py
|
|
||||||
!/plugins/user/Dashboard
|
|
||||||
/data/www/plugins/*
|
|
||||||
!/data/www/plugins/.gitkeep
|
|
||||||
/var/run/storage/*
|
|
||||||
!/var/run/storage/.gitkeep
|
|
||||||
10
.env.dist
@ -1,11 +1,3 @@
|
|||||||
# Core
|
|
||||||
DEBUG=false
|
DEBUG=false
|
||||||
SECRET_KEY=ANY_SECRET_KEY_HERE
|
|
||||||
|
|
||||||
# Application Server
|
|
||||||
PORT=5000
|
PORT=5000
|
||||||
BIND=0.0.0.0
|
AUTOCONFIGURE_LX_FILE=/home/pi/.config/lxsession/LXDE-pi/autostart # Replace by "./var/run/dummy" if not needed
|
||||||
EXTERNAL_STORAGE_MOUNTPOINT=%application_dir%/var/run/storage
|
|
||||||
|
|
||||||
# Misc
|
|
||||||
DEMO=false
|
|
||||||
|
|||||||
1
.github/FUNDING.yml
vendored
@ -1 +0,0 @@
|
|||||||
custom: https://paypal.me/jierka
|
|
||||||
46
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,46 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: "[BUG] "
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**To Reproduce**
|
|
||||||
Steps to reproduce the behavior:
|
|
||||||
1. Go to '...'
|
|
||||||
2. Click on '....'
|
|
||||||
3. Scroll down to '....'
|
|
||||||
4. See error
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**Hardware (please complete the following information):**
|
|
||||||
- *Device*: `Raspberry Xb+`
|
|
||||||
- *OS*: `Raspbian vXX` [use command *lsb_release -a*]
|
|
||||||
- *Architecture*: `armvX` [use command *uname -a*]
|
|
||||||
|
|
||||||
**Sofware (please complete the following information):**
|
|
||||||
- *Obscreen version*: `v1.XX`
|
|
||||||
- *Installation method*: `Docker` or `System`
|
|
||||||
- *Browser*: `Chromium` or `Chrome`
|
|
||||||
- *Player method*: `Systemd with obscreen-player.service` or `Manually`
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
||||||
|
|
||||||
**Extra (Recommended)**
|
|
||||||
You can send us a backup of your data to help speed up the debugging process. Please ensure that no sensitive data is included in your slides and follow these steps:
|
|
||||||
```bash
|
|
||||||
cd obscreen
|
|
||||||
tar -vcf data.tar data/
|
|
||||||
```
|
|
||||||
Afterward, attach the `data.tar` file to your issue attachment.
|
|
||||||
21
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,21 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: "[FEATURE] "
|
|
||||||
labels: enhancement
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
|
|
||||||
0
.github/actions/common-docker-build/action.yml
vendored
Executable file → Normal file
41
.github/workflows/build-nightly.yml
vendored
@ -1,41 +0,0 @@
|
|||||||
name: Nightly build synced with develop and push docker image
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-push-nightly:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.ref == 'refs/heads/develop'
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: develop
|
|
||||||
|
|
||||||
- name: Set up Git
|
|
||||||
run: |
|
|
||||||
git config --global user.name 'github-actions'
|
|
||||||
git config --global user.email 'github-actions@github.com'
|
|
||||||
|
|
||||||
- name: Sync nightly branch
|
|
||||||
run: |
|
|
||||||
git checkout nightly
|
|
||||||
git merge develop --no-edit
|
|
||||||
git push origin nightly --force
|
|
||||||
|
|
||||||
- name: Checkout nightly branch
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
ref: nightly
|
|
||||||
|
|
||||||
- name: Call common build workflow
|
|
||||||
uses: ./.github/actions/common-docker-build
|
|
||||||
with:
|
|
||||||
build_tags: csmith1865/obscreen:nightly
|
|
||||||
manifest_tags: type=semver,pattern=nightly
|
|
||||||
flavor: ""
|
|
||||||
docker_username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
docker_password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
28
.github/workflows/build-pr.yml
vendored
@ -1,28 +0,0 @@
|
|||||||
name: PR build and push docker image
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types: [opened, synchronize, labeled]
|
|
||||||
push:
|
|
||||||
branches-ignore:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
- nightly
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-push-pr:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: contains(github.event.pull_request.labels.*.name, 'build-pr')
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Call common build workflow
|
|
||||||
uses: ./.github/actions/common-docker-build
|
|
||||||
with:
|
|
||||||
build_tags: csmith1865/obscreen:pr-${{ github.event.pull_request.number }}
|
|
||||||
manifest_tags: type=semver,pattern=pr
|
|
||||||
flavor: ""
|
|
||||||
docker_username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
docker_password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
25
.gitignore
vendored
@ -1,30 +1,19 @@
|
|||||||
.DS_Store
|
|
||||||
.idea
|
.idea
|
||||||
*.iws
|
*.iws
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
out/
|
out/
|
||||||
/data/uploads/*
|
data/uploads/*
|
||||||
!/data/uploads/.gitkeep
|
!data/uploads/sample.jpg
|
||||||
/data/db/*
|
data/db/*
|
||||||
!/data/db/.gitkeep
|
!data/db/slideshow.json.dist
|
||||||
/plugins/user/*
|
/plugins/user/*
|
||||||
!/plugins/user/.gitkeep
|
!/plugins/user/.gitkeep
|
||||||
*.lock
|
*.lock
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.log
|
*.log
|
||||||
/var/run/*
|
var/run/*
|
||||||
!/var/run/.gitkeep
|
!var/run/.gitkeep
|
||||||
|
!var/run/dummy
|
||||||
*.swp
|
*.swp
|
||||||
.env
|
.env
|
||||||
venv/
|
|
||||||
node_modules
|
|
||||||
tmp.py
|
|
||||||
!/plugins/user/Dashboard
|
|
||||||
/data/www/plugins/*
|
|
||||||
!/data/www/plugins/.gitkeep
|
|
||||||
/var/run/storage/*
|
|
||||||
!/var/run/storage/.gitkeep
|
|
||||||
*.egg-info
|
|
||||||
/build/
|
|
||||||
/dist/
|
|
||||||
|
|||||||
20
Dockerfile
@ -1,24 +1,12 @@
|
|||||||
FROM python:3.9-slim-bullseye
|
FROM python:3.9.17-alpine3.17
|
||||||
|
|
||||||
# Install ffmpeg and other dependencies
|
RUN apk add --no-cache git chromium \
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
&& apk add --no-cache --virtual .build-deps git gcc musl-dev
|
||||||
gcc \
|
|
||||||
libc6-dev \
|
|
||||||
sqlite3 \
|
|
||||||
libsqlite3-dev \
|
|
||||||
ntfs-3g \
|
|
||||||
ffmpeg \
|
|
||||||
build-essential \
|
|
||||||
curl \
|
|
||||||
tar \
|
|
||||||
bash \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Install Python dependencies
|
RUN pip install -r requirements.txt && apk del .build-deps gcc musl-dev
|
||||||
RUN pip install --no-cache-dir -r requirements.txt
|
|
||||||
|
|
||||||
ENTRYPOINT ["python", "/app/obscreen.py"]
|
ENTRYPOINT ["python", "/app/obscreen.py"]
|
||||||
|
|||||||
@ -1,4 +0,0 @@
|
|||||||
include README.md
|
|
||||||
include LICENSE
|
|
||||||
docs/setup-run-on-rpi.md
|
|
||||||
docs/setup-run-headless.md
|
|
||||||
184
README.md
@ -1,120 +1,118 @@
|
|||||||
<div align="center" width="100%">
|
# <img src="https://github.com/jr-k/obscreen/blob/master/docs/obscreen.png" width="22"> Obscreen
|
||||||
<img src="./docs/img/obscreen.png" width="128" alt="" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
# Obscreen
|
🧑🎄 Open to feature request and pull request
|
||||||
|
|
||||||
Obscreen is a user-friendly self-hosted digital signage tool leveraging chromium browser.
|
## About
|
||||||
|
Use a RaspberryPi to show a full-screen slideshow (Kiosk-mode)
|
||||||
|
|
||||||
<a target="_blank" href="https://git.sumisu.xyz/csmith1865/obscreen"><img src="https://img.shields.io/gitea/stars/csmith1865/obscreen?gitea_url=https%3A%2F%2Fgit.sumisu.xyz&style=flat" /></a> <a target="_blank" href="https://hub.docker.com/r/csmith1865/obscreen"><img src="https://img.shields.io/docker/pulls/csmith1865/obscreen" /></a> <a target="_blank" href="https://hub.docker.com/r/csmith1865/obscreen"><img src="https://img.shields.io/docker/v/csmith1865/obscreen/latest?label=docker%20image%20ver." /></a> <a target="_blank" href="https://git.sumisu.xyz/csmith1865/obscreen"><img src="https://img.shields.io/gitea/last-commit/csmith1865/obscreen?gitea_url=https%3A%2F%2Fgit.sumisu.xyz&style=flat" /></a>
|
[](https://hub.docker.com/r/jierka/obscreen/)
|
||||||
|
|
||||||
<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/screenshot-playlist-edit.png" width="700" alt="" />
|
### Features:
|
||||||
|
- Dead simple chromium webview
|
||||||
🧑🎄 Open to feature request and pull request. [Cast your vote for your preferred ones on the Canny platform](https://obscreen.canny.io/feature-requests)
|
- Clear GUI
|
||||||
|
- Fleet view to manage many devices easily
|
||||||
⭐️ You liked it ? Give this repository a star, it's free :)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 🕹️ Live Demo
|
|
||||||
|
|
||||||
Try it!
|
|
||||||
|
|
||||||
Demo Server (Location: Roubaix - France): [https://demo.obscreen.io](https://demo.obscreen.io/login?username=admin&password=admin)
|
|
||||||
|
|
||||||
It is a temporary live demo, all data will be deleted after 30 minutes (~30secs downtime).
|
|
||||||
|
|
||||||
## 🎉 Features
|
|
||||||
- Dead simple chromium webview inside
|
|
||||||
- Fancy graphical user interface
|
|
||||||
- Very few dependencies
|
- Very few dependencies
|
||||||
- Embeddable SQLite database
|
- JSON database files
|
||||||
- Fleet screen management
|
- Plugin system
|
||||||
- Playlist management
|
- No stupid pricing plan
|
||||||
- Authentication management
|
- No cloud
|
||||||
- Plays content from flashdrive in offline mode
|
- No telemetry
|
||||||
- Core API & Plugin system to extend capabilities
|
|
||||||
- [Multi Languages](https://git.sumisu.xyz/csmith1865/obscreen/src/branch/master/lang)
|
|
||||||
- Cast pictures and iframes to Chromecast
|
|
||||||
- No costly monthly pricing plan per screen or whatever, no cloud, no telemetry
|
|
||||||
|
|
||||||
## 👨🍳 How to install
|

|
||||||
|
|
||||||
### 🔴 [I want to power a RaspberryPi and automatically see my slideshow on a screen connected to it and manage the slideshow](docs/setup-run-on-rpi.md)
|
## 🐳 Run with docker
|
||||||
### 🔵 [I just want a slideshow manager and I'll deal with screen and browser myself](docs/setup-run-headless.md)
|
### With docker (for test)
|
||||||
|
```bash
|
||||||
|
# Prepare application data file tree
|
||||||
|
mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
|
||||||
|
|
||||||
## 📸 More Screenshots
|
# Run the Docker container
|
||||||
|
# If you ARE NOT on a RaspberryPi ignore the line (-v /home/pi/....)
|
||||||
|
docker run --rm --name obscreen --pull=always \
|
||||||
|
-e DEBUG=false \
|
||||||
|
-e PORT=5000 \
|
||||||
|
-e AUTOCONFIGURE_LX_FILE=/app/var/run/lxfile \
|
||||||
|
-p 5000:5000 \
|
||||||
|
-v ./data/db:/app/data/db \
|
||||||
|
-v ./data/uploads:/app/data/uploads \
|
||||||
|
-v /home/pi/.config/lxsession/LXDE-pi/autostart:/app/var/run/lxfile \
|
||||||
|
jierka/obscreen:latest
|
||||||
|
```
|
||||||
|
|
||||||
Light Mode:
|
### With docker-compose
|
||||||
|
```bash
|
||||||
|
# Prepare application data file tree
|
||||||
|
mkdir -p obscreen/data/db obscreen/data/uploads && cd obscreen
|
||||||
|
|
||||||
<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/screenshot-light-mode.png" width="512" alt="" />
|
# Download docker-compose.yml
|
||||||
|
curl https://raw.githubusercontent.com/jr-k/obscreen/master/docker-compose.yml > docker-compose.yml
|
||||||
|
|
||||||
Content Explorer:
|
# If you ARE NOT on a RaspberryPi execute the line below
|
||||||
|
uname | grep -q 'Darwin' && sed -i '' '/\/home\/pi/s/^/#/' docker-compose.yml || sed -i '/\/home\/pi/s/^/#/' docker-compose.yml
|
||||||
|
|
||||||
<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/screenshot-content-explorer.png" width="512" alt="" />
|
# Run
|
||||||
|
docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
Settings Page:
|
## 📠 Run system wide
|
||||||
|
### Install
|
||||||
|
```bash
|
||||||
|
# Install system dependencies
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y git chromium-browser unclutter
|
||||||
|
|
||||||
<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/screenshot-settings.png" width="512" alt="" />
|
# Get files
|
||||||
|
git clone https://github.com/jr-k/obscreen.git && cd obscreen
|
||||||
|
|
||||||
Add Content Modal:
|
# Install application dependencies
|
||||||
|
pip3 install -r requirements.txt
|
||||||
|
|
||||||
<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/screenshot-add-content.png" width="512" alt="" />
|
# Add some sample data
|
||||||
|
cp data/db/slideshow.json.dist data/db/slideshow.json
|
||||||
|
|
||||||
## 🫡 Motivation
|
# Customize server default values
|
||||||
|
cp .env.dist .env
|
||||||
|
```
|
||||||
|
|
||||||
- I was searching for a self-hosted monitoring tool similar to "Screenly", but struggled with "Anthias" (formerly Screenly OSE) due to compatibility issues on some webpages. Chromium does a great job at rendering webpages, so I decided to create my own solution based on browsers.
|
### Configure
|
||||||
- Enjoy a beautiful graphical interface
|
- Server configuration is editable in `.env` file.
|
||||||
- My goal was to keep the code as simple as possible, using reliable technology with minimal dependencies.
|
- Application configuration is available in `http://localhost:5000/settings` page.
|
||||||
- Aim to showcase the power of the Raspberry Pi 5.
|
|
||||||
- Deploy my first true Docker image to Docker Hub using a continuous deployment pipeline.
|
|
||||||
|
|
||||||
If you value this project, please think about awarding it a ⭐. Thanks ! 🙏
|
### Start server (for test)
|
||||||
|
```bash
|
||||||
|
./obscreen.py
|
||||||
|
```
|
||||||
|
|
||||||
## 🗺️ Short-term roadmap
|
### Start server forever with systemctl
|
||||||
- New `Composition` content type: Check out a [video demo here](https://demo.obscreen.io/data/uploads/compositions.mp4)
|
```bash
|
||||||
- New `Text` Content Type: Display text with customizable styles, including options for scrolling effects.
|
sudo ln -s "$(pwd)/system/obscreen.service" /etc/systemd/system/obscreen.service
|
||||||
- New `HTML` Content Type: Display HTML snippets for more powerful text customization, giving you full control over the content.
|
sudo systemctl daemon-reload
|
||||||
- Fleet Studio Management: Reviving a legacy feature
|
sudo systemctl enable obscreen.service
|
||||||
- Remote Player Server: A new way to manage a player from the studio without needing SSH access to player
|
sudo systemctl start obscreen.service
|
||||||
|
```
|
||||||
|
|
||||||
## 🛟 Discussion / Need help ?
|
To troubleshoot you can check logs
|
||||||
|
```bash
|
||||||
|
sudo journalctl -u obscreen -f
|
||||||
|
```
|
||||||
|
|
||||||
### Join our Discord
|
## 👌 Usage
|
||||||
[<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/img/discord.png" width="64">](https://discord.obscreen.io)
|
- Page which plays slideshow is reachable at `http://localhost:5000`
|
||||||
|
- Slideshow manager is reachable at `http://localhost:5000/manage`
|
||||||
|
|
||||||
### Open an Issue
|
## ✨ You are done now :)
|
||||||
[<img src="https://git.sumisu.xyz/csmith1865/obscreen/raw/branch/master/docs/img/github.png" width="64">](https://git.sumisu.xyz/csmith1865/obscreen/issues/new/choose)
|
- If everything is set up correctly, the RaspberryPi shall start chromium in fullscreen directly after boot screen and after some seconds of showing the date & time (`views/player/default.jinja.html`) your slideshow shall start and loop endlessly.
|
||||||
|
- Be sure that `AUTOCONFIGURE_LX_FILE` is writeable !
|
||||||
|
|
||||||
### Troubleshoot
|
## 📎 Additional
|
||||||
|
|
||||||
|
### Hardware checks
|
||||||
|
- Basic Setup
|
||||||
|
For basic RaspberryPi setup you can use most of the available guides, for example this one:
|
||||||
|
https://gist.github.com/blackjid/dfde6bedef148253f987
|
||||||
|
|
||||||
<details closed>
|
- HDMI Mode
|
||||||
<summary><h3>Why aren't the videos starting?</h3></summary>
|
You may need to set the HDMI Mode on the raspi to ensure the hdmi resolution matches your screen exactly. Here is the official documentation:
|
||||||
|
https://www.raspberrypi.org/documentation/configuration/config-txt/video.md
|
||||||
|
|
||||||
This is "normal" behavior. Videos do not play automatically in Chrome because it requires user interaction with the page (a simple click inside the webpage is enough). If you open the console, you'll see the error: [Uncaught (in promise) DOMException: play() failed because the user didn't interact with the document first...](https://goo.gl/xX8pDD)
|
However, I used this one: `(2,82) = 1920x1080 60Hz 1080p`
|
||||||
|
|
||||||
To resolve this, you need to use the Chrome flag `--autoplay-policy=no-user-gesture-required`. When connecting a Raspberry Pi with Obscreen Player autorun, this issue doesn't occur because the flag is handled automatically for you. You need to enable this flag yourself otherwise.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
## 👑 Contributions
|
|
||||||
|
|
||||||
### Create Pull Requests
|
|
||||||
|
|
||||||
We accept all types of pull requests.
|
|
||||||
|
|
||||||
### Test Beta Version
|
|
||||||
|
|
||||||
Check out the latest beta release here: https://github.com/jr-k/obscreen/releases
|
|
||||||
|
|
||||||
### Translations
|
|
||||||
|
|
||||||
If you want to translate Obscreen into your language, please visit [Languages Files](https://git.sumisu.xyz/csmith1865/obscreen/src/branch/master/lang).
|
|
||||||
|
|
||||||
### Spelling & Grammar
|
|
||||||
|
|
||||||
Feel free to correct the grammar in the documentation or code.
|
|
||||||
My mother language is not English and my grammar is not that great.
|
|
||||||
|
|||||||
32
data/db/slideshow.json.dist
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"keys": [
|
||||||
|
"duration",
|
||||||
|
"enabled",
|
||||||
|
"location",
|
||||||
|
"name",
|
||||||
|
"position",
|
||||||
|
"type",
|
||||||
|
"cron_schedule"
|
||||||
|
],
|
||||||
|
"data": {
|
||||||
|
"0": {
|
||||||
|
"location": "data/uploads/sample.jpg",
|
||||||
|
"duration": 10,
|
||||||
|
"type": "picture",
|
||||||
|
"enabled": true,
|
||||||
|
"name": "Picture Sample",
|
||||||
|
"position": 0,
|
||||||
|
"cron_schedule": null
|
||||||
|
},
|
||||||
|
"1": {
|
||||||
|
"location": "https://unix.org",
|
||||||
|
"duration": 20,
|
||||||
|
"type": "url",
|
||||||
|
"enabled": true,
|
||||||
|
"name": "URL Sample",
|
||||||
|
"position": 1,
|
||||||
|
"cron_schedule": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
data/uploads/sample.jpg
Executable file
|
After Width: | Height: | Size: 538 KiB |
@ -1,12 +1,2 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<browserconfig>
|
<browserconfig><msapplication><tile><square70x70logo src="/favicon/ms-icon-70x70.png"/><square150x150logo src="/favicon/ms-icon-150x150.png"/><square310x310logo src="/favicon/ms-icon-310x310.png"/><TileColor>#692fbd</TileColor></tile></msapplication></browserconfig>
|
||||||
<msapplication>
|
|
||||||
<tile>
|
|
||||||
<square70x70logo src="/favicon/mstile-70x70.png"/>
|
|
||||||
<square150x150logo src="/favicon/mstile-150x150.png"/>
|
|
||||||
<square310x310logo src="/favicon/mstile-310x3150.png"/>
|
|
||||||
<square310x310logo src="/favicon/mstile-310x310.png"/>
|
|
||||||
<TileColor>#333333</TileColor>
|
|
||||||
</tile>
|
|
||||||
</msapplication>
|
|
||||||
</browserconfig>
|
|
||||||
9
data/www/css/lib/fontawesome.min.css
vendored
@ -1,211 +0,0 @@
|
|||||||
/*
|
|
||||||
* Explr.js v1.4
|
|
||||||
* Explorer-like tree jQuery plugin
|
|
||||||
* https://github.com/faisalman/explr-js
|
|
||||||
*
|
|
||||||
* Copyright © 2010-2011 Faisal Salman <f@faisalman.com>
|
|
||||||
* Dual licensed under GPLv2 & MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
.explr-tree * {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree,
|
|
||||||
.explr-tree ol,
|
|
||||||
.explr-tree ul {
|
|
||||||
display: block;
|
|
||||||
font-family: Ubuntu, Helvetica, Tahoma, sans-serif;
|
|
||||||
font-size: 12px;
|
|
||||||
letter-spacing: normal;
|
|
||||||
line-height: 12px;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding-bottom: 0;
|
|
||||||
padding-left: 20px;
|
|
||||||
padding-top: 5px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree li {
|
|
||||||
background: url("../../img/explr/folder.png") 16px 2px no-repeat;
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree li a {
|
|
||||||
color: #555;
|
|
||||||
display: block;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-left: 30px;
|
|
||||||
padding: 3px 0 5px 8px;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree li a:hover {
|
|
||||||
color: #ff0084;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-line {
|
|
||||||
/*border-left: 1px dotted #999;*/
|
|
||||||
/*border-bottom: 1px dotted #999;*/
|
|
||||||
height: 22px;
|
|
||||||
position: absolute;
|
|
||||||
margin-left: 0;
|
|
||||||
margin-top: -12px;
|
|
||||||
width: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-tree ol>li:first-child>.explr-line,
|
|
||||||
.explr-tree ul>li:first-child>.explr-line {
|
|
||||||
margin-top: -8px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-line-fix {
|
|
||||||
/*border-left: 1px dotted #999;*/
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-icon {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 0 0;
|
|
||||||
height: 16px;
|
|
||||||
width: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-item i.fa {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
top: 2px;
|
|
||||||
font-size: 14px;
|
|
||||||
left: 16px;
|
|
||||||
color: rgb(187, 187, 187);
|
|
||||||
width: 18px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-toggler {
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 0 0;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: -8px;
|
|
||||||
margin-top: 2px;
|
|
||||||
position: absolute;
|
|
||||||
width: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*.explr-plus { background-image: url("../../img/explr/plus.png"); }*/
|
|
||||||
/*.explr-minus { background-image: url("../../img/explr/busy.png"); }*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Menu icons: */
|
|
||||||
|
|
||||||
.explr-tree .icon-text > li, .explr-tree li.icon-text { background-image: none; }
|
|
||||||
.explr-tree .icon-file > li, .explr-tree li.icon-file { background-image: url("../../img/explr/attibutes.png"); }
|
|
||||||
.explr-tree .icon-address > li, .explr-tree li.icon-address { background-image: url("../../img/explr/address.png"); }
|
|
||||||
.explr-tree .icon-archives > li, .explr-tree li.icon-archives { background-image: url("../../img/explr/archives.png"); }
|
|
||||||
.explr-tree .icon-badge > li, .explr-tree li.icon-badge { background-image: url("../../img/explr/bestseller.png"); }
|
|
||||||
.explr-tree .icon-bank > li, .explr-tree li.icon-bank { background-image: url("../../img/explr/bank.png"); }
|
|
||||||
.explr-tree .icon-basket > li, .explr-tree li.icon-basket { background-image: url("../../img/explr/basket.png"); }
|
|
||||||
.explr-tree .icon-board > li, .explr-tree li.icon-board { background-image: url("../../img/explr/order.png"); }
|
|
||||||
.explr-tree .icon-board2 > li, .explr-tree li.icon-board2 { background-image: url("../../img/explr/order-1.png"); }
|
|
||||||
.explr-tree .icon-book > li, .explr-tree li.icon-book { background-image: url("../../img/explr/library.png"); }
|
|
||||||
.explr-tree .icon-bookmark > li, .explr-tree li.icon-bookmark { background-image: url("../../img/explr/bookmark.png"); }
|
|
||||||
.explr-tree .icon-business > li, .explr-tree li.icon-business { background-image: url("../../img/explr/business-contact.png"); }
|
|
||||||
.explr-tree .icon-calendar > li, .explr-tree li.icon-calendar { background-image: url("../../img/explr/calendar.png"); }
|
|
||||||
.explr-tree .icon-card > li, .explr-tree li.icon-card { background-image: url("../../img/explr/credit-card.png"); }
|
|
||||||
.explr-tree .icon-card2 > li, .explr-tree li.icon-card2 { background-image: url("../../img/explr/my-account.png"); }
|
|
||||||
.explr-tree .icon-chain > li, .explr-tree li.icon-chain { background-image: url("../../img/explr/link.png"); }
|
|
||||||
.explr-tree .icon-chart > li, .explr-tree li.icon-chart { background-image: url("../../img/explr/statistics.png"); }
|
|
||||||
.explr-tree .icon-check > li, .explr-tree li.icon-check { background-image: url("../../img/explr/check.png"); }
|
|
||||||
.explr-tree .icon-clock > li, .explr-tree li.icon-clock { background-image: url("../../img/explr/full-time.png"); }
|
|
||||||
.explr-tree .icon-comment > li, .explr-tree li.icon-comment { background-image: url("../../img/explr/comment.png"); }
|
|
||||||
.explr-tree .icon-config > li, .explr-tree li.icon-config { background-image: url("../../img/explr/config.png"); }
|
|
||||||
.explr-tree .icon-customers > li, .explr-tree li.icon-customers { background-image: url("../../img/explr/customers.png"); }
|
|
||||||
.explr-tree .icon-cv > li, .explr-tree li.icon-cv { background-image: url("../../img/explr/cv.png"); }
|
|
||||||
.explr-tree .icon-db > li, .explr-tree li.icon-db { background-image: url("../../img/explr/database.png"); }
|
|
||||||
.explr-tree .icon-direction > li, .explr-tree li.icon-direction { background-image: url("../../img/explr/milestone.png"); }
|
|
||||||
.explr-tree .icon-flag > li, .explr-tree li.icon-flag { background-image: url("../../img/explr/flag.png"); }
|
|
||||||
.explr-tree .icon-folder > li, .explr-tree li.icon-folder, .explr-icon-folder { background-image: url("../../img/explr/folder.png"); }
|
|
||||||
.explr-tree .icon-folder2 > li, .explr-tree li.icon-folder2 { background-image: url("../../img/explr/finished-work.png"); }
|
|
||||||
.explr-tree .icon-folder3 > li, .explr-tree li.icon-folder3 { background-image: url("../../img/explr/upcoming-work.png"); }
|
|
||||||
.explr-tree .icon-hand > li, .explr-tree li.icon-hand { background-image: url("../../img/explr/freelance.png"); }
|
|
||||||
.explr-tree .icon-heart > li, .explr-tree li.icon-heart { background-image: url("../../img/explr/heart.png"); }
|
|
||||||
.explr-tree .icon-help > li, .explr-tree li.icon-help { background-image: url("../../img/explr/consulting.png"); }
|
|
||||||
.explr-tree .icon-home > li, .explr-tree li.icon-home { background-image: url("../../img/explr/home.png"); }
|
|
||||||
.explr-tree .icon-lamp > li, .explr-tree li.icon-lamp { background-image: url("../../img/explr/lightbulb.png"); }
|
|
||||||
.explr-tree .icon-left > li, .explr-tree li.icon-left { background-image: url("../../img/explr/sign-out.png"); }
|
|
||||||
.explr-tree .icon-left2 > li, .explr-tree li.icon-left2 { background-image: url("../../img/explr/login.png"); }
|
|
||||||
.explr-tree .icon-lock > li, .explr-tree li.icon-lock { background-image: url("../../img/explr/lock.png"); }
|
|
||||||
.explr-tree .icon-mail > li, .explr-tree li.icon-mail { background-image: url("../../img/explr/contact.png"); }
|
|
||||||
.explr-tree .icon-mail2 > li, .explr-tree li.icon-mail2 { background-image: url("../../img/explr/email.png"); }
|
|
||||||
.explr-tree .icon-palette > li, .explr-tree li.icon-palette { background-image: url("../../img/explr/drawings.png"); }
|
|
||||||
.explr-tree .icon-pencil > li, .explr-tree li.icon-pencil { background-image: url("../../img/explr/edit.png"); }
|
|
||||||
.explr-tree .icon-pencil2 > li, .explr-tree li.icon-pencil2 { background-image: url("../../img/explr/pencil.png"); }
|
|
||||||
.explr-tree .icon-phone > li, .explr-tree li.icon-phone { background-image: url("../../img/explr/phone.png"); }
|
|
||||||
.explr-tree .icon-photo > li, .explr-tree li.icon-photo { background-image: url("../../img/explr/photography.png"); }
|
|
||||||
.explr-tree .icon-print > li, .explr-tree li.icon-print { background-image: url("../../img/explr/print.png"); }
|
|
||||||
.explr-tree .icon-project > li, .explr-tree li.icon-project { background-image: url("../../img/explr/project.png"); }
|
|
||||||
.explr-tree .icon-refresh > li, .explr-tree li.icon-refresh { background-image: url("../../img/explr/refresh.png"); }
|
|
||||||
.explr-tree .icon-right > li, .explr-tree li.icon-right { background-image: url("../../img/explr/sign-in.png"); }
|
|
||||||
.explr-tree .icon-right2 > li, .explr-tree li.icon-right2 { background-image: url("../../img/explr/logout.png"); }
|
|
||||||
.explr-tree .icon-showreel > li, .explr-tree li.icon-showreel { background-image: url("../../img/explr/showreel.png"); }
|
|
||||||
.explr-tree .icon-star > li, .explr-tree li.icon-star { background-image: url("../../img/explr/star.png"); }
|
|
||||||
.explr-tree .icon-tag > li, .explr-tree li.icon-tag { background-image: url("../../img/explr/tag.png"); }
|
|
||||||
.explr-tree .icon-text2 > li, .explr-tree li.icon-text2 { background-image: url("../../img/explr/issue.png"); }
|
|
||||||
.explr-tree .icon-text3 > li, .explr-tree li.icon-text3 { background-image: url("../../img/explr/future-projects.png"); }
|
|
||||||
.explr-tree .icon-text4 > li, .explr-tree li.icon-text4 { background-image: url("../../img/explr/old-versions.png"); }
|
|
||||||
.explr-tree .icon-user > li, .explr-tree li.icon-user { background-image: url("../../img/explr/user.png"); }
|
|
||||||
.explr-tree .icon-world > li, .explr-tree li.icon-world { background-image: url("../../img/explr/world.png"); }
|
|
||||||
.explr-tree .icon-zoom > li, .explr-tree li.icon-zoom { background-image: url("../../img/explr/zoom.png"); }
|
|
||||||
.explr-tree .icon-youtube > li, .explr-tree li.icon-youtube { background-image: url("../../img/explr/youtube.png"); }
|
|
||||||
.explr-tree .icon-globe > li, .explr-tree li.icon-globe { background-image: url("../../img/explr/globe.png"); }
|
|
||||||
.explr-tree .icon-video > li, .explr-tree li.icon-video { background-image: url("../../img/explr/video.png"); }
|
|
||||||
.explr-tree .icon-landscape > li, .explr-tree li.icon-landscape { background-image: url("../../img/explr/landscape.png"); }
|
|
||||||
|
|
||||||
|
|
||||||
/* IE Hack Fixes: */
|
|
||||||
|
|
||||||
.explr-ie,
|
|
||||||
.explr-ie ol,
|
|
||||||
.explr-ie ul {
|
|
||||||
margin-left: 4px;
|
|
||||||
padding-left: 16px;
|
|
||||||
position: static;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-ie ol,
|
|
||||||
.explr-ie ul {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-ie {
|
|
||||||
padding-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-ie .explr-line,
|
|
||||||
.explr-ie .explr-toggler {
|
|
||||||
top: 0;
|
|
||||||
left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-ie li {
|
|
||||||
height: auto !important;
|
|
||||||
height: 24px;
|
|
||||||
*padding-top: 12px;
|
|
||||||
_padding-top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.explr-ie li a {
|
|
||||||
*position: absolute;
|
|
||||||
_position: static;
|
|
||||||
*top: 0;
|
|
||||||
_top: auto;
|
|
||||||
}
|
|
||||||
601
data/www/css/main.css
Normal file
@ -0,0 +1,601 @@
|
|||||||
|
* {
|
||||||
|
font-family: Roboto;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100vh;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
background-color: #0f0035;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
flex: 1;
|
||||||
|
background-color: #0f0035;
|
||||||
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.invisible {
|
||||||
|
visibility: hidden !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tac {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: rgba(0, 0, 0, 0.1);
|
||||||
|
margin: auto;
|
||||||
|
display: flex;
|
||||||
|
align-self: stretch;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 70%;
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1200px) {
|
||||||
|
min-width: 95%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
align-self: stretch;
|
||||||
|
padding: 0 25px 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .logo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .logo a {
|
||||||
|
color: inherit;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header .logo img {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav ul {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav ul li {
|
||||||
|
margin: 0 15px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav ul li a {
|
||||||
|
color: rgba(255, 255, 255, 0.6);
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
header nav ul li a:hover,
|
||||||
|
header nav ul li.active a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
padding: 0 25px 0 25px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar h2 {
|
||||||
|
padding: 0 25px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toolbar .toolbar-actions {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.btn,
|
||||||
|
button {
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 5px;
|
||||||
|
border: 1px solid #bc48ff;
|
||||||
|
color: #270035;
|
||||||
|
padding: 10px 30px;
|
||||||
|
text-decoration: none;
|
||||||
|
margin: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: .2s linear all;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.btn:hover,
|
||||||
|
button:hover {
|
||||||
|
color: #bc48ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.purple {
|
||||||
|
font-weight: bold;
|
||||||
|
border: 1px solid #692fbd;
|
||||||
|
color: white;
|
||||||
|
background: #692fbd;
|
||||||
|
background: linear-gradient(90deg, #bc48ff 0%, #692fbd 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.green {
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #0eef5f;
|
||||||
|
background: linear-gradient(90deg, #2fde6f 0%, #13c251 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.normal:hover {
|
||||||
|
color: white;
|
||||||
|
border-color: #692fbd;
|
||||||
|
background: #692fbd;
|
||||||
|
background: linear-gradient(90deg, #bc48ff 0%, #692fbd 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.green:hover,
|
||||||
|
button.purple:hover {
|
||||||
|
border: 1px solid #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
margin: 10px 30px 20px 30px;
|
||||||
|
padding: 20px 50px;
|
||||||
|
flex: 1;
|
||||||
|
align-self: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-success {
|
||||||
|
color: rgb(14, 239, 95);
|
||||||
|
border: 1px solid rgb(14, 239, 95);
|
||||||
|
background: rgba(14, 239, 95, .2);
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.panel {
|
||||||
|
background: rgba(255, 255, 255, 0.15);
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 0 25px 80px 25px;
|
||||||
|
margin: 10px 25px;
|
||||||
|
border-left: 5px solid #0eef5f;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel h3 {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-inactive {
|
||||||
|
background: white;
|
||||||
|
color: #AAA;
|
||||||
|
border-color: #BBB;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-inactive h3 {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel table {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 30px;
|
||||||
|
border-collapse: collapse;
|
||||||
|
text-align: left;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel th {
|
||||||
|
border-bottom: 1px solid #fff;
|
||||||
|
border-collapse: collapse;
|
||||||
|
padding: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-inactive th {
|
||||||
|
border-color: #EEE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td {
|
||||||
|
border-collapse: collapse;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td a.item.sort {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td a.item-name {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-inactive td a.item-name {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td a.item-name:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.actions a {
|
||||||
|
background: white;
|
||||||
|
color: #333;
|
||||||
|
border: 1px solid #AAA;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 2px;
|
||||||
|
width: 35px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.actions a:hover {
|
||||||
|
color: #0eef5f;
|
||||||
|
border-color: #0eef5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.actions a.item-edit:hover {
|
||||||
|
color: #bc48ff;
|
||||||
|
border-color: #bc48ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.actions a.item-delete:hover {
|
||||||
|
color: #ef0e0e;
|
||||||
|
border-color: #ef0e0e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.infos {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel td.infos .inner {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel a {
|
||||||
|
color: #0eef5f;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel a:hover {
|
||||||
|
color: #0bc44e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-right {
|
||||||
|
margin: 0 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-left {
|
||||||
|
margin: 0 10px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch {
|
||||||
|
z-index: 0;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input {
|
||||||
|
appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
z-index: -1;
|
||||||
|
position: absolute;
|
||||||
|
right: 6px;
|
||||||
|
top: -8px;
|
||||||
|
display: block;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
outline: none;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(1);
|
||||||
|
pointer-events: none;
|
||||||
|
transition: opacity 0.3s 0.1s, transform 0.2s 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > span {
|
||||||
|
display: inline-block;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > span::before {
|
||||||
|
content: "";
|
||||||
|
float: right;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px 0 5px 10px;
|
||||||
|
border-radius: 7px;
|
||||||
|
width: 36px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
vertical-align: top;
|
||||||
|
transition: background-color 0.2s, opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > span::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 2px;
|
||||||
|
right: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: rgb(255, 255, 255);
|
||||||
|
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
transition: background-color 0.2s, transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:checked {
|
||||||
|
right: -10px;
|
||||||
|
background-color: rgb(14, 239, 95);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:checked + span::before {
|
||||||
|
background-color: rgba(14, 239, 95, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:checked + span::after {
|
||||||
|
background-color: rgb(14, 239, 95);
|
||||||
|
transform: translateX(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch:hover > input {
|
||||||
|
opacity: 0.04;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:focus {
|
||||||
|
opacity: 0.12;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch:hover > input:focus {
|
||||||
|
opacity: 0.16;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:active {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(0);
|
||||||
|
transition: transform 0s, opacity 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:active + span::before {
|
||||||
|
background-color: rgba(14, 239, 95, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:checked:active + span::before {
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:disabled {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:disabled + span {
|
||||||
|
color: rgb(0, 0, 0);
|
||||||
|
opacity: 0.38;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:disabled + span::before {
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
.pure-material-switch > input:checked:disabled + span::before {
|
||||||
|
background-color: rgba(14, 239, 95, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modals {
|
||||||
|
position: fixed;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modals-outer {
|
||||||
|
min-width: 30%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modals-outer .modal-close {
|
||||||
|
color: white;
|
||||||
|
font-size: 30px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
margin-top: -100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modals-inner {
|
||||||
|
background: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modals-inner .modal h2 {
|
||||||
|
border-bottom: 1px solid #DDD;
|
||||||
|
padding: 15px 15px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group {
|
||||||
|
margin: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
align-self: stretch;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group label {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: right;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group .widget {
|
||||||
|
flex: 3;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: center;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group input,
|
||||||
|
form .form-group select,
|
||||||
|
form .form-group textarea {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px 5px 10px 5px;
|
||||||
|
border: 1px solid #EEE;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group input[type=checkbox] {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group .trigger {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group select.trigger {
|
||||||
|
max-width: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .form-group span {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .actions button.green,
|
||||||
|
form .actions button {
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .actions button.green:hover {
|
||||||
|
background: white;
|
||||||
|
color: rgb(14, 239, 95);
|
||||||
|
border-color: rgb(14, 239, 95);
|
||||||
|
}
|
||||||
|
|
||||||
|
form .actions button.modal-close {
|
||||||
|
color: #999;
|
||||||
|
border-color: #999;
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
form .actions button.modal-close:hover {
|
||||||
|
color: #555;
|
||||||
|
border-color: #555;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.empty {
|
||||||
|
text-transform: uppercase;
|
||||||
|
opacity: 0.5;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
align-self: stretch;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
flex-direction: column;
|
||||||
|
display: flex;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer .version {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
BIN
data/www/favicon.ico
Normal file → Executable file
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 1.1 KiB |
BIN
data/www/favicon/android-icon-144x144.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
BIN
data/www/favicon/android-icon-192x192.png
Executable file
|
After Width: | Height: | Size: 27 KiB |
BIN
data/www/favicon/android-icon-36x36.png
Executable file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
data/www/favicon/android-icon-48x48.png
Executable file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
data/www/favicon/android-icon-72x72.png
Executable file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
data/www/favicon/android-icon-96x96.png
Executable file
|
After Width: | Height: | Size: 10 KiB |
BIN
data/www/favicon/apple-icon-114x114.png
Executable file
|
After Width: | Height: | Size: 13 KiB |
BIN
data/www/favicon/apple-icon-120x120.png
Executable file
|
After Width: | Height: | Size: 14 KiB |
BIN
data/www/favicon/apple-icon-144x144.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
BIN
data/www/favicon/apple-icon-152x152.png
Executable file
|
After Width: | Height: | Size: 20 KiB |
BIN
data/www/favicon/apple-icon-180x180.png
Executable file
|
After Width: | Height: | Size: 26 KiB |
BIN
data/www/favicon/apple-icon-57x57.png
Executable file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
data/www/favicon/apple-icon-60x60.png
Executable file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
data/www/favicon/apple-icon-72x72.png
Executable file
|
After Width: | Height: | Size: 6.9 KiB |
BIN
data/www/favicon/apple-icon-76x76.png
Executable file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
data/www/favicon/apple-icon-precomposed.png
Executable file
|
After Width: | Height: | Size: 28 KiB |
BIN
data/www/favicon/apple-icon.png
Executable file
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
BIN
data/www/favicon/favicon-16x16.png
Normal file → Executable file
|
Before Width: | Height: | Size: 547 B After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
BIN
data/www/favicon/favicon-32x32.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
data/www/favicon/favicon-96x96.png
Normal file → Executable file
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 34 KiB |
BIN
data/www/favicon/ms-icon-144x144.png
Executable file
|
After Width: | Height: | Size: 18 KiB |
BIN
data/www/favicon/ms-icon-150x150.png
Executable file
|
After Width: | Height: | Size: 20 KiB |
BIN
data/www/favicon/ms-icon-310x310.png
Executable file
|
After Width: | Height: | Size: 61 KiB |
BIN
data/www/favicon/ms-icon-70x70.png
Executable file
|
After Width: | Height: | Size: 6.8 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 536 B |
|
Before Width: | Height: | Size: 438 B |
|
Before Width: | Height: | Size: 876 B |
|
Before Width: | Height: | Size: 545 B |
|
Before Width: | Height: | Size: 435 B |
|
Before Width: | Height: | Size: 799 B |
|
Before Width: | Height: | Size: 595 B |
|
Before Width: | Height: | Size: 804 B |
|
Before Width: | Height: | Size: 425 B |
|
Before Width: | Height: | Size: 517 B |
|
Before Width: | Height: | Size: 871 B |
|
Before Width: | Height: | Size: 496 B |
|
Before Width: | Height: | Size: 720 B |
|
Before Width: | Height: | Size: 430 B |
|
Before Width: | Height: | Size: 444 B |
|
Before Width: | Height: | Size: 689 B |
|
Before Width: | Height: | Size: 863 B |
|
Before Width: | Height: | Size: 559 B |
|
Before Width: | Height: | Size: 577 B |
|
Before Width: | Height: | Size: 706 B |
|
Before Width: | Height: | Size: 807 B |
|
Before Width: | Height: | Size: 661 B |
|
Before Width: | Height: | Size: 638 B |
|
Before Width: | Height: | Size: 446 B |
|
Before Width: | Height: | Size: 487 B |
|
Before Width: | Height: | Size: 499 B |
|
Before Width: | Height: | Size: 789 B |
|
Before Width: | Height: | Size: 445 B |
|
Before Width: | Height: | Size: 319 B |
|
Before Width: | Height: | Size: 434 B |
|
Before Width: | Height: | Size: 387 B |
|
Before Width: | Height: | Size: 596 B |
|
Before Width: | Height: | Size: 540 B |
|
Before Width: | Height: | Size: 913 B |