Allow admin to view collection metadata

This commit is contained in:
Alex Cabal 2024-12-14 11:32:02 -06:00
parent bcc2f331bc
commit 23b5c8ef31
8 changed files with 82 additions and 55 deletions

View file

@ -7,6 +7,7 @@ CREATE TABLE IF NOT EXISTS `Benefits` (
`CanReviewArtwork` tinyint(1) unsigned NOT NULL DEFAULT 0, `CanReviewArtwork` tinyint(1) unsigned NOT NULL DEFAULT 0,
`CanReviewOwnArtwork` tinyint(1) unsigned NOT NULL DEFAULT 0, `CanReviewOwnArtwork` tinyint(1) unsigned NOT NULL DEFAULT 0,
`CanEditUsers` tinyint(1) unsigned NOT NULL DEFAULT 0, `CanEditUsers` tinyint(1) unsigned NOT NULL DEFAULT 0,
`CanEditCollections` tinyint(1) unsigned NOT NULL DEFAULT 0,
`CanCreateEbookPlaceholders` tinyint(1) unsigned NOT NULL DEFAULT 0, `CanCreateEbookPlaceholders` tinyint(1) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`UserId`), PRIMARY KEY (`UserId`),
KEY `idxBenefits` (`CanAccessFeeds`,`CanVote`,`CanBulkDownload`) KEY `idxBenefits` (`CanAccessFeeds`,`CanVote`,`CanBulkDownload`)

View file

@ -15,6 +15,7 @@ class Benefits{
public bool $CanReviewArtwork = false; public bool $CanReviewArtwork = false;
public bool $CanReviewOwnArtwork = false; public bool $CanReviewOwnArtwork = false;
public bool $CanEditUsers = false; public bool $CanEditUsers = false;
public bool $CanEditCollections = false;
public bool $CanCreateEbookPlaceholders = false; public bool $CanCreateEbookPlaceholders = false;
protected bool $_HasBenefits; protected bool $_HasBenefits;

View file

@ -3,6 +3,7 @@ use function Safe\preg_replace;
/** /**
* @property string $Url * @property string $Url
* @property array<Ebook> $Ebooks
*/ */
class Collection{ class Collection{
use Traits\Accessor; use Traits\Accessor;
@ -13,7 +14,9 @@ class Collection{
public ?Enums\CollectionType $Type = null; public ?Enums\CollectionType $Type = null;
public bool $ArePlaceholdersComplete; /** Has a producer verified that every possible item in this `Collection` been added to our database? */ public bool $ArePlaceholdersComplete; /** Has a producer verified that every possible item in this `Collection` been added to our database? */
protected ?string $_Url = null; protected string $_Url;
/** @var array<Ebook> $_Ebooks */
protected array $_Ebooks;
// ******* // *******
@ -21,13 +24,24 @@ class Collection{
// ******* // *******
protected function GetUrl(): string{ protected function GetUrl(): string{
if($this->_Url === null){ if(!isset($this->_Url)){
$this->_Url = '/collections/' . $this->UrlName; $this->_Url = '/collections/' . $this->UrlName;
} }
return $this->_Url; return $this->_Url;
} }
/**
* @return array<Ebook>
*/
protected function GetEbooks(): array{
if(!isset($this->_Ebooks)){
$this->_Ebooks = Ebook::GetAllByCollection($this->CollectionId);
}
return $this->_Ebooks;
}
// *********** // ***********
// ORM METHODS // ORM METHODS
@ -57,6 +71,23 @@ class Collection{
return $result[0] ?? throw new Exceptions\CollectionNotFoundException();; return $result[0] ?? throw new Exceptions\CollectionNotFoundException();;
} }
/**
* @throws Exceptions\CollectionNotFoundException
*/
public static function GetByUrlName(?string $urlName): Collection{
if($urlName === null){
throw new Exceptions\CollectionNotFoundException();
}
$result = Db::Query('
SELECT *
from Collections
where UrlName = ?
', [$urlName], Collection::class);
return $result[0] ?? throw new Exceptions\CollectionNotFoundException();;
}
/** /**
* @return array<Collection> * @return array<Collection>
*/ */

View file

@ -2020,17 +2020,17 @@ class Ebook{
* Queries for books in a collection. * Queries for books in a collection.
* *
* Puts ebooks without a `SequenceNumber` at the end of the list, which is more common in a collection with both published and placeholder ebooks. * Puts ebooks without a `SequenceNumber` at the end of the list, which is more common in a collection with both published and placeholder ebooks.
*
* @return array<Ebook> * @return array<Ebook>
*/ */
public static function GetAllByCollection(string $collection): array{ public static function GetAllByCollection(int $collectionId): array{
$ebooks = Db::Query(' $ebooks = Db::Query('
SELECT e.* SELECT e.*
from Ebooks e from Ebooks e
inner join CollectionEbooks ce using (EbookId) inner join CollectionEbooks ce using (EbookId)
inner join Collections c using (CollectionId) where ce.CollectionId = ?
where c.UrlName = ?
order by ce.SequenceNumber is null, ce.SequenceNumber, e.EbookCreated desc order by ce.SequenceNumber is null, ce.SequenceNumber, e.EbookCreated desc
', [$collection], Ebook::class); ', [$collectionId], Ebook::class);
return $ebooks; return $ebooks;
} }

View file

@ -2,34 +2,15 @@
use function Safe\preg_replace; use function Safe\preg_replace;
try{ try{
$collection = HttpInput::Str(GET, 'collection') ?? ''; $collection = Collection::GetByUrlName(HttpInput::Str(GET, 'collection'));
$collectionObject = null; $collectionName = preg_replace('/^The /ius', '', $collection->Name);
$collectionName = ''; $collectionType = $collection->Type->value ?? 'collection';
$collectionType = '';
$ebooks = Ebook::GetAllByCollection($collection);
// Get the *actual* name of the collection, in case there are accent marks (like `Arsène Lupin`).
if(sizeof($ebooks) > 0){
foreach($ebooks[0]->CollectionMemberships as $cm){
$c = $cm->Collection;
if($collection == Formatter::MakeUrlSafe($c->Name)){
$collectionObject = $c;
}
}
}
if($collectionObject === null){
throw new Exceptions\CollectionNotFoundException();
}
$collectionName = preg_replace('/^The /ius', '', $collectionObject->Name);
$collectionType = $collectionObject->Type->value ?? 'collection';
$pageTitle = 'Browse free ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType; $pageTitle = 'Browse free ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType;
$pageDescription = 'A list of free ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType; $pageDescription = 'A list of free ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType;
$pageHeader = 'Free Ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . ucfirst($collectionType); $pageHeader = 'Free Ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . ucfirst($collectionType);
$feedUrl = '/collections/' . $collection; $feedUrl = '/collections/' . $collection->UrlName;
$feedTitle = 'Standard Ebooks - Ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType; $feedTitle = 'Standard Ebooks - Ebooks in the ' . Formatter::EscapeHtml($collectionName) . ' ' . $collectionType;
} }
catch(Exceptions\CollectionNotFoundException){ catch(Exceptions\CollectionNotFoundException){
@ -44,13 +25,26 @@ catch(Exceptions\CollectionNotFoundException){
<?= Template::DonationAlert() ?> <?= Template::DonationAlert() ?>
<p class="ebooks-toolbar"> <p class="ebooks-toolbar">
<a class="button" href="/collections/<?= Formatter::EscapeHtml($collection) ?>/downloads">Download collection</a> <a class="button" href="/collections/<?= Formatter::EscapeHtml($collection->UrlName) ?>/downloads">Download collection</a>
<a class="button" href="/collections/<?= Formatter::EscapeHtml($collection) ?>/feeds">Collection feeds</a> <a class="button" href="/collections/<?= Formatter::EscapeHtml($collection->UrlName) ?>/feeds">Collection feeds</a>
</p> </p>
<? if(sizeof($ebooks) == 0){ ?>
<? if(sizeof($collection->Ebooks) == 0){ ?>
<p class="no-results">No ebooks matched your filters. You can try different filters, or <a href="/ebooks">browse all of our ebooks</a>.</p> <p class="no-results">No ebooks matched your filters. You can try different filters, or <a href="/ebooks">browse all of our ebooks</a>.</p>
<? }else{ ?> <? }else{ ?>
<?= Template::EbookGrid(['ebooks' => $ebooks, 'view' => Enums\ViewType::Grid, 'collection' => $collectionObject]) ?> <?= Template::EbookGrid(['ebooks' => $collection->Ebooks, 'view' => Enums\ViewType::Grid, 'collection' => $collection]) ?>
<? } ?>
<? if(Session::$User?->Benefits->CanEditCollections){ ?>
<h2>Metadata</h2>
<table class="admin-table">
<tbody>
<tr>
<td>Collection ID:</td>
<td><?= $collection->CollectionId ?></td>
</tr>
</tbody>
</table>
<? } ?> <? } ?>
<p class="feeds-alert">We also have <a href="/bulk-downloads">bulk ebook downloads</a> and a <a href="/collections">list of collections</a> available, as well as <a href="/feeds">ebook catalog feeds</a> for use directly in your ereader app or RSS reader.</p> <p class="feeds-alert">We also have <a href="/bulk-downloads">bulk ebook downloads</a> and a <a href="/collections">list of collections</a> available, as well as <a href="/feeds">ebook catalog feeds</a> for use directly in your ereader app or RSS reader.</p>

View file

@ -3254,6 +3254,25 @@ ol.ebooks-list > li.ribbon.not-pd a::after{
content: "not p.d. yet"; content: "not p.d. yet";
} }
h2 + table.admin-table{
margin-top: .5rem;
}
table.admin-table td{
padding: .5rem;
vertical-align: top;
}
table.admin-table td:first-child{
font-weight: bold;
text-align: right;
white-space: nowrap;
}
table.admin-table td + td{
width: 100%;
}
@media (hover: none) and (pointer: coarse){ /* target ipads and smartphones without a mouse */ @media (hover: none) and (pointer: coarse){ /* target ipads and smartphones without a mouse */
/* For iPad, unset the height so it matches the other elements */ /* For iPad, unset the height so it matches the other elements */
select[multiple]{ select[multiple]{

View file

@ -7,25 +7,6 @@ label:has(input[name="password-action"]) + label{
margin-top: .5rem; margin-top: .5rem;
} }
h2 + table{
margin-top: .5rem;
}
table td{
padding: .5rem;
vertical-align: top;
}
table td:first-child{
font-weight: bold;
text-align: right;
white-space: nowrap;
}
table td + td{
width: 100%;
}
form{ form{
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -52,7 +52,7 @@ catch(Exceptions\SeeOtherException $ex){
<a href="<?= $user->Url ?>/edit">Edit user</a> <a href="<?= $user->Url ?>/edit">Edit user</a>
<h2>Basics</h2> <h2>Basics</h2>
<table> <table class="admin-table">
<tbody> <tbody>
<tr> <tr>
<td>Email:</td> <td>Email:</td>
@ -74,7 +74,7 @@ catch(Exceptions\SeeOtherException $ex){
</table> </table>
<h2>Patron info</h2> <h2>Patron info</h2>
<table> <table class="admin-table">
<tbody> <tbody>
<tr> <tr>
<td>Is Patron:</td> <td>Is Patron:</td>
@ -134,7 +134,7 @@ catch(Exceptions\SeeOtherException $ex){
<? } ?> <? } ?>
<h2>Registration info</h2> <h2>Registration info</h2>
<table> <table class="admin-table">
<tbody> <tbody>
<tr> <tr>
<td>Is registered:</td> <td>Is registered:</td>