1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-14 07:02:34 +01:00

Merge pull request #9193 from turbo124/v5-develop

v5.8.16
This commit is contained in:
David Bomba 2024-01-25 15:12:46 +11:00 committed by GitHub
commit 18f1e3c1b8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 168 additions and 55 deletions

View File

@ -1 +1 @@
5.8.15 5.8.16

View File

@ -922,6 +922,17 @@ class CheckData extends Command
}); });
Company::whereNull("subdomain")
->cursor()
->when(Ninja::isHosted())
->each(function ($c) {
$c->subdomain = MultiDB::randomSubdomainGenerator();
$c->save();
$this->logMessage("Fixing subdomain for # {$c->id}");
});
} }

View File

@ -832,6 +832,42 @@ class BaseExport
return $query; return $query;
} }
protected function addClientFilter($query, $clients): Builder
{
$transformed_clients = $this->transformKeys(explode(',', $clients));
$query->whereIn('client_id', $transformed_clients);
return $query;
}
protected function addVendorFilter($query, $vendors): Builder
{
$transformed_vendors = $this->transformKeys(explode(',', $vendors));
$query->whereIn('vendor_id', $transformed_vendors);
return $query;
}
protected function addProjectFilter($query, $projects): Builder
{
$transformed_projects = $this->transformKeys(explode(',', $projects));
$query->whereIn('project_id', $transformed_projects);
return $query;
}
protected function addCategoryFilter($query, $expense_categories): Builder
{
$transformed_expense_categories = $this->transformKeys(explode(',', $expense_categories));
$query->whereIn('category_id', $transformed_expense_categories);
return $query;
}
protected function addInvoiceStatusFilter($query, $status): Builder protected function addInvoiceStatusFilter($query, $status): Builder
{ {

View File

@ -88,6 +88,22 @@ class ExpenseExport extends BaseExport
$query = $this->addDateRange($query); $query = $this->addDateRange($query);
if(isset($this->input['clients'])) {
$query = $this->addClientFilter($query, $this->input['clients']);
}
if(isset($this->input['vendors'])) {
$query = $this->addVendorFilter($query, $this->input['vendors']);
}
if(isset($this->input['projects'])) {
$query = $this->addProjectFilter($query, $this->input['projects']);
}
if(isset($this->input['categories'])) {
$query = $this->addCategoryFilter($query, $this->input['categories']);
}
return $query; return $query;
} }

View File

@ -11,13 +11,14 @@
namespace App\Http\Requests\Company; namespace App\Http\Requests\Company;
use App\Http\Requests\Request;
use App\Http\ValidationRules\Company\ValidCompanyQuantity;
use App\Http\ValidationRules\Company\ValidSubdomain;
use App\Http\ValidationRules\ValidSettingsRule;
use App\Models\Company;
use App\Utils\Ninja; use App\Utils\Ninja;
use App\Models\Company;
use App\Libraries\MultiDB;
use App\Http\Requests\Request;
use App\Utils\Traits\MakesHash; use App\Utils\Traits\MakesHash;
use App\Http\ValidationRules\ValidSettingsRule;
use App\Http\ValidationRules\Company\ValidSubdomain;
use App\Http\ValidationRules\Company\ValidCompanyQuantity;
class StoreCompanyRequest extends Request class StoreCompanyRequest extends Request
{ {
@ -74,6 +75,10 @@ class StoreCompanyRequest extends Request
$input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/"); $input['portal_domain'] = rtrim(strtolower($input['portal_domain']), "/");
} }
if(Ninja::isHosted() && !isset($input['subdomain'])) {
$input['subdomain'] = MultiDB::randomSubdomainGenerator();
}
$this->replace($input); $this->replace($input);
} }
} }

View File

@ -557,9 +557,9 @@ class MultiDB
$current_db = config('database.default'); $current_db = config('database.default');
do { do {
$length = 8; $length = 10;
$string = ''; $string = '';
$vowels = ['a', 'e', 'i', 'o', 'u']; $vowels = ['a', 'e', 'i', 'o', 'u', 'y'];
$consonants = [ $consonants = [
'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm',
'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'n', 'p', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z',
@ -568,7 +568,7 @@ class MultiDB
$max = $length / 2; $max = $length / 2;
for ($i = 1; $i <= $max; $i++) { for ($i = 1; $i <= $max; $i++) {
$string .= $consonants[rand(0, 19)]; $string .= $consonants[rand(0, 19)];
$string .= $vowels[rand(0, 4)]; $string .= $vowels[rand(0, 5)];
} }
} while (! self::checkDomainAvailable($string)); } while (! self::checkDomainAvailable($string));

View File

@ -54,6 +54,7 @@ class TasksTable extends Component
return render('components.livewire.tasks-table', [ return render('components.livewire.tasks-table', [
'tasks' => $query, 'tasks' => $query,
'show_item_description' => auth()->guard('contact')->user()->company->invoice_task_item_description ?? false,
]); ]);
} }
} }

View File

@ -139,7 +139,7 @@ class TemplateEmail extends Mailable
'whitelabel' => $this->client->user->account->isPaid() ? true : false, 'whitelabel' => $this->client->user->account->isPaid() ? true : false,
'logo' => $this->company->present()->logo($settings), 'logo' => $this->company->present()->logo($settings),
'links' => $this->build_email->getAttachmentLinks(), 'links' => $this->build_email->getAttachmentLinks(),
'email_preferences' => URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key]), 'email_preferences' => (Ninja::isHosted() && in_array($settings->email_sending_method, ['default', 'mailgun'])) ? URL::signedRoute('client.email_preferences', ['entity' => $this->invitation->getEntityString(), 'invitation_key' => $this->invitation->key]) : false,
]); ]);
foreach ($this->build_email->getAttachments() as $file) { foreach ($this->build_email->getAttachments() as $file) {

View File

@ -316,8 +316,8 @@ class Task extends BaseModel
$logged['end_date'] = ctrans('texts.running'); $logged['end_date'] = ctrans('texts.running');
} }
$logged['description'] = $log[2]; $logged['description'] = $log[2] ?? '';
$logged['billable'] = $log[3]; $logged['billable'] = $log[3] ?? false;
$logged['duration_raw'] = $duration; $logged['duration_raw'] = $duration;
$logged['duration'] = gmdate("H:i:s", $duration); $logged['duration'] = gmdate("H:i:s", $duration);

View File

@ -70,7 +70,7 @@ class ClientRepository extends BaseRepository
$client->settings = $client->saveSettings($data['settings'], $client); $client->settings = $client->saveSettings($data['settings'], $client);
} }
if (! $client->country_id) { if (! $client->country_id || $client->country_id == 0) {
/** @var \App\Models\Company $company **/ /** @var \App\Models\Company $company **/
$company = Company::find($client->company_id); $company = Company::find($client->company_id);
$client->country_id = $company->settings->country_id; $client->country_id = $company->settings->country_id;

View File

@ -11,13 +11,14 @@
namespace App\Services\Email; namespace App\Services\Email;
use App\Utils\Ninja;
use App\Models\Document; use App\Models\Document;
use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Attachment;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Support\Facades\URL; use Illuminate\Support\Facades\URL;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Headers;
use Illuminate\Mail\Mailables\Envelope;
class EmailMailable extends Mailable class EmailMailable extends Mailable
{ {
@ -77,7 +78,7 @@ class EmailMailable extends Mailable
'company' => $this->email_object->company, 'company' => $this->email_object->company,
'greeting' => '', 'greeting' => '',
'links' => array_merge($this->email_object->links, $links->toArray()), 'links' => array_merge($this->email_object->links, $links->toArray()),
'email_preferences' => $this->email_object->invitation 'email_preferences' => (Ninja::isHosted() && in_array($this->email_object->settings->email_sending_method, ['default', 'mailgun']) && $this->email_object->invitation)
? URL::signedRoute('client.email_preferences', ['entity' => $this->email_object->invitation->getEntityString(), 'invitation_key' => $this->email_object->invitation->key]) ? URL::signedRoute('client.email_preferences', ['entity' => $this->email_object->invitation->getEntityString(), 'invitation_key' => $this->email_object->invitation->key])
: false, : false,
] ]

View File

@ -17,8 +17,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true), 'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'), 'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'), 'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => env('APP_VERSION', '5.8.15'), 'app_version' => env('APP_VERSION', '5.8.16'),
'app_tag' => env('APP_TAG', '5.8.15'), 'app_tag' => env('APP_TAG', '5.8.16'),
'minimum_client_version' => '5.0.16', 'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1', 'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', false), 'api_secret' => env('API_SECRET', false),

View File

@ -1359,7 +1359,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "List of client tokens" summary: "List of client payment tokens"
description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available" description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available"
operationId: getClientGatewayTokens operationId: getClientGatewayTokens
parameters: parameters:
@ -1400,8 +1400,8 @@ paths:
post: post:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Adds a client" summary: "Adds a client payment token"
description: "Adds an client to a company" description: "Adds a client payment token to a company"
operationId: storeClientGatewayToken operationId: storeClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1409,7 +1409,7 @@ paths:
- $ref: "#/components/parameters/include" - $ref: "#/components/parameters/include"
responses: responses:
200: 200:
description: "Returns the saved client object" description: "Returns the saved client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1433,8 +1433,8 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Shows a client" summary: "Shows a client payment token"
description: "Displays a client by id" description: "Displays a client payment token by id"
operationId: showClientGatewayToken operationId: showClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1450,7 +1450,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the cl.ient object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1473,8 +1473,8 @@ paths:
put: put:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Updates a client" summary: "Updates a client payment token"
description: "Handles the updating of a client by id" description: "Handles the updating of a client payment token by id"
operationId: updateClientGatewayToken operationId: updateClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1490,7 +1490,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1514,7 +1514,7 @@ paths:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Deletes a client" summary: "Deletes a client"
description: "Handles the deletion of a client by id" description: "Handles the deletion of a client payment token by id"
operationId: deleteClientGatewayToken operationId: deleteClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1550,7 +1550,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Shows a client for editting" summary: "Shows a client payment token for editting"
description: "Displays a client by id" description: "Displays a client by id"
operationId: editClientGatewayToken operationId: editClientGatewayToken
parameters: parameters:
@ -1567,7 +1567,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1591,7 +1591,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Gets a new blank client object" summary: "Gets a new blank client payment token object"
description: "Returns a blank object with default values" description: "Returns a blank object with default values"
operationId: getClientGatewayTokensCreate operationId: getClientGatewayTokensCreate
parameters: parameters:
@ -1600,7 +1600,7 @@ paths:
- $ref: "#/components/parameters/include" - $ref: "#/components/parameters/include"
responses: responses:
200: 200:
description: "A blank client object" description: "A blank client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"

View File

@ -1335,7 +1335,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "List of client tokens" summary: "List of client payment tokens"
description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available" description: "Lists client_gateway_tokens, search and filters allow fine grained lists to be generated.\n\n Query parameters can be added to performed more fine grained filtering of the client_gateway_tokens, these are handled by the ClientGatewayTokenFilters class which defines the methods available"
operationId: getClientGatewayTokens operationId: getClientGatewayTokens
parameters: parameters:
@ -1376,8 +1376,8 @@ paths:
post: post:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Adds a client" summary: "Adds a client payment token"
description: "Adds an client to a company" description: "Adds a client payment token to a company"
operationId: storeClientGatewayToken operationId: storeClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1385,7 +1385,7 @@ paths:
- $ref: "#/components/parameters/include" - $ref: "#/components/parameters/include"
responses: responses:
200: 200:
description: "Returns the saved client object" description: "Returns the saved client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1409,8 +1409,8 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Shows a client" summary: "Shows a client payment token"
description: "Displays a client by id" description: "Displays a client payment token by id"
operationId: showClientGatewayToken operationId: showClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1426,7 +1426,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the cl.ient object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1449,8 +1449,8 @@ paths:
put: put:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Updates a client" summary: "Updates a client payment token"
description: "Handles the updating of a client by id" description: "Handles the updating of a client payment token by id"
operationId: updateClientGatewayToken operationId: updateClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1466,7 +1466,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1490,7 +1490,7 @@ paths:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Deletes a client" summary: "Deletes a client"
description: "Handles the deletion of a client by id" description: "Handles the deletion of a client payment token by id"
operationId: deleteClientGatewayToken operationId: deleteClientGatewayToken
parameters: parameters:
- $ref: "#/components/parameters/X-API-TOKEN" - $ref: "#/components/parameters/X-API-TOKEN"
@ -1526,7 +1526,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Shows a client for editting" summary: "Shows a client payment token for editting"
description: "Displays a client by id" description: "Displays a client by id"
operationId: editClientGatewayToken operationId: editClientGatewayToken
parameters: parameters:
@ -1543,7 +1543,7 @@ paths:
example: D2J234DFA example: D2J234DFA
responses: responses:
200: 200:
description: "Returns the client object" description: "Returns the client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"
@ -1567,7 +1567,7 @@ paths:
get: get:
tags: tags:
- client_gateway_tokens - client_gateway_tokens
summary: "Gets a new blank client object" summary: "Gets a new blank client payment token object"
description: "Returns a blank object with default values" description: "Returns a blank object with default values"
operationId: getClientGatewayTokensCreate operationId: getClientGatewayTokensCreate
parameters: parameters:
@ -1576,7 +1576,7 @@ paths:
- $ref: "#/components/parameters/include" - $ref: "#/components/parameters/include"
responses: responses:
200: 200:
description: "A blank client object" description: "A blank client payment token object"
headers: headers:
X-MINIMUM-CLIENT-VERSION: X-MINIMUM-CLIENT-VERSION:
$ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION" $ref: "#/components/headers/X-MINIMUM-CLIENT-VERSION"

View File

@ -12,7 +12,7 @@
</div> </div>
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8"> <div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
<div class="align-middle inline-block min-w-full overflow-hidden rounded"> <div class="align-middle inline-block min-w-full overflow-hidden rounded">
<table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table"> <table class="min-w-full shadow rounded border border-gray-200 mt-4 credits-table bg-white">
<thead> <thead>
<tr> <tr>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary"> <th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-primary">
@ -38,7 +38,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@forelse($tasks as $task) @foreach($tasks as $task)
<tr class="bg-white group hover:bg-gray-100"> <tr class="bg-white group hover:bg-gray-100">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500"> <td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500">
{{ \Illuminate\Support\Str::limit($task->description, 80) }} {{ \Illuminate\Support\Str::limit($task->description, 80) }}
@ -63,13 +63,56 @@
{{ \Carbon\CarbonInterval::seconds($task->calcDuration())->cascade()->forHumans() }} {{ \Carbon\CarbonInterval::seconds($task->calcDuration())->cascade()->forHumans() }}
</td> </td>
</tr> </tr>
@empty @if($show_item_description)
<tr><td width="100%" colspan="4">
<table class="min-w-full ml-5">
<thead>
<tr>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<span>
{{ ctrans('texts.date') }}
</span>
</th>
<th class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<span>
{{ ctrans('texts.duration') }}
</span>
</th>
<th colspan="4" class="px-6 py-3 text-xs font-medium leading-4 tracking-wider text-left text-white uppercase border-b border-gray-200 bg-gray-500">
<span>
{{ ctrans('texts.description') }}
</span>
</th>
</tr>
</thead>
<tbody>
@foreach($task->processLogsExpandedNotation() as $log)
@if(strlen($log['description']) > 1)
<tr class="bg-white group border-b border-gray-100">
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
{{ $log['start_date']}}
</td>
<td class="px-6 py-4 text-sm leading-5 text-gray-500 w-1/6">
{{ $log['duration']}}
</td>
<td colspan="4" class="px-6 py-4 text-sm leading-5 text-gray-500 w-4/6">
{!! nl2br(e($log['description'])) !!}
</td>
</tr>
@endif
@endforeach
</tbody>
</table>
</td></tr>
@endif
@endforeach
@if($tasks->count() == 0)
<tr class="bg-white group hover:bg-gray-100"> <tr class="bg-white group hover:bg-gray-100">
<td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500" colspan="100%"> <td class="px-6 py-4 whitespace-nowrap text-sm leading-5 text-gray-500" colspan="100%">
{{ ctrans('texts.no_results') }} {{ ctrans('texts.no_results') }}
</td> </td>
</tr> </tr>
@endforelse @endif
</tbody> </tbody>
</table> </table>
</div> </div>