diff --git a/app/Console/Commands/data/handle.dat b/app/Console/Commands/data/handle.dat
index ae7d4f7..2675606 100644
--- a/app/Console/Commands/data/handle.dat
+++ b/app/Console/Commands/data/handle.dat
@@ -1,16 +1,21 @@
argument('part'));
- $section = strtolower($this->argument('section'));
+ $part = $this->argument('part');
+ $segment = strtolower($this->argument('segment'));
// make detail
$detail = [
@@ -45,13 +47,13 @@ class makePart extends Command
'packages' => [],
];
// check section
- if (!in_array($section, Theme::$sections)) {
- $this->error(__('Invalid theme section'));
+ if (!in_array($segment, Area::$allSegments)) {
+ $this->error(__('Invalid area segment'));
return -1;
}
- $folderPath = resource_path() . '/views/segments/' . $section . '/' . $part;
+ $folderPath = resource_path() . '/views/segments/' . $segment . '/' . ucfirst($part);
// check is exists
@@ -64,7 +66,7 @@ class makePart extends Command
File::makeDirectory($folderPath, 0755, true);
File::makeDirectory($folderPath.'/assets', 0755, true);
- $this->info('Directory created as: /theme/' . $section . '/' . $part);
+ $this->info('Directory created as: /segments/' . $segment . '/' . ucfirst($part));
$handler = file_get_contents(__DIR__.'/data/handle.dat');
@@ -83,6 +85,9 @@ DOC;
File::copy(__DIR__.'/data/screen.png',$folderPath .'/screenshot.png');
+
+ $process = new Process(['composer', 'dump-autoload']);
+ $process->setWorkingDirectory(base_path())->run();
$this->info(__("Theme part created successfully: [blade, js, json, scss, php, assets, screenshot]"));
return 0;
diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php
index 3c36971..45c480a 100644
--- a/app/Helpers/Helper.php
+++ b/app/Helpers/Helper.php
@@ -327,6 +327,10 @@ function lastCrump()
$title = __('Trashed') . ' ' . __($routes[count($routes) - 2]);
$icon = 'ri-delete-bin-6-line';
break;
+ case 'design':
+ $title = __('Design') . ' ' . __($routes[count($routes) - 2]);
+ $icon = 'ri-paint-brush-line';
+ break;
default:
$title = __('') . ' ' . __(ucfirst($routes[count($routes) - 1]));
$icon = 'ri-bubble-chart-line';
diff --git a/app/Http/Controllers/Admin/AreaController.php b/app/Http/Controllers/Admin/AreaController.php
new file mode 100644
index 0000000..36e086e
--- /dev/null
+++ b/app/Http/Controllers/Admin/AreaController.php
@@ -0,0 +1,72 @@
+segment as $seg) {
+ $dirs = File::directories(resource_path() . '/views/segments/' . $seg);
+ foreach ($dirs as $dir) {
+ $temp = explode('/', $dir);
+ $valids[] = [
+ 'segment' => $temp[count($temp) - 2],
+ 'part' => $temp[count($temp) - 1],
+ 'data' => json_decode(file_get_contents($dir . '/' . $temp[count($temp) - 1] . '.json'), true)
+ ];
+ }
+ }
+
+ return view('admin.areas.area-design', compact('area', 'valids'));
+ }
+
+ /**
+ * screenshot segment
+ * @param $segment
+ * @param $part
+ * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
+ */
+ public function image($segment, $part)
+ {
+ return response()->file(resource_path() . '/views/segments/' . $segment . '/' . $part . '/screenshot.png', ['Content-Type' => 'image/png']);
+ }
+
+ public function update(Request $request, Area $area)
+ {
+// return $request->all();
+ foreach ($request->input('parts',[]) as $item) {
+ $data = json_decode($item);
+ if ($data->id == null){
+ // create
+ $part = new Part();
+ $part->area_id = $area->id;
+ $part->segment = $data->segment;
+ $part->part = $data->part;
+ $part->save();
+ }else{
+ $part = Part::whereId($data->id)->first();
+ $part->segment = $data->segment;
+ $part->part = $data->part;
+ $part->save();
+ }
+ }
+ logAdmin(__METHOD__,__CLASS__,$area->id);
+ return redirect()->back()->with(['message' => __('area :NAME of website updated',['NAME' => $area->name])]);
+ }
+}
diff --git a/app/Http/Controllers/Admin/GfxController.php b/app/Http/Controllers/Admin/GfxController.php
index 4b180b1..5178438 100644
--- a/app/Http/Controllers/Admin/GfxController.php
+++ b/app/Http/Controllers/Admin/GfxController.php
@@ -20,6 +20,7 @@ class GfxController extends Controller
$g->value = $gfx;
$g->save();
}
+
logAdmin(__METHOD__,__CLASS__,null);
\Artisan::call('client');
return redirect()->back()->with(['message' => __('GFX of website updated')]);
diff --git a/app/Models/Area.php b/app/Models/Area.php
new file mode 100644
index 0000000..74213fd
--- /dev/null
+++ b/app/Models/Area.php
@@ -0,0 +1,60 @@
+valid_segments,true);
+ }
+
+
+ public function getRouteKeyName(){
+ return 'name';
+ }
+
+ public function parts(){
+ return $this->hasMany(Part::class);
+ }
+}
diff --git a/app/Models/Part.php b/app/Models/Part.php
new file mode 100644
index 0000000..4951087
--- /dev/null
+++ b/app/Models/Part.php
@@ -0,0 +1,11 @@
+part);
+ $handle = "\\Resources\\Views\\Segments\\$className";
+ $handle::onAdd($part);
+ }
+
+ /**
+ * Handle the Part "updated" event.
+ */
+ public function updated(Part $part): void
+ {
+ // remove old part add new part
+
+ if ($part->isDirty('part')){
+ $className = ucfirst($part->getOriginal('part'));
+ $handle = "\\Resources\\Views\\Segments\\$className";
+ $handle::onRemove($part);
+
+ $className = $part->part;
+ $className= ucfirst($part->part);
+ $handle = "\\Resources\\Views\\Segments\\$className";
+ $handle::onAdd($part);
+ }
+
+ }
+
+ /**
+ * Handle the Part "deleted" event.
+ */
+ public function deleted(Part $part): void
+ {
+ // remove part
+ $className= ucfirst($part->part);
+ $handle = "\\Resources\\Views\\Segments\\$className";
+ $handle::onRemove($part);
+ }
+
+ /**
+ * Handle the Part "restored" event.
+ */
+ public function restored(Part $part): void
+ {
+ //
+ }
+
+ /**
+ * Handle the Part "force deleted" event.
+ */
+ public function forceDeleted(Part $part): void
+ {
+ //
+ }
+}
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index 3f5cfb9..1a6b261 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -3,6 +3,10 @@
namespace App\Providers;
use App\Helpers\TDate;
use App\Http\Middleware\Acl;
+use App\Models\Area;
+use App\Models\Part;
+use App\Observers\AreaObsever;
+use App\Observers\PartObsever;
use Carbon\Carbon;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Blade;
@@ -44,6 +48,8 @@ class AppServiceProvider extends ServiceProvider
}
});
+ Part::observe(PartObsever::class);
+
}
}
diff --git a/composer.json b/composer.json
index ea33ab7..f6aefcb 100644
--- a/composer.json
+++ b/composer.json
@@ -43,6 +43,9 @@
},
"files": [
"app/Helpers/Helper.php"
+ ],
+ "classmap": [
+ "resources/views/segments"
]
},
"autoload-dev": {
diff --git a/database/migrations/2024_07_04_050212_create_areas_table.php b/database/migrations/2024_07_04_050212_create_areas_table.php
new file mode 100644
index 0000000..191b562
--- /dev/null
+++ b/database/migrations/2024_07_04_050212_create_areas_table.php
@@ -0,0 +1,31 @@
+id();
+ $table->string('name')->unique();
+ $table->tinyInteger('max')->default(1);
+ $table->string('icon')->nullable();
+ $table->json('valid_segments');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('areas');
+ }
+};
diff --git a/database/migrations/2024_07_04_053952_create_parts_table.php b/database/migrations/2024_07_04_053952_create_parts_table.php
new file mode 100644
index 0000000..486553f
--- /dev/null
+++ b/database/migrations/2024_07_04_053952_create_parts_table.php
@@ -0,0 +1,32 @@
+id();
+ $table->unsignedBigInteger('area_id');
+ $table->integer('sort')->default(0);
+ $table->string('segment');
+ $table->string('part');
+ $table->json('data')->default('[]');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::dropIfExists('parts');
+ }
+};
diff --git a/database/seeders/AreaSeeder.php b/database/seeders/AreaSeeder.php
new file mode 100644
index 0000000..b7b610e
--- /dev/null
+++ b/database/seeders/AreaSeeder.php
@@ -0,0 +1,44 @@
+ 'preloader',
+ 'valid_segments' => json_encode(
+ ['preloader']
+ ),
+ 'max' => 1,
+ 'icon' => 'ri-loader-2-line',
+ ],
+ [
+ 'name' => 'top',
+ 'valid_segments' => json_encode(
+ ['top']
+ ),
+ 'max' => 1,
+ 'icon' => 'ri-layout-top-2-line',
+ ],
+ ];
+ foreach ($areas as $area){
+ $a = new Area();
+ $a->name = $area['name'];
+ $a->max = $area['max'];
+ $a->valid_segments = $area['valid_segments'];
+ $a->icon = $area['icon'];
+ $a->save();
+ }
+ }
+}
diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php
index 38cb4c8..3b5970a 100644
--- a/database/seeders/DatabaseSeeder.php
+++ b/database/seeders/DatabaseSeeder.php
@@ -34,6 +34,8 @@ class DatabaseSeeder extends Seeder
CommentSeeder::class,
SettingSeeder::class,
GfxSeeder::class,
+ AreaSeeder::class,
+ PartSeeder::class,
]
);
}
diff --git a/database/seeders/PartSeeder.php b/database/seeders/PartSeeder.php
new file mode 100644
index 0000000..f8919c5
--- /dev/null
+++ b/database/seeders/PartSeeder.php
@@ -0,0 +1,26 @@
+segment = 'preloader';
+ $part->part = 'PreloaderImage';
+ $part->area_id = Area::where('name','preloader')->first()->id;
+ $part->save();
+
+ }
+}
diff --git a/resources/js/app.js b/resources/js/app.js
index a04354f..c6b371b 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -90,6 +90,9 @@ app.component('morph-selector', MorphSelector);
import Gfxer from "./components/Gfxer.vue";
app.component('gfxer', Gfxer);
+import AreaDesginer from "./components/AreaDesginer.vue";
+app.component('area-designer', AreaDesginer);
+
/**
* The following block of code may be used to automatically register your
diff --git a/resources/js/components/AreaDesginer.vue b/resources/js/components/AreaDesginer.vue
new file mode 100644
index 0000000..775aa18
--- /dev/null
+++ b/resources/js/components/AreaDesginer.vue
@@ -0,0 +1,83 @@
+
+