diff --git a/app/Console/Commands/DemoteUser.php b/app/Console/Commands/DemoteUser.php new file mode 100644 index 0000000..94dfe58 --- /dev/null +++ b/app/Console/Commands/DemoteUser.php @@ -0,0 +1,61 @@ +argument('username'))->first(); + if ($user === null) { + $this->error('No user with such username'); + + return 1; + } + + if (!$user->is_admin) { + $this->info('@' . $user->name . ' is already an user.'); + + return 0; + } + + $user->is_admin = false; + if ($user->save()) { + $this->info('@' . $user->name . ' is an user now.'); + } else { + $this->error('Something happened.'); + } + } +} diff --git a/app/Console/Commands/PromoteUser.php b/app/Console/Commands/PromoteUser.php new file mode 100644 index 0000000..b737ca5 --- /dev/null +++ b/app/Console/Commands/PromoteUser.php @@ -0,0 +1,61 @@ +argument('username'))->first(); + if ($user === null) { + $this->error('No user with such username'); + + return 1; + } + + if ($user->is_admin) { + $this->info('@' . $user->name . ' is already an administrator.'); + + return 0; + } + + $user->is_admin = true; + if ($user->save()) { + $this->info('@' . $user->name . ' is an administrator now.'); + } else { + $this->error('Something happened.'); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 622e774..da3f264 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -2,6 +2,8 @@ namespace App\Console; +use App\Console\Commands\DemoteUser; +use App\Console\Commands\PromoteUser; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Foundation\Console\Kernel as ConsoleKernel; @@ -35,6 +37,8 @@ class Kernel extends ConsoleKernel */ protected function commands() { + $this->load(__DIR__.'/Commands'); + require base_path('routes/console.php'); } } diff --git a/app/Http/Controllers/Admin/DashboardController.php b/app/Http/Controllers/Admin/DashboardController.php new file mode 100644 index 0000000..b09d0c8 --- /dev/null +++ b/app/Http/Controllers/Admin/DashboardController.php @@ -0,0 +1,14 @@ +select('id', 'category', 'pinned', 'title', 'created_at') + ->orderByDesc('pinned') + ->orderByDesc('created_at') + ->paginate(20); + + return view('admin.info.index')->with([ + 'informations' => $informations, + 'categories' => Information::CATEGORIES + ]); + } + + public function create() + { + return view('admin.info.create')->with([ + 'categories' => Information::CATEGORIES + ]); + } + + public function store(AdminInfoStoreRequest $request) + { + $inputs = $request->all(); + if (!$request->has('pinned')) { + $inputs['pinned'] = false; + } + + $info = Information::create($inputs); + + return redirect()->route('admin.info.edit', ['info' => $info])->with('status', 'お知らせを更新しました。'); + } + + public function edit($id) + { + $information = Information::findOrFail($id); + + return view('admin.info.edit')->with([ + 'info' => $information, + 'categories' => Information::CATEGORIES + ]); + } + + public function update(AdminInfoStoreRequest $request, Information $info) + { + $inputs = $request->all(); + if (!$request->has('pinned')) { + $inputs['pinned'] = false; + } + + $info->fill($inputs)->save(); + + return redirect()->route('admin.info.edit', ['info' => $info])->with('status', 'お知らせを更新しました。'); + } + + public function destroy(Information $info) + { + $info->delete(); + + return redirect()->route('admin.info')->with('status', 'お知らせを削除しました。'); + } +} diff --git a/app/Http/Requests/AdminInfoStoreRequest.php b/app/Http/Requests/AdminInfoStoreRequest.php new file mode 100644 index 0000000..45b3d2e --- /dev/null +++ b/app/Http/Requests/AdminInfoStoreRequest.php @@ -0,0 +1,35 @@ + ['required', Rule::in(array_keys(Information::CATEGORIES))], + 'pinned' => 'nullable|boolean', + 'title' => 'required|string|max:255', + 'content' => 'required|string|max:10000' + ]; + } +} diff --git a/app/Information.php b/app/Information.php index e0ae6ed..2b237fb 100644 --- a/app/Information.php +++ b/app/Information.php @@ -16,5 +16,9 @@ class Information extends Model 3 => ['label' => 'メンテナンス', 'class' => 'badge-warning'] ]; + protected $fillable = [ + 'category', 'pinned', 'title', 'content' + ]; + protected $dates = ['deleted_at']; } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index e12ff88..600ff72 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -25,6 +25,8 @@ class AuthServiceProvider extends ServiceProvider { $this->registerPolicies(); - // + Gate::define('admin', function ($user) { + return $user->is_admin; + }); } } diff --git a/database/migrations/2019_02_11_140657_add_is_admin_to_users.php b/database/migrations/2019_02_11_140657_add_is_admin_to_users.php new file mode 100644 index 0000000..2b37986 --- /dev/null +++ b/database/migrations/2019_02_11_140657_add_is_admin_to_users.php @@ -0,0 +1,32 @@ +boolean('is_admin')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('is_admin'); + }); + } +} diff --git a/public/dashboard.png b/public/dashboard.png new file mode 100644 index 0000000..c85ca1c Binary files /dev/null and b/public/dashboard.png differ diff --git a/resources/lang/ja/validation.php b/resources/lang/ja/validation.php index ecf3a03..d154816 100644 --- a/resources/lang/ja/validation.php +++ b/resources/lang/ja/validation.php @@ -119,6 +119,8 @@ return [ 'attributes' => [ 'email' => 'メールアドレス', 'password' => 'パスワード', + 'title' => 'タイトル', + 'content' => '本文', ], ]; diff --git a/resources/views/admin/dashboard.blade.php b/resources/views/admin/dashboard.blade.php new file mode 100644 index 0000000..beb9602 --- /dev/null +++ b/resources/views/admin/dashboard.blade.php @@ -0,0 +1,10 @@ +@extends('layouts.admin') + +@section('title', 'ダッシュボード') + +@section('tab-content') +
+ +

TODO: 役に立つ情報を表示する

+
+@endsection \ No newline at end of file diff --git a/resources/views/admin/info/create.blade.php b/resources/views/admin/info/create.blade.php new file mode 100644 index 0000000..576b7ab --- /dev/null +++ b/resources/views/admin/info/create.blade.php @@ -0,0 +1,54 @@ +@extends('layouts.admin') + +@section('title', 'お知らせ') + +@section('tab-content') +
+

お知らせの作成

+
+
+ {{ csrf_field() }} + +
+
+ + +
+
+
+ + +
+
+
+
+ + + + @if ($errors->has('title')) +
{{ $errors->first('title') }}
+ @endif +
+
+ + + + 最大 10000 文字、Markdown 形式 + + + @if ($errors->has('content')) +
{{ $errors->first('content') }}
+ @endif +
+ +
+ +
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/admin/info/edit.blade.php b/resources/views/admin/info/edit.blade.php new file mode 100644 index 0000000..d5eb513 --- /dev/null +++ b/resources/views/admin/info/edit.blade.php @@ -0,0 +1,60 @@ +@extends('layouts.admin') + +@section('title', 'お知らせ') + +@section('tab-content') +
+

お知らせの編集

+
+
+ {{ method_field('PUT') }} + {{ csrf_field() }} + +
+
+ + +
+
+
+ pinned) ? 'checked' : ''}}> + +
+
+
+
+ + + + @if ($errors->has('title')) +
{{ $errors->first('title') }}
+ @endif +
+
+ + + + 最大 10000 文字、Markdown 形式 + + + @if ($errors->has('content')) +
{{ $errors->first('content') }}
+ @endif +
+ +
+ + +
+
+
+ {{ method_field('DELETE') }} + {{ csrf_field() }} +
+
+@endsection \ No newline at end of file diff --git a/resources/views/admin/info/index.blade.php b/resources/views/admin/info/index.blade.php new file mode 100644 index 0000000..8d5ae40 --- /dev/null +++ b/resources/views/admin/info/index.blade.php @@ -0,0 +1,57 @@ +@extends('layouts.admin') + +@section('title', 'お知らせ') + +@section('tab-content') +
+

お知らせ

+
+
+ 新規作成 +
+ + + + + + + + + + @foreach($informations as $info) + + + + + + @endforeach + +
カテゴリタイトル作成日
+ @if ($info->pinned) + ピン留め + @endif + {{ $categories[$info->category]['label'] }} + + {{ $info->title }} + + {{ $info->created_at->format('Y年n月j日') }} +
+ +
+@endsection \ No newline at end of file diff --git a/resources/views/layouts/admin.blade.php b/resources/views/layouts/admin.blade.php new file mode 100644 index 0000000..45fa2b5 --- /dev/null +++ b/resources/views/layouts/admin.blade.php @@ -0,0 +1,20 @@ +@extends('layouts.base') + +@section('content') +
+
+ +
+ @yield('tab-content') +
+
+
+@endsection \ No newline at end of file diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index 3aabcb2..1c524af 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -105,6 +105,9 @@ 設定 + @can ('admin') + 管理 + @endcan ログアウト diff --git a/routes/web.php b/routes/web.php index a772f46..23eca8e 100644 --- a/routes/web.php +++ b/routes/web.php @@ -44,3 +44,17 @@ Route::get('/info/{id}', 'InfoController@show')->where('id', '[0-9]+')->name('in Route::redirect('/search', '/search/checkin', 301); Route::get('/search/checkin', 'SearchController@index')->name('search'); Route::get('/search/related-tag', 'SearchController@relatedTag')->name('search.related-tag'); + +Route::middleware('can:admin') + ->namespace('Admin') + ->prefix('admin') + ->name('admin.') + ->group(function () { + Route::get('/', 'DashboardController@index')->name('dashboard'); + Route::get('/info', 'InfoController@index')->name('info'); + Route::get('/info/create', 'InfoController@create')->name('info.create'); + Route::post('/info', 'InfoController@store')->name('info.store'); + Route::get('/info/{info}', 'InfoController@edit')->name('info.edit'); + Route::put('/info/{info}', 'InfoController@update')->name('info.update'); + Route::delete('/info/{info}', 'InfoController@destroy')->name('info.destroy'); + });