完成後台編輯文章架構
This commit is contained in:
parent
31286d4e85
commit
142d787436
42
app/Console/Commands/CreatePostType.php
Normal file
42
app/Console/Commands/CreatePostType.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class CreatePostType extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'command:name';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Command description';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
88
app/Console/Commands/GeneratePosts.php
Normal file
88
app/Console/Commands/GeneratePosts.php
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Post;
|
||||||
|
use App\User;
|
||||||
|
use App\Repositories\PostRepository;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class GeneratePosts extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'post:generate {postType} {amount?} {--user_id=}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Generate posts';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$user_id = $this->option('user_id');
|
||||||
|
if($user_id) {
|
||||||
|
$user = User::find($user_id);
|
||||||
|
if(!$user) {
|
||||||
|
throw new \Exception("User $user_id doesn't exist");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$user = User::inRandomOrder()->first();
|
||||||
|
if(!$user) {
|
||||||
|
throw new \Exception("User $user_id doesn't exist");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$amount = $this->argument('amount');
|
||||||
|
if(!$amount) {
|
||||||
|
$amount = 1;
|
||||||
|
}
|
||||||
|
$postType = $this->argument('postType');
|
||||||
|
$postTypes = config('postTypes');
|
||||||
|
if(array_key_exists($postType, $postTypes)) {
|
||||||
|
/** @var Post $model */
|
||||||
|
$postRepo = new PostRepository($postTypes[$postType]['model']);
|
||||||
|
$faker = \Faker\Factory::create();
|
||||||
|
for($i = 0; $i < $amount; $i++) {
|
||||||
|
$post = $postRepo->createModel();
|
||||||
|
$post->fill([
|
||||||
|
'title' => $this->randomTextLength($faker, 10, 25),
|
||||||
|
'excerpt' => $this->randomTextLength($faker, 10, 30),
|
||||||
|
'introduction' => $faker->realText($faker->numberBetween(20, 400)),
|
||||||
|
'user_id' => $user->id
|
||||||
|
]);
|
||||||
|
$post->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function randomTextLength($faker, $min, $max)
|
||||||
|
{
|
||||||
|
return mb_substr($this->rtrim($faker->realText($max)), 0, $faker->numberBetween($min, $max - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function rtrim($text)
|
||||||
|
{
|
||||||
|
return mb_substr($text, 0, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Articles;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ArticlesMenuItemController extends BaseMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.articles.articles';
|
||||||
|
|
||||||
|
$this->slug = 'articles';
|
||||||
|
|
||||||
|
$this->permissions = ['admin manage post articles'];
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Articles\Children;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
|
||||||
|
use App\Http\Controllers\Admin\Menu\PostCreateMenuItemController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class CreateMenuItemController extends PostCreateMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.articles.create';
|
||||||
|
|
||||||
|
$this->slug = 'create';
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
|
||||||
|
$this->postType = 'article';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Articles\Children;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\PostListMenuItemController;
|
||||||
|
|
||||||
|
class ListMenuItemController extends PostListMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.articles.list';
|
||||||
|
|
||||||
|
$this->slug = 'list';
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
|
||||||
|
$this->postType = 'article';
|
||||||
|
|
||||||
|
$this->pageHeader = trans('adminPageHeader.articles.articles');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Portfolios\Children;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\PostCreateMenuItemController;
|
||||||
|
|
||||||
|
class CreateMenuItemController extends PostCreateMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.portfolios.create';
|
||||||
|
|
||||||
|
$this->slug = 'create';
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
|
||||||
|
$this->postType = 'portfolio';
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Portfolios\Children;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\PostListMenuItemController;
|
||||||
|
|
||||||
|
class ListMenuItemController extends PostListMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.portfolios.list';
|
||||||
|
|
||||||
|
$this->slug = 'list';
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
|
||||||
|
$this->postType = 'portfolio';
|
||||||
|
|
||||||
|
$this->pageHeader = trans('adminPageHeader.portfolios.portfolios');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu\Portfolios;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Admin\Menu\BaseMenuItemController;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PortfoliosMenuItemController extends BaseMenuItemController
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->name = 'adminMenu.items.portfolios.portfolios';
|
||||||
|
|
||||||
|
$this->slug = 'portfolios';
|
||||||
|
|
||||||
|
$this->permissions = ['admin manage post portfolio'];
|
||||||
|
|
||||||
|
$this->iconClasses = 'nav-icon icon-wrench';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle(Request $request)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PostCreateMenuItemController extends BaseMenuItemController
|
||||||
|
{
|
||||||
|
protected $postType;
|
||||||
|
|
||||||
|
public function handle(Request $request)
|
||||||
|
{
|
||||||
|
$languages = app('SiteState')->languageTranslations;
|
||||||
|
return view('admin.menu.posts.edit', [
|
||||||
|
'adminRouteNamePrefix' => config('admin.route_name_prefix'),
|
||||||
|
'languages' => $languages,
|
||||||
|
'post' => null,
|
||||||
|
'resource' => $this->postType
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin\Menu;
|
||||||
|
|
||||||
|
use App\Repositories\PostRepository;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PostListMenuItemController extends BaseMenuItemController
|
||||||
|
{
|
||||||
|
protected $postType;
|
||||||
|
|
||||||
|
protected $pageHeader;
|
||||||
|
|
||||||
|
public function handle(Request $request)
|
||||||
|
{
|
||||||
|
$postTypes = config('postTypes.' . $this->postType);
|
||||||
|
$postRepo = new PostRepository($postTypes['model']);
|
||||||
|
$posts = $postRepo->getPostsPager();
|
||||||
|
return view('admin.menu.posts.list', [
|
||||||
|
'adminRouteNamePrefix' => config('admin.route_name_prefix'),
|
||||||
|
'resource' => $this->postType,
|
||||||
|
'pageHeader' => $this->pageHeader,
|
||||||
|
'posts' => $posts
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
app/Http/Controllers/Admin/PostController.php
Normal file
106
app/Http/Controllers/Admin/PostController.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use App\Traits\ModelAttributeTranslationsUpdattable;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Auth;
|
||||||
|
|
||||||
|
class PostController extends Controller
|
||||||
|
{
|
||||||
|
use ModelAttributeTranslationsUpdattable;
|
||||||
|
|
||||||
|
private function getModelClass($resource)
|
||||||
|
{
|
||||||
|
return config('postTypes.' . $resource)['model'];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getResource(Request $request)
|
||||||
|
{
|
||||||
|
return explode('.', str_replace(config('admin.route_name_prefix'), '', $request->route()->getName()))[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit(Request $request, $postId)
|
||||||
|
{
|
||||||
|
$resource = $this->getResource($request);
|
||||||
|
$modelClass = $this->getModelClass($resource);
|
||||||
|
$post = $modelClass::find($postId);
|
||||||
|
$languages = app('SiteState')->languageTranslations;
|
||||||
|
return view('admin.menu.posts.edit', [
|
||||||
|
'adminRouteNamePrefix' => config('admin.route_name_prefix'),
|
||||||
|
'resource' => $resource,
|
||||||
|
'post' => $post,
|
||||||
|
'languages' => $languages
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
return $this->update($request, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(Request $request, $postId)
|
||||||
|
{
|
||||||
|
$defaultLocale = config('app.locale');
|
||||||
|
$resource = $this->getResource($request);
|
||||||
|
$modelClass = $this->getModelClass($resource);
|
||||||
|
|
||||||
|
/** @var \App\Post $post */
|
||||||
|
if($postId) {
|
||||||
|
$post = $modelClass::find($postId);
|
||||||
|
} else {
|
||||||
|
$post = app($modelClass);
|
||||||
|
$translatableAttributes = $post->getTranslatableAttributes();
|
||||||
|
$translatableAttributeValues = $request->all($translatableAttributes);
|
||||||
|
$translatableAttributeValues = collect($translatableAttributeValues)->map(function($translatableAttributeValue) use ($defaultLocale){
|
||||||
|
return $translatableAttributeValue[$defaultLocale];
|
||||||
|
});
|
||||||
|
$post = $modelClass::create(array_merge($translatableAttributeValues->toArray(), [
|
||||||
|
'user_id' => Auth::id()
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Post的可翻譯屬性
|
||||||
|
$translatableAttributes = $post->getTranslatableAttributes();
|
||||||
|
// 更新所有可翻譯的屬性
|
||||||
|
foreach ($translatableAttributes as $translatableAttribute) {
|
||||||
|
$translations = $request->get($translatableAttribute);
|
||||||
|
if($translations) {
|
||||||
|
$this->updateAttributeTranslations($post, $translatableAttribute, $translations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$post->fill([
|
||||||
|
'feature_image_id' => $request->get('feature_image_id')
|
||||||
|
]);
|
||||||
|
$post->save();
|
||||||
|
|
||||||
|
return redirect(route(config('admin.route_name_prefix') . $resource . '.edit', [$resource => $post->id]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show(Request $request)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function destroy(Request $request, $postId)
|
||||||
|
{
|
||||||
|
$resource = $this->getResource($request);
|
||||||
|
$modelClass = $this->getModelClass($resource);
|
||||||
|
|
||||||
|
$post = $modelClass::find($postId);
|
||||||
|
$post->delete();
|
||||||
|
return back();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
app/Post.php
14
app/Post.php
@ -9,4 +9,18 @@ abstract class Post extends TranslatableModel
|
|||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'title', 'content', 'excerpt', 'user_id', 'feature_image_id'
|
'title', 'content', 'excerpt', 'user_id', 'feature_image_id'
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected $translatableAttributes = [
|
||||||
|
'title', 'content', 'excerpt'
|
||||||
|
];
|
||||||
|
|
||||||
|
public function author()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'user_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function featureImage()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MediaFile::class, 'feature_image_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class MainMenuItemPresenter
|
|||||||
case 'title':
|
case 'title':
|
||||||
$html .= $htmlPresenter->li([
|
$html .= $htmlPresenter->li([
|
||||||
'class' => 'nav-title',
|
'class' => 'nav-title',
|
||||||
'html' => trans('menu.titles.' . $item['name'])
|
'html' => trans('adminMenu.titles.' . $item['name'])
|
||||||
]);
|
]);
|
||||||
break;
|
break;
|
||||||
case 'item':
|
case 'item':
|
||||||
|
|||||||
60
app/Presenters/Admin/MediaSelectionFieldPresenter.php
Normal file
60
app/Presenters/Admin/MediaSelectionFieldPresenter.php
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
namespace App\Presenters\Admin;
|
||||||
|
|
||||||
|
use App\Repositories\MediaFileRepository;
|
||||||
|
|
||||||
|
class MediaSelectionFieldPresenter
|
||||||
|
{
|
||||||
|
public function render($mediaFileId = null, $inputHtmlArgs = [], $wrapperClasses = [])
|
||||||
|
{
|
||||||
|
$presenter = app('Html');
|
||||||
|
$mediaFileRepo = app(MediaFileRepository::class);
|
||||||
|
$mediaFile = $mediaFileRepo->findModel($mediaFileId);
|
||||||
|
$previewImgHtml = '';
|
||||||
|
$mediaFieldContentHtml = '';
|
||||||
|
if($mediaFile) {
|
||||||
|
$previewImgHtml = $presenter->img([
|
||||||
|
'src' => $mediaFile->url
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$mediaFieldContentHtml .= $presenter->input(array_merge([
|
||||||
|
'type' => 'hidden',
|
||||||
|
'class' => 'input',
|
||||||
|
'value' => $mediaFileId
|
||||||
|
], $inputHtmlArgs));
|
||||||
|
$mediaFieldContentHtml .= $presenter->div([
|
||||||
|
'class' => 'form-group row',
|
||||||
|
'html' => $presenter->div([
|
||||||
|
'class' => 'col-6',
|
||||||
|
'html' => $presenter->div([
|
||||||
|
'class' => 'preview',
|
||||||
|
'html' => $previewImgHtml
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
$mediaFieldContentHtml .= $presenter->div([
|
||||||
|
'class' => 'form-group row',
|
||||||
|
'html' => [
|
||||||
|
$presenter->div([
|
||||||
|
'class' => 'col-3',
|
||||||
|
'html' => $presenter->button([
|
||||||
|
'class' => ['btn', 'btn-success', 'select-media'],
|
||||||
|
'html' => trans('form.buttons.select')
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
$presenter->div([
|
||||||
|
'class' => 'col-3',
|
||||||
|
'html' => $presenter->button([
|
||||||
|
'class' => ['btn', 'btn-danger', 'clear-media'],
|
||||||
|
'style' => !$mediaFile ? 'display:none;' : '',
|
||||||
|
'html' => trans('form.buttons.remove')
|
||||||
|
])
|
||||||
|
])
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
return $presenter->div([
|
||||||
|
'class' => array_merge($wrapperClasses, ['media-selection-field']),
|
||||||
|
'html' => $mediaFieldContentHtml
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,7 +12,7 @@ class OptionFormFieldsPresenter
|
|||||||
$options = config('admin.options.' . $page);
|
$options = config('admin.options.' . $page);
|
||||||
$presenter = app('Html');
|
$presenter = app('Html');
|
||||||
$optionRepo = app('Option');
|
$optionRepo = app('Option');
|
||||||
$mediaFileRepo = app(MediaFileRepository::class);
|
$mediaSelectionFieldPresenter = app(MediaSelectionFieldPresenter::class);
|
||||||
$html = '';
|
$html = '';
|
||||||
if(!empty($options['fields'])) {
|
if(!empty($options['fields'])) {
|
||||||
foreach($options['fields'] as $key => $option) {
|
foreach($options['fields'] as $key => $option) {
|
||||||
@ -37,7 +37,7 @@ class OptionFormFieldsPresenter
|
|||||||
]),
|
]),
|
||||||
$presenter->div([
|
$presenter->div([
|
||||||
'class' => 'col-12 col-md-6',
|
'class' => 'col-12 col-md-6',
|
||||||
'html' => function() use ($key, $type, $required, $presenter, $optionRepo, $mediaFileRepo) {
|
'html' => function() use ($key, $type, $required, $presenter, $optionRepo, $mediaSelectionFieldPresenter) {
|
||||||
$html = '';
|
$html = '';
|
||||||
|
|
||||||
$bastHtmlArgs = [
|
$bastHtmlArgs = [
|
||||||
@ -46,54 +46,8 @@ class OptionFormFieldsPresenter
|
|||||||
];
|
];
|
||||||
switch ($type) {
|
switch ($type) {
|
||||||
case 'media':
|
case 'media':
|
||||||
$mediaFiledId = $optionRepo->$key;
|
$mediaFileId = $optionRepo->$key;
|
||||||
$mediaFile = $mediaFileRepo->findModel($mediaFiledId);
|
$html .= $mediaSelectionFieldPresenter->render($mediaFileId, $bastHtmlArgs, ['option-media-field']);
|
||||||
$previewImgHtml = '';
|
|
||||||
$mediaFieldContentHtml = '';
|
|
||||||
if($mediaFile) {
|
|
||||||
$previewImgHtml = $presenter->img([
|
|
||||||
'src' => $mediaFile->url
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
$mediaFieldContentHtml .= $presenter->input(array_merge([
|
|
||||||
'type' => 'hidden',
|
|
||||||
'class' => 'input',
|
|
||||||
'value' => $mediaFiledId
|
|
||||||
], $bastHtmlArgs));
|
|
||||||
$mediaFieldContentHtml .= $presenter->div([
|
|
||||||
'class' => 'form-group row',
|
|
||||||
'html' => $presenter->div([
|
|
||||||
'class' => 'col-6',
|
|
||||||
'html' => $presenter->div([
|
|
||||||
'class' => 'preview',
|
|
||||||
'html' => $previewImgHtml
|
|
||||||
])
|
|
||||||
])
|
|
||||||
]);
|
|
||||||
$mediaFieldContentHtml .= $presenter->div([
|
|
||||||
'class' => 'form-group row',
|
|
||||||
'html' => [
|
|
||||||
$presenter->div([
|
|
||||||
'class' => 'col-3',
|
|
||||||
'html' => $presenter->button([
|
|
||||||
'class' => ['btn', 'btn-success', 'select-media'],
|
|
||||||
'html' => trans('form.buttons.select')
|
|
||||||
])
|
|
||||||
]),
|
|
||||||
$presenter->div([
|
|
||||||
'class' => 'col-3',
|
|
||||||
'html' => $presenter->button([
|
|
||||||
'class' => ['btn', 'btn-danger', 'clear-media'],
|
|
||||||
'style' => !$mediaFile ? 'display:none;' : '',
|
|
||||||
'html' => trans('form.buttons.remove')
|
|
||||||
])
|
|
||||||
])
|
|
||||||
]
|
|
||||||
]);
|
|
||||||
$html .= $presenter->div([
|
|
||||||
'class' => 'option-media-field',
|
|
||||||
'html' => $mediaFieldContentHtml
|
|
||||||
]);
|
|
||||||
break;
|
break;
|
||||||
case 'text':
|
case 'text':
|
||||||
case 'password':
|
case 'password':
|
||||||
|
|||||||
27
app/Repositories/PostRepository.php
Normal file
27
app/Repositories/PostRepository.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repositories;
|
||||||
|
|
||||||
|
use App\Post;
|
||||||
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
|
|
||||||
|
class PostRepository extends BaseRepository
|
||||||
|
{
|
||||||
|
public function __construct($model)
|
||||||
|
{
|
||||||
|
if(is_string($model)) {
|
||||||
|
$this->setModel(app($model));
|
||||||
|
} elseif($model instanceof Post) {
|
||||||
|
$this->setModel($model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $postsPerPage
|
||||||
|
* @return LengthAwarePaginator
|
||||||
|
*/
|
||||||
|
public function getPostsPager($postsPerPage = 15)
|
||||||
|
{
|
||||||
|
return $this->getModelClass()::orderByDesc('created_at')->paginate($postsPerPage);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
app/Traits/ModelAttributeTranslationsUpdattable.php
Normal file
26
app/Traits/ModelAttributeTranslationsUpdattable.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use App\Repositories\ModelTranslationRepository;
|
||||||
|
|
||||||
|
trait ModelAttributeTranslationsUpdattable
|
||||||
|
{
|
||||||
|
private function updateAttributeTranslations($model, $attribute, $translations)
|
||||||
|
{
|
||||||
|
$transRepo = app(ModelTranslationRepository::class);
|
||||||
|
$transRepo->setTranslatedModel($model);
|
||||||
|
$locales = app('SiteState')->languages;
|
||||||
|
$defaultLocale = config('app.locale');
|
||||||
|
|
||||||
|
foreach ($translations as $locale => $translation) {
|
||||||
|
if(in_array($locale, $locales)) {
|
||||||
|
$transRepo->updateModelTranslation($model->id, $attribute, $locale, $translation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(isset($translations[$defaultLocale])) {
|
||||||
|
$model->$attribute = $translations[$defaultLocale];
|
||||||
|
$model->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -8,6 +8,29 @@ return [
|
|||||||
'route_name_prefix' => 'admin.',
|
'route_name_prefix' => 'admin.',
|
||||||
// 後台選單項目
|
// 後台選單項目
|
||||||
'menuItems' => [
|
'menuItems' => [
|
||||||
|
[
|
||||||
|
'type' => 'title',
|
||||||
|
'name' => 'posts',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'item',
|
||||||
|
'controller' => Menu\Articles\ArticlesMenuItemController::class,
|
||||||
|
'children' => [
|
||||||
|
Menu\Articles\Children\ListMenuItemController::class,
|
||||||
|
Menu\Articles\Children\CreateMenuItemController::class,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'item',
|
||||||
|
'controller' => Menu\Portfolios\PortfoliosMenuItemController::class,
|
||||||
|
'children' => [
|
||||||
|
Menu\Portfolios\Children\ListMenuItemController::class,
|
||||||
|
Menu\Portfolios\Children\CreateMenuItemController::class,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'type' => 'divider'
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'type' => 'item',
|
'type' => 'item',
|
||||||
'controller' => Menu\Options\OptionsMenuItemController::class,
|
'controller' => Menu\Options\OptionsMenuItemController::class,
|
||||||
|
|||||||
9
config/postTypes.php
Normal file
9
config/postTypes.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
return [
|
||||||
|
'article' => [
|
||||||
|
'model' => \App\Article::class
|
||||||
|
],
|
||||||
|
'portfolio' => [
|
||||||
|
'model' => \App\Portfolio::class
|
||||||
|
],
|
||||||
|
];
|
||||||
@ -1,5 +0,0 @@
|
|||||||
<?php
|
|
||||||
return [
|
|
||||||
\App\Article::class,
|
|
||||||
\App\Portfolio::class,
|
|
||||||
];
|
|
||||||
29
resources/js/admin/app.js
vendored
29
resources/js/admin/app.js
vendored
@ -106,4 +106,33 @@ $(() => {
|
|||||||
$('#app-header .medialibrary').on('click', function(){
|
$('#app-header .medialibrary').on('click', function(){
|
||||||
app.adminMediaLibrary = app.methods.media(false, null, false);
|
app.adminMediaLibrary = app.methods.media(false, null, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('.media-selection-field .select-media').on('click', e => {
|
||||||
|
e.preventDefault()
|
||||||
|
let $this = $(e.currentTarget),
|
||||||
|
$wrapper = $this.closest('.media-selection-field'),
|
||||||
|
$input = $wrapper.find('input'),
|
||||||
|
$preview = $wrapper.find('.preview'),
|
||||||
|
$clearButton = $wrapper.find('.clear-media')
|
||||||
|
|
||||||
|
app.methods.media(true, $input.get(0), true, (data) => {
|
||||||
|
let media = data.medias[0]
|
||||||
|
$preview.empty().append(
|
||||||
|
$('<img>').attr('src', media.url)
|
||||||
|
)
|
||||||
|
$clearButton.show()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
$('.media-selection-field .clear-media').on('click', e => {
|
||||||
|
e.preventDefault()
|
||||||
|
let $this = $(e.currentTarget),
|
||||||
|
$wrapper = $this.closest('.media-selection-field'),
|
||||||
|
$input = $wrapper.find('input'),
|
||||||
|
$preview = $wrapper.find('.preview')
|
||||||
|
|
||||||
|
$input.val(null)
|
||||||
|
$preview.empty()
|
||||||
|
$this.hide()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
28
resources/js/admin/page/options.js
vendored
28
resources/js/admin/page/options.js
vendored
@ -1,28 +0,0 @@
|
|||||||
$('.select-media').on('click', e => {
|
|
||||||
e.preventDefault()
|
|
||||||
let $this = $(e.currentTarget),
|
|
||||||
$wrapper = $this.closest('.option-media-field'),
|
|
||||||
$input = $wrapper.find('input'),
|
|
||||||
$preview = $wrapper.find('.preview'),
|
|
||||||
$clearButton = $wrapper.find('.clear-media')
|
|
||||||
|
|
||||||
app.methods.media(true, $input.get(0), true, (data) => {
|
|
||||||
let media = data.medias[0]
|
|
||||||
$preview.empty().append(
|
|
||||||
$('<img>').attr('src', media.url)
|
|
||||||
)
|
|
||||||
$clearButton.show()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
$('.clear-media').on('click', e => {
|
|
||||||
e.preventDefault()
|
|
||||||
let $this = $(e.currentTarget),
|
|
||||||
$wrapper = $this.closest('.option-media-field'),
|
|
||||||
$input = $wrapper.find('input'),
|
|
||||||
$preview = $wrapper.find('.preview')
|
|
||||||
|
|
||||||
$input.val(null)
|
|
||||||
$preview.empty()
|
|
||||||
$this.hide()
|
|
||||||
})
|
|
||||||
@ -12,6 +12,19 @@ return array(
|
|||||||
'routes' => 'Route List',
|
'routes' => 'Route List',
|
||||||
'system' => 'System',
|
'system' => 'System',
|
||||||
'gateAbilities' => 'Gate Abilities',
|
'gateAbilities' => 'Gate Abilities',
|
||||||
|
],
|
||||||
|
'articles' => [
|
||||||
|
'articles' => 'Articles',
|
||||||
|
'list' => 'List',
|
||||||
|
'create' => 'Create',
|
||||||
|
],
|
||||||
|
'portfolios' => [
|
||||||
|
'portfolios' => 'Portfolios',
|
||||||
|
'list' => 'List',
|
||||||
|
'create' => 'Create'
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
'titles' => [
|
||||||
|
'posts' => 'Posts'
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|||||||
@ -6,4 +6,10 @@ return [
|
|||||||
'development' => 'Development Settings',
|
'development' => 'Development Settings',
|
||||||
'platform' => 'Platform Settings',
|
'platform' => 'Platform Settings',
|
||||||
],
|
],
|
||||||
|
'articles' => [
|
||||||
|
'articles' => 'Articles'
|
||||||
|
],
|
||||||
|
'portfolios' => [
|
||||||
|
'portfolios' => 'Portfolios'
|
||||||
|
]
|
||||||
];
|
];
|
||||||
|
|||||||
@ -3,6 +3,19 @@ return [
|
|||||||
'buttons' => [
|
'buttons' => [
|
||||||
'update' => 'Update',
|
'update' => 'Update',
|
||||||
'select' => 'Select',
|
'select' => 'Select',
|
||||||
'remove' => 'Remove'
|
'remove' => 'Remove',
|
||||||
|
'create' => 'Create',
|
||||||
|
'delete' => 'Delete',
|
||||||
|
'logout' => 'Logout',
|
||||||
|
],
|
||||||
|
'titles' => [
|
||||||
|
'title' => 'Title',
|
||||||
|
'author' => 'Author',
|
||||||
|
'created' => 'Created',
|
||||||
|
'updated' => 'Updated',
|
||||||
|
'operations' => 'Operations',
|
||||||
|
'excerpt' => 'Excerpt',
|
||||||
|
'content' => 'Content',
|
||||||
|
'featureImage' => 'Feature Image'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|||||||
9
resources/lang/en/languages.php
Normal file
9
resources/lang/en/languages.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return array (
|
||||||
|
'en' => 'English',
|
||||||
|
'zh-tw' => 'Chinese Traditional',
|
||||||
|
'zh-cn' => 'Chinese Simplified',
|
||||||
|
'ja' => 'Japanese',
|
||||||
|
'ko' => 'Korean',
|
||||||
|
);
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
|
'mediaLibrary' => 'Media Library',
|
||||||
'tabCategory' => 'Category',
|
'tabCategory' => 'Category',
|
||||||
'tabUpload' => 'Upload',
|
'tabUpload' => 'Upload',
|
||||||
'tabBrowse' => 'Browse',
|
'tabBrowse' => 'Browse',
|
||||||
|
|||||||
30
resources/lang/zh-tw/adminMenu.php
Normal file
30
resources/lang/zh-tw/adminMenu.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
return array(
|
||||||
|
'items' => [
|
||||||
|
'options' => [
|
||||||
|
'options' => '設定',
|
||||||
|
'general' => '一般',
|
||||||
|
'development' => '開發',
|
||||||
|
'platform' => '平台',
|
||||||
|
],
|
||||||
|
'systemStatus' => [
|
||||||
|
'systemStatus' => '系統狀態',
|
||||||
|
'routes' => '路由列表',
|
||||||
|
'system' => '系統資訊',
|
||||||
|
'gateAbilities' => 'Gate能力列表',
|
||||||
|
],
|
||||||
|
'articles' => [
|
||||||
|
'articles' => '文章',
|
||||||
|
'list' => '列表',
|
||||||
|
'create' => '建立',
|
||||||
|
],
|
||||||
|
'portfolios' => [
|
||||||
|
'portfolios' => '作品集',
|
||||||
|
'list' => '列表',
|
||||||
|
'create' => '建立'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'titles' => [
|
||||||
|
'posts' => '文章內容'
|
||||||
|
]
|
||||||
|
);
|
||||||
9
resources/lang/zh-tw/languages.php
Normal file
9
resources/lang/zh-tw/languages.php
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return array (
|
||||||
|
'en' => '英文',
|
||||||
|
'zh-tw' => '繁體中文',
|
||||||
|
'zh-cn' => '簡體中文',
|
||||||
|
'ja' => '日文',
|
||||||
|
'ko' => '韓文',
|
||||||
|
);
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
|
'mediaLibrary' => '媒體庫',
|
||||||
'category' => '分類',
|
'category' => '分類',
|
||||||
'date' => '日期',
|
'date' => '日期',
|
||||||
'delete' => '刪除',
|
'delete' => '刪除',
|
||||||
|
|||||||
18
resources/sass/admin/app.scss
vendored
18
resources/sass/admin/app.scss
vendored
@ -5,3 +5,21 @@
|
|||||||
@import "components/blockui";
|
@import "components/blockui";
|
||||||
@import "../components/media-library";
|
@import "../components/media-library";
|
||||||
@import "../app-common";
|
@import "../app-common";
|
||||||
|
//媒體庫圖片預覽
|
||||||
|
.media-selection-field {
|
||||||
|
.preview {
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//左側主選單子項目
|
||||||
|
.sidebar-nav {
|
||||||
|
ul.submenu {
|
||||||
|
li.nav-item {
|
||||||
|
a.nav-link {
|
||||||
|
padding: 0.3rem 0.6rem 0.3rem 1.4rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
5
resources/sass/admin/page/post-list.scss
vendored
Normal file
5
resources/sass/admin/page/post-list.scss
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
td.feature-image {
|
||||||
|
img {
|
||||||
|
max-width: 50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -34,7 +34,7 @@
|
|||||||
@include('components.navBrand')
|
@include('components.navBrand')
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item px-3">
|
<li class="nav-item px-3">
|
||||||
<a href="#" class="nav-link medialibrary">Media Library</a>
|
<a href="#" class="nav-link medialibrary">{{ trans('mediaLibrary.mediaLibrary') }}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="nav navbar-nav ml-auto">
|
<ul class="nav navbar-nav ml-auto">
|
||||||
@ -49,7 +49,7 @@
|
|||||||
</button>
|
</button>
|
||||||
<form action="{{ route('logout') }}" method="post">
|
<form action="{{ route('logout') }}" method="post">
|
||||||
@csrf
|
@csrf
|
||||||
<button class="btn btn-outline-danger btn-sm">登出</button>
|
<button class="btn btn-outline-danger btn-sm">{{ trans('form.buttons.logout') }}</button>
|
||||||
</form>
|
</form>
|
||||||
</header>
|
</header>
|
||||||
<div id="app-body" class="app-body">
|
<div id="app-body" class="app-body">
|
||||||
|
|||||||
56
resources/views/admin/menu/posts/edit.blade.php
Normal file
56
resources/views/admin/menu/posts/edit.blade.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@section('admin-page-content')
|
||||||
|
<form action="{{ $post ? route($adminRouteNamePrefix . $resource . '.update', [$post->id]) : route($adminRouteNamePrefix . $resource . '.store') }}" method="POST">
|
||||||
|
@if($post)
|
||||||
|
@method('PUT')
|
||||||
|
@endif
|
||||||
|
@csrf
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-8">
|
||||||
|
<ul class="nav nav-tabs" id="language-tab" role="tablist">
|
||||||
|
@foreach ($languages as $languageCode => $name)
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link {{ $languageCode == config('app.locale') ? 'active' : ''}}" id="{{ $languageCode }}-tab" data-toggle="tab" href="#{{ $languageCode }}-content" role="tab" aria-controls="{{ $languageCode }}-content" aria-selected="true">@lang('languages.' . $languageCode)</a>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
<div class="tab-content">
|
||||||
|
<?php foreach ($languages as $languageCode => $name): ?>
|
||||||
|
<div class="tab-pane {{ $languageCode == config('app.locale') ? 'active' : ''}}" id="{{$languageCode}}-content" role="tabpanel" aria-labelledby="{{ $languageCode }}-tab">
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ trans('form.titles.title') }}</label>
|
||||||
|
<input type="text" name="title[{{ $languageCode }}]" class="form-control" value="{{ $post ? $post->trans('title', $languageCode) : '' }}" required>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ trans('form.titles.excerpt') }}</label>
|
||||||
|
<input type="text" name="excerpt[{{ $languageCode }}]" class="form-control" value="{{ $post ? $post->trans('excerpt', $languageCode) : '' }}">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ trans('form.titles.content') }}</label>
|
||||||
|
<textarea name="content[{{ $languageCode }}]" class="form-control" rows="10">{{ $post ? $post->trans('content', $languageCode) : ''}}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="col-4">
|
||||||
|
@if($post)
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ trans('form.titles.author') }}</label>
|
||||||
|
<div>{{ $post->author->email}}</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@inject('mediaSelectionFieldPresenter', 'App\Presenters\Admin\MediaSelectionFieldPresenter')
|
||||||
|
<div class="form-group">
|
||||||
|
<label>{{ trans('form.titles.featureImage') }}</label>
|
||||||
|
{!! $mediaSelectionFieldPresenter->render($post ? $post->feature_image_id : null, ['name' => 'feature_image_id']) !!}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-success">{{ $post ? trans('form.buttons.update') : trans('form.buttons.create') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
@endsection
|
||||||
46
resources/views/admin/menu/posts/list.blade.php
Normal file
46
resources/views/admin/menu/posts/list.blade.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
@extends('admin.layouts.app')
|
||||||
|
|
||||||
|
@push('admin-app-styles')
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/admin/page/post-list.css') }}">
|
||||||
|
@endpush
|
||||||
|
|
||||||
|
@section('admin-page-content')
|
||||||
|
<h2>{{ $pageHeader }}</h2>
|
||||||
|
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>{{ trans('form.titles.title') }}</th>
|
||||||
|
<th>{{ trans('form.titles.author') }}</th>
|
||||||
|
<th>{{ trans('form.titles.created') }}</th>
|
||||||
|
<th>{{ trans('form.titles.updated') }}</th>
|
||||||
|
<th>{{ trans('form.titles.operations') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach($posts as $post)
|
||||||
|
<tr>
|
||||||
|
<td class="feature-image">
|
||||||
|
@if($post->featureImage)
|
||||||
|
<img src="{{ $post->featureImage->url }}" alt="{{ $post->featureImage->description }}">
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td><a href="{{ route($adminRouteNamePrefix . $resource . '.edit', [$resource => $post->id]) }}">{{ $post->title }}</a></td>
|
||||||
|
<td>{{ $post->author->email }}</td>
|
||||||
|
<td>{{ $post->created_at }}</td>
|
||||||
|
<td>{{ $post->updated_at }}</td>
|
||||||
|
<td>
|
||||||
|
<form action="{{ route($adminRouteNamePrefix . $resource . '.destroy', [$resource => $post->id]) }}" method="POST">
|
||||||
|
@method('delete')
|
||||||
|
@csrf
|
||||||
|
<button class="btn btn-danger">{{ trans('form.buttons.delete') }}</button>
|
||||||
|
</form>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
{!! $posts->links() !!}
|
||||||
|
@endsection
|
||||||
@ -28,6 +28,10 @@ Route::get('/robots.txt', 'PageController@robotstxt');
|
|||||||
*/
|
*/
|
||||||
Route::group(['prefix' => config('admin.route'), 'middleware' => ['admin.area'], 'as' => config('admin.route_name_prefix')], function() {
|
Route::group(['prefix' => config('admin.route'), 'middleware' => ['admin.area'], 'as' => config('admin.route_name_prefix')], function() {
|
||||||
Route::get('/', 'AdminPageController@index')->name('index');
|
Route::get('/', 'AdminPageController@index')->name('index');
|
||||||
|
|
||||||
|
foreach (config('postTypes') as $resource => $postType) {
|
||||||
|
Route::resource($resource, 'Admin\PostController');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
1
webpack.mix.js
vendored
1
webpack.mix.js
vendored
@ -28,3 +28,4 @@ mix.sass('resources/sass/admin/lib.scss', publicAdminCssDir)
|
|||||||
.sass('resources/sass/admin/app.scss', publicAdminCssDir)
|
.sass('resources/sass/admin/app.scss', publicAdminCssDir)
|
||||||
.sass('resources/sass/admin/page/system-status.scss', publicAdminCssDir + '/page')
|
.sass('resources/sass/admin/page/system-status.scss', publicAdminCssDir + '/page')
|
||||||
.sass('resources/sass/admin/page/options.scss', publicAdminCssDir + '/page')
|
.sass('resources/sass/admin/page/options.scss', publicAdminCssDir + '/page')
|
||||||
|
.sass('resources/sass/admin/page/post-list.scss', publicAdminCssDir + '/page')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user