mirror of
https://github.com/standardebooks/web.git
synced 2025-07-08 07:40:39 -04:00
Allow creating new ebook placeholders when creating a new project
This commit is contained in:
parent
4596aeb007
commit
98e09f414e
14 changed files with 114 additions and 44 deletions
7
lib/Exceptions/InvalidDiscussionUrlException.php
Normal file
7
lib/Exceptions/InvalidDiscussionUrlException.php
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?
|
||||
namespace Exceptions;
|
||||
|
||||
class InvalidDiscussionUrlException extends InvalidUrlException{
|
||||
/** @var string $message */
|
||||
protected $message = 'Invalid discussion URL.';
|
||||
}
|
|
@ -222,6 +222,10 @@ final class Project{
|
|||
// Get the base thread URL in case we were passed a URL with a specific message or query string.
|
||||
$this->DiscussionUrl = preg_replace('|^(https://groups\.google\.com/g/standardebooks/c/[^/]+).*|iu', '\1', $this->DiscussionUrl);
|
||||
}
|
||||
|
||||
if(!preg_match('|^https://groups\.google\.com/g/standardebooks/c/[^/\?]+$|iu', $this->DiscussionUrl)){
|
||||
$error->Add(new Exceptions\InvalidDiscussionUrlException($this->DiscussionUrl));
|
||||
}
|
||||
}
|
||||
|
||||
$this->VcsUrl = trim($this->VcsUrl ?? '');
|
||||
|
@ -231,7 +235,7 @@ final class Project{
|
|||
elseif(preg_match('|^https?://(www\.)?github.com/|ius', $this->VcsUrl)){
|
||||
$this->VcsUrl = rtrim($this->VcsUrl, '/');
|
||||
if(!preg_match('|^https://github.com/[^/]+/[^/]+$|ius', $this->VcsUrl)){
|
||||
$error->Add(new Exceptions\InvalidVcsUrlException());
|
||||
$error->Add(new Exceptions\InvalidVcsUrlException($this->VcsUrl));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?
|
||||
$ebook = $ebook ?? new Ebook();
|
||||
$isEditForm = $isEditForm ?? false;
|
||||
$showProjectForm = $showProjectForm ?? true;
|
||||
?>
|
||||
<fieldset>
|
||||
<legend>Contributors</legend>
|
||||
|
@ -190,11 +191,11 @@ $isEditForm = $isEditForm ?? false;
|
|||
</label>
|
||||
</fieldset>
|
||||
</details>
|
||||
<? if(!$isEditForm){ ?>
|
||||
<? if(!$isEditForm && $showProjectForm){ ?>
|
||||
<fieldset>
|
||||
<legend>Project</legend>
|
||||
<label class="controls-following-fieldset">
|
||||
<span>In progress?</span>
|
||||
<span>In progress</span>
|
||||
<input type="hidden" name="ebook-placeholder-is-in-progress" value="false" />
|
||||
<input
|
||||
type="checkbox"
|
||||
|
@ -210,7 +211,7 @@ $isEditForm = $isEditForm ?? false;
|
|||
<fieldset>
|
||||
<legend>Wanted list</legend>
|
||||
<label class="controls-following-fieldset">
|
||||
<span>On the wanted list?</span>
|
||||
<span>On the wanted list</span>
|
||||
<input type="hidden" name="ebook-placeholder-is-wanted" value="false" />
|
||||
<input
|
||||
type="checkbox"
|
||||
|
@ -220,7 +221,7 @@ $isEditForm = $isEditForm ?? false;
|
|||
</label>
|
||||
<fieldset>
|
||||
<label>
|
||||
<span>Did a Patron request this book?</span>
|
||||
<span>A Patron requested this book</span>
|
||||
<input type="hidden" name="ebook-placeholder-is-patron" value="false" />
|
||||
<input
|
||||
type="checkbox"
|
||||
|
@ -255,6 +256,3 @@ $isEditForm = $isEditForm ?? false;
|
|||
</label>
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
<div class="footer">
|
||||
<button>Submit</button>
|
||||
</div>
|
||||
|
|
|
@ -2562,6 +2562,10 @@ details summary ~ *{
|
|||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
fieldset label.controls-following-fieldset + fieldset{
|
||||
margin-top: -.5rem;
|
||||
}
|
||||
|
||||
fieldset p{
|
||||
border-bottom: 1px dashed var(--input-border);
|
||||
}
|
||||
|
|
|
@ -1,65 +1,65 @@
|
|||
form.create-update-ebook-placeholder fieldset{
|
||||
.create-update-ebook-placeholder fieldset{
|
||||
display: grid;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder details + fieldset,
|
||||
form.create-update-ebook-placeholder fieldset + fieldset{
|
||||
.create-update-ebook-placeholder details + fieldset,
|
||||
.create-update-ebook-placeholder fieldset + fieldset{
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder > fieldset:nth-of-type(1),
|
||||
form.create-update-ebook-placeholder details:nth-of-type(1) fieldset{
|
||||
.create-update-ebook-placeholder > fieldset:nth-of-type(1),
|
||||
.create-update-ebook-placeholder details:nth-of-type(1) fieldset{
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder > fieldset:nth-of-type(2),
|
||||
form.create-update-ebook-placeholder details:nth-of-type(2) fieldset{
|
||||
.create-update-ebook-placeholder > fieldset:nth-of-type(2),
|
||||
.create-update-ebook-placeholder details:nth-of-type(2) fieldset{
|
||||
grid-template-columns: 1fr 200px;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder fieldset label:has(input[name="ebook-placeholder-transcription-url"]),
|
||||
form.create-update-ebook-placeholder fieldset label:has(textarea[name="ebook-placeholder-notes"]){
|
||||
.create-update-ebook-placeholder fieldset label:has(input[name="ebook-placeholder-transcription-url"]),
|
||||
.create-update-ebook-placeholder fieldset label:has(textarea[name="ebook-placeholder-notes"]){
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-1"]),
|
||||
form.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-2"]),
|
||||
form.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-3"]){
|
||||
.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-1"]),
|
||||
.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-2"]),
|
||||
.create-update-ebook-placeholder fieldset:has(input[name="sequence-number-collection-name-3"]){
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 200px 200px;
|
||||
gap: 2rem;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder fieldset label:has(input[type="checkbox"]){
|
||||
.create-update-ebook-placeholder fieldset label:has(input[type="checkbox"]){
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder details{
|
||||
.create-update-ebook-placeholder details{
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder summary{
|
||||
.create-update-ebook-placeholder summary{
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder p{
|
||||
.create-update-ebook-placeholder p{
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 1.5rem;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder fieldset p{
|
||||
.create-update-ebook-placeholder fieldset p{
|
||||
font-style: italic;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder fieldset p:first-of-type{
|
||||
.create-update-ebook-placeholder fieldset p:first-of-type{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder legend{
|
||||
.create-update-ebook-placeholder legend{
|
||||
font-size: 1.4rem;
|
||||
font-family: "League Spartan", Arial, sans-serif;
|
||||
margin-bottom: 1rem;
|
||||
|
@ -68,7 +68,7 @@ form.create-update-ebook-placeholder legend{
|
|||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder label{
|
||||
.create-update-ebook-placeholder label{
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
@ -78,12 +78,12 @@ form div.footer{
|
|||
}
|
||||
|
||||
/* Hide the next fieldset unless the ebook-placeholder-is-wanted checkbox is checked. */
|
||||
form.create-update-ebook-placeholder label.controls-following-fieldset + fieldset{
|
||||
.create-update-ebook-placeholder label.controls-following-fieldset + fieldset{
|
||||
display: none;
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
form.create-update-ebook-placeholder label.controls-following-fieldset:has(input[type="checkbox"]:checked) + fieldset{
|
||||
.create-update-ebook-placeholder label.controls-following-fieldset:has(input[type="checkbox"]:checked) + fieldset{
|
||||
display: grid;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,10 @@
|
|||
text-align: right;
|
||||
}
|
||||
|
||||
.project-form .placeholder-form{
|
||||
grid-column: 1 / span 2;
|
||||
}
|
||||
|
||||
table.data-table .status,
|
||||
table.data-table .producer{
|
||||
white-space: nowrap;
|
||||
|
|
|
@ -56,6 +56,9 @@ catch(Exceptions\InvalidPermissionsException){
|
|||
<form class="create-update-ebook-placeholder" method="<?= Enums\HttpMethod::Post->value ?>" action="<?= $ebook->Url ?>" autocomplete="off">
|
||||
<input type="hidden" name="_method" value="<?= Enums\HttpMethod::Put->value ?>" />
|
||||
<?= Template::EbookPlaceholderForm(['ebook' => $ebook, 'isEditForm' => true]) ?>
|
||||
<div class="footer">
|
||||
<button>Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
|
|
@ -82,6 +82,9 @@ catch(Exceptions\InvalidPermissionsException){
|
|||
|
||||
<form class="create-update-ebook-placeholder" method="<?= Enums\HttpMethod::Post->value ?>" action="/ebook-placeholders" autocomplete="off">
|
||||
<?= Template::EbookPlaceholderForm(['ebook' => $ebook]) ?>
|
||||
<div class="footer">
|
||||
<button>Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
</main>
|
||||
|
|
|
@ -42,9 +42,9 @@ try{
|
|||
$_SESSION['is-only-ebook-project-created'] = true;
|
||||
}
|
||||
else{
|
||||
// No `Project`, throw the exception and really fail.
|
||||
// The existing ebook already has a `Project`, throw the exception and really fail.
|
||||
$ebook = $existingEbook;
|
||||
throw $ex;
|
||||
throw new Exceptions\ProjectExistsException('This ebook already exists, and already has an in-progress project.');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ catch(Exceptions\LoginRequiredException){
|
|||
catch(Exceptions\InvalidPermissionsException | Exceptions\InvalidHttpMethodException | Exceptions\HttpMethodNotAllowedException){
|
||||
Template::ExitWithCode(Enums\HttpCode::Forbidden);
|
||||
}
|
||||
catch(Exceptions\InvalidEbookException | Exceptions\InvalidProjectException $ex){
|
||||
catch(Exceptions\InvalidEbookException | Exceptions\ProjectExistsException | Exceptions\InvalidProjectException $ex){
|
||||
$_SESSION['ebook'] = $ebook;
|
||||
$_SESSION['exception'] = $ex;
|
||||
|
||||
|
|
|
@ -47,10 +47,10 @@ if($exception){
|
|||
<p>What kind of email would you like to receive?</p>
|
||||
<ul>
|
||||
<li>
|
||||
<label><input type="checkbox" value="1" name="issubscribedtonewsletter"<? if($subscription->IsSubscribedToNewsletter){ ?> checked="checked"<? } ?> />The occasional Standard Ebooks newsletter</label>
|
||||
<label><input type="checkbox" value="true" name="is-subscribed-to-newsletter"<? if($subscription->IsSubscribedToNewsletter){ ?> checked="checked"<? } ?> />The occasional Standard Ebooks newsletter</label>
|
||||
</li>
|
||||
<li>
|
||||
<label><input type="checkbox" value="1" name="issubscribedtosummary"<? if($subscription->IsSubscribedToSummary){ ?> checked="checked"<? } ?> />A monthly summary of new ebook releases</label>
|
||||
<label><input type="checkbox" value="true" name="is-subscribed-to-summary"<? if($subscription->IsSubscribedToSummary){ ?> checked="checked"<? } ?> />A monthly summary of new ebook releases</label>
|
||||
</li>
|
||||
</ul>
|
||||
</fieldset>
|
||||
|
|
|
@ -32,8 +32,8 @@ try{
|
|||
|
||||
$subscription->User = new User();
|
||||
$subscription->User->Email = HttpInput::Str(POST, 'email');
|
||||
$subscription->IsSubscribedToNewsletter = HttpInput::Bool(POST, 'issubscribedtonewsletter') ?? false;
|
||||
$subscription->IsSubscribedToSummary = HttpInput::Bool(POST, 'issubscribedtosummary') ?? false;
|
||||
$subscription->IsSubscribedToNewsletter = HttpInput::Bool(POST, 'is-subscribed-to-newsletter') ?? false;
|
||||
$subscription->IsSubscribedToSummary = HttpInput::Bool(POST, 'is-subscribed-to-summary') ?? false;
|
||||
|
||||
$expectedCaptcha = HttpInput::Str(SESSION, 'captcha') ?? '';
|
||||
$receivedCaptcha = HttpInput::Str(POST, 'captcha');
|
||||
|
|
|
@ -19,8 +19,10 @@ try{
|
|||
session_start();
|
||||
|
||||
$isCreated = HttpInput::Bool(SESSION, 'is-project-created') ?? false;
|
||||
$isOnlyProjectCreated = HttpInput::Bool(SESSION, 'is-only-ebook-project-created') ?? false;
|
||||
$createdProject = HttpInput::SessionObject('project', Project::class);
|
||||
|
||||
if($isCreated){
|
||||
if($isCreated || $isOnlyProjectCreated){
|
||||
// We got here because a `Project` was successfully submitted.
|
||||
http_response_code(Enums\HttpCode::Created->value);
|
||||
session_unset();
|
||||
|
@ -43,9 +45,19 @@ catch(Exceptions\InvalidPermissionsException){
|
|||
<main>
|
||||
<section>
|
||||
<h1>Projects</h1>
|
||||
<? if(Session::$User->Benefits->CanEditProjects){ ?>
|
||||
<p>
|
||||
<a href="/projects/new">New project</a>
|
||||
</p>
|
||||
<? } ?>
|
||||
<? if($createdProject !== null){ ?>
|
||||
<? if($isCreated){ ?>
|
||||
<p class="message success">Project for <a href="<?= $createdProject->Ebook->Url ?>"><?= Formatter::EscapeHtml($createdProject->Ebook->Title) ?></a> created!</p>
|
||||
<? } ?>
|
||||
|
||||
<? if($isCreated){ ?>
|
||||
<p class="message success">Project created!</p>
|
||||
<? if($isOnlyProjectCreated){ ?>
|
||||
<p class="message success">An ebook placeholder <a href="<?= $createdProject->Ebook->Url ?>">already exists</a> for this ebook, but a new project was created!</p>
|
||||
<? } ?>
|
||||
<? } ?>
|
||||
|
||||
<section id="active">
|
||||
|
|
|
@ -54,7 +54,7 @@ catch(Exceptions\InvalidPermissionsException){
|
|||
}
|
||||
?><?= Template::Header([
|
||||
'title' => 'New Project',
|
||||
'css' => ['/css/project.css'],
|
||||
'css' => ['/css/project.css', '/css/ebook-placeholder.css'],
|
||||
'description' => 'Add a new ebook project.'
|
||||
]) ?>
|
||||
<main>
|
||||
|
@ -69,7 +69,13 @@ catch(Exceptions\InvalidPermissionsException){
|
|||
<?= Template::Error(['exception' => $exception]) ?>
|
||||
|
||||
<form action="/projects" method="<?= Enums\HttpMethod::Post->value ?>" class="project-form">
|
||||
<?= Template::ProjectForm(['project' => $project, 'areFieldsRequired' => true]) ?>
|
||||
<?= Template::ProjectForm(['project' => $project]) ?>
|
||||
<? if(!isset($project->EbookId)){ ?>
|
||||
<fieldset class="create-update-ebook-placeholder placeholder-form">
|
||||
<legend>Placeholder</legend>
|
||||
<?= Template::EbookPlaceholderForm(['ebook' => $project->Ebook ?? new Ebook(), 'showProjectForm' => false]) ?>
|
||||
</fieldset>
|
||||
<? } ?>
|
||||
<div class="footer">
|
||||
<button>Submit</button>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,36 @@ try{
|
|||
|
||||
$project->FillFromHttpPost();
|
||||
|
||||
$project->Create();
|
||||
// Are we creating a new placeholder at the same time?
|
||||
if(!isset($project->EbookId)){
|
||||
$project->Ebook = new Ebook();
|
||||
$project->Ebook->FillFromEbookPlaceholderForm();
|
||||
$project->Ebook->Validate();
|
||||
|
||||
$project->Validate(true, true);
|
||||
|
||||
try{
|
||||
$project->Ebook->Create();
|
||||
$project->EbookId = $project->Ebook->EbookId;
|
||||
}
|
||||
catch(Exceptions\DuplicateEbookException $ex){
|
||||
// If the `Ebook` already exists, create the `Project` anyway.
|
||||
$project->Ebook = Ebook::GetByIdentifier($project->Ebook->Identifier);
|
||||
if(!$project->Ebook->EbookPlaceholder?->IsInProgress){
|
||||
$project->EbookId = $project->Ebook->EbookId;
|
||||
$_SESSION['is-only-ebook-project-created'] = true;
|
||||
}
|
||||
else{
|
||||
// `Ebook` exists and it's not a placeholder, so really fail.
|
||||
throw new Exceptions\EbookIsNotAPlaceholderException();
|
||||
}
|
||||
}
|
||||
|
||||
$project->Create();
|
||||
}
|
||||
else{
|
||||
$project->Create();
|
||||
}
|
||||
|
||||
$_SESSION['project'] = $project;
|
||||
$_SESSION['is-project-created'] = true;
|
||||
|
@ -52,7 +81,7 @@ catch(Exceptions\LoginRequiredException){
|
|||
catch(Exceptions\InvalidPermissionsException){
|
||||
Template::ExitWithCode(Enums\HttpCode::Forbidden);
|
||||
}
|
||||
catch(Exceptions\InvalidProjectException | Exceptions\ProjectExistsException | Exceptions\EbookIsNotAPlaceholderException $ex){
|
||||
catch(Exceptions\InvalidProjectException | Exceptions\InvalidEbookException | Exceptions\ProjectExistsException | Exceptions\DuplicateEbookException | Exceptions\EbookIsNotAPlaceholderException $ex){
|
||||
$_SESSION['project'] = $project;
|
||||
$_SESSION['exception'] = $ex;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue