Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement simple playlists of songs for events.
- Loading branch information
Showing
10 changed files
with
281 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<?php | ||
|
||
use Nette\Database\Connection, | ||
Nette\Database\Table\Selection; | ||
|
||
/** | ||
* An ordered many-to-many mapping between songs and events. | ||
*/ | ||
class PlaylistItems extends Selection | ||
{ | ||
public function __construct(\Nette\Database\Connection $connection) | ||
{ | ||
parent::__construct('corale_playlist_item', $connection); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
<?php | ||
|
||
use Nette\Application\UI\Form; | ||
|
||
class PlaylistPresenter extends BasePresenter | ||
{ | ||
/** @persistent */ | ||
private $eventId; | ||
|
||
/** @var Songs */ | ||
private $songQuery; | ||
|
||
public function actionUpdateItem($eventId, $songId, $order) { | ||
$this->ensureLoggedUser(); | ||
|
||
$this->eventId = $eventId; | ||
$values = array(); | ||
if ($order) { | ||
$values['ord'] = $order; | ||
} | ||
$key = array('event_id' => $eventId, 'song_id' => $songId); | ||
$playlistItem = $this->context->createPlaylistItems()->where($key)->fetch(); | ||
if ($playlistItem) { | ||
$this->context->createPlaylistItems()->where($key)->update($values); | ||
$this->flashMessage("Písnička v playlistu byla upravena."); | ||
} else { | ||
$values['event_id'] = $eventId; | ||
$values['song_id'] = $songId; | ||
$this->context->createPlaylistItems()->insert($values); | ||
$this->flashMessage("Písnička byla přidána do playlistu."); | ||
} | ||
$this->redirect('edit', array('eventId' => $eventId)); | ||
} | ||
|
||
public function actionDelete($eventId, $songId) { | ||
$this->ensureLoggedUser(); | ||
|
||
$key = array('event_id' => $eventId, 'song_id' => $songId); | ||
$this->context->createPlaylistItems()->where($key)->delete(); | ||
// TODO: hande the situation where the playlist item is badly specified | ||
// or does not exist | ||
$this->flashMessage("Písnička byla smazána z playlistu."); | ||
$this->redirect('edit', array('eventId' => $eventId)); | ||
} | ||
|
||
public function actionDefault($eventId) { | ||
$this->eventId = $eventId; | ||
} | ||
|
||
public function actionEdit($eventId) { | ||
$this->eventId = $eventId; | ||
|
||
$this->ensureLoggedUser(); | ||
} | ||
|
||
public function renderDefault() { | ||
$this->template->eventId = $this->eventId; | ||
$this->template->playlist = $this->getPlaylist($this->eventId); | ||
} | ||
|
||
public function renderEdit() { | ||
$this->template->eventId = $this->eventId; | ||
$this->template->playlist = $this->getPlaylist($this->eventId); | ||
} | ||
|
||
public function getPlaylist($eventId) { | ||
$query = <<<EOQ | ||
SELECT s.id id, s.title title, p.ord `order` | ||
FROM corale_song s | ||
JOIN corale_playlist_item p ON s.id = p.song_id | ||
JOIN corale_event e ON e.id = p.event_id | ||
WHERE p.event_id = ? | ||
ORDER BY p.ord, s.title | ||
EOQ; | ||
return $this->context->createPlaylistItems()->getConnection()->query($query, $eventId); | ||
} | ||
|
||
// TODO: use AJAX | ||
public function actionAdd($eventId, $query) | ||
{ | ||
$this->eventId = $eventId; | ||
$this->songQuery = $query; | ||
$this["songSearchForm"]->setDefaults(array('query' => $this->songQuery)); | ||
} | ||
|
||
public function renderAdd() { | ||
$q = $this->context->createSongs(); | ||
if ($this->songQuery) { | ||
$term = "%$this->songQuery%"; | ||
$q->where("title LIKE ? OR author LIKE ? OR description LIKE ?", | ||
array($term, $term, $term)); | ||
} | ||
$q->order('title'); | ||
$this->template->songs = $q; | ||
$this->template->eventId = $this->eventId; | ||
} | ||
|
||
protected function createComponentSongSearchForm() | ||
{ | ||
$form = new Form(); | ||
$form->addText('query', 'Hledaný text'); | ||
$form->addSubmit('search', 'Hledat'); | ||
return $form; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{block content} | ||
{include 'songSearchForm.latte'} | ||
|
||
{include 'songSearchList.latte'} | ||
{/block} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{var $title = 'Playlist'} | ||
|
||
{block content} | ||
|
||
{if $user->isLoggedIn()} | ||
<p> | ||
<a href="{link Event:details $eventId}" class="btn"> | ||
<i class="icon-search"></i> Detaily události | ||
</a> | ||
<a href="{link edit eventId=>$eventId}" class="btn btn-primary"> | ||
<i class="icon-pencil icon-white"></i> Upravit | ||
</a> | ||
</p> | ||
{/if} | ||
|
||
{foreach $playlist as $song} | ||
{first} | ||
{var $i = 0} | ||
<table class="table table-condensed playlist"> | ||
{/first} | ||
{? $i++} | ||
<tr> | ||
<td style="width: 2em">{$i}.</td> | ||
<td><a href="{link Song:details $song->id}">{$song->title}</td> | ||
</tr> | ||
{last} | ||
</table> | ||
{/last} | ||
{/foreach} | ||
|
||
{/block} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
{var $title = 'Playlist'} | ||
|
||
{block content} | ||
|
||
<p> | ||
<a href="{link Event:details $eventId}" class="btn"> | ||
<i class="icon-search"></i> Detaily události | ||
</a> | ||
<a href="{link default eventId=>$eventId}" class="btn"> | ||
<i class="icon-list"></i> Zobrazit playlist | ||
</a> | ||
<a href="{link add eventId=>$eventId}" class="btn btn-success"> | ||
<i class="icon-plus icon-white"></i> Přidat písničku | ||
</a> | ||
</p> | ||
|
||
|
||
{* TODO: AJAXify | ||
<p> | ||
<a href="#playlistItemAddModal" data-toggle="modal" class="btn btn-success"> | ||
<i class="icon-plus icon-white"></i> Přidat písničku | ||
</a> | ||
</p> | ||
<div class="modal hide" id="playlistItemAddModal"> | ||
<div class="modal-header"> | ||
<a class="close" data-dismiss="modal">×</a> | ||
<h3>Přidat písničky do playlistu</h3> | ||
</div> | ||
<div class="modal-body"> | ||
{control songSearchPanel} | ||
</div> | ||
<div class="modal-footer"> | ||
<a href="#" class="btn" data-dismiss="modal">Zpět</a> | ||
</div> | ||
</div> | ||
*} | ||
|
||
<style type="text/css"> | ||
table.playlist th.action, table.playlist td.action { | ||
width: 9em; | ||
text-align: center; | ||
} | ||
</style> | ||
|
||
{foreach $playlist as $song} | ||
{first} | ||
{var $i = 0} | ||
<table class="table table-condensed playlist"> | ||
{/first} | ||
{? $i++} | ||
<tr> | ||
<td style="width: 2em">{$i}.</td> | ||
<td class="song-title"><a href="{link Song:details $song->id}">{$song->title}</td> | ||
<td class="action"> | ||
<a {if $song->order > 0}href="{link Playlist:updateItem eventId=>$eventId, songId=>$song->id, order=>$song->order-1}"{/if} | ||
class="btn{if $song->order <= 0} disabled{/if}" title="Posunout nahoru"><i class="icon-chevron-up"></i></a> | ||
<a href="{link Playlist:updateItem eventId=>$eventId, songId=>$song->id, order=>$song->order+1}" | ||
class="btn" title="Posunout dolů"><i class="icon-chevron-down"></i></a> | ||
<a href="{link Playlist:delete eventId=>$eventId, songId=>$song->id}" | ||
class="btn" title="Odstranit z playlistu"><i class="icon-remove"></i></a> | ||
</td> | ||
</tr> | ||
{last} | ||
</table> | ||
{/last} | ||
{/foreach} | ||
|
||
{/block} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{form songSearchForm action=>"playlist/add", method=>"GET", class=>"form-search"} | ||
{input query class=>"input-medium search-query"} | ||
{input search class=>"btn"} | ||
{if isset($query) && $query} | ||
<a n:href="add id=>''" class="btn">Zrušit hledání</a> | ||
{/if} | ||
{/form} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{if isset($songs) and count($songs) > 0} | ||
<style type="text/css"> | ||
table th.action, table td.action { | ||
width: 7em; | ||
text-align: center; | ||
} | ||
</style> | ||
|
||
<table class="table table-striped table-bordered table-condensed"> | ||
<thead> | ||
<tr> | ||
<th class="title"><i class="icon-music"></i> Název</th> | ||
<th class="author"><i class="icon-music"></i> Autor</th> | ||
<th class="action"><i class="icon-cog"></i></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{foreach $songs as $song} | ||
<tr n:class="$iterator->isOdd() ? odd : even"> | ||
<td class="title"><a href="{link Song:details $song->id}"><strong>{$song->title}</strong></a></td> | ||
<td class="author">{$song->author}</td> | ||
<td class="action"> | ||
<a href="{link updateItem eventId=>$eventId, songId=>$song->id}" class="btn btn-success" title="Přidat do playlistu"> | ||
<i class="icon-plus icon-white"></i> | ||
</a> | ||
</td> | ||
</tr> | ||
{/foreach} | ||
</tbody> | ||
</table> | ||
{else} | ||
<p>Žádné písničky.</p> | ||
{/if} |