Added a basic show part info with new design. Not finished yet...

This commit is contained in:
Jan Böhmer 2019-02-24 18:05:06 +01:00
parent f8bd1458d3
commit f0bea8ff4d
22 changed files with 7883 additions and 25 deletions

8
.gitignore vendored
View file

@ -18,4 +18,10 @@
###< symfony/web-server-bundle ###
.idea/
.idea/
###> symfony/webpack-encore-bundle ###
/node_modules/
/public/build/
npm-debug.log
yarn-error.log
###< symfony/webpack-encore-bundle ###

1
.idea/php.xml generated
View file

@ -112,6 +112,7 @@
<path value="$PROJECT_DIR$/vendor/ocramius/package-versions" />
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
<path value="$PROJECT_DIR$/vendor/ocramius/proxy-manager" />
<path value="$PROJECT_DIR$/vendor/symfony/webpack-encore-bundle" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="7.1" />

623
assets/css/app.css Normal file
View file

@ -0,0 +1,623 @@
/*
*
* Part-DB Version 0.4+ "nextgen"
* Copyright (C) 2016 - 2018 Jan Böhmer
* https://github.com/jbtronics
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
/************************************
* Basic layout (Navbar, sidebar, etc.)
*************************************/
/* Add padding for fixed header bar */
body {
overflow-x: hidden;
position: relative;
padding-top: 70px;
/* Use font size like in BS3 */
font-size: 14px;
line-height: 1.428;
}
@media (min-width: 768px) {
.fixed-sidebar {
/*
position: fixed;
left: 15px;
z-index: 1000;
/* display: flex;
width: inherit; '/
overflow-x: hidden;
overflow-y: auto;
/*noinspection W3CssValidation*/
/* -webkit-overflow-scrolling: touch;
max-height: 100%;
padding-bottom: 50px; */
position: fixed;
top: 60px;
bottom: 0;
left: 0;
z-index: 1000;
/* padding: 20px; */
padding-left: 15px;
/* padding-top: 15px; */
padding-right: 0;
overflow-x: hidden;
overflow-y: auto;
/*noinspection W3CssValidation*/
-webkit-overflow-scrolling: touch;
/** Hide scrollbar in old Firefox and Edge **/
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
}
/*noinspection W3CssValidation*/
@media (max-width: 768px) {
.fixed-sidebar {
position: fixed;
top: 56px;
right: 0;
left: 0;
background-color: inherit;
z-index: 1000;
width: inherit;
overflow-x: hidden;
overflow-y: auto;
/*noinspection W3CssValidation*/
-webkit-overflow-scrolling: touch;
max-height: 100%;
opacity: 0.97;
padding: 7px 15px 50px;
margin-top: -10px;
/** Hide scrollbar in Firefox and Edge **/
-ms-overflow-style: none;
overflow: -moz-scrollbars-none;
}
.sidebar-container {
margin-top: 0;
padding-top: 5px;
background-color: #F8F8F8;
}
}
/* Hide scrollbar */
.fixed-sidebar::-webkit-scrollbar {display:none;}
@media (min-width: 768px) {
.sidebar-collapse.collapse {
display: block !important;
height: auto !important;
padding-bottom: 0;
overflow: visible !important;
}
}
/* Back to top button */
.back-to-top {
cursor: pointer;
position: fixed;
bottom: 20px;
right: 20px;
display:none;
z-index: 1030;
}
.sidebar-title {
margin-top: 0;
font-size: 18px;
margin-bottom: 10px;
line-height: 1.1;
}
/**********************************
* Helper classes
*********************************/
.vertical-align {
display: flex;
align-items: center;
}
.vertical-align-table>tbody>tr>td,
.vertical-align-table>tbody>tr>th,
.vertical-align-table>tfoot>tr>td,
.vertical-align-table>tfoot>tr>th,
.vertical-align-table>thead>tr>td,
.vertical-align-table>thead>tr>th {
vertical-align: middle;
}
.table-center{
text-align: center;
}
.font-weight-bold {
font-weight:bold;
}
.table-no-margin {
margin-top: 0;
margin-bottom: 0;
}
/**
Use this class if you has a <span> or <p> and you want to create automatic textbreaks in the text.
*/
.text-break {
/*noinspection W3CssValidation,CssUnknownProperty*/
-ms-word-break: break-all;
/*noinspection CssOverwrittenProperties*/
word-break: break-all;
/* Non standard for webkit */
/*noinspection W3CssValidation,CssInvalidPropertyValue,CssOverwrittenProperties*/
word-break: break-word;
/*noinspection W3CssValidation*/
-webkit-hyphens: auto;
/*noinspection W3CssValidation*/
-moz-hyphens: auto;
hyphens: auto;
}
.auto-size-select {
height: inherit;
}
/****************************************
* Bootstrap extensions
*****************************************/
.form-group-sm {
margin-bottom: 5px;
}
/* Use this if you want to use a link inside a form-group */
.form-control-link {
display: block;
padding-top: 7px;
padding-bottom: 7px;
}
/* A text-only button without border */
.btn-text {
color: inherit;
padding: 0;
border: hidden;
background-color: transparent;
}
/* Size sensitive pull-* helpers */
@media (max-width: 767px) {
.pull-right-not-xs, .pull-left-not-xs{
float: none;
}
.pull-right-xs {
float: right;
}
.pull-left-xs {
float: left;
}
}
@media (min-width: 768px) and (max-width: 991px) {
.pull-right-not-sm, .pull-left-not-sm{
float: none;
}
.pull-right-sm {
float: right;
}
.pull-left-sm {
float: left;
}
}
@media (min-width: 992px) and (max-width: 1199px) {
.pull-right-not-md, .pull-left-not-md{
float: none;
}
.pull-right-md {
float: right;
}
.pull-left-md {
float: left;
}
}
@media (min-width: 1200px) {
.pull-right-not-lg, .pull-left-not-lg{
float: none;
}
.pull-right-lg {
float: right;
}
.pull-left-lg {
float: left;
}
}
/**************************************
btn-xs
btn-xs
*/
.btn-xs {
/*padding: .1rem .3rem; */
padding: 1px 5px;
font-size: 12px;
line-height: 1.5
}
.not-enough-instock {
background-color: rgba(220, 53, 69, 0.4);
}
/****************************************
* Picture classes
*****************************************/
.companypic {
width: 17px;
display: inline;
}
.companypic:hover {
filter: opacity(60%);
}
.companypic-bg {
width: 20px;
display: inline;
}
.companypic-bg:hover {
filter: opacity(60%);
}
.hoverpic {
min-width: 10px;
max-width: 30px;
display: block;
margin-left: auto;
margin-right: auto;
}
.thumbnail-sm {
height: 100px;
}
img.img-attachement {
max-width: 25%;
margin: 10px;
}
/****************************************
* Tables
****************************************/
.table-compact>tbody>tr>td,
.table-compact>tbody>tr>th,
.table-compact>tfoot>tr>td,
.table-compact>tfoot>tr>th,
.table-compact>thead>tr>td,
.table-compact>thead>tr>th,
table.dataTable>tbody>tr>th,
table.dataTable>tbody>tr>td
{
padding: 3px;
}
/* We need to override the z index, or the elements will overlap the fixed header from datatables. */
table .input-group .form-control {
z-index: 0;
}
table .input-group-btn:last-child>.btn, table .input-group-btn:last-child>.btn-group {
z-index: 0;
}
/* Hide datatables fixedHeaders on small devices */
@media only screen and (max-width: 1000px){
.fixedHeader-floating {
display: none;
}
}
/***************************************
* Dropdown with radio buttons
***************************************/
.container-progress {
padding-top: 25%;
}
.dropdown-menu-radio {
padding-left: 10px;
}
.drop-radio {
margin-left: 10px;
}
/*************************************
* Smaller radio buttons
**************************************/
.radio-small {
margin-bottom: 0;
margin-top: 0;
}
/************************************
X3DOM
*************************************/
.x3d-fullscreen {
/*height: auto;*/
width: 100%;
}
/*******************************
* Collapsable panel definitions.
********************************/
.fancy-collapse-panel .panel-default > .panel-heading {
padding: 0;
}
.card-header a[data-toggle=collapse] {
display: inline-block;
width: 100%;
position: relative;
}
/*
@font-face {
font-family: 'FA5';
font-style: normal;
font-weight: 900;
src: url("../../webfonts/fa-solid-900.eot");
src: url("../../webfonts/fa-solid-900.eot?#iefix") format("embedded-opentype"), url("../../webfonts/fa-solid-900.woff2") format("woff2"), url("../../webfonts/fa-solid-900.woff") format("woff"), url("../../webfonts/fa-solid-900.ttf") format("truetype"), url("../../webfonts/fa-solid-900.svg#fontawesome") format("svg");
} */
.card-header a[data-toggle=collapse]:after {
/*noinspection CssNoGenericFontName*/
font-family: "FA5";
content: "\f106";
position: absolute;
right: 20px;
font-size: 20px;
font-weight: 400;
top: 50%;
line-height: 1;
margin-top: -10px;
}
.card-header a[data-toggle=collapse].collapsed:after
{
content: "\f107";
}
.card-header {
overflow: hidden;
}
a.link-collapse {
color: #333;
}
/******************************************************
Classes for Datatables export
*******************************************************/
#export-title,
#export-messageTop,
.export-helper{
display: none;
}
/**************************************************
* Link styles
***************************************************/
/* Show symbol after exteral links */
/*noinspection CssNoGenericFontName*/
a[target="_blank"].link-external:after {
content: "\f35d ";
font-family: "FA5";
margin-left: 3px;
font-weight: normal;
font-size: smaller;
font-style: normal;
display: inline-block;
text-decoration: inherit;
}
a.text-white {
color: #fff;
}
/****************************************************
* Search highlighting
*****************************************************/
span.highlight {
background-color: yellow;
}
/******************************
* Bootstrap treeview overrides
*******************************/
/* Set display style to flexbox, so wraped text is aligned to */
.list-group-item {
padding: 5px 10px;
display: flex;
}
.treeview {
font-size: 12px;
}
.fa-treeview {
line-height: 1.428;
}
/*****************************
* Pagination bar
*****************************/
/** Select in pagination */
.pagination>li>select
{
position: relative;
float: left;
padding: 7px 5px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
}
.pagination>li>button
{
position: relative;
float: left;
padding: 6px 5px;
margin-left: -1px;
line-height: 1.42857143;
color: #337ab7;
text-decoration: none;
background-color: #fff;
border: 1px solid #ddd;
}
/******************************
* Breadcrumb like structural links
********************************/
/* Style the list */
ul.structural_link {
padding-top: 7px;
padding-bottom: 7px;
padding-left: 0;
list-style: none;
background-color: inherit;
}
/* Display list items side by side */
ul.structural_link li {
display: inline;
font-size: inherit;
}
/* Add a slash symbol (/) before/behind each list item */
ul.structural_link li+li:before {
padding: 2px;
color: grey;
/*content: "/\00a0";*/
font-family: "FA5", sans-serif;
font-style: normal;
font-weight: normal;
content: "\f30b"; /* long-arrow-alt-right */
}
/* Add a color to all links inside the list */
ul.structural_link li a {
color: #0275d8;
text-decoration: none;
}
/* Add a color on mouse-over */
ul.structural_link li a:hover {
color: #01447e;
text-decoration: underline;
}
/*****************************
* Print styles
*****************************/
@media print {
body {
padding-top: 0;
}
a.hidden-print-href[href]:after {
content: none !important;
}
}
/*****************************
BS 4 overrides
****************************/
@media (min-width: 768px) {
.col-form-label {
font-weight: bold;
text-align: right;
}
}
label:not(.form-check-label) {
font-weight: bold;
}
.form-group {
margin-bottom: 0.4rem;
}
.dropdown-item,
.dropdown-header,
.dropdown-divider {
padding: .1rem 1.5rem;
}
/* Font Awesome 5 with Checkbox support */
.abc-checkbox input[type="checkbox"]:checked+label::after,
.abc-checkbox input[type="radio"]:checked+label::after {
/*noinspection CssNoGenericFontName*/
font-family: "FA5", "Font Awesome 5 Pro", "Font Awesome 5 Free";
content: "\f00c";
font-weight: 900;
}
.form-check-dropdown {
display: flex;
width: auto;
padding-left: 10%;
}
.btn-group-append {
border-top-left-radius: 0;
border-bottom-left-radius: 0
}
.tooltip {
pointer-events: none;
}

19
assets/js/app.js Normal file
View file

@ -0,0 +1,19 @@
/*
* Welcome to your app's main JavaScript file!
*
* We recommend including the built version of this JavaScript file
* (and its CSS file) in your base layout (base.html.twig).
*/
// any CSS you require will output into a single css file (app.css in this case)
require('../css/app.css');
// Need jQuery? Install it with "yarn add jquery", then uncomment to require it.
const $ = require('jquery');
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import '@fortawesome/fontawesome-free/css/all.css'
//console.log('Hello Webpack Encore! Edit me in assets/js/app.js');

View file

@ -23,6 +23,7 @@
"symfony/twig-bundle": "4.2.*",
"symfony/validator": "4.2.*",
"symfony/web-link": "4.2.*",
"symfony/webpack-encore-bundle": "^1.1",
"symfony/yaml": "4.2.*"
},
"require-dev": {

56
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "cee4085fe3fa88057621162b3c43239f",
"content-hash": "54e0b48ecf19934241734a4229c9b47f",
"packages": [
{
"name": "doctrine/annotations",
@ -5032,6 +5032,60 @@
],
"time": "2019-01-16T20:31:39+00:00"
},
{
"name": "symfony/webpack-encore-bundle",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/webpack-encore-bundle.git",
"reference": "9c89795a4577c522101206a1a88272660735257c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/webpack-encore-bundle/zipball/9c89795a4577c522101206a1a88272660735257c",
"reference": "9c89795a4577c522101206a1a88272660735257c",
"shasum": ""
},
"require": {
"php": "^7.1.3",
"symfony/asset": "^3.4 || ^4.0",
"symfony/config": "^3.4 || ^4.0",
"symfony/contracts": "^1.0",
"symfony/dependency-injection": "^3.4 || ^4.0",
"symfony/http-kernel": "^3.4 || ^4.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.14",
"symfony/framework-bundle": "^3.4 || ^4.0",
"symfony/phpunit-bridge": "^3.4 || ^4.1",
"symfony/twig-bundle": "^3.4 || ^4.0",
"twig/twig": "^1.35 || ^2.0"
},
"type": "symfony-bundle",
"extra": {
"thanks": {
"name": "symfony/webpack-encore",
"url": "https://github.com/symfony/webpack-encore"
}
},
"autoload": {
"psr-4": {
"Symfony\\WebpackEncoreBundle\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Integration with your Symfony app & Webpack Encore!",
"time": "2019-01-17T02:29:30+00:00"
},
{
"name": "symfony/yaml",
"version": "v4.2.3",

View file

@ -14,4 +14,5 @@ return [
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
];

View file

@ -0,0 +1,3 @@
framework:
assets:
json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'

View file

@ -0,0 +1,4 @@
webpack_encore:
# The path where Encore is building the assets.
# This should match Encore.setOutputPath() in webpack.config.js.
output_path: '%kernel.project_dir%/public/build'

18
package.json Normal file
View file

@ -0,0 +1,18 @@
{
"devDependencies": {
"@fortawesome/fontawesome-free": "^5.7.2",
"@symfony/webpack-encore": "^0.22.0",
"bootstrap": "^4.3.1",
"jquery": "^3.3.1",
"popper.js": "^1.14.7",
"webpack-notifier": "^1.6.0"
},
"license": "UNLICENSED",
"private": true,
"scripts": {
"dev-server": "encore dev-server",
"dev": "encore dev",
"watch": "encore dev --watch",
"build": "encore production --progress"
}
}

View file

@ -0,0 +1,39 @@
<?php
/**
* Created by PhpStorm.
* User: janhb
* Date: 24.02.2019
* Time: 13:00
*/
namespace App\Controller;
use App\Entity\Part;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
class PartController extends AbstractController
{
/**
* @Route("/part/{id}/info")
* @Route("/part/{id}")
*/
function show(int $id)
{
$repo = $this->getDoctrine()->getRepository(Part::class);
/** @var Part $part */
$part = $repo->find($id);
dump($part);
return $this->render('show_part_info.html.twig',
[
"part" => $part
]
);
}
}

View file

@ -69,14 +69,11 @@ abstract class NamedDBElement extends DBElement
/**
* Returns the last time when the element was modified.
* @param $formatted bool When true, the date gets formatted with the locale and timezone settings.
* When false, the raw value from the DB is returned.
* @return string The time of the last edit.
*/
public function getLastModified(bool $formatted = true) : string
public function getLastModified() : \DateTime
{
//TODO
return "TODO";
return $this->lastModified;
}
/**
@ -85,10 +82,10 @@ abstract class NamedDBElement extends DBElement
* When false, the raw value from the DB is returned.
* @return string The creation time of the part.
*/
public function getDatetimeAdded(bool $formatted = true) : string
public function getDatetimeAdded() : \DateTime
{
//TODO
return "TODO";
return $this->addedDate;
}
/********************************************************************************

View file

@ -15,7 +15,7 @@ use Doctrine\ORM\Mapping as ORM;
* Class Orderdetail
* @package App\Entity
*
* @ORM\Table("oderdetails")
* @ORM\Table("orderdetails")
* @ORM\Entity()
*/
class Orderdetail extends DBElement

View file

@ -219,7 +219,7 @@ class Part extends AttachmentContainingDBElement
* @param boolean|int $bbcode_parsing_level Should BBCode converted to HTML, before returning
* @return string the comment
*/
public function getComment($bbcode_parsing_level = BBCodeParsingLevel::PARSE) : string
public function getComment($bbcode_parsing_level = true /*= BBCodeParsingLevel::PARSE*/) : string
{
$val = htmlspecialchars($this->comment);

View file

@ -187,13 +187,13 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
if (! \is_array($this->full_path_strings)) {
$this->full_path_strings = array();
$this->full_path_strings[] = $this->getName();
$parent_id = $this->getParentID();
while ($parent_id > 0) {
/** @var StructuralDBElement $element */
$element = static::getInstance($this->database, $this->current_user, $this->log, $parent_id);
$parent_id = $element->getParentID();
$element = $this;
while ($element->parent != null) {
$element = $element->parent;
$this->full_path_strings[] = $element->getName();
}
$this->full_path_strings = array_reverse($this->full_path_strings);
}

View file

@ -480,6 +480,23 @@
"ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
}
},
"symfony/webpack-encore-bundle": {
"version": "1.0",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "master",
"version": "1.0",
"ref": "5880e1fef9f9eb6a523e698a63f8feabcc8b0834"
},
"files": [
"./assets/css/app.css",
"./assets/js/app.js",
"./config/packages/assets.yaml",
"./config/packages/webpack_encore.yaml",
"./package.json",
"./webpack.config.js"
]
},
"symfony/yaml": {
"version": "v4.2.3"
},

View file

@ -1,12 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Welcome!{% endblock %}</title>
{% block stylesheets %}{% endblock %}
</head>
<body>
{% block body %}{% endblock %}
{% block javascripts %}{% endblock %}
</body>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block title %}Part-DB{% endblock %}</title>
{% block stylesheets %}
{{ encore_entry_link_tags('app') }}
{% endblock %}
</head>
<body>
{% block body %}
<div class="container-fluid">
{% block content %}
{% endblock %}
</div>
{% endblock %}
{% block javascripts %}
{{ encore_entry_script_tags('app') }}
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,15 @@
{% if list != null %}
<ul class="structural_link">
{% for element in list %}
<li {% if element.selected != null %}class="active"{% endif %}>
{% if element.href %}
<a href="{{ element.href }}">{if $element.label}{$element.label}{/if}</a>
{% else %}
{$element.label}
{% endif %}
</li>
{% endfor %}
</ul>
{% else %}
<div class="form-control-static">-</div>
{% endif %}

View file

@ -0,0 +1,298 @@
{% extends "base.html.twig" %}
{% block title %}
{% trans %}Detail info for{% endtrans %} {{ part.name }}
{% endblock %}
{% block content %}
<div class="card border-primary">
<div class="card-header bg-primary text-white">
<i class="fa {{ part.favorite ? 'fa-star' : 'fa-info-circle'}} fa-fw" aria-hidden="true"></i>
{% trans %}Detail info for{% endtrans %} <b>"{{ part.name }}"</b>
<div class="float-right">
{% trans %}ID:{% endtrans %} {{ part.id }}
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-9">
<div class="row">
<div class="col-md-3">
<img src="https://via.placeholder.com/300" class="img-fluid img-thumbnail" height="300" width="300">
</div>
<div class="col-md-9">
<h5 class="text-muted pt-2" title="{% trans %}Manufacturer{% endtrans %}">{{ part.manufacturer.name ?? ""}}</h5>
<h3>{{ part.name }}</h3>
<h6 class="text-muted"><span title="{% trans %}Description{% endtrans %}">{{ part.description }}</span></h6>
<h6 class="" title="{% trans %}Store location{% endtrans %}">
<i class="fas fa-cube fa-fw"></i>
<span class="text-muted">{{ part.storelocation.fullPath ?? "-"}}</span>
</h6>
<h6><i class="fas fa-shapes fa-fw"></i>
<span class="text-muted">
<span title="{% trans %}Instock{% endtrans %}">{{ part.instock }}</span>
/
<span title="{% trans %}Minimum Instock{% endtrans %}">{{ part.mininstock }}</span>
</span>
</h6>
<h6 class="" title="{% trans %}Footprint{% endtrans %}">
<i class="fas fa-microchip fa-fw" ></i>
<span class="text-muted">{{ part.footprint.fullPath ?? "-"}}</span>
</h6>
<h6 title="{% trans %}Average price{% endtrans %}">
<i class="fas fa-money-bill-alt fa-fw"></i>
<span class="text-muted">{{ part.averagePrice }}</span>
</h6>
<h6 title="{% trans %}Comment{% endtrans %}">
<i class="fas fa-comment-alt fa-fw"></i>
<span class="text-muted">{{ part.comment }}</span>
</h6>
</div>
</div>
<div class="mt-3">
<ul class="nav nav-tabs" id="partTab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="attachment-tab" data-toggle="tab"
href="#attachments" role="tab" aria-controls="home" aria-selected="true">
<i class="fas fa-paperclip fa-fw"></i>
{% trans %}Attachments{% endtrans %}
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="supplier-tab" data-toggle="tab" href="#suppliers" role="tab" aria-controls="profile" aria-selected="false">
<i class="fas fa-shopping-cart fa-fw"></i>
{% trans %}Shopping Informations{% endtrans %}
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="history-tab" data-toggle="tab" href="#history" role="tab" aria-controls="contact" aria-selected="false">
<i class="fas fa-history"></i>
{% trans %}History{% endtrans %}
</a>
</li>
<li class="nav-item">
<a class="nav-link" id="tools-tab" data-toggle="tab" href="#tools" role="tab" aria-controls="contact" aria-selected="false">
<i class="fas fa-tools"></i>
{% trans %}Tools{% endtrans %}
</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div class="tab-pane fade show active" id="attachments" role="tabpanel" aria-labelledby="home-tab">
</div>
<div class="tab-pane fade" id="suppliers" role="tabpanel" aria-labelledby="profile-tab">
</div>
<div class="tab-pane fade" id="history" role="tabpanel" aria-labelledby="profile-tab">
TODO
</div>
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="contact-tab">
<form class="mt-3">
<div class="form-group">
<label>{% trans %}Delete part:{% endtrans %}</label>
<button class="btn btn-danger">{% trans %}Delete part{% endtrans %}</button>
</div>
</form>
</div>
</div>
</div>
</div>
<div class="col-md-3">
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
<label for="n_less">{% trans %}Withdraw parts:{% endtrans %}</label>
<div class="input-group">
<input type="number" class="form-control" name="n_less" min="0" max="999999" value="1" placeholder="Anzahl">
<div class="input-group-append">
<div class="btn-group">
<button type="submit" class="btn btn-outline-secondary btn-group-append" name="dec"> {% trans %}Withdraw{% endtrans %}</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<div class="px-4 py-3">
<div class="form-group">
<label>{% trans %}Comment/Purpose:{% endtrans %}</label>
<input type="text" class="form-control" name="instock_change_comment" placeholder="{{ "TODO" }}">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<p></p>
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
<label for="n_more">{% trans %}Add parts:{% endtrans %}</label>
<div class="input-group">
<input type="number" class="form-control" name="n_more" min="0" max="999999" value="1">
<div class="input-group-append">
<div class="btn-group">
<button type="submit" class="btn btn-outline-secondary btn-group-append" name="inc" >{% trans %}Add{% endtrans %}</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<div class="px-4 py-3">
<div class="form-group">
<label>{% trans %}Comment/Purpose:{% endtrans %}</label>
<input type="text" class="form-control" name="instock_change_comment" placeholder="TODO">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<p></p>
{#
{if $can_order_read && !$instock_unknown}
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
{if $manual_order_exists}
<label for="remove_mark_to_order">{% trans %}Bauteil wurde manuell zum Bestellen vorgemerkt.{% endtrans %}</label>
<button type="submit" class="btn btn-outline-secondary"
name="remove_mark_to_order" >
{% trans %}Aufheben{% endtrans %}</button>
{else}
{if $auto_order_exists}
<i>{% trans %}Das Bauteil wird unter "Zu bestellende Teile"aufgelistet, da der Bestand kleiner als der Mindestbestand ist.{% endtrans %}</i>
{else}
<label for="order_quantity">{% trans %}Zum Bestellen vormerken:{% endtrans %}</label>
<div class="input-group">
<input type="number" min="0" max="999999" class="form-control" value="1" name="order_quantity"
placeholder="Bestellmenge" {if !$can_order_edit}disabled{/if}><br>
<span class="input-group-append">
<button type="submit" class="btn btn-outline-secondary"
name="mark_to_order" {if !$can_order_edit}disabled{/if}>{% trans %}Übernehmen{% endtrans %}</button>
</span>
</div>
{/if}
{/if}
</div>
</div>
</form>
{/if}
#}
<p></p>
<div class="form-group">
<label>{% trans %}Created at:{% endtrans %}</label>
<p>{{ part.datetimeAdded | date}}
{#{if !empty($creation_user)} {% trans %}durch{% endtrans %}
{if $can_visit_user}
<a href="{$relative_path}user_info.php?uid={$creation_user_id}">{$creation_user}</a>
{else}
{$creation_user}
{/if}
{/if} #}
</p>
</div>
<p></p>
<div class="form-group">
<label>{% trans %}Last modified:{% endtrans %}</label>
<p>{{ part.lastModified | date }}
{# {if !empty($last_modified_user)} {% trans %}durch{% endtrans %}
{if $can_visit_user}
<a href="{$relative_path}user_info.php?uid={$last_modified_user_id}">{$last_modified_user}</a>
{else}
{$last_modified_user}
{/if}
{/if} #}
</p>
</div>
<p></p>
{#
<form action="show_part_label.php" class="d-print-none">
{if $can_generate_barcode}
{if count($barcode_profiles) > 0}
<input type="hidden" name="label_generate">
<input type="hidden" name="id" value="{$pid}">
<div class="btn-group btn-block">
<button type="submit" class="btn btn-secondary btn-block"><i class="fa fa-barcode fa-fw" aria-hidden="true"></i>
{% trans %}Barcode erzeugen{% endtrans %}</button>
<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-right" id="label-dropdown">
{foreach $barcode_profiles as $profile}
<a href="#" class="link-anchor dropdown-item" onclick="submitFormSubmitBtn($(this).closest('form'), $('#profile_btn_{$profile|replace:" ":"_"}'));">{$profile}</a>
<button type="submit" name="profile" id="profile_btn_{$profile|replace:" ":"_"}" value="{$profile}" class="d-none">{$profile}</button>
{/foreach}
</ul>
</div>
{else}
<input type="hidden" name="id" value="{$pid}">
<input type="hidden" name="generator" value="part">
<input type="hidden" name="size" value="50x30">
<input type="hidden" name="preset" value="Preset A">
<input type="hidden" name="label_generate">
<button type="submit" class="btn btn-secondary btn-block"><i class="fa fa-barcode fa-fw" aria-hidden="true"></i>
{% trans %}Barcode erzeugen{% endtrans %}</button>
{/if}
</form>
<p></p>
{/if}
<div class=" d-print-none">
<button type="button" class="btn btn-secondary btn-block" onclick="window.print();"><i class="fa fa-print fa-fw" aria-hidden="true"></i>
{% trans %}Übersicht drucken{% endtrans %}
</button>
</div>
<p></p>
<div class=" d-print-none">
<div class="dropdown">
<button class="btn btn-secondary btn-block dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-file fa-fw" aria-hidden="true"></i> {% trans %}Datenblattlinks{% endtrans %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
{foreach $datasheet_loop as $sheet}
<li>
<a class="link-datasheet datasheet dropdown-item" title="{$sheet.name}" href="{$sheet.url}" target="_blank">
<img class="companypic-bg" src="{$relative_path}{$sheet.image}" alt="{$sheet.name}">
&nbsp;{$sheet.name}
</a>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
#}
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,329 @@
{% extends "base.html.twig" %}
{% block content %}
<div class="card border-primary">
<div class="card-header bg-primary text-white">
<i class="fa {{ part.favorite ? 'fa-star' : 'fa-info-circle'}} fa-fw" aria-hidden="true"></i>
{% trans %}Detail info for{% endtrans %} <b>"{{ part.name }}"</b>
<div class="float-right">
{% trans %}ID:{% endtrans %} {{ part.id }}
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-9">
{#
<div class="form-horizontal">
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Name:{% endtrans %}</label>
<div class="col-sm-9">
{% if part.manufacturerProductUrl %}
<a class="form-control-link d-print-none-href link-external" target="_blank" title="{{ part.manufacturerProductUrl }}" href="{{ part.manufacturerProductUrl }}">{{part.name}}</a>
{% else %}
<p class="form-control-plaintext">{{ part.name }}</p>
{% endif %}
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Description:{% endtrans %}</label>
<div class="col-sm-9">
<p class="form-control-plaintext">
{% if part.description %}{{part.description}}{% else %}-{% endif %}
</p>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Instock:{% endtrans %}</label>
<div class="col-sm-9">
<p class="form-control-plaintext">{{ part.instock }}</p>
</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Mininmum Instock:{% endtrans %}</label>
<div class="col-sm-9"><p class="form-control-plaintext">{{ part.mininstock}}</p></div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Category:{% endtrans %}</label>
{#
<div class="col-sm-9">{* <a href="show_category_parts.php?cid={$category_id}" class="form-control-link d-print-none-href">{$category_full_path}</a>*}
{include "../smarty_structural_link.tpl" link=$category_path}
</div>
<div class="col-sm-9">TODO: {{ part.category.fullPath }}</div>
</div>
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Storelocation:{% endtrans %}</label>
<div class="col-sm-9">
{# {include "../smarty_structural_link.tpl" link=$storelocation_path}
TODO: {{ part.storelocation.fullPath }}
</div>
</div>
{if !$disable_manufacturers}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Hersteller:{% endtrans %}</label>
<div class="col-sm-9">
{include "../smarty_structural_link.tpl" link=$manufacturer_path}
</div>
</div>
{/if}
{if !$disable_footprints}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Footprint:{% endtrans %}</label>
<div class="col-sm-9">
{include "../smarty_structural_link.tpl" link=$footprint_path}
</div>
</div>
{if !empty($footprint_filename) && $footprint_valid}
<div class="form-group row">
<div class="col-sm-9 offset-md-3">
<img align="middle" rel="popover" src="{$footprint_filename}" alt="" height="70">
</div>
</div>
{/if}
{if $foot3d_active && !empty($foot3d_filename) && $foot3d_valid}
<div class="form-group row">
<div class="col-sm-9 offset-md-3">
<x3d id="foot3d" class="img-thumbnail" height="150" width="500" >
<scene >
<!-- <Viewpoint id="front" position="0 0 10" orientation="-0.01451 0.99989 0.00319 3.15833" description="camera"></Viewpoint> -->
<transform>
<inline url="{$foot3d_filename}"> </inline>
</transform>
</scene>
<button class="btn btn-sm btn-outline-secondary" data-toggle="modal" data-target="#fullscreen"><i class="fa fa-arrows-alt" aria-hidden="true"></i></button>
</x3d>
</div>
</div>
{/if}
{/if}
<div class="form-group row">
<label class="col-sm-3 col-form-label">{% trans %}Kommentar:{% endtrans %}</label>
<div class="col-sm-9">
<p class="form-control-plaintext">{if !empty($comment)}{$comment nofilter}{else}-{/if}</p>
</div>
</div>
{if $can_edit}
<div class="form-group d-print-none row mt-2">
<div class="col-sm-9 offset-sm-3">
<a class="btn btn-primary" href="edit_part_info.php?pid={$pid}">
<i class="fa fa-edit fa-fw" aria-hidden="true"></i> {% trans %}Angaben verändern{% endtrans %}</a>
</div>
</div>
{/if}
</div>
#}
<div class="row">
<div class="col-md-3">
<img src="https://via.placeholder.com/150" class="img-fluid img-thumbnail" height="150" width="150">
</div>
<div class="col-md-9">
<h5 class="text-muted">Hersteller</h5>
<h3>{{ part.name }}</h3>
</div>
</div>
</div>
<div class="col-md-3">
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
<label for="n_less">{% trans %}Teile entnehmen:{% endtrans %}</label>
<div class="input-group">
<input type="number" class="form-control" name="n_less" min="0" max="999999" value="1" placeholder="Anzahl" {if !$can_instock || $instock_unknown}disabled{/if}>
<div class="input-group-append">
<div class="btn-group">
<button type="submit" class="btn btn-outline-secondary btn-group-append" name="dec" {if !$can_instock || $instock_unknown}disabled{/if}>{% trans %}Entnehmen{% endtrans %}</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<div class="px-4 py-3">
<div class="form-group">
<label>{% trans %}Kommentar/Zweck:{% endtrans %}</label>
<input type="text" class="form-control" name="instock_change_comment" placeholder="{$default_instock_change_comment_w}">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<p></p>
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
<label for="n_more">{% trans %}Teile hinzufügen{% endtrans %}:</label>
<div class="input-group">
<input type="number" class="form-control" name="n_more" min="0" max="999999" value="1" {if !$can_instock || $instock_unknown}disabled{/if}>
<div class="input-group-append">
<div class="btn-group">
<button type="submit" class="btn btn-outline-secondary btn-group-append" name="inc" {if !$can_instock || $instock_unknown}disabled{/if}>{% trans %}Hinzufügen{% endtrans %}</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<div class="px-4 py-3">
<div class="form-group">
<label>{% trans %}Kommentar/Zweck:{% endtrans %}</label>
<input type="text" class="form-control" name="instock_change_comment" placeholder="{$default_instock_change_comment_a}">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
<p></p>
{if $can_order_read && !$instock_unknown}
<form action="" method="post" class="d-print-none no-progbar">
<input type="hidden" name="pid" value="{$pid}">
<div class="row">
<div class="col-md-12">
{if $manual_order_exists}
<label for="remove_mark_to_order">{% trans %}Bauteil wurde manuell zum Bestellen vorgemerkt.{% endtrans %}</label>
<button type="submit" class="btn btn-outline-secondary"
name="remove_mark_to_order" {if !$can_order_read}disabled{/if}>
{% trans %}Aufheben{% endtrans %}</button>
{else}
{if $auto_order_exists}
<i>{% trans %}Das Bauteil wird unter "Zu bestellende Teile"aufgelistet, da der Bestand kleiner als der Mindestbestand ist.{% endtrans %}</i>
{else}
<label for="order_quantity">{% trans %}Zum Bestellen vormerken:{% endtrans %}</label>
<div class="input-group">
<input type="number" min="0" max="999999" class="form-control" value="1" name="order_quantity"
placeholder="Bestellmenge" {if !$can_order_edit}disabled{/if}><br>
<span class="input-group-append">
<button type="submit" class="btn btn-outline-secondary"
name="mark_to_order" {if !$can_order_edit}disabled{/if}>{% trans %}Übernehmen{% endtrans %}</button>
</span>
</div>
{/if}
{/if}
</div>
</div>
</form>
{/if}
<p></p>
<div class="form-group">
<label>{% trans %}Hinzugefügt:{% endtrans %}</label>
<p>{$datetime_added}
{if !empty($creation_user)} {% trans %}durch{% endtrans %}
{if $can_visit_user}
<a href="{$relative_path}user_info.php?uid={$creation_user_id}">{$creation_user}</a>
{else}
{$creation_user}
{/if}
{/if}
</p>
</div>
<p></p>
<div class="form-group">
<label>{% trans %}Letzte Änderung:{% endtrans %}</label>
<p>{$last_modified}
{if !empty($last_modified_user)} {% trans %}durch{% endtrans %}
{if $can_visit_user}
<a href="{$relative_path}user_info.php?uid={$last_modified_user_id}">{$last_modified_user}</a>
{else}
{$last_modified_user}
{/if}
{/if}
</p>
</div>
<p></p>
<form action="show_part_label.php" class="d-print-none">
{if $can_generate_barcode}
{if count($barcode_profiles) > 0}
<input type="hidden" name="label_generate">
<input type="hidden" name="id" value="{$pid}">
<div class="btn-group btn-block">
<button type="submit" class="btn btn-secondary btn-block"><i class="fa fa-barcode fa-fw" aria-hidden="true"></i>
{% trans %}Barcode erzeugen{% endtrans %}</button>
<button type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-right" id="label-dropdown">
{foreach $barcode_profiles as $profile}
<a href="#" class="link-anchor dropdown-item" onclick="submitFormSubmitBtn($(this).closest('form'), $('#profile_btn_{$profile|replace:" ":"_"}'));">{$profile}</a>
<button type="submit" name="profile" id="profile_btn_{$profile|replace:" ":"_"}" value="{$profile}" class="d-none">{$profile}</button>
{/foreach}
</ul>
</div>
{else}
<input type="hidden" name="id" value="{$pid}">
<input type="hidden" name="generator" value="part">
<input type="hidden" name="size" value="50x30">
<input type="hidden" name="preset" value="Preset A">
<input type="hidden" name="label_generate">
<button type="submit" class="btn btn-secondary btn-block"><i class="fa fa-barcode fa-fw" aria-hidden="true"></i>
{% trans %}Barcode erzeugen{% endtrans %}</button>
{/if}
</form>
<p></p>
{/if}
<div class=" d-print-none">
<button type="button" class="btn btn-secondary btn-block" onclick="window.print();"><i class="fa fa-print fa-fw" aria-hidden="true"></i>
{% trans %}Übersicht drucken{% endtrans %}
</button>
</div>
<p></p>
<div class=" d-print-none">
<div class="dropdown">
<button class="btn btn-secondary btn-block dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="fa fa-file fa-fw" aria-hidden="true"></i> {% trans %}Datenblattlinks{% endtrans %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
{foreach $datasheet_loop as $sheet}
<li>
<a class="link-datasheet datasheet dropdown-item" title="{$sheet.name}" href="{$sheet.url}" target="_blank">
<img class="companypic-bg" src="{$relative_path}{$sheet.image}" alt="{$sheet.name}">
&nbsp;{$sheet.name}
</a>
</li>
{/foreach}
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

58
webpack.config.js Normal file
View file

@ -0,0 +1,58 @@
var Encore = require('@symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
// uncomment if you use API Platform Admin (composer req api-admin)
//.enableReactPreset()
//.addEntry('admin', './assets/js/admin.js')
;
module.exports = Encore.getWebpackConfig();

6363
yarn.lock Normal file

File diff suppressed because it is too large Load diff