fix: 🐛 update api routes for multi-tenancy
This commit is contained in:
parent
2e8ca74962
commit
ea87502ba4
11 changed files with 138 additions and 137 deletions
|
|
@ -16,8 +16,16 @@ class AppController extends Controller
|
|||
*/
|
||||
public function get(): \App\Http\Resources\ApiResponseResource
|
||||
{
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
|
||||
$response = [];
|
||||
$settings = Setting::where('key', 'Button1')->orWhere('key', 'Button2')->orWhere('key', 'Button3')->get();
|
||||
$settings = Setting::query()
|
||||
->where('tenant_id', $tenantKey)
|
||||
->where('key', 'Button1')
|
||||
->orWhere('key', 'Button2')
|
||||
->orWhere('key', 'Button3')
|
||||
->get();
|
||||
|
||||
foreach ($settings as $setting) {
|
||||
$directory = Directory::find($setting->value)->only('id', 'name');
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ use App\Models\Directory;
|
|||
use App\Models\Document;
|
||||
use App\Models\Formulary;
|
||||
use App\Models\Setting;
|
||||
use Google\Cloud\Vision\V1\ImageAnnotatorClient;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -38,8 +37,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getUsers(): \App\Http\Resources\ApiResponseResource
|
||||
{
|
||||
$users = AppUserResource::collection(AppUser::where('status', 1)->get())->toArray(request());
|
||||
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
$users = AppUserResource::collection(
|
||||
AppUser::query()->where('tenant_id', $tenantKey)->where('status', 1)->get()
|
||||
)->toArray(request());
|
||||
return new ApiResponseResource("OK", $users);
|
||||
}
|
||||
|
||||
|
|
@ -53,9 +55,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getContacts(AppUser $app_user): \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||
{
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
return ContactResource::collection(
|
||||
Contact::query()->whereHas('appUser', function (Builder $q) use ($app_user) {
|
||||
$q->where('id', $app_user->id);
|
||||
Contact::query()->whereHas('appUser', function (Builder $q) use ($tenantKey, $app_user) {
|
||||
$q->where('tenant_id', $tenantKey)->where('id', $app_user->id);
|
||||
})->get()
|
||||
);
|
||||
}
|
||||
|
|
@ -71,40 +75,46 @@ class SyncController extends Controller
|
|||
UpsertContactsRequest $request,
|
||||
AppUser $app_user
|
||||
): \Illuminate\Http\JsonResponse {
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = $request->tenant;
|
||||
|
||||
/** @var \Illuminate\Support\Collection<string,integer> */
|
||||
$formularies = Formulary::query()->pluck('slug')->flip();
|
||||
$contactQuery = Contact::query()->whereHas('appUser', function (Builder $q) use ($app_user) {
|
||||
$q->where('id', $app_user->id);
|
||||
$contactQuery = Contact::query()->whereHas('appUser', function (Builder $q) use ($tenantKey, $app_user) {
|
||||
$q->where('tenant_id', $tenantKey)->where('id', $app_user->getKey());
|
||||
});
|
||||
|
||||
\collect($request->contacts)->each(function (array $contactRequestData) use ($contactQuery, $formularies) {
|
||||
/** @var \App\Models\Contact */
|
||||
$model = (clone $contactQuery)->where('id', Arr::get($contactRequestData, 'id'))->firstOrNew();
|
||||
\collect($request->contacts)->each(
|
||||
function (array $contactRequestData) use ($contactQuery, $formularies, $app_user) {
|
||||
/** @var \App\Models\Contact $model */
|
||||
$model = (clone $contactQuery)->where('id', Arr::get($contactRequestData, 'id'))->firstOrNew();
|
||||
|
||||
$contactRequestData['timestamp'] = Carbon::parse($contactRequestData['timestamp'], 'UTC')
|
||||
->setTimezone(\now()->getTimezone());
|
||||
// @phpstan-ignore logicalAnd.leftAlwaysTrue
|
||||
if ($model->timestamp and $model->timestamp->gte($contactRequestData['timestamp'])) {
|
||||
return;
|
||||
$contactRequestData['timestamp'] = Carbon::parse($contactRequestData['timestamp'], 'UTC')
|
||||
->setTimezone(\now()->getTimezone());
|
||||
// @phpstan-ignore logicalAnd.leftAlwaysTrue
|
||||
if ($model->timestamp and $model->timestamp->gte($contactRequestData['timestamp'])) {
|
||||
return;
|
||||
}
|
||||
// * Set parse values on data prop to fill in model.
|
||||
$contactRequestData['data'] = \collect($contactRequestData['dataParsed'])
|
||||
// * FILTER CONTACT DATA WITH ACTUAL FORMULARY
|
||||
->filter(function (Input $input) use ($formularies) {
|
||||
return $formularies->has($input->data->formSlug);
|
||||
});
|
||||
$model->fill($contactRequestData);
|
||||
$model->app_user_id = $app_user->getKey();
|
||||
|
||||
// * Send contact to Feature
|
||||
if (
|
||||
!empty($contactRequestData['send_to_app_user_id']) and
|
||||
($destUser = AppUser::query()->where('id', $contactRequestData['send_to_app_user_id'])->first())
|
||||
) {
|
||||
$model->appUser()->associate($destUser);
|
||||
}
|
||||
|
||||
$model->saveOrFail();
|
||||
}
|
||||
// * Set parse values on data prop to fill in model.
|
||||
$contactRequestData['data'] = \collect($contactRequestData['dataParsed'])
|
||||
// * FILTER CONTACT DATA WITH ACTUAL FORMULARY
|
||||
->filter(function (Input $input) use ($formularies) {
|
||||
return $formularies->has($input->data->formSlug);
|
||||
});
|
||||
$model->fill($contactRequestData);
|
||||
|
||||
// * Send contact to Feature
|
||||
if (
|
||||
!empty($contactRequestData['send_to_app_user_id']) and
|
||||
($destUser = AppUser::query()->where('id', $contactRequestData['send_to_app_user_id'])->first())
|
||||
) {
|
||||
$model->appUser()->associate($destUser);
|
||||
}
|
||||
|
||||
$model->saveOrFail();
|
||||
});
|
||||
);
|
||||
|
||||
// * HTTP 200 is ok.
|
||||
return \response()->json();
|
||||
|
|
@ -119,9 +129,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function destroyContacts(DestroyContactsRequest $request, AppUser $app_user): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = $request->tenant;
|
||||
Contact::query()->whereIn('id', $request->contactUuidList)
|
||||
->whereHas('appUser', function (Builder $q) use ($app_user) {
|
||||
$q->where('id', $app_user->id);
|
||||
->whereHas('appUser', function (Builder $q) use ($tenantKey, $app_user) {
|
||||
$q->where('tenant_id', $tenantKey)->where('id', $app_user->id);
|
||||
})->delete();
|
||||
|
||||
// * HTTP 200 is ok.
|
||||
|
|
@ -135,7 +147,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getDirectories(): \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||
{
|
||||
return DirectoryResource::collection(Directory::query()->orderBy('order')->get());
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
return DirectoryResource::collection(
|
||||
Directory::query()->where('tenant_id', $tenantKey)->orderBy('order')->get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -143,7 +159,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getDocuments(): \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||
{
|
||||
return DocumentResource::collection(Document::where('status', 1)->get());
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
return DocumentResource::collection(
|
||||
Document::query()->where('tenant_id', $tenantKey)->where('status', 1)->get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -152,10 +172,12 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getVersion(Request $request): array
|
||||
{
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = $request->tenant;
|
||||
$app_uuid = $request->app_uuid;
|
||||
$app_version = $request->app_version;
|
||||
$version = Setting::query()->where('key', 'version')->value('value');
|
||||
$ShowIsActive = Setting::query()->where('key', 'ShowIsActive')->value('value');
|
||||
$version = Setting::query()->where('tenant_id', $tenantKey)->where('key', 'version')->value('value');
|
||||
$ShowIsActive = Setting::query()->where('tenant_id', $tenantKey)->where('key', 'ShowIsActive')->value('value');
|
||||
|
||||
try {
|
||||
$client = new \GuzzleHttp\Client();
|
||||
|
|
@ -183,7 +205,11 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function getFormularies(): \Illuminate\Http\Resources\Json\AnonymousResourceCollection
|
||||
{
|
||||
return FormularyResource::collection(Formulary::query()->orderBy('order')->get());
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = request()->tenant;
|
||||
return FormularyResource::collection(
|
||||
Formulary::query()->where('tenant_id', $tenantKey)->orderBy('order')->get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -192,12 +218,14 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function sendFlyer(SendFlyerRequest $request): string
|
||||
{
|
||||
$requestData = \json_decode($request->emails, true);
|
||||
/** @var string $tenantKey */
|
||||
$tenantKey = $request->tenant;
|
||||
$requestData = $request->validated()['emails'];
|
||||
$email = $requestData['email'];
|
||||
$subject = $requestData['subject'];
|
||||
$message = $requestData['message'];
|
||||
$app_user_id = $requestData['app_user_id'];
|
||||
$docs = \json_decode($requestData['documents'], true);
|
||||
$docs = $requestData['documents'];
|
||||
|
||||
$user = AppUser::find($app_user_id);
|
||||
|
||||
|
|
@ -206,12 +234,12 @@ class SyncController extends Controller
|
|||
$noExists = [];
|
||||
foreach ($docs as $doc) {
|
||||
$exists = Storage::disk('public')
|
||||
->exists(sprintf('docs/%s/%s.%s', \tenant()->getKey(), $doc['uuid'], $doc['type']));
|
||||
->exists(sprintf('docs/%s/%s.%s', $tenantKey, $doc['uuid'], $doc['type']));
|
||||
if ($exists) {
|
||||
array_push($attach, URL::temporarySignedRoute(
|
||||
'docs.download',
|
||||
'bo.docs.download',
|
||||
now()->addDays(30),
|
||||
['uuid' => $doc['uuid']]
|
||||
['tenant' => $tenantKey, 'uuid' => $doc['uuid']]
|
||||
));
|
||||
array_push($filesName, $doc['title']);
|
||||
} else {
|
||||
|
|
@ -228,9 +256,7 @@ class SyncController extends Controller
|
|||
'filesName' => $filesName,
|
||||
]);
|
||||
|
||||
Mail::to($email)
|
||||
->cc($user->email)
|
||||
->queue($message);
|
||||
Mail::to($email)->cc($user->email)->queue($message);
|
||||
} else {
|
||||
$message = new SendFlyerFailed([
|
||||
'email' => $email,
|
||||
|
|
@ -244,30 +270,4 @@ class SyncController extends Controller
|
|||
} //end if
|
||||
return 'OK';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function processOcr(): void
|
||||
{
|
||||
// Instantiates a client.
|
||||
$imageAnnotator = new ImageAnnotatorClient([
|
||||
'credentials' => public_path() . '/credentials.json'
|
||||
]);
|
||||
|
||||
// The name of the image file to annotate.
|
||||
$fileName = 'test.jpg';
|
||||
|
||||
// Prepare the image to be annotated.
|
||||
$image = file_get_contents(public_path() . "/" . $fileName);
|
||||
|
||||
// Performs label detection on the image file.
|
||||
$response = $imageAnnotator->textDetection($image);
|
||||
$labels = $response->getTextAnnotations();
|
||||
|
||||
// @phpstan-ignore foreach.nonIterable
|
||||
foreach ($labels as $label) {
|
||||
echo $label->getDescription() . "<br>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,6 @@ use Illuminate\Foundation\Http\FormRequest;
|
|||
|
||||
class DestroyContactsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'contactUuidList' => \collect($this->contactUuidList)->filter()->all()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -5,22 +5,10 @@ namespace App\Http\Requests\Api\Contacts;
|
|||
use App\Enums\Formularies\InputTypeEnum;
|
||||
use App\Lib\Inputs\Definition\InputData;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
|
||||
class UpsertContactsRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
// * Check is done with api.token middleware
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
|
|
@ -67,11 +55,11 @@ class UpsertContactsRequest extends FormRequest
|
|||
'contacts' => 'present|array',
|
||||
'contacts.*' => 'array',
|
||||
'contacts.*.id' => 'uuid',
|
||||
'contacts.*.lastname' => 'nullable|string|max:255',
|
||||
'contacts.*.firstname' => 'nullable|string|max:255',
|
||||
'contacts.*.lastname' => 'nullable|string|between:3,255',
|
||||
'contacts.*.firstname' => 'nullable|string|between:3,255',
|
||||
// * Dot not validate email here (soft validate), if it does not pass, app will be blocked.
|
||||
'contacts.*.email' => 'required|string|max:255',
|
||||
'contacts.*.phone' => 'nullable|string|max:255',
|
||||
'contacts.*.email' => 'required|string|between:3,255',
|
||||
'contacts.*.phone' => 'nullable|string|between:3,255',
|
||||
'contacts.*.timestamp' => 'required|date',
|
||||
|
||||
// * DATA
|
||||
|
|
@ -80,7 +68,10 @@ class UpsertContactsRequest extends FormRequest
|
|||
'contacts.*.data.*' => 'array',
|
||||
'contacts.*.data.*.title' => 'present|string|min:1|max:255',
|
||||
'contacts.*.data.*.formSlug' => 'present|string|min:1|max:255',
|
||||
'contacts.*.data.*.type' => ['present', new Enum(InputTypeEnum::class)],
|
||||
'contacts.*.data.*.type' => 'present|in:' . implode(
|
||||
',',
|
||||
array_column(InputTypeEnum::cases(), 'name')
|
||||
),
|
||||
'contacts.*.data.*.value' => 'present',
|
||||
'contacts.*.data.*.required' => 'present|boolean',
|
||||
'contacts.*.data.*.send_to_app_user_id' => 'nullable|numeric',
|
||||
|
|
@ -117,7 +108,7 @@ class UpsertContactsRequest extends FormRequest
|
|||
'error' => "wrong formSlug on data index '{$index}'"
|
||||
]);
|
||||
}
|
||||
$type = InputTypeEnum::make($data->get('type') ? $data->get('type') : null);
|
||||
$type = InputTypeEnum::make($data->get('type') ? $data->get('type') : null, 'name');
|
||||
$value = $data['value'] ?? null;
|
||||
$required = $data->get('required') ? true : false;
|
||||
$inputClass = $type->inputTypes();
|
||||
|
|
|
|||
|
|
@ -15,18 +15,26 @@ class SendFlyerRequest extends FormRequest
|
|||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'email' => [
|
||||
'emails.email' => [
|
||||
'required',
|
||||
'email:rfc,strict,dns,spoof,filter',
|
||||
Rule::unique('users', 'email')->where('tenant_id', tenant('id'))
|
||||
Rule::exists('contacts', 'email')->where(function ($query) {
|
||||
$query->whereIn('app_user_id', function ($subQuery) {
|
||||
$subQuery->select('id')->from('app_users')->where('tenant_id', $this->tenant);
|
||||
});
|
||||
}),
|
||||
],
|
||||
'subject' => 'required|string|between:3,255',
|
||||
'message' => 'required|string|min:3',
|
||||
'app_user_id' => [
|
||||
'emails.subject' => 'required|string|between:3,255',
|
||||
'emails.message' => 'required|string|min:3',
|
||||
'emails.app_user_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::exists('app_users', 'id')->where('tenant_id', tenant('id'))
|
||||
Rule::exists('app_users', 'id')->where('tenant_id', $this->tenant)
|
||||
],
|
||||
'emails.documents' => 'required|array|min:1',
|
||||
'emails.documents.*.title' => 'required|string|min:3',
|
||||
'emails.documents.*.uuid' => 'required|string|min:3',
|
||||
'emails.documents.*.type' => 'required|string|min:1',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -38,10 +46,10 @@ class SendFlyerRequest extends FormRequest
|
|||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'email' => trans('validation.attributes.email'),
|
||||
'subject' => trans('validation.attributes.subject'),
|
||||
'message' => trans('validation.attributes.message'),
|
||||
'app_user_id' => trans('models.classes.app_user'),
|
||||
'emails.email' => trans('validation.attributes.email'),
|
||||
'emails.subject' => trans('validation.attributes.subject'),
|
||||
'emails.message' => trans('validation.attributes.message'),
|
||||
'emails.app_user_id' => trans('models.classes.app_user'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class TranslationServiceProvider extends ServiceProvider
|
|||
// * Suported locales
|
||||
Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
|
||||
$translations = [
|
||||
'php' => $this->phpTranslations($locale),
|
||||
'php' => $this->phpTranslations($locale),
|
||||
'json' => $this->jsonTranslations($locale),
|
||||
];
|
||||
return $translations;
|
||||
|
|
|
|||
|
|
@ -17,9 +17,7 @@ return [
|
|||
*
|
||||
* Only relevant if you're using the domain or subdomain identification middleware.
|
||||
*/
|
||||
'central_domains' => [
|
||||
'showroom-bo.s-web.test'
|
||||
],
|
||||
'central_domains' => [],
|
||||
|
||||
/**
|
||||
* Tenancy bootstrappers are executed when tenancy is initialized.
|
||||
|
|
|
|||
|
|
@ -29,8 +29,10 @@ class ContactFactory extends Factory
|
|||
'notes' => $this->faker->boolean() ? $this->faker->text() : null,
|
||||
'visits' => \collect(range(0, $this->faker->numberBetween(1, 5)))->mapWithKeys(function () {
|
||||
return [
|
||||
'title' => 'Visite du ' . $this->faker->dateTime()->format('D/M/Y H:i'),
|
||||
'note' => $this->faker->text()
|
||||
[
|
||||
'title' => 'Visite du ' . $this->faker->dateTime()->format('D/M/Y H:i'),
|
||||
'note' => $this->faker->text(),
|
||||
]
|
||||
];
|
||||
}),
|
||||
'data' => null,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
@extends('bo.layout')
|
||||
@extends('bo.layout', ['brParam' => $contactModel])
|
||||
|
||||
@section('title', sprintf('%s - %s', str(__('models.classes.contact'))->plural(), Str::ucfirst(__('liste'))))
|
||||
@section('description', __('Page de contôle sur tous les contacts de l\'application.'))
|
||||
|
|
|
|||
|
|
@ -16,16 +16,18 @@ use Illuminate\Support\Facades\Route;
|
|||
|
|
||||
*/
|
||||
|
||||
Route::name('api.')->middleware('api.token')->group(function () {
|
||||
Route::get('settings', [SettingsController::class, 'get'])->name('settings.index');
|
||||
Route::get('app', [AppController::class, 'get'])->name('settings.app');
|
||||
Route::get('formularies', [SyncController::class, 'getFormularies'])->name('formularies.index');
|
||||
Route::get('users', [SyncController::class, 'getUsers'])->name('users.index');
|
||||
Route::get('directories', [SyncController::class, 'getDirectories'])->name('directories.index');
|
||||
Route::get('documents', [SyncController::class, 'getDocuments'])->name('documents.index');
|
||||
Route::get('version', [SyncController::class, 'getVersion'])->name('version');
|
||||
Route::get('contacts/{app_user}', [SyncController::class, 'getContacts'])->name('contacts.index');
|
||||
Route::post('contacts/{app_user}', [SyncController::class, 'upsertContact'])->name('contacts.upsert');
|
||||
Route::delete('contacts/{app_user}', [SyncController::class, 'destroyContacts'])->name('contacts.delete');
|
||||
Route::post('sendBrochure', [SyncController::class, 'SendFlyer'])->name('send-flyers');
|
||||
});
|
||||
Route::middleware('api.token')
|
||||
->name('api.')
|
||||
->group(function () {
|
||||
Route::get('settings', [SettingsController::class, 'get'])->name('settings.index');
|
||||
Route::get('app', [AppController::class, 'get'])->name('settings.app');
|
||||
Route::get('formularies', [SyncController::class, 'getFormularies'])->name('formularies.index');
|
||||
Route::get('users', [SyncController::class, 'getUsers'])->name('users.index');
|
||||
Route::get('directories', [SyncController::class, 'getDirectories'])->name('directories.index');
|
||||
Route::get('documents', [SyncController::class, 'getDocuments'])->name('documents.index');
|
||||
Route::get('version', [SyncController::class, 'getVersion'])->name('version');
|
||||
Route::get('contacts/{app_user}', [SyncController::class, 'getContacts'])->name('contacts.index');
|
||||
Route::post('contacts/{app_user}', [SyncController::class, 'upsertContact'])->name('contacts.upsert');
|
||||
Route::delete('contacts/{app_user}', [SyncController::class, 'destroyContacts'])->name('contacts.delete');
|
||||
Route::post('sendBrochure', [SyncController::class, 'SendFlyer'])->name('send-flyers');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Models\AppUser;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Directory;
|
||||
use App\Models\Document;
|
||||
use App\Models\Formulary;
|
||||
|
|
@ -105,9 +106,12 @@ Breadcrumbs::for('bo.contacts.index', function (Generator $trail) {
|
|||
route('bo.contacts.index', ['tenant' => \tenant()])
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('bo.contacts.show', function (Generator $trail) {
|
||||
Breadcrumbs::for('bo.contacts.show', function (Generator $trail, Contact $contact) {
|
||||
$trail->parent('bo.contacts.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.show')), route('bo.contacts.show', ['tenant' => \tenant()]));
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.show')), route('bo.contacts.show', [
|
||||
'tenant' => \tenant(),
|
||||
'contact' => $contact
|
||||
]));
|
||||
});
|
||||
|
||||
// * FORMULARIES
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue