diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php index f0f2f5e13e..b4c8f5605d 100644 --- a/app/Helpers/Helper.php +++ b/app/Helpers/Helper.php @@ -1220,6 +1220,47 @@ class Helper return true; \Log::debug('app locked!'); } + + return false; + } + + + /** + * Conversion between units of measurement + * + * @author Grant Le Roux + * @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 + * @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'); return false; } diff --git a/app/Http/Controllers/Api/LabelsController.php b/app/Http/Controllers/Api/LabelsController.php new file mode 100644 index 0000000000..6576ec0373 --- /dev/null +++ b/app/Http/Controllers/Api/LabelsController.php @@ -0,0 +1,71 @@ + + * @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 + * @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); + } + +} diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php index 74b3dffa1c..e699779a34 100755 --- a/app/Http/Controllers/Assets/AssetsController.php +++ b/app/Http/Controllers/Assets/AssetsController.php @@ -14,6 +14,7 @@ use App\Models\Location; use App\Models\Setting; use App\Models\Statuslabel; use App\Models\User; +use App\View\Label; use Auth; use Carbon\Carbon; use DB; @@ -453,11 +454,12 @@ class AssetsController extends Controller * @since [v3.0] * @return Redirect */ - public function getAssetByTag(Request $request) + public function getAssetByTag(Request $request, $tag=null) { + $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); @@ -554,9 +556,11 @@ class AssetsController extends Controller $asset = Asset::find($assetId); $this->authorize('view', $asset); - return view('hardware/labels') - ->with('assets', Asset::find($asset)) + return (new Label()) + ->with('assets', collect([ $asset ])) ->with('settings', Setting::getSettings()) + ->with('template', request()->get('template')) + ->with('offset', request()->get('offset')) ->with('bulkedit', false) ->with('count', 0); } diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php index 80d17f1b30..8419098936 100644 --- a/app/Http/Controllers/Assets/BulkAssetsController.php +++ b/app/Http/Controllers/Assets/BulkAssetsController.php @@ -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; @@ -45,7 +46,7 @@ class BulkAssetsController extends Controller switch ($request->input('bulk_actions')) { case 'labels': $this->authorize('view', Asset::class); - return view('hardware/labels') + return (new Label) ->with('assets', Asset::find($asset_ids)) ->with('settings', Setting::getSettings()) ->with('bulkedit', true) diff --git a/app/Http/Controllers/LabelsController.php b/app/Http/Controllers/LabelsController.php new file mode 100755 index 0000000000..97608cb5e2 --- /dev/null +++ b/app/Http/Controllers/LabelsController.php @@ -0,0 +1,77 @@ + + * @param string $labelName + * @return \Illuminate\Contracts\View\View + */ + public function show(string $labelName) + { + $labelName = str_replace('/', '\\', $labelName); + $template = Label::find($labelName); + + $exampleAsset = new Asset(); + + $exampleAsset->id = 999999; + $exampleAsset->name = 'AST-AB-CD-1234'; + $exampleAsset->asset_tag = 'TCA-00001'; + $exampleAsset->serial = 'SN9876543210'; + + $exampleAsset->company = new Company(); + $exampleAsset->company->id = 999999; + $exampleAsset->company->name = 'Test Company Limited'; + $exampleAsset->company->image = 'company-image-test.png'; + + $exampleAsset->assignedto = new User(); + $exampleAsset->assignedto->id = 999999; + $exampleAsset->assignedto->first_name = 'Test'; + $exampleAsset->assignedto->last_name = 'Person'; + $exampleAsset->assignedto->username = 'Test.Person'; + $exampleAsset->assignedto->employee_num = '0123456789'; + + $exampleAsset->model = new AssetModel(); + $exampleAsset->model->id = 999999; + $exampleAsset->model->name = 'Test Model'; + $exampleAsset->model->model_number = 'MDL5678'; + $exampleAsset->model->manufacturer = new Manufacturer(); + $exampleAsset->model->manufacturer->id = 999999; + $exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.'; + $exampleAsset->model->category = new Category(); + $exampleAsset->model->category->id = 999999; + $exampleAsset->model->category->name = 'Test Category'; + + $settings = Setting::getSettings(); + if (request()->has('settings')) { + $overrides = request()->get('settings'); + foreach ($overrides as $key => $value) { + $settings->$key = $value; + } + } + + return (new LabelView()) + ->with('assets', collect([$exampleAsset])) + ->with('settings', $settings) + ->with('template', $template) + ->with('bulkedit', false) + ->with('count', 0); + + return redirect()->route('home')->with('error', trans('admin/labels/message.does_not_exist')); + } +} diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 87fc98c197..f8c0638422 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -827,6 +827,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'); diff --git a/app/Http/Transformers/LabelsTransformer.php b/app/Http/Transformers/LabelsTransformer.php new file mode 100644 index 0000000000..8e0e8ca44e --- /dev/null +++ b/app/Http/Transformers/LabelsTransformer.php @@ -0,0 +1,71 @@ +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_asset_tag' => $label->getSupportAssetTag(), + '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; + } +} diff --git a/app/Models/Labels/DefaultLabel.php b/app/Models/Labels/DefaultLabel.php new file mode 100644 index 0000000000..3a7dd5af1c --- /dev/null +++ b/app/Models/Labels/DefaultLabel.php @@ -0,0 +1,224 @@ +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 getSupportAssetTag() { return false; } + 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 = $record->get('asset'); + $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++; + } + } + + } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Field.php b/app/Models/Labels/Field.php new file mode 100644 index 0000000000..b264c7ac29 --- /dev/null +++ b/app/Models/Labels/Field.php @@ -0,0 +1,39 @@ +options; } + public function setOptions($options) { + $tempCollect = collect($options); + if (!$tempCollect->contains(fn($o) => !is_subclass_of($o, FieldOption::class))) { + $this->options = $options; + } + } + + public function toArray(Asset $asset) { return Field::makeArray($this, $asset); } + + /* Statics */ + + public static function makeArray(Field $field, Asset $asset) { + return $field->getOptions() + ->map(fn($option) => $option->toArray($asset)) + ->filter(fn($result) => $result['value'] != null); + } + + public static function makeString(Field $option) { + return implode('|', $option->getOptions()); + } + + public static function fromString(string $theString) { + $field = new Field(); + $field->options = collect(explode('|', $theString)) + ->filter(fn($optionString) => !empty($optionString)) + ->map(fn($optionString) => FieldOption::fromString($optionString)); + return $field; + } +} \ No newline at end of file diff --git a/app/Models/Labels/FieldOption.php b/app/Models/Labels/FieldOption.php new file mode 100644 index 0000000000..76427accaf --- /dev/null +++ b/app/Models/Labels/FieldOption.php @@ -0,0 +1,49 @@ +label; } + + protected string $dataSource; + public function getDataSource() { return $this->dataSource; } + + public function getValue(Asset $asset) { + $dataPath = collect(explode('.', $this->dataSource)); + return $dataPath->reduce(function ($myValue, $path) { + try { return $myValue ? $myValue->{$path} : ${$myValue}; } + catch (\Exception $e) { return $myValue; } + }, $asset); + } + + public function toArray(Asset $asset=null) { return FieldOption::makeArray($this, $asset); } + public function toString() { return FieldOption::makeString($this); } + + /* Statics */ + + public static function makeArray(FieldOption $option, Asset $asset=null) { + return [ + 'label' => $option->getLabel(), + 'dataSource' => $option->getDataSource(), + 'value' => $asset ? $option->getValue($asset) : null + ]; + } + + public static function makeString(FieldOption $option) { + return $option->getLabel() . '=' . $option->getDataSource(); + } + + public static function fromString(string $theString) { + $parts = explode('=', $theString); + if (count($parts) == 2) { + $option = new FieldOption(); + $option->label = $parts[0]; + $option->dataSource = $parts[1]; + return $option; + } + } +} \ No newline at end of file diff --git a/app/Models/Labels/Label.php b/app/Models/Labels/Label.php new file mode 100644 index 0000000000..ff759ac544 --- /dev/null +++ b/app/Models/Labels/Label.php @@ -0,0 +1,598 @@ +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(strtoupper($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(); + }); + } + + + +} diff --git a/app/Models/Labels/RectangleSheet.php b/app/Models/Labels/RectangleSheet.php new file mode 100644 index 0000000000..f5fe5cda98 --- /dev/null +++ b/app/Models/Labels/RectangleSheet.php @@ -0,0 +1,48 @@ +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 ]; + } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheet.php b/app/Models/Labels/Sheet.php new file mode 100644 index 0000000000..83e363591a --- /dev/null +++ b/app/Models/Labels/Sheet.php @@ -0,0 +1,209 @@ +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; } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/L7162.php b/app/Models/Labels/Sheets/Avery/L7162.php new file mode 100644 index 0000000000..e1097db9b2 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L7162.php @@ -0,0 +1,71 @@ +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; } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/L7162_A.php b/app/Models/Labels/Sheets/Avery/L7162_A.php new file mode 100644 index 0000000000..0b3312ba7c --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L7162_A.php @@ -0,0 +1,100 @@ +getLabelPrintableArea(); + + $usableWidth = $pa->w; + $usableHeight = $pa->h; + $currentX = $pa->x1; + $currentY = $pa->y1; + $titleShiftX = 0; + + $barcodeSize = $pa->h - self::TAG_SIZE; + + if ($record->has('barcode2d')) { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'C', + $barcodeSize, self::TAG_SIZE, true, 0 + ); + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $pa->x1, $pa->y1, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } else { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y1, + 'freemono', 'b', self::TITLE_SIZE, 'L', + $barcodeSize, self::TITLE_SIZE, true, 0 + ); + $titleShiftX = $barcodeSize; + } + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX + $titleShiftX, $currentY, + 'freesans', '', self::TITLE_SIZE, 'L', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.3 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + } +} + + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/L7162_B.php b/app/Models/Labels/Sheets/Avery/L7162_B.php new file mode 100644 index 0000000000..268754e04f --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L7162_B.php @@ -0,0 +1,103 @@ +getLabelPrintableArea(); + + $usableWidth = $pa->w; + $usableHeight = $pa->h; + $currentX = $pa->x1; + $currentY = $pa->y1; + + if ($record->has('barcode1d')) { + static::write1DBarcode( + $pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type, + $pa->x1, $pa->y2 - self::BARCODE_SIZE, + $usableWidth, self::BARCODE_SIZE + ); + $usableHeight -= self::BARCODE_SIZE + self::BARCODE_MARGIN; + } + + if ($record->has('logo')) { + $logoSize = static::writeImage( + $pdf, $record->get('logo'), + $pa->x1, $pa->y1, + self::LOGO_MAX_WIDTH, $usableHeight, + 'L', 'T', 300, true, false, 0.1 + ); + $currentX += $logoSize[0] + self::LOGO_MARGIN; + $usableWidth -= $logoSize[0] + self::LOGO_MARGIN; + } + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX, $currentY, + 'freesans', '', self::TITLE_SIZE, 'L', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.3 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + static::writeText( + $pdf, $record->get('tag'), + $currentX, $pa->y2 - self::BARCODE_SIZE - self::BARCODE_MARGIN - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'R', + $usableWidth, self::TAG_SIZE, true, 0, 0.3 + ); + + } +} + + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/L7163.php b/app/Models/Labels/Sheets/Avery/L7163.php new file mode 100644 index 0000000000..f143260336 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L7163.php @@ -0,0 +1,71 @@ +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 7; } + + 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; } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/L7163_A.php b/app/Models/Labels/Sheets/Avery/L7163_A.php new file mode 100644 index 0000000000..6dc33f64dd --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/L7163_A.php @@ -0,0 +1,98 @@ +getLabelPrintableArea(); + + $usableWidth = $pa->w; + $usableHeight = $pa->h; + $currentX = $pa->x1; + $currentY = $pa->y1; + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX, $currentY, + 'freesans', '', self::TITLE_SIZE, 'C', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + $barcodeSize = $pa->h - self::TITLE_SIZE - self::TITLE_MARGIN - self::TAG_SIZE; + + if ($record->has('barcode2d')) { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'C', + $barcodeSize, self::TAG_SIZE, true, 0 + ); + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $pa->x1, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } else { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'R', + $usableWidth, self::TAG_SIZE, true, 0 + ); + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.5 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + } +} + + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/_5267.php b/app/Models/Labels/Sheets/Avery/_5267.php new file mode 100644 index 0000000000..f5f2f13557 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/_5267.php @@ -0,0 +1,71 @@ +getUnit(), 2); + $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 4; } + public function getRows() { return 20; } + + 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; } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/_5267_A.php b/app/Models/Labels/Sheets/Avery/_5267_A.php new file mode 100644 index 0000000000..efe0855d5e --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/_5267_A.php @@ -0,0 +1,68 @@ +getLabelPrintableArea(); + + if ($record->has('barcode1d')) { + static::write1DBarcode( + $pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type, + $pa->x1, $pa->y2 - self::BARCODE_SIZE, + $pa->w, self::BARCODE_SIZE + ); + } + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $pa->x1, $pa->y1, + 'freesans', '', self::TITLE_SIZE, 'L', + $pa->w, self::TITLE_SIZE, true, 0 + ); + } + + $fieldY = $pa->y2 - self::BARCODE_SIZE - self::BARCODE_MARGIN - self::FIELD_SIZE; + if ($record->has('fields')) { + if ($record->get('fields')->count() >= 1) { + $field = $record->get('fields')->first(); + static::writeText( + $pdf, $field['value'], + $pa->x1, $fieldY, + 'freemono', 'B', self::FIELD_SIZE, 'C', + $pa->w, self::FIELD_SIZE, true, 0, 0.01 + ); + } + } + + } +} + + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/_5520.php b/app/Models/Labels/Sheets/Avery/_5520.php new file mode 100644 index 0000000000..00cb0e0687 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/_5520.php @@ -0,0 +1,71 @@ +getUnit(), 2); + $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 3; } + public function getRows() { return 10; } + + 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; } +} + +?> \ No newline at end of file diff --git a/app/Models/Labels/Sheets/Avery/_5520_A.php b/app/Models/Labels/Sheets/Avery/_5520_A.php new file mode 100644 index 0000000000..199566d248 --- /dev/null +++ b/app/Models/Labels/Sheets/Avery/_5520_A.php @@ -0,0 +1,85 @@ +getLabelPrintableArea(); + + $currentX = $pa->x1; + $currentY = $pa->y1; + $usableWidth = $pa->w; + $usableHeight = $pa->h; + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $pa->x1, $pa->y1, + 'freesans', '', self::TITLE_SIZE, 'C', + $pa->w, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + $usableHeight -= self::TITLE_SIZE + self::TITLE_MARGIN; + } + + $barcodeSize = $usableHeight; + if ($record->has('barcode2d')) { + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $currentX, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.01 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + + } +} + + +?> \ No newline at end of file diff --git a/app/Models/Labels/Tapes/Brother/TZe_12mm.php b/app/Models/Labels/Tapes/Brother/TZe_12mm.php new file mode 100644 index 0000000000..f9196847ce --- /dev/null +++ b/app/Models/Labels/Tapes/Brother/TZe_12mm.php @@ -0,0 +1,19 @@ +getUnit()); } + public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); } + public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());} + public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); } + public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); } +} \ No newline at end of file diff --git a/app/Models/Labels/Tapes/Brother/TZe_12mm_A.php b/app/Models/Labels/Tapes/Brother/TZe_12mm_A.php new file mode 100644 index 0000000000..f89cfc5d47 --- /dev/null +++ b/app/Models/Labels/Tapes/Brother/TZe_12mm_A.php @@ -0,0 +1,56 @@ +getPrintableArea(); + + if ($record->has('barcode1d')) { + static::write1DBarcode( + $pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type, + $pa->x1, $pa->y1, $pa->w, self::BARCODE_SIZE + ); + } + + $currentY = $pa->y1 + self::BARCODE_SIZE + self::BARCODE_MARGIN; + $usableHeight = $pa->h - self::BARCODE_SIZE - self::BARCODE_MARGIN; + $fontSize = $usableHeight + self::TEXT_SIZE_MOD; + + $tagWidth = $pa->w / 3; + $fieldWidth = $pa->w / 3 * 2; + + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $currentY, + 'freemono', 'b', $fontSize, 'L', + $tagWidth, $usableHeight, true, 0, 0 + ); + + if ($record->get('fields')->count() >= 1) { + static::writeText( + $pdf, $record->get('fields')->values()->get(0)['value'], + $pa->x1 + ($tagWidth), $currentY, + 'freemono', 'b', $fontSize, 'R', + $fieldWidth, $usableHeight, true, 0, 0 + ); + } + + } +} \ No newline at end of file diff --git a/app/Models/Labels/Tapes/Brother/TZe_24mm.php b/app/Models/Labels/Tapes/Brother/TZe_24mm.php new file mode 100644 index 0000000000..3c67bc1614 --- /dev/null +++ b/app/Models/Labels/Tapes/Brother/TZe_24mm.php @@ -0,0 +1,19 @@ +getUnit()); } + public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); } + public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());} + public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); } + public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); } +} \ No newline at end of file diff --git a/app/Models/Labels/Tapes/Brother/TZe_24mm_A.php b/app/Models/Labels/Tapes/Brother/TZe_24mm_A.php new file mode 100644 index 0000000000..ea4c6c9dfb --- /dev/null +++ b/app/Models/Labels/Tapes/Brother/TZe_24mm_A.php @@ -0,0 +1,87 @@ +getPrintableArea(); + + $currentX = $pa->x1; + $currentY = $pa->y1; + $usableWidth = $pa->w; + + $barcodeSize = $pa->h - self::TAG_SIZE; + + if ($record->has('barcode2d')) { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'C', + $barcodeSize, self::TAG_SIZE, true, 0 + ); + static::write2DBarcode( + $pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type, + $currentX, $currentY, + $barcodeSize, $barcodeSize + ); + $currentX += $barcodeSize + self::BARCODE_MARGIN; + $usableWidth -= $barcodeSize + self::BARCODE_MARGIN; + } else { + static::writeText( + $pdf, $record->get('tag'), + $pa->x1, $pa->y2 - self::TAG_SIZE, + 'freemono', 'b', self::TAG_SIZE, 'R', + $usableWidth, self::TAG_SIZE, true, 0 + ); + } + + if ($record->has('title')) { + static::writeText( + $pdf, $record->get('title'), + $currentX, $currentY, + 'freesans', '', self::TITLE_SIZE, 'L', + $usableWidth, self::TITLE_SIZE, true, 0 + ); + $currentY += self::TITLE_SIZE + self::TITLE_MARGIN; + } + + foreach ($record->get('fields') as $field) { + static::writeText( + $pdf, $field['label'], + $currentX, $currentY, + 'freesans', '', self::LABEL_SIZE, 'L', + $usableWidth, self::LABEL_SIZE, true, 0, 0 + ); + $currentY += self::LABEL_SIZE + self::LABEL_MARGIN; + + static::writeText( + $pdf, $field['value'], + $currentX, $currentY, + 'freemono', 'B', self::FIELD_SIZE, 'L', + $usableWidth, self::FIELD_SIZE, true, 0, 0.3 + ); + $currentY += self::FIELD_SIZE + self::FIELD_MARGIN; + } + } +} \ No newline at end of file diff --git a/app/Presenters/LabelPresenter.php b/app/Presenters/LabelPresenter.php new file mode 100644 index 0000000000..5ff95d2c4d --- /dev/null +++ b/app/Presenters/LabelPresenter.php @@ -0,0 +1,96 @@ + '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_asset_tag', + 'searchable' => false, + 'sortable' => true, + 'switchable' => true, + 'title' => trans('admin/labels/table.support_asset_tag'), + 'visible' => true, + 'formatter' => 'trueFalseFormatter' + ], [ + '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); + } +} diff --git a/app/View/Label.php b/app/View/Label.php new file mode 100644 index 0000000000..de955afffa --- /dev/null +++ b/app/View/Label.php @@ -0,0 +1,211 @@ +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'); + $template = $this->data->get('template'); + + // If disabled, pass to legacy view + if ((!$settings->label2_enable) && (!$template)) { + return view('hardware/labels') + ->with('assets', $assets) + ->with('settings', $settings) + ->with('bulkedit', $this->data->get('bulkedit')) + ->with('count', $this->data->get('count')); + } + + if (empty($template)) $template = LabelModel::find($settings->label2_template); + elseif (is_string($template)) $template = LabelModel::find($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); + + // Get fields from settings + $fieldDefinitions = collect(explode(';', $settings->label2_fields)) + ->filter(fn($fieldString) => !empty($fieldString)) + ->map(fn($fieldString) => Field::fromString($fieldString)); + + // Prepare data + $data = $assets + ->map(function ($asset) use ($template, $settings, $fieldDefinitions) { + + $assetData = new Collection(); + + $assetData->put('asset', $asset); + $assetData->put('id', $asset->id); + $assetData->put('tag', $asset->asset_tag); + + if ($template->getSupportTitle()) { + $title = !empty($settings->label2_title) ? + str_ireplace(':company', $asset->company->name, $settings->label2_title) : + $settings->qr_text; + if (!empty($title)) $assetData->put('title', $title); + } + + if ($template->getSupportLogo()) { + $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 (!empty($logo)) $assetData->put('logo', $logo); + } + + if ($template->getSupport1DBarcode()) { + $barcode1DType = $settings->label2_1d_type; + $barcode1DType = ($barcode1DType == 'default') ? + (($settings->alt_barcode_enabled) ? $settings->alt_barcode : null) : + $barcode1DType; + if ($barcode1DType != 'none') { + $assetData->put('barcode1d', (object)[ + 'type' => $barcode1DType, + 'content' => $asset->asset_tag, + ]); + } + } + + if ($template->getSupport2DBarcode()) { + $barcode2DType = $settings->label2_2d_type; + $barcode2DType = ($barcode2DType == 'default') ? + $settings->barcode_type : + $barcode2DType; + if (($barcode2DType != 'none') && (!is_null($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(fn($field) => $field->toArray($asset)) + ->filter(fn($field) => $field != null) + ->reduce(function($myFields, $field) { + // Remove Duplicates + $toAdd = $field + ->filter(fn($o) => !$myFields->contains('dataSource', $o['dataSource'])) + ->first(); + + return $toAdd ? $myFields->push($toAdd) : $myFields; + }, 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; + } + +} \ No newline at end of file diff --git a/composer.json b/composer.json index 2b127f907d..bb9acd9b1d 100644 --- a/composer.json +++ b/composer.json @@ -70,6 +70,7 @@ "spatie/laravel-backup": "^6.16", "symfony/polyfill-mbstring": "^1.22", "tecnickcom/tc-lib-barcode": "^1.15", + "tecnickcom/tcpdf": "^6.5.0", "unicodeveloper/laravel-password": "^1.0", "watson/validating": "^6.1" }, diff --git a/database/migrations/2022_10_25_215520_add_label2_settings.php b/database/migrations/2022_10_25_215520_add_label2_settings.php new file mode 100644 index 0000000000..692e8440db --- /dev/null +++ b/database/migrations/2022_10_25_215520_add_label2_settings.php @@ -0,0 +1,50 @@ +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.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'); + }); + } +} diff --git a/package.json b/package.json index 67b5988541..7a497786e3 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "acorn-import-assertions": "^1.9.0", "admin-lte": "^2.4.18", "ajv": "^6.12.6", + "alpinejs": "^3.10.5", "blueimp-file-upload": "^9.34.0", "bootstrap": "^3.4.1", "bootstrap-colorpicker": "^2.5.3", diff --git a/public/js/dist/all-defer.js b/public/js/dist/all-defer.js new file mode 100644 index 0000000000..3eac3595a9 Binary files /dev/null and b/public/js/dist/all-defer.js differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index b1c491bc26..28549f366a 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -33,6 +33,7 @@ "/js/build/vendor.js": "/js/build/vendor.js?id=3592e07ae9a6d1805a4ea3bd3c034aef", "/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=df78f0c4cc93c29c02a41144590f6350", "/js/dist/all.js": "/js/dist/all.js?id=ba07d399f23b294f7c4983030b757423", + "/js/dist/all-defer.js": "/js/dist/all-defer.js?id=7d1b362ddda912bce36f333cd492191b", "/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397", "/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=e36e83c2aa3c3afdbb8ebe2c0309e91d", "/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb", diff --git a/public/uploads/companies/.gitignore b/public/uploads/companies/.gitignore index f935021a8f..a24807084c 100755 --- a/public/uploads/companies/.gitignore +++ b/public/uploads/companies/.gitignore @@ -1 +1,2 @@ !.gitignore +!company-image-test.png \ No newline at end of file diff --git a/public/uploads/companies/company-image-test.png b/public/uploads/companies/company-image-test.png new file mode 100644 index 0000000000..681ec5401e Binary files /dev/null and b/public/uploads/companies/company-image-test.png differ diff --git a/resources/lang/en/admin/labels/message.php b/resources/lang/en/admin/labels/message.php new file mode 100644 index 0000000000..96785f0754 --- /dev/null +++ b/resources/lang/en/admin/labels/message.php @@ -0,0 +1,11 @@ + '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', + +]; diff --git a/resources/lang/en/admin/labels/table.php b/resources/lang/en/admin/labels/table.php new file mode 100644 index 0000000000..87dee4bad0 --- /dev/null +++ b/resources/lang/en/admin/labels/table.php @@ -0,0 +1,13 @@ + 'Labels', + 'support_fields' => 'Fields', + 'support_asset_tag' => 'Tag', + 'support_1d_barcode' => '1D', + 'support_2d_barcode' => '2D', + 'support_logo' => 'Logo', + 'support_title' => 'Title', + +]; \ No newline at end of file diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index 92faf85c5f..9c038a87be 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -330,9 +330,30 @@ return [ 'setup_migration_create_user' => 'Next: Create User', 'ldap_settings_link' => 'LDAP Settings Page', 'slack_test' => 'Test Integration', + 'label2_enable' => 'New Label Engine', + 'label2_enable_help' => 'Switch to the new label engine. Note: You will need to save this setting before setting others.', + '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 :company will be replaced with the asset's company name', + 'label2_asset_logo' => 'Use Asset Logo', + 'label2_asset_logo_help' => 'Use the logo of the asset's assigned company, rather than the value at :setting_name', + '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' => 'Field Definitions', + 'label2_fields_help' => 'Fields can be added, removed, and reordered in the left column. For each field, multiple options for Label and DataSource can be added, removed, and reordered in the right column.', + 'help_asterisk_bold' => 'Text entered as **text** will be displayed as bold', + 'help_blank_to_use' => 'Leave blank to use the value from :setting_name', + 'help_default_will_use' => ':default will use the value from :setting_name', + 'default' => 'Default', + 'none' => 'None', 'google_callback_help' => 'This should be entered as the callback URL in your Google OAuth app settings in your organization's Google developer console .', 'google_login' => 'Google Workspace Login Settings', 'enable_google_login' => 'Enable users to login with Google Workspace', 'enable_google_login_help' => 'Users will not be automatically provisioned. They must have an existing account here AND in Google Workspace, and their username here must match their Google Workspace email address. ', - ]; diff --git a/resources/views/layouts/default.blade.php b/resources/views/layouts/default.blade.php index 4363584972..13a65bf28b 100644 --- a/resources/views/layouts/default.blade.php +++ b/resources/views/layouts/default.blade.php @@ -947,6 +947,7 @@ {{-- Javascript files --}} + @@ -1022,6 +1023,5 @@ @livewireScripts - diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 14ce6ba4c2..c4cae63e87 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -699,6 +699,25 @@ } } + function labelPerPageFormatter(value, row, index, field) { + if (row) { + if (!row.hasOwnProperty('sheet_info')) { 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; diff --git a/resources/views/partials/label2-field-definitions.blade.php b/resources/views/partials/label2-field-definitions.blade.php new file mode 100644 index 0000000000..6522b951d8 --- /dev/null +++ b/resources/views/partials/label2-field-definitions.blade.php @@ -0,0 +1,334 @@ +@once + @push('css') + + @endpush +@endonce + +@push('js') + +@endpush +@php + $selector = '[x-data="'.$name.'"]'; +@endphp +@push('css') + +@endpush + +
+ +
+

Fields

+
+ +
+
+ + + + +
+ +

Options

+
+ + +
+
+ + + + +
+
+
\ No newline at end of file diff --git a/resources/views/partials/label2-preview.blade.php b/resources/views/partials/label2-preview.blade.php new file mode 100644 index 0000000000..36617bcc37 --- /dev/null +++ b/resources/views/partials/label2-preview.blade.php @@ -0,0 +1,98 @@ +@once + @push('css') + + @endpush +@endonce + +@push('js') + +@endpush + +
+
+ + +
+ +
diff --git a/resources/views/settings/labels.blade.php b/resources/views/settings/labels.blade.php index e214ce0f41..ae9bfc3a61 100644 --- a/resources/views/settings/labels.blade.php +++ b/resources/views/settings/labels.blade.php @@ -20,8 +20,7 @@ } - - {{ Form::open(['method' => 'POST', 'files' => false, 'autocomplete' => 'off', 'class' => 'form-horizontal', 'role' => 'form' ]) }} + {{ Form::open(['id' => 'settingsForm', 'method' => 'POST', 'files' => false, 'autocomplete' => 'off', 'class' => 'form-horizontal', 'role' => 'form' ]) }} {{csrf_field()}} @@ -40,158 +39,366 @@
-
+ +
- {{ Form::label('labels_per_page', trans('admin/settings/general.labels_per_page')) }} + {{ Form::label('label2_enable', trans('admin/settings/general.label2_enable')) }}
- {{ 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', '') !!} + {{ Form::checkbox('label2_enable', '1', old('label2_enable', $setting->label2_enable, [ 'class'=>'minimal', 'aria-label'=>'label2_enable' ])) }} + {{ trans('general.yes') }} + {!! $errors->first('label2_enable', '') !!} +

{!! trans('admin/settings/general.label2_enable_help') !!}

-
-
- {{ Form::label('labels_fontsize', trans('admin/settings/general.labels_fontsize')) }} -
-
-
- {{ Form::text('labels_fontsize', old('labels_fontsize', $setting->labels_fontsize), ['class' => 'form-control', 'aria-label'=>'labels_fontsize']) }} -
{{ trans('admin/settings/general.text_pt') }}
-
-
-
- {!! $errors->first('labels_fontsize', '') !!} -
-
+ @if ($setting->label2_enable) + -
-
- {{ Form::label('labels_width', trans('admin/settings/general.label_dimensions')) }} -
-
-
- {{ Form::text('labels_width', old('labels_width', $setting->labels_width), ['class' => 'form-control', 'aria-label'=>'labels_width']) }} -
{{ trans('admin/settings/general.width_w') }}
+ +
+
+ {{ Form::label('label2_template', trans('admin/settings/general.label2_template')) }} + @include('partials.label2-preview') +
+
+
+
-
-
- {{ Form::text('labels_height', old('labels_height', $setting->labels_height), ['class' => 'form-control', 'aria-label'=>'labels_height']) }} -
{{ trans('admin/settings/general.height_h') }}
-
-
-
- {!! $errors->first('labels_width', '') !!} - {!! $errors->first('labels_height', '') !!} -
-
-
-
- {{ Form::label('labels_display_sgutter', trans('admin/settings/general.label_gutters')) }} -
-
-
- {{ Form::text('labels_display_sgutter', old('labels_display_sgutter', $setting->labels_display_sgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_sgutter']) }} -
{{ trans('admin/settings/general.horizontal') }}
+ +
+
+ {{ Form::label('label2_title', trans('admin/settings/general.label2_title')) }} +
+
+ {{ 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', '') !!} +

{!! trans('admin/settings/general.label2_title_help') !!}

+

+ {!! trans('admin/settings/general.label2_title_help_phold') !!}.
+ {!! trans('admin/settings/general.help_asterisk_bold') !!}.
+ {!! + trans('admin/settings/general.help_blank_to_use', [ + 'setting_name' => trans('admin/settings/general.barcodes').' > '.trans('admin/settings/general.qr_text') + ]) + !!} +

-
-
- {{ Form::text('labels_display_bgutter', old('labels_display_bgutter', $setting->labels_display_bgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_bgutter']) }} -
{{ trans('admin/settings/general.vertical') }}
-
-
-
- {!! $errors->first('labels_display_sgutter', '') !!} - {!! $errors->first('labels_display_bgutter', '') !!} -
-
-
-
- {{ Form::label('labels_pmargin_top', trans('admin/settings/general.page_padding')) }} -
-
-
- {{ Form::text('labels_pmargin_top', old('labels_pmargin_top', $setting->labels_pmargin_top), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_top']) }} -
{{ trans('admin/settings/general.top') }}
+ +
+
+ {{ Form::label('label2_asset_logo', trans('admin/settings/general.label2_asset_logo')) }}
-
- {{ Form::text('labels_pmargin_right', old('labels_pmargin_right', $setting->labels_pmargin_right), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_right']) }} -
{{ trans('admin/settings/general.right') }}
+
+ {{ 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', '') !!} +

{!! trans('admin/settings/general.label2_asset_logo_help', ['setting_name' => trans('admin/settings/general.brand').' > '.trans('admin/settings/general.label_logo')]) !!}

-
-
- {{ Form::text('labels_pmargin_bottom', old('labels_pmargin_bottom', $setting->labels_pmargin_bottom), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_bottom']) }} -
{{ trans('admin/settings/general.bottom') }}
+ + +
+
+ {{ Form::label('label2_1d_type', trans('admin/settings/general.label2_1d_type')) }}
-
- {{ Form::text('labels_pmargin_left', old('labels_pmargin_left', $setting->labels_pmargin_left), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_left']) }} -
{{ trans('admin/settings/general.left') }}
-
- -
-
- {!! $errors->first('labels_width', '') !!} - {!! $errors->first('labels_height', '') !!} -
-
- -
-
- {{ Form::label('labels_pagewidth', trans('admin/settings/general.page_dimensions')) }} -
-
-
- {{ Form::text('labels_pagewidth', old('labels_pagewidth', $setting->labels_pagewidth), ['class' => 'form-control', 'aria-label'=>'labels_pagewidth']) }} -
{{ trans('admin/settings/general.width_w') }}
+
+ @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', '') !!} +

+ {{ 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').' > '.trans('admin/settings/general.alt_barcode_type'), + ]) + !!} +

-
-
- {{ Form::text('labels_pageheight', old('labels_pageheight', $setting->labels_pageheight), ['class' => 'form-control', 'aria-label'=>'labels_pageheight']) }} -
{{ trans('admin/settings/general.height_h') }}
+ + +
+
+ {{ Form::label('label2_2d_type', trans('admin/settings/general.label2_2d_type')) }} +
+
+ @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', '') !!} +

+ {{ 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').' > '.trans('admin/settings/general.barcode_type'), + ]) + !!} +

-
- {!! $errors->first('labels_pagewidth', '') !!} - {!! $errors->first('labels_pageheight', '') !!} + + +
+
+ {{ Form::label('label2_2d_target', trans('admin/settings/general.label2_2d_target')) }} +
+
+ {{ 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', '') !!} +

{{ trans('admin/settings/general.label2_2d_target_help') }}

+
-
-
-
- {{ Form::label('labels_display', trans('admin/settings/general.label_fields')) }} + +
+
+ {{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }} +
+
+ @include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields) ]) + {!! $errors->first('label2_fields', '') !!} +

{{ trans('admin/settings/general.label2_fields_help') }}

+
-
- - - - - -
-
+ @include('partials.bootstrap-table') + + @else + + {{ 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')) + + {{ 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 + +
+
+ {{ Form::label('labels_per_page', trans('admin/settings/general.labels_per_page')) }} +
+
+ {{ 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', '') !!} +
+
+ +
+
+ {{ Form::label('labels_fontsize', trans('admin/settings/general.labels_fontsize')) }} +
+
+
+ {{ Form::text('labels_fontsize', old('labels_fontsize', $setting->labels_fontsize), ['class' => 'form-control', 'aria-label'=>'labels_fontsize']) }} +
{{ trans('admin/settings/general.text_pt') }}
+
+
+
+ {!! $errors->first('labels_fontsize', '') !!} +
+
+ +
+
+ {{ Form::label('labels_width', trans('admin/settings/general.label_dimensions')) }} +
+
+
+ {{ Form::text('labels_width', old('labels_width', $setting->labels_width), ['class' => 'form-control', 'aria-label'=>'labels_width']) }} +
{{ trans('admin/settings/general.width_w') }}
+
+
+
+
+ {{ Form::text('labels_height', old('labels_height', $setting->labels_height), ['class' => 'form-control', 'aria-label'=>'labels_height']) }} +
{{ trans('admin/settings/general.height_h') }}
+
+
+
+ {!! $errors->first('labels_width', '') !!} + {!! $errors->first('labels_height', '') !!} +
+
+ +
+
+ {{ Form::label('labels_display_sgutter', trans('admin/settings/general.label_gutters')) }} +
+
+
+ {{ Form::text('labels_display_sgutter', old('labels_display_sgutter', $setting->labels_display_sgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_sgutter']) }} +
{{ trans('admin/settings/general.horizontal') }}
+
+
+
+
+ {{ Form::text('labels_display_bgutter', old('labels_display_bgutter', $setting->labels_display_bgutter), ['class' => 'form-control', 'aria-label'=>'labels_display_bgutter']) }} +
{{ trans('admin/settings/general.vertical') }}
+
+
+
+ {!! $errors->first('labels_display_sgutter', '') !!} + {!! $errors->first('labels_display_bgutter', '') !!} +
+
+ +
+
+ {{ Form::label('labels_pmargin_top', trans('admin/settings/general.page_padding')) }} +
+
+
+ {{ Form::text('labels_pmargin_top', old('labels_pmargin_top', $setting->labels_pmargin_top), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_top']) }} +
{{ trans('admin/settings/general.top') }}
+
+
+ {{ Form::text('labels_pmargin_right', old('labels_pmargin_right', $setting->labels_pmargin_right), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_right']) }} +
{{ trans('admin/settings/general.right') }}
+
+
+
+
+ {{ Form::text('labels_pmargin_bottom', old('labels_pmargin_bottom', $setting->labels_pmargin_bottom), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_bottom']) }} +
{{ trans('admin/settings/general.bottom') }}
+
+
+ {{ Form::text('labels_pmargin_left', old('labels_pmargin_left', $setting->labels_pmargin_left), ['class' => 'form-control', 'aria-label'=>'labels_pmargin_left']) }} +
{{ trans('admin/settings/general.left') }}
+
+ +
+
+ {!! $errors->first('labels_width', '') !!} + {!! $errors->first('labels_height', '') !!} +
+
+ +
+
+ {{ Form::label('labels_pagewidth', trans('admin/settings/general.page_dimensions')) }} +
+
+
+ {{ Form::text('labels_pagewidth', old('labels_pagewidth', $setting->labels_pagewidth), ['class' => 'form-control', 'aria-label'=>'labels_pagewidth']) }} +
{{ trans('admin/settings/general.width_w') }}
+
+
+
+
+ {{ Form::text('labels_pageheight', old('labels_pageheight', $setting->labels_pageheight), ['class' => 'form-control', 'aria-label'=>'labels_pageheight']) }} +
{{ trans('admin/settings/general.height_h') }}
+
+
+
+ {!! $errors->first('labels_pagewidth', '') !!} + {!! $errors->first('labels_pageheight', '') !!} +
+
+ +
+
+ {{ Form::label('labels_display', trans('admin/settings/general.label_fields')) }} +
+
+ + + + + + +
+
+ + @endif
diff --git a/routes/api.php b/routes/api.php index ef1b821a3e..4b8866dc2f 100644 --- a/routes/api.php +++ b/routes/api.php @@ -606,6 +606,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 diff --git a/routes/web.php b/routes/web.php index 5de6ef9025..4bc8b3bb58 100644 --- a/routes/web.php +++ b/routes/web.php @@ -10,6 +10,7 @@ use App\Http\Controllers\DepreciationsController; use App\Http\Controllers\GroupsController; use App\Http\Controllers\HealthController; use App\Http\Controllers\ImportsController; +use App\Http\Controllers\LabelsController; use App\Http\Controllers\LocationsController; use App\Http\Controllers\ManufacturersController; use App\Http\Controllers\ModalController; @@ -39,8 +40,14 @@ Route::group(['middleware' => 'auth'], function () { Route::resource('categories', CategoriesController::class, [ 'parameters' => ['category' => 'category_id'], ]); - - + + /* + * Labels + */ + Route::get( + 'labels/{labelName}', + [LabelsController::class, 'show'] + )->where('labelName', '.*')->name('labels.show'); /* * Locations @@ -68,9 +75,6 @@ Route::group(['middleware' => 'auth'], function () { ]); - - - /* * Manufacturers */ diff --git a/routes/web/hardware.php b/routes/web/hardware.php index 690d8e0d1c..1643e5794e 100644 --- a/routes/web/hardware.php +++ b/routes/web/hardware.php @@ -187,3 +187,7 @@ Route::resource('hardware', 'parameters' => ['asset' => 'asset_id' ], ]); + +Route::get('ht/{any?}', + [AssetsController::class, 'getAssetByTag'] +)->where('any', '.*')->name('ht/assetTag'); diff --git a/webpack.mix.js b/webpack.mix.js index 2cda1ee50f..babab0fad6 100644 --- a/webpack.mix.js +++ b/webpack.mix.js @@ -202,6 +202,13 @@ mix ) .version(); +mix + .combine( + ['./node_modules/alpinejs/dist/cdn.js'], + './public/js/dist/all-defer.js' + ) + .version(); + /** * Copy, minify and version skins */