Merge branch 'main' of github.com:masroore/radsparc-web
# Conflicts: # composer.lock
This commit is contained in:
commit
fb85254d01
20
.env.example
20
.env.example
@ -3,7 +3,7 @@ APP_ENV=local
|
|||||||
APP_KEY=
|
APP_KEY=
|
||||||
APP_DEBUG=true
|
APP_DEBUG=true
|
||||||
APP_TIMEZONE=UTC
|
APP_TIMEZONE=UTC
|
||||||
APP_URL=http://localhost
|
APP_URL=http://radsparc.test
|
||||||
APP_PORT=80
|
APP_PORT=80
|
||||||
APP_LOCALE=en
|
APP_LOCALE=en
|
||||||
APP_FALLBACK_LOCALE=en
|
APP_FALLBACK_LOCALE=en
|
||||||
@ -21,14 +21,14 @@ LOG_STACK=single
|
|||||||
LOG_DEPRECATIONS_CHANNEL=null
|
LOG_DEPRECATIONS_CHANNEL=null
|
||||||
LOG_LEVEL=debug
|
LOG_LEVEL=debug
|
||||||
|
|
||||||
DB_CONNECTION=sqlite
|
DB_CONNECTION=pgsql
|
||||||
# DB_HOST=127.0.0.1
|
DB_HOST=pgsql
|
||||||
# DB_PORT=3306
|
DB_PORT=5432
|
||||||
# DB_DATABASE=laravel
|
DB_DATABASE=radsphere
|
||||||
# DB_USERNAME=root
|
DB_USERNAME=sail
|
||||||
# DB_PASSWORD=
|
DB_PASSWORD=secret
|
||||||
|
|
||||||
SESSION_DRIVER=database
|
SESSION_DRIVER=redis
|
||||||
SESSION_LIFETIME=120
|
SESSION_LIFETIME=120
|
||||||
SESSION_ENCRYPT=false
|
SESSION_ENCRYPT=false
|
||||||
SESSION_PATH=/
|
SESSION_PATH=/
|
||||||
@ -38,13 +38,13 @@ BROADCAST_CONNECTION=log
|
|||||||
FILESYSTEM_DISK=local
|
FILESYSTEM_DISK=local
|
||||||
QUEUE_CONNECTION=database
|
QUEUE_CONNECTION=database
|
||||||
|
|
||||||
CACHE_STORE=database
|
CACHE_STORE=redis
|
||||||
CACHE_PREFIX=
|
CACHE_PREFIX=
|
||||||
|
|
||||||
MEMCACHED_HOST=127.0.0.1
|
MEMCACHED_HOST=127.0.0.1
|
||||||
|
|
||||||
REDIS_CLIENT=phpredis
|
REDIS_CLIENT=phpredis
|
||||||
REDIS_HOST=127.0.0.1
|
REDIS_HOST=redis
|
||||||
REDIS_PASSWORD=null
|
REDIS_PASSWORD=null
|
||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ yarn-error.log
|
|||||||
/.nova
|
/.nova
|
||||||
/.vscode
|
/.vscode
|
||||||
/.zed
|
/.zed
|
||||||
|
*.lock
|
||||||
|
25
app/Http/Requests/StudyHistoryRequest.php
Normal file
25
app/Http/Requests/StudyHistoryRequest.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
|
||||||
|
class StudyHistoryRequest extends FormRequest
|
||||||
|
{
|
||||||
|
public function rules(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'study_id' => ['required', 'exists:studies'],
|
||||||
|
'user_id' => ['required', 'exists:users'],
|
||||||
|
'clinical_history' => ['nullable'],
|
||||||
|
'surgical_history' => ['nullable'],
|
||||||
|
'lab_results' => ['nullable'],
|
||||||
|
'clinical_diagnosis' => ['nullable'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
10
app/Models/BaseModel.php
Normal file
10
app/Models/BaseModel.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
abstract class BaseModel extends Model
|
||||||
|
{
|
||||||
|
protected $guarded = ['id'];
|
||||||
|
}
|
@ -3,9 +3,8 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
|
|
||||||
class Institute extends Model
|
class Institute extends BaseModel
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
|
@ -4,9 +4,10 @@
|
|||||||
|
|
||||||
use App\Models\Enums\ReportStatus;
|
use App\Models\Enums\ReportStatus;
|
||||||
use App\Models\Enums\StudyLevelStatus;
|
use App\Models\Enums\StudyLevelStatus;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
|
|
||||||
class Study extends Model
|
class Study extends BaseModel
|
||||||
{
|
{
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
'is_locked' => 'boolean',
|
'is_locked' => 'boolean',
|
||||||
@ -15,5 +16,18 @@ class Study extends Model
|
|||||||
'report_status' => ReportStatus::class,
|
'report_status' => ReportStatus::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
public function history(): HasOne
|
||||||
|
{
|
||||||
|
return $this->hasOne(StudyHistory::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachments(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(StudyAttachment::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reports(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(StudyReport::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,4 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
class StudyAttachment extends BaseModel {}
|
||||||
|
|
||||||
class StudyAttachment extends Model {}
|
|
||||||
|
@ -2,6 +2,4 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
class StudyDeleteRequest extends BaseModel {}
|
||||||
|
|
||||||
class StudyDeleteRequest extends Model {}
|
|
||||||
|
18
app/Models/StudyHistory.php
Normal file
18
app/Models/StudyHistory.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
class StudyHistory extends BaseModel
|
||||||
|
{
|
||||||
|
public function study(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Study::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function user(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,4 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
class StudyNote extends BaseModel {}
|
||||||
|
|
||||||
class StudyNote extends Model {}
|
|
||||||
|
@ -2,10 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class StudyReport extends Model
|
class StudyReport extends BaseModel
|
||||||
{
|
{
|
||||||
public function study(): BelongsTo
|
public function study(): BelongsTo
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,17 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class Template extends Model {}
|
class Template extends BaseModel
|
||||||
|
{
|
||||||
|
public function owner(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'owner_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function category(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(TemplateCategory::class, 'category_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,4 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
class TemplateCategory extends BaseModel {}
|
||||||
|
|
||||||
class TemplateCategory extends Model {}
|
|
||||||
|
@ -12,6 +12,24 @@
|
|||||||
/** @psalm-type Int32BitMask = int<0, 2147483647> */
|
/** @psalm-type Int32BitMask = int<0, 2147483647> */
|
||||||
trait BitmaskFunctionality
|
trait BitmaskFunctionality
|
||||||
{
|
{
|
||||||
|
/** @param Int32BitMask $value */
|
||||||
|
public static function hasCase(int $value): bool
|
||||||
|
{
|
||||||
|
return self::tryFrom($value) !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Int32BitMask */
|
||||||
|
public static function build(self ...$bits): int
|
||||||
|
{
|
||||||
|
return self::set(0, ...$bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return Int32BitMask */
|
||||||
|
public static function set(int $value, self ...$bits): int
|
||||||
|
{
|
||||||
|
return $value | self::mask(...$bits);
|
||||||
|
}
|
||||||
|
|
||||||
/** @return Int32BitMask */
|
/** @return Int32BitMask */
|
||||||
public static function mask(self ...$bits): int
|
public static function mask(self ...$bits): int
|
||||||
{
|
{
|
||||||
@ -22,39 +40,6 @@ public static function mask(self ...$bits): int
|
|||||||
return array_reduce($bits, static fn (?int $sum, self $case) => ($sum ?? 0) | $case->value);
|
return array_reduce($bits, static fn (?int $sum, self $case) => ($sum ?? 0) | $case->value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
|
||||||
public static function hasCase(int $value): bool
|
|
||||||
{
|
|
||||||
return self::tryFrom($value) !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
|
||||||
public static function valueToString(int $value): string
|
|
||||||
{
|
|
||||||
return '0b'.substr(chunk_split(sprintf('%\'032b', $value), 4, '_'), 0, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toString(): string
|
|
||||||
{
|
|
||||||
return self::valueToString($this->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return Int32BitMask */
|
|
||||||
public static function build(self ...$bits): int
|
|
||||||
{
|
|
||||||
return self::set(0, ...$bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
|
||||||
|
|
||||||
/** @return Int32BitMask */
|
|
||||||
public static function set(int $value, self ...$bits): int
|
|
||||||
{
|
|
||||||
return $value | self::mask(...$bits);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
|
||||||
|
|
||||||
/** @return Int32BitMask */
|
/** @return Int32BitMask */
|
||||||
public static function clear(int $value, self ...$bits): int
|
public static function clear(int $value, self ...$bits): int
|
||||||
{
|
{
|
||||||
@ -70,10 +55,6 @@ public static function toggle(int $value, self ...$bits): int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
/** @param Int32BitMask $value */
|
||||||
public static function on(int $value, self $bit): bool
|
|
||||||
{
|
|
||||||
return ($value & $bit->value) === $bit->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
/** @param Int32BitMask $value */
|
||||||
public static function off(int $value, self $bit): bool
|
public static function off(int $value, self $bit): bool
|
||||||
@ -81,6 +62,8 @@ public static function off(int $value, self $bit): bool
|
|||||||
return ($value & $bit->value) === 0;
|
return ($value & $bit->value) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param Int32BitMask $value */
|
||||||
|
|
||||||
/** @param Int32BitMask $value */
|
/** @param Int32BitMask $value */
|
||||||
public static function any(int $value, self ...$bits): bool
|
public static function any(int $value, self ...$bits): bool
|
||||||
{
|
{
|
||||||
@ -123,4 +106,21 @@ public static function parse(int $value): array
|
|||||||
{
|
{
|
||||||
return array_filter(self::cases(), static fn (self $case) => self::on($value, $case));
|
return array_filter(self::cases(), static fn (self $case) => self::on($value, $case));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param Int32BitMask $value */
|
||||||
|
public static function on(int $value, self $bit): bool
|
||||||
|
{
|
||||||
|
return ($value & $bit->value) === $bit->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toString(): string
|
||||||
|
{
|
||||||
|
return self::valueToString($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param Int32BitMask $value */
|
||||||
|
public static function valueToString(int $value): string
|
||||||
|
{
|
||||||
|
return '0b'.substr(chunk_split(sprintf('%\'032b', $value), 4, '_'), 0, -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||||
|
use Database\Factories\UserFactory;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@ -15,7 +16,7 @@ class User extends Authenticatable
|
|||||||
{
|
{
|
||||||
use HasApiTokens;
|
use HasApiTokens;
|
||||||
|
|
||||||
/** @use HasFactory<\Database\Factories\UserFactory> */
|
/** @use HasFactory<UserFactory> */
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
use HasProfilePhoto;
|
use HasProfilePhoto;
|
||||||
|
@ -95,7 +95,7 @@ private function prepareData(mixed $study): array
|
|||||||
'institution_name' => $inst_name,
|
'institution_name' => $inst_name,
|
||||||
'institute_id' => $inst_id,
|
'institute_id' => $inst_id,
|
||||||
|
|
||||||
'patient_uuid' => $study['ParentPatient'],
|
'patient_uid' => $study['ParentPatient'],
|
||||||
'patient_id' => data_get($study, 'PatientMainDicomTags.PatientID'),
|
'patient_id' => data_get($study, 'PatientMainDicomTags.PatientID'),
|
||||||
'patient_name' => data_get($study, 'PatientMainDicomTags.PatientName'),
|
'patient_name' => data_get($study, 'PatientMainDicomTags.PatientName'),
|
||||||
'patient_sex' => data_get($study, 'PatientMainDicomTags.PatientSex'),
|
'patient_sex' => data_get($study, 'PatientMainDicomTags.PatientSex'),
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"laravel/tinker": "^2.9",
|
"laravel/tinker": "^2.9",
|
||||||
"league/url": "^3.3",
|
"league/url": "^3.3",
|
||||||
"livewire/livewire": "^3.0",
|
"livewire/livewire": "^3.0",
|
||||||
|
"phpoffice/phpword": "^1.3",
|
||||||
"propaganistas/laravel-phone": "^5.3",
|
"propaganistas/laravel-phone": "^5.3",
|
||||||
"rap2hpoutre/fast-excel": "^5.5",
|
"rap2hpoutre/fast-excel": "^5.5",
|
||||||
"spatie/laravel-permission": "^6.10",
|
"spatie/laravel-permission": "^6.10",
|
||||||
@ -31,7 +32,7 @@
|
|||||||
"fakerphp/faker": "^1.23",
|
"fakerphp/faker": "^1.23",
|
||||||
"laravel/pail": "^1.1",
|
"laravel/pail": "^1.1",
|
||||||
"laravel/pint": "^1.13",
|
"laravel/pint": "^1.13",
|
||||||
"laravel/sail": "^1.26",
|
"laravel/sail": "^1.39",
|
||||||
"mockery/mockery": "^1.6",
|
"mockery/mockery": "^1.6",
|
||||||
"nunomaduro/collision": "^8.1",
|
"nunomaduro/collision": "^8.1",
|
||||||
"pestphp/pest": "^3.7",
|
"pestphp/pest": "^3.7",
|
||||||
|
11143
composer.lock
generated
11143
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,7 @@ public function up(): void
|
|||||||
$table->boolean('is_locked')->default(true);
|
$table->boolean('is_locked')->default(true);
|
||||||
$table->unsignedTinyInteger('study_priority')->default(0);
|
$table->unsignedTinyInteger('study_priority')->default(0);
|
||||||
$table->string('patient_id')->nullable();
|
$table->string('patient_id')->nullable();
|
||||||
$table->string('patient_uuid')->nullable();
|
$table->string('patient_uid')->nullable();
|
||||||
$table->string('patient_name');
|
$table->string('patient_name');
|
||||||
$table->string('patient_sex')->nullable();
|
$table->string('patient_sex')->nullable();
|
||||||
$table->date('patient_birthdate')->nullable();
|
$table->date('patient_birthdate')->nullable();
|
||||||
@ -35,6 +35,7 @@ public function up(): void
|
|||||||
$table->string('operators_name')->nullable();
|
$table->string('operators_name')->nullable();
|
||||||
$table->string('manufacturer')->nullable();
|
$table->string('manufacturer')->nullable();
|
||||||
$table->string('manufacturer_model_name')->nullable();
|
$table->string('manufacturer_model_name')->nullable();
|
||||||
|
$table->string('software_versions')->nullable();
|
||||||
|
|
||||||
$table->string('referring_physician_name')->nullable();
|
$table->string('referring_physician_name')->nullable();
|
||||||
$table->string('study_modality', 4)->nullable();
|
$table->string('study_modality', 4)->nullable();
|
||||||
|
@ -12,8 +12,8 @@ public function up(): void
|
|||||||
{
|
{
|
||||||
Schema::create('study_notes', function (Blueprint $table) {
|
Schema::create('study_notes', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->foreignIdFor(Study::class)->constrained()->onDelete('cascade');
|
$table->foreignIdFor(Study::class)->constrained()->cascadeOnDelete();
|
||||||
$table->foreignIdFor(User::class)->nullable()->constrained()->onDelete('cascade');
|
$table->foreignIdFor(User::class)->nullable()->constrained()->cascadeOnDelete();
|
||||||
$table->string('title')->nullable();
|
$table->string('title')->nullable();
|
||||||
$table->longText('content');
|
$table->longText('content');
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
@ -14,8 +14,9 @@ public function up(): void
|
|||||||
Schema::create('study_reports', function (Blueprint $table) {
|
Schema::create('study_reports', function (Blueprint $table) {
|
||||||
$table->id();
|
$table->id();
|
||||||
$table->unsignedTinyInteger('report_status')->default(ReportStatus::Pending->value);
|
$table->unsignedTinyInteger('report_status')->default(ReportStatus::Pending->value);
|
||||||
$table->foreignIdFor(Study::class)->index()->constrained()->onDelete('cascade');
|
$table->foreignIdFor(Study::class)->index()->constrained()->cascadeOnDelete();
|
||||||
$table->foreignIdFor(User::class)->index()->constrained()->onDelete('cascade');
|
$table->foreignIdFor(User::class, 'radiologist_id')->index()->constrained()->cascadeOnDelete();
|
||||||
|
$table->string('report_title')->nullable();
|
||||||
$table->string('file_path');
|
$table->string('file_path');
|
||||||
$table->string('pdf_path')->nullable();
|
$table->string('pdf_path')->nullable();
|
||||||
$table->timestamps();
|
$table->timestamps();
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('study_histories', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->foreignId('study_id')->index()->constrained('studies')->cascadeOnDelete();
|
||||||
|
$table->foreignId('user_id')->constrained('users');
|
||||||
|
$table->text('clinical_history')->nullable();
|
||||||
|
$table->text('surgical_history')->nullable();
|
||||||
|
$table->text('lab_results')->nullable();
|
||||||
|
$table->text('clinical_diagnosis')->nullable();
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('study_histories');
|
||||||
|
}
|
||||||
|
};
|
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "radsparc",
|
"name": "html",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
Loading…
Reference in New Issue
Block a user