Merge branch 'feature-label2' into develop

This commit is contained in:
Cram42 2022-11-01 20:12:28 +08:00
commit 6b2fe582ca
24 changed files with 2304 additions and 132 deletions

View file

@ -1126,4 +1126,43 @@ class Helper
return $settings;
}
/**
* Conversion between units of measurement
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @since 5.0
* @param float $value Measurement value to convert
* @param string $srcUnit Source unit of measurement
* @param string $dstUnit Destination unit of measurement
* @param int $round Round the result to decimals (Default false - No rounding)
* @return float
*/
public static function convertUnit($value, $srcUnit, $dstUnit, $round=false) {
$srcFactor = static::getUnitConversionFactor($srcUnit);
$dstFactor = static::getUnitConversionFactor($dstUnit);
$output = $value * $srcFactor / $dstFactor;
return ($round !== false) ? round($output, $round) : $output;
}
/**
* Get conversion factor from unit of measurement to mm
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @since 5.0
* @param string $unit Unit of measurement
* @return float
*/
public static function getUnitConversionFactor($unit) {
switch (strtolower($unit)) {
case 'mm': return 1.0;
case 'cm': return 10.0;
case 'm': return 1000.0;
case 'in': return 25.4;
case 'ft': return 12 * static::getUnitConversionFactor('in');
case 'yd': return 3 * static::getUnitConversionFactor('ft');
case 'pt': return (1/72) * static::getUnitConversionFactor('in');
default: throw new \InvalidArgumentException('Unit: \''.$unit.'\' is not supported');
}
}
}

View file

@ -0,0 +1,71 @@
<?php
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LabelsTransformer;
use App\Models\Labels\Label;
use Illuminate\Http\Request;
use Illuminate\Support\ItemNotFoundException;
use Auth;
class LabelsController extends Controller
{
/**
* Returns JSON listing of all labels.
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @return JsonResponse
*/
public function index(Request $request)
{
$this->authorize('view', Label::class);
$labels = Label::find();
if ($request->filled('search')) {
$search = $request->get('search');
$labels = $labels->filter(function ($label, $index) use ($search) {
return stripos($label->getName(), $search) !== false;
});
}
$total = $labels->count();
$offset = $request->get('offset', 0);
$offset = ($offset > $total) ? $total : $offset;
$maxLimit = config('app.max_results');
$limit = $request->get('limit', $maxLimit);
$limit = ($limit > $maxLimit) ? $maxLimit : $limit;
$labels = $labels->skip($offset)->take($limit);
return (new LabelsTransformer)->transformLabels($labels, $total, $request);
}
/**
* Returns JSON with information about a label for detail view.
*
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
* @param string $labelName
* @return JsonResponse
*/
public function show(string $labelName)
{
$labelName = str_replace('/', '\\', $labelName);
try {
$label = Label::find($labelName);
} catch(ItemNotFoundException $e) {
return response()
->json(
Helper::formatStandardApiResponse('error', null, trans('admin/labels/message.does_not_exist')),
404
);
}
$this->authorize('view', $label);
return (new LabelsTransformer)->transformLabel($label);
}
}

View file

@ -13,6 +13,7 @@ use App\Models\Company;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use App\View\Label;
use Auth;
use Carbon\Carbon;
use DB;
@ -441,11 +442,12 @@ class AssetsController extends Controller
* @since [v3.0]
* @return Redirect
*/
public function getAssetByTag(Request $request)
public function getAssetByTag($tag=null, Request $request)
{
$tag = $tag ? $tag : $request->get('assetTag');
$topsearch = ($request->get('topsearch') == 'true');
if (! $asset = Asset::where('asset_tag', '=', $request->get('assetTag'))->first()) {
if (! $asset = Asset::where('asset_tag', '=', $tag)->first()) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
$this->authorize('view', $asset);
@ -542,9 +544,10 @@ class AssetsController extends Controller
$asset = Asset::find($assetId);
$this->authorize('view', $asset);
return view('hardware/labels')
return (new Label())
->with('assets', collect([ $asset ]))
->with('settings', Setting::getSettings())
->with('offset', request()->get('offset'))
->with('bulkedit', false)
->with('count', 0);
}

View file

@ -8,6 +8,7 @@ use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use App\Models\Setting;
use App\View\Label;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
@ -44,7 +45,7 @@ class BulkAssetsController extends Controller
if ($request->filled('bulk_actions')) {
switch ($request->input('bulk_actions')) {
case 'labels':
return view('hardware/labels')
return (new Label)
->with('assets', Asset::find($asset_ids))
->with('settings', Setting::getSettings())
->with('bulkedit', true)

View file

@ -844,6 +844,14 @@ class SettingsController extends Controller
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->label2_enable = $request->input('label2_enable');
$setting->label2_template = $request->input('label2_template');
$setting->label2_title = $request->input('label2_title');
$setting->label2_asset_logo = $request->input('label2_asset_logo');
$setting->label2_1d_type = $request->input('label2_1d_type');
$setting->label2_2d_type = $request->input('label2_2d_type');
$setting->label2_2d_target = $request->input('label2_2d_target');
$setting->label2_fields = $request->input('label2_fields');
$setting->labels_per_page = $request->input('labels_per_page');
$setting->labels_width = $request->input('labels_width');
$setting->labels_height = $request->input('labels_height');

View file

@ -0,0 +1,70 @@
<?php
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Labels\Label;
use App\Models\Labels\Sheet;
use App\Models\Labels\RectangleSheet;
use Illuminate\Support\Collection;
class LabelsTransformer
{
public function transformLabels(Collection $labels, $total)
{
$array = [];
foreach ($labels as $label) {
$array[] = self::transformLabel($label);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformLabel(Label $label)
{
$array = [
'name' => $label->getName(),
'unit' => $label->getUnit(),
'width' => $label->getWidth(),
'height' => $label->getHeight(),
'margin_top' => $label->getMarginTop(),
'margin_bottom' => $label->getMarginBottom(),
'margin_left' => $label->getMarginLeft(),
'margin_right' => $label->getMarginRight(),
'support_1d_barcode' => $label->getSupport1DBarcode(),
'support_2d_barcode' => $label->getSupport2DBarcode(),
'support_fields' => $label->getSupportFields(),
'support_logo' => $label->getSupportLogo(),
'support_title' => $label->getSupportTitle(),
];
if ($label instanceof Sheet) {
$array['sheet_info'] = [
'label_width' => $label->getLabelWidth(),
'label_height' => $label->getLabelHeight(),
'label_margin_top' => $label->getLabelMarginTop(),
'label_margin_bottom' => $label->getLabelMarginBottom(),
'label_margin_left' => $label->getLabelMarginLeft(),
'label_margin_right' => $label->getLabelMarginRight(),
'labels_per_page' => $label->getLabelsPerPage(),
'label_border' => $label->getLabelBorder(),
];
}
if ($label instanceof RectangleSheet) {
$array['rectanglesheet_info'] = [
'columns' => $label->getColumns(),
'rows' => $label->getRows(),
'column_spacing' => $label->getLabelColumnSpacing(),
'row_spacing' => $label->getLabelRowSpacing(),
];
}
return $array;
}
}

View file

@ -0,0 +1,224 @@
<?php
namespace App\Models\Labels;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\Setting;
class DefaultLabel extends RectangleSheet
{
private const BARCODE1D_SIZE = 0.15;
private const BARCODE2D_SIZE = 0.76;
private const BARCODE2D_MARGIN = 0.075;
private const LOGO_SIZE = [0.75, 0.50];
private const LOGO_MARGIN = 0.05;
private const TEXT_MARGIN = 0.04;
private float $textSize;
private float $labelWidth;
private float $labelHeight;
private float $labelSpacingH;
private float $labelSpacingV;
private float $pageMarginTop;
private float $pageMarginBottom;
private float $pageMarginLeft;
private float $pageMarginRight;
private float $pageWidth;
private float $pageHeight;
private int $columns;
private int $rows;
public function __construct() {
$settings = Setting::getSettings();
$this->textSize = Helper::convertUnit($settings->labels_fontsize, 'pt', 'in');
$this->labelWidth = $settings->labels_width;
$this->labelHeight = $settings->labels_height;
$this->labelSpacingH = $settings->labels_display_sgutter;
$this->labelSpacingV = $settings->labels_display_bgutter;
$this->pageMarginTop = $settings->labels_pmargin_top;
$this->pageMarginBottom = $settings->labels_pmargin_bottom;
$this->pageMarginLeft = $settings->labels_pmargin_left;
$this->pageMarginRight = $settings->labels_pmargin_right;
$this->pageWidth = $settings->labels_pagewidth;
$this->pageHeight = $settings->labels_pageheight;
$usableWidth = $this->pageWidth - $this->pageMarginLeft - $this->pageMarginRight;
$usableHeight = $this->pageHeight - $this->pageMarginTop - $this->pageMarginBottom;
$this->columns = ($usableWidth + $this->labelSpacingH) / ($this->labelWidth + $this->labelSpacingH);
$this->rows = ($usableHeight + $this->labelSpacingV) / ($this->labelHeight + $this->labelSpacingV);
}
public function getUnit() { return 'in'; }
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginBottom; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginRight; }
public function getColumns() { return $this->columns; }
public function getRows() { return $this->rows; }
public function getLabelBorder() { return 0.01; }
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelMarginTop() { return 0; }
public function getLabelMarginBottom() { return 0; }
public function getLabelMarginLeft() { return 0; }
public function getLabelMarginRight() { return 0; }
public function getLabelColumnSpacing() { return $this->labelSpacingH; }
public function getLabelRowSpacing() { return $this->labelSpacingV; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 4; }
public function getSupportTitle() { return true; }
public function getSupportLogo() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$asset = Asset::find($record->get('id'));
$settings = Setting::getSettings();
$textY = 0;
$textX1 = 0;
$textX2 = $this->getLabelWidth();
// 1D Barcode
if ($record->get('barcode1d')) {
static::write1DBarcode(
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
0.05, $this->getLabelHeight() - self::BARCODE1D_SIZE,
$this->getLabelWidth() - 0.1, self::BARCODE1D_SIZE
);
}
// 2D Barcode
if ($record->get('barcode2d')) {
static::write2DBarcode(
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
0, 0, self::BARCODE2D_SIZE, self::BARCODE2D_SIZE
);
$textX1 += self::BARCODE2D_SIZE + self::BARCODE2D_MARGIN;
}
// Logo
if ($record->get('logo')) {
$logoSize = static::writeImage(
$pdf, $record->get('logo'),
$this->labelWidth - self::LOGO_SIZE[0], 0,
self::LOGO_SIZE[0], self::LOGO_SIZE[1],
'R', 'T', 300, true, false, 0
);
$textX2 -= ($logoSize[0] + self::LOGO_MARGIN);
}
$textW = $textX2 - $textX1;
// Title
if ($record->get('title')) {
static::writeText(
$pdf, $record->get('title'),
$textX1, 0,
'freesans', 'b', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
}
// Fields
$fieldsDone = 0;
if ($settings->labels_display_name && $fieldsDone < $this->getSupportFields()) {
if ($asset->name) {
static::writeText(
$pdf, 'N: '.$asset->name,
$textX1, $textY,
'freesans', '', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
$fieldsDone++;
}
}
if ($settings->labels_display_company_name && $fieldsDone < $this->getSupportFields()) {
if ($asset->company) {
static::writeText(
$pdf, 'C: '.$asset->company->name,
$textX1, $textY,
'freesans', '', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
$fieldsDone++;
}
}
if ($settings->labels_display_tag && $fieldsDone < $this->getSupportFields()) {
if ($asset->asset_tag) {
static::writeText(
$pdf, 'T: '.$asset->asset_tag,
$textX1, $textY,
'freesans', '', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
$fieldsDone++;
}
}
if ($settings->labels_display_serial && $fieldsDone < $this->getSupportFields()) {
if ($asset->serial) {
static::writeText(
$pdf, 'S: '.$asset->serial,
$textX1, $textY,
'freesans', '', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
$fieldsDone++;
}
}
if ($settings->labels_display_model && $fieldsDone < $this->getSupportFields()) {
if ($asset->model) {
static::writeText(
$pdf, 'M: '.$asset->model->name,
$textX1, $textY,
'freesans', '', $this->textSize, 'L',
$textW, $this->textSize,
true, 0
);
$textY += $this->textSize + self::TEXT_MARGIN;
$fieldsDone++;
}
}
}
}
?>

591
app/Models/Labels/Label.php Normal file
View file

@ -0,0 +1,591 @@
<?php
namespace App\Models\Labels;
use App\Helpers\Helper;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use TCPDF;
use TCPDF_STATIC;
/**
* Model for Labels.
*
* @version v1.0
*/
abstract class Label
{
/**
* Returns the unit of measure used
* 'pt', 'mm', 'cm', 'in'
*
* @return string
*/
public abstract function getUnit();
/**
* Returns the label's width in getUnit() units
*
* @return float
*/
public abstract function getWidth();
/**
* Returns the label's height in getUnit() units
*
* @return float
*/
public abstract function getHeight();
/**
* Returns the label's top margin in getUnit() units
*
* @return float
*/
public abstract function getMarginTop();
/**
* Returns the label's bottom margin in getUnit() units
*
* @return float
*/
public abstract function getMarginBottom();
/**
* Returns the label's left margin in getUnit() units
*
* @return float
*/
public abstract function getMarginLeft();
/**
* Returns the label's right margin in getUnit() units
*
* @return float
*/
public abstract function getMarginRight();
/**
* Returns whether the template supports a 1D barcode.
*
* @return bool
*/
public abstract function getSupport1DBarcode();
/**
* Returns whether the template supports a 2D barcode.
*
* @return bool
*/
public abstract function getSupport2DBarcode();
/**
* Returns the number of fields the template supports.
*
* @return int
*/
public abstract function getSupportFields();
/**
* Returns whether the template supports a logo.
*
* @return bool
*/
public abstract function getSupportLogo();
/**
* Returns whether the template supports a title.
*
* @return bool
*/
public abstract function getSupportTitle();
/**
* Make changes to the PDF properties here. OPTIONAL.
*
* @param TCPDF $pdf The TCPDF instance
*/
public abstract function preparePDF(TCPDF $pdf);
/**
* Write single data record as content here.
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $record A data record
*/
public abstract function write(TCPDF $pdf, Collection $record);
/**
* Handle the data here. Override for multiple-per-page handling
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
*/
public function writeAll(TCPDF $pdf, Collection $data) {
$data->each(function ($record, $index) use ($pdf) {
$pdf->AddPage();
$this->write($pdf, $record);
});
}
/**
* Returns the qualified class name relative to the Label class's namespace.
*
* @return string
*/
public final function getName() {
$refClass = new \ReflectionClass(Label::class);
return str_replace($refClass->getNamespaceName() . '\\', '', get_class($this));
}
/**
* Returns the label's orientation as a string.
* 'L' = Landscape
* 'P' = Portrait
*
* @return string
*/
public final function getOrientation() {
return ($this->getWidth() >= $this->getHeight()) ? 'L' : 'P';
}
/**
* Returns the label's printable area as an object.
*
* @return object [ 'x1'=>0.00, 'y1'=>0.00, 'x2'=>0.00, 'y2'=>0.00, 'w'=>0.00, 'h'=>0.00 ]
*/
public final function getPrintableArea() {
return (object)[
'x1' => $this->getMarginLeft(),
'y1' => $this->getMarginTop(),
'x2' => $this->getWidth() - $this->getMarginRight(),
'y2' => $this->getHeight() - $this->getMarginBottom(),
'w' => $this->getWidth() - $this->getMarginLeft() - $this->getMarginRight(),
'h' => $this->getHeight() - $this->getMarginTop() - $this->getMarginBottom(),
];
}
/**
* Write a text cell.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $text The text to write. Supports 'some **bold** text'.
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param string $font The font family
* @param string $style The font style
* @param int $size The font size in getUnit() units
* @param string $align Align text in the box. 'L' left, 'R' right, 'C' center.
* @param float $width Force text box width. NULL to auto-fit.
* @param float $height Force text box height. NULL to auto-fit.
* @param bool $squash Squash text if it's too big
* @param int $border Thickness of border. Default = 0.
* @param int $spacing Letter spacing. Default = 0.
*/
public final function writeText(TCPDF $pdf, $text, $x, $y, $font=null, $style=null, $size=null, $align='L', $width=null, $height=null, $squash=false, $border=0, $spacing=0) {
$prevFamily = $pdf->getFontFamily();
$prevStyle = $pdf->getFontStyle();
$prevSizePt = $pdf->getFontSizePt();
$text = !empty($text) ? $text : '';
$fontFamily = !empty($font) ? $font : $prevFamily;
$fontStyle = !empty($style) ? $style : $prevStyle;
if ($size) $fontSizePt = Helper::convertUnit($size, $this->getUnit(), 'pt', true);
else $fontSizePt = $prevSizePt;
$pdf->SetFontSpacing($spacing);
$parts = collect(explode('**', $text))
->map(function ($part, $index) use ($pdf, $fontFamily, $fontStyle, $fontSizePt) {
$modStyle = ($index % 2 == 1) ? 'B' : $fontStyle;
$pdf->setFont($fontFamily, $modStyle, $fontSizePt);
return [
'text' => $part,
'text_width' => $pdf->GetStringWidth($part),
'font_family' => $fontFamily,
'font_style' => $modStyle,
'font_size' => $fontSizePt,
];
});
$textWidth = $parts->reduce(function ($carry, $part) { return $carry += $part['text_width']; });
$cellWidth = !empty($width) ? $width : $textWidth;
if ($squash && ($textWidth > 0)) {
$scaleFactor = min(1.0, $cellWidth / $textWidth);
$parts = $parts->map(function ($part, $index) use ($scaleFactor) {
$part['text_width'] = $part['text_width'] * $scaleFactor;
return $part;
});
}
$cellHeight = !empty($height) ? $height : Helper::convertUnit($fontSizePt, 'pt', $this->getUnit());
if ($border) {
$prevLineWidth = $pdf->getLineWidth();
$pdf->setLineWidth($border);
$pdf->Rect($x, $y, $cellWidth, $cellHeight);
$pdf->setLineWidth($prevLineWidth);
}
switch($align) {
case 'R': $startX = ($x + $cellWidth) - min($cellWidth, $textWidth); break;
case 'C': $startX = ($x + ($cellWidth / 2)) - (min($cellWidth, $textWidth) / 2); break;
case 'L':
default: $startX = $x; break;
}
$parts->reduce(function ($currentX, $part) use ($pdf, $y, $cellHeight) {
$pdf->SetXY($currentX, $y);
$pdf->setFont($part['font_family'], $part['font_style'], $part['font_size']);
$pdf->Cell($part['text_width'], $cellHeight, $part['text'], 0, 0, '', false, '', 1, true);
return $currentX += $part['text_width'];
}, $startX);
$pdf->SetFont($prevFamily, $prevStyle, $prevSizePt);
$pdf->SetFontSpacing(0);
}
/**
* Write an image.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $image The image to write
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
* @param string $halign Align text in the box. 'L' left, 'R' right, 'C' center. Default 'L'.
* @param string $valign Align text in the box. 'T' top, 'B' bottom, 'C' center. Default 'T'.
* @param int $dpi Pixels per inch
* @param bool $resize Resize to fit container
* @param bool $stretch Stretch (vs Scale) to fit container
* @param int $border Thickness of border. Default = 0.
*
* @return array Returns the final calculated size [w,h]
*/
public final function writeImage(TCPDF $pdf, $image, $x, $y, $width=null, $height=null, $halign='L', $valign='L', $dpi=300, $resize=false, $stretch=false, $border=0) {
if (empty($image)) return [0,0];
$imageInfo = getimagesize($image);
if (!$imageInfo) return [0,0]; // TODO: SVG or other
$imageWidthPx = $imageInfo[0];
$imageHeightPx = $imageInfo[1];
$imageType = image_type_to_extension($imageInfo[2], false);
$imageRatio = $imageWidthPx / $imageHeightPx;
$dpu = Helper::convertUnit($dpi, $this->getUnit(), 'in');
$imageWidth = $imageWidthPx / $dpu;
$imageHeight = $imageHeightPx / $dpu;
$outputWidth = $imageWidth;
$outputHeight = $imageHeight;
if ($resize) {
// Assign specified parameters
$limitWidth = $width;
$limitHeight = $height;
// If not, try calculating from the other dimension
$limitWidth = ($limitWidth > 0) ? $limitWidth : ($limitHeight / $imageRatio);
$limitHeight = ($limitHeight > 0) ? $limitHeight : ($limitWidth * $imageRatio);
// If not, just use the image size
$limitWidth = ($limitWidth > 0) ? $limitWidth : $imageWidth;
$limitHeight = ($limitHeight > 0) ? $limitHeight : $imageHeight;
$scaleWidth = $limitWidth / $imageWidth;
$scaleHeight = $limitHeight / $imageHeight;
// If non-stretch, make both scales factors equal
if (!$stretch) {
// Do we need to scale down at all? That's most important.
if (($scaleWidth < 1.0) || ($scaleHeight < 1.0)) {
// Choose largest scale-down
$scaleWidth = min($scaleWidth, $scaleHeight);
} else {
// Choose smallest scale-up
$scaleWidth = min(max($scaleWidth, 1.0), max($scaleHeight, 1.0));
}
$scaleHeight = $scaleWidth;
}
$outputWidth = $imageWidth * $scaleWidth;
$outputHeight = $imageHeight * $scaleHeight;
}
// Container
$containerWidth = !empty($width) ? $width : $outputWidth;
$containerHeight = !empty($height) ? $height : $outputHeight;
// Horizontal Position
switch ($halign) {
case 'R': $originX = ($x + $containerWidth) - $outputWidth; break;
case 'C': $originX = ($x + ($containerWidth / 2)) - ($outputWidth / 2); break;
case 'L':
default: $originX = $x; break;
}
// Vertical Position
switch ($valign) {
case 'B': $originY = ($y + $containerHeight) - $outputHeight; break;
case 'C': $originY = ($y + ($containerHeight / 2)) - ($outputHeight / 2); break;
case 'T':
default: $originY = $y; break;
}
// Actual Image
$pdf->Image($image, $originX, $originY, $outputWidth, $outputHeight, $imageType, '', '', true);
// Border
if ($border) {
$prevLineWidth = $pdf->getLineWidth();
$pdf->setLineWidth($border);
$pdf->Rect($x, $y, $containerWidth, $containerHeight);
$pdf->setLineWidth($prevLineWidth);
}
return [ $outputWidth, $outputHeight ];
}
/**
* Write a 1D barcode.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
*/
public final function write1DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height) {
if (empty($value)) return;
$pdf->write1DBarcode($value, $type, $x, $y, $width, $height, null, ['stretch'=>true]);
}
/**
* Write a 2D barcode.
*
* @param TCPDF $pdf The TCPDF instance
* @param string $value The barcode content
* @param string $type The barcode type
* @param float $x X position of top-left
* @param float $y Y position of top-left
* @param float $width The container width
* @param float $height The container height
*/
public final function write2DBarcode(TCPDF $pdf, $value, $type, $x, $y, $width, $height) {
if (empty($value)) return;
$pdf->write2DBarcode($value, $type, $x, $y, $width, $height, null, ['stretch'=>true]);
}
/**
* Checks the template is internally valid
*/
public final function validate() {
$this->validateUnits();
$this->validateSize();
$this->validateMargins();
$this->validateSupport();
}
private function validateUnits() {
$validUnits = [ 'pt', 'mm', 'cm', 'in' ];
$unit = $this->getUnit();
if (!in_array(strtolower($unit), $validUnits)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_value', [
'name' => 'getUnit()',
'expected' => '[ \''.implode('\', \'', $validUnits).'\' ]',
'actual' => '\''.$unit.'\''
]));
}
}
private function validateSize() {
$width = $this->getWidth();
if (!is_numeric($width) || is_string($width)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getWidth()',
'expected' => 'float',
'actual' => gettype($width)
]));
}
$height = $this->getHeight();
if (!is_numeric($height) || is_string($height)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getHeight()',
'expected' => 'float',
'actual' => gettype($height)
]));
}
}
private function validateMargins() {
$marginTop = $this->getMarginTop();
if (!is_numeric($marginTop) || is_string($marginTop)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginTop()',
'expected' => 'float',
'actual' => gettype($marginTop)
]));
}
$marginBottom = $this->getMarginBottom();
if (!is_numeric($marginBottom) || is_string($marginBottom)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginBottom()',
'expected' => 'float',
'actual' => gettype($marginBottom)
]));
}
$marginLeft = $this->getMarginLeft();
if (!is_numeric($marginLeft) || is_string($marginLeft)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginLeft()',
'expected' => 'float',
'actual' => gettype($marginLeft)
]));
}
$marginRight = $this->getMarginRight();
if (!is_numeric($marginRight) || is_string($marginRight)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getMarginRight()',
'expected' => 'float',
'actual' => gettype($marginRight)
]));
}
}
private function validateSupport() {
$support1D = $this->getSupport1DBarcode();
if (!is_bool($support1D)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupport1DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support1D)
]));
}
$support2D = $this->getSupport2DBarcode();
if (!is_bool($support2D)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupport2DBarcode()',
'expected' => 'boolean',
'actual' => gettype($support2D)
]));
}
$supportFields = $this->getSupportFields();
if (!is_int($supportFields)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportFields()',
'expected' => 'integer',
'actual' => gettype($supportFields)
]));
}
$supportLogo = $this->getSupportLogo();
if (!is_bool($supportLogo)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportLogo()',
'expected' => 'boolean',
'actual' => gettype($supportLogo)
]));
}
$supportTitle = $this->getSupportTitle();
if (!is_bool($supportTitle)) {
throw new \UnexpectedValueException(trans('admin/labels/message.invalid_return_type', [
'name' => 'getSupportTitle()',
'expected' => 'boolean',
'actual' => gettype($supportTitle)
]));
}
}
/**
* Public Static Functions
*/
/**
* Find size of a page by its format.
*
* @param string $format Format name (eg: 'A4', 'LETTER', etc.)
* @param string $orientation 'L' for Landscape, 'P' for Portrait ('L' default)
* @param string $unit Unit of measure to return in ('mm' default)
*
* @return object (object)[ 'width' => (float)123.4, 'height' => (float)123.4 ]
*/
public static function fromFormat($format, $orientation='L', $unit='mm', $round=false) {
$size = collect(TCPDF_STATIC::getPageSizeFromFormat($format))
->sort()
->map(function ($value) use ($unit) {
return Helper::convertUnit($value, 'pt', $unit);
})
->toArray();
$width = ($orientation == 'L') ? $size[1] : $size[0];
$height = ($orientation == 'L') ? $size[0] : $size[1];
return (object)[
'width' => ($round !== false) ? round($width, $round) : $width,
'height' => ($round !== false) ? round($height, $round) : $height,
];
}
/**
* Find a Label by its path (or just return them all).
*
* Unlike most Models, these are defined by their existence as non-
* abstract classes stored in Models\Labels.
*
* @param string|Arrayable|array|null $path Label path[s]
* @return Collection|Label|null
*/
public static function find($name=null) {
// Find many
if (is_array($name) || $name instanceof Arrayable) {
$labels = collect($name)
->map(function ($thisname) {
return static::find($thisname);
})
->whereNotNull();
return ($labels->count() > 0) ? $labels : null;
}
// Find one
if ($name !== null) {
return static::find()
->sole(function ($label) use ($name) {
return $label->getName() == $name;
});
}
// Find all
return collect(File::allFiles(__DIR__))
->map(function ($file) {
preg_match_all('/\/*(.+?)(?:\/|\.)/', $file->getRelativePathName(), $matches);
return __NAMESPACE__ . '\\' . implode('\\', $matches[1]);
})
->filter(function ($name) {
if (!class_exists($name)) return false;
$refClass = new \ReflectionClass($name);
if ($refClass->isAbstract()) return false;
return $refClass->isSubclassOf(Label::class);
})
->map(function ($name) {
return new $name();
});
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Models\Labels;
abstract class RectangleSheet extends Sheet
{
/**
* Returns the number of columns per sheet
*
* @return int
*/
public abstract function getColumns();
/**
* Returns the number of rows per sheet
*
* @return int
*/
public abstract function getRows();
/**
* Returns the spacing between columns
*
* @return int
*/
public abstract function getLabelColumnSpacing();
/**
* Returns the spacing between rows
*
* @return int
*/
public abstract function getLabelRowSpacing();
public function getLabelsPerPage() { return $this->getColumns() * $this->getRows(); }
public function getLabelPosition($index) {
$printIndex = $index + $this->getLabelIndexOffset();
$row = (int)($printIndex / $this->getColumns());
$col = $printIndex - ($row * $this->getColumns());
$x = $this->getPageMarginLeft() + (($this->getLabelWidth() + $this->getLabelColumnSpacing()) * $col);
$y = $this->getPageMarginTop() + (($this->getLabelHeight() + $this->getLabelRowSpacing()) * $row);
return [ $x, $y ];
}
}
?>

209
app/Models/Labels/Sheet.php Normal file
View file

@ -0,0 +1,209 @@
<?php
namespace App\Models\Labels;
abstract class Sheet extends Label
{
protected int $indexOffset = 0;
public function getWidth() { return $this->getPageWidth(); }
public function getHeight() { return $this->getPageHeight(); }
public function getMarginTop() { return $this->getPageMarginTop(); }
public function getMarginBottom() { return $this->getPageMarginBottom(); }
public function getMarginLeft() { return $this->getPageMarginLeft(); }
public function getMarginRight() { return $this->getPageMarginRight(); }
/**
* Returns the page width in getUnit() units
*
* @return float
*/
public abstract function getPageWidth();
/**
* Returns the page height in getUnit() units
*
* @return float
*/
public abstract function getPageHeight();
/**
* Returns the page top margin in getUnit() units
*
* @return float
*/
public abstract function getPageMarginTop();
/**
* Returns the page bottom margin in getUnit() units
*
* @return float
*/
public abstract function getPageMarginBottom();
/**
* Returns the page left margin in getUnit() units
*
* @return float
*/
public abstract function getPageMarginLeft();
/**
* Returns the page right margin in getUnit() units
*
* @return float
*/
public abstract function getPageMarginRight();
/**
* Returns the page width in getUnit() units
*
* @return float
*/
public abstract function getLabelWidth();
/**
* Returns each label's height in getUnit() units
*
* @return float
*/
public abstract function getLabelHeight();
/**
* Returns each label's top margin in getUnit() units
*
* @return float
*/
public abstract function getLabelMarginTop();
/**
* Returns each label's bottom margin in getUnit() units
*
* @return float
*/
public abstract function getLabelMarginBottom();
/**
* Returns each label's left margin in getUnit() units
*
* @return float
*/
public abstract function getLabelMarginLeft();
/**
* Returns each label's right margin in getUnit() units
*
* @return float
*/
public abstract function getLabelMarginRight();
/**
* Returns the number of labels each page supports
*
* @return int
*/
public abstract function getLabelsPerPage();
/**
* Returns label position based on its index
*
* @param int $index
*
* @return array [x,y]
*/
public abstract function getLabelPosition(int $index);
/**
* Returns the border to draw around labels
*
* @return int
*/
public abstract function getLabelBorder();
/**
* Handle the data here. Override for multiple-per-page handling
*
* @param TCPDF $pdf The TCPDF instance
* @param Collection $data The data
*/
public function writeAll($pdf, $data) {
$prevPageNumber = -1;
foreach ($data->toArray() as $recordIndex => $record) {
$pageNumber = (int)($recordIndex / $this->getLabelsPerPage());
if ($pageNumber != $prevPageNumber) {
$pdf->AddPage();
$prevPageNumber = $pageNumber;
}
$pageIndex = $recordIndex - ($this->getLabelsPerPage() * $pageNumber);
$position = $this->getLabelPosition($pageIndex);
$pdf->StartTemplate();
$this->write($pdf, $data->get($recordIndex));
$template = $pdf->EndTemplate();
$pdf->printTemplate($template, $position[0], $position[1]);
if ($this->getLabelBorder()) {
$prevLineWidth = $pdf->GetLineWidth();
$borderThickness = $this->getLabelBorder();
$borderOffset = $borderThickness / 2;
$borderX = $position[0]- $borderOffset;
$borderY = $position[1] - $borderOffset;
$borderW = $this->getLabelWidth() + $borderThickness;
$borderH = $this->getLabelHeight() + $borderThickness;
$pdf->setLineWidth($borderThickness);
$pdf->Rect($borderX, $borderY, $borderW, $borderH);
$pdf->setLineWidth($prevLineWidth);
}
}
}
/**
* Returns each label's orientation as a string.
* 'L' = Landscape
* 'P' = Portrait
*
* @return string
*/
public final function getLabelOrientation() {
return ($this->getLabelWidth() >= $this->getLabelHeight()) ? 'L' : 'P';
}
/**
* Returns each label's printable area as an object.
*
* @return object [ 'x1'=>0.00, 'y1'=>0.00, 'x2'=>0.00, 'y2'=>0.00, 'w'=>0.00, 'h'=>0.00 ]
*/
public final function getLabelPrintableArea() {
return (object)[
'x1' => $this->getLabelMarginLeft(),
'y1' => $this->getLabelMarginTop(),
'x2' => $this->getLabelWidth() - $this->getLabelMarginRight(),
'y2' => $this->getLabelHeight() - $this->getLabelMarginBottom(),
'w' => $this->getLabelWidth() - $this->getLabelMarginLeft() - $this->getLabelMarginRight(),
'h' => $this->getLabelHeight() - $this->getLabelMarginTop() - $this->getLabelMarginBottom(),
];
}
/**
* Returns label index offset (skip positions)
*
* @return int
*/
public function getLabelIndexOffset() { return $this->indexOffset; }
/**
* Sets label index offset (skip positions)
*
* @param int $offset
*
*/
public function setLabelIndexOffset(int $offset) { $this->indexOffset = $offset; }
}
?>

View file

@ -0,0 +1,71 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
use App\Helpers\Helper;
use App\Models\Labels\RectangleSheet;
abstract class L7162 extends RectangleSheet
{
private const PAPER_FORMAT = 'A4';
private const PAPER_ORIENTATION = 'P';
/* Data in pt from Word Template */
private const COLUMN1_X = 13.25;
private const COLUMN2_X = 301.25;
private const ROW1_Y = 37.00;
private const ROW2_Y = 133.00;
private const LABEL_W = 280.80;
private const LABEL_H = 96.00;
private float $pageWidth;
private float $pageHeight;
private float $pageMarginLeft;
private float $pageMarginTop;
private float $columnSpacing;
private float $rowSpacing;
private float $labelWidth;
private float $labelHeight;
public function __construct() {
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 0);
$this->pageWidth = $paperSize->width;
$this->pageHeight = $paperSize->height;
$this->pageMarginLeft = Helper::convertUnit(self::COLUMN1_X, 'pt', $this->getUnit());
$this->pageMarginTop = Helper::convertUnit(self::ROW1_Y, 'pt', $this->getUnit());
$columnSpacingPt = self::COLUMN2_X - self::COLUMN1_X - self::LABEL_W;
$this->columnSpacing = Helper::convertUnit($columnSpacingPt, 'pt', $this->getUnit());
$rowSpacingPt = self::ROW2_Y - self::ROW1_Y - self::LABEL_H;
$this->rowSpacing = Helper::convertUnit($rowSpacingPt, 'pt', $this->getUnit());
$this->labelWidth = Helper::convertUnit(self::LABEL_W, 'pt', $this->getUnit());
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
}
public function getPageWidth() { return $this->pageWidth; }
public function getPageHeight() { return $this->pageHeight; }
public function getPageMarginTop() { return $this->pageMarginTop; }
public function getPageMarginBottom() { return $this->pageMarginTop; }
public function getPageMarginLeft() { return $this->pageMarginLeft; }
public function getPageMarginRight() { return $this->pageMarginLeft; }
public function getColumns() { return 2; }
public function getRows() { return 8; }
public function getLabelColumnSpacing() { return $this->columnSpacing; }
public function getLabelRowSpacing() { return $this->rowSpacing; }
public function getLabelWidth() { return $this->labelWidth; }
public function getLabelHeight() { return $this->labelHeight; }
public function getLabelBorder() { return 0; }
}
?>

View file

@ -0,0 +1,91 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
class L7162_Example extends L7162
{
private const BARCODE1D_SIZE = 6.0;
private const LOGO_MAX_WIDTH = 25.0;
private const LOGO_MARGIN = 1.4;
private const TITLE_SIZE = 4.0;
private const TITLE_MARGIN = 1.6;
private const LABEL_SIZE = 2.2;
private const LABEL_MARGIN = -0.5;
private const FIELD_SIZE = 4.8;
private const FIELD_MARGIN = 0.3;
public function getUnit() { return 'mm'; }
public function getLabelMarginTop() { return 1.0; }
public function getLabelMarginBottom() { return 0; }
public function getLabelMarginLeft() { return 1.0; }
public function getLabelMarginRight() { return 1.0; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return false; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return true; }
public function getSupportTitle() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$pa = $this->getLabelPrintableArea();
$x = $pa->x1;
$y = $pa->y1;
$w = $pa->w;
static::write1DBarcode(
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
$pa->x1, $pa->y2 - self::BARCODE1D_SIZE,
$pa->w, self::BARCODE1D_SIZE
);
if ($record->get('logo')) {
$logoMaxHeight = $pa->h - self::BARCODE1D_SIZE - self::LOGO_MARGIN;
$logoSize = static::writeImage(
$pdf, $record->get('logo'),
$x, $y,
self::LOGO_MAX_WIDTH, $logoMaxHeight,
'L', 'T', 300,
true, false, 0
);
$x += $logoSize[0] + self::LOGO_MARGIN;
$w -= ($logoSize[0] + self::LOGO_MARGIN);
}
if ($record->get('title')) {
static::writeText(
$pdf, $record->get('title'),
$x, $y,
'freesans', '', self::TITLE_SIZE, 'L',
$w, self::TITLE_SIZE, true, 0
);
$y += self::TITLE_SIZE + self::TITLE_MARGIN;
}
foreach ($record->get('fields') as $label => $value) {
static::writeText(
$pdf, $label,
$x, $y,
'freesans', '', self::LABEL_SIZE, 'L',
$w, self::LABEL_SIZE, true, 0
);
$y += self::LABEL_SIZE + self::LABEL_MARGIN;
static::writeText(
$pdf, $value,
$x, $y,
'freemono', 'B', self::FIELD_SIZE, 'L',
$w, self::FIELD_SIZE, true, 0, 0.3
);
$y += self::FIELD_SIZE + self::FIELD_MARGIN;
}
}
}
?>

View file

@ -0,0 +1,77 @@
<?php
namespace App\Models\Labels\Sheets\Avery;
class L7162_Example_QR extends L7162
{
private const BARCODE1D_SIZE = 6.0;
private const BARCODE2D_MARGIN = 1.4;
private const TITLE_SIZE = 4.0;
private const TITLE_MARGIN = 1.6;
private const LABEL_SIZE = 2.2;
private const LABEL_MARGIN = - 0.5;
private const FIELD_SIZE = 4.8;
private const FIELD_MARGIN = 0.3;
public function getUnit() { return 'mm'; }
public function getLabelMarginTop() { return 1.0; }
public function getLabelMarginBottom() { return 1.0; }
public function getLabelMarginLeft() { return 1.0; }
public function getLabelMarginRight() { return 1.0; }
public function getSupport1DBarcode() { return false; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 4; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$pa = $this->getLabelPrintableArea();
static::write2DBarcode(
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
$pa->x1, $pa->y1,
$pa->h, $pa->h
);
$x = $pa->x1 + $pa->h + self::BARCODE2D_MARGIN;
$y = $pa->y1;
$w = $pa->w - $pa->h - self::BARCODE2D_MARGIN;
if ($record->get('title')) {
static::writeText(
$pdf, $record->get('title'),
$x, $y,
'freesans', '', self::TITLE_SIZE, 'L',
$w, self::TITLE_SIZE, true, 0
);
$y += self::TITLE_SIZE + self::TITLE_MARGIN;
}
foreach ($record->get('fields') as $label => $value) {
static::writeText(
$pdf, $label,
$x, $y,
'freesans', '', self::LABEL_SIZE, 'L',
$w, self::LABEL_SIZE, true, 0
);
$y += self::LABEL_SIZE + self::LABEL_MARGIN;
static::writeText(
$pdf, $value,
$x, $y,
'freemono', 'B', self::FIELD_SIZE, 'L',
$w, self::FIELD_SIZE, true, 0, 0.3
);
$y += self::FIELD_SIZE + self::FIELD_MARGIN;
}
}
}
?>

View file

@ -0,0 +1,88 @@
<?php
namespace App\Presenters;
/**
* Class LabelPresenter
*/
class LabelPresenter extends Presenter
{
/**
* Json Column Layout for bootstrap table
* @return string
*/
public static function dataTableLayout()
{
$layout = [
[
'field' => 'radio',
'radio' => true,
'formatter' => 'labelRadioFormatter'
], [
'field' => 'name',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.name'),
'visible' => true,
], [
'field' => 'size',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('admin/settings/table.size'),
'visible' => true,
'formatter' => 'labelSizeFormatter'
], [
'field' => 'labels_per_page',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('admin/labels/table.labels_per_page'),
'visible' => true,
'formatter' => 'labelPerPageFormatter'
], [
'field' => 'support_fields',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/labels/table.support_fields'),
'visible' => true
], [
'field' => 'support_1d_barcode',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/labels/table.support_1d_barcode'),
'visible' => true,
'formatter' => 'trueFalseFormatter'
], [
'field' => 'support_2d_barcode',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/labels/table.support_2d_barcode'),
'visible' => true,
'formatter' => 'trueFalseFormatter'
], [
'field' => 'support_logo',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/labels/table.support_logo'),
'visible' => true,
'formatter' => 'trueFalseFormatter'
], [
'field' => 'support_title',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/labels/table.support_title'),
'visible' => true,
'formatter' => 'trueFalseFormatter'
]
];
return json_encode($layout);
}
}

243
app/View/Label.php Normal file
View file

@ -0,0 +1,243 @@
<?php
namespace App\View;
use App\Models\Labels\Label as LabelModel;
use App\Models\Labels\Sheet;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Traits\Macroable;
use TCPDF;
class Label implements View
{
use Macroable { __call as macroCall; }
protected const NAME = 'label';
/**
* A Collection of passed data.
*
* @var Collection
*/
protected $data;
public function __construct() {
$this->data = new Collection();
}
/**
* Render the PDF label.
*
* @param callable|null $callback
*/
public function render(callable $callback = null)
{
$settings = $this->data->get('settings');
$assets = $this->data->get('assets');
$offset = $this->data->get('offset');
// If disabled, pass to legacy view
if (!$settings->label2_enable) {
return view('hardware/labels')
->with('assets', $assets)
->with('settings', $settings)
->with('bulkedit', $this->data->get('bulkedit'))
->with('count', $this->data->get('count'));
}
$template = LabelModel::find($settings->label2_template);
$template->validate();
$pdf = new TCPDF(
$template->getOrientation(),
$template->getUnit(),
[ $template->getWidth(), $template->getHeight() ]
);
// Reset parameters
$pdf->SetPrintHeader(false);
$pdf->SetPrintFooter(false);
$pdf->SetAutoPageBreak(false);
$pdf->SetMargins(0, 0, null, true);
$pdf->SetCellMargins(0, 0, 0, 0);
$pdf->SetCellPaddings(0, 0, 0, 0);
$pdf->setCreator('Snipe-IT');
$pdf->SetSubject('Asset Labels');
$template->preparePDF($pdf);
// 'Label1=field1|Alt1=altfield1;Label2=field2;Alt1=altfield1|Label3=field3'
$fieldDefinitions = (new Collection())
->merge(explode(';', $settings->label2_fields))
->filter(function ($defString) {
return strpos($defString, '=') !== false;
})
->map(function ($defString) {
return (new Collection())
->merge(explode('|', $defString)) // ['Label1=field1', 'Alt1=altfield1']
->mapWithKeys(function ($altString) {
$parts = explode('=', $altString);
if (count($parts) != 2) throw new \Exception(var_export($parts, true));
return [ $parts[0] => $parts[1] ];
});
});
/*
$fieldDefinitions should now look like:
[
[
'Label1'=>'field1',
'Alt1'=>'altfield1'
],
[
'Label2'=>'field2'
],
[
'Alt1'=>'altfield1',
'Label3'=>'field3'
]
]
*/
// Prepare data
$data = $assets
->map(function ($asset) use ($template, $settings, $fieldDefinitions) {
$assetData = new Collection();
$assetData->put('id', $asset->id);
$assetData->put('tag', $asset->asset_tag);
if ($template->getSupportTitle()) {
$assetData->put('title', !empty($settings->label2_title) ?
str_ireplace(':company', $asset->company->name, $settings->label2_title) :
$settings->qr_text
);
}
if ($template->getSupportLogo()) {
$assetData->put('logo', $settings->label2_asset_logo ?
(
!empty($asset->company->image) ?
Storage::disk('public')->path('companies/'.e($asset->company->image)) :
null
) :
(
!empty($settings->label_logo) ?
Storage::disk('public')->path(''.e($settings->label_logo)) :
null
)
);
}
if ($template->getSupport1DBarcode()) {
$barcode1DType = $settings->label2_1d_type;
$barcode1DType = ($barcode1DType == 'default') ?
(($settings->alt_barcode_enabled) ? $settings->alt_barcode : null) :
$barcode1DType;
if ($barcode1DType) {
$assetData->put('barcode1d', (object)[
'type' => $barcode1DType,
'content' => $asset->asset_tag,
]);
}
}
if ($template->getSupport2DBarcode()) {
$barcode2DType = $settings->label2_2d_type;
$barcode2DType = ($barcode2DType == 'default') ?
(($settings->qr_code) ? $settings->barcode_type : null) :
$barcode2DType;
if ($barcode2DType) {
switch ($settings->label2_2d_target) {
case 'ht_tag': $barcode2DTarget = route('ht/assetTag', $asset->asset_tag); break;
case 'hardware_id':
default: $barcode2DTarget = route('hardware.show', $asset->id); break;
}
$assetData->put('barcode2d', (object)[
'type' => $barcode2DType,
'content' => $barcode2DTarget,
]);
}
}
$fields = $fieldDefinitions
->map(function ($group, $index) use ($asset) {
return $group->mapWithKeys(function ($definition, $label) use ($asset) {
$value = collect(explode('.', $definition))
->reduce(function ($carry, $chunk) {
return $carry ? $carry->{$chunk} : ${$carry};
}, $asset);
return [ $label => $value ];
});
})
->reduce(function ($carry, $group, $index) {
$values = $group
->filter(function ($value, $label) use ($carry) {
if (empty($value)) return false;
if ($carry->has($label)) return false;
return true;
})
->take(1);
return $carry->merge($values);
}, new Collection());
$assetData->put('fields', $fields->take($template->getSupportFields()));
return $assetData;
});
if ($template instanceof Sheet) {
$template->setLabelIndexOffset($offset ?? 0);
}
$template->writeAll($pdf, $data);
$filename = $assets->count() > 1 ? 'assets.pdf' : $assets->first()->asset_tag.'.pdf';
$pdf->Output($filename, 'I');
}
/**
* Add a piece of data.
*
* @param string|array $key
* @param mixed $value
* @return $this
*/
public function with($key, $value = null)
{
$this->data->put($key, $value);
return $this;
}
/**
* Get the array of view data.
*
* @return array
*/
public function getData()
{
return $this->data;
}
/**
* Get the name of the view.
*
* @return string
*/
public function name()
{
return $this->getName();
}
/**
* Get the name of the view.
*
* @return string
*/
public function getName()
{
return self::NAME;
}
}

View file

@ -68,6 +68,7 @@
"rollbar/rollbar-laravel": "^7.0",
"spatie/laravel-backup": "^6.16",
"tecnickcom/tc-lib-barcode": "^1.15",
"tecnickcom/tcpdf": "^6.5.0",
"unicodeveloper/laravel-password": "^1.0",
"watson/validating": "^6.1"
},

View file

@ -0,0 +1,51 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddLabel2Settings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('label2_enable')->default(false);
$table->string('label2_template')->nullable()->default('DefaultLabel');
$table->string('label2_title')->nullable()->default(null);
$table->boolean('label2_asset_logo')->default(false);
$table->string('label2_1d_type')->default('default');
$table->string('label2_2d_type')->default('default');
$table->string('label2_2d_target')->default('hardware_id');
$table->string('label2_fields')->default(
trans('admin/hardware/form.tag').'=asset_tag;'.
trans('admin/hardware/form.name').'=name;'.
trans('admin/hardware/form.serial').'=serial;'.
trans('admin/hardware/form.model').'=model.name;'
);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
if (Schema::hasColumn('settings', 'label2_enable')) $table->dropColumn('label2_enable');
if (Schema::hasColumn('settings', 'label2_template')) $table->dropColumn('label2_template');
if (Schema::hasColumn('settings', 'label2_title')) $table->dropColumn('label2_title');
if (Schema::hasColumn('settings', 'label2_asset_logo')) $table->dropColumn('label2_asset_logo');
if (Schema::hasColumn('settings', 'label2_1d_type')) $table->dropColumn('label2_1d_type');
if (Schema::hasColumn('settings', 'label2_2d_type')) $table->dropColumn('label2_2d_type');
if (Schema::hasColumn('settings', 'label2_2d_target')) $table->dropColumn('label2_2d_target');
if (Schema::hasColumn('settings', 'label2_fields')) $table->dropColumn('label2_fields');
});
}
}

View file

@ -0,0 +1,11 @@
<?php
return [
'invalid_return_count' => 'Invalid count returned from :name. Expected :expected, got :actual.',
'invalid_return_type' => 'Invalid type returned from :name. Expected :expected, got :actual.',
'invalid_return_value' => 'Invalid value returned from :name. Expected :expected, got :actual.',
'does_not_exist' => 'Label does not exist',
];

View file

@ -0,0 +1,12 @@
<?php
return [
'labels_per_page' => 'Labels',
'support_fields' => 'Fields',
'support_1d_barcode' => '1D',
'support_2d_barcode' => '2D',
'support_logo' => 'Logo',
'support_title' => 'Title',
];

View file

@ -320,4 +320,31 @@ return [
'setup_migration_create_user' => 'Next: Create User',
'ldap_settings_link' => 'LDAP Settings Page',
'slack_test' => 'Test <i class="fab fa-slack"></i> Integration',
'label2_enable' => 'New Label Engine',
'label2_enable_help' => 'Switch to the new label engine. <b>Note: You will need to save this setting before setting others.</b>',
'label2_template' => 'Template',
'label2_template_help' => 'Select which template to use for label generation',
'label2_title' => 'Title',
'label2_title_help' => 'The title to show on labels that support it',
'label2_title_help_phold' => 'The placeholder <code>&colon;company</code> will be replaced with the asset&apos;s company name',
'label2_asset_logo' => 'Use Asset Logo',
'label2_asset_logo_help' => 'Use the logo of the asset&apos;s assigned company, rather than the value at <code>:setting_name</code>',
'label2_1d_type' => '1D Barcode Type',
'label2_1d_type_help' => 'Format for 1D barcodes',
'label2_2d_type' => '2D Barcode Type',
'label2_2d_type_help' => 'Format for 2D barcodes',
'label2_2d_target' => '2D Barcode Target',
'label2_2d_target_help' => 'The URL the 2D barcode points to when scanned',
'label2_fields' => 'Fields Definition',
'label2_fields_help' => 'Fields to show on the label in the format <code>Label=asset_field</code>',
'label2_fields_help_semi' => 'Use <code>&semi;</code> to separate fields',
'label2_fields_help_pipe' => 'Use <code>|</code> to allow multiple options in each field. For example <code>Name=name|Nickname=_snipeit_my_custom_field_2</code> will use <code>name</code> if a value is set, otherwise it will use <code>_snipeit_my_custom_field_2</code>. This is useful to ensure field order',
'label2_fields_help_once' => 'Each field will only be selected once per label',
'help_asterisk_bold' => 'Text entered as <code>**text**</code> will be displayed as bold',
'help_blank_to_use' => 'Leave blank to use the value from <code>:setting_name</code>',
'help_default_will_use' => '<code>:default</code> will use the value from <code>:setting_name</code>',
'default' => 'Default',
'none' => 'None',
];

View file

@ -663,6 +663,25 @@
}
}
function labelPerPageFormatter(value, row, index, field) {
if (row) {
if (row.sheet_labels) { return 1; }
else { return row.sheet_info.labels_per_page; }
}
}
function labelRadioFormatter(value, row, index, field) {
if (row) {
return row.name == '{{ str_replace("\\", "\\\\", $snipeSettings->label2_template) }}';
}
}
function labelSizeFormatter(value, row) {
if (row) {
return row.width + ' x ' + row.height + ' ' + row.unit;
}
}
function cleanFloat(number) {
if(!number) { // in a JavaScript context, meaning, if it's null or zero or unset
return 0.0;

View file

@ -40,160 +40,363 @@
<div class="col-md-11 col-md-offset-1">
<div class="form-group {{ $errors->has('labels_per_page') ? 'error' : '' }}">
<!-- New Label Engine -->
<div class="form-group {{ $errors->has('label2_enable') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_per_page', trans('admin/settings/general.labels_per_page')) }}
{{ Form::label('label2_enable', trans('admin/settings/general.label2_enable')) }}
</div>
<div class="col-md-9">
{{ Form::text('labels_per_page', old('labels_per_page', $setting->labels_per_page), ['class' => 'form-control','style' => 'width: 100px;', 'aria-label'=>'labels_per_page']) }}
{!! $errors->first('labels_per_page', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{{ Form::checkbox('label2_enable', '1', old('label2_enable', $setting->label2_enable, [ 'class'=>'minimal', 'aria-label'=>'label2_enable' ])) }}
{{ trans('general.yes') }}
{!! $errors->first('label2_enable', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
<p class="help-block">{!! trans('admin/settings/general.label2_enable_help') !!}</p>
</div>
</div>
<div class="form-group {{ $errors->has('labels_fontsize') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_fontsize', trans('admin/settings/general.labels_fontsize')) }}
</div>
<div class="col-md-2 form-group">
<div class="input-group">
{{ Form::text('labels_fontsize', old('labels_fontsize', $setting->labels_fontsize), ['class' => 'form-control', 'aria-label'=>'labels_fontsize']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.text_pt') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_fontsize', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
@if ($setting->label2_enable)
<!-- New Settings -->
<div class="form-group {{ $errors->has('labels_width') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_width', trans('admin/settings/general.label_dimensions')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_width', old('labels_width', $setting->labels_width), ['class' => 'form-control', 'aria-label'=>'labels_width']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.width_w') }}</div>
<!-- Template -->
<div class="form-group {{ $errors->has('label2_template') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_template', trans('admin/settings/general.label2_template')) }}
</div>
<div class="col-md-9">
<table
data-click-to-select="true"
data-columns="{{ \App\Presenters\LabelPresenter::dataTableLayout() }}"
data-cookie="true"
data-cookie-id-table="label2TemplateTable"
data-id-table="label2TemplateTable"
data-pagination="true"
data-search="true"
data-select-item-name="label2_template"
data-id-field="name"
data-show-columns="true"
data-show-fullscreen="true"
data-show-refresh="true"
data-side-pagination="server"
data-sort-name="name"
data-sort-order="asc"
data-url="{{ route('api.labels.index') }}"
id="label2TemplateTable"
class="table table-striped snipe-table"
></table>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_height', old('labels_height', $setting->labels_height), ['class' => 'form-control', 'aria-label'=>'labels_height']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.height_h') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_width', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_height', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_display_sgutter') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_display_sgutter', trans('admin/settings/general.label_gutters')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_display_sgutter', old('labels_display_sgutter', $setting->labels_display_sgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_sgutter']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.horizontal') }}</div>
<!-- Title -->
<div class="form-group {{ $errors->has('label2_title') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_title', trans('admin/settings/general.label2_title')) }}
</div>
<div class="col-md-9">
{{ Form::text('label2_title', old('label2_title', $setting->label2_title), [ 'class'=>'form-control', 'placeholder'=>$setting->qr_text, 'aria-label'=>'label2_title' ]) }}
{!! $errors->first('label2_title', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
<p class="help-block">{!! trans('admin/settings/general.label2_title_help') !!}</p>
<p class="help-block">
{!! trans('admin/settings/general.label2_title_help_phold') !!}.<br />
{!! trans('admin/settings/general.help_asterisk_bold') !!}.<br />
{!!
trans('admin/settings/general.help_blank_to_use', [
'setting_name' => trans('admin/settings/general.barcodes').' &gt; '.trans('admin/settings/general.qr_text')
])
!!}
</p>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_display_bgutter', old('labels_display_bgutter', $setting->labels_display_bgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_bgutter']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.vertical') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_display_sgutter', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_display_bgutter', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_pmargin_top') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_pmargin_top', trans('admin/settings/general.page_padding')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group" style="margin-bottom: 15px;">
{{ Form::text('labels_pmargin_top', old('labels_pmargin_top', $setting->labels_pmargin_top), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_top']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.top') }}</div>
<!-- Use Asset Logo -->
<div class="form-group {{ $errors->has('label2_asset_logo') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_asset_logo', trans('admin/settings/general.label2_asset_logo')) }}
</div>
<div class="input-group">
{{ Form::text('labels_pmargin_right', old('labels_pmargin_right', $setting->labels_pmargin_right), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_right']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.right') }}</div>
<div class="col-md-9">
{{ Form::checkbox('label2_asset_logo', '1', old('label2_asset_logo', $setting->label2_asset_logo, [ 'class'=>'minimal', 'aria-label'=>'label2_asset_logo' ])) }}
{{ trans('general.yes') }}
{!! $errors->first('label2_asset_logo', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
<p class="help-block">{!! trans('admin/settings/general.label2_asset_logo_help', ['setting_name' => trans('admin/settings/general.brand').' &gt; '.trans('admin/settings/general.label_logo')]) !!}</p>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px; ">
<div class="input-group" style="margin-bottom: 15px;">
{{ Form::text('labels_pmargin_bottom', old('labels_pmargin_bottom', $setting->labels_pmargin_bottom), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_bottom']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.bottom') }}</div>
<!-- 1D Barcode Type -->
<div class="form-group{{ $errors->has('label2_1d_type') ? ' has-error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_1d_type', trans('admin/settings/general.label2_1d_type')) }}
</div>
<div class="input-group">
{{ Form::text('labels_pmargin_left', old('labels_pmargin_left', $setting->labels_pmargin_left), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_left']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.left') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_width', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_height', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ (($errors->has('labels_pageheight')) || $errors->has('labels_pagewidth')) ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_pagewidth', trans('admin/settings/general.page_dimensions')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_pagewidth', old('labels_pagewidth', $setting->labels_pagewidth), ['class' => 'form-control', 'aria-label'=>'labels_pagewidth']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.width_w') }}</div>
<div class="col-md-9">
@php
$select1DValues = [
'default' => trans('admin/settings/general.default').' [ '.$setting->alt_barcode.' ]',
'none' => trans('admin/settings/general.none'),
'C128' => 'C128',
'C39' => 'C39',
'EAN5' => 'EAN5',
'EAN13' => 'EAN13',
'UPCA' => 'UPCA',
'UPCE' => 'UPCE'
];
@endphp
{{ Form::select('label2_1d_type', $select1DValues, old('label2_1d_type', $setting->label2_1d_type), [ 'class'=>'select2 col-md-4', 'aria-label'=>'label2_1d_type' ]) }}
{!! $errors->first('label2_1d_type', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
<p class="help-block">
{{ trans('admin/settings/general.label2_1d_type_help') }}.
{!!
trans('admin/settings/general.help_default_will_use', [
'default' => trans('admin/settings/general.default'),
'setting_name' => trans('admin/settings/general.barcodes').' &gt; '.trans('admin/settings/general.alt_barcode_type'),
])
!!}
</p>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_pageheight', old('labels_pageheight', $setting->labels_pageheight), ['class' => 'form-control', 'aria-label'=>'labels_pageheight']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.height_h') }}</div>
<!-- 2D Barcode Type -->
<div class="form-group{{ $errors->has('label2_2d_type') ? ' has-error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_2d_type', trans('admin/settings/general.label2_2d_type')) }}
</div>
<div class="col-md-9">
@php
$select2DValues = [
'default' => trans('admin/settings/general.default').' [ '.$setting->barcode_type.' ]',
'none' => trans('admin/settings/general.none'),
'QRCODE' => 'QRCODE',
'DATAMATRIX' => 'DATAMATRIX',
'PDF417' => 'PDF417',
];
@endphp
{{ Form::select('label2_2d_type', $select2DValues, old('label2_2d_type', $setting->label2_2d_type), [ 'class'=>'select2 col-md-4', 'aria-label'=>'label2_2d_type' ]) }}
{!! $errors->first('label2_2d_type', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
<p class="help-block">
{{ trans('admin/settings/general.label2_2d_type_help', ['current' => $setting->barcode_type]) }}.
{!!
trans('admin/settings/general.help_default_will_use', [
'default' => trans('admin/settings/general.default'),
'setting_name' => trans('admin/settings/general.barcodes').' &gt; '.trans('admin/settings/general.barcode_type'),
])
!!}
</p>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_pagewidth', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_pageheight', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
<!-- 2D Barcode Target -->
<div class="form-group{{ $errors->has('label2_2d_target') ? ' has-error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_2d_target', trans('admin/settings/general.label2_2d_target')) }}
</div>
<div class="col-md-9">
{{ Form::select('label2_2d_target', ['hardware_id'=>'/hardware/{id} ('.trans('admin/settings/general.default').')', 'ht_tag'=>'/ht/{asset_tag}'], old('label2_2d_target', $setting->label2_2d_target), [ 'class'=>'select2 col-md-4', 'aria-label'=>'label2_2d_target' ]) }}
{!! $errors->first('label2_2d_target', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
<p class="help-block">{!! trans('admin/settings/general.label2_2d_target_help') !!}</p>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-3">
{{ Form::label('labels_display', trans('admin/settings/general.label_fields')) }}
<!-- Fields -->
<div class="form-group {{ $errors->has('label2_fields') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }}
</div>
<div class="col-md-9">
{{ Form::text('label2_fields', old('label2_fields', $setting->label2_fields), [ 'class'=>'form-control', 'aria-label'=>'label2_fields' ]) }}
{!! $errors->first('label2_fields', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
<p class="help-block">{!! trans('admin/settings/general.label2_fields_help') !!}</p>
<p class="help-block">
{!! trans('admin/settings/general.label2_fields_help_semi') !!}.<br />
{!! trans('admin/settings/general.label2_fields_help_pipe') !!}.<br />
{!! trans('admin/settings/general.label2_fields_help_once') !!}.
</p>
</div>
</div>
<div class="col-md-9">
<div class="checkbox">
<label for="labels_display_name">
{{ Form::checkbox('labels_display_name', '1', old('labels_display_name', $setting->labels_display_name),['class' => 'minimal', 'aria-label'=>'labels_display_name']) }}
{{ trans('admin/hardware/form.name') }}
</label>
<label for="labels_display_serial">
{{ Form::checkbox('labels_display_serial', '1', old('labels_display_serial', $setting->labels_display_serial),['class' => 'minimal', 'aria-label'=>'labels_display_serial']) }}
{{ trans('admin/hardware/form.serial') }}
</label>
<label for="labels_display_tag">
{{ Form::checkbox('labels_display_tag', '1', old('labels_display_tag', $setting->labels_display_tag),['class' => 'minimal', 'aria-label'=>'labels_display_tag']) }}
{{ trans('admin/hardware/form.tag') }}
</label>
<label for="labels_display_model">
{{ Form::checkbox('labels_display_model', '1', old('labels_display_model', $setting->labels_display_model),['class' => 'minimal', 'aria-label'=>'labels_display_model']) }}
{{ trans('admin/hardware/form.model') }}
</label>
<label for="labels_display_company_name">
{{ Form::checkbox('labels_display_company_name', '1', old('labels_display_company_name', $setting->labels_display_company_name),['class' => 'minimal', 'aria-label'=>'labels_display_company_name']) }}
{{ trans('admin/companies/table.name') }}
</label>
</div> <!--/.CHECKBOX-->
</div> <!--/.col-md-9-->
</div> <!--/.form-group-->
@include('partials.bootstrap-table')
@else
<!-- Hidden version of new settings -->
{{ Form::hidden('label2_template', old('label2_template', $setting->label2_template)) }}
{{ Form::hidden('label2_title', old('label2_title', $setting->label2_title)) }}
{{ Form::hidden('label2_asset_logo', old('label2_asset_logo', $setting->label2_asset_logo)) }}
{{ Form::hidden('label2_1d_type', old('label2_1d_type', $setting->label2_1d_type)) }}
{{ Form::hidden('label2_2d_type', old('label2_2d_type', $setting->label2_2d_type)) }}
{{ Form::hidden('label2_2d_target', old('label2_2d_target', $setting->label2_2d_target)) }}
{{ Form::hidden('label2_fields', old('label2_fields', $setting->label2_fields)) }}
@endif
@if ($setting->label2_enable && ($setting->label2_template != 'DefaultLabel'))
<!-- Hidden version of legacy settings -->
{{ Form::hidden('labels_per_page', old('labels_per_page', $setting->labels_per_page)) }}
{{ Form::hidden('labels_fontsize', old('labels_fontsize', $setting->labels_fontsize)) }}
{{ Form::hidden('labels_width', old('labels_width', $setting->labels_width)) }}
{{ Form::hidden('labels_height', old('labels_height', $setting->labels_height)) }}
{{ Form::hidden('labels_display_sgutter', old('labels_display_sgutter', $setting->labels_display_sgutter)) }}
{{ Form::hidden('labels_display_bgutter', old('labels_display_bgutter', $setting->labels_display_bgutter)) }}
{{ Form::hidden('labels_pmargin_top', old('labels_pmargin_top', $setting->labels_pmargin_top)) }}
{{ Form::hidden('labels_pmargin_bottom', old('labels_pmargin_bottom', $setting->labels_pmargin_bottom)) }}
{{ Form::hidden('labels_pmargin_left', old('labels_pmargin_left', $setting->labels_pmargin_left)) }}
{{ Form::hidden('labels_pmargin_right', old('labels_pmargin_right', $setting->labels_pmargin_right)) }}
{{ Form::hidden('labels_pagewidth', old('labels_pagewidth', $setting->labels_pagewidth)) }}
{{ Form::hidden('labels_pageheight', old('labels_pageheight', $setting->labels_pageheight)) }}
{{ Form::hidden('labels_display_name', old('labels_display_name', $setting->labels_display_name)) }}
{{ Form::hidden('labels_display_serial', old('labels_display_serial', $setting->labels_display_serial)) }}
{{ Form::hidden('labels_display_tag', old('labels_display_tag', $setting->labels_display_tag)) }}
{{ Form::hidden('labels_display_model', old('labels_display_model', $setting->labels_display_model)) }}
{{ Form::hidden('labels_display_company_name', old('labels_display_company_name', $setting->labels_display_company_name)) }}
@else
<!-- Legacy settings -->
<div class="form-group {{ $errors->has('labels_per_page') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_per_page', trans('admin/settings/general.labels_per_page')) }}
</div>
<div class="col-md-9">
{{ Form::text('labels_per_page', old('labels_per_page', $setting->labels_per_page), ['class' => 'form-control','style' => 'width: 100px;', 'aria-label'=>'labels_per_page']) }}
{!! $errors->first('labels_per_page', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_fontsize') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_fontsize', trans('admin/settings/general.labels_fontsize')) }}
</div>
<div class="col-md-2 form-group">
<div class="input-group">
{{ Form::text('labels_fontsize', old('labels_fontsize', $setting->labels_fontsize), ['class' => 'form-control', 'aria-label'=>'labels_fontsize']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.text_pt') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_fontsize', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_width') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_width', trans('admin/settings/general.label_dimensions')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_width', old('labels_width', $setting->labels_width), ['class' => 'form-control', 'aria-label'=>'labels_width']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.width_w') }}</div>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_height', old('labels_height', $setting->labels_height), ['class' => 'form-control', 'aria-label'=>'labels_height']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.height_h') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_width', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_height', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_display_sgutter') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_display_sgutter', trans('admin/settings/general.label_gutters')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_display_sgutter', old('labels_display_sgutter', $setting->labels_display_sgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_sgutter']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.horizontal') }}</div>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_display_bgutter', old('labels_display_bgutter', $setting->labels_display_bgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_bgutter']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.vertical') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_display_sgutter', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_display_bgutter', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ $errors->has('labels_pmargin_top') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_pmargin_top', trans('admin/settings/general.page_padding')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group" style="margin-bottom: 15px;">
{{ Form::text('labels_pmargin_top', old('labels_pmargin_top', $setting->labels_pmargin_top), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_top']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.top') }}</div>
</div>
<div class="input-group">
{{ Form::text('labels_pmargin_right', old('labels_pmargin_right', $setting->labels_pmargin_right), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_right']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.right') }}</div>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px; ">
<div class="input-group" style="margin-bottom: 15px;">
{{ Form::text('labels_pmargin_bottom', old('labels_pmargin_bottom', $setting->labels_pmargin_bottom), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_bottom']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.bottom') }}</div>
</div>
<div class="input-group">
{{ Form::text('labels_pmargin_left', old('labels_pmargin_left', $setting->labels_pmargin_left), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_left']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.left') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_width', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_height', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group {{ (($errors->has('labels_pageheight')) || $errors->has('labels_pagewidth')) ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('labels_pagewidth', trans('admin/settings/general.page_dimensions')) }}
</div>
<div class="col-md-3 form-group">
<div class="input-group">
{{ Form::text('labels_pagewidth', old('labels_pagewidth', $setting->labels_pagewidth), ['class' => 'form-control', 'aria-label'=>'labels_pagewidth']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.width_w') }}</div>
</div>
</div>
<div class="col-md-3 form-group" style="margin-left: 10px">
<div class="input-group">
{{ Form::text('labels_pageheight', old('labels_pageheight', $setting->labels_pageheight), ['class' => 'form-control', 'aria-label'=>'labels_pageheight']) }}
<div class="input-group-addon">{{ trans('admin/settings/general.height_h') }}</div>
</div>
</div>
<div class="col-md-9 col-md-offset-3">
{!! $errors->first('labels_pagewidth', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
{!! $errors->first('labels_pageheight', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
</div>
</div>
<div class="form-group">
<div class="col-md-3">
{{ Form::label('labels_display', trans('admin/settings/general.label_fields')) }}
</div>
<div class="col-md-9">
<div class="checkbox">
<label for="labels_display_name">
{{ Form::checkbox('labels_display_name', '1', old('labels_display_name', $setting->labels_display_name),['class' => 'minimal', 'aria-label'=>'labels_display_name']) }}
{{ trans('admin/hardware/form.name') }}
</label>
<label for="labels_display_serial">
{{ Form::checkbox('labels_display_serial', '1', old('labels_display_serial', $setting->labels_display_serial),['class' => 'minimal', 'aria-label'=>'labels_display_serial']) }}
{{ trans('admin/hardware/form.serial') }}
</label>
<label for="labels_display_tag">
{{ Form::checkbox('labels_display_tag', '1', old('labels_display_tag', $setting->labels_display_tag),['class' => 'minimal', 'aria-label'=>'labels_display_tag']) }}
{{ trans('admin/hardware/form.tag') }}
</label>
<label for="labels_display_model">
{{ Form::checkbox('labels_display_model', '1', old('labels_display_model', $setting->labels_display_model),['class' => 'minimal', 'aria-label'=>'labels_display_model']) }}
{{ trans('admin/hardware/form.model') }}
</label>
<label for="labels_display_company_name">
{{ Form::checkbox('labels_display_company_name', '1', old('labels_display_company_name', $setting->labels_display_company_name),['class' => 'minimal', 'aria-label'=>'labels_display_company_name']) }}
{{ trans('admin/companies/table.name') }}
</label>
</div> <!--/.CHECKBOX-->
</div> <!--/.col-md-9-->
</div> <!--/.form-group-->
@endif
</div>

View file

@ -611,6 +611,16 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi
); // end imports API routes
/**
* Labels API routes
*/
Route::group(['prefix' => 'labels'], function() {
Route::get('{name}', [ Api\LabelsController::class, 'show'])
->where('name', '.*')
->name('api.labels.show');
Route::get('', [ Api\LabelsController::class, 'index'])
->name('api.labels.index');
});
/**
* Licenses API routes

View file

@ -181,4 +181,8 @@ Route::resource('hardware',
'middleware' => ['auth'],
'parameters' => ['asset' => 'asset_id'
],
]);
]);
Route::get('ht/{any?}',
[AssetsController::class, 'getAssetByTag']
)->where('any', '.*')->name('ht/assetTag');