mirror of
https://github.com/sp-tarkov/forge.git
synced 2025-02-13 04:30:41 -05:00
Merge branch 'develop'
This commit is contained in:
commit
e8f2562005
@ -43,9 +43,8 @@ DB_HUB_PASSWORD=
|
|||||||
DB_HUB_CHARSET=utf8mb4
|
DB_HUB_CHARSET=utf8mb4
|
||||||
DB_HUB_COLLATION=utf8mb4_0900_ai_ci
|
DB_HUB_COLLATION=utf8mb4_0900_ai_ci
|
||||||
|
|
||||||
SESSION_DRIVER=redis
|
SESSION_DRIVER=database
|
||||||
SESSION_STORE=redis
|
SESSION_CONNECTION=mysql
|
||||||
SESSION_CONNECTION=default
|
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
SESSION_ENCRYPT=false
|
SESSION_ENCRYPT=false
|
||||||
SESSION_PATH=/
|
SESSION_PATH=/
|
||||||
@ -82,8 +81,6 @@ MAIL_ENCRYPTION=null
|
|||||||
MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com"
|
MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com"
|
||||||
MAIL_FROM_NAME="${APP_NAME}"
|
MAIL_FROM_NAME="${APP_NAME}"
|
||||||
|
|
||||||
NOVA_LICENSE_KEY=
|
|
||||||
|
|
||||||
OCTANE_SERVER=frankenphp
|
OCTANE_SERVER=frankenphp
|
||||||
OCTANE_HTTPS=true
|
OCTANE_HTTPS=true
|
||||||
|
|
44
.env.light
Normal file
44
.env.light
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
APP_NAME="The Forge"
|
||||||
|
APP_ENV=local
|
||||||
|
|
||||||
|
# Generate a new key with: `php artisan key:generate`
|
||||||
|
APP_KEY=
|
||||||
|
|
||||||
|
APP_DEBUG=true
|
||||||
|
APP_TIMEZONE=UTC
|
||||||
|
APP_LOCALE=en
|
||||||
|
APP_FALLBACK_LOCALE=en
|
||||||
|
APP_FAKER_LOCALE=en_US
|
||||||
|
|
||||||
|
# Update to whatever you've configured your local web server to use.
|
||||||
|
APP_URL=http://forge.test
|
||||||
|
|
||||||
|
VITE_APP_NAME="${APP_NAME}"
|
||||||
|
|
||||||
|
# Much higher in production
|
||||||
|
BCRYPT_ROUNDS=4
|
||||||
|
|
||||||
|
LOG_CHANNEL=stack
|
||||||
|
LOG_STACK=single
|
||||||
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
|
# SQLite is being used here for simplicity, but will break functionality with
|
||||||
|
# the import job. Shouldn't matter for light development work. Must be absolute!
|
||||||
|
DB_CONNECTION=sqlite
|
||||||
|
DB_DATABASE=/Users/USER/Sites/forge/database/database.sqlite
|
||||||
|
|
||||||
|
FILESYSTEM_DISK=local
|
||||||
|
ASSET_URL="${APP_URL}/storage"
|
||||||
|
ASSET_URL_LIVEWIRE=/vendor/livewire/livewire.js
|
||||||
|
|
||||||
|
SESSION_DRIVER=file
|
||||||
|
BROADCAST_CONNECTION=log
|
||||||
|
CACHE_STORE=file
|
||||||
|
QUEUE_CONNECTION=sync
|
||||||
|
SCOUT_DRIVER=collection
|
||||||
|
|
||||||
|
# Mail will be written to the file log.
|
||||||
|
MAIL_MAILER=log
|
||||||
|
MAIL_FROM_ADDRESS="no-reply@sp-tarkov.com"
|
||||||
|
MAIL_FROM_NAME="${APP_NAME}"
|
24
.github/README.md
vendored
24
.github/README.md
vendored
@ -12,11 +12,7 @@ The Forge is a Laravel-based web application that provides a platform for the Si
|
|||||||
|
|
||||||
## Development Environment Setup
|
## Development Environment Setup
|
||||||
|
|
||||||
This is a [Laravel](https://laravel.com/docs/11.x) project that uses [Sail](https://laravel.com/docs/11.x/sail), which provides a Docker-based development environment. Ensure you review the Sail documentation for useage, particularly in a [Windows environment](https://laravel.com/docs/11.x/installation#sail-on-windows), as WSL2 is recommended.
|
We use [Laravel Sail](https://laravel.com/docs/11.x/sail) to mirror the services that are used in our production server in a local development environment. You can see detailed instructions on how to configure the [full development environment](https://github.com/sp-tarkov/forge/wiki/Full-Windows-Dev-Env) or a [lightweight development environment](https://github.com/sp-tarkov/forge/wiki/Light-Windows-Dev-Env) on the project wiki. The full development environment is recommended.
|
||||||
|
|
||||||
### Accessing the Application:
|
|
||||||
|
|
||||||
Once the Docker containers are running with Sail you can access the application at <https://localhost>.
|
|
||||||
|
|
||||||
### Available Services:
|
### Available Services:
|
||||||
|
|
||||||
@ -31,15 +27,13 @@ Once the Docker containers are running with Sail you can access the application
|
|||||||
|
|
||||||
| Service | Authentication | Access Via Host |
|
| Service | Authentication | Access Via Host |
|
||||||
|----------------------------------|----------------|-----------------------------|
|
|----------------------------------|----------------|-----------------------------|
|
||||||
| Administration Panel (Nova*) | Via User Role | <https://localhost/nova> |
|
| Laravel Filament Admin Panel | Via User Role | <https://localhost/admin> |
|
||||||
| Redis Queue Management (Horizon) | Via User Role | <https://localhost/horizon> |
|
| Redis Queue Management (Horizon) | Via User Role | <https://localhost/horizon> |
|
||||||
| Website Status (Pulse) | Via User Role | <https://localhost/pulse> |
|
| Website Status (Pulse) | Via User Role | <https://localhost/pulse> |
|
||||||
| Meilisearch WebUI | Local Only | <http://localhost:7700> |
|
| Meilisearch WebUI | Local Only | <http://localhost:7700> |
|
||||||
| Mailpit WebUI | Local Only | <http://localhost:8025> |
|
| Mailpit WebUI | Local Only | <http://localhost:8025> |
|
||||||
|
|
||||||
<sup>*Nova may be replaced shortly due to License issues.</sup>
|
Most of these connection settings should already be configured in the `.env.full` or `.env.light` example files. Simply save one of these (depending on your environment) as `.env` and adjust settings as needed.
|
||||||
|
|
||||||
Most of these connection settings should already be configured in the `.env.example` file. Simply save the `.env.example` file as `.env` and adjust further settings as needed.
|
|
||||||
|
|
||||||
### Basic Usage Examples
|
### Basic Usage Examples
|
||||||
|
|
||||||
@ -47,32 +41,32 @@ Here are some basic commands to get started with Forge:
|
|||||||
|
|
||||||
```
|
```
|
||||||
# Start the Docker containers in detached mode:
|
# Start the Docker containers in detached mode:
|
||||||
./vendor/bin/sail up -d
|
sail up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
# View all of the available Artisan commands:
|
# View all of the available Artisan commands:
|
||||||
./vendor/bin/sail artisan
|
sail artisan
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
# Migrate and seed the database with test data:
|
# Migrate and seed the database with test data:
|
||||||
./vendor/bin/sail artisan migrate:fresh –seed
|
sail artisan migrate:fresh –seed
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
# Run Laravel Horizon (the queue workers/monitor):
|
# Run Laravel Horizon (the queue workers/monitor):
|
||||||
./vendor/bin/sail artisan horizon
|
sail artisan horizon
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
# Install NPM dependencies from within the container:
|
# Install NPM dependencies from within the container:
|
||||||
./vendor/bin/sail npm install
|
sail npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
```
|
||||||
# Start the development server:
|
# Start the development server:
|
||||||
./vendor/bin/sail npm run dev
|
sail npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
### More Information
|
### More Information
|
||||||
|
22
.github/workflows/quality.yaml
vendored
22
.github/workflows/quality.yaml
vendored
@ -22,12 +22,6 @@ jobs:
|
|||||||
php-version: '8.3'
|
php-version: '8.3'
|
||||||
extensions: mbstring, dom, fileinfo
|
extensions: mbstring, dom, fileinfo
|
||||||
coverage: none
|
coverage: none
|
||||||
- name: Configure Laravel Nova Authentication
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
NOVA_USERNAME: ${{ secrets.NOVA_USERNAME }}
|
|
||||||
NOVA_LICENSE_KEY: ${{ secrets.NOVA_LICENSE_KEY }}
|
|
||||||
run: composer config http-basic.nova.laravel.com "$NOVA_USERNAME" "$NOVA_LICENSE_KEY"
|
|
||||||
- name: Get Composer Cache Directory
|
- name: Get Composer Cache Directory
|
||||||
id: composer-cache
|
id: composer-cache
|
||||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||||
@ -43,10 +37,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
||||||
php artisan key:generate
|
php artisan key:generate
|
||||||
php artisan config:cache
|
php artisan optimize
|
||||||
php artisan route:cache
|
|
||||||
- name: Clear Laravel Config
|
|
||||||
run: php artisan config:clear
|
|
||||||
- name: Execute Code Static Analysis with Larastan
|
- name: Execute Code Static Analysis with Larastan
|
||||||
run: ./vendor/bin/phpstan analyse -c ./phpstan.neon --no-progress --error-format=github
|
run: ./vendor/bin/phpstan analyse -c ./phpstan.neon --no-progress --error-format=github
|
||||||
|
|
||||||
@ -63,12 +54,6 @@ jobs:
|
|||||||
php-version: '8.3'
|
php-version: '8.3'
|
||||||
extensions: mbstring, dom, fileinfo
|
extensions: mbstring, dom, fileinfo
|
||||||
coverage: none
|
coverage: none
|
||||||
- name: Configure Laravel Nova Authentication
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
NOVA_USERNAME: ${{ secrets.NOVA_USERNAME }}
|
|
||||||
NOVA_LICENSE_KEY: ${{ secrets.NOVA_LICENSE_KEY }}
|
|
||||||
run: composer config http-basic.nova.laravel.com "$NOVA_USERNAME" "$NOVA_LICENSE_KEY"
|
|
||||||
- name: Get Composer Cache Directory
|
- name: Get Composer Cache Directory
|
||||||
id: composer-cache
|
id: composer-cache
|
||||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||||
@ -84,10 +69,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
||||||
php artisan key:generate
|
php artisan key:generate
|
||||||
php artisan config:cache
|
php artisan optimize
|
||||||
php artisan route:cache
|
|
||||||
- name: Clear Laravel Config
|
|
||||||
run: php artisan config:clear
|
|
||||||
- name: Run Pint Code Style Fixer
|
- name: Run Pint Code Style Fixer
|
||||||
run: ./vendor/bin/pint
|
run: ./vendor/bin/pint
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||||
|
9
.github/workflows/tests.yaml
vendored
9
.github/workflows/tests.yaml
vendored
@ -25,12 +25,6 @@ jobs:
|
|||||||
php-version: '8.3'
|
php-version: '8.3'
|
||||||
extensions: mbstring, dom, fileinfo
|
extensions: mbstring, dom, fileinfo
|
||||||
coverage: none
|
coverage: none
|
||||||
- name: Configure Laravel Nova Authentication
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
NOVA_USERNAME: ${{ secrets.NOVA_USERNAME }}
|
|
||||||
NOVA_LICENSE_KEY: ${{ secrets.NOVA_LICENSE_KEY }}
|
|
||||||
run: composer config http-basic.nova.laravel.com "$NOVA_USERNAME" "$NOVA_LICENSE_KEY"
|
|
||||||
- name: Get Composer Cache Directory
|
- name: Get Composer Cache Directory
|
||||||
id: composer-cache
|
id: composer-cache
|
||||||
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||||
@ -59,8 +53,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
php -r "file_exists('.env') || copy('.env.ci', '.env');"
|
||||||
php artisan key:generate
|
php artisan key:generate
|
||||||
php artisan config:cache
|
php artisan optimize
|
||||||
php artisan route:cache
|
|
||||||
- name: Run Database Migrations
|
- name: Run Database Migrations
|
||||||
run: php artisan migrate
|
run: php artisan migrate
|
||||||
- name: Link Storage
|
- name: Link Storage
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -22,3 +22,4 @@ Homestead.json
|
|||||||
Homestead.yaml
|
Homestead.yaml
|
||||||
npm-debug.log
|
npm-debug.log
|
||||||
yarn-error.log
|
yarn-error.log
|
||||||
|
config/psysh
|
||||||
|
91
app/Filament/Resources/UserResource.php
Normal file
91
app/Filament/Resources/UserResource.php
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources;
|
||||||
|
|
||||||
|
use App\Filament\Resources\UserResource\Pages;
|
||||||
|
use App\Models\User;
|
||||||
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Form;
|
||||||
|
use Filament\Resources\Resource;
|
||||||
|
use Filament\Tables;
|
||||||
|
use Filament\Tables\Table;
|
||||||
|
|
||||||
|
class UserResource extends Resource
|
||||||
|
{
|
||||||
|
protected static ?string $model = User::class;
|
||||||
|
|
||||||
|
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||||
|
|
||||||
|
public static function form(Form $form): Form
|
||||||
|
{
|
||||||
|
return $form
|
||||||
|
->schema([
|
||||||
|
Forms\Components\TextInput::make('name')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\TextInput::make('email')
|
||||||
|
->email()
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\DateTimePicker::make('email_verified_at'),
|
||||||
|
Forms\Components\TextInput::make('password')
|
||||||
|
->password()
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\TextInput::make('user_role_id')
|
||||||
|
->numeric(),
|
||||||
|
Forms\Components\TextInput::make('profile_photo_path')
|
||||||
|
->maxLength(2048),
|
||||||
|
Forms\Components\DateTimePicker::make('created_at'),
|
||||||
|
Forms\Components\DateTimePicker::make('updated_at'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function table(Table $table): Table
|
||||||
|
{
|
||||||
|
return $table
|
||||||
|
->columns([
|
||||||
|
Tables\Columns\TextColumn::make('name')
|
||||||
|
->searchable(),
|
||||||
|
Tables\Columns\TextColumn::make('email')
|
||||||
|
->searchable(),
|
||||||
|
Tables\Columns\TextColumn::make('role.name')
|
||||||
|
->sortable(),
|
||||||
|
Tables\Columns\TextColumn::make('email_verified_at')
|
||||||
|
->dateTime()
|
||||||
|
->sortable()
|
||||||
|
->toggleable(isToggledHiddenByDefault: true),
|
||||||
|
Tables\Columns\TextColumn::make('created_at')
|
||||||
|
->dateTime()
|
||||||
|
->sortable()
|
||||||
|
->toggleable(isToggledHiddenByDefault: true),
|
||||||
|
])
|
||||||
|
->filters([
|
||||||
|
//
|
||||||
|
])
|
||||||
|
->actions([
|
||||||
|
Tables\Actions\EditAction::make(),
|
||||||
|
])
|
||||||
|
->bulkActions([
|
||||||
|
Tables\Actions\BulkActionGroup::make([
|
||||||
|
Tables\Actions\DeleteBulkAction::make(),
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getRelations(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getPages(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'index' => Pages\ListUsers::route('/'),
|
||||||
|
'create' => Pages\CreateUser::route('/create'),
|
||||||
|
'edit' => Pages\EditUser::route('/{record}/edit'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
11
app/Filament/Resources/UserResource/Pages/CreateUser.php
Normal file
11
app/Filament/Resources/UserResource/Pages/CreateUser.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\UserResource\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\UserResource;
|
||||||
|
use Filament\Resources\Pages\CreateRecord;
|
||||||
|
|
||||||
|
class CreateUser extends CreateRecord
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
}
|
19
app/Filament/Resources/UserResource/Pages/EditUser.php
Normal file
19
app/Filament/Resources/UserResource/Pages/EditUser.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\UserResource\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\UserResource;
|
||||||
|
use Filament\Actions;
|
||||||
|
use Filament\Resources\Pages\EditRecord;
|
||||||
|
|
||||||
|
class EditUser extends EditRecord
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Actions\DeleteAction::make(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
19
app/Filament/Resources/UserResource/Pages/ListUsers.php
Normal file
19
app/Filament/Resources/UserResource/Pages/ListUsers.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Filament\Resources\UserResource\Pages;
|
||||||
|
|
||||||
|
use App\Filament\Resources\UserResource;
|
||||||
|
use Filament\Actions;
|
||||||
|
use Filament\Resources\Pages\ListRecords;
|
||||||
|
|
||||||
|
class ListUsers extends ListRecords
|
||||||
|
{
|
||||||
|
protected static string $resource = UserResource::class;
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Actions\CreateAction::make(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
49
app/Http/Controllers/Api/AuthController.php
Normal file
49
app/Http/Controllers/Api/AuthController.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Api\LoginUserRequest;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Traits\ApiResponses;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
|
class AuthController extends Controller
|
||||||
|
{
|
||||||
|
use ApiResponses;
|
||||||
|
|
||||||
|
public function login(LoginUserRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$request->validated($request->all());
|
||||||
|
|
||||||
|
if (! Auth::attempt($request->only('email', 'password'))) {
|
||||||
|
return $this->error(__('Invalid credentials'), 401);
|
||||||
|
}
|
||||||
|
|
||||||
|
$user = User::firstWhere('email', $request->email);
|
||||||
|
$tokenName = $request->token_name ?? __('Dynamic API Token');
|
||||||
|
|
||||||
|
return $this->success(__('Authenticated'), [
|
||||||
|
// Only allowing the 'read' scope to be dynamically created. Can revisit later when writes are possible.
|
||||||
|
'token' => $user->createToken($tokenName, ['read'])->plainTextToken,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
/** @var \Laravel\Sanctum\PersonalAccessToken $token */
|
||||||
|
$token = $request->user()->currentAccessToken();
|
||||||
|
$token->delete();
|
||||||
|
|
||||||
|
return $this->success(__('Revoked API token'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logoutAll(Request $request): JsonResponse
|
||||||
|
{
|
||||||
|
$request->user()->tokens()->delete();
|
||||||
|
|
||||||
|
return $this->success(__('Revoked all API tokens'));
|
||||||
|
}
|
||||||
|
}
|
52
app/Http/Controllers/Api/V0/ModController.php
Normal file
52
app/Http/Controllers/Api/V0/ModController.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\V0;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Api\V0\StoreModRequest;
|
||||||
|
use App\Http\Requests\Api\V0\UpdateModRequest;
|
||||||
|
use App\Http\Resources\Api\V0\ModResource;
|
||||||
|
use App\Models\Mod;
|
||||||
|
|
||||||
|
class ModController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return ModResource::collection(Mod::paginate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(StoreModRequest $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(Mod $mod)
|
||||||
|
{
|
||||||
|
return new ModResource($mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(UpdateModRequest $request, Mod $mod)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(Mod $mod)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
52
app/Http/Controllers/Api/V0/UsersController.php
Normal file
52
app/Http/Controllers/Api/V0/UsersController.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api\V0;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Api\V0\StoreUserRequest;
|
||||||
|
use App\Http\Requests\Api\V0\UpdateUserRequest;
|
||||||
|
use App\Http\Resources\Api\V0\UserResource;
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class UsersController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return UserResource::collection(User::paginate());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*/
|
||||||
|
public function store(StoreUserRequest $request)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the specified resource.
|
||||||
|
*/
|
||||||
|
public function show(User $user)
|
||||||
|
{
|
||||||
|
return new UserResource($user);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*/
|
||||||
|
public function update(UpdateUserRequest $request, User $user)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*/
|
||||||
|
public function destroy(User $user)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
28
app/Http/Requests/Api/LoginUserRequest.php
Normal file
28
app/Http/Requests/Api/LoginUserRequest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class LoginUserRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => ['required', 'string', 'email'],
|
||||||
|
'password' => ['required', 'string'],
|
||||||
|
'token_name' => ['sometimes'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
26
app/Http/Requests/Api/V0/StoreModRequest.php
Normal file
26
app/Http/Requests/Api/V0/StoreModRequest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api\V0;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreModRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
26
app/Http/Requests/Api/V0/StoreUserRequest.php
Normal file
26
app/Http/Requests/Api/V0/StoreUserRequest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api\V0;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StoreUserRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
26
app/Http/Requests/Api/V0/UpdateModRequest.php
Normal file
26
app/Http/Requests/Api/V0/UpdateModRequest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api\V0;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateModRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
26
app/Http/Requests/Api/V0/UpdateUserRequest.php
Normal file
26
app/Http/Requests/Api/V0/UpdateUserRequest.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Api\V0;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class UpdateUserRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*/
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
//
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
61
app/Http/Resources/Api/V0/ModResource.php
Normal file
61
app/Http/Resources/Api/V0/ModResource.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Api\V0;
|
||||||
|
|
||||||
|
use App\Models\Mod;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
/** @mixin Mod */
|
||||||
|
class ModResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => 'mod',
|
||||||
|
'id' => $this->id,
|
||||||
|
'attributes' => [
|
||||||
|
'name' => $this->name,
|
||||||
|
'slug' => $this->slug,
|
||||||
|
'description' => $this->when(
|
||||||
|
$request->routeIs('api.v0.mods.show'),
|
||||||
|
$this->description
|
||||||
|
),
|
||||||
|
'source_code_link' => $this->source_code_link,
|
||||||
|
'user_id' => $this->user_id,
|
||||||
|
'license_id' => $this->license_id,
|
||||||
|
'created_at' => $this->created_at,
|
||||||
|
],
|
||||||
|
'relationships' => [
|
||||||
|
'user' => [
|
||||||
|
'data' => [
|
||||||
|
'type' => 'user',
|
||||||
|
'id' => $this->user_id,
|
||||||
|
],
|
||||||
|
// TODO: Provide 'links.self' to user profile:
|
||||||
|
//'links' => ['self' => '#'],
|
||||||
|
],
|
||||||
|
'license' => [
|
||||||
|
'data' => [
|
||||||
|
'type' => 'license',
|
||||||
|
'id' => $this->license_id,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'included' => [
|
||||||
|
new UserResource($this->user),
|
||||||
|
// TODO: Provide 'included' data for attached 'license':
|
||||||
|
//new LicenseResource($this->license),
|
||||||
|
],
|
||||||
|
'links' => [
|
||||||
|
'self' => route('mod.show', [
|
||||||
|
'mod' => $this->id,
|
||||||
|
'slug' => $this->slug,
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
40
app/Http/Resources/Api/V0/UserResource.php
Normal file
40
app/Http/Resources/Api/V0/UserResource.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources\Api\V0;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
|
||||||
|
/** @mixin User */
|
||||||
|
class UserResource extends JsonResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => 'user',
|
||||||
|
'id' => $this->id,
|
||||||
|
'attributes' => [
|
||||||
|
'name' => $this->name,
|
||||||
|
'user_role_id' => $this->user_role_id,
|
||||||
|
'created_at' => $this->created_at,
|
||||||
|
],
|
||||||
|
'relationships' => [
|
||||||
|
'user_role' => [
|
||||||
|
'data' => [
|
||||||
|
'type' => 'user_role',
|
||||||
|
'id' => $this->user_role_id,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
// TODO: Provide 'included' data for attached 'user_role'
|
||||||
|
//'included' => [new UserRoleResource($this->role)],
|
||||||
|
|
||||||
|
// TODO: Provide 'links.self' to user profile:
|
||||||
|
//'links' => ['self' => '#'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -3,19 +3,74 @@
|
|||||||
namespace App\Livewire;
|
namespace App\Livewire;
|
||||||
|
|
||||||
use App\Models\Mod;
|
use App\Models\Mod;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class GlobalSearch extends Component
|
class GlobalSearch extends Component
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The search query.
|
||||||
|
*/
|
||||||
public string $query = '';
|
public string $query = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the search result dropdown.
|
||||||
|
*/
|
||||||
|
public bool $showDropdown = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to show the "no results found" message.
|
||||||
|
*/
|
||||||
|
public bool $noResults = false;
|
||||||
|
|
||||||
public function render(): View
|
public function render(): View
|
||||||
{
|
{
|
||||||
$results = $this->query ? Mod::search($this->query)->get() : collect();
|
|
||||||
|
|
||||||
return view('livewire.global-search', [
|
return view('livewire.global-search', [
|
||||||
'results' => $results,
|
'results' => $this->executeSearch($this->query),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the search against each of the searchable models.
|
||||||
|
*/
|
||||||
|
protected function executeSearch(string $query): array
|
||||||
|
{
|
||||||
|
$query = Str::trim($query);
|
||||||
|
$results = ['data' => [], 'total' => 0];
|
||||||
|
|
||||||
|
if (Str::length($query)) {
|
||||||
|
$results['data'] = [
|
||||||
|
'user' => User::search($query)->get(),
|
||||||
|
'mod' => Mod::search($query)->get(),
|
||||||
|
];
|
||||||
|
$results['total'] = $this->countTotalResults($results['data']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->showDropdown = Str::length($query) > 0;
|
||||||
|
$this->noResults = $results['total'] === 0 && $this->showDropdown;
|
||||||
|
|
||||||
|
return $results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Count the total number of results across all models.
|
||||||
|
*/
|
||||||
|
protected function countTotalResults($results): int
|
||||||
|
{
|
||||||
|
return collect($results)->reduce(function ($carry, $result) {
|
||||||
|
return $carry + $result->count();
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the search query and hide the dropdown.
|
||||||
|
*/
|
||||||
|
public function clearSearch(): void
|
||||||
|
{
|
||||||
|
$this->query = '';
|
||||||
|
$this->showDropdown = false;
|
||||||
|
$this->noResults = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Laravel\Scout\Searchable;
|
use Laravel\Scout\Searchable;
|
||||||
|
|
||||||
@ -31,17 +32,10 @@ class Mod extends Model
|
|||||||
|
|
||||||
protected static function booted(): void
|
protected static function booted(): void
|
||||||
{
|
{
|
||||||
|
// Apply the global scope to exclude disabled mods.
|
||||||
static::addGlobalScope(new DisabledScope);
|
static::addGlobalScope(new DisabledScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function slug(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn (string $value) => strtolower($value),
|
|
||||||
set: fn (string $value) => Str::slug($value),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user(): BelongsTo
|
public function user(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
@ -57,6 +51,9 @@ class Mod extends Model
|
|||||||
return $this->hasMany(ModVersion::class);
|
return $this->hasMany(ModVersion::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scope a query to include the total number of downloads for a mod.
|
||||||
|
*/
|
||||||
public function scopeWithTotalDownloads($query)
|
public function scopeWithTotalDownloads($query)
|
||||||
{
|
{
|
||||||
return $query->addSelect(['total_downloads' => ModVersion::selectRaw('SUM(downloads) AS total_downloads')
|
return $query->addSelect(['total_downloads' => ModVersion::selectRaw('SUM(downloads) AS total_downloads')
|
||||||
@ -110,6 +107,9 @@ class Mod extends Model
|
|||||||
->with(['lastUpdatedVersion', 'lastUpdatedVersion.sptVersion']);
|
->with(['lastUpdatedVersion', 'lastUpdatedVersion.sptVersion']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the indexable data array for the model.
|
||||||
|
*/
|
||||||
public function toSearchableArray(): array
|
public function toSearchableArray(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@ -124,8 +124,45 @@ class Mod extends Model
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the model should be searchable.
|
||||||
|
*/
|
||||||
public function shouldBeSearchable(): bool
|
public function shouldBeSearchable(): bool
|
||||||
{
|
{
|
||||||
return ! $this->disabled;
|
return ! $this->disabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the URL to the thumbnail.
|
||||||
|
*/
|
||||||
|
public function thumbnailUrl(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::get(function (): string {
|
||||||
|
return $this->thumbnail
|
||||||
|
? Storage::disk($this->thumbnailDisk())->url($this->thumbnail)
|
||||||
|
: '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the disk where the thumbnail is stored.
|
||||||
|
*/
|
||||||
|
protected function thumbnailDisk(): string
|
||||||
|
{
|
||||||
|
return match (config('app.env')) {
|
||||||
|
'production' => 'r2', // Cloudflare R2 Storage
|
||||||
|
default => 'public', // Local
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the slug is always lower case when retrieved and slugified when saved.
|
||||||
|
*/
|
||||||
|
protected function slug(): Attribute
|
||||||
|
{
|
||||||
|
return Attribute::make(
|
||||||
|
get: fn (string $value) => Str::lower($value),
|
||||||
|
set: fn (string $value) => Str::slug($value),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,14 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||||||
return $this->belongsTo(UserRole::class, 'user_role_id');
|
return $this->belongsTo(UserRole::class, 'user_role_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isMod(): bool
|
||||||
|
{
|
||||||
|
return Str::lower($this->role?->name) === 'moderator';
|
||||||
|
}
|
||||||
|
|
||||||
public function isAdmin(): bool
|
public function isAdmin(): bool
|
||||||
{
|
{
|
||||||
return Str::lower($this->role->name) === 'administrator';
|
return Str::lower($this->role?->name) === 'administrator';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
@ -84,4 +89,15 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the disk that profile photos should be stored on.
|
||||||
|
*/
|
||||||
|
protected function profilePhotoDisk(): string
|
||||||
|
{
|
||||||
|
return match (config('app.env')) {
|
||||||
|
'production' => 'r2', // Cloudflare R2 Storage
|
||||||
|
default => 'public', // Local
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova\Dashboards;
|
|
||||||
|
|
||||||
use Laravel\Nova\Cards\Help;
|
|
||||||
use Laravel\Nova\Dashboards\Main as Dashboard;
|
|
||||||
|
|
||||||
class Main extends Dashboard
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Get the cards for the dashboard.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function cards()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
new Help,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Nova\Fields\HasMany;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
|
|
||||||
class License extends Resource
|
|
||||||
{
|
|
||||||
public static $model = \App\Models\License::class;
|
|
||||||
|
|
||||||
public static $title = 'name';
|
|
||||||
|
|
||||||
public static $search = [
|
|
||||||
'id', 'name', 'link',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function fields(Request $request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Text::make('Name')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Link')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
HasMany::make('Mods'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cards(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filters(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lenses(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function actions(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Nova\Fields\BelongsTo;
|
|
||||||
use Laravel\Nova\Fields\Boolean;
|
|
||||||
use Laravel\Nova\Fields\HasMany;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
|
|
||||||
class Mod extends Resource
|
|
||||||
{
|
|
||||||
public static $model = \App\Models\Mod::class;
|
|
||||||
|
|
||||||
public static $title = 'name';
|
|
||||||
|
|
||||||
public static $search = [
|
|
||||||
'id', 'name', 'slug', 'description', 'source_code_link',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function fields(Request $request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Text::make('Name')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Slug')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Description')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Source Code Link')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Boolean::make('Contains AI Content')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
BelongsTo::make('User', 'user', User::class),
|
|
||||||
|
|
||||||
BelongsTo::make('License', 'license', License::class),
|
|
||||||
|
|
||||||
HasMany::make('Versions', 'versions', ModVersion::class),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cards(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filters(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lenses(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function actions(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Nova\Fields\BelongsTo;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Number;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
|
|
||||||
class ModVersion extends Resource
|
|
||||||
{
|
|
||||||
public static $model = \App\Models\ModVersion::class;
|
|
||||||
|
|
||||||
public static $title = 'id';
|
|
||||||
|
|
||||||
public static $search = [
|
|
||||||
'id', 'version', 'description', 'virus_total_link',
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function label(): string
|
|
||||||
{
|
|
||||||
return 'Mod Versions';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fields(Request $request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Text::make('Version')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Description')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Virus Total Link')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Number::make('Downloads')
|
|
||||||
->sortable()
|
|
||||||
->rules('required', 'integer'),
|
|
||||||
|
|
||||||
BelongsTo::make('Mod', 'mod', Mod::class),
|
|
||||||
|
|
||||||
BelongsTo::make('SptVersion', 'spt_version', SptVersion::class),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cards(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filters(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lenses(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function actions(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
|
||||||
use Laravel\Nova\Resource as NovaResource;
|
|
||||||
|
|
||||||
abstract class Resource extends NovaResource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Build an "index" query for the given resource.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
|
||||||
*/
|
|
||||||
public static function indexQuery(NovaRequest $request, $query)
|
|
||||||
{
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a Scout search query for the given resource.
|
|
||||||
*
|
|
||||||
* @param \Laravel\Scout\Builder $query
|
|
||||||
* @return \Laravel\Scout\Builder
|
|
||||||
*/
|
|
||||||
public static function scoutQuery(NovaRequest $request, $query)
|
|
||||||
{
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a "detail" query for the given resource.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
|
||||||
*/
|
|
||||||
public static function detailQuery(NovaRequest $request, $query)
|
|
||||||
{
|
|
||||||
return parent::detailQuery($request, $query);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a "relatable" query for the given resource.
|
|
||||||
*
|
|
||||||
* This query determines which instances of the model may be attached to other resources.
|
|
||||||
*
|
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
|
||||||
*/
|
|
||||||
public static function relatableQuery(NovaRequest $request, $query)
|
|
||||||
{
|
|
||||||
return parent::relatableQuery($request, $query);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
|
|
||||||
class SptVersion extends Resource
|
|
||||||
{
|
|
||||||
public static $model = \App\Models\SptVersion::class;
|
|
||||||
|
|
||||||
public static $title = 'id';
|
|
||||||
|
|
||||||
public static $search = [
|
|
||||||
'id', 'version', 'color_class',
|
|
||||||
];
|
|
||||||
|
|
||||||
public static function label(): string
|
|
||||||
{
|
|
||||||
return 'SPT Versions';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function fields(Request $request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Text::make('Version')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Color Class')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cards(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filters(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lenses(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function actions(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use Illuminate\Validation\Rules;
|
|
||||||
use Laravel\Nova\Fields\Gravatar;
|
|
||||||
use Laravel\Nova\Fields\HasMany;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Password;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
use Laravel\Nova\Http\Requests\NovaRequest;
|
|
||||||
|
|
||||||
class User extends Resource
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* The model the resource corresponds to.
|
|
||||||
*/
|
|
||||||
public static $model = \App\Models\User::class;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The single value that should be used to represent the resource when being displayed.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public static $title = 'name';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The columns that should be searched.
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
public static $search = [
|
|
||||||
'id', 'name', 'email',
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the fields displayed by the resource.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function fields(NovaRequest $request)
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Gravatar::make()->maxWidth(50),
|
|
||||||
|
|
||||||
Text::make('Name')
|
|
||||||
->sortable()
|
|
||||||
->rules('required', 'max:255'),
|
|
||||||
|
|
||||||
Text::make('Email')
|
|
||||||
->sortable()
|
|
||||||
->rules('required', 'email', 'max:254')
|
|
||||||
->creationRules('unique:users,email')
|
|
||||||
->updateRules('unique:users,email,{{resourceId}}'),
|
|
||||||
|
|
||||||
Password::make('Password')
|
|
||||||
->onlyOnForms()
|
|
||||||
->creationRules('required', Rules\Password::defaults())
|
|
||||||
->updateRules('nullable', Rules\Password::defaults()),
|
|
||||||
|
|
||||||
HasMany::make('Mods', 'mods', Mod::class),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the cards available for the request.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function cards(NovaRequest $request)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the filters available for the resource.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function filters(NovaRequest $request)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the lenses available for the resource.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function lenses(NovaRequest $request)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the actions available for the resource.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function actions(NovaRequest $request)
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Nova;
|
|
||||||
|
|
||||||
use App\Models\UserRole;
|
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Laravel\Nova\Fields\ID;
|
|
||||||
use Laravel\Nova\Fields\Text;
|
|
||||||
|
|
||||||
class UserRoleResource extends Resource
|
|
||||||
{
|
|
||||||
public static string $model = UserRole::class;
|
|
||||||
|
|
||||||
public static $title = 'name';
|
|
||||||
|
|
||||||
public static $search = [
|
|
||||||
'id', 'name', 'description',
|
|
||||||
];
|
|
||||||
|
|
||||||
public function fields(Request $request): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
ID::make()->sortable(),
|
|
||||||
|
|
||||||
Text::make('Name')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
|
|
||||||
Text::make('Description')
|
|
||||||
->sortable()
|
|
||||||
->rules('required'),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function cards(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filters(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function lenses(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function actions(Request $request): array
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
58
app/Providers/Filament/AdminPanelProvider.php
Normal file
58
app/Providers/Filament/AdminPanelProvider.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Providers\Filament;
|
||||||
|
|
||||||
|
use Filament\Http\Middleware\Authenticate;
|
||||||
|
use Filament\Http\Middleware\DisableBladeIconComponents;
|
||||||
|
use Filament\Http\Middleware\DispatchServingFilamentEvent;
|
||||||
|
use Filament\Pages;
|
||||||
|
use Filament\Panel;
|
||||||
|
use Filament\PanelProvider;
|
||||||
|
use Filament\Support\Colors\Color;
|
||||||
|
use Filament\Widgets;
|
||||||
|
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||||
|
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||||
|
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||||
|
use Illuminate\Routing\Middleware\SubstituteBindings;
|
||||||
|
use Illuminate\Session\Middleware\AuthenticateSession;
|
||||||
|
use Illuminate\Session\Middleware\StartSession;
|
||||||
|
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||||
|
|
||||||
|
class AdminPanelProvider extends PanelProvider
|
||||||
|
{
|
||||||
|
public function panel(Panel $panel): Panel
|
||||||
|
{
|
||||||
|
return $panel
|
||||||
|
->default()
|
||||||
|
->id('admin')
|
||||||
|
->path('admin')
|
||||||
|
->login()
|
||||||
|
->colors([
|
||||||
|
'primary' => Color::Blue,
|
||||||
|
])
|
||||||
|
->discoverResources(in: app_path('Filament/Resources'), for: 'App\\Filament\\Resources')
|
||||||
|
->discoverPages(in: app_path('Filament/Pages'), for: 'App\\Filament\\Pages')
|
||||||
|
->pages([
|
||||||
|
Pages\Dashboard::class,
|
||||||
|
])
|
||||||
|
->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets')
|
||||||
|
->widgets([
|
||||||
|
Widgets\AccountWidget::class,
|
||||||
|
Widgets\FilamentInfoWidget::class,
|
||||||
|
])
|
||||||
|
->middleware([
|
||||||
|
EncryptCookies::class,
|
||||||
|
AddQueuedCookiesToResponse::class,
|
||||||
|
StartSession::class,
|
||||||
|
AuthenticateSession::class,
|
||||||
|
ShareErrorsFromSession::class,
|
||||||
|
VerifyCsrfToken::class,
|
||||||
|
SubstituteBindings::class,
|
||||||
|
DisableBladeIconComponents::class,
|
||||||
|
DispatchServingFilamentEvent::class,
|
||||||
|
])
|
||||||
|
->authMiddleware([
|
||||||
|
Authenticate::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Providers;
|
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Gate;
|
|
||||||
use Laravel\Nova\Nova;
|
|
||||||
use Laravel\Nova\NovaApplicationServiceProvider;
|
|
||||||
|
|
||||||
class NovaServiceProvider extends NovaApplicationServiceProvider
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Bootstrap any application services.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function boot()
|
|
||||||
{
|
|
||||||
parent::boot();
|
|
||||||
|
|
||||||
Nova::withBreadcrumbs();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the tools that should be listed in the Nova sidebar.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
public function tools()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the Nova routes.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function routes()
|
|
||||||
{
|
|
||||||
Nova::routes()
|
|
||||||
->withAuthenticationRoutes()
|
|
||||||
->withPasswordResetRoutes()
|
|
||||||
->register();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register any application services.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function register()
|
|
||||||
{
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register the Nova gate.
|
|
||||||
*
|
|
||||||
* This gate determines who can access Nova in non-local environments.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
protected function gate()
|
|
||||||
{
|
|
||||||
Gate::define('viewNova', function ($user) {
|
|
||||||
return $user->isAdmin();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the dashboards that should be listed in the Nova sidebar.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
protected function dashboards()
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
new \App\Nova\Dashboards\Main,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
26
app/Traits/ApiResponses.php
Normal file
26
app/Traits/ApiResponses.php
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Traits;
|
||||||
|
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
|
trait ApiResponses
|
||||||
|
{
|
||||||
|
protected function success(string $message, ?array $data = []): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->baseResponse(message: $message, data: $data, code: 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function baseResponse(?string $message = '', ?array $data = [], ?int $code = 200): JsonResponse
|
||||||
|
{
|
||||||
|
return response()->json([
|
||||||
|
'message' => $message,
|
||||||
|
'data' => $data,
|
||||||
|
], $code);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function error(string $message, int $code): JsonResponse
|
||||||
|
{
|
||||||
|
return $this->baseResponse(message: $message, code: $code);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
use Illuminate\Foundation\Application;
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Foundation\Configuration\Exceptions;
|
use Illuminate\Foundation\Configuration\Exceptions;
|
||||||
use Illuminate\Foundation\Configuration\Middleware;
|
use Illuminate\Foundation\Configuration\Middleware;
|
||||||
|
use Illuminate\Support\Facades\Route;
|
||||||
use Mchev\Banhammer\Middleware\IPBanned;
|
use Mchev\Banhammer\Middleware\IPBanned;
|
||||||
|
|
||||||
return Application::configure(basePath: dirname(__DIR__))
|
return Application::configure(basePath: dirname(__DIR__))
|
||||||
@ -11,6 +12,12 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||||||
api: __DIR__.'/../routes/api.php',
|
api: __DIR__.'/../routes/api.php',
|
||||||
commands: __DIR__.'/../routes/console.php',
|
commands: __DIR__.'/../routes/console.php',
|
||||||
health: '/up',
|
health: '/up',
|
||||||
|
then: function () {
|
||||||
|
Route::middleware('api')
|
||||||
|
->prefix('api/v0')
|
||||||
|
->name('api.v0.')
|
||||||
|
->group(base_path('routes/api_v0.php'));
|
||||||
|
},
|
||||||
)
|
)
|
||||||
->withMiddleware(function (Middleware $middleware) {
|
->withMiddleware(function (Middleware $middleware) {
|
||||||
$middleware->append(IPBanned::class);
|
$middleware->append(IPBanned::class);
|
||||||
|
@ -5,5 +5,5 @@ return [
|
|||||||
App\Providers\FortifyServiceProvider::class,
|
App\Providers\FortifyServiceProvider::class,
|
||||||
App\Providers\HorizonServiceProvider::class,
|
App\Providers\HorizonServiceProvider::class,
|
||||||
App\Providers\JetstreamServiceProvider::class,
|
App\Providers\JetstreamServiceProvider::class,
|
||||||
App\Providers\NovaServiceProvider::class,
|
App\Providers\Filament\AdminPanelProvider::class,
|
||||||
];
|
];
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
"php": "^8.3",
|
"php": "^8.3",
|
||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"aws/aws-sdk-php": "^3.314",
|
"aws/aws-sdk-php": "^3.314",
|
||||||
|
"filament/filament": "^3.2",
|
||||||
"http-interop/http-factory-guzzle": "^1.2",
|
"http-interop/http-factory-guzzle": "^1.2",
|
||||||
"laravel/framework": "^11.11",
|
"laravel/framework": "^11.11",
|
||||||
"laravel/horizon": "^5.24",
|
"laravel/horizon": "^5.24",
|
||||||
"laravel/jetstream": "^5.1",
|
"laravel/jetstream": "^5.1",
|
||||||
"laravel/nova": "^4.34",
|
|
||||||
"laravel/octane": "^2.4",
|
"laravel/octane": "^2.4",
|
||||||
"laravel/pulse": "^1.2",
|
"laravel/pulse": "^1.2",
|
||||||
"laravel/sanctum": "^4.0",
|
"laravel/sanctum": "^4.0",
|
||||||
@ -49,9 +49,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"phpstan": [
|
||||||
|
"./vendor/bin/phpstan analyse --debug --memory-limit=2G"
|
||||||
|
],
|
||||||
"post-autoload-dump": [
|
"post-autoload-dump": [
|
||||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||||
"@php artisan package:discover --ansi"
|
"@php artisan package:discover --ansi",
|
||||||
|
"@php artisan filament:upgrade"
|
||||||
],
|
],
|
||||||
"post-update-cmd": [
|
"post-update-cmd": [
|
||||||
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
|
"@php artisan vendor:publish --tag=laravel-assets --ansi --force",
|
||||||
@ -66,12 +70,6 @@
|
|||||||
"@php artisan migrate --graceful --ansi"
|
"@php artisan migrate --graceful --ansi"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"repositories": [
|
|
||||||
{
|
|
||||||
"type": "composer",
|
|
||||||
"url": "https://nova.laravel.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"extra": {
|
"extra": {
|
||||||
"laravel": {
|
"laravel": {
|
||||||
"dont-discover": []
|
"dont-discover": []
|
||||||
|
2541
composer.lock
generated
2541
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -41,7 +41,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use' => 'default',
|
'use' => 'queue',
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -114,7 +114,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'inject_assets' => false,
|
'inject_assets' => true,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|---------------------------------------------------------------------------
|
|---------------------------------------------------------------------------
|
||||||
@ -157,16 +157,4 @@ return [
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
'pagination_theme' => 'tailwind',
|
'pagination_theme' => 'tailwind',
|
||||||
|
|
||||||
/*
|
|
||||||
|---------------------------------------------------------------------------
|
|
||||||
| Asset URL
|
|
||||||
|---------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| When serving assets from a CDN, you may need to override the asset URL
|
|
||||||
| that Livewire uses to include assets in the response.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'asset_url' => env('ASSET_URL_LIVEWIRE'),
|
|
||||||
];
|
];
|
||||||
|
206
config/nova.php
206
config/nova.php
@ -1,206 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Laravel\Nova\Actions\ActionResource;
|
|
||||||
use Laravel\Nova\Http\Middleware\Authenticate;
|
|
||||||
use Laravel\Nova\Http\Middleware\Authorize;
|
|
||||||
use Laravel\Nova\Http\Middleware\BootTools;
|
|
||||||
use Laravel\Nova\Http\Middleware\DispatchServingNovaEvent;
|
|
||||||
use Laravel\Nova\Http\Middleware\HandleInertiaRequests;
|
|
||||||
|
|
||||||
return [
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova License Key
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| The following configuration option contains your Nova license key. On
|
|
||||||
| non-local domains, Nova will verify that the Nova installation has
|
|
||||||
| a valid license associated with the application's active domain.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'license_key' => env('NOVA_LICENSE_KEY'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova App Name
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This value is the name of your application. This value is used when the
|
|
||||||
| framework needs to display the name of the application within the UI
|
|
||||||
| or in other locations. Of course, you're free to change the value.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'name' => env('NOVA_APP_NAME', env('APP_NAME')),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Domain Name
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This value is the "domain name" associated with your application. This
|
|
||||||
| can be used to prevent Nova's internal routes from being registered
|
|
||||||
| on subdomains which do not need access to your admin application.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'domain' => env('NOVA_DOMAIN_NAME', null),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Path
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This is the URI path where Nova will be accessible from. Feel free to
|
|
||||||
| change this path to anything you like. Note that this URI will not
|
|
||||||
| affect Nova's internal API routes which aren't exposed to users.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'path' => '/nova',
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Authentication Guard
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option defines the authentication guard that will
|
|
||||||
| be used to protect your Nova routes. This option should match one
|
|
||||||
| of the authentication guards defined in the "auth" config file.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'guard' => env('NOVA_GUARD', null),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Password Reset Broker
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option defines the password broker that will be
|
|
||||||
| used when passwords are reset. This option should mirror one of
|
|
||||||
| the password reset options defined in the "auth" config file.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'passwords' => env('NOVA_PASSWORDS', null),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Route Middleware
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| These middleware will be assigned to every Nova route, giving you the
|
|
||||||
| chance to add your own middleware to this stack or override any of
|
|
||||||
| the existing middleware. Or, you can just stick with this stack.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'middleware' => [
|
|
||||||
'web',
|
|
||||||
HandleInertiaRequests::class,
|
|
||||||
DispatchServingNovaEvent::class,
|
|
||||||
BootTools::class,
|
|
||||||
],
|
|
||||||
|
|
||||||
'api_middleware' => [
|
|
||||||
'nova',
|
|
||||||
Authenticate::class,
|
|
||||||
Authorize::class,
|
|
||||||
],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Pagination Type
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This option defines the visual style used in Nova's resource pagination
|
|
||||||
| views. You may select between "simple", "load-more", and "links" for
|
|
||||||
| your applications. Feel free to adjust this option to your choice.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'pagination' => 'simple',
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Storage Disk
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option allows you to define the default disk that
|
|
||||||
| will be used to store files using the Image, File, and other file
|
|
||||||
| related field types. You're welcome to use any configured disk.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'storage_disk' => env('NOVA_STORAGE_DISK', 'public'),
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Currency
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option allows you to define the default currency
|
|
||||||
| used by the Currency field within Nova. You may change this to a
|
|
||||||
| valid ISO 4217 currency code to suit your application's needs.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'currency' => 'USD',
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Branding
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| These configuration values allow you to customize the branding of the
|
|
||||||
| Nova interface, including the primary color and the logo that will
|
|
||||||
| be displayed within the Nova interface. This logo value must be
|
|
||||||
| the absolute path to an SVG logo within the local filesystem.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
// 'brand' => [
|
|
||||||
// 'logo' => resource_path('/img/example-logo.svg'),
|
|
||||||
|
|
||||||
// 'colors' => [
|
|
||||||
// "400" => "24, 182, 155, 0.5",
|
|
||||||
// "500" => "24, 182, 155",
|
|
||||||
// "600" => "24, 182, 155, 0.75",
|
|
||||||
// ]
|
|
||||||
// ],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Action Resource Class
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option allows you to specify a custom resource class
|
|
||||||
| to use for action log entries instead of the default that ships with
|
|
||||||
| Nova, thus allowing for the addition of additional UI form fields.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'actions' => [
|
|
||||||
'resource' => ActionResource::class,
|
|
||||||
],
|
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Nova Impersonation Redirection URLs
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| This configuration option allows you to specify a URL where Nova should
|
|
||||||
| redirect an administrator after impersonating another user and a URL
|
|
||||||
| to redirect the administrator after stopping impersonating a user.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
'impersonation' => [
|
|
||||||
'started' => '/',
|
|
||||||
'stopped' => '/',
|
|
||||||
],
|
|
||||||
|
|
||||||
];
|
|
@ -180,9 +180,11 @@ return [
|
|||||||
'bootstrap',
|
'bootstrap',
|
||||||
'config/**/*.php',
|
'config/**/*.php',
|
||||||
'database/**/*.php',
|
'database/**/*.php',
|
||||||
|
'lang/**/*.php',
|
||||||
'public/**/*.php',
|
'public/**/*.php',
|
||||||
'resources/**/*.php',
|
'resources/**/*.php',
|
||||||
'routes',
|
'routes',
|
||||||
|
'tests/**/*.php',
|
||||||
'composer.lock',
|
'composer.lock',
|
||||||
'.env',
|
'.env',
|
||||||
],
|
],
|
||||||
|
@ -13,7 +13,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'default' => env('QUEUE_CONNECTION', 'database'),
|
'default' => env('QUEUE_CONNECTION', 'redis'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -19,7 +19,7 @@ return [
|
|||||||
|
|
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'driver' => env('SCOUT_DRIVER', 'algolia'),
|
'driver' => env('SCOUT_DRIVER', 'meilisearch'),
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
@ -137,9 +137,13 @@ return [
|
|||||||
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
|
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
|
||||||
'key' => env('MEILISEARCH_KEY'),
|
'key' => env('MEILISEARCH_KEY'),
|
||||||
'index-settings' => [
|
'index-settings' => [
|
||||||
|
User::class => [
|
||||||
|
'filterableAttributes' => [],
|
||||||
|
'sortableAttributes' => [],
|
||||||
|
],
|
||||||
Mod::class => [
|
Mod::class => [
|
||||||
'filterableAttributes' => ['featured'],
|
'filterableAttributes' => [],
|
||||||
'sortableAttributes' => ['created_at', 'updated_at'],
|
'sortableAttributes' => [],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -13,8 +13,8 @@ class LicenseFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->name(),
|
'name' => fake()->name(),
|
||||||
'link' => $this->faker->url,
|
'link' => fake()->url(),
|
||||||
'created_at' => Carbon::now(),
|
'created_at' => Carbon::now(),
|
||||||
'updated_at' => Carbon::now(),
|
'updated_at' => Carbon::now(),
|
||||||
];
|
];
|
||||||
|
@ -7,27 +7,31 @@ use App\Models\Mod;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Random\RandomException;
|
||||||
|
|
||||||
class ModFactory extends Factory
|
class ModFactory extends Factory
|
||||||
{
|
{
|
||||||
protected $model = Mod::class;
|
protected $model = Mod::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RandomException
|
||||||
|
*/
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
$name = $this->faker->words(3, true);
|
$name = fake()->catchPhrase();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'user_id' => User::factory(),
|
'user_id' => User::factory(),
|
||||||
'name' => $name,
|
'name' => $name,
|
||||||
'slug' => Str::slug($name),
|
'slug' => Str::slug($name),
|
||||||
'teaser' => $this->faker->sentence,
|
'teaser' => fake()->sentence(),
|
||||||
'description' => $this->faker->sentences(6, true),
|
'description' => fake()->paragraphs(random_int(4, 20), true),
|
||||||
'license_id' => License::factory(),
|
'license_id' => License::factory(),
|
||||||
'source_code_link' => $this->faker->url(),
|
'source_code_link' => fake()->url(),
|
||||||
'featured' => $this->faker->boolean,
|
'featured' => fake()->boolean(),
|
||||||
'contains_ai_content' => $this->faker->boolean,
|
'contains_ai_content' => fake()->boolean(),
|
||||||
'contains_ads' => $this->faker->boolean,
|
'contains_ads' => fake()->boolean(),
|
||||||
'disabled' => $this->faker->boolean,
|
'disabled' => fake()->boolean(),
|
||||||
'created_at' => now(),
|
'created_at' => now(),
|
||||||
'updated_at' => now(),
|
'updated_at' => now(),
|
||||||
];
|
];
|
||||||
|
@ -16,13 +16,13 @@ class ModVersionFactory extends Factory
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'mod_id' => Mod::factory(),
|
'mod_id' => Mod::factory(),
|
||||||
'version' => $this->faker->numerify('1.#.#'),
|
'version' => fake()->numerify('1.#.#'),
|
||||||
'description' => $this->faker->text(),
|
'description' => fake()->text(),
|
||||||
'link' => $this->faker->url(),
|
'link' => fake()->url(),
|
||||||
'spt_version_id' => SptVersion::factory(),
|
'spt_version_id' => SptVersion::factory(),
|
||||||
'virus_total_link' => $this->faker->url(),
|
'virus_total_link' => fake()->url(),
|
||||||
'downloads' => $this->faker->randomNumber(),
|
'downloads' => fake()->randomNumber(),
|
||||||
'disabled' => $this->faker->boolean,
|
'disabled' => fake()->boolean(),
|
||||||
'created_at' => Carbon::now(),
|
'created_at' => Carbon::now(),
|
||||||
'updated_at' => Carbon::now(),
|
'updated_at' => Carbon::now(),
|
||||||
];
|
];
|
||||||
|
@ -19,7 +19,7 @@ class UserFactory extends Factory
|
|||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => fake()->name(),
|
'name' => fake()->userName(),
|
||||||
'email' => fake()->unique()->safeEmail(),
|
'email' => fake()->unique()->safeEmail(),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'password' => static::$password ??= Hash::make('password'),
|
'password' => static::$password ??= Hash::make('password'),
|
||||||
|
@ -14,12 +14,20 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('users', function (Blueprint $table) {
|
Schema::create('users', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->bigInteger('hub_id')->nullable()->default(null)->unique();
|
$table->bigInteger('hub_id')
|
||||||
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->unique();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('email')->unique();
|
$table->string('email')->unique();
|
||||||
$table->timestamp('email_verified_at')->nullable();
|
$table->timestamp('email_verified_at')->nullable();
|
||||||
$table->string('password');
|
$table->string('password');
|
||||||
$table->foreignIdFor(UserRole::class)->nullable()->default(null)->constrained('user_roles');
|
$table->foreignIdFor(UserRole::class)
|
||||||
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->constrained('user_roles')
|
||||||
|
->nullOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
$table->rememberToken();
|
$table->rememberToken();
|
||||||
$table->string('profile_photo_path', 2048)->nullable();
|
$table->string('profile_photo_path', 2048)->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::create('cache', function (Blueprint $table) {
|
|
||||||
$table->string('key')->primary();
|
|
||||||
$table->mediumText('value');
|
|
||||||
$table->integer('expiration');
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::create('cache_locks', function (Blueprint $table) {
|
|
||||||
$table->string('key')->primary();
|
|
||||||
$table->string('owner');
|
|
||||||
$table->integer('expiration');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('cache');
|
|
||||||
Schema::dropIfExists('cache_locks');
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,57 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::create('jobs', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('queue')->index();
|
|
||||||
$table->longText('payload');
|
|
||||||
$table->unsignedTinyInteger('attempts');
|
|
||||||
$table->unsignedInteger('reserved_at')->nullable();
|
|
||||||
$table->unsignedInteger('available_at');
|
|
||||||
$table->unsignedInteger('created_at');
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::create('job_batches', function (Blueprint $table) {
|
|
||||||
$table->string('id')->primary();
|
|
||||||
$table->string('name');
|
|
||||||
$table->integer('total_jobs');
|
|
||||||
$table->integer('pending_jobs');
|
|
||||||
$table->integer('failed_jobs');
|
|
||||||
$table->longText('failed_job_ids');
|
|
||||||
$table->mediumText('options')->nullable();
|
|
||||||
$table->integer('cancelled_at')->nullable();
|
|
||||||
$table->integer('created_at');
|
|
||||||
$table->integer('finished_at')->nullable();
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::create('failed_jobs', function (Blueprint $table) {
|
|
||||||
$table->id();
|
|
||||||
$table->string('uuid')->unique();
|
|
||||||
$table->text('connection');
|
|
||||||
$table->text('queue');
|
|
||||||
$table->longText('payload');
|
|
||||||
$table->longText('exception');
|
|
||||||
$table->timestamp('failed_at')->useCurrent();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::dropIfExists('jobs');
|
|
||||||
Schema::dropIfExists('job_batches');
|
|
||||||
Schema::dropIfExists('failed_jobs');
|
|
||||||
}
|
|
||||||
};
|
|
@ -12,14 +12,25 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('mods', function (Blueprint $table) {
|
Schema::create('mods', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->bigInteger('hub_id')->nullable()->default(null)->unique();
|
$table->bigInteger('hub_id')
|
||||||
$table->foreignIdFor(User::class)->constrained('users');
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->unique();
|
||||||
|
$table->foreignIdFor(User::class)
|
||||||
|
->constrained('users')
|
||||||
|
->cascadeOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
$table->string('name');
|
$table->string('name');
|
||||||
$table->string('slug');
|
$table->string('slug');
|
||||||
$table->string('teaser');
|
$table->string('teaser');
|
||||||
$table->longText('description');
|
$table->longText('description');
|
||||||
$table->string('thumbnail')->default('');
|
$table->string('thumbnail')->default('');
|
||||||
$table->foreignIdFor(License::class)->nullable()->default(null)->constrained('licenses');
|
$table->foreignIdFor(License::class)
|
||||||
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->constrained('licenses')
|
||||||
|
->nullOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
$table->string('source_code_link');
|
$table->string('source_code_link');
|
||||||
$table->boolean('featured')->default(false);
|
$table->boolean('featured')->default(false);
|
||||||
$table->boolean('contains_ai_content')->default(false);
|
$table->boolean('contains_ai_content')->default(false);
|
||||||
@ -27,6 +38,8 @@ return new class extends Migration
|
|||||||
$table->boolean('disabled')->default(false);
|
$table->boolean('disabled')->default(false);
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['deleted_at', 'disabled'], 'mods_show_index');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,11 +10,16 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('spt_versions', function (Blueprint $table) {
|
Schema::create('spt_versions', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->bigInteger('hub_id')->nullable()->default(null)->unique();
|
$table->bigInteger('hub_id')
|
||||||
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->unique();
|
||||||
$table->string('version');
|
$table->string('version');
|
||||||
$table->string('color_class');
|
$table->string('color_class');
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['version', 'deleted_at'], 'spt_versions_filtering_index');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,17 +12,30 @@ return new class extends Migration
|
|||||||
{
|
{
|
||||||
Schema::create('mod_versions', function (Blueprint $table) {
|
Schema::create('mod_versions', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->bigInteger('hub_id')->nullable()->default(null)->unique();
|
$table->bigInteger('hub_id')
|
||||||
$table->foreignIdFor(Mod::class)->constrained('mods');
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->unique();
|
||||||
|
$table->foreignIdFor(Mod::class)
|
||||||
|
->constrained('mods')
|
||||||
|
->cascadeOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
$table->string('version');
|
$table->string('version');
|
||||||
$table->longText('description');
|
$table->longText('description');
|
||||||
$table->string('link');
|
$table->string('link');
|
||||||
$table->foreignIdFor(SptVersion::class)->constrained('spt_versions');
|
$table->foreignIdFor(SptVersion::class)
|
||||||
|
->nullable()
|
||||||
|
->default(null)
|
||||||
|
->constrained('spt_versions')
|
||||||
|
->nullOnDelete()
|
||||||
|
->cascadeOnUpdate();
|
||||||
$table->string('virus_total_link');
|
$table->string('virus_total_link');
|
||||||
$table->unsignedBigInteger('downloads');
|
$table->unsignedBigInteger('downloads');
|
||||||
$table->boolean('disabled')->default(false);
|
$table->boolean('disabled')->default(false);
|
||||||
$table->softDeletes();
|
$table->softDeletes();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
|
||||||
|
$table->index(['mod_id', 'deleted_at', 'disabled', 'version'], 'mod_versions_filtering_index');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
return new class extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*/
|
|
||||||
public function up(): void
|
|
||||||
{
|
|
||||||
Schema::table('mods', function (Blueprint $table) {
|
|
||||||
$table->index(['deleted_at', 'disabled'], 'mods_show_index');
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('mod_versions', function (Blueprint $table) {
|
|
||||||
$table->index(['mod_id', 'deleted_at', 'disabled', 'version'], 'mod_versions_filtering_index');
|
|
||||||
});
|
|
||||||
|
|
||||||
Schema::table('spt_versions', function (Blueprint $table) {
|
|
||||||
$table->index(['version', 'deleted_at'], 'spt_versions_filtering_index');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reverse the migrations.
|
|
||||||
*/
|
|
||||||
public function down(): void
|
|
||||||
{
|
|
||||||
Schema::table('mods', function (Blueprint $table) {
|
|
||||||
$table->dropIndex('mods_show_index');
|
|
||||||
$table->dropIndex('mod_versions_filtering_index');
|
|
||||||
$table->dropIndex('spt_versions_filtering_index');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
@ -25,7 +25,10 @@ class DatabaseSeeder extends Seeder
|
|||||||
|
|
||||||
// Add 5 administrators.
|
// Add 5 administrators.
|
||||||
$administrator = UserRole::factory()->administrator()->create();
|
$administrator = UserRole::factory()->administrator()->create();
|
||||||
User::factory(5)->for($administrator, 'role')->create();
|
User::factory()->for($administrator, 'role')->create([
|
||||||
|
'email' => 'test@example.com',
|
||||||
|
]);
|
||||||
|
User::factory(4)->for($administrator, 'role')->create();
|
||||||
|
|
||||||
// Add 10 moderators.
|
// Add 10 moderators.
|
||||||
$moderator = UserRole::factory()->moderator()->create();
|
$moderator = UserRole::factory()->moderator()->create();
|
||||||
|
@ -19,7 +19,7 @@ services:
|
|||||||
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
|
XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
|
||||||
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
|
XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
|
||||||
IGNITION_LOCAL_SITES_PATH: '${PWD}'
|
IGNITION_LOCAL_SITES_PATH: '${PWD}'
|
||||||
SUPERVISOR_PHP_COMMAND: "/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan octane:start --host=localhost --port=443 --admin-port=2019 --https"
|
SUPERVISOR_PHP_COMMAND: "/usr/bin/php -d variables_order=EGPCS /var/www/html/artisan octane:start --host=localhost --port=443 --admin-port=2019 --https --watch"
|
||||||
XDG_CONFIG_HOME: /var/www/html/config
|
XDG_CONFIG_HOME: /var/www/html/config
|
||||||
XDG_DATA_HOME: /var/www/html/data
|
XDG_DATA_HOME: /var/www/html/data
|
||||||
volumes:
|
volumes:
|
||||||
|
135
package-lock.json
generated
135
package-lock.json
generated
@ -4,11 +4,15 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"@alpinejs/focus": "^3.14.1"
|
||||||
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"axios": "^1.6.4",
|
"axios": "^1.6.4",
|
||||||
|
"chokidar": "^3.6.0",
|
||||||
"laravel-vite-plugin": "^1.0",
|
"laravel-vite-plugin": "^1.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.32",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
@ -30,6 +34,16 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@alpinejs/focus": {
|
||||||
|
"version": "3.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.14.1.tgz",
|
||||||
|
"integrity": "sha512-z4xdpK6X1LB2VitsWbL61tmABoOORuEhE5v2tnUX/be6/nAygXyeDxZ1x9s1u+bOEYlIOXXLmjdmTlhchUVWxw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"focus-trap": "^6.9.4",
|
||||||
|
"tabbable": "^5.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@esbuild/aix-ppc64": {
|
"node_modules/@esbuild/aix-ppc64": {
|
||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
|
||||||
@ -999,9 +1013,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/caniuse-lite": {
|
"node_modules/caniuse-lite": {
|
||||||
"version": "1.0.30001636",
|
"version": "1.0.30001640",
|
||||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001636.tgz",
|
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz",
|
||||||
"integrity": "sha512-bMg2vmr8XBsbL6Lr0UHXy/21m84FTxDLWn2FSqMd5PrlbMxwJlQnC2YWYxVgp66PZE+BBNF2jYQUBKCo1FDeZg==",
|
"integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1044,19 +1058,6 @@
|
|||||||
"fsevents": "~2.3.2"
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chokidar/node_modules/glob-parent": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"is-glob": "^4.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/color-convert": {
|
"node_modules/color-convert": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
@ -1160,9 +1161,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.4.807",
|
"version": "1.4.816",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.807.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz",
|
||||||
"integrity": "sha512-kSmJl2ZwhNf/bcIuCH/imtNOKlpkLDn2jqT5FJ+/0CXjhnFaOa9cOe9gHKKy71eM49izwuQjZhKk+lWQ1JxB7A==",
|
"integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
@ -1239,19 +1240,6 @@
|
|||||||
"node": ">=8.6.0"
|
"node": ">=8.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/fast-glob/node_modules/glob-parent": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "ISC",
|
|
||||||
"dependencies": {
|
|
||||||
"is-glob": "^4.0.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
@ -1275,6 +1263,15 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/focus-trap": {
|
||||||
|
"version": "6.9.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-6.9.4.tgz",
|
||||||
|
"integrity": "sha512-v2NTsZe2FF59Y+sDykKY+XjqZ0cPfhq/hikWVL88BqLivnNiEffAsac6rP6H45ff9wG9LL5ToiDqrLEP9GX9mw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"tabbable": "^5.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/follow-redirects": {
|
"node_modules/follow-redirects": {
|
||||||
"version": "1.15.6",
|
"version": "1.15.6",
|
||||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
|
||||||
@ -1392,16 +1389,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/glob-parent": {
|
"node_modules/glob-parent": {
|
||||||
"version": "6.0.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-glob": "^4.0.3"
|
"is-glob": "^4.0.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.13.0"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/hasown": {
|
"node_modules/hasown": {
|
||||||
@ -1431,13 +1428,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/is-core-module": {
|
"node_modules/is-core-module": {
|
||||||
"version": "2.13.1",
|
"version": "2.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz",
|
||||||
"integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
|
"integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"hasown": "^2.0.0"
|
"hasown": "^2.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.4"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
@ -1581,9 +1581,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/lru-cache": {
|
"node_modules/lru-cache": {
|
||||||
"version": "10.2.2",
|
"version": "10.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.3.0.tgz",
|
||||||
"integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
|
"integrity": "sha512-CQl19J/g+Hbjbv4Y3mFNNXFEL/5t/KCg8POCuUqd4rMKjGG+j1ybER83hxV58zL+dFI1PTkt3GNFSHRt+d8qEQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -1648,9 +1648,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/minimatch": {
|
"node_modules/minimatch": {
|
||||||
"version": "9.0.4",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
"integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==",
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -1833,9 +1833,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.38",
|
"version": "8.4.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.39.tgz",
|
||||||
"integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
|
"integrity": "sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -1854,7 +1854,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.7",
|
"nanoid": "^3.3.7",
|
||||||
"picocolors": "^1.0.0",
|
"picocolors": "^1.0.1",
|
||||||
"source-map-js": "^1.2.0"
|
"source-map-js": "^1.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -2420,6 +2420,12 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tabbable": {
|
||||||
|
"version": "5.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-5.3.3.tgz",
|
||||||
|
"integrity": "sha512-QD9qKY3StfbZqWOPLp0++pOrAVb/HbUi5xCc8cUo4XjP19808oaMiDzn0leBY5mCespIBM0CIZePzZjgzR83kA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tailwindcss": {
|
"node_modules/tailwindcss": {
|
||||||
"version": "3.4.4",
|
"version": "3.4.4",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz",
|
||||||
@ -2458,6 +2464,19 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tailwindcss/node_modules/glob-parent": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"is-glob": "^4.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tailwindcss/node_modules/postcss-selector-parser": {
|
"node_modules/tailwindcss/node_modules/postcss-selector-parser": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
|
||||||
@ -2516,9 +2535,9 @@
|
|||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/update-browserslist-db": {
|
"node_modules/update-browserslist-db": {
|
||||||
"version": "1.0.16",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz",
|
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",
|
||||||
"integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==",
|
"integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@ -2554,14 +2573,14 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.3.1",
|
"version": "5.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.3.3.tgz",
|
||||||
"integrity": "sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==",
|
"integrity": "sha512-NPQdeCU0Dv2z5fu+ULotpuq5yfCS1BzKUIPhNbP3YBfAMGJXbt2nS+sbTFu+qchaqWTD+H3JK++nRwr6XIcp6A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.39",
|
||||||
"rollup": "^4.13.0"
|
"rollup": "^4.13.0"
|
||||||
},
|
},
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -10,11 +10,15 @@
|
|||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
"autoprefixer": "^10.4.16",
|
"autoprefixer": "^10.4.16",
|
||||||
"axios": "^1.6.4",
|
"axios": "^1.6.4",
|
||||||
|
"chokidar": "^3.6.0",
|
||||||
"laravel-vite-plugin": "^1.0",
|
"laravel-vite-plugin": "^1.0",
|
||||||
"postcss": "^8.4.32",
|
"postcss": "^8.4.32",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.5",
|
"prettier-plugin-tailwindcss": "^0.6.5",
|
||||||
"tailwindcss": "^3.4.0",
|
"tailwindcss": "^3.4.0",
|
||||||
"vite": "^5.0"
|
"vite": "^5.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@alpinejs/focus": "^3.14.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
public/css/filament/filament/app.css
Normal file
1
public/css/filament/filament/app.css
Normal file
File diff suppressed because one or more lines are too long
49
public/css/filament/forms/forms.css
Normal file
49
public/css/filament/forms/forms.css
Normal file
File diff suppressed because one or more lines are too long
1
public/css/filament/support/support.css
Normal file
1
public/css/filament/support/support.css
Normal file
@ -0,0 +1 @@
|
|||||||
|
.fi-pagination-items,.fi-pagination-overview,.fi-pagination-records-per-page-select:not(.fi-compact){display:none}@supports (container-type:inline-size){.fi-pagination{container-type:inline-size}@container (min-width: 28rem){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@container (min-width: 56rem){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}@supports not (container-type:inline-size){@media (min-width:640px){.fi-pagination-records-per-page-select.fi-compact{display:none}.fi-pagination-records-per-page-select:not(.fi-compact){display:inline}}@media (min-width:768px){.fi-pagination:not(.fi-simple)>.fi-pagination-previous-btn{display:none}.fi-pagination-overview{display:inline}.fi-pagination:not(.fi-simple)>.fi-pagination-next-btn{display:none}.fi-pagination-items{display:flex}}}.tippy-box[data-animation=fade][data-state=hidden]{opacity:0}[data-tippy-root]{max-width:calc(100vw - 10px)}.tippy-box{background-color:#333;border-radius:4px;color:#fff;font-size:14px;line-height:1.4;outline:0;position:relative;transition-property:transform,visibility,opacity;white-space:normal}.tippy-box[data-placement^=top]>.tippy-arrow{bottom:0}.tippy-box[data-placement^=top]>.tippy-arrow:before{border-top-color:initial;border-width:8px 8px 0;bottom:-7px;left:0;transform-origin:center top}.tippy-box[data-placement^=bottom]>.tippy-arrow{top:0}.tippy-box[data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:initial;border-width:0 8px 8px;left:0;top:-7px;transform-origin:center bottom}.tippy-box[data-placement^=left]>.tippy-arrow{right:0}.tippy-box[data-placement^=left]>.tippy-arrow:before{border-left-color:initial;border-width:8px 0 8px 8px;right:-7px;transform-origin:center left}.tippy-box[data-placement^=right]>.tippy-arrow{left:0}.tippy-box[data-placement^=right]>.tippy-arrow:before{border-right-color:initial;border-width:8px 8px 8px 0;left:-7px;transform-origin:center right}.tippy-box[data-inertia][data-state=visible]{transition-timing-function:cubic-bezier(.54,1.5,.38,1.11)}.tippy-arrow{color:#333;height:16px;width:16px}.tippy-arrow:before{border-color:transparent;border-style:solid;content:"";position:absolute}.tippy-content{padding:5px 9px;position:relative;z-index:1}.tippy-box[data-theme~=light]{background-color:#fff;box-shadow:0 0 20px 4px #9aa1b126,0 4px 80px -8px #24282f40,0 4px 4px -2px #5b5e6926;color:#26323d}.tippy-box[data-theme~=light][data-placement^=top]>.tippy-arrow:before{border-top-color:#fff}.tippy-box[data-theme~=light][data-placement^=bottom]>.tippy-arrow:before{border-bottom-color:#fff}.tippy-box[data-theme~=light][data-placement^=left]>.tippy-arrow:before{border-left-color:#fff}.tippy-box[data-theme~=light][data-placement^=right]>.tippy-arrow:before{border-right-color:#fff}.tippy-box[data-theme~=light]>.tippy-backdrop{background-color:#fff}.tippy-box[data-theme~=light]>.tippy-svg-arrow{fill:#fff}.fi-sortable-ghost{opacity:.3}
|
1
public/js/filament/filament/app.js
Normal file
1
public/js/filament/filament/app.js
Normal file
File diff suppressed because one or more lines are too long
13
public/js/filament/filament/echo.js
Normal file
13
public/js/filament/filament/echo.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/forms/components/color-picker.js
Normal file
1
public/js/filament/forms/components/color-picker.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/forms/components/date-time-picker.js
Normal file
1
public/js/filament/forms/components/date-time-picker.js
Normal file
File diff suppressed because one or more lines are too long
123
public/js/filament/forms/components/file-upload.js
Normal file
123
public/js/filament/forms/components/file-upload.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/forms/components/key-value.js
Normal file
1
public/js/filament/forms/components/key-value.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
function r({state:o}){return{state:o,rows:[],shouldUpdateRows:!0,init:function(){this.updateRows(),this.rows.length<=0?this.rows.push({key:"",value:""}):this.updateState(),this.$watch("state",(t,e)=>{let s=i=>i===null?0:Array.isArray(i)?i.length:typeof i!="object"?0:Object.keys(i).length;s(t)===0&&s(e)===0||this.updateRows()})},addRow:function(){this.rows.push({key:"",value:""}),this.updateState()},deleteRow:function(t){this.rows.splice(t,1),this.rows.length<=0&&this.addRow(),this.updateState()},reorderRows:function(t){let e=Alpine.raw(this.rows);this.rows=[];let s=e.splice(t.oldIndex,1)[0];e.splice(t.newIndex,0,s),this.$nextTick(()=>{this.rows=e,this.updateState()})},updateRows:function(){if(!this.shouldUpdateRows){this.shouldUpdateRows=!0;return}let t=[];for(let[e,s]of Object.entries(this.state??{}))t.push({key:e,value:s});this.rows=t},updateState:function(){let t={};this.rows.forEach(e=>{e.key===""||e.key===null||(t[e.key]=e.value)}),this.shouldUpdateRows=!1,this.state=t}}}export{r as default};
|
51
public/js/filament/forms/components/markdown-editor.js
Normal file
51
public/js/filament/forms/components/markdown-editor.js
Normal file
File diff suppressed because one or more lines are too long
144
public/js/filament/forms/components/rich-editor.js
Normal file
144
public/js/filament/forms/components/rich-editor.js
Normal file
File diff suppressed because one or more lines are too long
6
public/js/filament/forms/components/select.js
Normal file
6
public/js/filament/forms/components/select.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/forms/components/tags-input.js
Normal file
1
public/js/filament/forms/components/tags-input.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
function i({state:a,splitKeys:n}){return{newTag:"",state:a,createTag:function(){if(this.newTag=this.newTag.trim(),this.newTag!==""){if(this.state.includes(this.newTag)){this.newTag="";return}this.state.push(this.newTag),this.newTag=""}},deleteTag:function(t){this.state=this.state.filter(e=>e!==t)},reorderTags:function(t){let e=this.state.splice(t.oldIndex,1)[0];this.state.splice(t.newIndex,0,e),this.state=[...this.state]},input:{["x-on:blur"]:"createTag()",["x-model"]:"newTag",["x-on:keydown"](t){["Enter",...n].includes(t.key)&&(t.preventDefault(),t.stopPropagation(),this.createTag())},["x-on:paste"](){this.$nextTick(()=>{if(n.length===0){this.createTag();return}let t=n.map(e=>e.replace(/[/\-\\^$*+?.()|[\]{}]/g,"\\$&")).join("|");this.newTag.split(new RegExp(t,"g")).forEach(e=>{this.newTag=e,this.createTag()})})}}}}export{i as default};
|
1
public/js/filament/forms/components/textarea.js
Normal file
1
public/js/filament/forms/components/textarea.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
function i({initialHeight:t}){return{height:t+"rem",init:function(){this.setInitialHeight(),this.setUpResizeObserver()},setInitialHeight:function(){this.height=t+"rem",!(this.$el.scrollHeight<=0)&&(this.$el.style.height=this.height)},resize:function(){if(this.setInitialHeight(),this.$el.scrollHeight<=0)return;let e=this.$el.scrollHeight+"px";this.height!==e&&(this.height=e,this.$el.style.height=this.height)},setUpResizeObserver:function(){new ResizeObserver(()=>{this.height=this.$el.style.height}).observe(this.$el)}}}export{i as default};
|
1
public/js/filament/notifications/notifications.js
Normal file
1
public/js/filament/notifications/notifications.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/support/async-alpine.js
Normal file
1
public/js/filament/support/async-alpine.js
Normal file
File diff suppressed because one or more lines are too long
46
public/js/filament/support/support.js
Normal file
46
public/js/filament/support/support.js
Normal file
File diff suppressed because one or more lines are too long
1
public/js/filament/tables/components/table.js
Normal file
1
public/js/filament/tables/components/table.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
function n(){return{collapsedGroups:[],isLoading:!1,selectedRecords:[],shouldCheckUniqueSelection:!0,lastCheckedRecord:null,livewireId:null,init:function(){this.livewireId=this.$root.closest("[wire\\:id]").attributes["wire:id"].value,this.$wire.$on("deselectAllTableRecords",()=>this.deselectAllRecords()),this.$watch("selectedRecords",()=>{if(!this.shouldCheckUniqueSelection){this.shouldCheckUniqueSelection=!0;return}this.selectedRecords=[...new Set(this.selectedRecords)],this.shouldCheckUniqueSelection=!1}),this.$nextTick(()=>this.watchForCheckboxClicks()),Livewire.hook("element.init",({component:e})=>{e.id===this.livewireId&&this.watchForCheckboxClicks()})},mountAction:function(e,t=null){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableAction(e,t)},mountBulkAction:function(e){this.$wire.set("selectedTableRecords",this.selectedRecords,!1),this.$wire.mountTableBulkAction(e)},toggleSelectRecordsOnPage:function(){let e=this.getRecordsOnPage();if(this.areRecordsSelected(e)){this.deselectRecords(e);return}this.selectRecords(e)},toggleSelectRecordsInGroup:async function(e){if(this.isLoading=!0,this.areRecordsSelected(this.getRecordsInGroupOnPage(e))){this.deselectRecords(await this.$wire.getGroupedSelectableTableRecordKeys(e));return}this.selectRecords(await this.$wire.getGroupedSelectableTableRecordKeys(e)),this.isLoading=!1},getRecordsInGroupOnPage:function(e){let t=[];for(let s of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])s.dataset.group===e&&t.push(s.value);return t},getRecordsOnPage:function(){let e=[];for(let t of this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[])e.push(t.value);return e},selectRecords:function(e){for(let t of e)this.isRecordSelected(t)||this.selectedRecords.push(t)},deselectRecords:function(e){for(let t of e){let s=this.selectedRecords.indexOf(t);s!==-1&&this.selectedRecords.splice(s,1)}},selectAllRecords:async function(){this.isLoading=!0,this.selectedRecords=await this.$wire.getAllSelectableTableRecordKeys(),this.isLoading=!1},deselectAllRecords:function(){this.selectedRecords=[]},isRecordSelected:function(e){return this.selectedRecords.includes(e)},areRecordsSelected:function(e){return e.every(t=>this.isRecordSelected(t))},toggleCollapseGroup:function(e){if(this.isGroupCollapsed(e)){this.collapsedGroups.splice(this.collapsedGroups.indexOf(e),1);return}this.collapsedGroups.push(e)},isGroupCollapsed:function(e){return this.collapsedGroups.includes(e)},resetCollapsedGroups:function(){this.collapsedGroups=[]},watchForCheckboxClicks:function(){let e=this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[];for(let t of e)t.removeEventListener("click",this.handleCheckboxClick),t.addEventListener("click",s=>this.handleCheckboxClick(s,t))},handleCheckboxClick:function(e,t){if(!this.lastChecked){this.lastChecked=t;return}if(e.shiftKey){let s=Array.from(this.$root?.getElementsByClassName("fi-ta-record-checkbox")??[]);if(!s.includes(this.lastChecked)){this.lastChecked=t;return}let o=s.indexOf(this.lastChecked),r=s.indexOf(t),l=[o,r].sort((i,d)=>i-d),c=[];for(let i=l[0];i<=l[1];i++)s[i].checked=t.checked,c.push(s[i].value);t.checked?this.selectRecords(c):this.deselectRecords(c)}this.lastChecked=t}}}export{n as default};
|
37
public/js/filament/widgets/components/chart.js
Normal file
37
public/js/filament/widgets/components/chart.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
public/vendor/livewire/livewire.esm.js
vendored
6
public/vendor/livewire/livewire.esm.js
vendored
@ -8660,7 +8660,7 @@ function extractDestinationFromLink(linkEl) {
|
|||||||
return createUrlObjectFromString(linkEl.getAttribute("href"));
|
return createUrlObjectFromString(linkEl.getAttribute("href"));
|
||||||
}
|
}
|
||||||
function createUrlObjectFromString(urlString) {
|
function createUrlObjectFromString(urlString) {
|
||||||
return new URL(urlString, document.baseURI);
|
return urlString !== null && new URL(urlString, document.baseURI);
|
||||||
}
|
}
|
||||||
function getUriStringFromUrlObject(urlObject) {
|
function getUriStringFromUrlObject(urlObject) {
|
||||||
return urlObject.pathname + urlObject.search + urlObject.hash;
|
return urlObject.pathname + urlObject.search + urlObject.hash;
|
||||||
@ -9087,12 +9087,16 @@ function navigate_default(Alpine19) {
|
|||||||
let shouldPrefetchOnHover = modifiers.includes("hover");
|
let shouldPrefetchOnHover = modifiers.includes("hover");
|
||||||
shouldPrefetchOnHover && whenThisLinkIsHoveredFor(el, 60, () => {
|
shouldPrefetchOnHover && whenThisLinkIsHoveredFor(el, 60, () => {
|
||||||
let destination = extractDestinationFromLink(el);
|
let destination = extractDestinationFromLink(el);
|
||||||
|
if (!destination)
|
||||||
|
return;
|
||||||
prefetchHtml(destination, (html, finalDestination) => {
|
prefetchHtml(destination, (html, finalDestination) => {
|
||||||
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
whenThisLinkIsPressed(el, (whenItIsReleased) => {
|
whenThisLinkIsPressed(el, (whenItIsReleased) => {
|
||||||
let destination = extractDestinationFromLink(el);
|
let destination = extractDestinationFromLink(el);
|
||||||
|
if (!destination)
|
||||||
|
return;
|
||||||
prefetchHtml(destination, (html, finalDestination) => {
|
prefetchHtml(destination, (html, finalDestination) => {
|
||||||
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
||||||
});
|
});
|
||||||
|
6
public/vendor/livewire/livewire.js
vendored
6
public/vendor/livewire/livewire.js
vendored
@ -7305,7 +7305,7 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
|||||||
return createUrlObjectFromString(linkEl.getAttribute("href"));
|
return createUrlObjectFromString(linkEl.getAttribute("href"));
|
||||||
}
|
}
|
||||||
function createUrlObjectFromString(urlString) {
|
function createUrlObjectFromString(urlString) {
|
||||||
return new URL(urlString, document.baseURI);
|
return urlString !== null && new URL(urlString, document.baseURI);
|
||||||
}
|
}
|
||||||
function getUriStringFromUrlObject(urlObject) {
|
function getUriStringFromUrlObject(urlObject) {
|
||||||
return urlObject.pathname + urlObject.search + urlObject.hash;
|
return urlObject.pathname + urlObject.search + urlObject.hash;
|
||||||
@ -7730,12 +7730,16 @@ ${expression ? 'Expression: "' + expression + '"\n\n' : ""}`, el);
|
|||||||
let shouldPrefetchOnHover = modifiers.includes("hover");
|
let shouldPrefetchOnHover = modifiers.includes("hover");
|
||||||
shouldPrefetchOnHover && whenThisLinkIsHoveredFor(el, 60, () => {
|
shouldPrefetchOnHover && whenThisLinkIsHoveredFor(el, 60, () => {
|
||||||
let destination = extractDestinationFromLink(el);
|
let destination = extractDestinationFromLink(el);
|
||||||
|
if (!destination)
|
||||||
|
return;
|
||||||
prefetchHtml(destination, (html, finalDestination) => {
|
prefetchHtml(destination, (html, finalDestination) => {
|
||||||
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
whenThisLinkIsPressed(el, (whenItIsReleased) => {
|
whenThisLinkIsPressed(el, (whenItIsReleased) => {
|
||||||
let destination = extractDestinationFromLink(el);
|
let destination = extractDestinationFromLink(el);
|
||||||
|
if (!destination)
|
||||||
|
return;
|
||||||
prefetchHtml(destination, (html, finalDestination) => {
|
prefetchHtml(destination, (html, finalDestination) => {
|
||||||
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
storeThePrefetchedHtmlForWhenALinkIsClicked(html, destination, finalDestination);
|
||||||
});
|
});
|
||||||
|
4
public/vendor/livewire/livewire.min.js
vendored
4
public/vendor/livewire/livewire.min.js
vendored
File diff suppressed because one or more lines are too long
4
public/vendor/livewire/livewire.min.js.map
vendored
4
public/vendor/livewire/livewire.min.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/manifest.json
vendored
2
public/vendor/livewire/manifest.json
vendored
@ -1,2 +1,2 @@
|
|||||||
|
|
||||||
{"/livewire.js":"87e1046f"}
|
{"/livewire.js":"c4fc8c5d"}
|
||||||
|
3
public/vendor/nova/app.css
vendored
3
public/vendor/nova/app.css
vendored
File diff suppressed because one or more lines are too long
1
public/vendor/nova/app.css.map
vendored
1
public/vendor/nova/app.css.map
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/nova/app.js
vendored
2
public/vendor/nova/app.js
vendored
File diff suppressed because one or more lines are too long
46
public/vendor/nova/app.js.LICENSE.txt
vendored
46
public/vendor/nova/app.js.LICENSE.txt
vendored
@ -1,46 +0,0 @@
|
|||||||
/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress
|
|
||||||
* @license MIT */
|
|
||||||
|
|
||||||
/*!
|
|
||||||
autosize 4.0.4
|
|
||||||
license: MIT
|
|
||||||
http://www.jacklmoore.com/autosize
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* @overview es6-promise - a tiny implementation of Promises/A+.
|
|
||||||
* @copyright Copyright (c) 2014 Yehuda Katz, Tom Dale, Stefan Penner and contributors (Conversion to ES6 API by Jake Archibald)
|
|
||||||
* @license Licensed under MIT license
|
|
||||||
* See https://raw.githubusercontent.com/stefanpenner/es6-promise/master/LICENSE
|
|
||||||
* @version v4.2.8+1e68dce6
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* JavaScript Cookie v2.2.1
|
|
||||||
* https://github.com/js-cookie/js-cookie
|
|
||||||
*
|
|
||||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
|
||||||
* Released under the MIT license
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
* vuex v4.1.0
|
|
||||||
* (c) 2022 Evan You
|
|
||||||
* @license MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*! Hammer.JS - v2.0.7 - 2016-04-22
|
|
||||||
* http://hammerjs.github.io/
|
|
||||||
*
|
|
||||||
* Copyright (c) 2016 Jorik Tangelder;
|
|
||||||
* Licensed under the MIT license */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @license
|
|
||||||
* Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
|
|
||||||
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
|
||||||
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
|
||||||
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
|
||||||
* Code distributed by Google as part of the polymer project is also
|
|
||||||
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
|
||||||
*/
|
|
1
public/vendor/nova/app.js.map
vendored
1
public/vendor/nova/app.js.map
vendored
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user