Jetstream dashboard
This commit is contained in:
34
app/Actions/Fortify/CreateNewUser.php
Normal file
34
app/Actions/Fortify/CreateNewUser.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Laravel\Fortify\Contracts\CreatesNewUsers;
|
||||||
|
|
||||||
|
class CreateNewUser implements CreatesNewUsers
|
||||||
|
{
|
||||||
|
use PasswordValidationRules;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and create a newly registered user.
|
||||||
|
*
|
||||||
|
* @param array $input
|
||||||
|
* @return \App\Models\User
|
||||||
|
*/
|
||||||
|
public function create(array $input)
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
|
||||||
|
'password' => $this->passwordRules(),
|
||||||
|
])->validate();
|
||||||
|
|
||||||
|
return User::create([
|
||||||
|
'name' => $input['name'],
|
||||||
|
'email' => $input['email'],
|
||||||
|
'password' => Hash::make($input['password']),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
18
app/Actions/Fortify/PasswordValidationRules.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use Laravel\Fortify\Rules\Password;
|
||||||
|
|
||||||
|
trait PasswordValidationRules
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the validation rules used to validate passwords.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function passwordRules()
|
||||||
|
{
|
||||||
|
return ['required', 'string', new Password, 'confirmed'];
|
||||||
|
}
|
||||||
|
}
|
30
app/Actions/Fortify/ResetUserPassword.php
Normal file
30
app/Actions/Fortify/ResetUserPassword.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Laravel\Fortify\Contracts\ResetsUserPasswords;
|
||||||
|
|
||||||
|
class ResetUserPassword implements ResetsUserPasswords
|
||||||
|
{
|
||||||
|
use PasswordValidationRules;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and reset the user's forgotten password.
|
||||||
|
*
|
||||||
|
* @param mixed $user
|
||||||
|
* @param array $input
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function reset($user, array $input)
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'password' => $this->passwordRules(),
|
||||||
|
])->validateWithBag('updatePassword');
|
||||||
|
|
||||||
|
$user->forceFill([
|
||||||
|
'password' => Hash::make($input['password']),
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
}
|
35
app/Actions/Fortify/UpdateUserPassword.php
Normal file
35
app/Actions/Fortify/UpdateUserPassword.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Hash;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Laravel\Fortify\Contracts\UpdatesUserPasswords;
|
||||||
|
|
||||||
|
class UpdateUserPassword implements UpdatesUserPasswords
|
||||||
|
{
|
||||||
|
use PasswordValidationRules;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and update the user's password.
|
||||||
|
*
|
||||||
|
* @param mixed $user
|
||||||
|
* @param array $input
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update($user, array $input)
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'current_password' => ['required', 'string'],
|
||||||
|
'password' => $this->passwordRules(),
|
||||||
|
])->after(function ($validator) use ($user, $input) {
|
||||||
|
if (! Hash::check($input['current_password'], $user->password)) {
|
||||||
|
$validator->errors()->add('current_password', __('The provided password does not match your current password.'));
|
||||||
|
}
|
||||||
|
})->validateWithBag('updatePassword');
|
||||||
|
|
||||||
|
$user->forceFill([
|
||||||
|
'password' => Hash::make($input['password']),
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
}
|
35
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
35
app/Actions/Fortify/UpdateUserProfileInformation.php
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Fortify;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Laravel\Fortify\Contracts\UpdatesUserProfileInformation;
|
||||||
|
|
||||||
|
class UpdateUserProfileInformation implements UpdatesUserProfileInformation
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Validate and update the given user's profile information.
|
||||||
|
*
|
||||||
|
* @param mixed $user
|
||||||
|
* @param array $input
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update($user, array $input)
|
||||||
|
{
|
||||||
|
Validator::make($input, [
|
||||||
|
'name' => ['required', 'string', 'max:255'],
|
||||||
|
'email' => ['required', 'email', 'max:255', Rule::unique('users')->ignore($user->id)],
|
||||||
|
'photo' => ['nullable', 'image', 'max:1024'],
|
||||||
|
])->validateWithBag('updateProfileInformation');
|
||||||
|
|
||||||
|
if (isset($input['photo'])) {
|
||||||
|
$user->updateProfilePhoto($input['photo']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user->forceFill([
|
||||||
|
'name' => $input['name'],
|
||||||
|
'email' => $input['email'],
|
||||||
|
])->save();
|
||||||
|
}
|
||||||
|
}
|
19
app/Actions/Jetstream/DeleteUser.php
Normal file
19
app/Actions/Jetstream/DeleteUser.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Jetstream;
|
||||||
|
|
||||||
|
use Laravel\Jetstream\Contracts\DeletesUsers;
|
||||||
|
|
||||||
|
class DeleteUser implements DeletesUsers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Delete the given user.
|
||||||
|
*
|
||||||
|
* @param mixed $user
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function delete($user)
|
||||||
|
{
|
||||||
|
$user->delete();
|
||||||
|
}
|
||||||
|
}
|
19
app/Http/Controllers/Admin/AnalyticsController.php
Normal file
19
app/Http/Controllers/Admin/AnalyticsController.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Admin;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use Spatie\Analytics\Period;
|
||||||
|
use Analytics;
|
||||||
|
|
||||||
|
class AnalyticsController extends Controller
|
||||||
|
{
|
||||||
|
public function __invoke()
|
||||||
|
{
|
||||||
|
return view('admin.analytics', [
|
||||||
|
'VisitorsAndPageViews' => Analytics::fetchVisitorsAndPageViews(Period::days(2)),
|
||||||
|
'TotalVisitorsAndPageViews' => Analytics::fetchTotalVisitorsAndPageViews(Period::days(7))->reverse()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -33,7 +33,7 @@ class Kernel extends HttpKernel
|
|||||||
\App\Http\Middleware\EncryptCookies::class,
|
\App\Http\Middleware\EncryptCookies::class,
|
||||||
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
|
||||||
\Illuminate\Session\Middleware\StartSession::class,
|
\Illuminate\Session\Middleware\StartSession::class,
|
||||||
// \Illuminate\Session\Middleware\AuthenticateSession::class,
|
\Laravel\Jetstream\Http\Middleware\AuthenticateSession::class,
|
||||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||||
\App\Http\Middleware\VerifyCsrfToken::class,
|
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||||
|
@@ -1,14 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
use Laravel\Fortify\TwoFactorAuthenticatable;
|
||||||
|
use Laravel\Jetstream\HasProfilePhoto;
|
||||||
|
use Laravel\Sanctum\HasApiTokens;
|
||||||
|
|
||||||
class User extends Authenticatable
|
class User extends Authenticatable
|
||||||
{
|
{
|
||||||
|
use HasApiTokens;
|
||||||
|
use HasFactory;
|
||||||
|
use HasProfilePhoto;
|
||||||
use Notifiable;
|
use Notifiable;
|
||||||
|
use TwoFactorAuthenticatable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
@@ -16,7 +24,9 @@ class User extends Authenticatable
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
'name', 'email', 'password',
|
'name',
|
||||||
|
'email',
|
||||||
|
'password',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,7 +35,10 @@ class User extends Authenticatable
|
|||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
protected $hidden = [
|
protected $hidden = [
|
||||||
'password', 'remember_token',
|
'password',
|
||||||
|
'remember_token',
|
||||||
|
'two_factor_recovery_codes',
|
||||||
|
'two_factor_secret',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,4 +49,13 @@ class User extends Authenticatable
|
|||||||
protected $casts = [
|
protected $casts = [
|
||||||
'email_verified_at' => 'datetime',
|
'email_verified_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The accessors to append to the model's array form.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $appends = [
|
||||||
|
'profile_photo_url',
|
||||||
|
];
|
||||||
}
|
}
|
36
app/Providers/FortifyServiceProvider.php
Normal file
36
app/Providers/FortifyServiceProvider.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Actions\Fortify\CreateNewUser;
|
||||||
|
use App\Actions\Fortify\ResetUserPassword;
|
||||||
|
use App\Actions\Fortify\UpdateUserPassword;
|
||||||
|
use App\Actions\Fortify\UpdateUserProfileInformation;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Laravel\Fortify\Fortify;
|
||||||
|
|
||||||
|
class FortifyServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
Fortify::createUsersUsing(CreateNewUser::class);
|
||||||
|
Fortify::updateUserProfileInformationUsing(UpdateUserProfileInformation::class);
|
||||||
|
Fortify::updateUserPasswordsUsing(UpdateUserPassword::class);
|
||||||
|
Fortify::resetUserPasswordsUsing(ResetUserPassword::class);
|
||||||
|
}
|
||||||
|
}
|
49
app/Providers/JetstreamServiceProvider.php
Normal file
49
app/Providers/JetstreamServiceProvider.php
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Actions\Jetstream\DeleteUser;
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Laravel\Jetstream\Jetstream;
|
||||||
|
|
||||||
|
class JetstreamServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap any application services.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function boot()
|
||||||
|
{
|
||||||
|
$this->configurePermissions();
|
||||||
|
|
||||||
|
Jetstream::deleteUsersUsing(DeleteUser::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the permissions that are available within the application.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function configurePermissions()
|
||||||
|
{
|
||||||
|
Jetstream::defaultApiTokenPermissions(['read']);
|
||||||
|
|
||||||
|
Jetstream::permissions([
|
||||||
|
'create',
|
||||||
|
'read',
|
||||||
|
'update',
|
||||||
|
'delete',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@@ -21,7 +21,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
public const HOME = '/home';
|
public const HOME = '/dashboard';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define your route model bindings, pattern filters, etc.
|
* Define your route model bindings, pattern filters, etc.
|
||||||
|
18
app/View/Components/AppLayout.php
Normal file
18
app/View/Components/AppLayout.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\View\Components;
|
||||||
|
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
|
class AppLayout extends Component
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the view / contents that represents the component.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('layouts.admin');
|
||||||
|
}
|
||||||
|
}
|
18
app/View/Components/GuestLayout.php
Normal file
18
app/View/Components/GuestLayout.php
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\View\Components;
|
||||||
|
|
||||||
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
|
class GuestLayout extends Component
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the view / contents that represents the component.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\View\View
|
||||||
|
*/
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('layouts.guest');
|
||||||
|
}
|
||||||
|
}
|
@@ -16,9 +16,13 @@
|
|||||||
"goldspecdigital/laravel-eloquent-uuid": "^8.0",
|
"goldspecdigital/laravel-eloquent-uuid": "^8.0",
|
||||||
"guzzlehttp/guzzle": "^7.0.1",
|
"guzzlehttp/guzzle": "^7.0.1",
|
||||||
"laravel/framework": "^8.0",
|
"laravel/framework": "^8.0",
|
||||||
|
"laravel/jetstream": "^1.2",
|
||||||
|
"laravel/sanctum": "^2.6",
|
||||||
"laravel/tinker": "^2.0",
|
"laravel/tinker": "^2.0",
|
||||||
|
"livewire/livewire": "^2.0",
|
||||||
"mtownsend/read-time": "^1.1",
|
"mtownsend/read-time": "^1.1",
|
||||||
"realrashid/sweet-alert": "^3.1",
|
"realrashid/sweet-alert": "^3.1",
|
||||||
|
"spatie/laravel-analytics": "^3.10",
|
||||||
"symfony/panther": "^0.7.1"
|
"symfony/panther": "^0.7.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
1223
composer.lock
generated
1223
composer.lock
generated
File diff suppressed because it is too large
Load Diff
33
config/analytics.php
Normal file
33
config/analytics.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The view id of which you want to display data.
|
||||||
|
*/
|
||||||
|
'view_id' => env('ANALYTICS_VIEW_ID'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Path to the client secret json file. Take a look at the README of this package
|
||||||
|
* to learn how to get this file. You can also pass the credentials as an array
|
||||||
|
* instead of a file path.
|
||||||
|
*/
|
||||||
|
'service_account_credentials_json' => storage_path('app/analytics/service-account-credentials.json'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The amount of minutes the Google API responses will be cached.
|
||||||
|
* If you set this to zero, the responses won't be cached at all.
|
||||||
|
*/
|
||||||
|
'cache_lifetime_in_minutes' => 60 * 24,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here you may configure the "store" that the underlying Google_Client will
|
||||||
|
* use to store it's data. You may also add extra parameters that will
|
||||||
|
* be passed on setCacheConfig (see docs for google-api-php-client).
|
||||||
|
*
|
||||||
|
* Optional parameters: "lifetime", "prefix"
|
||||||
|
*/
|
||||||
|
'cache' => [
|
||||||
|
'store' => 'file',
|
||||||
|
],
|
||||||
|
];
|
@@ -174,6 +174,8 @@ return [
|
|||||||
// App\Providers\BroadcastServiceProvider::class,
|
// App\Providers\BroadcastServiceProvider::class,
|
||||||
App\Providers\EventServiceProvider::class,
|
App\Providers\EventServiceProvider::class,
|
||||||
App\Providers\RouteServiceProvider::class,
|
App\Providers\RouteServiceProvider::class,
|
||||||
|
App\Providers\FortifyServiceProvider::class,
|
||||||
|
App\Providers\JetstreamServiceProvider::class,
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@@ -68,7 +68,7 @@ return [
|
|||||||
'providers' => [
|
'providers' => [
|
||||||
'users' => [
|
'users' => [
|
||||||
'driver' => 'eloquent',
|
'driver' => 'eloquent',
|
||||||
'model' => App\User::class,
|
'model' => App\Models\User::class,
|
||||||
],
|
],
|
||||||
|
|
||||||
// 'users' => [
|
// 'users' => [
|
||||||
|
216
config/debugbar.php
Normal file
216
config/debugbar.php
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Debugbar Settings
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Debugbar is enabled by default, when debug is set to true in app.php.
|
||||||
|
| You can override the value by setting enable to true or false instead of null.
|
||||||
|
|
|
||||||
|
| You can provide an array of URI's that must be ignored (eg. 'api/*')
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'enabled' => env('DEBUGBAR_ENABLED', null),
|
||||||
|
'except' => [
|
||||||
|
'telescope*',
|
||||||
|
'horizon*',
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Storage settings
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| DebugBar stores data for session/ajax requests.
|
||||||
|
| You can disable this, so the debugbar stores data in headers/session,
|
||||||
|
| but this can cause problems with large data collectors.
|
||||||
|
| By default, file storage (in the storage folder) is used. Redis and PDO
|
||||||
|
| can also be used. For PDO, run the package migrations first.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'storage' => [
|
||||||
|
'enabled' => true,
|
||||||
|
'driver' => 'file', // redis, file, pdo, custom
|
||||||
|
'path' => storage_path('debugbar'), // For file driver
|
||||||
|
'connection' => null, // Leave null for default connection (Redis/PDO)
|
||||||
|
'provider' => '', // Instance of StorageInterface for custom driver
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Vendors
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Vendor files are included by default, but can be set to false.
|
||||||
|
| This can also be set to 'js' or 'css', to only include javascript or css vendor files.
|
||||||
|
| Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
|
||||||
|
| and for js: jquery and and highlight.js
|
||||||
|
| So if you want syntax highlighting, set it to true.
|
||||||
|
| jQuery is set to not conflict with existing jQuery scripts.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'include_vendors' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Capture Ajax Requests
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
|
||||||
|
| you can use this option to disable sending the data through the headers.
|
||||||
|
|
|
||||||
|
| Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'capture_ajax' => true,
|
||||||
|
'add_ajax_timing' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Custom Error Handler for Deprecated warnings
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When enabled, the Debugbar shows deprecated warnings for Symfony components
|
||||||
|
| in the Messages tab.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'error_handler' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Clockwork integration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The Debugbar can emulate the Clockwork headers, so you can use the Chrome
|
||||||
|
| Extension, without the server-side code. It uses Debugbar collectors instead.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'clockwork' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| DataCollectors
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Enable/disable DataCollectors
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'collectors' => [
|
||||||
|
'phpinfo' => true, // Php version
|
||||||
|
'messages' => true, // Messages
|
||||||
|
'time' => true, // Time Datalogger
|
||||||
|
'memory' => true, // Memory usage
|
||||||
|
'exceptions' => true, // Exception displayer
|
||||||
|
'log' => true, // Logs from Monolog (merged in messages if enabled)
|
||||||
|
'db' => true, // Show database (PDO) queries and bindings
|
||||||
|
'views' => true, // Views with their data
|
||||||
|
'route' => true, // Current route information
|
||||||
|
'auth' => false, // Display Laravel authentication status
|
||||||
|
'gate' => true, // Display Laravel Gate checks
|
||||||
|
'session' => true, // Display session data
|
||||||
|
'symfony_request' => true, // Only one can be enabled..
|
||||||
|
'mail' => true, // Catch mail messages
|
||||||
|
'laravel' => false, // Laravel version and environment
|
||||||
|
'events' => false, // All events fired
|
||||||
|
'default_request' => false, // Regular or special Symfony request logger
|
||||||
|
'logs' => false, // Add the latest log messages
|
||||||
|
'files' => false, // Show the included files
|
||||||
|
'config' => false, // Display config settings
|
||||||
|
'cache' => false, // Display cache events
|
||||||
|
'models' => true, // Display models
|
||||||
|
'livewire' => true, // Display Livewire (when available)
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Extra options
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Configure some DataCollectors
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'options' => [
|
||||||
|
'auth' => [
|
||||||
|
'show_name' => true, // Also show the users name/email in the debugbar
|
||||||
|
],
|
||||||
|
'db' => [
|
||||||
|
'with_params' => true, // Render SQL with the parameters substituted
|
||||||
|
'backtrace' => true, // Use a backtrace to find the origin of the query in your files.
|
||||||
|
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
|
||||||
|
'timeline' => false, // Add the queries to the timeline
|
||||||
|
'explain' => [ // Show EXPLAIN output on queries
|
||||||
|
'enabled' => false,
|
||||||
|
'types' => ['SELECT'], // Deprecated setting, is always only SELECT
|
||||||
|
],
|
||||||
|
'hints' => false, // Show hints for common mistakes
|
||||||
|
'show_copy' => false, // Show copy button next to the query
|
||||||
|
],
|
||||||
|
'mail' => [
|
||||||
|
'full_log' => false,
|
||||||
|
],
|
||||||
|
'views' => [
|
||||||
|
'data' => false, //Note: Can slow down the application, because the data can be quite large..
|
||||||
|
],
|
||||||
|
'route' => [
|
||||||
|
'label' => true, // show complete route on bar
|
||||||
|
],
|
||||||
|
'logs' => [
|
||||||
|
'file' => null,
|
||||||
|
],
|
||||||
|
'cache' => [
|
||||||
|
'values' => true, // collect cache values
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Inject Debugbar in Response
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Usually, the debugbar is added just before </body>, by listening to the
|
||||||
|
| Response after the App is done. If you disable this, you have to add them
|
||||||
|
| in your template yourself. See http://phpdebugbar.com/docs/rendering.html
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'inject' => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| DebugBar route prefix
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Sometimes you want to set route prefix to be used by DebugBar to load
|
||||||
|
| its resources from. Usually the need comes from misconfigured web server or
|
||||||
|
| from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
'route_prefix' => '_debugbar',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| DebugBar route domain
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| By default DebugBar route served from the same domain that request served.
|
||||||
|
| To override default domain, specify it as a non-empty value.
|
||||||
|
*/
|
||||||
|
'route_domain' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| DebugBar theme
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Switches between light and dark theme. If set to auto it will respect system preferences
|
||||||
|
| Possible values: auto, light, dark
|
||||||
|
*/
|
||||||
|
'theme' => 'auto',
|
||||||
|
];
|
97
config/fortify.php
Normal file
97
config/fortify.php
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Providers\RouteServiceProvider;
|
||||||
|
use Laravel\Fortify\Features;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Fortify Guard
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify which authentication guard Fortify will use while
|
||||||
|
| authenticating users. This value should correspond with one of your
|
||||||
|
| guards that is already present in your "auth" configuration file.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'guard' => 'web',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Fortify Password Broker
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may specify which password broker Fortify can use when a user
|
||||||
|
| is resetting their password. This configured value should match one
|
||||||
|
| of your password brokers setup in your "auth" configuration file.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'passwords' => 'users',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Username
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value defines which model attribute should be considered as your
|
||||||
|
| application's "username" field. Typically, this might be the email
|
||||||
|
| address of the users but you are free to change this value here.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'username' => 'email',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Home Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Here you may configure the path where users will get redirected during
|
||||||
|
| authentication or password reset when the operations are successful
|
||||||
|
| and the user is authenticated. You are free to change this value.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'home' => RouteServiceProvider::HOME,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Rate Limiting
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| By default, Fortify will throttle logins to five requests per minute for
|
||||||
|
| every email and IP address combination. However, if you would like to
|
||||||
|
| specify a custom rate limiter to call then you may specify it here.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'limiters' => [
|
||||||
|
'login' => null,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Features
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Some of the Fortify features are optional. You may disable the features
|
||||||
|
| by removing them from this array. You're free to only remove some of
|
||||||
|
| these features or you can even remove all of these if you need to.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'features' => [
|
||||||
|
//Features::registration(),
|
||||||
|
Features::resetPasswords(),
|
||||||
|
// Features::emailVerification(),
|
||||||
|
Features::updateProfileInformation(),
|
||||||
|
Features::updatePasswords(),
|
||||||
|
Features::twoFactorAuthentication([
|
||||||
|
'confirmPassword' => true,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
37
config/jetstream.php
Normal file
37
config/jetstream.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Laravel\Jetstream\Features;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Jetstream Stack
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This configuration value informs Jetstream which "stack" you will be
|
||||||
|
| using for your application. In general, this value is set for you
|
||||||
|
| during installation and will not need to be changed after that.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stack' => 'livewire',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Features
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Some of Jetstream's features are optional. You may disable the features
|
||||||
|
| by removing them from this array. You're free to only remove some of
|
||||||
|
| these features or you can even remove all of these if you need to.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'features' => [
|
||||||
|
Features::profilePhotos(),
|
||||||
|
//Features::api(),
|
||||||
|
// Features::teams(),
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
95
config/livewire.php
Normal file
95
config/livewire.php
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Class Namespace
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the root namespace for Livewire component classes in
|
||||||
|
| your application. This value affects component auto-discovery and
|
||||||
|
| any Livewire file helper commands, like `artisan make:livewire`.
|
||||||
|
|
|
||||||
|
| After changing this item, run: `php artisan livewire:discover`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'class_namespace' => 'App\\Http\\Livewire',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| View Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path for Livewire component views. This affects
|
||||||
|
| file manipulation helper commands like `artisan make:livewire`.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'view_path' => resource_path('views/livewire'),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Assets URL
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path to Livewire JavaScript assets, for cases where
|
||||||
|
| your app's domain root is not the correct path. By default, Livewire
|
||||||
|
| will load its JavaScript assets from the app's "relative root".
|
||||||
|
|
|
||||||
|
| Examples: "/assets", "myurl.com/app".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'asset_url' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Endpoint Middleware Group
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the middleware group that will be applied to the main
|
||||||
|
| Livewire "message" endpoint (the endpoint that gets hit everytime
|
||||||
|
| a Livewire component updates). It is set to "web" by default.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware_group' => 'web',
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Livewire Temporary File Uploads Endpoint Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Livewire handles file uploads by storing uploads in a temporary directory
|
||||||
|
| before the file is validated and stored permanently. All file uploads
|
||||||
|
| are directed to a global endpoint for temporary storage. The config
|
||||||
|
| items below are used for customizing the way the endpoint works.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'temporary_file_upload' => [
|
||||||
|
'disk' => null, // Example: 'local', 's3' Default: 'default'
|
||||||
|
'rules' => null, // Example: ['file', 'mimes:png,jpg'] Default: ['required', 'file', 'max:12288'] (12MB)
|
||||||
|
'directory' => null, // Example: 'tmp' Default 'livewire-tmp'
|
||||||
|
'middleware' => null, // Example: 'throttle:5,1' Default: 'throttle:60,1'
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Manifest File Path
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value sets the path to the Livewire manifest file.
|
||||||
|
| The default should work for most cases (which is
|
||||||
|
| "<app_root>/bootstrap/cache/livewire-components.php)", but for specific
|
||||||
|
| cases like when hosting on Laravel Vapor, it could be set to a different value.
|
||||||
|
|
|
||||||
|
| Example: for Laravel Vapor, it would be "/tmp/storage/bootstrap/cache/livewire-components.php".
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'manifest_path' => null,
|
||||||
|
|
||||||
|
];
|
47
config/sanctum.php
Normal file
47
config/sanctum.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Stateful Domains
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| Requests from the following domains / hosts will receive stateful API
|
||||||
|
| authentication cookies. Typically, these should include your local
|
||||||
|
| and production domains which access your API via a frontend SPA.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,127.0.0.1:8000,::1')),
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expiration Minutes
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| This value controls the number of minutes until an issued token will be
|
||||||
|
| considered expired. If this value is null, personal access tokens do
|
||||||
|
| not expire. This won't tweak the lifetime of first-party sessions.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'expiration' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanctum Middleware
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When authenticating your first-party SPA with Sanctum you may need to
|
||||||
|
| customize some of the middleware Sanctum uses while processing the
|
||||||
|
| request. You may change the middleware listed below as required.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
'middleware' => [
|
||||||
|
'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
|
||||||
|
'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
|
||||||
|
],
|
||||||
|
|
||||||
|
];
|
@@ -18,7 +18,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'driver' => env('SESSION_DRIVER', 'file'),
|
'driver' => env('SESSION_DRIVER', 'database'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@@ -20,6 +20,8 @@ class CreateUsersTable extends Migration
|
|||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
|
$table->string('current_team_id')->nullable();
|
||||||
|
$table->text('profile_photo_path')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddTwoFactorColumnsToUsersTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->text('two_factor_secret')
|
||||||
|
->after('password')
|
||||||
|
->nullable();
|
||||||
|
|
||||||
|
$table->text('two_factor_recovery_codes')
|
||||||
|
->after('two_factor_secret')
|
||||||
|
->nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('users', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('two_factor_secret');
|
||||||
|
$table->dropColumn('two_factor_recovery_codes');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreatePersonalAccessTokensTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('personal_access_tokens', function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->morphs('tokenable');
|
||||||
|
$table->string('name');
|
||||||
|
$table->string('token', 64)->unique();
|
||||||
|
$table->text('abilities')->nullable();
|
||||||
|
$table->timestamp('last_used_at')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('personal_access_tokens');
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class CreateSessionsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::create('sessions', function (Blueprint $table) {
|
||||||
|
$table->string('id')->primary();
|
||||||
|
$table->foreignId('user_id')->nullable()->index();
|
||||||
|
$table->string('ip_address', 45)->nullable();
|
||||||
|
$table->text('user_agent')->nullable();
|
||||||
|
$table->text('payload');
|
||||||
|
$table->integer('last_activity')->index();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('sessions');
|
||||||
|
}
|
||||||
|
}
|
143
package-lock.json
generated
143
package-lock.json
generated
@@ -1068,17 +1068,6 @@
|
|||||||
"purgecss": "^2.3.0"
|
"purgecss": "^2.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@lottiefiles/lottie-player": {
|
|
||||||
"version": "0.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@lottiefiles/lottie-player/-/lottie-player-0.3.0.tgz",
|
|
||||||
"integrity": "sha512-XxRTIEiD3LUUOmsymhLmtyMpGpjRMQhuOqjF3K8PDIE0UEi/yWS67N4klx5UccTACc/pI2TSB5oKl31Z9qVSeA==",
|
|
||||||
"requires": {
|
|
||||||
"@types/pako": "^1.0.1",
|
|
||||||
"lit-element": "^2.3.1",
|
|
||||||
"lottie-web": "^5.6.6",
|
|
||||||
"pako": "^1.0.11"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@mrmlnc/readdir-enhanced": {
|
"@mrmlnc/readdir-enhanced": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||||
@@ -1095,6 +1084,35 @@
|
|||||||
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
|
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@tailwindcss/custom-forms": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/custom-forms/-/custom-forms-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-XdP5XY6kxo3x5o50mWUyoYWxOPV16baagLoZ5uM41gh6IhXzhz/vJYzqrTb/lN58maGIKlpkxgVsQUNSsbAS3Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"mini-svg-data-uri": "^1.0.3",
|
||||||
|
"traverse": "^0.6.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@tailwindcss/typography": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-aPgMH+CjQiScLZculoDNOQUrrK2ktkbl3D6uCLYp1jgYRlNDrMONu9nMu8LfwAeetYNpVNeIGx7WzHSu0kvECg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"@tailwindcss/ui": {
|
||||||
|
"version": "0.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/ui/-/ui-0.5.0.tgz",
|
||||||
|
"integrity": "sha512-UbKe9ti0uMXN2lmgaFgNJC/DY4s2izLaowhIn2A4AgmplC2+XzcYJ9vHLLNNXNBthDq9X+js92tpxey6dBjgfw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@tailwindcss/custom-forms": "^0.2.1",
|
||||||
|
"@tailwindcss/typography": "^0.2.0",
|
||||||
|
"hex-rgb": "^4.1.0",
|
||||||
|
"postcss-selector-parser": "^6.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/color-name": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
@@ -1128,11 +1146,6 @@
|
|||||||
"integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==",
|
"integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/pako": {
|
|
||||||
"version": "1.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.1.tgz",
|
|
||||||
"integrity": "sha512-GdZbRSJ3Cv5fiwT6I0SQ3ckeN2PWNqxd26W9Z2fCK1tGrrasGy4puvNFtnddqH9UJFMQYXxEuuB7B8UK+LLwSg=="
|
|
||||||
},
|
|
||||||
"@types/q": {
|
"@types/q": {
|
||||||
"version": "1.5.4",
|
"version": "1.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz",
|
||||||
@@ -4601,6 +4614,12 @@
|
|||||||
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
|
"integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"hex-rgb": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/hex-rgb/-/hex-rgb-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-I7DkKeQ2kR2uyqgbxPgNgClH/rfs1ioKZhZW8VTIAirsxCR5EyhYeywgZbhMScgUbKCkgo6bb6JwA0CLTn9beA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"hmac-drbg": {
|
"hmac-drbg": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
|
||||||
@@ -5461,19 +5480,6 @@
|
|||||||
"leven": "^3.1.0"
|
"leven": "^3.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lit-element": {
|
|
||||||
"version": "2.4.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-2.4.0.tgz",
|
|
||||||
"integrity": "sha512-pBGLglxyhq/Prk2H91nA0KByq/hx/wssJBQFiYqXhGDvEnY31PRGYf1RglVzyLeRysu0IHm2K0P196uLLWmwFg==",
|
|
||||||
"requires": {
|
|
||||||
"lit-html": "^1.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lit-html": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-0Q1bwmaFH9O14vycPHw8C/IeHMk/uSDldVLIefu/kfbTBGIc44KGH6A8p1bDfxUfHdc8q6Ct7kQklWoHgr4t1Q=="
|
|
||||||
},
|
|
||||||
"loader-runner": {
|
"loader-runner": {
|
||||||
"version": "2.4.0",
|
"version": "2.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
|
||||||
@@ -5549,19 +5555,6 @@
|
|||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"lottie-player-vue": {
|
|
||||||
"version": "0.0.14",
|
|
||||||
"resolved": "https://registry.npmjs.org/lottie-player-vue/-/lottie-player-vue-0.0.14.tgz",
|
|
||||||
"integrity": "sha512-0Gznqnxdsz+mNGkI9xYuX03E/z3k9oYDClKAMLx/8BVbmKLGRof9LVxhNz+eirT4hqACUnWfsUaaJzfAOrhApA==",
|
|
||||||
"requires": {
|
|
||||||
"@lottiefiles/lottie-player": "^0.3.0-rc2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lottie-web": {
|
|
||||||
"version": "5.7.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.7.2.tgz",
|
|
||||||
"integrity": "sha512-lLQ/r/WlYxXe+J8zki/0blBNtNRJJBKm0AdBcD8KJXxpY4Epf70+9XwBM/Z4OHRP+89V1Tuma1wq5oR+hy08qg=="
|
|
||||||
},
|
|
||||||
"lower-case": {
|
"lower-case": {
|
||||||
"version": "1.1.4",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||||
@@ -5781,6 +5774,12 @@
|
|||||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"mini-svg-data-uri": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-zd6KCAyXgmq6FV1mR10oKXYtvmA9vRoB6xPSTUJTbFApCtkefDnYueVR1gkof3KcdLZo1Y8mjF2DFmQMIxsHNQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"minimalistic-assert": {
|
"minimalistic-assert": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
|
||||||
@@ -5880,9 +5879,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"moment": {
|
"moment": {
|
||||||
"version": "2.27.0",
|
"version": "2.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.28.0.tgz",
|
||||||
"integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ=="
|
"integrity": "sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw=="
|
||||||
},
|
},
|
||||||
"move-concurrently": {
|
"move-concurrently": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -6388,7 +6387,8 @@
|
|||||||
"pako": {
|
"pako": {
|
||||||
"version": "1.0.11",
|
"version": "1.0.11",
|
||||||
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw=="
|
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"parallel-transform": {
|
"parallel-transform": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
@@ -6743,6 +6743,26 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"postcss-import": {
|
||||||
|
"version": "12.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-12.0.1.tgz",
|
||||||
|
"integrity": "sha512-3Gti33dmCjyKBgimqGxL3vcV8w9+bsHwO5UrBawp796+jdardbcFl4RP5w/76BwNL7aGzpKstIfF9I+kdE8pTw==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"postcss": "^7.0.1",
|
||||||
|
"postcss-value-parser": "^3.2.3",
|
||||||
|
"read-cache": "^1.0.0",
|
||||||
|
"resolve": "^1.1.7"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"postcss-value-parser": {
|
||||||
|
"version": "3.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
|
||||||
|
"integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"postcss-js": {
|
"postcss-js": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.3.tgz",
|
||||||
@@ -7524,6 +7544,23 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"read-cache": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-5mTvMRYRZsl1HNvo28+GtftY93Q=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"pify": "^2.3.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"pify": {
|
||||||
|
"version": "2.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
|
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "2.3.7",
|
"version": "2.3.7",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
|
||||||
@@ -9104,6 +9141,12 @@
|
|||||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"traverse": {
|
||||||
|
"version": "0.6.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.6.tgz",
|
||||||
|
"integrity": "sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.13.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||||
@@ -9452,14 +9495,6 @@
|
|||||||
"vue-style-loader": "^4.1.0"
|
"vue-style-loader": "^4.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-moment": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/vue-moment/-/vue-moment-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-Gzisqpg82ItlrUyiD9d0Kfru+JorW2o4mQOH06lEDZNgxci0tv/fua1Hl0bo4DozDV2JK1r52Atn/8QVCu8qQw==",
|
|
||||||
"requires": {
|
|
||||||
"moment": "^2.19.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vue-style-loader": {
|
"vue-style-loader": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.2.tgz",
|
||||||
|
12
package.json
12
package.json
@@ -10,19 +10,23 @@
|
|||||||
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
"production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@tailwindcss/ui": "^0.5.0",
|
||||||
"axios": "^0.19",
|
"axios": "^0.19",
|
||||||
"cross-env": "^7.0",
|
"cross-env": "^7.0",
|
||||||
"laravel-mix": "^5.0.1",
|
"laravel-mix": "^5.0.1",
|
||||||
|
"laravel-mix-postcss-config": "^1.0.4",
|
||||||
|
"laravel-mix-purgecss": "^5.0.0",
|
||||||
|
"laravel-mix-tailwind": "^0.1.0",
|
||||||
"lodash": "^4.17.19",
|
"lodash": "^4.17.19",
|
||||||
|
"postcss-import": "^12.0.1",
|
||||||
"resolve-url-loader": "^3.1.0",
|
"resolve-url-loader": "^3.1.0",
|
||||||
"sass": "^1.15.2",
|
"sass": "^1.15.2",
|
||||||
"sass-loader": "^8.0.0",
|
"sass-loader": "^8.0.0",
|
||||||
"vue-template-compiler": "^2.6.11",
|
"tailwindcss": "^1.3.0",
|
||||||
"laravel-mix-postcss-config": "^1.0.4",
|
"vue-template-compiler": "^2.6.11"
|
||||||
"laravel-mix-purgecss": "^5.0.0",
|
|
||||||
"laravel-mix-tailwind": "^0.1.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"moment": "^2.28.0",
|
||||||
"tailwindcss": "^1.6.2",
|
"tailwindcss": "^1.6.2",
|
||||||
"vue": "^2.6.11"
|
"vue": "^2.6.11"
|
||||||
}
|
}
|
||||||
|
2
public/css/app.css
vendored
2
public/css/app.css
vendored
File diff suppressed because one or more lines are too long
2
public/js/app.js
vendored
2
public/js/app.js
vendored
File diff suppressed because one or more lines are too long
2
public/js/vendor.js
vendored
2
public/js/vendor.js
vendored
File diff suppressed because one or more lines are too long
@@ -15,6 +15,4 @@
|
|||||||
|
|
||||||
//! moment.js
|
//! moment.js
|
||||||
|
|
||||||
//! moment.js language configuration
|
|
||||||
|
|
||||||
//! moment.js locale configuration
|
//! moment.js locale configuration
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"/js/app.js": "/js/app.js?id=3f5b2f331693f177ea0a",
|
"/js/app.js": "/js/app.js?id=0ba17f3ef78289d4c782",
|
||||||
"/css/app.css": "/css/app.css?id=bbb0c2c0b76d949f1c54",
|
"/css/app.css": "/css/app.css?id=68dfaea3ff29afe7eab0",
|
||||||
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
|
"/js/manifest.js": "/js/manifest.js?id=3c768977c2574a34506e",
|
||||||
"/js/vendor.js": "/js/vendor.js?id=968f85387c9bab0e92d2"
|
"/js/vendor.js": "/js/vendor.js?id=90cd8c399584d7cba69e"
|
||||||
}
|
}
|
||||||
|
14
public/vendor/livewire/livewire.js
vendored
Normal file
14
public/vendor/livewire/livewire.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/vendor/livewire/livewire.js.map
vendored
Normal file
1
public/vendor/livewire/livewire.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/vendor/livewire/manifest.json
vendored
Normal file
1
public/vendor/livewire/manifest.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"/livewire.js":"/livewire.js?id=09c5bbff75d74521e6c7"}
|
3
resources/css/app.css
vendored
Normal file
3
resources/css/app.css
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@import 'tailwindcss/base';
|
||||||
|
@import 'tailwindcss/components';
|
||||||
|
@import 'tailwindcss/utilities';
|
5
resources/sass/app.scss
vendored
5
resources/sass/app.scss
vendored
@@ -1,5 +0,0 @@
|
|||||||
@tailwind base;
|
|
||||||
|
|
||||||
@tailwind components;
|
|
||||||
|
|
||||||
@tailwind utilities;
|
|
111
resources/views/admin/analytics.blade.php
Normal file
111
resources/views/admin/analytics.blade.php
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||||
|
{{ __('Analytics') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 mt-8">
|
||||||
|
<div class="sm:grid sm:grid-cols-2 sm:gap-10">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-2xl font-bold leading-tight text-gray-900">
|
||||||
|
Visitors and Page Views(Last 2 days)
|
||||||
|
</h2>
|
||||||
|
<div class="flex flex-col mt-6">
|
||||||
|
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
||||||
|
<div
|
||||||
|
class="align-middle inline-block min-w-full shadow overflow-hidden rounded-lg border-b border-gray-200">
|
||||||
|
<table class="min-w-full">
|
||||||
|
<tbody>
|
||||||
|
<tr class="bg-white">
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-semibold text-gray-800">
|
||||||
|
Page Title
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-semibold text-gray-800">
|
||||||
|
Visitors
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-semibold text-gray-800">
|
||||||
|
Page Views
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@foreach ($VisitorsAndPageViews as $VisitorsAndPageView)
|
||||||
|
<tr class="bg-gray-50">
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
|
||||||
|
{{Str::limit($VisitorsAndPageView['pageTitle'],35)}}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
|
{{$VisitorsAndPageView['visitors']}}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
|
{{$VisitorsAndPageView['pageViews']}}
|
||||||
|
|
||||||
|
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-6 sm:mt-0">
|
||||||
|
<h2 class="text-2xl font-bold leading-tight text-gray-900">
|
||||||
|
Total Visitors and Page Views (Last 7 days)
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="flex flex-col mt-6">
|
||||||
|
<div class="-my-2 py-2 overflow-x-auto sm:-mx-6 sm:px-6 lg:-mx-8 lg:px-8">
|
||||||
|
<div
|
||||||
|
class="align-middle inline-block min-w-full shadow overflow-hidden rounded-lg border-b border-gray-200">
|
||||||
|
<table class="min-w-full">
|
||||||
|
<tbody>
|
||||||
|
<tr class="bg-white">
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-semibold text-gray-900">
|
||||||
|
Date
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-semibold text-gray-900">
|
||||||
|
Visitors
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5font-semibold text-gray-900">
|
||||||
|
Page Views
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@foreach ($TotalVisitorsAndPageViews as $TotalVisitorsAndPageView)
|
||||||
|
<tr class="bg-gray-50">
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-no-wrap text-sm leading-5 font-medium text-gray-900">
|
||||||
|
{{$TotalVisitorsAndPageView['date']->diffforHumans()}}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
|
{{$TotalVisitorsAndPageView['visitors']}}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-no-wrap text-sm leading-5 text-gray-500">
|
||||||
|
{{$TotalVisitorsAndPageView['pageViews']}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</x-app-layout>
|
87
resources/views/admin/dashboard.blade.php
Normal file
87
resources/views/admin/dashboard.blade.php
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||||
|
{{ __('Dashboard') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div class="py-12">
|
||||||
|
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||||
|
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
|
||||||
|
<div class="p-6 sm:px-20 bg-white border-b border-gray-200">
|
||||||
|
<div class="mt-8 text-2xl font-semibold">
|
||||||
|
Karudhaas Overview
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-gray-200 bg-opacity-25 grid grid-cols-1 md:grid-cols-3">
|
||||||
|
<div class="p-6">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
<div class="ml-4 text-lg text-gray-600 leading-7 font-semibold">Articles</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ml-12">
|
||||||
|
<div class="mt-2 text-gray-500 font-bold text-3xl">
|
||||||
|
{{$total_articles}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6 border-t border-gray-200 md:border-t-0 md:border-l">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
<div class="ml-4 text-lg text-gray-600 leading-7 font-semibold">Topics</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ml-12">
|
||||||
|
<div class="mt-2 text-gray-500 font-bold text-3xl">
|
||||||
|
{{$total_topics}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-6 border-t border-gray-200">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<svg class="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" stroke-linecap="round"
|
||||||
|
stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M19 20H5a2 2 0 01-2-2V6a2 2 0 012-2h10a2 2 0 012 2v1m2 13a2 2 0 01-2-2V7m2 13a2 2 0 002-2V9a2 2 0 00-2-2h-2m-4-3H9M7 16h6M7 8h6v4H7V8z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
<div class="ml-4 text-lg text-gray-600 leading-7 font-semibold">Sources</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ml-12">
|
||||||
|
<div class="mt-2 text-gray-500 font-bold text-3xl">
|
||||||
|
{{$total_sources}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
167
resources/views/api/api-token-manager.blade.php
Normal file
167
resources/views/api/api-token-manager.blade.php
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
<div>
|
||||||
|
<!-- Generate API Token -->
|
||||||
|
<x-jet-form-section submit="createApiToken">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Create API Token') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('API tokens allow third-party services to authenticate with our application on your behalf.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="form">
|
||||||
|
<!-- Token Name -->
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="name" value="{{ __('Token Name') }}" />
|
||||||
|
<x-jet-input id="name" type="text" class="mt-1 block w-full" wire:model.defer="createApiTokenForm.name" autofocus />
|
||||||
|
<x-jet-input-error for="name" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Token Permissions -->
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasPermissions())
|
||||||
|
<div class="col-span-6">
|
||||||
|
<x-jet-label for="permissions" value="{{ __('Permissions') }}" />
|
||||||
|
|
||||||
|
<div class="mt-2 grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
|
||||||
|
<label class="flex items-center">
|
||||||
|
<input type="checkbox" class="form-checkbox" value="{{ $permission }}" wire:model.defer="createApiTokenForm.permissions">
|
||||||
|
<span class="ml-2 text-sm text-gray-600">{{ $permission }}</span>
|
||||||
|
</label>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="actions">
|
||||||
|
<x-jet-action-message class="mr-3" on="created">
|
||||||
|
{{ __('Created.') }}
|
||||||
|
</x-jet-action-message>
|
||||||
|
|
||||||
|
<x-jet-button>
|
||||||
|
{{ __('Create') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-form-section>
|
||||||
|
|
||||||
|
@if ($this->user->tokens->isNotEmpty())
|
||||||
|
<x-jet-section-border />
|
||||||
|
|
||||||
|
<!-- Manage API Tokens -->
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
<x-jet-action-section>
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Manage API Tokens') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('You may delete any of your existing tokens if they are no longer needed.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<!-- API Token List -->
|
||||||
|
<x-slot name="content">
|
||||||
|
<div class="space-y-6">
|
||||||
|
@foreach ($this->user->tokens->sortBy('name') as $token)
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div>
|
||||||
|
{{ $token->name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center">
|
||||||
|
@if ($token->last_used_at)
|
||||||
|
<div class="text-sm text-gray-400">
|
||||||
|
{{ __('Last used') }} {{ $token->last_used_at->diffForHumans() }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasPermissions())
|
||||||
|
<button class="cursor-pointer ml-6 text-sm text-gray-400 underline focus:outline-none" wire:click="manageApiTokenPermissions({{ $token->id }})">
|
||||||
|
{{ __('Permissions') }}
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<button class="cursor-pointer ml-6 text-sm text-red-500 focus:outline-none" wire:click="confirmApiTokenDeletion({{ $token->id }})">
|
||||||
|
{{ __('Delete') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-action-section>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Token Value Modal -->
|
||||||
|
<x-jet-dialog-modal wire:model="displayingToken">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('API Token') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<div>
|
||||||
|
{{ __('Please copy your new API token. For your security, it won\'t be shown again.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4 bg-gray-100 px-4 py-2 rounded font-mono text-sm text-gray-500">
|
||||||
|
{{ $plainTextToken }}
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="$set('displayingToken', false)" wire:loading.attr="disabled">
|
||||||
|
{{ __('Close') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dialog-modal>
|
||||||
|
|
||||||
|
<!-- API Token Permissions Modal -->
|
||||||
|
<x-jet-dialog-modal wire:model="managingApiTokenPermissions">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('API Token Permissions') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
|
@foreach (Laravel\Jetstream\Jetstream::$permissions as $permission)
|
||||||
|
<label class="flex items-center">
|
||||||
|
<input type="checkbox" class="form-checkbox" value="{{ $permission }}" wire:model.defer="updateApiTokenForm.permissions">
|
||||||
|
<span class="ml-2 text-sm text-gray-600">{{ $permission }}</span>
|
||||||
|
</label>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="$set('managingApiTokenPermissions', false)" wire:loading.attr="disabled">
|
||||||
|
{{ __('Nevermind') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
<x-jet-button class="ml-2" wire:click="updateApiToken" wire:loading.attr="disabled">
|
||||||
|
{{ __('Save') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dialog-modal>
|
||||||
|
|
||||||
|
<!-- Delete Token Confirmation Modal -->
|
||||||
|
<x-jet-confirmation-modal wire:model="confirmingApiTokenDeletion">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Delete API Token') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
{{ __('Are you sure you would like to delete this API token?') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="$toggle('confirmingApiTokenDeletion')" wire:loading.attr="disabled">
|
||||||
|
{{ __('Nevermind') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
<x-jet-danger-button class="ml-2" wire:click="deleteApiToken" wire:loading.attr="disabled">
|
||||||
|
{{ __('Delete') }}
|
||||||
|
</x-jet-danger-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-confirmation-modal>
|
||||||
|
</div>
|
13
resources/views/api/index.blade.php
Normal file
13
resources/views/api/index.blade.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||||
|
{{ __('API Tokens') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||||
|
@livewire('api.api-token-manager')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
34
resources/views/auth/forgot-password.blade.php
Normal file
34
resources/views/auth/forgot-password.blade.php
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div class="mb-4 text-sm text-gray-600">
|
||||||
|
{{ __('Forgot your password? No problem. Just let us know your email address and we will email you a password reset link that will allow you to choose a new one.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (session('status'))
|
||||||
|
<div class="mb-4 font-medium text-sm text-green-600">
|
||||||
|
{{ session('status') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-jet-validation-errors class="mb-4" />
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('password.email') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
<x-jet-label value="{{ __('Email') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
<x-jet-button>
|
||||||
|
{{ __('Email Password Reset Link') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
48
resources/views/auth/login.blade.php
Normal file
48
resources/views/auth/login.blade.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-jet-validation-errors class="mb-4" />
|
||||||
|
|
||||||
|
@if (session('status'))
|
||||||
|
<div class="mb-4 font-medium text-sm text-green-600">
|
||||||
|
{{ session('status') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('login') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-jet-label value="{{ __('Email') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Password') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="password" name="password" required autocomplete="current-password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="block mt-4">
|
||||||
|
<label class="flex items-center">
|
||||||
|
<input type="checkbox" class="form-checkbox" name="remember">
|
||||||
|
<span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
@if (Route::has('password.request'))
|
||||||
|
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('password.request') }}">
|
||||||
|
{{ __('Forgot your password?') }}
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-jet-button class="ml-4">
|
||||||
|
{{ __('Login') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
43
resources/views/auth/register.blade.php
Normal file
43
resources/views/auth/register.blade.php
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-jet-validation-errors class="mb-4" />
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('register') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-jet-label value="{{ __('Name') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Email') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="email" name="email" :value="old('email')" required />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Password') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Confirm Password') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="password" name="password_confirmation" required autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('login') }}">
|
||||||
|
{{ __('Already registered?') }}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<x-jet-button class="ml-4">
|
||||||
|
{{ __('Register') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
36
resources/views/auth/reset-password.blade.php
Normal file
36
resources/views/auth/reset-password.blade.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-jet-validation-errors class="mb-4" />
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('password.update') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<input type="hidden" name="token" value="{{ $request->route('token') }}">
|
||||||
|
|
||||||
|
<div class="block">
|
||||||
|
<x-jet-label value="{{ __('Email') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="email" name="email" :value="old('email', $request->email)" required autofocus />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Password') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="password" name="password" required autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
<x-jet-label value="{{ __('Confirm Password') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="password" name="password_confirmation" required autocomplete="new-password" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
<x-jet-button>
|
||||||
|
{{ __('Reset Password') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
57
resources/views/auth/two-factor-challenge.blade.php
Normal file
57
resources/views/auth/two-factor-challenge.blade.php
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div x-data="{ recovery: false }">
|
||||||
|
<div class="mb-4 text-sm text-gray-600" x-show="! recovery">
|
||||||
|
{{ __('Please confirm access to your account by entering the authentication code provided by your authenticator application.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4 text-sm text-gray-600" x-show="recovery">
|
||||||
|
{{ __('Please confirm access to your account by entering one of your emergency recovery codes.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-jet-validation-errors class="mb-4" />
|
||||||
|
|
||||||
|
<form method="POST" action="/two-factor-challenge">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div class="mt-4" x-show="! recovery">
|
||||||
|
<x-jet-label value="{{ __('Code') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="text" name="code" autofocus x-ref="code" autocomplete="one-time-code" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4" x-show="recovery">
|
||||||
|
<x-jet-label value="{{ __('Recovery Code') }}" />
|
||||||
|
<x-jet-input class="block mt-1 w-full" type="text" name="recovery_code" x-ref="recovery_code" autocomplete="one-time-code" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center justify-end mt-4">
|
||||||
|
<button type="button" class="text-sm text-gray-600 hover:text-gray-900 underline cursor-pointer"
|
||||||
|
x-show="! recovery"
|
||||||
|
x-on:click="
|
||||||
|
recovery = true;
|
||||||
|
$nextTick(() => { $refs.recovery_code.focus() })
|
||||||
|
">
|
||||||
|
{{ __('Use a recovery code') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="text-sm text-gray-600 hover:text-gray-900 underline cursor-pointer"
|
||||||
|
x-show="recovery"
|
||||||
|
x-on:click="
|
||||||
|
recovery = false;
|
||||||
|
$nextTick(() => { $refs.code.focus() })
|
||||||
|
">
|
||||||
|
{{ __('Use an authentication code') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<x-jet-button class="ml-4">
|
||||||
|
{{ __('Login') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
37
resources/views/auth/verify-email.blade.php
Normal file
37
resources/views/auth/verify-email.blade.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<x-guest-layout>
|
||||||
|
<x-jet-authentication-card>
|
||||||
|
<x-slot name="logo">
|
||||||
|
<x-jet-authentication-card-logo />
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div class="mb-4 text-sm text-gray-600">
|
||||||
|
{{ __('Thanks for signing up! Before getting started, could you verify your email address by clicking on the link we just emailed to you? If you didn\'t receive the email, we will gladly send you another.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (session('status') == 'verification-link-sent')
|
||||||
|
<div class="mb-4 font-medium text-sm text-green-600">
|
||||||
|
{{ __('A new verification link has been sent to the email address you provided during registration.') }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="mt-4 flex items-center justify-between">
|
||||||
|
<form method="POST" action="{{ route('verification.send') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<x-jet-button type="submit">
|
||||||
|
{{ __('Resend Verification Email') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<button type="submit" class="underline text-sm text-gray-600 hover:text-gray-900">
|
||||||
|
{{ __('Logout') }}
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</x-jet-authentication-card>
|
||||||
|
</x-guest-layout>
|
42
resources/views/layouts/admin.blade.php
Normal file
42
resources/views/layouts/admin.blade.php
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
|
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:400,600,700" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Styles -->
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
|
||||||
|
|
||||||
|
@livewireStyles
|
||||||
|
|
||||||
|
<!-- Scripts -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.6.0/dist/alpine.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body class="font-sans antialiased">
|
||||||
|
<div class="min-h-screen bg-gray-100">
|
||||||
|
@livewire('navigation-dropdown')
|
||||||
|
|
||||||
|
<!-- Page Heading -->
|
||||||
|
<header class="bg-white shadow">
|
||||||
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||||
|
{{ $header }}
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Page Content -->
|
||||||
|
<main>
|
||||||
|
{{ $slot }}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@stack('modals')
|
||||||
|
|
||||||
|
@livewireScripts
|
||||||
|
</body>
|
||||||
|
</html>
|
24
resources/views/layouts/guest.blade.php
Normal file
24
resources/views/layouts/guest.blade.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||||
|
|
||||||
|
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||||
|
|
||||||
|
<!-- Fonts -->
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Nunito:400,600,700" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- Styles -->
|
||||||
|
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
|
||||||
|
|
||||||
|
<!-- Scripts -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.2.1/dist/alpine.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="font-sans text-gray-900 antialiased">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
186
resources/views/navigation-dropdown.blade.php
Normal file
186
resources/views/navigation-dropdown.blade.php
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
<nav x-data="{ open: false }" class="bg-white border-b border-gray-100">
|
||||||
|
<!-- Primary Navigation Menu -->
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex justify-between h-16">
|
||||||
|
<div class="flex">
|
||||||
|
<!-- Logo -->
|
||||||
|
<div class="flex-shrink-0 flex items-center">
|
||||||
|
<a href="/dashboard">
|
||||||
|
<img src="/images/icon.png" class="block h-9 w-auto" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Navigation Links -->
|
||||||
|
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||||
|
<x-jet-nav-link href="/dashboard" :active="request()->routeIs('dashboard.index')">
|
||||||
|
{{ __('Dashboard') }}
|
||||||
|
</x-jet-nav-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
|
||||||
|
<x-jet-nav-link href="/dashboard/analytics" :active="request()->routeIs('dashboard.analytics')">
|
||||||
|
{{ __('Analytics') }}
|
||||||
|
</x-jet-nav-link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Settings Dropdown -->
|
||||||
|
<div class="hidden sm:flex sm:items-center sm:ml-6">
|
||||||
|
<x-jet-dropdown align="right" width="48">
|
||||||
|
<x-slot name="trigger">
|
||||||
|
<button class="flex text-sm border-2 border-transparent rounded-full focus:outline-none focus:border-gray-300 transition duration-150 ease-in-out">
|
||||||
|
<img class="h-8 w-8 rounded-full object-cover" src="{{ Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" />
|
||||||
|
</button>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<!-- Account Management -->
|
||||||
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
|
{{ __('Manage Account') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-jet-dropdown-link href="/user/profile">
|
||||||
|
{{ __('Profile') }}
|
||||||
|
</x-jet-dropdown-link>
|
||||||
|
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasApiFeatures())
|
||||||
|
<x-jet-dropdown-link href="/user/api-tokens">
|
||||||
|
{{ __('API Tokens') }}
|
||||||
|
</x-jet-dropdown-link>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="border-t border-gray-100"></div>
|
||||||
|
|
||||||
|
<!-- Team Management -->
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasTeamFeatures())
|
||||||
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
|
{{ __('Manage Team') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Team Settings -->
|
||||||
|
<x-jet-dropdown-link href="/teams/{{ Auth::user()->currentTeam->id }}">
|
||||||
|
{{ __('Team Settings') }}
|
||||||
|
</x-jet-dropdown-link>
|
||||||
|
|
||||||
|
@can('create', Laravel\Jetstream\Jetstream::newTeamModel())
|
||||||
|
<x-jet-dropdown-link href="/teams/create">
|
||||||
|
{{ __('Create New Team') }}
|
||||||
|
</x-jet-dropdown-link>
|
||||||
|
@endcan
|
||||||
|
|
||||||
|
<div class="border-t border-gray-100"></div>
|
||||||
|
|
||||||
|
<!-- Team Switcher -->
|
||||||
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
|
{{ __('Switch Teams') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach (Auth::user()->allTeams() as $team)
|
||||||
|
<x-jet-switchable-team :team="$team" />
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<div class="border-t border-gray-100"></div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Authentication -->
|
||||||
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<x-jet-dropdown-link href="{{ route('logout') }}"
|
||||||
|
onclick="event.preventDefault();
|
||||||
|
this.closest('form').submit();">
|
||||||
|
{{ __('Logout') }}
|
||||||
|
</x-jet-dropdown-link>
|
||||||
|
</form>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dropdown>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Hamburger -->
|
||||||
|
<div class="-mr-2 flex items-center sm:hidden">
|
||||||
|
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out">
|
||||||
|
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
|
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Responsive Navigation Menu -->
|
||||||
|
<div :class="{'block': open, 'hidden': ! open}" class="hidden sm:hidden">
|
||||||
|
<div class="pt-2 pb-3 space-y-1">
|
||||||
|
<x-jet-responsive-nav-link href="/dashboard" :active="request()->routeIs('dashboard')">
|
||||||
|
{{ __('Dashboard') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Responsive Settings Options -->
|
||||||
|
<div class="pt-4 pb-1 border-t border-gray-200">
|
||||||
|
<div class="flex items-center px-4">
|
||||||
|
<div class="flex-shrink-0">
|
||||||
|
<img class="h-10 w-10 rounded-full" src="{{ Auth::user()->profile_photo_url }}" alt="{{ Auth::user()->name }}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ml-3">
|
||||||
|
<div class="font-medium text-base text-gray-800">{{ Auth::user()->name }}</div>
|
||||||
|
<div class="font-medium text-sm text-gray-500">{{ Auth::user()->email }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 space-y-1">
|
||||||
|
<!-- Account Management -->
|
||||||
|
<x-jet-responsive-nav-link href="/user/profile" :active="request()->routeIs('profile.show')">
|
||||||
|
{{ __('Profile') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasApiFeatures())
|
||||||
|
<x-jet-responsive-nav-link href="/user/api-tokens" :active="request()->routeIs('api-tokens.index')">
|
||||||
|
{{ __('API Tokens') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Authentication -->
|
||||||
|
<form method="POST" action="{{ route('logout') }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<x-jet-responsive-nav-link href="{{ route('logout') }}"
|
||||||
|
onclick="event.preventDefault();
|
||||||
|
this.closest('form').submit();">
|
||||||
|
{{ __('Logout') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<!-- Team Management -->
|
||||||
|
@if (Laravel\Jetstream\Jetstream::hasTeamFeatures())
|
||||||
|
<div class="border-t border-gray-200"></div>
|
||||||
|
|
||||||
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
|
{{ __('Manage Team') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Team Settings -->
|
||||||
|
<x-jet-responsive-nav-link href="/teams/{{ Auth::user()->currentTeam->id }}" :active="request()->routeIs('teams.show')">
|
||||||
|
{{ __('Team Settings') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
|
||||||
|
<x-jet-responsive-nav-link href="/teams/create" :active="request()->routeIs('teams.create')">
|
||||||
|
{{ __('Create New Team') }}
|
||||||
|
</x-jet-responsive-nav-link>
|
||||||
|
|
||||||
|
<div class="border-t border-gray-200"></div>
|
||||||
|
|
||||||
|
<!-- Team Switcher -->
|
||||||
|
<div class="block px-4 py-2 text-xs text-gray-400">
|
||||||
|
{{ __('Switch Teams') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@foreach (Auth::user()->allTeams() as $team)
|
||||||
|
<x-jet-switchable-team :team="$team" component="jet-responsive-nav-link" />
|
||||||
|
@endforeach
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
51
resources/views/profile/delete-user-form.blade.php
Normal file
51
resources/views/profile/delete-user-form.blade.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<x-jet-action-section>
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Delete Account') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Permanently delete your account.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<div class="max-w-xl text-sm text-gray-600">
|
||||||
|
{{ __('Once your account is deleted, all of its resources and data will be permanently deleted. Before deleting your account, please download any data or information that you wish to retain.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-5">
|
||||||
|
<x-jet-danger-button wire:click="confirmUserDeletion" wire:loading.attr="disabled">
|
||||||
|
{{ __('Delete Account') }}
|
||||||
|
</x-jet-danger-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Delete User Confirmation Modal -->
|
||||||
|
<x-jet-dialog-modal wire:model="confirmingUserDeletion">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Delete Account') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
{{ __('Are you sure you want to delete your account? Once your account is deleted, all of its resources and data will be permanently deleted. Please enter your password to confirm you would like to permanently delete your account.') }}
|
||||||
|
|
||||||
|
<div class="mt-4" x-data="{}" x-on:confirming-delete-user.window="setTimeout(() => $refs.password.focus(), 250)">
|
||||||
|
<x-jet-input type="password" class="mt-1 block w-3/4" placeholder="Password"
|
||||||
|
x-ref="password"
|
||||||
|
wire:model.defer="password"
|
||||||
|
wire:keydown.enter="deleteUser" />
|
||||||
|
|
||||||
|
<x-jet-input-error for="password" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="$toggle('confirmingUserDeletion')" wire:loading.attr="disabled">
|
||||||
|
{{ __('Nevermind') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
<x-jet-danger-button class="ml-2" wire:click="deleteUser" wire:loading.attr="disabled">
|
||||||
|
{{ __('Delete Account') }}
|
||||||
|
</x-jet-danger-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dialog-modal>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-action-section>
|
@@ -0,0 +1,94 @@
|
|||||||
|
<x-jet-action-section>
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Browser Sessions') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Manage and logout your active sessions on other browsers and devices.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<div class="max-w-xl text-sm text-gray-600">
|
||||||
|
{{ __('If necessary, you may logout of all of your other browser sessions across all of your devices. If you feel your account has been compromised, you should also update your password.') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (count($this->sessions) > 0)
|
||||||
|
<div class="mt-5 space-y-6">
|
||||||
|
<!-- Other Browser Sessions -->
|
||||||
|
@foreach ($this->sessions as $session)
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div>
|
||||||
|
@if ($session->agent->isDesktop())
|
||||||
|
<svg fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" stroke="currentColor" class="w-8 h-8 text-gray-500">
|
||||||
|
<path d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z"></path>
|
||||||
|
</svg>
|
||||||
|
@else
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" class="w-8 h-8 text-gray-500">
|
||||||
|
<path d="M0 0h24v24H0z" stroke="none"></path><rect x="7" y="4" width="10" height="16" rx="1"></rect><path d="M11 5h2M12 17v.01"></path>
|
||||||
|
</svg>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="ml-3">
|
||||||
|
<div class="text-sm text-gray-600">
|
||||||
|
{{ $session->agent->platform() }} - {{ $session->agent->browser() }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="text-xs text-gray-500">
|
||||||
|
{{ $session->ip_address }},
|
||||||
|
|
||||||
|
@if ($session->is_current_device)
|
||||||
|
<span class="text-green-500 font-semibold">{{ __('This device') }}</span>
|
||||||
|
@else
|
||||||
|
{{ __('Last active') }} {{ $session->last_active }}
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="flex items-center mt-5">
|
||||||
|
<x-jet-button wire:click="confirmLogout" wire:loading.attr="disabled">
|
||||||
|
{{ __('Logout Other Browser Sessions') }}
|
||||||
|
</x-jet-button>
|
||||||
|
|
||||||
|
<x-jet-action-message class="ml-3" on="loggedOut">
|
||||||
|
{{ __('Done.') }}
|
||||||
|
</x-jet-action-message>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Logout Other Devices Confirmation Modal -->
|
||||||
|
<x-jet-dialog-modal wire:model="confirmingLogout">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Logout Other Browser Sessions') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
{{ __('Please enter your password to confirm you would like to logout of your other browser sessions across all of your devices.') }}
|
||||||
|
|
||||||
|
<div class="mt-4" x-data="{}" x-on:confirming-logout-other-browser-sessions.window="setTimeout(() => $refs.password.focus(), 250)">
|
||||||
|
<x-jet-input type="password" class="mt-1 block w-3/4" placeholder="Password"
|
||||||
|
x-ref="password"
|
||||||
|
wire:model.defer="password"
|
||||||
|
wire:keydown.enter="logoutOtherBrowserSessions" />
|
||||||
|
|
||||||
|
<x-jet-input-error for="password" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="$toggle('confirmingLogout')" wire:loading.attr="disabled">
|
||||||
|
{{ __('Nevermind') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
<x-jet-button class="ml-2" wire:click="logoutOtherBrowserSessions" wire:loading.attr="disabled">
|
||||||
|
{{ __('Logout Other Browser Sessions') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dialog-modal>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-action-section>
|
41
resources/views/profile/show.blade.php
Normal file
41
resources/views/profile/show.blade.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<x-app-layout>
|
||||||
|
<x-slot name="header">
|
||||||
|
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||||
|
{{ __('Profile') }}
|
||||||
|
</h2>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||||
|
@livewire('profile.update-profile-information-form')
|
||||||
|
|
||||||
|
@if (Laravel\Fortify\Features::enabled(Laravel\Fortify\Features::updatePasswords()))
|
||||||
|
<x-jet-section-border />
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
@livewire('profile.update-password-form')
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if (Laravel\Fortify\Features::canManageTwoFactorAuthentication())
|
||||||
|
<x-jet-section-border />
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
@livewire('profile.two-factor-authentication-form')
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-jet-section-border />
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
@livewire('profile.logout-other-browser-sessions-form')
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-jet-section-border />
|
||||||
|
|
||||||
|
<div class="mt-10 sm:mt-0">
|
||||||
|
@livewire('profile.delete-user-form')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
@@ -0,0 +1,83 @@
|
|||||||
|
<x-jet-action-section>
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Two Factor Authentication') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Add additional security to your account using two factor authentication.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
<h3 class="text-lg font-medium text-gray-900">
|
||||||
|
@if ($this->enabled)
|
||||||
|
{{ __('You have enabled two factor authentication.') }}
|
||||||
|
@else
|
||||||
|
{{ __('You have not enabled two factor authentication.') }}
|
||||||
|
@endif
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="mt-3 max-w-xl text-sm text-gray-600">
|
||||||
|
<p>
|
||||||
|
{{ __('When two factor authentication is enabled, you will be prompted for a secure, random token during authentication. You may retrieve this token from your phone\'s Google Authenticator application.') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if ($this->enabled)
|
||||||
|
@if ($showingQrCode)
|
||||||
|
<div class="mt-4 max-w-xl text-sm text-gray-600">
|
||||||
|
<p class="font-semibold">
|
||||||
|
{{ __('Two factor authentication is now enabled. Scan the following QR code using your phone\'s authenticator application.') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
{!! $this->user->twoFactorQrCodeSvg() !!}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
@if ($showingRecoveryCodes)
|
||||||
|
<div class="mt-4 max-w-xl text-sm text-gray-600">
|
||||||
|
<p class="font-semibold">
|
||||||
|
{{ __('Store these recovery codes in a secure password manager. They can be used to recover access to your account if your two factor authentication device is lost.') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid gap-1 max-w-xl mt-4 px-4 py-4 font-mono text-sm bg-gray-100 rounded-lg">
|
||||||
|
@foreach (json_decode(decrypt($this->user->two_factor_recovery_codes), true) as $code)
|
||||||
|
<div>{{ $code }}</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="mt-5">
|
||||||
|
@if (! $this->enabled)
|
||||||
|
<x-jet-confirms-password wire:then="enableTwoFactorAuthentication">
|
||||||
|
<x-jet-button type="button" wire:loading.attr="disabled">
|
||||||
|
{{ __('Enable') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-jet-confirms-password>
|
||||||
|
@else
|
||||||
|
@if ($showingRecoveryCodes)
|
||||||
|
<x-jet-confirms-password wire:then="regenerateRecoveryCodes">
|
||||||
|
<x-jet-secondary-button class="mr-3">
|
||||||
|
{{ __('Regenerate Recovery Codes') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
</x-jet-confirms-password>
|
||||||
|
@else
|
||||||
|
<x-jet-confirms-password wire:then="showRecoveryCodes">
|
||||||
|
<x-jet-secondary-button class="mr-3">
|
||||||
|
{{ __('Show Recovery Codes') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
</x-jet-confirms-password>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-jet-confirms-password wire:then="disableTwoFactorAuthentication">
|
||||||
|
<x-jet-danger-button wire:loading.attr="disabled">
|
||||||
|
{{ __('Disable') }}
|
||||||
|
</x-jet-danger-button>
|
||||||
|
</x-jet-confirms-password>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-action-section>
|
39
resources/views/profile/update-password-form.blade.php
Normal file
39
resources/views/profile/update-password-form.blade.php
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<x-jet-form-section submit="updatePassword">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Update Password') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Ensure your account is using a long, random password to stay secure.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="form">
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="current_password" value="{{ __('Current Password') }}" />
|
||||||
|
<x-jet-input id="current_password" type="password" class="mt-1 block w-full" wire:model.defer="state.current_password" autocomplete="current-password" />
|
||||||
|
<x-jet-input-error for="current_password" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="password" value="{{ __('New Password') }}" />
|
||||||
|
<x-jet-input id="password" type="password" class="mt-1 block w-full" wire:model.defer="state.password" autocomplete="new-password" />
|
||||||
|
<x-jet-input-error for="password" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="password_confirmation" value="{{ __('Confirm Password') }}" />
|
||||||
|
<x-jet-input id="password_confirmation" type="password" class="mt-1 block w-full" wire:model.defer="state.password_confirmation" autocomplete="new-password" />
|
||||||
|
<x-jet-input-error for="password_confirmation" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="actions">
|
||||||
|
<x-jet-action-message class="mr-3" on="saved">
|
||||||
|
{{ __('Saved.') }}
|
||||||
|
</x-jet-action-message>
|
||||||
|
|
||||||
|
<x-jet-button>
|
||||||
|
{{ __('Save') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-form-section>
|
@@ -0,0 +1,79 @@
|
|||||||
|
<x-jet-form-section submit="updateProfileInformation">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ __('Profile Information') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="description">
|
||||||
|
{{ __('Update your account\'s profile information and email address.') }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="form">
|
||||||
|
<!-- Profile Photo -->
|
||||||
|
@if (Laravel\Jetstream\Jetstream::managesProfilePhotos())
|
||||||
|
<div x-data="{photoName: null, photoPreview: null}" class="col-span-6 sm:col-span-4">
|
||||||
|
<!-- Profile Photo File Input -->
|
||||||
|
<input type="file" class="hidden"
|
||||||
|
wire:model="photo"
|
||||||
|
x-ref="photo"
|
||||||
|
x-on:change="
|
||||||
|
photoName = $refs.photo.files[0].name;
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
photoPreview = e.target.result;
|
||||||
|
};
|
||||||
|
reader.readAsDataURL($refs.photo.files[0]);
|
||||||
|
" />
|
||||||
|
|
||||||
|
<x-jet-label for="photo" value="{{ __('Photo') }}" />
|
||||||
|
|
||||||
|
<!-- Current Profile Photo -->
|
||||||
|
<div class="mt-2" x-show="! photoPreview">
|
||||||
|
<img src="{{ $this->user->profile_photo_url }}" alt="{{ $this->user->name }}" class="rounded-full h-20 w-20 object-cover">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- New Profile Photo Preview -->
|
||||||
|
<div class="mt-2" x-show="photoPreview">
|
||||||
|
<span class="block rounded-full w-20 h-20"
|
||||||
|
x-bind:style="'background-size: cover; background-repeat: no-repeat; background-position: center center; background-image: url(\'' + photoPreview + '\');'">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<x-jet-secondary-button class="mt-2 mr-2" type="button" x-on:click.prevent="$refs.photo.click()">
|
||||||
|
{{ __('Select A New Photo') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
@if ($this->user->profile_photo_path)
|
||||||
|
<x-jet-secondary-button type="button" class="mt-2" wire:click="deleteProfilePhoto">
|
||||||
|
{{ __('Remove Photo') }}
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<x-jet-input-error for="photo" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- Name -->
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="name" value="{{ __('Name') }}" />
|
||||||
|
<x-jet-input id="name" type="text" class="mt-1 block w-full" wire:model.defer="state.name" autocomplete="name" />
|
||||||
|
<x-jet-input-error for="name" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Email -->
|
||||||
|
<div class="col-span-6 sm:col-span-4">
|
||||||
|
<x-jet-label for="email" value="Email" />
|
||||||
|
<x-jet-input id="email" type="email" class="mt-1 block w-full" wire:model.defer="state.email" />
|
||||||
|
<x-jet-input-error for="email" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="actions">
|
||||||
|
<x-jet-action-message class="mr-3" on="saved">
|
||||||
|
{{ __('Saved.') }}
|
||||||
|
</x-jet-action-message>
|
||||||
|
|
||||||
|
<x-jet-button>
|
||||||
|
{{ __('Save') }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-form-section>
|
9
resources/views/vendor/jetstream/components/action-message.blade.php
vendored
Normal file
9
resources/views/vendor/jetstream/components/action-message.blade.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
@props(['on'])
|
||||||
|
|
||||||
|
<div x-data="{ shown: false, timeout: null }"
|
||||||
|
x-init="@this.on('{{ $on }}', () => { clearTimeout(timeout); shown = true; timeout = setTimeout(() => { shown = false }, 2000); })"
|
||||||
|
x-show.transition.opacity.out.duration.1500ms="shown"
|
||||||
|
style="display: none;"
|
||||||
|
{{ $attributes->merge(['class' => 'text-sm text-gray-600']) }}>
|
||||||
|
{{ $slot ?? 'Saved.' }}
|
||||||
|
</div>
|
12
resources/views/vendor/jetstream/components/action-section.blade.php
vendored
Normal file
12
resources/views/vendor/jetstream/components/action-section.blade.php
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<div class="md:grid md:grid-cols-3 md:gap-6" {{ $attributes }}>
|
||||||
|
<x-jet-section-title>
|
||||||
|
<x-slot name="title">{{ $title }}</x-slot>
|
||||||
|
<x-slot name="description">{{ $description }}</x-slot>
|
||||||
|
</x-jet-section-title>
|
||||||
|
|
||||||
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||||
|
<div class="px-4 py-5 sm:p-6 bg-white shadow sm:rounded-lg">
|
||||||
|
{{ $content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
5
resources/views/vendor/jetstream/components/application-logo.blade.php
vendored
Normal file
5
resources/views/vendor/jetstream/components/application-logo.blade.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg viewBox="0 0 317 48" fill="none" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<path d="M74.09 30.04V13h-4.14v21H82.1v-3.96h-8.01zM95.379 19v1.77c-1.08-1.35-2.7-2.19-4.89-2.19-3.99 0-7.29 3.45-7.29 7.92s3.3 7.92 7.29 7.92c2.19 0 3.81-.84 4.89-2.19V34h3.87V19h-3.87zm-4.17 11.73c-2.37 0-4.14-1.71-4.14-4.23 0-2.52 1.77-4.23 4.14-4.23 2.4 0 4.17 1.71 4.17 4.23 0 2.52-1.77 4.23-4.17 4.23zM106.628 21.58V19h-3.87v15h3.87v-7.17c0-3.15 2.55-4.05 4.56-3.81V18.7c-1.89 0-3.78.84-4.56 2.88zM124.295 19v1.77c-1.08-1.35-2.7-2.19-4.89-2.19-3.99 0-7.29 3.45-7.29 7.92s3.3 7.92 7.29 7.92c2.19 0 3.81-.84 4.89-2.19V34h3.87V19h-3.87zm-4.17 11.73c-2.37 0-4.14-1.71-4.14-4.23 0-2.52 1.77-4.23 4.14-4.23 2.4 0 4.17 1.71 4.17 4.23 0 2.52-1.77 4.23-4.17 4.23zM141.544 19l-3.66 10.5-3.63-10.5h-4.26l5.7 15h4.41l5.7-15h-4.26zM150.354 28.09h11.31c.09-.51.15-1.02.15-1.59 0-4.41-3.15-7.92-7.59-7.92-4.71 0-7.92 3.45-7.92 7.92s3.18 7.92 8.22 7.92c2.88 0 5.13-1.17 6.54-3.21l-3.12-1.8c-.66.87-1.86 1.5-3.36 1.5-2.04 0-3.69-.84-4.23-2.82zm-.06-3c.45-1.92 1.86-3.03 3.93-3.03 1.62 0 3.24.87 3.72 3.03h-7.65zM164.516 34h3.87V12.1h-3.87V34zM185.248 34.36c3.69 0 6.9-2.01 6.9-6.3V13h-2.1v15.06c0 3.03-2.07 4.26-4.8 4.26-2.19 0-3.93-.78-4.62-2.61l-1.77 1.05c1.05 2.43 3.57 3.6 6.39 3.6zM203.124 18.64c-4.65 0-7.83 3.45-7.83 7.86 0 4.53 3.24 7.86 7.98 7.86 3.03 0 5.34-1.41 6.6-3.45l-1.74-1.02c-.81 1.44-2.46 2.55-4.83 2.55-3.18 0-5.55-1.89-5.97-4.95h13.17c.03-.3.06-.63.06-.93 0-4.11-2.85-7.92-7.44-7.92zm0 1.92c2.58 0 4.98 1.71 5.4 5.01h-11.19c.39-2.94 2.64-5.01 5.79-5.01zM221.224 20.92V19h-4.32v-4.2l-1.98.6V19h-3.15v1.92h3.15v9.09c0 3.6 2.25 4.59 6.3 3.99v-1.74c-2.91.12-4.32.33-4.32-2.25v-9.09h4.32zM225.176 22.93c0-1.62 1.59-2.37 3.15-2.37 1.44 0 2.97.57 3.6 2.1l1.65-.96c-.87-1.86-2.79-3.06-5.25-3.06-3 0-5.13 1.89-5.13 4.29 0 5.52 8.76 3.39 8.76 7.11 0 1.77-1.68 2.4-3.45 2.4-2.01 0-3.57-.99-4.11-2.52l-1.68.99c.75 1.92 2.79 3.45 5.79 3.45 3.21 0 5.43-1.77 5.43-4.32 0-5.52-8.76-3.39-8.76-7.11zM244.603 20.92V19h-4.32v-4.2l-1.98.6V19h-3.15v1.92h3.15v9.09c0 3.6 2.25 4.59 6.3 3.99v-1.74c-2.91.12-4.32.33-4.32-2.25v-9.09h4.32zM249.883 21.49V19h-1.98v15h1.98v-8.34c0-3.72 2.34-4.98 4.74-4.98v-1.92c-1.92 0-3.69.63-4.74 2.73zM263.358 18.64c-4.65 0-7.83 3.45-7.83 7.86 0 4.53 3.24 7.86 7.98 7.86 3.03 0 5.34-1.41 6.6-3.45l-1.74-1.02c-.81 1.44-2.46 2.55-4.83 2.55-3.18 0-5.55-1.89-5.97-4.95h13.17c.03-.3.06-.63.06-.93 0-4.11-2.85-7.92-7.44-7.92zm0 1.92c2.58 0 4.98 1.71 5.4 5.01h-11.19c.39-2.94 2.64-5.01 5.79-5.01zM286.848 19v2.94c-1.26-2.01-3.39-3.3-6.06-3.3-4.23 0-7.74 3.42-7.74 7.86s3.51 7.86 7.74 7.86c2.67 0 4.8-1.29 6.06-3.3V34h1.98V19h-1.98zm-5.91 13.44c-3.33 0-5.91-2.61-5.91-5.94 0-3.33 2.58-5.94 5.91-5.94s5.91 2.61 5.91 5.94c0 3.33-2.58 5.94-5.91 5.94zM309.01 18.64c-1.92 0-3.75.87-4.86 2.73-.84-1.74-2.46-2.73-4.56-2.73-1.8 0-3.42.72-4.59 2.55V19h-1.98v15H295v-8.31c0-3.72 2.16-5.13 4.32-5.13 2.13 0 3.51 1.41 3.51 4.08V34h1.98v-8.31c0-3.72 1.86-5.13 4.17-5.13 2.13 0 3.66 1.41 3.66 4.08V34h1.98v-9.36c0-3.75-2.31-6-5.61-6z" fill="#000"/>
|
||||||
|
<path d="M11.395 44.428C4.557 40.198 0 32.632 0 24 0 10.745 10.745 0 24 0a23.891 23.891 0 0113.997 4.502c-.2 17.907-11.097 33.245-26.602 39.926z" fill="#6875F5"/>
|
||||||
|
<path d="M14.134 45.885A23.914 23.914 0 0024 48c13.255 0 24-10.745 24-24 0-3.516-.756-6.856-2.115-9.866-4.659 15.143-16.608 27.092-31.75 31.751z" fill="#6875F5"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
4
resources/views/vendor/jetstream/components/application-mark.blade.php
vendored
Normal file
4
resources/views/vendor/jetstream/components/application-mark.blade.php
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||||
|
<path d="M11.395 44.428C4.557 40.198 0 32.632 0 24 0 10.745 10.745 0 24 0a23.891 23.891 0 0113.997 4.502c-.2 17.907-11.097 33.245-26.602 39.926z" fill="#6875F5"/>
|
||||||
|
<path d="M14.134 45.885A23.914 23.914 0 0024 48c13.255 0 24-10.745 24-24 0-3.516-.756-6.856-2.115-9.866-4.659 15.143-16.608 27.092-31.75 31.751z" fill="#6875F5"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 428 B |
6
resources/views/vendor/jetstream/components/authentication-card-logo.blade.php
vendored
Normal file
6
resources/views/vendor/jetstream/components/authentication-card-logo.blade.php
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<a href="/">
|
||||||
|
<svg class="w-16 h-16" viewbox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M11.395 44.428C4.557 40.198 0 32.632 0 24 0 10.745 10.745 0 24 0a23.891 23.891 0 0113.997 4.502c-.2 17.907-11.097 33.245-26.602 39.926z" fill="#6875F5"/>
|
||||||
|
<path d="M14.134 45.885A23.914 23.914 0 0024 48c13.255 0 24-10.745 24-24 0-3.516-.756-6.856-2.115-9.866-4.659 15.143-16.608 27.092-31.75 31.751z" fill="#6875F5"/>
|
||||||
|
</svg>
|
||||||
|
</a>
|
9
resources/views/vendor/jetstream/components/authentication-card.blade.php
vendored
Normal file
9
resources/views/vendor/jetstream/components/authentication-card.blade.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
|
||||||
|
<div>
|
||||||
|
{{ $logo }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
|
</div>
|
3
resources/views/vendor/jetstream/components/button.blade.php
vendored
Normal file
3
resources/views/vendor/jetstream/components/button.blade.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:shadow-outline-gray disabled:opacity-25 transition ease-in-out duration-150']) }}>
|
||||||
|
{{ $slot }}
|
||||||
|
</button>
|
27
resources/views/vendor/jetstream/components/confirmation-modal.blade.php
vendored
Normal file
27
resources/views/vendor/jetstream/components/confirmation-modal.blade.php
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
@props(['id' => null, 'maxWidth' => null])
|
||||||
|
|
||||||
|
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-red-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg class="h-6 w-6 text-red-600" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg">
|
||||||
|
{{ $title }}
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="mt-2">
|
||||||
|
{{ $content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-6 py-4 bg-gray-100 text-right">
|
||||||
|
{{ $footer }}
|
||||||
|
</div>
|
||||||
|
</x-jet-modal>
|
46
resources/views/vendor/jetstream/components/confirms-password.blade.php
vendored
Normal file
46
resources/views/vendor/jetstream/components/confirms-password.blade.php
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
@props(['title' => __('Confirm Password'), 'content' => __('For your security, please confirm your password to continue.'), 'button' => __('Confirm')])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$confirmableId = md5($attributes->wire('then'));
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<span
|
||||||
|
{{ $attributes->wire('then') }}
|
||||||
|
x-data
|
||||||
|
x-ref="span"
|
||||||
|
x-on:click="$wire.startConfirmingPassword('{{ $confirmableId }}')"
|
||||||
|
x-on:password-confirmed.window="setTimeout(() => $event.detail.id === '{{ $confirmableId }}' && $refs.span.dispatchEvent(new CustomEvent('then', { bubbles: false })), 250);"
|
||||||
|
>
|
||||||
|
{{ $slot }}
|
||||||
|
</span>
|
||||||
|
|
||||||
|
@once
|
||||||
|
<x-jet-dialog-modal wire:model="confirmingPassword">
|
||||||
|
<x-slot name="title">
|
||||||
|
{{ $title }}
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="content">
|
||||||
|
{{ $content }}
|
||||||
|
|
||||||
|
<div class="mt-4" x-data="{}" x-on:confirming-password.window="setTimeout(() => $refs.confirmable_password.focus(), 250)">
|
||||||
|
<x-jet-input type="password" class="mt-1 block w-3/4" placeholder="Password"
|
||||||
|
x-ref="confirmable_password"
|
||||||
|
wire:model.defer="confirmablePassword"
|
||||||
|
wire:keydown.enter="confirmPassword" />
|
||||||
|
|
||||||
|
<x-jet-input-error for="confirmable_password" class="mt-2" />
|
||||||
|
</div>
|
||||||
|
</x-slot>
|
||||||
|
|
||||||
|
<x-slot name="footer">
|
||||||
|
<x-jet-secondary-button wire:click="stopConfirmingPassword" wire:loading.attr="disabled">
|
||||||
|
Nevermind
|
||||||
|
</x-jet-secondary-button>
|
||||||
|
|
||||||
|
<x-jet-button class="ml-2" wire:click="confirmPassword" wire:loading.attr="disabled">
|
||||||
|
{{ $button }}
|
||||||
|
</x-jet-button>
|
||||||
|
</x-slot>
|
||||||
|
</x-jet-dialog-modal>
|
||||||
|
@endonce
|
3
resources/views/vendor/jetstream/components/danger-button.blade.php
vendored
Normal file
3
resources/views/vendor/jetstream/components/danger-button.blade.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center justify-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 focus:outline-none focus:border-red-700 focus:shadow-outline-red active:bg-red-600 transition ease-in-out duration-150']) }}>
|
||||||
|
{{ $slot }}
|
||||||
|
</button>
|
17
resources/views/vendor/jetstream/components/dialog-modal.blade.php
vendored
Normal file
17
resources/views/vendor/jetstream/components/dialog-modal.blade.php
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
@props(['id' => null, 'maxWidth' => null])
|
||||||
|
|
||||||
|
<x-jet-modal :id="$id" :maxWidth="$maxWidth" {{ $attributes }}>
|
||||||
|
<div class="px-6 py-4">
|
||||||
|
<div class="text-lg">
|
||||||
|
{{ $title }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-4">
|
||||||
|
{{ $content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="px-6 py-4 bg-gray-100 text-right">
|
||||||
|
{{ $footer }}
|
||||||
|
</div>
|
||||||
|
</x-jet-modal>
|
1
resources/views/vendor/jetstream/components/dropdown-link.blade.php
vendored
Normal file
1
resources/views/vendor/jetstream/components/dropdown-link.blade.php
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<a {{ $attributes->merge(['class' => 'block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>
|
43
resources/views/vendor/jetstream/components/dropdown.blade.php
vendored
Normal file
43
resources/views/vendor/jetstream/components/dropdown.blade.php
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white'])
|
||||||
|
|
||||||
|
@php
|
||||||
|
switch ($align) {
|
||||||
|
case 'left':
|
||||||
|
$alignmentClasses = 'origin-top-left left-0';
|
||||||
|
break;
|
||||||
|
case 'top':
|
||||||
|
$alignmentClasses = 'origin-top';
|
||||||
|
break;
|
||||||
|
case 'right':
|
||||||
|
default:
|
||||||
|
$alignmentClasses = 'origin-top-right right-0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($width) {
|
||||||
|
case '48':
|
||||||
|
$width = 'w-48';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div class="relative" x-data="{ open: false }" @click.away="open = false" @close.stop="open = false">
|
||||||
|
<div @click="open = ! open">
|
||||||
|
{{ $trigger }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div x-show="open"
|
||||||
|
x-transition:enter="transition ease-out duration-200"
|
||||||
|
x-transition:enter-start="transform opacity-0 scale-95"
|
||||||
|
x-transition:enter-end="transform opacity-100 scale-100"
|
||||||
|
x-transition:leave="transition ease-in duration-75"
|
||||||
|
x-transition:leave-start="transform opacity-100 scale-100"
|
||||||
|
x-transition:leave-end="transform opacity-0 scale-95"
|
||||||
|
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }}"
|
||||||
|
style="display: none;"
|
||||||
|
@click="open = false">
|
||||||
|
<div class="rounded-md shadow-xs {{ $contentClasses }}">
|
||||||
|
{{ $content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
26
resources/views/vendor/jetstream/components/form-section.blade.php
vendored
Normal file
26
resources/views/vendor/jetstream/components/form-section.blade.php
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
@props(['submit'])
|
||||||
|
|
||||||
|
<div {{ $attributes->merge(['class' => 'md:grid md:grid-cols-3 md:gap-6']) }}>
|
||||||
|
<x-jet-section-title>
|
||||||
|
<x-slot name="title">{{ $title }}</x-slot>
|
||||||
|
<x-slot name="description">{{ $description }}</x-slot>
|
||||||
|
</x-jet-section-title>
|
||||||
|
|
||||||
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||||
|
<form wire:submit.prevent="{{ $submit }}">
|
||||||
|
<div class="shadow overflow-hidden sm:rounded-md">
|
||||||
|
<div class="px-4 py-5 bg-white sm:p-6">
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
{{ $form }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@if (isset($actions))
|
||||||
|
<div class="flex items-center justify-end px-4 py-3 bg-gray-50 text-right sm:px-6">
|
||||||
|
{{ $actions }}
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
5
resources/views/vendor/jetstream/components/input-error.blade.php
vendored
Normal file
5
resources/views/vendor/jetstream/components/input-error.blade.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@props(['for'])
|
||||||
|
|
||||||
|
@error($for)
|
||||||
|
<p {{ $attributes->merge(['class' => 'text-sm text-red-600']) }}>{{ $message }}</p>
|
||||||
|
@enderror
|
3
resources/views/vendor/jetstream/components/input.blade.php
vendored
Normal file
3
resources/views/vendor/jetstream/components/input.blade.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
@props(['disabled' => false])
|
||||||
|
|
||||||
|
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'form-input rounded-md shadow-sm']) !!}>
|
5
resources/views/vendor/jetstream/components/label.blade.php
vendored
Normal file
5
resources/views/vendor/jetstream/components/label.blade.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@props(['value'])
|
||||||
|
|
||||||
|
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
|
||||||
|
{{ $value ?? $slot }}
|
||||||
|
</label>
|
50
resources/views/vendor/jetstream/components/modal.blade.php
vendored
Normal file
50
resources/views/vendor/jetstream/components/modal.blade.php
vendored
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
@props(['id', 'maxWidth'])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$id = $id ?? md5($attributes->wire('model'));
|
||||||
|
|
||||||
|
switch ($maxWidth ?? '2xl') {
|
||||||
|
case 'sm':
|
||||||
|
$maxWidth = 'sm:max-w-sm';
|
||||||
|
break;
|
||||||
|
case 'md':
|
||||||
|
$maxWidth = 'sm:max-w-md';
|
||||||
|
break;
|
||||||
|
case 'lg':
|
||||||
|
$maxWidth = 'sm:max-w-lg';
|
||||||
|
break;
|
||||||
|
case 'xl':
|
||||||
|
$maxWidth = 'sm:max-w-xl';
|
||||||
|
break;
|
||||||
|
case '2xl':
|
||||||
|
default:
|
||||||
|
$maxWidth = 'sm:max-w-2xl';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<div id="{{ $id }}" x-data="{ show: @entangle($attributes->wire('model')) }"
|
||||||
|
x-show="show"
|
||||||
|
x-on:close.stop="show = false"
|
||||||
|
x-on:keydown.escape.window="show = false"
|
||||||
|
class="fixed top-0 inset-x-0 px-4 pt-6 sm:px-0 sm:flex sm:items-top sm:justify-center"
|
||||||
|
style="display: none;">
|
||||||
|
<div x-show="show" class="fixed inset-0 transform transition-all" x-on:click="show = false" x-transition:enter="ease-out duration-300"
|
||||||
|
x-transition:enter-start="opacity-0"
|
||||||
|
x-transition:enter-end="opacity-100"
|
||||||
|
x-transition:leave="ease-in duration-200"
|
||||||
|
x-transition:leave-start="opacity-100"
|
||||||
|
x-transition:leave-end="opacity-0">
|
||||||
|
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div x-show="show" class="bg-white rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full {{ $maxWidth }}"
|
||||||
|
x-transition:enter="ease-out duration-300"
|
||||||
|
x-transition:enter-start="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
||||||
|
x-transition:enter-end="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
x-transition:leave="ease-in duration-200"
|
||||||
|
x-transition:leave-start="opacity-100 translate-y-0 sm:scale-100"
|
||||||
|
x-transition:leave-end="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
|
</div>
|
11
resources/views/vendor/jetstream/components/nav-link.blade.php
vendored
Normal file
11
resources/views/vendor/jetstream/components/nav-link.blade.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@props(['active'])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$classes = ($active ?? false)
|
||||||
|
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
|
||||||
|
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||||
|
{{ $slot }}
|
||||||
|
</a>
|
11
resources/views/vendor/jetstream/components/responsive-nav-link.blade.php
vendored
Normal file
11
resources/views/vendor/jetstream/components/responsive-nav-link.blade.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@props(['active'])
|
||||||
|
|
||||||
|
@php
|
||||||
|
$classes = ($active ?? false)
|
||||||
|
? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
|
||||||
|
: 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||||
|
{{ $slot }}
|
||||||
|
</a>
|
3
resources/views/vendor/jetstream/components/secondary-button.blade.php
vendored
Normal file
3
resources/views/vendor/jetstream/components/secondary-button.blade.php
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<button {{ $attributes->merge(['type' => 'button', 'class' => 'inline-flex items-center px-4 py-2 bg-white border border-gray-300 rounded-md font-semibold text-xs text-gray-700 uppercase tracking-widest shadow-sm hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150']) }}>
|
||||||
|
{{ $slot }}
|
||||||
|
</button>
|
5
resources/views/vendor/jetstream/components/section-border.blade.php
vendored
Normal file
5
resources/views/vendor/jetstream/components/section-border.blade.php
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<div class="hidden sm:block">
|
||||||
|
<div class="py-8">
|
||||||
|
<div class="border-t border-gray-200"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
9
resources/views/vendor/jetstream/components/section-title.blade.php
vendored
Normal file
9
resources/views/vendor/jetstream/components/section-title.blade.php
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<div class="md:col-span-1">
|
||||||
|
<div class="px-4 sm:px-0">
|
||||||
|
<h3 class="text-lg font-medium text-gray-900">{{ $title }}</h3>
|
||||||
|
|
||||||
|
<p class="mt-1 text-sm text-gray-600">
|
||||||
|
{{ $description }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
19
resources/views/vendor/jetstream/components/switchable-team.blade.php
vendored
Normal file
19
resources/views/vendor/jetstream/components/switchable-team.blade.php
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
@props(['team', 'component' => 'jet-dropdown-link'])
|
||||||
|
|
||||||
|
<form method="POST" action="/current-team">
|
||||||
|
@method('PUT')
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
<!-- Hidden Team ID -->
|
||||||
|
<input type="hidden" name="team_id" value="{{ $team->id }}">
|
||||||
|
|
||||||
|
<x-dynamic-component :component="$component" href="#" onclick="event.preventDefault(); this.closest('form').submit();">
|
||||||
|
<div class="flex items-center">
|
||||||
|
@if (Auth::user()->isCurrentTeam($team))
|
||||||
|
<svg class="mr-2 h-5 w-5 text-green-400" fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" stroke="currentColor" viewBox="0 0 24 24"><path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<div class="truncate">{{ $team->name }}</div>
|
||||||
|
</div>
|
||||||
|
</x-dynamic-component>
|
||||||
|
</form>
|
11
resources/views/vendor/jetstream/components/validation-errors.blade.php
vendored
Normal file
11
resources/views/vendor/jetstream/components/validation-errors.blade.php
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@if ($errors->any())
|
||||||
|
<div {{ $attributes }}>
|
||||||
|
<div class="font-medium text-red-600">Whoops! Something went wrong.</div>
|
||||||
|
|
||||||
|
<ul class="mt-3 list-disc list-inside text-sm text-red-600">
|
||||||
|
@foreach ($errors->all() as $error)
|
||||||
|
<li>{{ $error }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endif
|
28
routes/jetstream.php
Normal file
28
routes/jetstream.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
|
use Laravel\Jetstream\Http\Controllers\CurrentTeamController;
|
||||||
|
use Laravel\Jetstream\Http\Controllers\Livewire\ApiTokenController;
|
||||||
|
use Laravel\Jetstream\Http\Controllers\Livewire\TeamController;
|
||||||
|
use Laravel\Jetstream\Http\Controllers\Livewire\UserProfileController;
|
||||||
|
use Laravel\Jetstream\Jetstream;
|
||||||
|
|
||||||
|
Route::group(['middleware' => config('jetstream.middleware', ['web'])], function () {
|
||||||
|
Route::group(['middleware' => ['auth', 'verified']], function () {
|
||||||
|
// User & Profile...
|
||||||
|
Route::get('/user/profile', [UserProfileController::class, 'show'])
|
||||||
|
->name('profile.show');
|
||||||
|
|
||||||
|
// API...
|
||||||
|
if (Jetstream::hasApiFeatures()) {
|
||||||
|
Route::get('/user/api-tokens', [ApiTokenController::class, 'index'])->name('api-tokens.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Teams...
|
||||||
|
if (Jetstream::hasTeamFeatures()) {
|
||||||
|
Route::get('/teams/create', [TeamController::class, 'create'])->name('teams.create');
|
||||||
|
Route::get('/teams/{team}', [TeamController::class, 'show'])->name('teams.show');
|
||||||
|
Route::put('/current-team', [CurrentTeamController::class, 'update'])->name('current-team.update');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@@ -1,24 +1,21 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Route;
|
|
||||||
use App\Article;
|
use App\Article;
|
||||||
use App\Source;
|
use App\Source;
|
||||||
|
use App\Topic;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
use App\Http\Controllers\ArticlesController;
|
use App\Http\Controllers\ArticlesController;
|
||||||
use App\Http\Controllers\TopicsController;
|
use App\Http\Controllers\TopicsController;
|
||||||
use App\Http\Controllers\SourcesController;
|
use App\Http\Controllers\SourcesController;
|
||||||
use App\Http\Controllers\MylistController;
|
use App\Http\Controllers\MylistController;
|
||||||
use App\Topic;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
| Web Routes
|
| Web Routes
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
|
||||||
| Here is where you can register web routes for your application. These
|
|
||||||
| routes are loaded by the RouteServiceProvider within a group which
|
|
||||||
| contains the "web" middleware group. Now create something great!
|
|
||||||
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
Route::get('/', function () {
|
Route::get('/', function () {
|
||||||
@@ -51,9 +48,19 @@ Route::get('/about', function () {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::get('/ogimage', function (Request $request) {
|
|
||||||
|
|
||||||
$article = Article::findOrFail($request->query('id'));
|
Route::middleware(['auth:sanctum', 'verified'])->prefix('dashboard')->namespace('Admin')->group(function() {
|
||||||
|
|
||||||
return view('ogimage', ['article' => $article]);
|
Route::get('/', function () {
|
||||||
|
return view('admin.dashboard', [
|
||||||
|
'total_sources' => Source::count(),
|
||||||
|
'total_topics' => Topic::count(),
|
||||||
|
'total_articles' => Article::count()
|
||||||
|
]);
|
||||||
|
})->name('dashboard.index');
|
||||||
|
|
||||||
|
|
||||||
|
Route::get('/analytics', AnalyticsController::class)->name('dashboard.analytics');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
20
tailwind.config.js
vendored
20
tailwind.config.js
vendored
@@ -1,13 +1,25 @@
|
|||||||
|
const defaultTheme = require('tailwindcss/defaultTheme');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
purge: [
|
purge: [
|
||||||
|
'./storage/framework/views/*.php',
|
||||||
'./resources/views/**/*.blade.php',
|
'./resources/views/**/*.blade.php',
|
||||||
'./resources/css/**/*.css',
|
'./resources/css/**/*.css',
|
||||||
'./resources/js/**/*.vue',
|
'./resources/js/**/*.vue',
|
||||||
'./resources/js/**/*.js',
|
'./resources/js/**/*.js',
|
||||||
],
|
],
|
||||||
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['Nunito', ...defaultTheme.fontFamily.sans],
|
||||||
},
|
},
|
||||||
variants: {},
|
},
|
||||||
plugins: [],
|
},
|
||||||
}
|
|
||||||
|
variants: {
|
||||||
|
opacity: ['responsive', 'hover', 'focus', 'disabled'],
|
||||||
|
},
|
||||||
|
|
||||||
|
plugins: [require('@tailwindcss/ui')],
|
||||||
|
};
|
||||||
|
2
webpack.mix.js
vendored
2
webpack.mix.js
vendored
@@ -8,7 +8,7 @@ require('laravel-mix-purgecss');
|
|||||||
mix.js('resources/js/app.js', 'public/js')
|
mix.js('resources/js/app.js', 'public/js')
|
||||||
.extract();
|
.extract();
|
||||||
|
|
||||||
mix.sass('resources/sass/app.scss', 'public/css')
|
mix.postCss('resources/css/app.css', 'public/css')
|
||||||
.tailwind('./tailwind.config.js')
|
.tailwind('./tailwind.config.js')
|
||||||
.purgeCss({
|
.purgeCss({
|
||||||
enabled: mix.inProduction(),
|
enabled: mix.inProduction(),
|
||||||
|
Reference in New Issue
Block a user