Compare commits
2 Commits
00820715ea
...
a0f06d3bbe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0f06d3bbe | ||
|
|
67e970183f |
@@ -15,14 +15,14 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="file in files">
|
<tr v-for="file in files">
|
||||||
<td>{{ file.fileName }}
|
<td>{{ file.file_name }}
|
||||||
<p class="mb-0" v-if="file.book">
|
<p class="mb-0" v-if="file.book">
|
||||||
<a class="text-decoration-none" :href="'/book/'+file.book.id">{{
|
<a class="text-decoration-none" :href="'/book/'+file.book.id">{{
|
||||||
file.book.title
|
file.book.title
|
||||||
}}</a> <a href="" class="text-decoration-none link-secondary">{{ file.book.author }}</a>
|
}}</a> <a href="" class="text-decoration-none link-secondary">{{ file.book.author }}</a>
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
<td class="text-end">{{ formatSize(file.fileSize) }}</td>
|
<td class="text-end">{{ file.file_size_human }}</td>
|
||||||
<td>{{ file.extension }}</td>
|
<td>{{ file.extension }}</td>
|
||||||
<td><a :href="'/file/'+ file.id" class="link-secondary">download</a></td>
|
<td><a :href="'/file/'+ file.id" class="link-secondary">download</a></td>
|
||||||
<td><a :href="'/file/delete/'+file.id" @click.prevent="deleteFile(file.id)" class="link-danger">remove</a>
|
<td><a :href="'/file/delete/'+file.id" @click.prevent="deleteFile(file.id)" class="link-danger">remove</a>
|
||||||
@@ -61,21 +61,18 @@ export default {
|
|||||||
deleteFile: function (fileId) {
|
deleteFile: function (fileId) {
|
||||||
axios.get(window.location.origin + '/file/delete/' + fileId).then(() => this.getFiles())
|
axios.get(window.location.origin + '/file/delete/' + fileId).then(() => this.getFiles())
|
||||||
},
|
},
|
||||||
formatSize: function (bytes) {
|
|
||||||
if (bytes === 0) {
|
|
||||||
return "0.00 B";
|
|
||||||
}
|
|
||||||
const e = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
||||||
return (bytes / Math.pow(1024, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B';
|
|
||||||
},
|
|
||||||
getFiles: function () {
|
getFiles: function () {
|
||||||
axios.get(this.getFilesEndpoint()).then(response => this.files = response.data)
|
axios.get(this.getFilesEndpoint(), {
|
||||||
|
headers: {
|
||||||
|
'accept': 'application/json'
|
||||||
|
}
|
||||||
|
}).then(response => this.files = response.data)
|
||||||
},
|
},
|
||||||
getFilesEndpoint: function () {
|
getFilesEndpoint: function () {
|
||||||
if (this.bookId) {
|
if (this.bookId) {
|
||||||
return '/book/' + this.bookId + '/files';
|
return `/api/books/${this.bookId}/files`;
|
||||||
}
|
}
|
||||||
return '/file/all';
|
return `/api/files`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,13 +111,6 @@ class BookController extends AbstractController
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/{id}/files', name: 'app_book_file', methods: ['GET'])]
|
|
||||||
public function files(Book $book): JsonResponse
|
|
||||||
{
|
|
||||||
return $this->json($book->getFiles(), context: [AbstractNormalizer::IGNORED_ATTRIBUTES => ['book']]);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])]
|
#[Route('/{id}/edit', name: 'app_book_edit', methods: ['GET', 'POST'])]
|
||||||
public function edit(
|
public function edit(
|
||||||
Request $request,
|
Request $request,
|
||||||
|
|||||||
@@ -2,20 +2,30 @@
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use ApiPlatform\Core\Annotation\ApiFilter;
|
||||||
|
use ApiPlatform\Core\Annotation\ApiResource;
|
||||||
|
use ApiPlatform\Core\Annotation\ApiSubresource;
|
||||||
|
use ApiPlatform\Core\Bridge\Doctrine\Common\Filter\SearchFilterInterface;
|
||||||
|
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
|
||||||
use App\Repository\BookRepository;
|
use App\Repository\BookRepository;
|
||||||
use Doctrine\Common\Collections\ArrayCollection;
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
use Doctrine\Common\Collections\Collection;
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
|
#[ApiResource]
|
||||||
#[ORM\Entity(repositoryClass: BookRepository::class)]
|
#[ORM\Entity(repositoryClass: BookRepository::class)]
|
||||||
|
#[ApiFilter(SearchFilter::class, properties: ['title' => SearchFilterInterface::STRATEGY_PARTIAL])]
|
||||||
class Book
|
class Book
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
#[ORM\GeneratedValue]
|
#[ORM\GeneratedValue]
|
||||||
#[ORM\Column(type: 'integer')]
|
#[ORM\Column(type: 'integer')]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $title;
|
private $title;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
@@ -33,6 +43,7 @@ class Book
|
|||||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||||
private $subtitle;
|
private $subtitle;
|
||||||
|
|
||||||
|
#[ApiSubresource]
|
||||||
#[ORM\OneToMany(mappedBy: 'book', targetEntity: File::class, orphanRemoval: true)]
|
#[ORM\OneToMany(mappedBy: 'book', targetEntity: File::class, orphanRemoval: true)]
|
||||||
private $files;
|
private $files;
|
||||||
|
|
||||||
@@ -46,6 +57,7 @@ class Book
|
|||||||
private $volume;
|
private $volume;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $author;
|
private $author;
|
||||||
|
|
||||||
#[ORM\Column(type: 'text', nullable: true)]
|
#[ORM\Column(type: 'text', nullable: true)]
|
||||||
|
|||||||
@@ -5,23 +5,28 @@ namespace App\Entity;
|
|||||||
use ApiPlatform\Core\Annotation\ApiResource;
|
use ApiPlatform\Core\Annotation\ApiResource;
|
||||||
use App\Repository\FileRepository;
|
use App\Repository\FileRepository;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Serializer\Annotation\SerializedName;
|
||||||
|
|
||||||
#[ApiResource]
|
#[ApiResource(collectionOperations: ['get'], itemOperations: ['get'], denormalizationContext: ['groups' => ['file:write']], normalizationContext: ['groups' => ['file:read']])]
|
||||||
#[ORM\Entity(repositoryClass: FileRepository::class)]
|
#[ORM\Entity(repositoryClass: FileRepository::class)]
|
||||||
class File
|
class File
|
||||||
{
|
{
|
||||||
#[ORM\Id]
|
#[ORM\Id]
|
||||||
#[ORM\GeneratedValue]
|
#[ORM\GeneratedValue]
|
||||||
#[ORM\Column(type: 'integer')]
|
#[ORM\Column(type: 'integer')]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $id;
|
private $id;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $file_name;
|
private $file_name;
|
||||||
|
|
||||||
#[ORM\Column(type: 'integer')]
|
#[ORM\Column(type: 'integer')]
|
||||||
private $file_size;
|
private $file_size;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $extension;
|
private $extension;
|
||||||
|
|
||||||
#[ORM\Column(type: 'string', length: 255)]
|
#[ORM\Column(type: 'string', length: 255)]
|
||||||
@@ -29,6 +34,7 @@ class File
|
|||||||
|
|
||||||
#[ORM\ManyToOne(targetEntity: Book::class, inversedBy: 'files')]
|
#[ORM\ManyToOne(targetEntity: Book::class, inversedBy: 'files')]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
|
#[Groups('file:read')]
|
||||||
private $book;
|
private $book;
|
||||||
|
|
||||||
public function getId(): ?int
|
public function getId(): ?int
|
||||||
@@ -53,6 +59,15 @@ class File
|
|||||||
return $this->file_size;
|
return $this->file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Groups('file:read')]
|
||||||
|
#[SerializedName('file_size_human')]
|
||||||
|
public function getFileSizeHuman(): string
|
||||||
|
{
|
||||||
|
$base = log($this->file_size) / log(1024);
|
||||||
|
$suffix = array("B", "KB", "MB", "GB", "TB")[floor($base)];
|
||||||
|
return round(pow(1024, $base - floor($base)), 2) . $suffix;
|
||||||
|
}
|
||||||
|
|
||||||
public function setFileSize(int $file_size): self
|
public function setFileSize(int $file_size): self
|
||||||
{
|
{
|
||||||
$this->file_size = $file_size;
|
$this->file_size = $file_size;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
<th></th>
|
<th></th>
|
||||||
<th>Title</th>
|
<th>Title</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
|
<th>Rating</th>
|
||||||
<th>Publisher</th>
|
<th>Publisher</th>
|
||||||
<th>Publish date</th>
|
<th>Publish date</th>
|
||||||
<th>actions</th>
|
<th>actions</th>
|
||||||
@@ -38,6 +39,7 @@
|
|||||||
<td><a href="{{ path('app_book_show', {'id': book.id}) }}"
|
<td><a href="{{ path('app_book_show', {'id': book.id}) }}"
|
||||||
class="text-decoration-none">{{ book.title }}</a></td>
|
class="text-decoration-none">{{ book.title }}</a></td>
|
||||||
<td>{{ book.description | slice(0, 200) }}</td>
|
<td>{{ book.description | slice(0, 200) }}</td>
|
||||||
|
<td>{% if book.rating %}{% for i in range(1, book.rating) %}⭐{% endfor %}{% endif %}</td>
|
||||||
<td>{{ book.publisher }}</td>
|
<td>{{ book.publisher }}</td>
|
||||||
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
|
<td>{{ book.publishDate ? book.publishDate|date('Y-m-d') : '' }}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<h1>{{ book.title }}</h1>
|
<h1>{{ book.title }}</h1>
|
||||||
<h3>{{ book.subtitle }}</h3>
|
<h3>{{ book.subtitle }}</h3>
|
||||||
<p>{{ book.author }}</p>
|
<p>{{ book.author }}</p>
|
||||||
<p>{% for i in range(1, book.rating) %}⭐{% endfor %}</p>
|
<p>{% if book.rating %}{% for i in range(1, book.rating) %}⭐{% endfor %}{% endif %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user