Skip to content

Commit

Permalink
Merge pull request #4 from bluecraank/bootstrap
Browse files Browse the repository at this point in the history
Change frontend framework to bootstrap
  • Loading branch information
bluecraank authored Feb 19, 2024
2 parents 889ab84 + 9eba70c commit 9e85169
Show file tree
Hide file tree
Showing 52 changed files with 2,345 additions and 2,083 deletions.
55 changes: 33 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
<h1 align="center" id="title">open-signage</h1>

<p id="description">Very easy way to create signage for digital content based on web browser built with Laravel</p>
<p id="description">Create signage for digital content based on web browser built with Laravel</p>

# This app is usable on any system, on any browser
- Your monitor only need a webbrowser
- Use Raspberry, Windows, FireTV, SmartTV or anything which has a browser with javascript
# Requirements
- Your monitor only needs a webbrowser with javascript
- Use a Raspberry Pi 3B or higher or any other device with browser
- Not supported: Raspberry Zero 2W, Raspberry Pi 2B
- Memory amount depends on amount of slides, i recommend at least 1GB
- Memory amount depends on amount of slides, recommend at least 1GB
- Recommendation: <a href="https://github.com/guysoft/FullPageOS">FullPageOS</a>

# Usage
- Export Presentation as PDF and upload document
- Background processing starts and generates images from each page
- Create and register monitor
- Assign presentation to monitor
- Display presentation on monitor
- Create schedule or group to easily assign mutliple devices one presentation
- Assign presentation to monitor, group or schedule
- Automatically display presentation on monitor
- Create schedules or groups to easily assign presentations to multiple devices

# Functions
- Create, manage, delete schedules
- LDAP-Login only
- Create, manage, delete devices
- Create, manage, delete groups
- Create, manage, delete presentations
- Create, manage, delete devices
- Assign roles to users
- Create, manage, delete schedules
- Manage monitor settings (e.g Slide-duration)
- Discover url for easy mass deployment (IP recognition)
- Logging of actions in UI
- Rightmanagement

# Clientside browser functions
- Hide cursor
- Hides the cursor
- Force monitor reload on request
- Force monitor reload after x hours to prevent memory leak
- Select and set loading screen
- Configure animation times and more


# Configuration
## Docker
- Edit docker-compose.yml to your needs

## Native
- Move env.example to .env
- Setup LDAP Connection
Expand Down Expand Up @@ -69,16 +71,27 @@ LDAP_ALLOWED_GROUP="CN=MIS,OU=Groups,DC=ldap,DC=server"

## Install native
### Requirements
```
apt install php8.2 php8.2-imagick php8.2-mbstring php8.2-curl php8.2-ldap php8.2-bcmath
```
- php8.2
- npm
- composer
- php ldap extension
- php imagick extension
- ghostscript
- Replace imagick policy
```sed -ri -e 's/<policy domain="coder" rights="none" pattern="PDF" \/>/<policy domain="coder" rights="read|write" pattern="PDF" \/>/g' /etc/ImageMagick-6/policy.xml```

### Installation
- ```git clone https://github.com/bluecraank/open-signage```
- ```cd open-signage```
- ```composer install```
- ```npm install```
- ```npm run build```
- ```php artisan migrate --force```
- ```php artisan db:seed```
- Serve with ```php artisan serve``` (Not recommended)
- ```php artisan serve``` (Not recommended)
- Use apache/nginx/caddy and configure root directory to ./public

## Words about reverse proxy
Expand All @@ -94,15 +107,13 @@ SSO_BYPASS_DOMAIN_VERIFICATION=false
```

## Deploy
- Example chromium
- use FullPageOS <a href="https://github.com/guysoft/FullPageOS">https://github.com/guysoft/FullPageOS</a>
- or chromium parameters
```chromium --enable-logging --log-level=2 --v=0 --kiosk --touch-events=enabled --disable-pinch --noerrdialogs --simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT' --disable-session-crashed-bubble --disable-component-update --overscroll-history-navigation=0 --disable-features=Translate --autoplay-policy=no-user-gesture-required --app=https://mis.dc.local/discover```
- or use FullPageOS <a href="https://github.com/guysoft/FullPageOS">https://github.com/guysoft/FullPageOS</a>

### SSL Errors
- Add --ignore-certificate-errors to chromium flags (Not recommended, add Root-CA if internal, or fix ssl error)

# Contribution
- Feel free to contribute and help to improve it
- Add --ignore-certificate-errors to chromium flags (Not recommended)
- Add root-ca of your organization or domain

# License
The MIT License (MIT). Please see License File for more information.
Expand Down
9 changes: 8 additions & 1 deletion app/Http/Controllers/DeviceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public function register(Request $request)

$device->save();

return redirect()->route('devices.index')->with('success', __('Device successfully registered'));
return redirect()->back()->with('success', __('Device successfully registered'));
}

/**
Expand Down Expand Up @@ -219,4 +219,11 @@ public function discover(Request $request) {

return redirect()->route('devices.monitor', ['secret' => $secret]);
}

static function getActiveInactiveDevices() {
$active = Device::where('active', true)->count();
$inactive = Device::where('active', false)->count();

return ['active' => $active, 'inactive' => $inactive];
}
}
2 changes: 2 additions & 0 deletions app/Http/Controllers/MonitorController.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public function show($secret)
}

public function hasUpdate(Request $request) {
// Trigger schedule check
ScheduleController::checkForExpiredSchedules();

$validator = Validator::make(
$request->all(),
Expand Down
30 changes: 28 additions & 2 deletions app/Http/Controllers/PresentationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use App\Models\Log;
use App\Models\Presentation;
use App\Models\Slide;
use App\Models\Group;
use App\Models\Device;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\File;
Expand All @@ -17,7 +19,31 @@ class PresentationController extends Controller
public function index()
{
$presentations = Presentation::all()->sortBy('name');
return view('presentations.index', compact('presentations'));

$groups = Group::all()->sortBy('name');
$devices = Device::all()->sortBy('name');

$countUsed = 0;
$countUnused = 0;

// Loop through groups and devices and see which presentations are unused
foreach($presentations as $presentation) {
foreach($groups as $group) {
if($group->presentation?->id == $presentation->id) {
$countUsed++;
break;
}
}

foreach($devices as $device) {
if($device->presentation?->id == $presentation->id) {
$countUsed++;
break;
}
}
}

return view('presentations.index', compact('presentations', 'countUsed', 'countUnused'));
}

/**
Expand Down Expand Up @@ -196,7 +222,7 @@ public function destroy(string $id)
}

static function getCurrentPresentationsInProgress() {
$presentations = Presentation::where('processed', false)->get();
$presentations = Presentation::where('processed', false)->latest()->take(2)->get();

if(!$presentations) {
return null;
Expand Down
73 changes: 60 additions & 13 deletions app/Http/Controllers/ScheduleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use App\Models\Device;
use App\Models\Group;
use App\Models\Log;
use App\Models\Presentation;
use App\Models\Schedule;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -46,30 +47,33 @@ public function store(Request $request)
'devices' => 'nullable|array',
'groups' => 'nullable|array',
'presentation_id' => 'required|integer|exists:presentations,id',
'del_pres_after_schedule_ends' => 'nullable|in:"on"',
]);

if(empty($request->devices) && empty($request->groups)) {
return redirect()->back()->withErrors(['message' => __('You must select at least one device or group')]);
}

$enabled = true;
// if($request->has('submit_without_enable')) {
// $enabled = false;
// }
if($request->has('del_pres_after_schedule_ends') && $request->del_pres_after_schedule_ends == 'on') {
$del_pres_after_schedule_ends = true;
} else {
$del_pres_after_schedule_ends = false;
}

// Date to timestamp
$start_date = strtotime($request->start_date);
$end_date = strtotime($request->end_date);

$schedule = Schedule::create([
Schedule::create([
'name' => $request->name,
'start_time' => $start_date,
'end_time' => $end_date,
'devices' => $request->devices ?? [],
'groups' => $request->groups ?? [],
'presentation_id' => $request->presentation_id,
'enabled' => $enabled,
'created_by' => Auth::user()->name ?? 'N/A'
'enabled' => true,
'created_by' => Auth::user()->name ?? 'N/A',
'delete_presentation' => $del_pres_after_schedule_ends,
]);

return redirect()->route('schedules.index')->with('success', __('Schedule created'));
Expand Down Expand Up @@ -111,17 +115,13 @@ public function update(Request $request, string $id)
'devices' => 'nullable|array',
'groups' => 'nullable|array',
'presentation_id' => 'required|integer|exists:presentations,id',
'del_pres_after_schedule_ends' => 'nullable|in:"on"',
]);

if(empty($request->devices) && empty($request->groups)) {
return redirect()->back()->withErrors(['message' => __('You must select at least one device or group')]);
}

$enabled = false;
if($request->has('enabled') && $request->enabled == 'on') {
$enabled = true;
}

// Date to timestamp
$start_date = strtotime($request->start_date);
$end_date = strtotime($request->end_date);
Expand All @@ -134,7 +134,8 @@ public function update(Request $request, string $id)
'devices' => $request->devices ?? [],
'groups' => $request->groups ?? [],
'presentation_id' => $request->presentation_id,
'enabled' => $enabled,
'enabled' => true,
'delete_presentation' => $request->has('del_pres_after_schedule_ends') && $request->del_pres_after_schedule_ends == 'on' ? true : false,
]);

return redirect()->route('schedules.index')->with('success', __('Schedule updated'));
Expand All @@ -155,4 +156,50 @@ public function destroy(string $id)

return redirect()->route('schedules.index')->with('success', __('Schedule deleted'));
}

static function checkForExpiredSchedules() {
$currentTimestamp = now();

$expiredSchedules = Schedule::where('end_time', '<', $currentTimestamp)->get();

// dd($expiredSchedules);

foreach($expiredSchedules as $schedule) {
if($schedule->delete_presentation == 1) {
$presentation = $schedule->presentation;

if($presentation) {
if($presentation->devices()->count() == 0 && $presentation->groups()->count() == 0) {
Log::create([
'ip_address' => "127.0.0.1",
'username' => 'System',
'action' => __('log.presentation_deleted_because_schedule', ['name' => $presentation->name, 'schedule' => $schedule->name,]),
]);

$presentation->delete();
} else {
Log::create([
'ip_address' => "127.0.0.1",
'username' => 'System',
'action' => __('log.presentation_not_deleted_because_schedule', ['name' => $presentation->name, 'schedule' => $schedule->name,]),
]);

$schedule->delete_presentation = false;
$schedule->save();

return false;
}
}

// Disable delete_presentation after deleting assigned presentation to avoid double deletion
$schedule->delete_presentation = false;
$schedule->save();

return true;
}

}

return false;
}
}
21 changes: 20 additions & 1 deletion app/Livewire/LiveMonitorOverview.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,28 @@

class LiveMonitorOverview extends Component
{
public $sort_by = 'name';

public $sortToColumn = [
'name' => 'name',
'group' => 'group_id',
'status' => 'active',
'updated' => 'updated_at',
'presentation' => 'presentation_id',
];

public function render()
{
$devices = Device::all();
$validSorts = ['name', 'group', 'status', 'updated', 'presentation'];

if (!in_array($this->sort_by, $validSorts)) {
$this->sort_by = 'name';
}

$devices = Device::all()->sortBy($this->sortToColumn[$this->sort_by]);



$presentation = Presentation::all()->keyBy('id')->toArray();

return view('livewire.live-monitor-overview', ['devices' => $devices, 'presentation' => $presentation]);
Expand Down
12 changes: 9 additions & 3 deletions app/Models/Device.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

class Device extends Model
{
use \Illuminate\Database\Eloquent\Factories\HasFactory;


protected static function booted(): void
{
static::created(function (Device $device) {
Expand Down Expand Up @@ -138,9 +141,10 @@ public function presentationFromSchedule() {
public function isActive() {
$now = new \DateTime();
$lastSeen = new \DateTime($this->last_seen);
$this->active = true;

if(!$this->registered) {
return '🟠';
$this->active = false;
}

$diff = $now->diff($lastSeen);
Expand All @@ -157,9 +161,11 @@ public function isActive() {

$seconds = $daysInSecs + $hoursInSecs + $minsInSecs + $diff->s;
if ($seconds > $refresh_interval*2.5 || $this->created_at == $this->updated_at) {
return '🔴';
$this->active = false;
}

return '🟢';
$this->save();

return $this->active;
}
}
Loading

0 comments on commit 9e85169

Please sign in to comment.