first commit

This commit is contained in:
ericli1018
2025-06-13 12:36:48 +08:00
commit 0475d9de8e
167 changed files with 20145 additions and 0 deletions

27
app/Console/Kernel.php Normal file
View File

@ -0,0 +1,27 @@
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*/
protected function schedule(Schedule $schedule): void
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*/
protected function commands(): void
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* The list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*/
public function register(): void
{
$this->reportable(function (Throwable $e) {
//
});
}
}

View File

@ -0,0 +1,47 @@
<?php
namespace App\Http\Controllers\Admin\Charts;
use Backpack\CRUD\app\Http\Controllers\ChartController;
use ConsoleTVs\Charts\Classes\Chartjs\Chart;
/**
* Class WeeklyUsersChartController
* @package App\Http\Controllers\Admin\Charts
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class WeeklyUsersChartController extends ChartController
{
public function setup()
{
$this->chart = new Chart();
// MANDATORY. Set the labels for the dataset points
$this->chart->labels([
'Today',
]);
// RECOMMENDED. Set URL that the ChartJS library should call, to get its data using AJAX.
$this->chart->load(backpack_url('charts/weekly-users'));
// OPTIONAL
// $this->chart->minimalist(false);
// $this->chart->displayLegend(true);
}
/**
* Respond to AJAX calls with all the chart data points.
*
* @return json
*/
public function data()
{
$users_created_today = \App\Models\User::whereDate('created_at', today())->count();
$this->chart->dataset('Users Created', 'bar', [
$users_created_today,
])
->color('rgba(205, 32, 31, 1)')
->backgroundColor('rgba(205, 32, 31, 0.4)');
}
}

View File

@ -0,0 +1,326 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\DemoCatalogsRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Backpack\CRUD\app\Library\Widget;
/**
* Class DemoCatalogsCrudController
* @package App\Http\Controllers\Admin
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class DemoCatalogsCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
//use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ReorderOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CloneOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\BulkDeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* @return void
*/
public function setup()
{
CRUD::setModel(\App\Models\DemoCatalogs::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/demo-catalogs');
CRUD::setEntityNameStrings('demo catalogs', 'demo catalogs');
CRUD::enableDetailsRow();
$this->crud->set('clone.redirect_after_clone', true);
}
protected function setupReorderOperation()
{
CRUD::set('reorder.label', 'name');
CRUD::set('reorder.max_level', 1);
}
protected function showDetailsRow($id)
{
$this->data['entry'] = $this->crud->getEntry($id);
$this->data['crud'] = $this->crud;
Widget::add()->to('crud-details-row')->type('progress')->value(135)->description('Progress')->progress(50);
$userCount = 300;
Widget::add()->to('crud-details-row')->type('div')->class('row')->content([
//widget made using fluent syntax
Widget::make()
->type('progress')
->class('card border-0 text-white bg-primary')
->progressClass('progress-bar')
->value($userCount)
->description('Registered users.')
->progress(100 * (int)$userCount / 1000)
->hint(1000 - $userCount . ' more until next milestone.'),
//widget made using the array definition
Widget::make(
[
'type' => 'card',
'class' => 'card bg-dark text-white',
'wrapper' => ['class' => 'col-sm-3 col-md-3'],
'content' => [
'header' => 'Example Widget',
'body' => 'Widget placed at "before_content" secion in same row',
]
]
),
]);
// load the view from /resources/views/vendor/backpack/crud/ if it exists, otherwise load the one in the package
return view('crud::details_row', $this->data);
}
/**
* Define what happens when the List operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-list-entries
* @return void
*/
protected function setupListOperation()
{
if (! $this->crud->getRequest()->has('order')){
$this->crud->orderBy('lft', 'asc')->orderBy('id', 'desc');
}
CRUD::addColumn('#');
CRUD::column('name')->label('名稱')->type('textarea_nl2br')->escaped(false)->searchLogic('text');
$this->crud->addColumns([
[
'value' => '111,222,333',
'label' => 'ttt',
'type' => 'text_split',
'wrapper' => [
'href' => function ($crud, $column, $entry, $related_key, $current_value) {
$query = "";
$query .= 'date_range='.$current_value;
return backpack_url('logs/view-by-cloud-id-days-r?'.$query);
},
],
],
// [
// 'name' => 'text9',
// 'type' => 'image',
// ],
// [
// 'name' => 'text9',
// 'type' => 'table',
// 'entity_singular' => '梯度價格', // used on the "Add X" button
// 'columns' => [
// 'name' => 'Name',
// 'desc' => 'Description',
// 'price' => 'Price'
// ],
// ],
[
'name' => 'text9', // The db column name
'label' => 'Video1', // Table column heading
'type' => 'video',
],
[
'name' => 'text10', // The db column name
'label' => 'Video2', // Table column heading
'type' => 'video',
],
]);
//CRUD::setFromDb(); // set columns from db columns.
/**
* Columns can be defined using the fluent syntax:
* - CRUD::column('price')->type('number');
*/
}
protected function fetchNewsCatalog()
{
return $this->fetch(\App\Models\NewsCatalog::class);
}
/**
* Define what happens when the Create operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-create
* @return void
*/
protected function setupCreateOperation()
{
CRUD::setValidation(DemoCatalogsRequest::class);
//CRUD::setFromDb(); // set fields from db columns.
/**
* Fields can be defined using the fluent syntax:
* - CRUD::field('price')->type('number');
*/
//CRUD::field('name')->label('名稱(必填)')->type('textarea');
CRUD::addFields([
[
'name' => 'name',
'lable' => 'Name',
],
[
'name' => 'photos',
'label' => '圖片',
'type' => 'upload_img_multiple',
'upload' => true,
'disk' => 'public',
'hint' => '',
'qty' => 3, // 0=no limit, >0=limit
'showSingleChoise' => '0', // 0=hidden, 1=show(default)
'showComment' => '0', // 0=hidden, 1=show(default)
],
[
'name' => 'text1',
'lable' => 'Text1',
'type' => 'select2_from_array',
'options' => ['one' => 'One', 'two' => 'Two'],
],
[
'name' => 'text2',
'lable' => 'Text2',
'type' => 'browse',
],
[
'name' => 'text3',
'lable' => 'Text3',
'type' => 'browse_multiple',
'sortable' => true,
// app/models/modelxxx.php add "protected $casts = ['text3' => 'array'];"
],
[ // date_range
'name' => 'text4,text5', // db columns for start_date & end_date
'label' => 'Text4,5',
'type' => 'date_range',
// app/models/modelxxx.php add "protected $casts = ['text4' => 'datetime', 'text5' => 'datetime'];"
// OPTIONALS
// default values for start_date & end_date
//'default' => ['2019-03-28 01:01', '2019-04-05 02:00'],
// options sent to daterangepicker.js
'date_range_options' => [
'drops' => 'down', // can be one of [down/up/auto]
'timePicker' => true,
'locale' => ['format' => 'YYYY/MM/DD HH:mm']
],
],
[
'name' => 'text6',
'lable' => 'Text6',
'type' => 'date_picker',
// app/models/modelxxx.php add "protected $casts = ['text6' => 'datetime'];"
'date_picker_options' => [
'todayBtn' => 'linked',
'format' => 'yyyy-mm-dd',
'language' => str_replace('_', '-', app()->getLocale()),
],
],
[
'name' => 'text7',
'lable' => 'Text7',
'type' => 'datetime_picker',
// app/models/modelxxx.php add "protected $casts = ['text7' => 'datetime'];"
'datetime_picker_options' => [
'format' => 'YYYY/MM/DD HH:mm',
//'language' => 'en',
'tooltips' => [ //use this to translate the tooltips in the field
'today' => 'Hoje',
'selectDate' => 'Selecione a data',
// available tooltips: today, clear, close, selectMonth, prevMonth, nextMonth, selectYear, prevYear, nextYear, selectDecade, prevDecade, nextDecade, prevCentury, nextCentury, pickHour, incrementHour, decrementHour, pickMinute, incrementMinute, decrementMinute, pickSecond, incrementSecond, decrementSecond, togglePeriod, selectTime, selectDate
]
],
'allows_null' => true,
// 'default' => '2017-05-12 11:59:59',
],
[
'name' => 'text8',
'lable' => 'Text8',
'type' => 'tinymce',
// optional overwrite of the configuration array
'options' => [
//'selector' => 'textarea.tinymce',
//'skin' => 'dick-light',
'plugins' => 'lists advlist image link media anchor table hr imagetools importcss insertdatetime paste searchreplace textcolor textpattern help',
'menubar' => 'edit insert view format help',
'toolbar' => 'undo redo bold italic alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | table image media link',
'language' => str_replace('-', '_', app()->getLocale()),
'height' => '500px',
],
],
// [
// 'name' => 'text9',
// 'lable' => 'Text9',
// 'type' => 'base64_image',
// 'filename' => null, // set to null if not needed
// 'aspect_ratio' => 1, // set to 0 to allow any aspect ratio
// 'crop' => true, // set to true to allow cropping, false to disable
// 'src' => NULL, // null to read straight from DB, otherwise set to model accessor function
// ],
// [
// 'name' => 'text9',
// 'label' => 'Text9',
// 'type' => 'table',
// 'entity_singular' => '梯度價格', // used on the "Add X" button
// 'columns' => [
// 'name' => 'Name',
// 'desc' => 'Description',
// 'price' => 'Price'
// ],
// 'max' => 5, // maximum rows allowed in the table
// 'min' => 0, // minimum rows allowed in the table
// ],
[ // URL
'name' => 'text9',
'label' => 'text9 Link to video file on YouTube or Vimeo',
'type' => 'video',
'youtube_api_key' => 'AIzaSyDXyjzIho2thtYafQ_ofKOPEkj63Dprj58',
],
[ // URL
'name' => 'text10',
'label' => 'text10 Link to video file on YouTube or Vimeo',
'type' => 'video',
'youtube_api_key' => 'AIzaSyDXyjzIho2thtYafQ_ofKOPEkj63Dprj58',
],
[
'type' => "relationship",
'name' => 'NewsCatalog', // the method on your model that defines the relationship
'ajax' => true,
'inline_create' => true, // assumes the URL will be "/admin/category/inline/create"
]
]);
}
/**
* Define what happens when the Update operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-update
* @return void
*/
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}

View File

@ -0,0 +1,79 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\NewsCatalogRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class NewsCatalogCrudController
* @package App\Http\Controllers\Admin
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class NewsCatalogCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\InlineCreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* @return void
*/
public function setup()
{
CRUD::setModel(\App\Models\NewsCatalog::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/news-catalog');
CRUD::setEntityNameStrings('news catalog', 'news catalogs');
}
/**
* Define what happens when the List operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-list-entries
* @return void
*/
protected function setupListOperation()
{
CRUD::setFromDb(); // set columns from db columns.
/**
* Columns can be defined using the fluent syntax:
* - CRUD::column('price')->type('number');
*/
}
/**
* Define what happens when the Create operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-create
* @return void
*/
protected function setupCreateOperation()
{
CRUD::setValidation(NewsCatalogRequest::class);
CRUD::setFromDb(); // set fields from db columns.
/**
* Fields can be defined using the fluent syntax:
* - CRUD::field('price')->type('number');
*/
}
/**
* Define what happens when the Update operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-update
* @return void
*/
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}

View File

@ -0,0 +1,77 @@
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Requests\NewsRequest;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
/**
* Class NewsCrudController
* @package App\Http\Controllers\Admin
* @property-read \Backpack\CRUD\app\Library\CrudPanel\CrudPanel $crud
*/
class NewsCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
/**
* Configure the CrudPanel object. Apply settings to all operations.
*
* @return void
*/
public function setup()
{
CRUD::setModel(\App\Models\News::class);
CRUD::setRoute(config('backpack.base.route_prefix') . '/news');
CRUD::setEntityNameStrings('news', 'news');
}
/**
* Define what happens when the List operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-list-entries
* @return void
*/
protected function setupListOperation()
{
CRUD::setFromDb(); // set columns from db columns.
/**
* Columns can be defined using the fluent syntax:
* - CRUD::column('price')->type('number');
*/
}
/**
* Define what happens when the Create operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-create
* @return void
*/
protected function setupCreateOperation()
{
CRUD::setValidation(NewsRequest::class);
CRUD::setFromDb(); // set fields from db columns.
/**
* Fields can be defined using the fluent syntax:
* - CRUD::field('price')->type('number');
*/
}
/**
* Define what happens when the Update operation is loaded.
*
* @see https://backpackforlaravel.com/docs/crud-operation-update
* @return void
*/
protected function setupUpdateOperation()
{
$this->setupCreateOperation();
}
}

View File

@ -0,0 +1,347 @@
<?php
namespace App\Http\Controllers\Admin;
use Backpack\CRUD\app\Http\Controllers\CrudController;
use Backpack\PermissionManager\app\Http\Requests\UserStoreCrudRequest as StoreRequest;
use Backpack\PermissionManager\app\Http\Requests\UserUpdateCrudRequest as UpdateRequest;
use Illuminate\Support\Facades\Hash;
use Backpack\CRUD\app\Library\CrudPanel\CrudPanelFacade as CRUD;
use Backpack\CRUD\app\Library\Widget;
class UserCrudController extends CrudController
{
use \Backpack\CRUD\app\Http\Controllers\Operations\ListOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\CreateOperation { store as traitStore; }
use \Backpack\CRUD\app\Http\Controllers\Operations\UpdateOperation { update as traitUpdate; }
use \Backpack\CRUD\app\Http\Controllers\Operations\DeleteOperation { destroy as traitDestroy; }
//use \Backpack\CRUD\app\Http\Controllers\Operations\ShowOperation;
use \Backpack\CRUD\app\Http\Controllers\Operations\FetchOperation;
protected function fetchUser()
{
return $this->fetch(\App\Models\User::class);
}
public function setup()
{
$this->crud->setModel(config('backpack.permissionmanager.models.user'));
$this->crud->setEntityNameStrings(trans('backpack::permissionmanager.user'), trans('backpack::permissionmanager.users'));
$this->crud->setRoute(backpack_url('user'));
$this->crud->addClause('where', 'id', '>', '1');
$this->crud->removeAllFilters();
}
public function setupListOperation()
{
Widget::add([
'type' => 'chart',
'controller' => \App\Http\Controllers\Admin\Charts\WeeklyUsersChartController::class,
// OPTIONALS
'class' => 'card mb-2',
'wrapper' => ['class'=> 'col-md-6'] ,
'content' => [
'header' => 'New Users',
'body' => 'This chart should make it obvious how many new users have signed up in the past 7 days.<br><br>',
],
])
->to('after_content');
$this->crud->addColumns([
[
'name' => 'name',
'label' => trans('backpack::permissionmanager.name'),
'type' => 'text',
],
[
'name' => 'email',
'label' => trans('backpack::permissionmanager.email'),
'type' => 'email',
],
[ // n-n relationship (with pivot table)
'label' => trans('backpack::permissionmanager.roles'), // Table column heading
'type' => 'select_multiple',
'name' => 'roles', // the method that defines the relationship in your Model
'entity' => 'roles', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.role'), // foreign key model
],
[ // n-n relationship (with pivot table)
'label' => trans('backpack::permissionmanager.extra_permissions'), // Table column heading
'type' => 'select_multiple',
'name' => 'permissions', // the method that defines the relationship in your Model
'entity' => 'permissions', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.permission'), // foreign key model
],
]);
if (backpack_pro()) {
// Role Filter
$this->crud->addFilter(
[
'name' => 'role',
'type' => 'select2',
'label' => trans('backpack::permissionmanager.role'),
],
config('permission.models.role')::all()->pluck('name', 'id')->toArray(),
function ($value) { // if the filter is active
$this->crud->addClause('whereHas', 'roles', function ($query) use ($value) {
$query->where('role_id', '=', $value);
});
}
);
// Extra Permission Filter
// $this->crud->addFilter(
// [
// 'name' => 'permission',
// 'type' => 'select2_multiple',
// 'label' => trans('backpack::permissionmanager.extra_permissions'),
// ],
// config('permission.models.permission')::all()->pluck('name', 'id')->toArray(),
// function ($values) { // if the filter is active
// //CRUD::addClause('whereIn', 'status', json_decode($values));
// $this->crud->addClause('whereHas', 'permissions', function ($query) use ($value) {
// $query->where('permission_id', 'in', json_decode($values));
// });
// }
// );
CRUD::filter('pw')
->label(trans('backpack::permissionmanager.extra_permissions'))
->type('select2_multiple')
->values(function () {
return config('permission.models.permission')::all()->pluck('name', 'id')->toArray();
})
->whenActive(function($values) {
//var_dump($values);
// CRUD::addClause('whereIn', 'status', json_decode($values));
$this->crud->addClause('whereHas', 'permissions', function ($query) use ($values) {
$query->whereIn('permission_id', json_decode($values));
});
});
CRUD::filter('pp')
->type('select2_ajax')
// set options to customize, www.daterangepicker.com/#options
->method('POST')
->values(backpack_url('user/fetch/user'))
->whenActive(function($value) {
CRUD::addClause('where', 'id', '=', $value);
});
CRUD::filter('active')
->type('simple')
->whenActive(function() {
// CRUD::addClause('active'); // apply the "active" eloquent scope
});
CRUD::filter('created_at')
->type('date_range')
// set options to customize, www.daterangepicker.com/#options
->date_range_options([
'timePicker' => true // example: enable/disable time picker
])
->whenActive(function($value) {
// $dates = json_decode($value);
// CRUD::addClause('where', 'date', '>=', $dates->from);
// CRUD::addClause('where', 'date', '<=', $dates->to);
});
CRUD::filter('updated_at')
->type('date')
->whenActive(function($value) {
// CRUD::addClause('where', 'date', $value);
});
CRUD::filter('email')
->type('text')
->whenActive(function($value) {
CRUD::addClause('where', 'email', 'LIKE', "%$value%");
});
CRUD::filter('id')
->type('range')
->whenActive(function($value) {
$range = json_decode($value);
if ($range->from) {
CRUD::addClause('where', 'id', '>=', (float) $range->from);
}
if ($range->to) {
CRUD::addClause('where', 'id', '<=', (float) $range->to);
}
});
}
}
public function setupCreateOperation()
{
$this->addUserFields();
$this->crud->setValidation(StoreRequest::class);
}
public function setupUpdateOperation()
{
$this->addUserFields();
$this->crud->setValidation(UpdateRequest::class);
}
public function destroy($id)
{
CRUD::hasAccessOrFail('delete');
$userId = \Auth::guard(config('backpack.base.guard'))->user()->id;
if ($id == $userId)
{
return \Alert::error('不可刪除自己!');
}
return CRUD::delete($id);
}
public function setupShowOperation()
{
// automatically add the columns
$this->crud->column('name');
$this->crud->column('email');
$this->crud->column([
// two interconnected entities
'label' => trans('backpack::permissionmanager.user_role_permission'),
'field_unique_name' => 'user_role_permission',
'type' => 'checklist_dependency',
'name' => 'roles_permissions',
'subfields' => [
'primary' => [
'label' => trans('backpack::permissionmanager.role'),
'name' => 'roles', // the method that defines the relationship in your Model
'entity' => 'roles', // the method that defines the relationship in your Model
'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.role'), // foreign key model
],
'secondary' => [
'label' => mb_ucfirst(trans('backpack::permissionmanager.permission_singular')),
'name' => 'permissions', // the method that defines the relationship in your Model
'entity' => 'permissions', // the method that defines the relationship in your Model
'entity_primary' => 'roles', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.permission'), // foreign key model,
],
],
]);
$this->crud->column('created_at');
$this->crud->column('updated_at');
}
/**
* Store a newly created resource in the database.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function store()
{
$this->crud->setRequest($this->crud->validateRequest());
$this->crud->setRequest($this->handlePasswordInput($this->crud->getRequest()));
$this->crud->unsetValidation(); // validation has already been run
return $this->traitStore();
}
/**
* Update the specified resource in the database.
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update()
{
$this->crud->setRequest($this->crud->validateRequest());
$this->crud->setRequest($this->handlePasswordInput($this->crud->getRequest()));
$this->crud->unsetValidation(); // validation has already been run
return $this->traitUpdate();
}
/**
* Handle password input fields.
*/
protected function handlePasswordInput($request)
{
// Remove fields not present on the user.
$request->request->remove('password_confirmation');
$request->request->remove('roles_show');
$request->request->remove('permissions_show');
// Encrypt password if specified.
if ($request->input('password')) {
$request->request->set('password', Hash::make($request->input('password')));
} else {
$request->request->remove('password');
}
return $request;
}
protected function addUserFields()
{
$this->crud->addFields([
[
'name' => 'name',
'label' => trans('backpack::permissionmanager.name'),
'type' => 'text',
],
[
'name' => 'email',
'label' => trans('backpack::permissionmanager.email'),
'type' => 'email',
],
[
'name' => 'password',
'label' => trans('backpack::permissionmanager.password'),
'type' => 'password',
],
[
'name' => 'password_confirmation',
'label' => trans('backpack::permissionmanager.password_confirmation'),
'type' => 'password',
],
[
// two interconnected entities
'label' => trans('backpack::permissionmanager.user_role_permission'),
'field_unique_name' => 'user_role_permission',
'type' => 'checklist_dependency',
'name' => 'roles,permissions',
'subfields' => [
'primary' => [
'label' => trans('backpack::permissionmanager.roles'),
'name' => 'roles', // the method that defines the relationship in your Model
'entity' => 'roles', // the method that defines the relationship in your Model
'entity_secondary' => 'permissions', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.role'), // foreign key model
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
'number_columns' => 3, //can be 1,2,3,4,6
],
'secondary' => [
'label' => mb_ucfirst(trans('backpack::permissionmanager.permission_plural')),
'name' => 'permissions', // the method that defines the relationship in your Model
'entity' => 'permissions', // the method that defines the relationship in your Model
'entity_primary' => 'roles', // the method that defines the relationship in your Model
'attribute' => 'name', // foreign key attribute that is shown to user
'model' => config('permission.models.permission'), // foreign key model
'pivot' => true, // on create&update, do you need to add/delete pivot table entries?]
'number_columns' => 3, //can be 1,2,3,4,6
],
],
],
]);
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
class Controller extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
}

68
app/Http/Kernel.php Normal file
View File

@ -0,0 +1,68 @@
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* The application's global HTTP middleware stack.
*
* These middleware are run during every request to your application.
*
* @var array<int, class-string|string>
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Illuminate\Http\Middleware\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
/**
* The application's route middleware groups.
*
* @var array<string, array<int, class-string|string>>
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's middleware aliases.
*
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
*
* @var array<string, class-string|string>
*/
protected $middlewareAliases = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
'signed' => \App\Http\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Auth\Middleware\Authenticate as Middleware;
use Illuminate\Http\Request;
class Authenticate extends Middleware
{
/**
* Get the path the user should be redirected to when they are not authenticated.
*/
protected function redirectTo(Request $request): ?string
{
return $request->expectsJson() ? null : route('login');
}
}

View File

@ -0,0 +1,68 @@
<?php
namespace App\Http\Middleware;
use Closure;
class CheckIfAdmin
{
/**
* Checked that the logged in user is an administrator.
*
* --------------
* VERY IMPORTANT
* --------------
* If you have both regular users and admins inside the same table, change
* the contents of this method to check that the logged in user
* is an admin, and not a regular user.
*
* Additionally, in Laravel 7+, you should change app/Providers/RouteServiceProvider::HOME
* which defines the route where a logged in user (but not admin) gets redirected
* when trying to access an admin route. By default it's '/home' but Backpack
* does not have a '/home' route, use something you've built for your users
* (again - users, not admins).
*
* @param \Illuminate\Contracts\Auth\Authenticatable|null $user
* @return bool
*/
private function checkIfUserIsAdmin($user)
{
// return ($user->is_admin == 1);
return true;
}
/**
* Answer to unauthorized access request.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
*/
private function respondToUnauthorizedRequest($request)
{
if ($request->ajax() || $request->wantsJson()) {
return response(trans('backpack::base.unauthorized'), 401);
} else {
return redirect()->guest(backpack_url('login'));
}
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if (backpack_auth()->guest()) {
return $this->respondToUnauthorizedRequest($request);
}
if (! $this->checkIfUserIsAdmin(backpack_user())) {
return $this->respondToUnauthorizedRequest($request);
}
return $next($request);
}
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware;
class PreventRequestsDuringMaintenance extends Middleware
{
/**
* The URIs that should be reachable while maintenance mode is enabled.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,30 @@
<?php
namespace App\Http\Middleware;
use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class RedirectIfAuthenticated
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next, string ...$guards): Response
{
$guards = empty($guards) ? [null] : $guards;
foreach ($guards as $guard) {
if (Auth::guard($guard)->check()) {
return redirect(RouteServiceProvider::HOME);
}
}
return $next($request);
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array<int, string>
*/
protected $except = [
'current_password',
'password',
'password_confirmation',
];
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustHosts as Middleware;
class TrustHosts extends Middleware
{
/**
* Get the host patterns that should be trusted.
*
* @return array<int, string|null>
*/
public function hosts(): array
{
return [
$this->allSubdomainsOfApplicationUrl(),
];
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Middleware\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The trusted proxies for this application.
*
* @var array<int, string>|string|null
*/
protected $proxies;
/**
* The headers that should be used to detect proxies.
*
* @var int
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Routing\Middleware\ValidateSignature as Middleware;
class ValidateSignature extends Middleware
{
/**
* The names of the query string parameters that should be ignored.
*
* @var array<int, string>
*/
protected $except = [
// 'fbclid',
// 'utm_campaign',
// 'utm_content',
// 'utm_medium',
// 'utm_source',
// 'utm_term',
];
}

View File

@ -0,0 +1,17 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
*
* @var array<int, string>
*/
protected $except = [
//
];
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class DemoCatalogsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// 'name' => 'required|min:5|max:255'
];
}
/**
* Get the validation attributes that apply to the request.
*
* @return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* @return array
*/
public function messages()
{
return [
//
];
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class NewsCatalogRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// 'name' => 'required|min:5|max:255'
];
}
/**
* Get the validation attributes that apply to the request.
*
* @return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* @return array
*/
public function messages()
{
return [
//
];
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class NewsRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// 'name' => 'required|min:5|max:255'
];
}
/**
* Get the validation attributes that apply to the request.
*
* @return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* @return array
*/
public function messages()
{
return [
//
];
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
// only allow updates if the user is logged in
return backpack_auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
// 'name' => 'required|min:5|max:255'
];
}
/**
* Get the validation attributes that apply to the request.
*
* @return array
*/
public function attributes()
{
return [
//
];
}
/**
* Get the validation messages that apply to the request.
*
* @return array
*/
public function messages()
{
return [
//
];
}
}

View File

@ -0,0 +1,96 @@
<?php
namespace App\Models;
use Ericli1018\AwesomeFieldsForBackpack\Models\Traits\HasUploadImgFields;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class DemoCatalogs extends Model
{
use CrudTrait;
use HasFactory;
use HasUploadImgFields;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/
protected $table = 'demo_catalogs';
// protected $primaryKey = 'id';
// public $timestamps = false;
protected $guarded = ['id'];
// protected $fillable = [];
// protected $hidden = [];
protected $casts = [
'photos' => 'array',
'text3' => 'array',
'text4' => 'datetime',
'text5' => 'datetime',
'text6' => 'datetime',
'text7' => 'datetime'
];
/*
|--------------------------------------------------------------------------
| FUNCTIONS
|--------------------------------------------------------------------------
*/
public static function boot()
{
parent::boot();
static::deleting(function($obj) {
if (count((array)$obj->photos)) {
foreach ($obj->photos as $item) {
\Storage::disk('public')->delete($item['file_path']);
}
}
});
}
/*
|--------------------------------------------------------------------------
| RELATIONS
|--------------------------------------------------------------------------
*/
public function NewsCatalog() : BelongsTo
{
return $this->belongsTo('App\Models\NewsCatalog', 'int1', 'id');
}
/*
|--------------------------------------------------------------------------
| SCOPES
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| ACCESSORS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| MUTATORS
|--------------------------------------------------------------------------
*/
public function setPhotosAttribute($value)
{
$attribute_name = "photos";
$disk = "public";
$destination_path = "demo_catalogs";
$this->uploadImgMultipleFilesToDisk($value, $attribute_name, $disk, $destination_path);
}
/**
* for datetime picker
*/
public function setDatetimeAttribute($value) {
$this->attributes['datetime'] = \Carbon\Carbon::parse($value);
}
}

56
app/Models/News.php Normal file
View File

@ -0,0 +1,56 @@
<?php
namespace App\Models;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class News extends Model
{
use CrudTrait;
use HasFactory;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/
protected $table = 'news';
// protected $primaryKey = 'id';
// public $timestamps = false;
protected $guarded = ['id'];
// protected $fillable = [];
// protected $hidden = [];
/*
|--------------------------------------------------------------------------
| FUNCTIONS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| RELATIONS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| SCOPES
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| ACCESSORS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| MUTATORS
|--------------------------------------------------------------------------
*/
}

View File

@ -0,0 +1,59 @@
<?php
namespace App\Models;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class NewsCatalog extends Model
{
use CrudTrait;
use HasFactory;
/*
|--------------------------------------------------------------------------
| GLOBAL VARIABLES
|--------------------------------------------------------------------------
*/
protected $table = 'news_catalogs';
// protected $primaryKey = 'id';
// public $timestamps = false;
protected $guarded = ['id'];
// protected $fillable = [];
// protected $hidden = [];
/*
|--------------------------------------------------------------------------
| FUNCTIONS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| RELATIONS
|--------------------------------------------------------------------------
*/
public function demo_catalogys()
{
return $this->hasMany('App\Models\DemoCatalogs', 'int1', 'id');
}
/*
|--------------------------------------------------------------------------
| SCOPES
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| ACCESSORS
|--------------------------------------------------------------------------
*/
/*
|--------------------------------------------------------------------------
| MUTATORS
|--------------------------------------------------------------------------
*/
}

49
app/Models/User.php Normal file
View File

@ -0,0 +1,49 @@
<?php
namespace App\Models;
use Backpack\CRUD\app\Models\Traits\CrudTrait;
use Spatie\Permission\Traits\HasRoles;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use CrudTrait;
use HasRoles;
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
$this->app->bind(
\Backpack\PermissionManager\app\Http\Controllers\UserCrudController::class, //this is package controller
\App\Http\Controllers\Admin\UserCrudController::class //this should be your own controller
);
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Schema::defaultStringLength(191);
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Providers;
// use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The model to policy mappings for the application.
*
* @var array<class-string, class-string>
*/
protected $policies = [
//
];
/**
* Register any authentication / authorization services.
*/
public function boot(): void
{
//
}
}

View File

@ -0,0 +1,19 @@
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Broadcast;
use Illuminate\Support\ServiceProvider;
class BroadcastServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Broadcast::routes();
require base_path('routes/channels.php');
}
}

View File

@ -0,0 +1,38 @@
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
/**
* The event to listener mappings for the application.
*
* @var array<class-string, array<int, class-string>>
*/
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
],
];
/**
* Register any events for your application.
*/
public function boot(): void
{
//
}
/**
* Determine if events and listeners should be automatically discovered.
*/
public function shouldDiscoverEvents(): bool
{
return false;
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Providers;
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
class RouteServiceProvider extends ServiceProvider
{
/**
* The path to your application's "home" route.
*
* Typically, users are redirected here after authentication.
*
* @var string
*/
public const HOME = '/home';
/**
* Define your route model bindings, pattern filters, and other route configuration.
*/
public function boot(): void
{
RateLimiter::for('api', function (Request $request) {
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
});
$this->routes(function () {
Route::middleware('api')
->prefix('api')
->group(base_path('routes/api.php'));
Route::middleware('web')
->group(base_path('routes/web.php'));
});
}
}