1
0
mirror of https://github.com/ToxicCrack/PrintABrick.git synced 2025-05-21 06:30:10 -07:00

Update controllers and views

This commit is contained in:
David Hübner 2017-05-28 19:35:28 +02:00
parent f08ed2d589
commit 124403a4b5
21 changed files with 183 additions and 230 deletions

View File

@ -4,8 +4,7 @@ $(document).ready(function(){
// ;
// $('.select2.dropdown').select2({
// placeholder: 'Select theme',
// allowClear: true
//
// });
$('.image.load img')

View File

@ -3,8 +3,8 @@
}
.masthead.segment {
min-height: 500px;
padding: 1em 0em;
min-height: 400px;
padding: 0.5em 0;
}
.masthead .logo.item img {
margin-right: 1em;
@ -14,7 +14,7 @@
}
.masthead h1.ui.header {
margin-top: 1.5em;
margin-bottom: 0em;
margin-bottom: 0;
font-size: 4em;
font-weight: normal;
}

View File

@ -1,8 +1,11 @@
.default-theme {
display: flex;
min-height: 100vh;
flex-direction: column;
.ui.main {
flex: 1;
padding-top: 50px;
min-height: calc(100% - 67px);
}
.ui.head {
@ -111,6 +114,10 @@
padding: 0.5em 1em !important;
}
.unpadded {
padding: 0;
}
.spacing.top {
margin-top: 1em;
}

View File

@ -365,7 +365,6 @@ u9140p02c01: u9140p01c01
u9142p02c03: u9142p01c08
u9151p02c03: u9151p01c04
u9106p02c02: u9106p01c03

View File

@ -427,3 +427,4 @@ x222: 13459
3068bor0323: 3068b
62363: 3815c01

View File

@ -29,6 +29,8 @@ set:
theme.all: All Themes
download:
unicolor.button: Download set (Uni-color)
multicolor.button: Download set (Multi-color)
button: Download set
title: Download - %set%
sorted:
@ -71,15 +73,20 @@ filter:
category: Category
homepage:
title.text: Web catalogue of LEGO<sup>®</sup> parts for 3D printing
models:
title: %count% models
text:
title: models
text: Browse 3D models of LEGO<sup>®</sup> parts from LDraw™ Library
browse: Browse models
sets:
title: %count% sets
text:
title: sets
text: Browse LEGO<sup>®</sup> sets from Rebrickable
browse: Browse sets
view.all:
sets: View all matched sets
models: View all matched models
flash:
warning.title: Warning
error.title: Error

View File

@ -53,7 +53,7 @@
<div class="ui black inverted vertical footer segment stripe">
{% block footer %}
<div class="ui aligned container">
<p>LEGO®, the LEGO logo, the Minifigure, and the Brick and Knob configurations are trademarks of the LEGO Group of Companies which does not sponsor, authorize, or endorse this site.</p>
<p>LEGO<sup>®</sup>, the LEGO logo, the Minifigure, and the Brick and Knob configurations are trademarks of the LEGO Group of Companies which does not sponsor, authorize, or endorse this site.</p>
</div>
{% endblock %}
</div>

View File

@ -1,8 +1,6 @@
{% extends 'base.html.twig' %}
{% block body %}
<!-- Page Contents -->
<div class="pusher">
<div class="ui inverted vertical masthead center aligned segment">
<div class="ui container">
@ -25,27 +23,46 @@
<h1 class="ui inverted header">
PrintABrick
</h1>
<h2>{{ 'page.home.title.text' | trans }}</h2>
<h2>{{ 'homepage.title.text' | trans | raw }}</h2>
</div>
</div>
<div class="ui vertical stripe quote segment">
<div class="ui main vertical stripe quote segment">
<div class="ui equal width stackable internally celled grid">
<div class="center aligned row">
<div class="column">
<h3>{{ 'homepage.models.title' | trans({'%count%' : models})}}</h3>
<p>{{ 'homepage.models.text' | trans }}</p>
<div class="ui horizontal statistic">
<div class="value">
{{ models }}
</div>
<div class="label">
{{ 'homepage.models.title' | trans }}
</div>
</div>
<p>{{ 'homepage.models.text' | trans | raw }}</p>
<a class="ui button big primary" href="{{ path('model_index') }}">{{ 'homepage.models.browse' | trans }}</a>
</div>
<div class="column">
<h3>{{ 'homepage.sets.title' | trans({'%count%' : sets}) }}</h3>
<p>{{ 'homepage.sets.text' | trans }}</p>
<div class="ui horizontal statistic">
<div class="value">
{{ sets }}
</div>
<div class="label">
{{ 'homepage.sets.title' | trans }}
</div>
</div>
<p>{{ 'homepage.sets.text' | trans | raw }}</p>
<a class="ui button big primary" href="{{ path('set_index') }}">{{ 'homepage.sets.browse' | trans }}</a>
</div>
</div>
</div>
</div>
<div class="ui black inverted vertical footer segment stripe">
<div class="ui aligned container">
<p>LEGO<sup>®</sup>, the LEGO logo, the Minifigure, and the Brick and Knob configurations are trademarks of the LEGO Group of Companies which does not sponsor, authorize, or endorse this site.</p>
</div>
</div>
{% endblock %}

View File

@ -9,7 +9,7 @@
{% endblock %}
<link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
</head>
<body class="default-theme">
<body class="default-theme body">
{% block body %}
{% endblock %}

View File

@ -79,6 +79,11 @@
</small>
</div>
</div>
{% if quantity %}
<div class="extra content">
<div class="right floated">{{ quantity }}x</div>
</div>
{% endif %}
</div>
</a>
{% endmacro %}

View File

@ -60,58 +60,43 @@
</table>
<a class="ui download fluid primary button" href="{{ path('model_zip', {id: model.id}) }}">{{ 'model.download'|trans }}</a>
</div>
</div>
</div>
<div class="ui segment vertical item-info">
<div class="ui tabular pointing secondary menu">
<a class="item active" data-tab="subparts"><i class="cubes icon"></i> Subparts ({{ model.subparts|length }})</a>
<a class="item" data-tab="related"><i class="cubes icon"></i> Related ({{ related|length }})</a>
<a class="item" data-tab="parents"><i class="cubes icon"></i> Parents ({{ model.parents|length }})</a>
{#<a class="item" data-tab="sets"><i class="cubes icon"></i> Sets ({{ sets|length }})</a>#}
</div>
<div class="ui vertical segment">
<div class="ui tab active" data-tab="subparts">
<div class="ui eight column grid parts">
<div class="ui segment vertical">
{% if subparts|length %}
<div class="ui segment vertical noborder">
<h4 class="ui horizontal divider header">Submodels ({{ model.subparts|length }})</h4>
<div class="ui grid doubling ten column row parts">
{% for subpart in subparts %}
{{ blocks.model(subpart['model'], subpart['quantity']) }}
{% endfor %}
</div>
</div>
{% endif %}
<div class="ui tab" data-tab="related">
<div class="ui eight column grid parts">
{% for subpart in related %}
<div class="column">
{{ blocks.model(subpart) }}
</div>
{% if related|length %}
<div class="ui segment vertical noborder">
<h4 class="ui horizontal divider header">Related models ({{ related|length }})</h4>
<div class="ui grid doubling ten column row parts">
{% for model in related %}
{{ blocks.model(model) }}
{% endfor %}
</div>
</div>
{% endif %}
<div class="ui tab" data-tab="parents">
<div class="ui eight column grid parts">
{% if model.parents|length %}
<div class="ui segment vertical noborder">
<h4 class="ui horizontal divider header">Parent models ({{ model.parents|length }})</h4>
<div class="ui grid doubling ten column row parts">
{% for subpart in model.parents %}
<div class="column">
{{ blocks.model(subpart.parent) }}
</div>
{% endfor %}
</div>
</div>
{#<div class="ui tab" data-tab="sets">#}
{#<div class="ui six column doubling grid">#}
{#<div class="row">#}
{#{% for set in sets %}#}
{#{{ blocks.set(set) }}#}
{#{% endfor %}#}
{#</div>#}
{#</div>#}
{#</div>#}
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -8,9 +8,9 @@
{% block content %}
<div class="ui vertical segment noborder">
<h2 class="ui dividing header">Sets</h2>
<h2 class="ui dividing header">Sets <small>({{ sets | length }})</small></h2>
<div class="ui eight column doubling grid sets">
{% for set in sets %}
{% for set in sets | slice(0,8) %}
{{ blocks.set(set) }}
{% endfor %}
</div>
@ -20,9 +20,9 @@
</div>
<div class="ui vertical segment noborder">
<h2 class="ui dividing header">Models</h2>
<h2 class="ui dividing header">Models <small>({{ models | length }})</small></h2>
<div class="ui eight column doubling grid parts">
{% for model in models %}
{% for model in models | slice(0,8) %}
{{ blocks.model(model) }}
{% endfor %}
</div>

View File

@ -44,7 +44,7 @@
<tr>
<td>{{ 'set.rating' | trans }}</td>
<td>
{{ brset.rating }}/5
{{ brset.rating | number_format(1, '.', ',') }} / 5
</td>
</tr>
{% endif %}
@ -58,42 +58,6 @@
</td>
</tr>
</table>
<div class="ui primary fluid open-modal button">{{ 'set.download.button' | trans }}</div>
{% embed 'embeds/modal.html.twig' %}
{% block title %}
{{ 'set.download.title' | trans({'%set%': set.id~' '~set.name}) }}
{% endblock %}
{% block content %}
{% if missingCount > 0 %}
<div class="ui warning icon message">
<i class="warning icon"></i>
<div class="content">
<div class="header">
{{ 'set.download.warning.title' | trans }}
</div>
<p> {{ 'set.download.warning.text' | trans({'%percent%':((1 - missingCount/partCount)*100)|number_format(2, '.', ','), '%total%':partCount, '%missing%': missingCount, '%unique%': uniqueMissing|length}) | raw | nl2br }}</p>
</div>
</div>
{% endif %}
{% endblock %}
{% block actions %}
<div class="ui two column divided center aligned grid">
<div class="column">
<h4 class="ui header">{{ 'set.download.sorted.title' | trans }}</h4>
<p>{{ 'set.download.sorted.text' | trans }}</p>
<a class="ui download button" href="{{ path('set_zip', {id: set.id, sorted: true }) }}" download>Download ZIP</a>
</div>
<div class="column">
<h4 class="ui header">{{ 'set.download.unsorted.title' | trans }}</h4>
<p>{{ 'set.download.unsorted.text' | trans }}</p>
<a class="ui download button" href="{{ path('set_zip', {id: set.id, sorted: false }) }}" download>Download ZIP</a>
</div>
</div>
{% endblock %}
{% endembed %}
</div>
</div>
</div>
@ -108,26 +72,10 @@
<a class="item" data-tab="reviews"><i class="write icon"></i> Reviews ({{ brset.reviewCount }})</a>
{% endif %}
</div>
<div class="ui vertical segment">
<div class="ui vertical segment unpadded">
<div class="ui tab active" data-tab="inventory">
{#<div class="ui vertical segment">#}
{#<p>{{ 'set.models.text' | trans({'%rebrickable%' : partCount, '%brickset%' : brset ? brset.pieces }) | nl2br }}</p>#}
{#</div>#}
<div class="ui vertical segment">
<div class="ui tabular icon buttons submenu">
<a class="ui item active button" data-tab="inventory/models"><i class="grid layout icon"></i> Uni-Color</a>
<a class="ui item button" data-tab="inventory/colors"><i class="list layout icon"></i> Multi-Color</a>
</div>
<div class="ui tab active" data-tab="inventory/models">
{{ render(path('set_models', {id: set.id})) }}
</div>
<div class="ui tab" data-tab="inventory/colors">
{{ render(path('set_colors', {id: set.id})) }}
</div>
{{ render(path('set_sets', {id: set.id})) }}
<div class="ui vertical segment unpadded">
{{ render(path('set_inventory', {id: set.id})) }}
</div>
</div>
{% if brset %}

View File

@ -8,6 +8,10 @@
{% endfor %}
{% endfor %}
<div class="ui segment clearing noborder vertical">
<a class="ui primary right floated button" href="{{ path('set_zip', {id: set.id, sorted: true }) }}" download>{{ 'set.download.multicolor.button' | trans}}</a>
</div>
{% if colors|length > 0 %}
<div class="ui segment vertical noborder">
<h3 class="ui horizontal divider header">Models</h3>

View File

@ -8,38 +8,36 @@
{% endfor %}
{% endfor %}
{% if regularParts|length > 0 %}
<h4 class="ui horizontal divider header">
Regular parts
</h4>
<div class="ui ten column grid">
{% for inventoryPart in regularParts %}
{{ blocks.part(inventoryPart.part.id,inventoryPart.quantity, inventoryPart.color.id) }}
{{ inventoryPart.color.id }}
{% if inventorySets %}
<h3 class="ui horizontal divider header">Sets</h3>
<div class="ui eight column doubling grid sets">
{% for inventorySet in inventorySets %}
{{ blocks.set(inventorySet.set, inventorySet.quantity) }}
{% endfor %}
</div>
{% else %}
{% if missingCount > 0 %}
<div class="ui warning icon message">
<i class="warning icon"></i>
<div class="content">
<div class="header">
{{ 'set.download.warning.title' | trans }}
</div>
<p> {{ 'set.download.warning.text' | trans({'%percent%':((1 - missingCount/partCount)*100)|number_format(2, '.', ','), '%total%':partCount, '%missing%': missingCount, '%unique%': missing|length}) | raw | nl2br }}</p>
</div>
</div>
{% endif %}
{% if missing|length > 0 %}
<h4 class="ui horizontal divider header">
Missing models
</h4>
<div class="ui ten column grid">
{% for inventoryPart in missing %}
{{ blocks.part(inventoryPart.part.id,inventoryPart.quantity, inventoryPart.color.id) }}
{% endfor %}
<div class="ui tabular icon pointing secondary menu submenu">
<a class="ui item active button" data-tab="inventory/models"><i class="grid layout icon"></i> Uni-Color</a>
<a class="ui item button" data-tab="inventory/colors"><i class="list layout icon"></i> Multi-Color</a>
</div>
{% endif %}
{% if spareParts|length > 0 %}
<h4 class="ui horizontal divider header">
Spare parts
</h4>
<div class="ui ten column grid">
{% for inventoryPart in spareParts %}
{{ blocks.part(inventoryPart.part.id,inventoryPart.quantity, inventoryPart.color.id) }}
{% endfor %}
<div class="ui tab active" data-tab="inventory/models">
{{ render(path('set_models', {id: set.id})) }}
</div>
<div class="ui tab" data-tab="inventory/colors">
{{ render(path('set_colors', {id: set.id})) }}
</div>
{% endif %}
{% endblock %}

View File

@ -8,6 +8,10 @@
{% endfor %}
{% endfor %}
<div class="ui segment clearing noborder vertical">
<a class="ui primary right floated button" href="{{ path('set_zip', {id: set.id, sorted: false }) }}" download>{{ 'set.download.unicolor.button' | trans}}</a>
</div>
{% if models|length > 0 %}
<div class="ui segment vertical noborder">
<h3 class="ui horizontal divider header">Models</h3>

View File

@ -1,21 +0,0 @@
{% import 'macros/blocks.html.twig' as blocks %}
{% import 'macros/elements.html.twig' as elements %}
{% block content %}
{% for label, flashes in app.session.flashbag.all %}
{% for flash in flashes %}
{{ elements.flash(label,flash) }}
{% endfor %}
{% endfor %}
{% if inventorySets %}
<h2 class="ui horizontal divider header">Sets</h2>
<div class="ui six column grid">
<div class="row">
{% for inventorySet in inventorySets %}
{{ blocks.set(inventorySet.set, inventorySet.quantity) }}
{% endfor %}
</div>
</div>
{% endif %}
{% endblock %}

View File

@ -93,10 +93,13 @@ class ModelController extends Controller
$response = new BinaryFileResponse($zip);
$response->headers->set('Content-Type', 'application/zip');
// escape forbidden characters from filename
$filename = preg_replace('/[^a-z0-9\.]/i', '_',"model_{$model->getId()}_{$model->getName()}.zip");
// Create the disposition of the file
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
"model_{$model->getId()}_{$model->getName()}.zip"
$filename
);
$response->headers->set('Content-Disposition', $disposition);

View File

@ -4,6 +4,8 @@ namespace AppBundle\Controller;
use AppBundle\Entity\LDraw\Model;
use AppBundle\Entity\Rebrickable\Set;
use AppBundle\Model\ModelSearch;
use AppBundle\Model\SetSearch;
use AppBundle\Repository\Search\ModelRepository;
use AppBundle\Repository\Search\SetRepository;
use FOS\ElasticaBundle\HybridResult;
@ -34,12 +36,11 @@ class SearchController extends Controller
/** @var SetRepository $setRepository */
$setRepository = $repositoryManager->getRepository(Set::class);
/** @var Repository $modelRepository */
/** @var ModelRepository $modelRepository */
$modelRepository = $repositoryManager->getRepository(Model::class);
// Option 1. Returns all users who have example.net in any of their mapped fields
$setsResult = $setRepository->find($query, 8);
$modelResult = $modelRepository->find($query, 8);
$setsResult = $setRepository->search(new SetSearch($query), 1000);
$modelResult = $modelRepository->search(new ModelSearch($query), 1000);
return $this->render('search/index.html.twig', [
'sets' => $setsResult,
@ -67,8 +68,8 @@ class SearchController extends Controller
$modelRepository = $repositoryManager->getRepository(Model::class);
// Option 1. Returns all users who have example.net in any of their mapped fields
$setsResult = $setRepository->findHighlighted($query, 5);
$modelResult = $modelRepository->findHighlighted($query, 5);
$setsResult = $setRepository->findHighlighted($query, 4);
$modelResult = $modelRepository->findHighlighted($query, 4);
$models = [];
/** @var HybridResult $model */

View File

@ -61,8 +61,6 @@ class SetController extends Controller
$bricksetSet = null;
$partCount = $inventoryPartRepository->getPartCount($set, false);
$missingCount = $inventoryPartRepository->getPartCount($set, false, false);
$uniqueMissing = $setService->getParts($set, false, false);
try {
if (!($bricksetSet = $this->get('api.manager.brickset')->getSetByNumber($set->getId()))) {
@ -78,27 +76,33 @@ class SetController extends Controller
'set' => $set,
'brset' => $bricksetSet,
'partCount' => $partCount,
'missingCount' => $missingCount,
'uniqueMissing' => $uniqueMissing,
]);
}
/**
* @Route("/{id}/parts", name="set_parts")
* @Route("/{id}/inventory", name="set_inventory")
*/
public function partsAction(Request $request, Set $set)
public function inventoryAction(Request $request, Set $set)
{
$inventoryPartRepository = $this->get('repository.rebrickable.inventorypart');
$em = $this->getDoctrine()->getManager();
$regularParts = $inventoryPartRepository->findAllBySetNumber($set->getId(), false, true);
$spareParts = $inventoryPartRepository->findAllBySetNumber($set->getId(), true);
$inventorySets = $em->getRepository(Inventory_Set::class)->findAllBySetNumber($set->getId());
$setService = $this->get('service.set');
$inventoryPartRepository = $this->get('repository.rebrickable.inventoryPart');
$missing = $inventoryPartRepository->findAllBySetNumber($set->getId(), false, false);
$models = $setService->getModels($set, false);
$missing = $setService->getParts($set, false, false);
$missingCount = $inventoryPartRepository->getPartCount($set, false, false);
$partCount = $inventoryPartRepository->getPartCount($set, false);
$template = $this->render('set/tabs/inventory.html.twig', [
'regularParts' => $regularParts,
'inventorySets' => $inventorySets,
'set' => $set,
'missing' => $missing,
'spareParts' => $spareParts,
'models' => $models,
'missingCount' => $missingCount,
'partCount' => $partCount,
]);
if ($request->isXmlHttpRequest()) {
@ -117,16 +121,14 @@ class SetController extends Controller
*/
public function modelsAction(Request $request, Set $set)
{
$setService = $this->get('service.set');
$models = null;
$spareModels = null;
$missing = null;
$missingSpare = null;
try {
$models = $this->get('service.set')->getModels($set, false);
$spareModels = $this->get('service.set')->getModels($set, true);
$missing = $this->get('service.set')->getParts($set, false, false);
$missingSpare = $this->get('repository.rebrickable.inventorypart')->findAllBySetNumber($set->getId(), true, false);
$models = $setService->getModels($set, false);
$missing = $setService->getParts($set, false, false);
} catch (\Exception $e) {
$this->addFlash('error', $e->getMessage());
}
@ -135,8 +137,6 @@ class SetController extends Controller
'set' => $set,
'missing' => $missing,
'models' => $models,
'spareModels' => $spareModels,
'missingSpare' => $missingSpare,
]);
if ($request->isXmlHttpRequest()) {
@ -155,14 +155,15 @@ class SetController extends Controller
*/
public function colorsAction(Request $request, Set $set)
{
$colors = null;
try {
/** @var SetService $setService */
$setService = $this->get('service.set');
$colors = null;
$missing = null;
try {
$colors = $setService->getModelsGroupedByColor($set, false);
$missing = $setService->getParts($set,false,false);
} catch (\Exception $e) {
$this->addFlash('error', $e->getMessage());
}
@ -184,30 +185,6 @@ class SetController extends Controller
return $template;
}
/**
* @Route("/{id}/sets", name="set_sets")
*/
public function setsAction(Request $request, Set $set)
{
$em = $this->getDoctrine()->getManager();
$inventorySets = $em->getRepository(Inventory_Set::class)->findAllBySetNumber($set->getId());
$template = $this->render('set/tabs/sets.html.twig', [
'inventorySets' => $inventorySets,
]);
if ($request->isXmlHttpRequest()) {
$json = json_encode($template->getContent());
$response = new Response($json, 200);
$response->headers->set('Content-Type', 'application/json');
return $response;
}
return $template;
}
/**
* @Route("/{id}/zip", name="set_zip")
*/
@ -222,10 +199,13 @@ class SetController extends Controller
$response = new BinaryFileResponse($zip);
$response->headers->set('Content-Type', 'application/zip');
// escape forbidden characters from filename
$filename = preg_replace('/[^a-z0-9\.]/i', '_', "set_{$set->getId()}_{$set->getName()}({$sort}).zip");
// Create the disposition of the file
$disposition = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
"set_{$set->getId()}_{$set->getName()}({$sort}).zip"
$filename
);
$response->headers->set('Content-Disposition', $disposition);

View File

@ -0,0 +1,16 @@
<?php
namespace AppBundle\Exception;
use Symfony\Component\Form\Exception\LogicException;
use Throwable;
class MissingContextException extends LogicException
{
public function __construct($context, $message = '', $code = 0, Throwable $previous = null)
{
$message = sprintf('"%s" context not found.', $context);
parent::__construct($message, $code, $previous);
}
}