Skip to content
86 changes: 86 additions & 0 deletions app/Http/Controllers/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace App\Http\Controllers;

use App\Models\News;
use App\Models\Prompt\Prompt;
use App\Models\Sales\Sales;
use App\Models\SitePage;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
Expand Down Expand Up @@ -43,4 +46,87 @@ public function getCreditsPage() {
'extensions' => DB::table('site_extensions')->get(),
]);
}

/**
* Shows the site calendar page.
*
* @return \Illuminate\Contracts\Support\Renderable
*/
public function getCalendarPage() {
return view('pages.calendar');
}

/**
* Returns all events from news, sales and prompts formatted as json.
*
* @return \Illuminate\Http\JsonResponse
*/
public function getCalendarEvents() {
$start_at = request()->get('start');
$end_at = request()->get('end');

// get all prompts within time frame, if hide_before_start is set or hide_after_end is set, filter them out if they are not within the prompt time frame
$prompts = Prompt::where('is_active', 1)->where('start_at', '>', $start_at)->where('end_at', '<', $end_at)
->where(function ($query) {
$query->where('hide_before_start', 0)->orWhere('hide_after_end', 0)
->orWhere(function ($query) {
$query->where('hide_before_start', 1)->where('start_at', '<=', now());
})
->orWhere(function ($query) {
$query->where('hide_after_end', 1)->where('end_at', '>=', now());
});
})->sortStart()->get();
// get all news as long as either created_at is within timeframe, or if post_at is set, if post_at is within timeframe
$news = News::visible()->where(function ($query) use ($start_at, $end_at) {
$query->where('created_at', '>', $start_at)->where('created_at', '<', $end_at)
->orWhere(function ($query) use ($start_at, $end_at) {
$query->where('post_at', '>', $start_at)->where('post_at', '<', $end_at);
});
})->get();
// get all sales as long as either created_at is within timeframe, or if post_at is set, if post_at is within timeframe
$sales = Sales::visible()->where(function ($query) use ($start_at, $end_at) {
$query->where('created_at', '>', $start_at)->where('created_at', '<', $end_at)
->orWhere(function ($query) use ($start_at, $end_at) {
$query->where('post_at', '>', $start_at)->where('post_at', '<', $end_at);
});
})->get();

$array = [];
foreach ($prompts as $prompt) {
$array[] = [
'id' => $prompt->id,
'title' => $prompt->name,
'url' => $prompt->url,
'start' => $prompt->start_at->toW3cString(),
'end' => $prompt->end_at->toW3cString(),
'color' => config('lorekeeper.settings.calendar_colours.prompts'),
];
}
// set start to start of 'post_at' day, if post_at is set, else use created_at
// set end to end of 'post_at' day, if post_at is set, else use created_at
foreach ($news as $news_item) {
$array[] = [
'id' => $news_item->id,
'title' => $news_item->title,
'url' => $news_item->url,
'start' => $news_item->post_at ? $news_item->post_at->startOfDay()->toW3cString() : $news_item->created_at->startOfDay()->toW3cString(),
'allDay' => 'true',
'color' => config('lorekeeper.settings.calendar_colours.news'),
];
}
foreach ($sales as $sale) {
$array[] = [
'id' => $sale->id,
'title' => $sale->title,
'url' => $sale->url,
'start' => $sale->post_at ? $sale->post_at->startOfDay()->toW3cString() : $sale->created_at->startOfDay()->toW3cString(),
// if there is a comment_open_at set, set end to that, else set end to start of next day
'end' => $sale->comments_open_at ? $sale->comments_open_at->endOfDay()->toW3cString() : null,
'allDay' => 'true',
'color' => config('lorekeeper.settings.calendar_colours.sales'),
];
}

return response()->json($array);
}
}
2 changes: 1 addition & 1 deletion app/Models/Gallery/GallerySubmission.php
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ public function getExcerptAttribute() {
* @return array
*/
public function getVoteData($withUsers = 0) {
$voteData['raw'] = json_decode($this->attributes['vote_data'], true);
$voteData['raw'] = $this->vote_data;

// Only query users if necessary, and condense to one query per submission
if ($withUsers) {
Expand Down
18 changes: 18 additions & 0 deletions app/Models/News.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,4 +189,22 @@ public function toFeedItem(): FeedItem {
'authorName' => $this->user->name,
]);
}

/**
* Returns news in a JSON format for the calendar.
*
* @return array
*/
public static function getCalendarEvents() {
$events = [];
foreach (self::visible()->get() as $news) {
$events[] = [
'title' => $news->title,
'start' => $news->post_at->toDateString(),
'url' => $news->url,
];
}

return $events;
}
}
13 changes: 13 additions & 0 deletions config/lorekeeper/settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,19 @@
*/
'wysiwyg_comments' => 1,

/*
| Calendar Colours
|--------------------------------------------------------------------------
|
| Colours used for event calendar entries.
|
*/
'calendar_colours' => [
'prompt' => '#4c96d4',
'news' => '#ad283e',
'sales' => '#f5a623',
],

/*
|--------------------------------------------------------------------------
| Allow Gallery Submissions on Prompts
Expand Down
6 changes: 6 additions & 0 deletions public/js/calendar.min.js

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions resources/views/layouts/_nav.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@
Activity
</a>
<div class="dropdown-menu" aria-labelledby="queueDropdown">
<a class="dropdown-item" href="{{ url('calendar') }}">
Calendar
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{{ url('submissions') }}">
Prompt Submissions
</a>
Expand Down
47 changes: 47 additions & 0 deletions resources/views/pages/calendar.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@extends('layouts.app')

@section('title')
Calendar
@endsection

@section('sidebar')
<ul>
<li class="sidebar-header"><a href="{{ url('/calendar') }}" class="card-link">Calendar</a></li>
<li class="sidebar-section">
<div class="sidebar-section-header">Items</div>
<div class="sidebar-item"><a href="{{ url('prompts') }}" class="{{ set_active('prompts') }}">Prompts</a></div>
<div class="sidebar-item"><a href="{{ url('news') }}" class="{{ set_active('news') }}">News</a></div>
<div class="sidebar-item"><a href="{{ url('sales') }}" class="{{ set_active('sales') }}">Sales</a></div>
</li>
</ul>
@endsection

@section('content')
{!! breadcrumbs(['World' => 'world', 'Calendar' => 'world/calendar']) !!}
<h1>Calendar</h1>

<div id='calendar'></div>

<script src="{{ asset('js/calendar.min.js') }}"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
const calendarEl = document.getElementById('calendar')
const calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'dayGridMonth',
lazyFetching: true,
height: '60vh',
timeZone: "{{ config('app.timezone') }}",
headerToolbar: {
left: 'prev,next',
center: 'title',
right: 'dayGridMonth multiMonthYear listWeek',
},
eventSources: [{
url: "{{ url('calendar/events') }}",
format: 'json',
}]
})
calendar.render()
})
</script>
@endsection
2 changes: 2 additions & 0 deletions routes/lorekeeper/browse.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@
**************************************************************************************************/
Route::get('credits', 'PageController@getCreditsPage');
Route::get('info/{key}', 'PageController@getPage');
Route::get('calendar', 'PageController@getCalendarPage');
Route::get('calendar/events', 'PageController@getCalendarEvents');

/**************************************************************************************************
Raffles
Expand Down
Loading