diff --git a/app/Resources/assets/images/brickset_logo.png b/app/Resources/assets/images/brickset_logo.png new file mode 100644 index 0000000..f1eee4d Binary files /dev/null and b/app/Resources/assets/images/brickset_logo.png differ diff --git a/app/Resources/assets/images/rebrickable_logo.png b/app/Resources/assets/images/rebrickable_logo.png new file mode 100644 index 0000000..4651fd8 Binary files /dev/null and b/app/Resources/assets/images/rebrickable_logo.png differ diff --git a/app/Resources/assets/style/main.scss b/app/Resources/assets/style/main.scss index 2f81fec..5f2e904 100644 --- a/app/Resources/assets/style/main.scss +++ b/app/Resources/assets/style/main.scss @@ -1,4 +1,43 @@ -.ui.fixed + .ui.main { - margin-top: 5em; -} +.default-theme { + .ui.fixed + .ui.grid { + border-radius: 0; + border: 0; + box-shadow: none; + } + + .item-info { + min-height: 300px; + } + + .ui.fixed + .ui.main { + margin-top: 3em; + padding-bottom: 4em; + } + + .link { + padding-left: 30px; + position: relative; + } + + .link:before { + width: 23px; + height: 23px; + position: absolute; + left: 0; + display: inline-block; + } + + .link.brickset:before { + content: ''; + background: url("/resources/images/brickset_logo.png"); + background-size: cover; + } + + .link.rebrickable:before { + content: ''; + background: url("/resources/images/rebrickable_logo.png"); + background-size: cover; + } + +} \ No newline at end of file diff --git a/app/Resources/views/base.html.twig b/app/Resources/views/base.html.twig index 89487ea..491df83 100644 --- a/app/Resources/views/base.html.twig +++ b/app/Resources/views/base.html.twig @@ -6,37 +6,43 @@ -
-
-
- - + {% endblock page %} {% endblock %} \ No newline at end of file diff --git a/app/Resources/views/default/index.html.twig b/app/Resources/views/default/index.html.twig index 918e8e0..4222685 100644 --- a/app/Resources/views/default/index.html.twig +++ b/app/Resources/views/default/index.html.twig @@ -1,6 +1,14 @@ {% extends 'base.html.twig' %} -{% block content %} - +{% block page %} +
+
+
+
+ Hello, world! +
+
+
+
{% endblock %} diff --git a/app/Resources/views/html.html.twig b/app/Resources/views/html.html.twig index 4e28c53..0c017fd 100644 --- a/app/Resources/views/html.html.twig +++ b/app/Resources/views/html.html.twig @@ -8,7 +8,7 @@ {% endblock %} - + {% block body %} {% endblock %} diff --git a/app/Resources/views/model/detail.html.twig b/app/Resources/views/model/detail.html.twig index 8d33ad5..67fe580 100644 --- a/app/Resources/views/model/detail.html.twig +++ b/app/Resources/views/model/detail.html.twig @@ -2,82 +2,111 @@ {% import 'macros/elements.html.twig' as elements %} -{% block title %}{{ model.name }}{% endblock %} +{% block title %}#{{ model.number }} - {{ model.name }}{% endblock %} -{% block header %}{{ model.name }}{% endblock %} +{% block header %}#{{ model.number }} - {{ model.name }}{% endblock %} {% block content %} -
- +
+
+
+ +
+
+
+
+ + + + + + + + + + +
category{{ model.category ? model.category.name }}
model{{ model.path }}
author{{ model.author }}
+ +
+
keywords:
+
+ {% for keyword in model.keywords %} + {{ keyword.name }} + {% endfor %} +
+
aliases:
+
+ {% for alias in model.aliases %} + {{ alias.number }}{% if not loop.last %},{% endif %} + {% endfor %} +
+
Download:
+
{{ model.number }}
+
rebrickable parts ({{ rbParts|length }}):
+
+ {#

#} + {#

#} + {#{% for alias in rbParts %}#} + {#{{ alias.number }}#} + {#{% endfor %}#} + {#
#} + {#

#} +
+
+
+
-
-
number:
{{ model.number }}
-
name:
{{ model.name }}
-
category:
{{ model.category ? model.category.name }}
-
model:
{{ model.path }}
-
author:
{{ model.author }}
-
modified:
{{ model.modified ? model.modified|date('Y-m-d') }}
-
keywords:
-
- {% for keyword in model.keywords %} - {{ keyword.name }} - {% endfor %} -
-
aliases:
-
- {% for alias in model.aliases %} - {{ alias.number }} - {% endfor %} -
-
Download:
-
{{ model.number }}
-
rebrickable parts ({{ rbParts|length }}):
-
-

-

- {% for alias in rbParts %} - {{ alias.number }} - {% endfor %} + + +

+ Subparts of this model +

+ +
+ {% for subpart in model.subparts %} +
+ {{ elements.part(subpart.subpart) }}
-

-
-
- -
-

- Subparts of this model -

- -
- {% for subpart in model.subparts %} -
- {{ elements.part(subpart.subpart) }} -
- {% endfor %} -
- -

- Model is subpart of -

- -
- {% for subpart in model.parents %} -
- {{ elements.part(subpart.parent) }} -
- {% endfor %} -
- -

- Sets ({{ sets|length }}) -

- - {% for set in sets %} - {{ set.number }} {% endfor %}
+ +

+ Model is subpart of +

+ +
+ {% for subpart in model.parents %} +
+ {{ elements.part(subpart.parent) }} +
+ {% endfor %} +
+ + +

+ Related +

+ +
+ {% for subpart in related %} +
+ {{ elements.part(subpart) }} +
+ {% endfor %} +
+ +

+ Sets ({{ sets|length }}) +

+ + {% for set in sets %} + {{ set.number }} + {% endfor %} + + + {% endblock %} {% block javascripts %} diff --git a/app/Resources/views/model/index.html.twig b/app/Resources/views/model/index.html.twig index 11219bf..f175824 100644 --- a/app/Resources/views/model/index.html.twig +++ b/app/Resources/views/model/index.html.twig @@ -2,7 +2,13 @@ {% import 'macros/elements.html.twig' as elements %} +{% block title %}{{ 'page.model.index' | trans }}{% endblock %} + +{% block header %}{{ 'page.model.index' | trans }}{% endblock %} + {% block content %} +
+
{{ form_start(form) }} @@ -16,8 +22,9 @@
{{ form_end(form) }} - - +
+
+ {{ knp_pagination_render(models) }}

{{ models.getTotalItemCount }}

{% for model in models %} @@ -26,4 +33,6 @@
{{ knp_pagination_render(models) }} +
+
{% endblock %} diff --git a/app/Resources/views/rebrickable/color/index.html.twig b/app/Resources/views/rebrickable/color/index.html.twig index e06398d..560f9f1 100644 --- a/app/Resources/views/rebrickable/color/index.html.twig +++ b/app/Resources/views/rebrickable/color/index.html.twig @@ -2,7 +2,7 @@ {% block content %} - +
diff --git a/app/Resources/views/rebrickable/part/index.html.twig b/app/Resources/views/rebrickable/part/index.html.twig new file mode 100644 index 0000000..9b5a206 --- /dev/null +++ b/app/Resources/views/rebrickable/part/index.html.twig @@ -0,0 +1,25 @@ +{% extends 'base.html.twig' %} + +{% block content %} + +
+
+ {% for part in parts %} + + {% endfor %} +
+
+ +

{{ parts.getTotalItemCount }}

+ + {{ knp_pagination_render(parts) }} +{% endblock %} diff --git a/app/Resources/views/rebrickable/set/parts.html.twig b/app/Resources/views/rebrickable/set/parts.html.twig index 5e52b8c..90b6c2a 100644 --- a/app/Resources/views/rebrickable/set/parts.html.twig +++ b/app/Resources/views/rebrickable/set/parts.html.twig @@ -1,8 +1,9 @@ +{% if regularParts|length > 0 %}

Regular parts

-
+
{% for inventoryPart in regularParts %} {% if inventoryPart.part is defined %}
@@ -12,18 +13,20 @@
-
{{ inventoryPart.part.number }}
{{ inventoryPart.isSpare ? 'Spare' : 'Regular' }}
+
{{ inventoryPart.part.number }}
{% endif %} {% endfor %}
+{% endif %} +{% if spareParts|length > 0 %}

Spare parts

-
+
{% for inventoryPart in spareParts %} {% if inventoryPart.part is defined %}
@@ -33,10 +36,11 @@
-
{{ inventoryPart.part.number }}
{{ inventoryPart.isSpare ? 'Spare' : 'Regular' }}
+
{{ inventoryPart.part.number }}
{% endif %} {% endfor %} -
\ No newline at end of file + +{% endif %} diff --git a/app/Resources/views/rebrickable/set/sets.html.twig b/app/Resources/views/rebrickable/set/sets.html.twig new file mode 100644 index 0000000..593b934 --- /dev/null +++ b/app/Resources/views/rebrickable/set/sets.html.twig @@ -0,0 +1,16 @@ +

Sets

+
+
+ {% for set in inventorySets %} + + {% endfor %} +
+
\ No newline at end of file diff --git a/app/Resources/views/set/detail.html.twig b/app/Resources/views/set/detail.html.twig index 0c2e5d3..6b93a16 100644 --- a/app/Resources/views/set/detail.html.twig +++ b/app/Resources/views/set/detail.html.twig @@ -5,90 +5,134 @@ {% block header %}{{ rbset ? rbset.number }} {{ rbset ? rbset.name }}{% endblock %} {% block content %} - {% if brset %} - Brickset - {% endif %} - - {% if rbset is not null %} - Rebrickable -
-
number:
{{ rbset.number }}
-
year:
{{ rbset.year }}
-
name:
{{ rbset.name }}
-
theme:
{{ rbset.theme.name }}
- {% if rbset.theme.parent %} -
themeparent:
{{ rbset.theme.parent.name }}
- {% if rbset.theme.parent.parent %} -
themeparent:
{{ rbset.theme.parent.parent.name }}
+
+
+
+ {% if brset %} + + {% elseif rbset %} + {% endif %} - {% endif %} -
count of parts:
{{ rbset.partCount }}
-
- {% endif %} + + +
+
+
+ + + + + + + + + + + + {% if rbset %} + + {% elseif brset %} + + {% endif %} + + + + + {% if brset %} + + + + + {% endif %} + {% if rbset %} + + + + + {% endif %} +
number{{ brset ? brset.legoSetID : rbset ? rbset.number : null}}
name{{ brset ? brset.name : rbset ? rbset.name : null}}
year{{ brset ? brset.year : rbset ? rbset.year : null}}
theme{{ rbset.theme.parent ? rbset.theme.parent.name }} {{ rbset.theme.name }} {{ brset.theme }}
parts{{ brset ? brset.pieces : rbset ? rbset.partCount }}
Brickset
Rebrickable
- {% if brset is not null %} -
-
year:
{{ brset.year }}
-
name:
{{ brset.name }}
-
themegroup:
{{ brset.themeGroup }}
-
theme:
{{ brset.theme }}
-
subtheme:
{{ brset.subtheme }}
-
count of parts:
{{ brset.pieces }}
-
lego id:
{{ brset.legoSetID }}
-
minifigs:
{{ brset.minifigs }}
-
description:
{{ brset.description }}
-
- {% endif %} - - {% if brset %} - - {% elseif rbset %} - - {% endif %} - - {#{{ brset ? dump(brset) }}#} - - +
-
- {% if rbset %} - {{ render(controller('AppBundle:Rebrickable/Set:parts', { 'number': rbset.number })) }} -
-
-

- Sets -

+
+ +
+ {% if rbset %} - {% for set in inventorySets %} - - {% endfor %} -
+
+ + {#{{ render(controller('AppBundle:Rebrickable/Set:parts', { 'number': rbset.number })) }}#} + + {% endif %} +
+ {% if brset %} +
+ {#
#} + + {{ render(controller('AppBundle:Brickset/Set:images', { 'id': brset.setID })) }} +
+
+ {#
#} + + {{ render(controller('AppBundle:Brickset/Set:instructions', { 'id': brset.setID })) }} +
+
+ {#
#} + + {{ render(controller('AppBundle:Brickset/Set:reviews', { 'id': brset.setID })) }} +
+
+ {{ brset.description }}
{% endif %}
- {% if brset %} -
- {{ render(controller('AppBundle:Brickset/Set:images', { 'id': brset.setID })) }} -
-
- {{ render(controller('AppBundle:Brickset/Set:instructions', { 'id': brset.setID })) }} -
-
- {{ render(controller('AppBundle:Brickset/Set:reviews', { 'id': brset.setID })) }} -
- {% endif %} + + +{% endblock %} + +{% block javascripts %} + {{ parent() }} + + {% endblock %} \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index ea31b09..bc7a03b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -48,9 +48,10 @@ gulp.task('files:semantic', function () { }); gulp.task('files:images', function () { - return gulp.src( - 'node_modules/lightbox2/dist/images/**' - ) + return gulp.src([ + 'node_modules/lightbox2/dist/images/**', + 'app/Resources/assets/images/**' + ]) .pipe(gulp.dest('web/resources/images')); }); diff --git a/src/AppBundle/Controller/Rebrickable/SetController.php b/src/AppBundle/Controller/Rebrickable/SetController.php index b86ef22..485b543 100644 --- a/src/AppBundle/Controller/Rebrickable/SetController.php +++ b/src/AppBundle/Controller/Rebrickable/SetController.php @@ -33,44 +33,32 @@ class SetController extends Controller $regularParts = $em->getRepository(Inventory_Part::class)->findAllRegularBySetNumber($set->getNumber()); $spareParts = $em->getRepository(Inventory_Part::class)->findAllSpareBySetNumber($set->getNumber()); - return $this->render('rebrickable/set/parts.html.twig', [ + $template = $this->render('rebrickable/set/parts.html.twig', [ 'regularParts' => $regularParts, 'spareParts' => $spareParts, ]); + + $json = json_encode($template->getContent()); + $response = new Response($json, 200); + $response->headers->set('Content-Type', 'application/json'); + return $response; } + /** + * @Route("/{number}/sets", name="rebrickable_set_sets") + */ + public function setsAction(Set $set) { + $em = $this->getDoctrine()->getManager(); -// /** -// * @Route("/download/{number}", name="set_download") -// */ -// public function downloadZipAction(Request $request, $number) { -// $em = $this->getDoctrine()->getManager(); -// -// $inventoryParts = $em->getRepository(Inventory_Part::class)->findAllBySetNumber($number); -// -// $zip = new \ZipArchive(); -// $zipName = 'set_'.$number.'.zip'; -// $zip->open($zipName, \ZipArchive::CREATE); -// /** @var Inventory_Part $part */ -// foreach ($inventoryParts as $part) { -// $filename = $part->getPart()->getNumber().'_('.$part->getColor()->getName().'_'.$part->getQuantity().'x).stl'; -// -// try { -// if($part->getPart()->getModel()) { -// $zip->addFromString($filename, $this->get('oneup_flysystem.media_filesystem')->read($part->getPart()->getModel()->getPath())); -// } -// } catch (\Exception $e) { -// dump($e); -// } -// } -// $zip->close(); -// -// $response = new Response(file_get_contents($zipName)); -// $response->headers->set('Content-Type', 'application/zip'); -// $response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"'); -// $response->headers->set('Content-length', filesize($zipName)); -// -// return $response; -// } + $inventorySets = $em->getRepository(Inventory_Set::class)->findAllBySetNumber($set->getNumber()); + $template = $this->render('rebrickable/set/sets.html.twig', [ + 'inventorySets' => $inventorySets, + ]); + + $json = json_encode($template->getContent()); + $response = new Response($json, 200); + $response->headers->set('Content-Type', 'application/json'); + return $response; + } } diff --git a/src/AppBundle/Controller/SetController.php b/src/AppBundle/Controller/SetController.php index c9bd5f3..14a1137 100644 --- a/src/AppBundle/Controller/SetController.php +++ b/src/AppBundle/Controller/SetController.php @@ -2,6 +2,7 @@ namespace AppBundle\Controller; +use AppBundle\Api\Exception\ApiException; use AppBundle\Api\Exception\EmptyResponseException; use AppBundle\Entity\LDraw\Model; use AppBundle\Entity\Rebrickable\Color; @@ -58,88 +59,64 @@ class SetController extends Controller */ public function detailAction(Request $request, $number) { - $brset = null; - $rbset = null; - $inventorySets = null; - - $inventorySets = $this->getDoctrine()->getManager()->getRepository(Inventory_Set::class)->findAllBySetNumber($number); + $rebrickableSet = null; + $bricksetSet = null; try { - if(($rbset = $this->getDoctrine()->getManager()->getRepository(Set::class)->find($number)) == null) { + if(($rebrickableSet = $this->getDoctrine()->getManager()->getRepository(Set::class)->find($number)) == null) { $this->addFlash('warning', 'Set not found in Rebrickable database'); }; - $brset = $this->get('api.manager.brickset')->getSetByNumber($number); + $bricksetSet = $this->get('api.manager.brickset')->getSetByNumber($number); + dump($bricksetSet); } catch (EmptyResponseException $e) { $this->addFlash('warning', 'Set not found in Brickset database'); + } catch (ApiException $e) { + $this->addFlash('error', $e->getService()); } catch (\Exception $e) { $this->addFlash('error', $e->getMessage()); } + if(!$rebrickableSet && !$bricksetSet) { + return $this->render('error/error.html.twig'); + } + return $this->render('set/detail.html.twig', [ - 'rbset' => $rbset, - 'inventorySets' => $inventorySets, - 'brset' => $brset, + 'rbset' => $rebrickableSet, + 'brset' => $bricksetSet, ]); } -// -// /** -// * @Route("/{number}/parts", name="set_parts") -// */ -// public function partsAction(Set $set) { -// $em = $this->getDoctrine()->getManager(); -// -// $em->getRepository(Color::class)->findAll(); -// $em->getRepository(Part::class)->findAllBySetNumber($set->getNumber()); -// -// $regularParts = $em->getRepository(Inventory_Part::class)->findAllRegularBySetNumber($set->getNumber()); -// $spareParts = $em->getRepository(Inventory_Part::class)->findAllSpareBySetNumber($set->getNumber()); -// -// $count = 0; -// /** @var Inventory_Part $inventoryPart */ -// foreach ($regularParts as $inventoryPart) { -// $count += $inventoryPart->getQuantity(); -// } -// -// dump($count); -// -// return $this->render('rebrickable/set/parts.html.twig', [ -// 'regularParts' => $regularParts, -// 'spareParts' => $spareParts, -// 'totalParts' => $count -// ]); -// } -// -//// /** -//// * @Route("/download/{number}", name="set_download") -//// */ -//// public function downloadZipAction(Request $request, $number) { -//// $em = $this->getDoctrine()->getManager(); -//// -//// $inventoryParts = $em->getRepository(Inventory_Part::class)->findAllBySetNumber($number); -//// -//// $zip = new \ZipArchive(); -//// $zipName = 'set_'.$number.'.zip'; -//// $zip->open($zipName, \ZipArchive::CREATE); -//// /** @var Inventory_Part $part */ -//// foreach ($inventoryParts as $part) { -//// $filename = $part->getPart()->getNumber().'_('.$part->getColor()->getName().'_'.$part->getQuantity().'x).stl'; -//// -//// try { -//// if($part->getPart()->getModel()) { -//// $zip->addFromString($filename, $this->get('oneup_flysystem.media_filesystem')->read($part->getPart()->getModel()->getPath())); -//// } -//// } catch (\Exception $e) { -//// dump($e); -//// } -//// } -//// $zip->close(); -//// -//// $response = new Response(file_get_contents($zipName)); -//// $response->headers->set('Content-Type', 'application/zip'); -//// $response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"'); -//// $response->headers->set('Content-length', filesize($zipName)); -//// -//// return $response; -//// } + + /** + * @Route("/{number}/download", name="set_download") + */ + public function downloadZipAction(Request $request, $number) { + $em = $this->getDoctrine()->getManager(); + + $inventoryParts = $em->getRepository(Inventory_Part::class)->findAllRegularBySetNumber($number); + + $zip = new \ZipArchive(); + $zipName = 'set_'.$number.'.zip'; + $zip->open($zipName, \ZipArchive::CREATE); + /** @var Inventory_Part $part */ + foreach ($inventoryParts as $part) { + $filename = $part->getPart()->getNumber().'_('.$part->getColor()->getName().'_'.$part->getQuantity().'x).stl'; + + try { + if($part->getPart()->getModel()) { + $zip->addFromString($filename, $this->get('oneup_flysystem.media_filesystem')->read($part->getPart()->getModel()->getPath())); + } + } catch (\Exception $e) { + dump($e); + } + } + $zip->close(); + + $response = new Response(file_get_contents($zipName)); + $response->headers->set('Content-Type', 'application/zip'); + $response->headers->set('Content-Disposition', 'attachment;filename="' . $zipName . '"'); + $response->headers->set('Content-length', filesize($zipName)); + + return $response; + } }