Skip to content

Commit 8b52b46

Browse files
committed
Merge remote-tracking branch 'origin/develop'
# Conflicts: # public/css/build/app.css # public/css/build/app.css.map # public/css/build/overrides.css # public/css/build/overrides.css.map # public/css/dist/all.css # public/mix-manifest.json
2 parents d877688 + ba5a674 commit 8b52b46

22 files changed

Lines changed: 246 additions & 103 deletions

File tree

app/Helpers/Helper.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,4 +1856,42 @@ public static function normalizeFullModelName($model): string
18561856
return 'App\\Models\\'.ucwords($model);
18571857

18581858
}
1859+
1860+
/**
1861+
* Render a markdown-textarea value as HTML.
1862+
*
1863+
* Soft line breaks (single newlines) are rendered as <br> so that line
1864+
* breaks typed in the textarea are preserved in the output.
1865+
*
1866+
* When $inline is true, block-level elements are suppressed and hard
1867+
* breaks are pre-processed manually — used for the encrypted reveal span
1868+
* where block HTML cannot be placed inside a font-size-toggled <span>.
1869+
*/
1870+
public static function renderMarkdown(?string $text, bool $inline = false): string
1871+
{
1872+
if (empty($text)) {
1873+
return '';
1874+
}
1875+
1876+
if ($inline) {
1877+
// Convert newlines to CommonMark hard breaks for inline rendering
1878+
$text = preg_replace('/(?<! {2})\n/', " \n", $text);
1879+
1880+
return Str::inlineMarkdown($text, ['html_input' => 'escape']);
1881+
}
1882+
1883+
$html = trim(Str::markdown($text, [
1884+
'html_input' => 'escape',
1885+
'renderer' => ['soft_break' => "<br>\n"],
1886+
]));
1887+
1888+
// If the entire output is a single <p> block, unwrap it so the content
1889+
// renders inline-ish without the <p> adding unwanted top spacing in the
1890+
// compact detail-view layout.
1891+
if (str_starts_with($html, '<p>') && str_ends_with($html, '</p>') && substr_count($html, '<p>') === 1) {
1892+
return substr($html, 3, -4);
1893+
}
1894+
1895+
return $html;
1896+
}
18591897
}

app/Http/Controllers/Kits/CheckoutKitController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public function showCheckout(PredefinedKit $kit)
5353
*/
5454
public function store(Request $request, $kit_id)
5555
{
56+
$this->authorize('checkout', Asset::class);
57+
5658
$user_id = e($request->input('user_id'));
5759
if (is_null($user = User::find($user_id))) {
5860
return redirect()->back()->with('error', trans('admin/users/message.user_not_found'));

app/Http/Controllers/ViewAssetsController.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,10 @@ public function getRequestItem(Request $request, $itemType, $itemId = null, $can
222222

223223
return redirect()->back()->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
224224
} else {
225+
if ($fullItemType === Asset::class && is_null(Asset::RequestableAssets()->find($item->id))) {
226+
return redirect()->back()->with('error', trans('admin/hardware/message.requests.error'));
227+
}
228+
225229
$item->request();
226230
if (($settings->alert_email != '') && ($settings->alerts_enabled == '1') && (! config('app.lock_passwords'))) {
227231
$logaction->logaction('requested');

app/Http/Transformers/AssetsTransformer.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ public function transformAsset(Asset $asset)
144144

145145
$fields_array[$field->name] = [
146146
'field' => e($field->db_column),
147-
'value' => e($value),
147+
'value' => ($field->element == 'markdown-textarea' && Gate::allows('assets.view.encrypted_custom_fields')) ? Helper::renderMarkdown($value) : e($value),
148148
'field_format' => $field->format,
149149
'element' => $field->element,
150150
];
@@ -158,7 +158,7 @@ public function transformAsset(Asset $asset)
158158

159159
$fields_array[$field->name] = [
160160
'field' => e($field->db_column),
161-
'value' => e($value),
161+
'value' => ($field->element == 'markdown-textarea') ? Helper::renderMarkdown($value) : e($value),
162162
'field_format' => $field->format,
163163
'element' => $field->element,
164164
];
@@ -274,7 +274,7 @@ public function transformRequestedAsset(Asset $asset)
274274
$value = Helper::getFormattedDateObject($value, 'date', false);
275275
}
276276

277-
$fields_array[$field->db_column] = e($value);
277+
$fields_array[$field->db_column] = ($field->element == 'markdown-textarea') ? Helper::renderMarkdown($value) : e($value);
278278
}
279279

280280
$array['custom_fields'] = $fields_array;

app/Models/CustomField.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class CustomField extends Model
5151
*/
5252
protected $rules = [
5353
'name' => 'required|unique:custom_fields',
54-
'element' => 'required|in:text,listbox,textarea,checkbox,radio',
54+
'element' => 'required|in:text,listbox,textarea,markdown-textarea,checkbox,radio',
5555
'field_encrypted' => 'nullable|boolean',
5656
'auto_add_to_fieldsets' => 'boolean',
5757
'show_in_listview' => 'boolean',

app/Services/PredefinedKitCheckoutService.php

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,21 @@
77
use App\Models\User;
88
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
99
use Illuminate\Http\Request;
10-
use Illuminate\Support\Facades\Auth;
1110
use Illuminate\Support\Facades\DB;
1211

1312
/**
1413
* Class incapsulates checkout logic for reuse in different controllers
14+
*
1515
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
1616
*/
1717
class PredefinedKitCheckoutService
1818
{
1919
use AuthorizesRequests;
2020

2121
/**
22-
* @param Request $request, this function works with fields: checkout_at, expected_checkin, note
23-
* @param PredefinedKit $kit kit for checkout
24-
* @param User $user checkout target
22+
* @param Request $request, this function works with fields: checkout_at, expected_checkin, note
23+
* @param PredefinedKit $kit kit for checkout
24+
* @param User $user checkout target
2525
* @return array Empty array if all ok, else [string_error1, string_error2...]
2626
*/
2727
public function checkout(Request $request, PredefinedKit $kit, User $user)
@@ -93,7 +93,7 @@ protected function getAssetsToAdd($kit, $user, &$errors)
9393
}
9494
}
9595
if ($quantity > 0) {
96-
$errors[] = trans('admin/kits/general.none_models', ['model'=> $model->name, 'qty' => $model->pivot->quantity]);
96+
$errors[] = trans('admin/kits/general.none_models', ['model' => $model->name, 'qty' => $model->pivot->quantity]);
9797
}
9898
}
9999

@@ -107,9 +107,10 @@ protected function getLicenseSeatsToAdd($kit, &$errors)
107107
->with('freeSeats')
108108
->get();
109109
foreach ($licenses as $license) {
110+
$this->authorize('checkout', $license);
110111
$quantity = $license->pivot->quantity;
111112
if ($quantity > count($license->freeSeats)) {
112-
$errors[] = trans('admin/kits/general.none_licenses', ['license'=> $license->name, 'qty' => $license->pivot->quantity]);
113+
$errors[] = trans('admin/kits/general.none_licenses', ['license' => $license->name, 'qty' => $license->pivot->quantity]);
113114
}
114115
for ($i = 0; $i < $quantity; $i++) {
115116
$seats_to_add[] = $license->freeSeats[$i];
@@ -123,8 +124,9 @@ protected function getConsumablesToAdd($kit, &$errors)
123124
{
124125
$consumables = $kit->consumables()->with('users')->get();
125126
foreach ($consumables as $consumable) {
127+
$this->authorize('checkout', $consumable);
126128
if ($consumable->numRemaining() < $consumable->pivot->quantity) {
127-
$errors[] = trans('admin/kits/general.none_consumables', ['consumable'=> $consumable->name, 'qty' => $consumable->pivot->quantity]);
129+
$errors[] = trans('admin/kits/general.none_consumables', ['consumable' => $consumable->name, 'qty' => $consumable->pivot->quantity]);
128130
}
129131
}
130132

@@ -135,8 +137,9 @@ protected function getAccessoriesToAdd($kit, &$errors)
135137
{
136138
$accessories = $kit->accessories()->with('users')->get();
137139
foreach ($accessories as $accessory) {
140+
$this->authorize('checkout', $accessory);
138141
if ($accessory->numRemaining() < $accessory->pivot->quantity) {
139-
$errors[] = trans('admin/kits/general.none_accessory', ['accessory'=> $accessory->name, 'qty' => $accessory->pivot->quantity]);
142+
$errors[] = trans('admin/kits/general.none_accessory', ['accessory' => $accessory->name, 'qty' => $accessory->pivot->quantity]);
140143
}
141144
}
142145

@@ -175,7 +178,7 @@ function () use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset
175178
]);
176179
event(new CheckoutableCheckedOut($consumable, $user, $admin, $note));
177180
}
178-
//accessories
181+
// accessories
179182
foreach ($accessories_to_add as $accessory) {
180183
$accessory->assigned_to = $user->id;
181184
$accessory->users()->attach($accessory->id, [

database/factories/CustomFieldFactory.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,15 @@ public function testRadio()
154154
];
155155
});
156156
}
157+
158+
public function testMarkdownTextarea()
159+
{
160+
return $this->state(function () {
161+
return [
162+
'name' => 'Notes',
163+
'help_text' => 'Additional notes about this asset. Markdown is supported.',
164+
'element' => 'markdown-textarea',
165+
];
166+
});
167+
}
157168
}

database/seeders/CustomFieldSeeder.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function run()
3636
CustomField::factory()->count(1)->testEncrypted()->create();
3737
CustomField::factory()->count(1)->testCheckbox()->create();
3838
CustomField::factory()->count(1)->testRadio()->create();
39+
CustomField::factory()->count(1)->testMarkdownTextarea()->create();
3940

4041
DB::table('custom_field_custom_fieldset')->insert([
4142
[
@@ -109,6 +110,20 @@ public function run()
109110
'required' => 0,
110111
],
111112

113+
[
114+
'custom_field_id' => '9',
115+
'custom_fieldset_id' => '1',
116+
'order' => 0,
117+
'required' => 0,
118+
],
119+
120+
[
121+
'custom_field_id' => '9',
122+
'custom_fieldset_id' => '2',
123+
'order' => 0,
124+
'required' => 0,
125+
],
126+
112127
]);
113128
}
114129
}

public/css/build/app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/css/build/app.css.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)