Skip to content

Commit ee8aeda

Browse files
committed
resolved conflicts.
2 parents 27a2c55 + 6d68eb2 commit ee8aeda

File tree

49 files changed

+1542
-556
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1542
-556
lines changed

CHANGELOG.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,43 @@
1+
## **v2.1.2 (16 of May 2025)** - *Release*
2+
3+
* #2172[fixed] Cleaned up unnecessary label-value JSON from Email and Contact columns in export.
4+
5+
* #2171[fixed] Corrected the success message when adding a tag to a person in Contacts module.
6+
7+
* #2167[fixed] Aligned "Schedule From" and date inputs in the Workflow action UI.
8+
9+
* #2155[fixed] Resolved validation for required custom attributes when creating a Person.
10+
11+
* #1992[fixed] Removed duplicate "Stage" options when selecting "Lead" in workflow conditions.
12+
13+
## **v2.1.1 (15 of May 2025)** - *Release*
14+
15+
* Fixed broken password change functionality
16+
17+
* Implemented missing SVG sanitization to enhance security
18+
19+
* Added contact visibility control for individual accounts across different groups.
20+
21+
* Introduced dashboard pie chart features for better data visualization.
22+
23+
* #2195.[fixed]. Resolved migration failure on new setup.
24+
25+
* #2189.[fixed]. Addressed missing installation instructions in Readme.md.
26+
27+
* #2185.[fixed]. Corrected display of internal ACL labels on Role Edit/Create page.
28+
29+
* #2184.[fixed]. Eliminated error 500 when creating lead or contact.
30+
31+
* #2183.[fixed]. Repaired issue with email view rendering.
32+
33+
* #2181.[fixed]. Handled installation error in `krayin/rest-api`.
34+
35+
* #2180.[fixed]. Fixed database migration failure during installation.
36+
37+
* #2178.[fixed]. Enabled person creation for roles other than Administrator.
38+
39+
* #2173.[fixed]. Improved condition operator input visibility in workflow automation.
40+
141
## **v2.1.0 (26th of March 2025)** - *Release*
242

343
* Mobile responsive pages.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('lead_pipelines', function (Blueprint $table) {
15+
$table->string('name')->unique()->change();
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
Schema::table('lead_pipelines', function (Blueprint $table) {
25+
$table->dropUnique(['name']);
26+
27+
$table->string('name')->change();
28+
});
29+
}
30+
};

packages/Webkul/Admin/src/DataGrids/Mail/EmailDataGrid.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ public function prepareMassActions(): void
198198

199199
$this->addMassAction([
200200
'icon' => 'icon-delete',
201-
'title' => trans('admin::app.mail.index.datagrid.delete'),
201+
'title' => request('route') == 'trash'
202+
? trans('admin::app.mail.index.datagrid.delete')
203+
: trans('admin::app.mail.index.datagrid.move-to-trash'),
202204
'method' => 'POST',
203205
'url' => route('admin.mail.mass_delete', [
204206
'type' => request('route') == 'trash'

packages/Webkul/Admin/src/DataGrids/Product/ProductDataGrid.php

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Database\Query\Builder;
66
use Illuminate\Support\Facades\DB;
77
use Webkul\DataGrid\DataGrid;
8+
use Webkul\Tag\Repositories\TagRepository;
89

910
class ProductDataGrid extends DataGrid
1011
{
@@ -17,15 +18,18 @@ public function prepareQueryBuilder(): Builder
1718

1819
$queryBuilder = DB::table('products')
1920
->leftJoin('product_inventories', 'products.id', '=', 'product_inventories.product_id')
21+
->leftJoin('product_tags', 'products.id', '=', 'product_tags.product_id')
22+
->leftJoin('tags', 'tags.id', '=', 'product_tags.tag_id')
2023
->select(
2124
'products.id',
2225
'products.sku',
2326
'products.name',
2427
'products.price',
28+
'tags.name as tag_name',
2529
)
26-
->addSelect(DB::raw('SUM('.$tablePrefix.'product_inventories.in_stock) as total_in_stock'))
27-
->addSelect(DB::raw('SUM('.$tablePrefix.'product_inventories.allocated) as total_allocated'))
28-
->addSelect(DB::raw('SUM('.$tablePrefix.'product_inventories.in_stock - '.$tablePrefix.'product_inventories.allocated) as total_on_hand'))
30+
->addSelect(DB::raw('SUM(product_inventories.in_stock) as total_in_stock'))
31+
->addSelect(DB::raw('SUM(product_inventories.allocated) as total_allocated'))
32+
->addSelect(DB::raw('SUM(product_inventories.in_stock - product_inventories.allocated) as total_on_hand'))
2933
->groupBy('products.id');
3034

3135
if (request()->route('id')) {
@@ -36,6 +40,7 @@ public function prepareQueryBuilder(): Builder
3640
$this->addFilter('total_in_stock', DB::raw('SUM('.$tablePrefix.'product_inventories.in_stock'));
3741
$this->addFilter('total_allocated', DB::raw('SUM('.$tablePrefix.'product_inventories.allocated'));
3842
$this->addFilter('total_on_hand', DB::raw('SUM('.$tablePrefix.'product_inventories.in_stock - '.$tablePrefix.'product_inventories.allocated'));
43+
$this->addFilter('tag_name', 'tags.name');
3944

4045
return $queryBuilder;
4146
}
@@ -93,6 +98,24 @@ public function prepareColumns(): void
9398
'type' => 'string',
9499
'sortable' => true,
95100
]);
101+
102+
$this->addColumn([
103+
'index' => 'tag_name',
104+
'label' => trans('admin::app.products.index.datagrid.tag-name'),
105+
'type' => 'string',
106+
'searchable' => false,
107+
'sortable' => true,
108+
'filterable' => true,
109+
'filterable_type' => 'searchable_dropdown',
110+
'closure' => fn ($row) => $row->tag_name ?? '--',
111+
'filterable_options' => [
112+
'repository' => TagRepository::class,
113+
'column' => [
114+
'label' => 'name',
115+
'value' => 'name',
116+
],
117+
],
118+
]);
96119
}
97120

98121
/**

packages/Webkul/Admin/src/DataGrids/Quote/QuoteDataGrid.php

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,6 @@ public function prepareColumns(): void
8484
],
8585
]);
8686

87-
$this->addColumn([
88-
'index' => 'expired_quotes',
89-
'label' => trans('admin::app.quotes.index.datagrid.expired-quotes'),
90-
'type' => 'date',
91-
'searchable' => false,
92-
'filterable' => true,
93-
]);
94-
9587
$this->addColumn([
9688
'index' => 'person_name',
9789
'label' => trans('admin::app.quotes.index.datagrid.person'),

packages/Webkul/Admin/src/Http/Controllers/Lead/LeadController.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -157,20 +157,24 @@ public function store(LeadForm $request): RedirectResponse
157157
{
158158
Event::dispatch('lead.create.before');
159159

160-
$data = $request->all();
160+
$data = request()->all();
161161

162162
$data['status'] = 1;
163163

164-
if (isset($data['lead_pipeline_stage_id'])) {
164+
if (! empty($data['lead_pipeline_stage_id'])) {
165165
$stage = $this->stageRepository->findOrFail($data['lead_pipeline_stage_id']);
166166

167167
$data['lead_pipeline_id'] = $stage->lead_pipeline_id;
168168
} else {
169-
$pipeline = $this->pipelineRepository->getDefaultPipeline();
169+
if (empty($data['lead_pipeline_id'])) {
170+
$pipeline = $this->pipelineRepository->getDefaultPipeline();
170171

171-
$stage = $pipeline->stages()->first();
172+
$data['lead_pipeline_id'] = $pipeline->id;
173+
} else {
174+
$pipeline = $this->pipelineRepository->findOrFail($data['lead_pipeline_id']);
175+
}
172176

173-
$data['lead_pipeline_id'] = $pipeline->id;
177+
$stage = $pipeline->stages()->first();
174178

175179
$data['lead_pipeline_stage_id'] = $stage->id;
176180
}
@@ -185,7 +189,11 @@ public function store(LeadForm $request): RedirectResponse
185189

186190
session()->flash('success', trans('admin::app.leads.create-success'));
187191

188-
return redirect()->route('admin.leads.index', $data['lead_pipeline_id']);
192+
if (! empty($data['lead_pipeline_id'])) {
193+
$params['pipeline_id'] = $data['lead_pipeline_id'];
194+
}
195+
196+
return redirect()->route('admin.leads.index', $params ?? []);
189197
}
190198

191199
/**

packages/Webkul/Admin/src/Http/Controllers/Quote/QuoteController.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ public function store(AttributeForm $request): RedirectResponse
6666

6767
$quote = $this->quoteRepository->create($request->all());
6868

69-
if (request('lead_id')) {
70-
$lead = $this->leadRepository->find(request('lead_id'));
69+
$leadId = request('lead_id');
70+
71+
if ($leadId) {
72+
$lead = $this->leadRepository->find($leadId);
7173

7274
$lead->quotes()->attach($quote->id);
7375
}
@@ -76,7 +78,9 @@ public function store(AttributeForm $request): RedirectResponse
7678

7779
session()->flash('success', trans('admin::app.quotes.index.create-success'));
7880

79-
return redirect()->route('admin.quotes.index');
81+
return request()->query('from') === 'lead' && $leadId
82+
? redirect()->route('admin.leads.view', ['id' => $leadId, 'from' => 'quotes'])
83+
: redirect()->route('admin.quotes.index');
8084
}
8185

8286
/**
@@ -100,8 +104,10 @@ public function update(AttributeForm $request, int $id): RedirectResponse
100104

101105
$quote->leads()->detach();
102106

103-
if (request('lead_id')) {
104-
$lead = $this->leadRepository->find(request('lead_id'));
107+
$leadId = request('lead_id');
108+
109+
if ($leadId) {
110+
$lead = $this->leadRepository->find($leadId);
105111

106112
$lead->quotes()->attach($quote->id);
107113
}
@@ -110,7 +116,9 @@ public function update(AttributeForm $request, int $id): RedirectResponse
110116

111117
session()->flash('success', trans('admin::app.quotes.index.update-success'));
112118

113-
return redirect()->route('admin.quotes.index');
119+
return request()->query('from') === 'lead' && $leadId
120+
? redirect()->route('admin.leads.view', ['id' => $leadId, 'from' => 'quotes'])
121+
: redirect()->route('admin.quotes.index');
114122
}
115123

116124
/**

packages/Webkul/Admin/src/Http/Controllers/User/SessionController.php

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,38 @@
22

33
namespace Webkul\Admin\Http\Controllers\User;
44

5+
use Illuminate\Http\RedirectResponse;
6+
use Illuminate\Support\Collection;
7+
use Illuminate\View\View;
58
use Webkul\Admin\Http\Controllers\Controller;
9+
use Webkul\Core\Menu\MenuItem;
610

711
class SessionController extends Controller
812
{
913
/**
1014
* Show the form for creating a new resource.
11-
*
12-
* @return \Illuminate\View\View
1315
*/
14-
public function create()
16+
public function create(): RedirectResponse|View
1517
{
1618
if (auth()->guard('user')->check()) {
1719
return redirect()->route('admin.dashboard.index');
18-
} else {
19-
if (strpos(url()->previous(), 'admin') !== false) {
20-
$intendedUrl = url()->previous();
21-
} else {
22-
$intendedUrl = route('admin.dashboard.index');
23-
}
20+
}
2421

25-
session()->put('url.intended', $intendedUrl);
22+
$previousUrl = url()->previous();
2623

27-
return view('admin::sessions.login');
28-
}
24+
$intendedUrl = str_contains($previousUrl, 'admin')
25+
? $previousUrl
26+
: route('admin.dashboard.index');
27+
28+
session()->put('url.intended', $intendedUrl);
29+
30+
return view('admin::sessions.login');
2931
}
3032

3133
/**
3234
* Store a newly created resource in storage.
33-
*
34-
* @return \Illuminate\Http\Response
3535
*/
36-
public function store()
36+
public function store(): RedirectResponse
3737
{
3838
$this->validate(request(), [
3939
'email' => 'required|email',
@@ -54,9 +54,11 @@ public function store()
5454
return redirect()->route('admin.session.create');
5555
}
5656

57-
if (! bouncer()->hasPermission('dashboard')) {
58-
$availableNextMenu = menu()->getItems('admin')?->first();
57+
$menus = menu()->getItems('admin');
5958

59+
$availableNextMenu = $menus?->first();
60+
61+
if (! bouncer()->hasPermission('dashboard')) {
6062
if (is_null($availableNextMenu)) {
6163
session()->flash('error', trans('admin::app.users.not-permission'));
6264

@@ -68,18 +70,48 @@ public function store()
6870
return redirect()->to($availableNextMenu->getUrl());
6971
}
7072

71-
return redirect()->intended(route('admin.dashboard.index'));
73+
$hasAccessToIntendedUrl = $this->canAccessIntendedUrl($menus, redirect()->getIntendedUrl());
74+
75+
if ($hasAccessToIntendedUrl) {
76+
return redirect()->intended(route('admin.dashboard.index'));
77+
}
78+
79+
return redirect()->to($availableNextMenu->getUrl());
7280
}
7381

7482
/**
7583
* Remove the specified resource from storage.
76-
*
77-
* @return \Illuminate\Http\Response
7884
*/
79-
public function destroy()
85+
public function destroy(): RedirectResponse
8086
{
8187
auth()->guard('user')->logout();
8288

8389
return redirect()->route('admin.session.create');
8490
}
91+
92+
/**
93+
* Find menu item by URL.
94+
*/
95+
protected function canAccessIntendedUrl(Collection $menus, ?string $url): ?MenuItem
96+
{
97+
if (is_null($url)) {
98+
return null;
99+
}
100+
101+
foreach ($menus as $menu) {
102+
if ($menu->getUrl() === $url) {
103+
return $menu;
104+
}
105+
106+
if ($menu->haveChildren()) {
107+
$found = $this->canAccessIntendedUrl($menu->getChildren(), $url);
108+
109+
if ($found) {
110+
return $found;
111+
}
112+
}
113+
}
114+
115+
return null;
116+
}
85117
}

packages/Webkul/Admin/src/Http/Requests/PipelineForm.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ public function rules()
3636
{
3737
if (request('id')) {
3838
return [
39-
'name' => 'required',
39+
'name' => 'required|unique:lead_pipelines,name,'.request('id'),
4040
'stages.*.name' => 'unique_key',
4141
'stages.*.code' => 'unique_key',
4242
];
4343
}
4444

4545
return [
46-
'name' => 'required',
46+
'name' => 'required|unique:lead_pipelines,name',
4747
'rotten_days' => 'required',
4848
'stages.*.name' => 'unique_key',
4949
'stages.*.code' => 'unique_key',

0 commit comments

Comments
 (0)