Styled book form and added an ux dropzone component.

This commit is contained in:
krzysiej
2022-05-31 14:34:47 +02:00
parent 040c82831b
commit 9817aa4c3f
14 changed files with 211 additions and 25 deletions

View File

@@ -1,4 +1,14 @@
{ {
"controllers": [], "controllers": {
"@symfony/ux-dropzone": {
"dropzone": {
"enabled": true,
"fetch": "eager",
"autoimport": {
"@symfony/ux-dropzone/src/style.css": true
}
}
}
},
"entrypoints": [] "entrypoints": []
} }

View File

@@ -0,0 +1,36 @@
// mydropzone_controller.js
import { Controller } from '@hotwired/stimulus';
export default class extends Controller {
connect() {
this.element.addEventListener('dropzone:connect', this._onConnect);
this.element.addEventListener('dropzone:change', this._onChange);
this.element.addEventListener('dropzone:clear', this._onClear);
}
disconnect() {
// You should always remove listeners when the controller is disconnected to avoid side-effects
this.element.removeEventListener('dropzone:connect', this._onConnect);
this.element.removeEventListener('dropzone:change', this._onChange);
this.element.removeEventListener('dropzone:clear', this._onClear);
}
_onConnect(event) {
// The dropzone was just created
console.info(event);
console.info('onconnect');
}
_onChange(event) {
// The dropzone just changed
console.info(event);
console.info('onchange');
}
_onClear(event) {
// The dropzone has just been cleared
console.info(event);
console.info('onclear');
}
}

View File

@@ -39,6 +39,7 @@
"symfony/string": "6.0.*", "symfony/string": "6.0.*",
"symfony/translation": "6.0.*", "symfony/translation": "6.0.*",
"symfony/twig-bundle": "6.0.*", "symfony/twig-bundle": "6.0.*",
"symfony/ux-dropzone": "^2.1",
"symfony/validator": "6.0.*", "symfony/validator": "6.0.*",
"symfony/web-link": "6.0.*", "symfony/web-link": "6.0.*",
"symfony/webapp-meta": "^1.0", "symfony/webapp-meta": "^1.0",

82
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "2eef8acf0a01cf89e1edb8087c4d2ac3", "content-hash": "38958ff5221180c36bc97324f82755b6",
"packages": [ "packages": [
{ {
"name": "doctrine/annotations", "name": "doctrine/annotations",
@@ -7460,6 +7460,86 @@
], ],
"time": "2022-04-03T13:04:20+00:00" "time": "2022-04-03T13:04:20+00:00"
}, },
{
"name": "symfony/ux-dropzone",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-dropzone.git",
"reference": "e5115ed7fc894248b77bffebb7f57bc2f584d219"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-dropzone/zipball/e5115ed7fc894248b77bffebb7f57bc2f584d219",
"reference": "e5115ed7fc894248b77bffebb7f57bc2f584d219",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/config": "^4.4.17|^5.0|^6.0",
"symfony/dependency-injection": "^4.4.17|^5.0|^6.0",
"symfony/form": "^4.4.17|^5.0|^6.0",
"symfony/http-kernel": "^4.4.17|^5.0|^6.0"
},
"require-dev": {
"symfony/framework-bundle": "^4.4.17|^5.0|^6.0",
"symfony/phpunit-bridge": "^5.2|^6.0",
"symfony/twig-bundle": "^4.4.17|^5.0|^6.0",
"symfony/var-dumper": "^4.4.17|^5.0|^6.0"
},
"type": "symfony-bundle",
"extra": {
"thanks": {
"name": "symfony/ux",
"url": "https://github.com/symfony/ux"
}
},
"autoload": {
"psr-4": {
"Symfony\\UX\\Dropzone\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Titouan Galopin",
"email": "galopintitouan@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "File input dropzones for Symfony Forms",
"homepage": "https://symfony.com",
"keywords": [
"symfony-ux"
],
"support": {
"source": "https://github.com/symfony/ux-dropzone/tree/v2.1.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2022-02-01T04:57:29+00:00"
},
{ {
"name": "symfony/validator", "name": "symfony/validator",
"version": "v6.0.8", "version": "v6.0.8",

View File

@@ -6,6 +6,9 @@
parameters: parameters:
book_covers: '%kernel.project_dir%/public/book_covers/' book_covers: '%kernel.project_dir%/public/book_covers/'
book_files: '%kernel.project_dir%/public/book_files/' book_files: '%kernel.project_dir%/public/book_files/'
api_pass: 'secret_password'
api_user: 'my_name'
bankAccount: '1093849023/2013'
services: services:
# default configuration for services in *this* file # default configuration for services in *this* file
@@ -13,6 +16,8 @@ services:
autowire: true # Automatically injects dependencies in your services. autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services # makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name # this creates a service per class whose id is the fully-qualified class name
App\: App\:
@@ -22,5 +27,9 @@ services:
- '../src/Entity/' - '../src/Entity/'
- '../src/Kernel.php' - '../src/Kernel.php'
App\Service\FileService:
arguments:
$bookFiles: '%book_files%'
# add more service definitions when explicit configuration is needed # add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones # please note that last definitions always *replace* previous ones

View File

@@ -2,6 +2,7 @@
"devDependencies": { "devDependencies": {
"@hotwired/stimulus": "^3.0.0", "@hotwired/stimulus": "^3.0.0",
"@symfony/stimulus-bridge": "^3.0.0", "@symfony/stimulus-bridge": "^3.0.0",
"@symfony/ux-dropzone": "file:vendor/symfony/ux-dropzone/Resources/assets",
"@symfony/webpack-encore": "^2.0.0", "@symfony/webpack-encore": "^2.0.0",
"axios": "^0.27.2", "axios": "^0.27.2",
"core-js": "^3.0.0", "core-js": "^3.0.0",

View File

@@ -44,9 +44,9 @@ class FileController extends AbstractController
public function get(File $file) public function get(File $file)
{ {
return $this->file( return $this->file(
$filePath = $this->getParameter('book_files') . '/' . 'ebook_' . $file->getBook()->getId() . '_' . $this->getParameter('book_files') . '/' . 'ebook_' . $file->getBook()->getId() . '_' .
md5($file->getFileName()) . '.' . md5($file->getFileName()) . '.' .
$file->getExtension(), $file->getExtension(),
$file->getFileName() $file->getFileName()
); );
} }

View File

@@ -0,0 +1,36 @@
<?php
namespace App\Service;
use App\Entity\File;
use App\Repository\FileRepository;
use Doctrine\Common\Collections\Collection;
use Symfony\Component\Filesystem\Filesystem;
class FileService
{
private Filesystem $fileSystem;
private string $bookFiles;
public function __construct(string $bookFiles, FileSystem $filesystem)
{
$this->bookFiles = $bookFiles;
$this->fileSystem = $filesystem;
}
/**
* @param File[] $files
* @return void
*/
public function removeFiles(Collection $files)
{
foreach ($files as $file) {
$filePath = $this->bookFiles . '/' . 'ebook_' . $file->getBook()->getId() . '_' .
md5($file->getFileName()) . '.' .
$file->getExtension();
$this->fileSystem->remove($filePath);
}
}
}

View File

@@ -462,6 +462,9 @@
"./templates/base.html.twig" "./templates/base.html.twig"
] ]
}, },
"symfony/ux-dropzone": {
"version": "v2.1.1"
},
"symfony/validator": { "symfony/validator": {
"version": "6.0", "version": "6.0",
"recipe": { "recipe": {

View File

@@ -7,7 +7,6 @@
{{ include('book/_form.html.twig', {'button_label': 'Update'}) }} {{ include('book/_form.html.twig', {'button_label': 'Update'}) }}
<a href="{{ path('app_book_index') }}">back to list</a>
{{ include('book/_delete_form.html.twig') }} {{ include('book/_delete_form.html.twig') }}
{% endblock %} {% endblock %}

View File

@@ -3,29 +3,40 @@
{% block title %}Book index{% endblock %} {% block title %}Book index{% endblock %}
{% block body %} {% block body %}
<h1>Book index</h1> <div class="d-flex flex-row justify-content-between align-items-center">
<div>
<h1>Book index</h1>
</div>
<div>
<a href="{{ path('app_book_new') }}" class="btn btn-primary">Create new</a>
</div>
</div>
<table class="table"> <table class="table">
<thead> <thead>
<tr> <tr>
<th>Cover</th> <th>Cover</th>
<th>Id</th> <th>Id</th>
<th>Title</th> <th>Title</th>
<th>Language</th> <th>Language</th>
<th>Description</th> <th>Description</th>
<th>Publisher</th> <th>Publisher</th>
<th>Publish_date</th> <th>Publish_date</th>
<th>actions</th> <th>actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for book in books %} {% for book in books %}
<tr> <tr>
<td>{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}<img class="img-thumbnail" style="max-width: 80px" src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}" /> {% endif %}</td> <td>{% if file_exists(asset('book_covers/cover_' ~ book.id ~ '.jpg')) %}<img class="img-thumbnail"
style="max-width: 80px"
src="{{ asset('book_covers/cover_' ~ book.id ~ '.jpg' ) }}" /> {% endif %}
</td>
<td>{{ book.id }}</td> <td>{{ book.id }}</td>
<td>{{ book.Title }}</td> <td>{{ book.Title }}</td>
<td>{{ book.language }}</td> <td>{{ book.language }}</td>
<td>{{ book.description }}</td> <td>{{ book.description | slice(0, 200) }}</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>
@@ -40,6 +51,4 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<a href="{{ path('app_book_new') }}">Create new</a>
{% endblock %} {% endblock %}

View File

@@ -9,7 +9,6 @@
{{ include('book/_form.html.twig') }} {{ include('book/_form.html.twig') }}
</book> </book>
</div> </div>
<a href="{{ path('app_book_index') }}">back to list</a>
{% endblock %} {% endblock %}
{% block javascripts %} {% block javascripts %}

View File

@@ -21,7 +21,7 @@
</tr> </tr>
<tr> <tr>
<th>Description</th> <th>Description</th>
<td>{{ book.description }}</td> <td>{{ book.description | nl2br }}</td>
</tr> </tr>
<tr> <tr>
<th>Publisher</th> <th>Publisher</th>
@@ -39,7 +39,7 @@
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>File name</th> <th>File name</th>
<th>File size</th> <th class="text-end">File size</th>
<th>Extension</th> <th>Extension</th>
<th>Download</th> <th>Download</th>
<th>Remove</th> <th>Remove</th>
@@ -50,7 +50,7 @@
<tr> <tr>
<td>{{ file.id }}</td> <td>{{ file.id }}</td>
<td>{{ file.fileName }}</td> <td>{{ file.fileName }}</td>
<td>{{ file.fileSize | bytes_format }}</td> <td class="text-end">{{ file.fileSize | bytes_format }}</td>
<td>{{ file.extension }}</td> <td>{{ file.extension }}</td>
<td><a href="{{ path('app_file_download', {id: file.id }) }}" class="link-secondary">download</a></td> <td><a href="{{ path('app_file_download', {id: file.id }) }}" class="link-secondary">download</a></td>
<td><a href="{{ path('app_file_delete', {id: file.id}) }}" class="link-danger">remove</a></td> <td><a href="{{ path('app_file_delete', {id: file.id}) }}" class="link-danger">remove</a></td>

View File

@@ -1008,6 +1008,9 @@
loader-utils "^2.0.0" loader-utils "^2.0.0"
schema-utils "^3.0.0" schema-utils "^3.0.0"
"@symfony/ux-dropzone@file:vendor/symfony/ux-dropzone/Resources/assets":
version "1.1.0"
"@symfony/webpack-encore@^2.0.0": "@symfony/webpack-encore@^2.0.0":
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-2.1.0.tgz#353a1b8bc38022046cbbc3d627c4076aca2e28c3" resolved "https://registry.yarnpkg.com/@symfony/webpack-encore/-/webpack-encore-2.1.0.tgz#353a1b8bc38022046cbbc3d627c4076aca2e28c3"