Added popup functionality and Library

* doPopup() JavaScript call creates a centered popup div with user
    defined width, height, title, content, and calls an optional
    callback function

* Library with currently non-modifiable book list, and a popup with the
    books' details

Signed-off-by: Gergely Polonkai <polesz@w00d5t0ck.info>
This commit is contained in:
Polonkai Gergely 2012-08-08 22:15:51 +02:00
parent 624e56389e
commit 55cde1594b
19 changed files with 1128 additions and 12 deletions

17
TODO
View File

@ -1,3 +1,5 @@
PDF header fix
User
FavouriteForumTopics
@ -28,7 +30,9 @@ PollAnswer
Article check if public
UserForumViewed
it should contain records that show the last viewed post in each forum topic
User
ForumTopic
timestamp of last visit
BlogPost
id
@ -55,17 +59,6 @@ ForumPost
last edit reason
edit count
Library
id
owner
author
title
year
borrowable
borrowed by
borrower returned
commentable
Event
last edited by
last edited timestamp

View File

@ -23,6 +23,7 @@ class AppKernel extends Kernel
new Ivory\CKEditorBundle\IvoryCKEditorBundle(),
new Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle(),
new Io\TcpdfBundle\IoTcpdfBundle(),
new FOS\JsRoutingBundle\FOSJsRoutingBundle(),
// Own bundles
new KekRozsak\FrontBundle\KekRozsakFrontBundle(),
new KekRozsak\SecurityBundle\KekRozsakSecurityBundle(),

View File

@ -0,0 +1,24 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your need!
*/
class Version20120801224509 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your need!
*/
class Version20120801224533 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("CREATE TABLE books (id INT AUTO_INCREMENT NOT NULL, author VARCHAR(100) NOT NULL, title VARCHAR(100) NOT NULL, year INT NOT NULL, commentable TINYINT(1) NOT NULL, PRIMARY KEY(id)) ENGINE = InnoDB");
$this->addSql("CREATE TABLE book_copies (id INT AUTO_INCREMENT NOT NULL, book_id INT NOT NULL, owner_id INT NOT NULL, borrower_id INT DEFAULT NULL, owner_comment LONGTEXT NOT NULL, borrowable TINYINT(1) NOT NULL, borrower_returned TINYINT(1) NOT NULL, INDEX IDX_F0A8D81116A2B381 (book_id), INDEX IDX_F0A8D8117E3C61F9 (owner_id), UNIQUE INDEX UNIQ_F0A8D81111CE312B (borrower_id), UNIQUE INDEX UNIQ_F0A8D8117E3C61F916A2B381 (owner_id, book_id), PRIMARY KEY(id)) ENGINE = InnoDB");
$this->addSql("ALTER TABLE book_copies ADD CONSTRAINT FK_F0A8D81116A2B381 FOREIGN KEY (book_id) REFERENCES books (id)");
$this->addSql("ALTER TABLE book_copies ADD CONSTRAINT FK_F0A8D8117E3C61F9 FOREIGN KEY (owner_id) REFERENCES users (id)");
$this->addSql("ALTER TABLE book_copies ADD CONSTRAINT FK_F0A8D81111CE312B FOREIGN KEY (borrower_id) REFERENCES users (id)");
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("ALTER TABLE book_copies DROP FOREIGN KEY FK_F0A8D81116A2B381");
$this->addSql("DROP TABLE books");
$this->addSql("DROP TABLE book_copies");
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your need!
*/
class Version20120806165106 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("CREATE TABLE book_would_borrow (book_id INT NOT NULL, user_id INT NOT NULL, INDEX IDX_7ED804D216A2B381 (book_id), INDEX IDX_7ED804D2A76ED395 (user_id), PRIMARY KEY(book_id, user_id)) ENGINE = InnoDB");
$this->addSql("CREATE TABLE book_would_buy (book_id INT NOT NULL, user_id INT NOT NULL, INDEX IDX_67D6BB5216A2B381 (book_id), INDEX IDX_67D6BB52A76ED395 (user_id), PRIMARY KEY(book_id, user_id)) ENGINE = InnoDB");
$this->addSql("ALTER TABLE book_would_borrow ADD CONSTRAINT FK_7ED804D216A2B381 FOREIGN KEY (book_id) REFERENCES books (id) ON DELETE CASCADE");
$this->addSql("ALTER TABLE book_would_borrow ADD CONSTRAINT FK_7ED804D2A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE");
$this->addSql("ALTER TABLE book_would_buy ADD CONSTRAINT FK_67D6BB5216A2B381 FOREIGN KEY (book_id) REFERENCES books (id) ON DELETE CASCADE");
$this->addSql("ALTER TABLE book_would_buy ADD CONSTRAINT FK_67D6BB52A76ED395 FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE");
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("DROP TABLE book_would_borrow");
$this->addSql("DROP TABLE book_would_buy");
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your need!
*/
class Version20120806165716 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("ALTER TABLE book_copies ADD buyable TINYINT(1) NOT NULL");
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("ALTER TABLE book_copies DROP buyable");
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace Application\Migrations;
use Doctrine\DBAL\Migrations\AbstractMigration,
Doctrine\DBAL\Schema\Schema;
/**
* Auto-generated Migration: Please modify to your need!
*/
class Version20120808111846 extends AbstractMigration
{
public function up(Schema $schema)
{
// this up() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("ALTER TABLE book_copies CHANGE owner_comment owner_comment LONGTEXT DEFAULT NULL");
}
public function down(Schema $schema)
{
// this down() migration is autogenerated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql");
$this->addSql("ALTER TABLE book_copies CHANGE owner_comment owner_comment LONGTEXT NOT NULL");
}
}

View File

@ -11,14 +11,32 @@
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript" src="{{ asset('js/jquery-cluetip/lib/jquery.hoverIntent.js')}}"></script>
<script type="text/javascript" src="{{ asset('js/jquery-cluetip/jquery.cluetip.js') }}"></script>
<script type="text/javascript" src="{{ asset('js/jquery.tinyscrollbar.min.js') }}"></script>
<script type="text/javascript" src="{{ asset('bundles/fosjsrouting/js/router.js') }}"></script>
<script type="text/javascript" src="{{ path('fos_js_routing_js', {callback: 'fos.Router.setData'}) }}"></script>
{% block additional_js %}{% endblock %}
</head>
<body>
<div id="popup-container">
<div id="popup-close"></div>
<div id="popup-inside">
<div id="popup-title"></div>
<div id="popup-scrollable">
<div class="scrollbar"><div class="track"><div class="thumb"><div class="end"></div></div></div></div>
<div class="viewport">
<div class="overview" id="popup-content"></div>
</div>
</div>
</div>
</div>
<div id="top-line-wrapper">
<div id="top-line">
{% if app.user %}
{% include ':Box:UserProfile.html.twig' %}
{% include ':Box:Events.html.twig' %}
<div id="konyvtar-gomb">
<a href="{{ path('KekRozsakFrontBundle_bookList') }}">[könyvtár gomb]</a>
</div>
{% else %}
{% include ':Box:Login.html.twig' %}
{% endif %}
@ -120,6 +138,40 @@
}
});
{% endif %}
jQuery.fn.center = function() {
this.css('top', Math.max(0, (($(window).height() - this.outerHeight()) / 2) + $(window).scrollTop()) + 'px');
this.css('left', Math.max(0, (($(window).width() - this.outerWidth()) / 2) + $(window).scrollLeft()) + 'px');
return this;
};
$('#popup-close').click(function() { $('#popup-container').fadeOut(); });
$('#popup-scrollable').tinyscrollbar();
function doPopup(title, content, url, w, h, callback)
{
$('#popup-title').html(title);
$('#popup-content').html(content);
$('#popup-container').css('width', w + 'px');
$('#popup-container').css('height', h + 'px');
$('#popup-inside').css('width', (w - 8) + 'px');
$('#popup-inside').css('height', (h - 8) + 'px');
$('#popup-scrollable').css('width', (w - 8) + 'px');
$('#popup-scrollable .viewport').css('width', (w - 28) + 'px');
$('#popup-scrollable .viewport').css('height', (h - 54) + 'px');
$('#popup-container').center();
$('#popup-container').fadeIn();
$.ajax({
method: 'GET',
url: url
}).done(function(data) {
$('#popup-content').html(data);
$('#popup-scrollable').tinyscrollbar();
$('.userdata').cluetip();
if (callback != null)
callback();
}).error(function() {
$('#popup-content').html('Nem sikerült betölteni a könyv adatait.');
});
}
</script>
{% block bottomscripts %}{% endblock %}
</body>

View File

@ -1,3 +1,6 @@
fos_js_routing:
resource: "@FOSJsRoutingBundle/Resources/config/routing/routing.xml"
KekRozsakAdminBundle:
resource: "@KekRozsakAdminBundle/Controller/"
type: annotation

View File

@ -26,6 +26,7 @@
"jms/di-extra-bundle": "1.0.*",
"doctrine/doctrine-migrations-bundle": "dev-master",
"egeloen/ckeditor-bundle": "dev-master",
"friendsofsymfony/jsrouting-bundle": "dev-master",
"gergelypolonkai/tcpdfbundle": "dev-master"
},
"scripts": {

View File

@ -0,0 +1,135 @@
<?php
namespace KekRozsak\FrontBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Symfony\Component\HttpFoundation\Response;
use KekRozsak\FrontBundle\Entity\Book;
use KekRozsak\FrontBundle\Entity\BookCopy;
class BookController extends Controller
{
/**
* @Route("/konyvtar", name="KekRozsakFrontBundle_bookList")
* @Template()
*/
public function listAction()
{
$query = $this->getDoctrine()->getEntityManager()->createQuery('SELECT b FROM KekRozsakFrontBundle:Book b ORDER BY b.author ASC, b.title ASC, b.year ASC');
$books = $query->getResult();
return array(
'books' => $books,
);
}
/**
* @Route("/konyvadat/{id}/ajax.{_format}", name="KekRozsakFrontBundle_bookAjaxData", defaults={"_format": "html"}, options={"expose": true})
* @Template()
* @ParamConverter("book")
*/
public function ajaxDataAction(Book $book)
{
return array(
'book' => $book,
);
}
/**
* @Route("/konyv/torles/{id}", name="KekRozsakFrontBundle_bookDeleteCopy", requirements={"id": "\d+"}, options={"expose": true})
* @ParamConverter("book")
*/
public function ajaxDeleteBookAction(Book $book)
{
$copies = $book->getUsersCopies($this->get('security.context')->getToken()->getUser());
$em = $this->getDoctrine()->getEntityManager();
$copies->forAll(function($key, $copy) use ($book, $em) {
$book->removeCopy($copy);
$em->remove($copy);
});
$em->persist($book);
$em->flush();
return new Response();
}
/**
* @Route("/konyv/ujpeldany/{id}", name="KekRozsakFrontBundle_bookAddCopy", requirements={"id": "\d+"}, options={"expose": true})
* @ParamConverter("book")
*/
public function ajaxAddBookAction(Book $book)
{
$user = $this->get('security.context')->getToken()->getUser();
$copies = $book->getUsersCopies($user);
if ($copies->count() == 0)
{
$copy = new BookCopy($book, $user);
$em = $this->getDoctrine()->getEntityManager();
$em->persist($copy);
$em->flush();
}
return new Response();
}
/**
* @Route("/konyv/kolcsonozheto/{id}/{newValue}", name="KekRozsakFrontBundle_bookSetCopyBorrowable", requirements={"id": "\d+"}, options={"expose": true})
* @ParamConverter("book")
*/
public function ajaxSetBookCopyBorrowableAction(Book $book, $newValue)
{
$user = $this->get('security.context')->getToken()->getUser();
$copies = $book->getUsersCopies($user);
$em = $this->getDoctrine()->getEntityManager();
$copies->forAll(function($key, $copy) use ($em, $newValue) {
$copy->setBorrowable($newValue);
$em->persist($copy);
});
$em->flush();
return new Response();
}
/**
* @Route("/konyv/megveheto/{id}/{newValue}", name="KekRozsakFrontBundle_bookSetCopyForSale", requirements={"id": "\d+"}, options={"expose": true})
* @ParamConverter("book")
*/
public function ajaxSetBookCopyForSaleAction(Book $book, $newValue)
{
$user = $this->get('security.context')->getToken()->getUser();
$copies = $book->getUsersCopies($user);
$em = $this->getDoctrine()->getEntityManager();
$copies->forAll(function($key, $copy) use ($em, $newValue) {
$copy->setBuyable($newValue);
$em->persist($copy);
});
$em->flush();
return new Response();
}
/**
* @Route("/konyv/szeretnek/{id}/{wantToBuy}", name="KekRozsakFrontBundle_bookWantOne", requirements={"id": "\d+"}, options={"expose": true})
* @ParamConverter("book")
*/
public function ajaxWantABookAction(Book $book, $wantToBuy)
{
$user = $this->get('security.context')->getToken()->getUser();
if ($wantToBuy)
{
$book->addWouldBuy($user);
}
else
{
$book->addWouldBorrow($user);
}
$em = $this->getDoctrine()->getEntityManager();
$em->persist($book);
$em->flush();
return new Response();
}
}

View File

@ -0,0 +1,299 @@
<?php
namespace KekRozsak\FrontBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
use Doctrine\Common\Collections\ArrayCollection;
use KekRozsak\SecurityBundle\Entity\User;
/**
* KekRozsak\FrontBundle\Entity\Book
*
* @ORM\Entity
* @ORM\Table(name="books")
*
* @DoctrineAssert\UniqueEntity(fields={"author", "title", "year"})
*/
class Book
{
public function __construct()
{
$this->copies = new ArrayCollection();
$this->wouldBorrow = new ArrayCollection();
$this->wouldBuy = new ArrayCollection();
}
/**
* @var integer $id
*
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* @var Doctrine\Common\Collections\ArrayCollection $copies
*
* @ORM\OneToMany(targetEntity="BookCopy", mappedBy="book")
*/
protected $copies;
/**
* Remove a copy
*
* @param KekRozsak\FrontBundle\Entity\BookCopy $copy
* @return Book
*/
public function removeCopy(BookCopy $copy)
{
$this->copies->removeElement($copy);
}
/**
* Get copies
*
* @return Doctrine\Common\Collections\ArrayCollection
*/
public function getCopies()
{
return $this->copies;
}
public function getCopiesBorrowed()
{
return $this->copies->filter(function($copy) {
return ($copy->getBorrower() !== null);
});
}
public function getCopiesBorrowedByUser(User $user)
{
return $this->copies->filter(function($copy) use ($user) {
return ($copy->getBorrower() == $user);
});
}
public function getCopiesBorrowedReturnedByUser(User $user)
{
return $this->copies->filter(function($copy) use ($user) {
return ($copy->getBorrower() == $user) && ($copy->isBorrowerReturned());
});
}
public function getCopiesBorrowable()
{
return $this->copies->filter(function($copy) {
return $copy->isBorrowable();
});
}
public function getUsersCopies(User $user)
{
return $this->copies->filter(function ($copy) use ($user) {
return ($copy->getOwner() == $user);
});
}
public function getUsersCopiesBorrowable(User $user)
{
return $this->copies->filter(function($copy) use ($user) {
return (($copy->getOwner() == $user) && $copy->isBorrowable());
});
}
public function getUsersCopiesBuyable(User $user)
{
return $this->copies->filter(function($copy) use ($user) {
return (($copy->getOwner() == $user) && $copy->isBuyable());
});
}
/**
* @var string $author
*
* @ORM\Column(type="string", length=100, nullable=false)
*/
protected $author;
/**
* Set author
*
* @param string $author
* @return Book
*/
public function setAuthor($author)
{
$this->author = $author;
return $this;
}
/**
* Get author
*
* @return string
*/
public function getAuthor()
{
return $this->author;
}
/**
* @var string $title
*
* @ORM\Column(type="string", length=100, nullable=false)
*/
protected $title;
/**
* Set title
*
* @param string $title
* @return Book
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* Get title
*
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @var integer $year
*
* @ORM\Column(type="integer", nullable=false)
*/
protected $year;
/**
* Set year
*
* @param integer $year
* @return Book
*/
public function setYear($year)
{
$this->year = $year;
return $this;
}
/**
* Get year
*
* @return integer
*/
public function getYear()
{
return $this->year;
}
/**
* @var boolean $commentable
*
* @ORM\Column(type="boolean", nullable=false)
*/
protected $commentable;
/**
* @var Doctrine\Common\Collections\ArrayCollection $wouldBorrow
*
* @ORM\ManyToMany(targetEntity="KekRozsak\SecurityBundle\Entity\User")
* @ORM\JoinTable(name="book_would_borrow")
*/
protected $wouldBorrow;
/**
* Add a user for want-to-borrowers
*
* @param KekRozsak\SecurityBundle\Entity\User $user
* @return Book
*/
public function addWouldBorrow(User $user)
{
$this->wouldBorrow->add($user);
return $this;
}
/**
* Get wouldBorrow list
*
* @return Doctrine\Common\Collections\ArrayCollection
*/
public function getWouldBorrow()
{
return $this->wouldBorrow;
}
/**
* Check if specified user would borrow this book
*
* @param KekRozsak\SecurityBundle\Entity\User $user
* @return boolean
*/
public function userWouldBorrow(User $user)
{
return $this->wouldBorrow->contains($user);
}
/**
* @var Doctrine\Common\Collections\ArrayCollection $wouldBuy
*
* @ORM\ManyToMany(targetEntity="KekRozsak\SecurityBundle\Entity\User")
* @ORM\JoinTable(name="book_would_buy")
*/
protected $wouldBuy;
/**
* Add a user for want-to-buyers
*
* @param KekRozsak\SecurityBundle\Entity\User $user
* @return Book
*/
public function addWouldBuy(User $user)
{
$this->wouldBuy->add($user);
return $this;
}
/**
* Get wouldBuy list
*
* @return Doctrine\Common\Collections\ArrayCollection
*/
public function getWouldBuy()
{
return $this->wouldBuy;
}
/**
* Check if specified user would buy this book
*
* @param KekRozsak\SecurityBundle\Entity\User $user
* @return boolean
*/
public function userWouldBuy(User $user)
{
return $this->wouldBuy->contains($user);
}
}

View File

@ -0,0 +1,165 @@
<?php
namespace KekRozsak\FrontBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints as DoctrineAssert;
use KekRozsak\FrontBundle\Entity\Book;
use KekRozsak\SecurityBundle\Entity\User;
/**
* KekRozsak\FrontBundle\Entity\BookCopy
* @ORM\Entity
* @ORM\Table(name="book_copies", uniqueConstraints={
* @ORM\UniqueConstraint(columns={"owner_id", "book_id"})
* })
*
* @DoctrineAssert\UniqueEntity(fields={"owner_id", "book_id"})
*/
class BookCopy
{
public function __construct(Book $book, User $owner)
{
$this->book = $book;
$this->owner = $owner;
$this->borrowable = false;
$this->buyable = false;
$this->borrower = null;
$this->borrowerReturned = true;
}
/**
* @var integer $id
*
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
* @ORM\Column(type="integer")
*/
protected $id;
/**
* @var KekRozsak\FrontBundle\Entity\Book $book
*
* @ORM\ManyToOne(targetEntity="Book", inversedBy="copies")
* @ORM\JoinColumn(nullable=false)
*/
protected $book;
/**
* @var KekRozsak\SecurityBundle\Entity\User $owner
*
* @ORM\ManyToOne(targetEntity="KekRozsak\SecurityBundle\Entity\User")
* @ORM\JoinColumn(nullable=false)
*/
protected $owner;
/**
* Get owner
*
* @return KekRozsak\SecurityBundle\Entity\User
*/
public function getOwner()
{
return $this->owner;
}
/**
* @var string $ownerComment
*
* @ORM\Column(type="text", name="owner_comment", nullable=true)
*/
protected $ownerComment;
/**
* @var boolean $borrowable
*
* @ORM\Column(type="boolean", nullable=false)
*/
protected $borrowable;
/**
* Set borrowable
*
* @param boolean $borrowable
* @return BookCopy
*/
public function setBorrowable($borrowable)
{
$this->borrowable = $borrowable;
return $this;
}
/**
* Get borrowable
*
* @return boolean
*/
public function isBorrowable()
{
return $this->borrowable;
}
/**
* @var boolean $buyable
*
* @ORM\Column(type="boolean", nullable=false)
*/
protected $buyable;
/**
* Set buyable
*
* @param boolean $buyable
* @return BookCopy
*/
public function setBuyable($buyable)
{
$this->buyable = $buyable;
return $this;
}
/**
* Get borrowable
*
* @return boolean
*/
public function isBuyable()
{
return $this->buyable;
}
/**
* @var KekRozsak\SecurityBundle\Entity\User $borrower
*
* @ORM\OneToOne(targetEntity="KekRozsak\SecurityBundle\Entity\User")
*/
protected $borrower;
/**
* Get borrower
*
* @return KekRozsak\SecurityBundle\Entity\User
*/
public function getBorrower()
{
return $this->borrower;
}
/**
* @var boolean $borrowerReturned
*
* @ORM\Column(type="boolean", nullable=false, name="borrower_returned")
*/
protected $borrowerReturned;
/**
* Get borrowerReturned
*
* @return boolean
*/
public function isBorrowerReturned()
{
return $this->borrowerReturned();
}
}

View File

@ -0,0 +1,63 @@
{# vim: ft=htmljinja
#}
<p>
<strong>Szerző:</strong> {{ book.author }}<br />
<strong>Cím:</strong> {{ book.title }}<br />
<strong>Kiadás éve:</strong> {{ book.year }}<br />
</p>
<p>
Nekem van <strong>{{ book.usersCopies(app.user)|length }}</strong>, ebből kölcsön van adva <strong>X</strong>.<br />
A teljes közösségnek összesen <strong>{{ book.copies|length }}</strong> példánya van.<br />
Kölcsönkérhető <strong>{{ book.copiesBorrowable|length }}</strong> példány, ebből <strong>{{ book.copiesBorrowedByUser(app.user)|length }}</strong> nálam van.<br />
</p>
<p>
{% if book.usersCopies(app.user)|length == 0 %}
<span class="gomb add-copy-button" id="add-copy-button-{{ book.id }}">[Nekem is van egy]</span>
{% else %}
<span class="gomb delete-copy-button" id="delete-copy-button-{{ book.id }}">[Nincs már]</span>
{# TODO
<span class="gomb">[Eladtam valakinek a körben]</span>
#}
{% if book.usersCopiesBorrowable(app.user)|length == 0 %}
<span class="gomb mine-is-borrowable-button" id="mine-is-borrowable-button-{{ book.id }}">[Az enyém is kölcsönkérhető]</span>
{% else %}
<span class="gomb mine-is-not-borrowable-button" id="mine-is-not-borrowable-button-{{ book.id }}">[Nem szeretném kölcsönadni]</span>
{% endif %}
{% endif %}
{% if book.usersCopies(app.user)|length > 0 %}
{% if book.usersCopiesBuyable(app.user)|length == 0 %}
<span class="gomb mine-is-for-sale-button" id="mine-is-for-sale-button-{{ book.id }}">[Az enyém eladó]</span>
{% else %}
<span class="gomb mine-is-not-for-sale-button" id="mine-is-not-for-sale-button-{{ book.id }}">[Nem szeretném eladni]</span>
{% endif %}
{% endif %}
{% if book.copiesBorrowedByUser(app.user)|length == 0 and book.usersCopies(app.user)|length == 0 and not book.userWouldBorrow(app.user) %}
<span class="gomb want-to-borrow-button" id="want-to-borrow-button-{{ book.id }}">[Kérek egyet kölcsön]</span>
{% endif %}
{% if book.usersCopies(app.user)|length == 0 and not book.userWouldBuy(app.user) %}
<span class="gomb want-to-buy-button" id="want-to-buy-button-{{ book.id }}">[Vennék egyet]</span>
{% endif %}
</p>
{% if book.wouldBuy|length > 0 %}
<p>
Ők szeretnének egyet kölcsönkérni:<br />
<ul>
{% for user in book.wouldBorrow %}
<li>{{ user|userdataspan }}</li>
{% endfor %}
</ul>
</p>
{% endif %}
{% if book.wouldBuy|length > 0 %}
<p>
Ők szeretnének venni egyet:<br />
<ul>
{% for user in book.wouldBuy %}
<li>{{ user|userdataspan }}</li>
{% endfor %}
</ul>
</p>
{% endif %}

View File

@ -0,0 +1,133 @@
{# vim: ft=htmljinja
#}
{% extends '::main_template.html.twig' %}
{% block title %} - Könyvtár{% endblock %}
{% block content %}
<h3>Könyvtár</h3>
[Saját könyveim] [Nálam lévő kölcsönzött könyvek]
{% if books|length > 0 %}
<table>
<thead>
<tr>
<td>Szerző</td>
<td>Cím</td>
<td>Év</td>
<td>Összes</td>
<td>Kölcsönözhető</td>
<td>Saját</td>
<td>Nálam (Vissza)</td>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr class="book-row popup-opener" id="book-{{ book.id }}">
<td class="popup-opener">{{ book.author }}</td>
<td>{{ book.title }}</td>
<td>{{ book.year }}</td>
<td>{{ book.copies|length }}</td>
<td>{{ book.copiesBorrowable|length }}</td>
<td>{{ book.usersCopies(app.user)|length }}</td>
<td>{{ book.copiesBorrowedByUser(app.user)|length }} ({{ book.copiesBorrowedReturnedByUser(app.user)|length }})</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endblock %}
{% block bottomscripts %}
<script type="text/javascript">
$('.book-row').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^book-\d+$/))
return false;
bookid = $(this).attr('id').replace(/^book-/, '');
bookUrl = Routing.generate('KekRozsakFrontBundle_bookAjaxData', { id: bookid, _format: 'html' });
bookCallback = function() {
// TODO: Change alert() calls to HTML flashes
$('.delete-copy-button').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^delete-copy-button-\d+$/))
return false;
bookid = $(this).attr('id').replace(/^delete-copy-button-/, '');
url = Routing.generate('KekRozsakFrontBundle_bookDeleteCopy', { id: bookid });
$.ajax({
method: 'GET',
url: url
}).done(function() {
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
}).error(function() {
alert('Nem sikerült törölni');
});
});
$('.add-copy-button').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^add-copy-button-\d+$/))
return false;
bookid = $(this).attr('id').replace(/^add-copy-button-/, '');
url = Routing.generate('KekRozsakFrontBundle_bookAddCopy', { id: bookid });
$.ajax({
method: 'GET',
url: url
}).done(function() {
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
}).error(function() {
alert('Nem sikerült bejegyezni ezt a példányt');
});
});
$('.mine-is-borrowable-button, .mine-is-not-borrowable-button').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^mine-is-(not-)?borrowable-button-\d+$/))
return false;
isBorrowable = ($(this).attr('id').match(/^mine-is-not-borrowable-button-\d+$/)) ? 0 : 1;
bookid = $(this).attr('id').replace(/^mine-is-(not-)?borrowable-button-/, '');
url = Routing.generate('KekRozsakFrontBundle_bookSetCopyBorrowable', { id: bookid, newValue: isBorrowable });
$.ajax({
method: 'GET',
url: url
}).done(function() {
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
}).error(function() {
alert('Nem sikerült bejegyezni ezt a példányt');
});
});
$('.mine-is-for-sale-button, .mine-is-not-for-sale-button').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^mine-is-(not-)?for-sale-button-\d+$/))
return false;
isForSale = ($(this).attr('id').match(/^mine-is-not-for-sale-button-\d+$/)) ? 0 : 1;
bookid = $(this).attr('id').replace(/^mine-is-(not-)?for-sale-button-/, '');
url = Routing.generate('KekRozsakFrontBundle_bookSetCopyForSale', { id: bookid, newValue: isForSale });
$.ajax({
method: 'GET',
url: url
}).done(function() {
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
}).error(function() {
alert('Nem sikerült bejegyezni ezt a példányt');
});
});
$('.want-to-buy-button, .want-to-borrow-button').click(function() {
bookid = 0;
if (!$(this).attr('id').match(/^want-to-(buy|borrow)-button-\d+$/))
return false;
toBuy = ($(this).attr('id').match(/^want-to-buy-button-\d+$/)) ? 1 : 0;
bookid = $(this).attr('id').replace(/^want-to-(buy|borrow)-button-/, '');
url = Routing.generate('KekRozsakFrontBundle_bookWantOne', { id: bookid, wantToBuy: toBuy });
$.ajax({
method: 'GET',
url: url
}).done(function() {
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
}).error(function() {
alert('Nem sikerült bejegyezni a kérést');
});
});
};
doPopup('', 'Betöltés...', bookUrl, 400, 300, bookCallback);
});
</script>
{% endblock bottomscripts %}

View File

@ -0,0 +1,13 @@
/**
* Portions of this code are from the Google Closure Library,
* received from the Closure Authors under the Apache 2.0 license.
*
* All other code is (C) 2011 FriendsOfSymfony and subject to the MIT license.
*/
(function() {var g=this;function i(a,b){var c=a.split("."),d=g;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)!c.length&&b!==void 0?d[e]=b:d=d[e]?d[e]:d[e]={}}
function k(a){var b=typeof a;if(b=="object")if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if(c=="[object Window]")return"object";if(c=="[object Array]"||typeof a.length=="number"&&typeof a.splice!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("splice"))return"array";if(c=="[object Function]"||typeof a.call!="undefined"&&typeof a.propertyIsEnumerable!="undefined"&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
else if(b=="function"&&typeof a.call=="undefined")return"object";return b};var l=/^[a-zA-Z0-9\-_.!~*'()]*$/;function m(a){a=""+a;return!l.test(a)?encodeURIComponent(a):a};var n=Array.prototype,p=n.forEach?function(a,b,c){n.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e=typeof a=="string"?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)};function q(a){var b=0,c;for(c in a)b++;return b}function r(a){var b={},c;for(c in a)b[c]=a[c];return b};function s(a,b){this.b={};this.a=[];var c=arguments.length;if(c>1){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a){var e;if(a instanceof s){t(a);d=a.a.concat();t(a);e=[];for(c=0;c<a.a.length;c++)e.push(a.b[a.a[c]])}else{var c=[],f=0;for(d in a)c[f++]=d;d=c;c=[];f=0;for(e in a)c[f++]=a[e];e=c}for(c=0;c<d.length;c++)this.set(d[c],e[c])}}s.prototype.e=0;s.prototype.m=0;
function t(a){if(a.e!=a.a.length){for(var b=0,c=0;b<a.a.length;){var d=a.a[b];Object.prototype.hasOwnProperty.call(a.b,d)&&(a.a[c++]=d);b++}a.a.length=c}if(a.e!=a.a.length){for(var e={},c=b=0;b<a.a.length;)d=a.a[b],Object.prototype.hasOwnProperty.call(e,d)||(a.a[c++]=d,e[d]=1),b++;a.a.length=c}}s.prototype.get=function(a,b){return Object.prototype.hasOwnProperty.call(this.b,a)?this.b[a]:b};
s.prototype.set=function(a,b){Object.prototype.hasOwnProperty.call(this.b,a)||(this.e++,this.a.push(a),this.m++);this.b[a]=b};function u(a){if(a[1]){var b=a[0],c=b.indexOf("#");c>=0&&(a.push(b.substr(c)),a[0]=b=b.substr(0,c));c=b.indexOf("?");c<0?a[1]="?":c==b.length-1&&(a[1]=void 0)}return a.join("")}function v(a,b){for(var c in b){var d=c,e=b[c],f=a;if(k(e)=="array")for(var h=0;h<e.length;h++)f.push("&",d),e[h]!==""&&f.push("=",m(e[h]));else e!=null&&(f.push("&",d),e!==""&&f.push("=",m(e)))}return a};function w(a,b){this.d=a||{c:""};this.g(b||{})}(function(a){a.f=function(){return a.l||(a.l=new a)}})(w);w.prototype.g=function(a){this.h=new s(a)};w.prototype.i=function(a){this.d.c=a};w.prototype.k=function(){return this.d.c};
w.prototype.j=function(a,b){if(!Object.prototype.hasOwnProperty.call(this.h.b,a))throw Error('The route "'+a+'" does not exist.');var c=this.h.get(a),d=b||{},e=r(d),f="",h=!0;p(c.tokens,function(b){if("text"===b[0])f=b[1]+f,h=!1;else if("variable"===b[0]){if(!1===h||!(b[3]in c.defaults)||b[3]in d&&d[b[3]]!=c.defaults[b[3]]){var j;if(b[3]in d){j=d[b[3]];var o=b[3];o in e&&delete e[o]}else if(b[3]in c.defaults)j=c.defaults[b[3]];else{if(h)return;throw Error('The route "'+a+'" requires the parameter "'+
b[3]+'".');}if(!(!0===j||!1===j||""===j)||!h)f=b[1]+encodeURIComponent(j).replace(/%2F/g,"/")+f;h=!1}}else throw Error('The token type "'+b[0]+'" is not supported.');});f===""&&(f="/");q(e)>0&&(f=u(v([f],e)));return this.d.c+f};i("fos.Router",w);i("fos.Router.setData",function(a){var b=w.f();b.i(a.base_url);b.g(a.routes)});w.getInstance=w.f;w.prototype.setRoutes=w.prototype.g;w.prototype.setBaseUrl=w.prototype.i;w.prototype.getBaseUrl=w.prototype.k;w.prototype.generate=w.prototype.j;window.Routing=w.f();})();

View File

@ -137,6 +137,16 @@ body {
padding: 5px;
}
#konyvtar-gomb {
float: left;
padding: 5px;
}
#konyvtar-gomb a {
color: inherit;
text-decoration: none;
}
#bottom-line {
position: fixed;
left: 0;
@ -358,3 +368,102 @@ td.uj-post p .kuldes-gomb {
font-style: italic;
}
#popup-container {
display: none;
position: fixed;
height: 300px;
width: 200px;
background: #ffffff;
z-index: 80;
}
#popup-close {
position: absolute;
width: 16px;
height: 16px;
top: -5px;
right: -5px;
background-image: url('../images/no.png');
}
#popup-inside {
border: 1px solid black;
height: 292px;
width: 192px;
margin-left: auto;
margin-right: auto;
margin-top: 3px;
}
#popup-title {
font-weight: bold;
padding: 5px;
}
#popup-content {
padding: 3px;
}
#popup-scrollable {
width: 192px;
clear: both;
margin: 20px 0 10px;
}
#popup-scrollable .viewport {
width: 172px;
height: 246px;
overflow: hidden;
position: relative;
}
#popup-scrollable .overview {
list-style: none;
position: absolute;
left: 0;
top: 0;
}
#popup-scrollable .thumb .end, #popup-scrollable .thumb {
background-color: #003D5D;
}
#popup-scrollable .scrollbar {
position: relative;
float: right;
width: 15px;
}
#popup-scrollable .track {
background-color: #D8EEFD;
height: 100%;
width: 13px;
position: relative;
padding: 0 1px;
}
#popup-scrollable .thumb {
height: 20px;
width: 13px;
cursor: pointer;
overflow: hidden;
position: absolute;
top: 0;
}
#popup-scrollable .thumb .end {
overflow: hidden;
height: 5px;
width: 13px;
}
#popup-scrollable .disable {
display: none;
}
.gomb {
background-color: #cccccc;
color: black;
white-space: nowrap;
}

BIN
web/images/no.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 894 B

1
web/js/jquery.tinyscrollbar.min.js vendored Normal file
View File

@ -0,0 +1 @@
(function(a){a.tiny=a.tiny||{};a.tiny.scrollbar={options:{axis:"y",wheel:40,scroll:true,lockscroll:true,size:"auto",sizethumb:"auto"}};a.fn.tinyscrollbar=function(d){var c=a.extend({},a.tiny.scrollbar.options,d);this.each(function(){a(this).data("tsb",new b(a(this),c))});return this};a.fn.tinyscrollbar_update=function(c){return a(this).data("tsb").update(c)};function b(q,g){var k=this,t=q,j={obj:a(".viewport",q)},h={obj:a(".overview",q)},d={obj:a(".scrollbar",q)},m={obj:a(".track",d.obj)},p={obj:a(".thumb",d.obj)},l=g.axis==="x",n=l?"left":"top",v=l?"Width":"Height",r=0,y={start:0,now:0},o={},e=("ontouchstart" in document.documentElement)?true:false;function c(){k.update();s();return k}this.update=function(z){j[g.axis]=j.obj[0]["offset"+v];h[g.axis]=h.obj[0]["scroll"+v];h.ratio=j[g.axis]/h[g.axis];d.obj.toggleClass("disable",h.ratio>=1);m[g.axis]=g.size==="auto"?j[g.axis]:g.size;p[g.axis]=Math.min(m[g.axis],Math.max(0,(g.sizethumb==="auto"?(m[g.axis]*h.ratio):g.sizethumb)));d.ratio=g.sizethumb==="auto"?(h[g.axis]/m[g.axis]):(h[g.axis]-j[g.axis])/(m[g.axis]-p[g.axis]);r=(z==="relative"&&h.ratio<=1)?Math.min((h[g.axis]-j[g.axis]),Math.max(0,r)):0;r=(z==="bottom"&&h.ratio<=1)?(h[g.axis]-j[g.axis]):isNaN(parseInt(z,10))?r:parseInt(z,10);w()};function w(){var z=v.toLowerCase();p.obj.css(n,r/d.ratio);h.obj.css(n,-r);o.start=p.obj.offset()[n];d.obj.css(z,m[g.axis]);m.obj.css(z,m[g.axis]);p.obj.css(z,p[g.axis])}function s(){if(!e){p.obj.bind("mousedown",i);m.obj.bind("mouseup",u)}else{j.obj[0].ontouchstart=function(z){if(1===z.touches.length){i(z.touches[0]);z.stopPropagation()}}}if(g.scroll&&window.addEventListener){t[0].addEventListener("DOMMouseScroll",x,false);t[0].addEventListener("mousewheel",x,false)}else{if(g.scroll){t[0].onmousewheel=x}}}function i(A){var z=parseInt(p.obj.css(n),10);o.start=l?A.pageX:A.pageY;y.start=z=="auto"?0:z;if(!e){a(document).bind("mousemove",u);a(document).bind("mouseup",f);p.obj.bind("mouseup",f)}else{document.ontouchmove=function(B){B.preventDefault();u(B.touches[0])};document.ontouchend=f}}function x(B){if(h.ratio<1){var A=B||window.event,z=A.wheelDelta?A.wheelDelta/120:-A.detail/3;r-=z*g.wheel;r=Math.min((h[g.axis]-j[g.axis]),Math.max(0,r));p.obj.css(n,r/d.ratio);h.obj.css(n,-r);if(g.lockscroll||(r!==(h[g.axis]-j[g.axis])&&r!==0)){A=a.event.fix(A);A.preventDefault()}}}function u(z){if(h.ratio<1){if(!e){y.now=Math.min((m[g.axis]-p[g.axis]),Math.max(0,(y.start+((l?z.pageX:z.pageY)-o.start))))}else{y.now=Math.min((m[g.axis]-p[g.axis]),Math.max(0,(y.start+(o.start-(l?z.pageX:z.pageY)))))}r=y.now*d.ratio;h.obj.css(n,-r);p.obj.css(n,y.now)}}function f(){a(document).unbind("mousemove",u);a(document).unbind("mouseup",f);p.obj.unbind("mouseup",f);document.ontouchmove=document.ontouchend=null}return c()}}(jQuery));