Added announcement system

This commit is contained in:
Josef Citrine 2016-11-11 19:39:31 +00:00
parent fa7e04aee9
commit ec8b64f494
10 changed files with 327 additions and 2 deletions

View file

@ -0,0 +1,45 @@
<?php
/**
* Pony.fm - A community for pony fan music.
* Copyright (C) 2016 Josef Citrine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Poniverse\Ponyfm\Http\Controllers\Api\Web;
use Carbon\Carbon;
use Poniverse\Ponyfm\Http\Controllers\Controller;
use Poniverse\Ponyfm\Models\Announcement;
use Response;
class AnnouncementsController extends Controller {
public function getIndex() {
$currentDate = Carbon::now();
$query = Announcement::whereNotNull('start_time')
->whereNotNull('end_time')
->where('start_time', '<', $currentDate)
->where('end_time', '>', $currentDate)
->orderBy('start_time', 'desc');
$announcement = $query->first();
return Response::json(
["announcement" => $announcement],
200
);
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* Pony.fm - A community for pony fan music.
* Copyright (C) 2016 Josef Citrine
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Poniverse\Ponyfm\Models;
use Illuminate\Database\Eloquent\Model;
class Announcement extends Model {
protected $table = 'announcements';
protected $casts = [
'links' => 'array',
'tracks' => 'array'
];
const TYPE_GENERIC = 1;
const TYPE_WARNING_ALERT = 2;
const TYPE_SERIOUS_ALERT = 3;
const TYPE_CUSTOM = 4;
}

View file

@ -0,0 +1,39 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAnnouncementsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('announcements', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('text_content', 65535)->nullable();
$table->integer('announcement_type_id')->unsigned()->nullable();
$table->json('links')->nullable();
$table->json('tracks')->nullable();
$table->string('css_class')->nullable();
$table->string('template_file')->nullable();
$table->dateTime("start_time")->nullable();
$table->dateTime("end_time")->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('announcements');
}
}

View file

@ -1,4 +1,7 @@
<div class="dashboard stretch-to-bottom"> <div class="dashboard stretch-to-bottom">
<section class="announce-wrapper" ng-class="announceWrapperClass">
<div id="announcement" ng-show="announcement != null" ng-class="announcementClass"></div>
</section>
<section class="recent-tracks"> <section class="recent-tracks">
<h1> <h1>
<a href="/tracks"><i class="fa fa-music"></i> see more</a> <a href="/tracks"><i class="fa fa-music"></i> see more</a>

View file

@ -0,0 +1,12 @@
<div class="announce-content">
<h2>{{ ::announcement.title }}</h2>
<p marked="announcement.text_content"></p>
</div>
<div class="announce-actions">
<span ng-repeat="link in announcement.links">
<a ng-href="{{ ::link.url }}" target="_blank">{{ ::link.title }}</a>
</span>
<a href="#" ng-click="announcement.dontShowAgain()">Don't show again</a>
</div>
<a href="#" class="dismiss-button" ng-click="announcement.dismiss()"><i class="fa fa-times"></i></a>
<i class="fa fa-exclamation-triangle announce-bg-icon" aria-hidden="true"></i>

View file

@ -0,0 +1,12 @@
<div class="announce-content">
<h2>{{ ::announcement.title }}</h2>
<p marked="announcement.text_content"></p>
</div>
<div class="announce-actions">
<span ng-repeat="link in announcement.links">
<a ng-href="{{ ::link.url }}" target="_blank">{{ ::link.title }}</a>
</span>
<a href="#" ng-click="announcement.dontShowAgain()">Don't show again</a>
</div>
<a href="#" class="dismiss-button" ng-click="announcement.dismiss()"><i class="fa fa-times"></i></a>
<i class="fa fa-info-circle announce-bg-icon" aria-hidden="true"></i>

View file

@ -20,13 +20,49 @@ window.pfm.preloaders['dashboard'] = [
] ]
module.exports = angular.module('ponyfm').controller "dashboard", [ module.exports = angular.module('ponyfm').controller "dashboard", [
'$scope', 'dashboard', 'auth', '$http' '$scope', 'dashboard', 'auth', '$http', 'announcements', '$compile'
($scope, dashboard, auth, $http) -> ($scope, dashboard, auth, $http, announcements, $compile) ->
$scope.recentTracks = null $scope.recentTracks = null
$scope.popularTracks = null $scope.popularTracks = null
$scope.announcementClass = 'disabled'
$scope.announceWrapperClass = 'disabled'
$scope.loadAnnouncementTemplate = (url) ->
$http.get('/templates/' + url).success (templateContent) ->
compiledHtml = $compile(templateContent)($scope)
$('#announcement').append(compiledHtml)
dashboard.refresh().done (res) -> dashboard.refresh().done (res) ->
$scope.recentTracks = res.recent_tracks $scope.recentTracks = res.recent_tracks
$scope.popularTracks = res.popular_tracks $scope.popularTracks = res.popular_tracks
announcements.refresh().done (ann) ->
$scope.announcement = ann
if $scope.announcement != null
if parseInt($.cookie('hide-announcement')) != parseInt($scope.announcement.id)
$scope.announcement.dismiss = () ->
$scope.announceWrapperClass = 'disabled'
$scope.announcement.dontShowAgain = () ->
$scope.announcement.dismiss()
$.cookie('hide-announcement', $scope.announcement.id)
switch $scope.announcement.announcement_type_id
when 1
$scope.announcementClass = "simple-announce " + $scope.announcement.css_class
$scope.announceWrapperClass = null
$scope.loadAnnouncementTemplate('partials/default-announcement.html')
when 2
$scope.announcementClass = "alert-announce " + $scope.announcement.css_class
$scope.announceWrapperClass = null
$scope.loadAnnouncementTemplate('partials/alert-announcement.html')
when 3
$scope.announcementClass = "serious-alert-announce " + $scope.announcement.css_class
$scope.announceWrapperClass = null
$scope.loadAnnouncementTemplate('partials/alert-announcement.html')
when 4
$scope.announcementClass = $scope.announcement.css_class
$scope.announceWrapperClass = null
$scope.loadAnnouncementTemplate($scope.announcement.template_url)
] ]

View file

@ -0,0 +1,32 @@
# Pony.fm - A community for pony fan music.
# Copyright (C) 2016 Josef Citrine
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
module.exports = angular.module('ponyfm').factory('announcements', [
'$rootScope', '$http'
($rootScope, $http) ->
def = null
self =
refresh: (force) ->
force = force || false
return def if !force && def
def = new $.Deferred()
$http.get('/api/web/announcements').success (announcementResponse) ->
def.resolve(announcementResponse.announcement)
def.promise()
self
])

View file

@ -94,6 +94,113 @@
width: 37.5%; width: 37.5%;
} }
.announce-wrapper {
width: 100%;
margin-bottom: 5px;
&.disabled {
margin: 0;
display: none;
}
#announcement {
width: 100%;
box-shadow: 0 1px 4px rgba(0,0,0,0.12), 0 2px 3px rgba(0,0,0,0.24);
border-radius: 3px;
position: relative;
overflow: hidden;
max-width: 1200px;
margin-left: auto;
margin-right: auto;
.announce-content {
padding: 10px;
overflow: hidden;
@media (max-width: 720px) {
padding-left: 10px !important;
}
}
.announce-actions {
padding: 5px 15px 15px;
position: relative;
background: inherit;
z-index: 2;
&.border {
border-top: 1px solid rgba(160,160,160,0.2);
}
a {
margin-right: 20px;
font-weight: bold;
}
}
&.simple-announce {
.announce-content {
padding-left: 75px;
}
}
&.alert-announce, &.serious-alert-announce {
.announce-content {
padding-left: 95px;
}
}
&.alert-announce {
background: #f57f17;
}
&.serious-alert-announce {
background: #d84315
}
&.simple-announce {
background: #894d8f;
}
&.disabled {
display: none;
}
.dismiss-button {
position: absolute;
top: 0;
right: 0;
padding: 6px 20px;
font-size: 22px;
}
h2, p, a {
color: #fff;
}
p {
margin: 0;
}
.announce-bg-icon {
color: #fff;
opacity: 0.6;
top: -13px;
left: -20px;
position: absolute;
font-size: 100px;
transform: rotate(-9deg);
z-index: 1;
@media (max-width: 720px) {
opacity: 0.1;
right: 0;
left: auto;
}
}
}
}
.news { .news {
width: 25%; width: 25%;

View file

@ -116,6 +116,8 @@ Route::group(['prefix' => 'api/web'], function () {
Route::get('/dashboard', 'Api\Web\DashboardController@getIndex'); Route::get('/dashboard', 'Api\Web\DashboardController@getIndex');
Route::get('/announcements', 'Api\Web\AnnouncementsController@getIndex');
Route::group(['middleware' => 'auth'], function () { Route::group(['middleware' => 'auth'], function () {
Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload'); Route::post('/tracks/upload', 'Api\Web\TracksController@postUpload');
Route::get('/tracks/{id}/upload-status', 'Api\Web\TracksController@getUploadStatus'); Route::get('/tracks/{id}/upload-status', 'Api\Web\TracksController@getUploadStatus');