wip
This commit is contained in:
parent
bd4ac224ad
commit
eb1def36a1
|
|
@ -7,7 +7,7 @@
|
|||
class DownloadController extends Controller
|
||||
{
|
||||
public function show() {
|
||||
return view('download.show');
|
||||
return view('download.show', ['project' => $project]);
|
||||
}
|
||||
//
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,5 +16,5 @@ public function show(Project $project)
|
|||
{
|
||||
return view('projects.show', compact('project'));
|
||||
}
|
||||
//
|
||||
|
||||
}
|
||||
|
|
|
|||
14
laravel_app/app/Http/Controllers/ProjectReportController.php
Normal file
14
laravel_app/app/Http/Controllers/ProjectReportController.php
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\ProjectReport;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ProjectReportController extends Controller
|
||||
{
|
||||
public function download(ProjectReport $projectReport)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
72
laravel_app/app/Jobs/ProjectReportGeneratorJob.php
Normal file
72
laravel_app/app/Jobs/ProjectReportGeneratorJob.php
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Models\ProjectReport;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Symfony\Component\Process\Process;
|
||||
|
||||
class ProjectReportGeneratorJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
public $timeout = 120;
|
||||
private ProjectReport $projectReport;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*/
|
||||
public function __construct(ProjectReport $projectReport)
|
||||
{
|
||||
$this->projectReport = $projectReport;
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*/
|
||||
public function handle(): void
|
||||
{
|
||||
logger('in handle');
|
||||
$this->projectReport->weeksAgo();
|
||||
|
||||
$projectFolder = base_path('../');
|
||||
|
||||
$command = [
|
||||
sprintf('%sbuild_report.sh', $projectFolder),
|
||||
sprintf('--filename=%s', $this->projectReport->getFullPathName()),
|
||||
sprintf('--weeks_ago=%s', $this->projectReport->weeksAgo()),
|
||||
sprintf('--report_date=%s', $this->projectReport->getReportDate()),
|
||||
];
|
||||
|
||||
// Convert commands array to a single string
|
||||
|
||||
$process = new Process($command);
|
||||
$process->setTimeout(120);
|
||||
$currentPath = '/usr/gnu/bin:/usr/local/bin:/bin:/usr/bin/Users/mfolkerts/anaconda3/bin:/Library/Apple/usr/bin';
|
||||
|
||||
$process->setEnv(['PATH' => $currentPath.':/usr/local/Cellar/pandoc/3.1.8/bin/pandoc']);
|
||||
// $process->setTimeout(36000); // stel een geschikte timeout in
|
||||
$process->start();
|
||||
try {
|
||||
$myOutput = [];
|
||||
$process->wait(function ($type, $buffer) use (&$myOutput) {
|
||||
// $this->stream(to: 'processOutput', content: $buffer);
|
||||
$myOutput[] = $buffer;
|
||||
logger($buffer);
|
||||
});
|
||||
$this->processOutput = collect($myOutput)->join('\n');
|
||||
$this->projectReport->setStatusSuccess();
|
||||
} catch (ProcessFailedException $exception) {
|
||||
echo $exception->getMessage();
|
||||
$this->projectReport->setStatusFailed();
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
}
|
||||
|
|
@ -2,27 +2,21 @@
|
|||
|
||||
namespace App\Livewire\Download;
|
||||
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
|
||||
class DownloadGrid extends Component
|
||||
{
|
||||
public $directories;
|
||||
private $files = [];
|
||||
|
||||
public function mount()
|
||||
public function mount(Project $project)
|
||||
{
|
||||
$this->directories = collect(Storage::directories('chemba/single_images'))
|
||||
->map(function ($directory) {
|
||||
$parts = explode('/', $directory);
|
||||
return Carbon::parse(end($parts));
|
||||
})->sortByDesc(function ($date, $key) {
|
||||
return $date;
|
||||
})->values();
|
||||
$this->files = $project->getMosaicList();
|
||||
// dd($this->directories);
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.download.download-grid')->with(['directories', $this->directories]);
|
||||
return view('livewire.download.download-grid')->with(['files' => $this->files]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
24
laravel_app/app/Livewire/Project/ReportRow.php
Normal file
24
laravel_app/app/Livewire/Project/ReportRow.php
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Project;
|
||||
|
||||
use App\Models\ProjectReport;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Livewire\Component;
|
||||
|
||||
class ReportRow extends Component
|
||||
{
|
||||
public ProjectReport $report;
|
||||
|
||||
public function download()
|
||||
{
|
||||
$filePath = $this->report->project->download_path . '/' . $this->report->path;
|
||||
|
||||
if (!Storage::exists($filePath)) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
return Storage::download($filePath);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,12 +2,79 @@
|
|||
|
||||
namespace App\Livewire\Projects;
|
||||
|
||||
use App\Jobs\ProjectReportGeneratorJob;
|
||||
use App\Models\Project;
|
||||
use App\Rules\AllMosaicsPresentRule;
|
||||
use Livewire\Component;
|
||||
|
||||
class ReportManager extends Component
|
||||
{
|
||||
public $formData = [];
|
||||
public $project_id;
|
||||
|
||||
public $showReportModal = false;
|
||||
|
||||
public $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
public function openCreateReportModal()
|
||||
{
|
||||
$this->resetFormData();
|
||||
$this->showReportModal = true;
|
||||
}
|
||||
|
||||
public function mount(Project $project)
|
||||
{
|
||||
$this->project_id = $project->id;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.projects.report-manager');
|
||||
$project = Project::find($this->project_id);
|
||||
return view('livewire.projects.report-manager')->with(compact('project'));
|
||||
}
|
||||
|
||||
private function resetFormData()
|
||||
{
|
||||
$this->formData['week'] = now()->weekOfYear;
|
||||
$this->formData['year'] = now()->year;
|
||||
}
|
||||
|
||||
public function saveProjectReport()
|
||||
{
|
||||
sleep(1);
|
||||
$this->validate([
|
||||
'formData.week' => ['required', 'integer', 'min:1', 'max:53' ],
|
||||
'formData.year' => 'required|integer|min:2020|max:'.now()->addYear()->year,
|
||||
'formData' => [new AllMosaicsPresentRule($this->project_id)],
|
||||
]);
|
||||
|
||||
$newReport = Project::find($this->project_id)
|
||||
->reports()->create([
|
||||
'name' => 'Report for week '.$this->formData['week'].' of '.$this->formData['year'],
|
||||
'week' => $this->formData['week'],
|
||||
'year' => $this->formData['year'],
|
||||
'path' => 'reports/week_'.$this->formData['week'].'_'.$this->formData['year'].'.docx',
|
||||
]);
|
||||
|
||||
ProjectReportGeneratorJob::dispatch($newReport);
|
||||
$this->dispatch('refresh');
|
||||
|
||||
$this->showReportModal = false;
|
||||
|
||||
}
|
||||
|
||||
public function getDateRangeProperty()
|
||||
{
|
||||
if (empty($this->formData['week']) || strlen($this->formData['year']) !== 4) {
|
||||
return '<span class="text-red-500">Invalid week or year</span>';
|
||||
}
|
||||
$begin = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->startOfWeek();
|
||||
$end = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->endOfWeek();
|
||||
return $begin->format('Y-m-d').' - '.$end->format('Y-m-d');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,21 @@
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Project extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = [
|
||||
|
||||
'name',
|
||||
'mail_template',
|
||||
'mail_subject',
|
||||
'mail_frequency',
|
||||
'mail_day',
|
||||
'download_path',
|
||||
];
|
||||
|
||||
public static function saveWithFormData(mixed $formData)
|
||||
|
|
@ -65,6 +68,24 @@ private function upsertMailRecipients($formData)
|
|||
);
|
||||
}
|
||||
|
||||
private function getMosaicPath()
|
||||
{
|
||||
return sprintf('%s/%s', $this->download_path, 'weekly_mosaic');
|
||||
}
|
||||
|
||||
public function getMosaicList(): \Illuminate\Support\Collection
|
||||
{
|
||||
return collect(Storage::files($this->getMosaicPath()))
|
||||
->filter(fn($file) => Str::endsWith($file, '.tif'))
|
||||
->sortByDesc(function ($file) {
|
||||
$parts = explode('_', str_replace('.tif', '', $file));
|
||||
$week = $parts[1];
|
||||
$year = $parts[2];
|
||||
return $year.sprintf('%02d', $week);
|
||||
})
|
||||
->values();
|
||||
}
|
||||
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot(); // TODO: Change the autogenerated stub
|
||||
|
|
@ -80,6 +101,11 @@ protected static function boot()
|
|||
});
|
||||
}
|
||||
|
||||
public function reports()
|
||||
{
|
||||
return $this->hasMany(ProjectReport::class);
|
||||
}
|
||||
|
||||
public function getAttachmentPathAttribute()
|
||||
{
|
||||
return storage_path(sprintf('%s/attachments', $this->download_path));
|
||||
|
|
@ -106,4 +132,46 @@ public function downloads()
|
|||
{
|
||||
return $this->hasMany(ProjectDownload::class);
|
||||
}
|
||||
|
||||
public function allMosaicsPresent(Carbon $endDate)
|
||||
{
|
||||
// end date is in the future
|
||||
if ($endDate->isFuture()) {
|
||||
throw new \Exception('End date is in the future');
|
||||
}
|
||||
|
||||
$mosaicsNotPresentInFilesystem = $this->getMosiacFilenameListByEndDate($endDate)
|
||||
->filter(function ($filename) {
|
||||
return !$this->getMosaicList()->contains(function ($mosaicFilename) use ($filename) {
|
||||
return Str::endsWith( $mosaicFilename, substr($filename, -16));
|
||||
});
|
||||
});
|
||||
if ($mosaicsNotPresentInFilesystem->count() === 0) {
|
||||
return true;
|
||||
}
|
||||
$message = sprintf(
|
||||
'Missing mosaics: %s',
|
||||
$mosaicsNotPresentInFilesystem->implode(', ')
|
||||
);
|
||||
throw new \Exception($message);
|
||||
}
|
||||
|
||||
public function getMosiacFilenameListByEndDate(Carbon $endDate): \Illuminate\Support\Collection
|
||||
{
|
||||
$result = collect([]);
|
||||
for ($i = 0; $i < 4; $i++) {
|
||||
$week = $endDate->weekOfYear;
|
||||
$year = $endDate->year;
|
||||
if ($week === 53) {
|
||||
$year--;
|
||||
}
|
||||
|
||||
$result->add(sprintf('week_%02d_%04d.tif', $week, $year));
|
||||
|
||||
$endDate = $endDate->subWeek();
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
68
laravel_app/app/Models/ProjectReport.php
Normal file
68
laravel_app/app/Models/ProjectReport.php
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class ProjectReport extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'path', 'week', 'year', 'status'];
|
||||
|
||||
public function setStatusSuccess()
|
||||
{
|
||||
$this->status = 'success';
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function setStatusFailed()
|
||||
{
|
||||
$this->status = 'failed';
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function project()
|
||||
{
|
||||
return $this->belongsTo(Project::class);
|
||||
}
|
||||
|
||||
public function weeksAgo()
|
||||
{
|
||||
return now()->diffInWeeks(now()->setISODate($this->year, $this->week));
|
||||
}
|
||||
|
||||
public function getFileName()
|
||||
{
|
||||
return 'week_'.$this->week.'_'.$this->year;
|
||||
}
|
||||
|
||||
public function getFullPathName()
|
||||
{
|
||||
return storage_path('app/'.$this->project->download_path.'/'.$this->path);
|
||||
}
|
||||
|
||||
public function getReportDate()
|
||||
{
|
||||
return self::getReportDateForYearAndWeek(
|
||||
$this->project,
|
||||
$this->year,
|
||||
$this->week
|
||||
)->toDateString();
|
||||
}
|
||||
|
||||
public static function getReportDateForYearAndWeek(Project $project, $year, $week)
|
||||
{
|
||||
$date = Carbon::now()->setISODate($year, $week);
|
||||
|
||||
$dayOfWeek = Carbon::parse($project->mail_day)->subDay(2)->dayOfWeek;
|
||||
if ($dayOfWeek == 6) {
|
||||
$reportDay = $date->startOfWeek()->subDay();
|
||||
} else {
|
||||
$reportDay = $date->startOfWeek()->addDays($dayOfWeek);
|
||||
}
|
||||
|
||||
return $reportDay;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Report extends Model
|
||||
{
|
||||
protected $fillable = ['name', 'path'];
|
||||
}
|
||||
42
laravel_app/app/Rules/AllMosaicsPresentRule.php
Normal file
42
laravel_app/app/Rules/AllMosaicsPresentRule.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectReport;
|
||||
|
||||
class AllMosaicsPresentRule implements Rule
|
||||
{
|
||||
protected $projectId;
|
||||
protected $errorMessage = '';
|
||||
|
||||
public function __construct($projectId)
|
||||
{
|
||||
$this->projectId = $projectId;
|
||||
}
|
||||
|
||||
public function passes($attribute, $value)
|
||||
{
|
||||
try {
|
||||
$project = Project::find($this->projectId);
|
||||
|
||||
if (!$project) {
|
||||
$this->errorMessage = 'Project not found.';
|
||||
return false;
|
||||
}
|
||||
|
||||
return $project->allMosaicsPresent(
|
||||
ProjectReport::getReportDateForYearAndWeek($project, $value['year'], $value['week'])
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
$this->errorMessage = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function message()
|
||||
{
|
||||
return $this->errorMessage;
|
||||
}
|
||||
}
|
||||
|
|
@ -188,4 +188,9 @@
|
|||
// 'Example' => App\Facades\Example::class,
|
||||
])->toArray(),
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
'password' => env('LAPTOP_PASSWORD', 'secret'),
|
||||
|
||||
];
|
||||
|
|
|
|||
|
|
@ -11,10 +11,14 @@
|
|||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('reports', function (Blueprint $table) {
|
||||
Schema::create('project_reports', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('path');
|
||||
$table->string('name');
|
||||
$table->integer('week');
|
||||
$table->integer('year');
|
||||
$table->string('status')->default('pending');
|
||||
$table->unsignedBigInteger('project_id');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?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->bigIncrements('id');
|
||||
$table->string('queue')->index();
|
||||
$table->longText('payload');
|
||||
$table->unsignedTinyInteger('attempts');
|
||||
$table->unsignedInteger('reserved_at')->nullable();
|
||||
$table->unsignedInteger('available_at');
|
||||
$table->unsignedInteger('created_at');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('jobs');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
<?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('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('failed_jobs');
|
||||
}
|
||||
};
|
||||
204
laravel_app/package-lock.json
generated
204
laravel_app/package-lock.json
generated
|
|
@ -1,15 +1,22 @@
|
|||
{
|
||||
"name": "Laravel_app",
|
||||
"name": "laravel_app",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@alpinejs/collapse": "^3.13.3",
|
||||
"@alpinejs/focus": "^3.13.3",
|
||||
"@alpinejs/intersect": "^3.13.3",
|
||||
"@alpinejs/ui": "^3.13.3-beta.4",
|
||||
"@ryangjchandler/alpine-clipboard": "^2.3.0",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"alpinejs": "^3.13.3",
|
||||
"tailwindcss": "^3.3.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.2",
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"axios": "^1.1.2",
|
||||
"laravel-vite-plugin": "^0.8.0",
|
||||
|
|
@ -22,7 +29,6 @@
|
|||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
|
@ -30,6 +36,30 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@alpinejs/collapse": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/@alpinejs/collapse/-/collapse-3.13.3.tgz",
|
||||
"integrity": "sha512-iGO6IzqBwVNxAaoS4XCCJIIg9U/mH7v4vk6wlzxXKFWMXt2yynw93TkdELyjwxQqeNTEGimZRR+2wNf9yhJn0A=="
|
||||
},
|
||||
"node_modules/@alpinejs/focus": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/@alpinejs/focus/-/focus-3.13.3.tgz",
|
||||
"integrity": "sha512-fTRX/9wOfysyZ1PJ4gHeUnmiNTIgqBDIqKxeP5iMvj1UHD3TFLDXllvoIKH3ezqcsyQZqxd/q1MFM7dlIhkmeg==",
|
||||
"dependencies": {
|
||||
"focus-trap": "^6.9.4",
|
||||
"tabbable": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@alpinejs/intersect": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/@alpinejs/intersect/-/intersect-3.13.3.tgz",
|
||||
"integrity": "sha512-4iwomnp4VXP1OmFfyol0sEgWdMFmX1WBlc8/gxRt6tO8PeeJjnZMdGjJeY6gNeRWS4g6I9aTUycdsyl6OQNv7w=="
|
||||
},
|
||||
"node_modules/@alpinejs/ui": {
|
||||
"version": "3.13.3-beta.4",
|
||||
"resolved": "https://registry.npmjs.org/@alpinejs/ui/-/ui-3.13.3-beta.4.tgz",
|
||||
"integrity": "sha512-Dc6j40tELUqSAIg93Dgi+Carkw8MB+YXm0sILD41vkxw0ByHf5pICCBvhxkcVRg2I/2/6YM/W7i1ZUORNEqrgw=="
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.18.20",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
|
||||
|
|
@ -386,7 +416,6 @@
|
|||
"version": "0.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
|
||||
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/set-array": "^1.0.1",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.10",
|
||||
|
|
@ -400,7 +429,6 @@
|
|||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
|
||||
"integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
|
|
@ -409,7 +437,6 @@
|
|||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
|
||||
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
|
|
@ -417,14 +444,12 @@
|
|||
"node_modules/@jridgewell/sourcemap-codec": {
|
||||
"version": "1.4.15",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
|
||||
},
|
||||
"node_modules/@jridgewell/trace-mapping": {
|
||||
"version": "0.3.19",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz",
|
||||
"integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/resolve-uri": "^3.1.0",
|
||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||
|
|
@ -434,7 +459,6 @@
|
|||
"version": "2.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "2.0.5",
|
||||
"run-parallel": "^1.1.9"
|
||||
|
|
@ -447,7 +471,6 @@
|
|||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
|
||||
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
|
|
@ -456,7 +479,6 @@
|
|||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
|
||||
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.scandir": "2.1.5",
|
||||
"fastq": "^1.6.0"
|
||||
|
|
@ -465,10 +487,23 @@
|
|||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@ryangjchandler/alpine-clipboard": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ryangjchandler/alpine-clipboard/-/alpine-clipboard-2.3.0.tgz",
|
||||
"integrity": "sha512-r1YL/LL851vSemjgcca+M6Yz9SNtA9ATul8nJ0n0sAS1W3V1GUWvH0Od2XdQF1r36YJF+/4sUc0eHF/Zexw7dA=="
|
||||
},
|
||||
"node_modules/@tailwindcss/aspect-ratio": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz",
|
||||
"integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==",
|
||||
"peerDependencies": {
|
||||
"tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/forms": {
|
||||
"version": "0.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.6.tgz",
|
||||
"integrity": "sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA==",
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz",
|
||||
"integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"mini-svg-data-uri": "^1.2.3"
|
||||
|
|
@ -505,17 +540,36 @@
|
|||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz",
|
||||
"integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz",
|
||||
"integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA=="
|
||||
},
|
||||
"node_modules/alpinejs": {
|
||||
"version": "3.13.3",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.3.tgz",
|
||||
"integrity": "sha512-WZ6WQjkAOl+WdW/jukzNHq9zHFDNKmkk/x6WF7WdyNDD6woinrfXCVsZXm0galjbco+pEpYmJLtwlZwcOfIVdg==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/any-promise": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
|
||||
"dev": true
|
||||
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
|
||||
},
|
||||
"node_modules/anymatch": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
|
|
@ -527,8 +581,7 @@
|
|||
"node_modules/arg": {
|
||||
"version": "5.0.2",
|
||||
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
||||
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
|
||||
},
|
||||
"node_modules/asynckit": {
|
||||
"version": "0.4.0",
|
||||
|
|
@ -587,14 +640,12 @@
|
|||
"node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
|
||||
},
|
||||
"node_modules/binary-extensions": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -603,7 +654,6 @@
|
|||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -613,7 +663,6 @@
|
|||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
},
|
||||
|
|
@ -657,7 +706,6 @@
|
|||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
||||
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
|
|
@ -686,7 +734,6 @@
|
|||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
|
@ -713,7 +760,6 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
|
|
@ -737,7 +783,6 @@
|
|||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
|
|
@ -745,14 +790,12 @@
|
|||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/cssesc": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"cssesc": "bin/cssesc"
|
||||
},
|
||||
|
|
@ -772,14 +815,12 @@
|
|||
"node_modules/didyoumean": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
|
||||
},
|
||||
"node_modules/dlv": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.549",
|
||||
|
|
@ -837,7 +878,6 @@
|
|||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
|
||||
"integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
|
|
@ -853,7 +893,6 @@
|
|||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.1"
|
||||
},
|
||||
|
|
@ -865,7 +904,6 @@
|
|||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
|
||||
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"reusify": "^1.0.4"
|
||||
}
|
||||
|
|
@ -874,7 +912,6 @@
|
|||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
},
|
||||
|
|
@ -882,6 +919,14 @@
|
|||
"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==",
|
||||
"dependencies": {
|
||||
"tabbable": "^5.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/follow-redirects": {
|
||||
"version": "1.15.3",
|
||||
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.3.tgz",
|
||||
|
|
@ -932,14 +977,12 @@
|
|||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
|
|
@ -953,7 +996,6 @@
|
|||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
|
|
@ -973,7 +1015,6 @@
|
|||
"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,
|
||||
"dependencies": {
|
||||
"is-glob": "^4.0.3"
|
||||
},
|
||||
|
|
@ -985,7 +1026,6 @@
|
|||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
|
||||
"integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
|
|
@ -994,7 +1034,6 @@
|
|||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
|
|
@ -1003,14 +1042,12 @@
|
|||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"node_modules/is-binary-path": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"binary-extensions": "^2.0.0"
|
||||
},
|
||||
|
|
@ -1022,7 +1059,6 @@
|
|||
"version": "2.13.0",
|
||||
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz",
|
||||
"integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"has": "^1.0.3"
|
||||
},
|
||||
|
|
@ -1034,7 +1070,6 @@
|
|||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1043,7 +1078,6 @@
|
|||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
|
|
@ -1055,7 +1089,6 @@
|
|||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.12.0"
|
||||
}
|
||||
|
|
@ -1064,7 +1097,6 @@
|
|||
"version": "1.20.0",
|
||||
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz",
|
||||
"integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"jiti": "bin/jiti.js"
|
||||
}
|
||||
|
|
@ -1089,7 +1121,6 @@
|
|||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
|
|
@ -1097,8 +1128,7 @@
|
|||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
|
||||
},
|
||||
"node_modules/lodash.castarray": {
|
||||
"version": "4.4.0",
|
||||
|
|
@ -1122,7 +1152,6 @@
|
|||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
|
|
@ -1131,7 +1160,6 @@
|
|||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"picomatch": "^2.3.1"
|
||||
|
|
@ -1174,7 +1202,6 @@
|
|||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
|
|
@ -1186,7 +1213,6 @@
|
|||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"any-promise": "^1.0.0",
|
||||
"object-assign": "^4.0.1",
|
||||
|
|
@ -1197,7 +1223,6 @@
|
|||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -1221,7 +1246,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1239,7 +1263,6 @@
|
|||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1248,7 +1271,6 @@
|
|||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
|
|
@ -1257,7 +1279,6 @@
|
|||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
|
@ -1266,7 +1287,6 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1274,20 +1294,17 @@
|
|||
"node_modules/path-parse": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
},
|
||||
|
|
@ -1299,7 +1316,6 @@
|
|||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1308,7 +1324,6 @@
|
|||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
|
|
@ -1317,7 +1332,6 @@
|
|||
"version": "8.4.31",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
|
||||
"integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
|
@ -1345,7 +1359,6 @@
|
|||
"version": "15.1.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
|
||||
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"postcss-value-parser": "^4.0.0",
|
||||
"read-cache": "^1.0.0",
|
||||
|
|
@ -1362,7 +1375,6 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
|
||||
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"camelcase-css": "^2.0.1"
|
||||
},
|
||||
|
|
@ -1381,7 +1393,6 @@
|
|||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
|
||||
"integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lilconfig": "^2.0.5",
|
||||
"yaml": "^2.1.1"
|
||||
|
|
@ -1410,7 +1421,6 @@
|
|||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz",
|
||||
"integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"postcss-selector-parser": "^6.0.11"
|
||||
},
|
||||
|
|
@ -1429,7 +1439,6 @@
|
|||
"version": "6.0.13",
|
||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz",
|
||||
"integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"cssesc": "^3.0.0",
|
||||
"util-deprecate": "^1.0.2"
|
||||
|
|
@ -1441,8 +1450,7 @@
|
|||
"node_modules/postcss-value-parser": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
|
|
@ -1454,7 +1462,6 @@
|
|||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
|
||||
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -1474,7 +1481,6 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"pify": "^2.3.0"
|
||||
}
|
||||
|
|
@ -1483,7 +1489,6 @@
|
|||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"picomatch": "^2.2.1"
|
||||
},
|
||||
|
|
@ -1495,7 +1500,6 @@
|
|||
"version": "1.22.6",
|
||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.6.tgz",
|
||||
"integrity": "sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-core-module": "^2.13.0",
|
||||
"path-parse": "^1.0.7",
|
||||
|
|
@ -1512,7 +1516,6 @@
|
|||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
|
||||
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"iojs": ">=1.0.0",
|
||||
"node": ">=0.10.0"
|
||||
|
|
@ -1538,7 +1541,6 @@
|
|||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
|
||||
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
|
|
@ -1561,7 +1563,6 @@
|
|||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -1570,7 +1571,6 @@
|
|||
"version": "3.34.0",
|
||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.34.0.tgz",
|
||||
"integrity": "sha512-70/LQEZ07TEcxiU2dz51FKaE6hCTWC6vr7FOk3Gr0U60C3shtAN+H+BFr9XlYe5xqf3RA8nrc+VIwzCfnxuXJw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@jridgewell/gen-mapping": "^0.3.2",
|
||||
"commander": "^4.0.0",
|
||||
|
|
@ -1592,7 +1592,6 @@
|
|||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
|
||||
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
|
|
@ -1600,11 +1599,15 @@
|
|||
"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=="
|
||||
},
|
||||
"node_modules/tailwindcss": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz",
|
||||
"integrity": "sha512-A0KgSkef7eE4Mf+nKJ83i75TMyq8HqY3qmFIJSWy8bNt0v1lG7jUcpGpoTFxAwYcWOphcTBLPPJg+bDfhDf52w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@alloc/quick-lru": "^5.2.0",
|
||||
"arg": "^5.0.2",
|
||||
|
|
@ -1641,7 +1644,6 @@
|
|||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"any-promise": "^1.0.0"
|
||||
}
|
||||
|
|
@ -1650,7 +1652,6 @@
|
|||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
||||
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"thenify": ">= 3.1.0 < 4"
|
||||
},
|
||||
|
|
@ -1662,7 +1663,6 @@
|
|||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
|
||||
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-number": "^7.0.0"
|
||||
},
|
||||
|
|
@ -1673,8 +1673,7 @@
|
|||
"node_modules/ts-interface-checker": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.0.13",
|
||||
|
|
@ -1709,8 +1708,7 @@
|
|||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "4.4.11",
|
||||
|
|
@ -1783,14 +1781,12 @@
|
|||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz",
|
||||
"integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
"build": "vite build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.2",
|
||||
"@tailwindcss/typography": "^0.5.0",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"autoprefixer": "^10.4.7",
|
||||
"axios": "^1.1.2",
|
||||
"laravel-vite-plugin": "^0.8.0",
|
||||
|
|
@ -16,6 +16,13 @@
|
|||
"vite": "^4.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@alpinejs/collapse": "^3.13.3",
|
||||
"@alpinejs/focus": "^3.13.3",
|
||||
"@alpinejs/intersect": "^3.13.3",
|
||||
"@alpinejs/ui": "^3.13.3-beta.4",
|
||||
"@ryangjchandler/alpine-clipboard": "^2.3.0",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.2",
|
||||
"alpinejs": "^3.13.3",
|
||||
"tailwindcss": "^3.3.3"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
@import url('https://rsms.me/inter/inter.css');
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
|
||||
[x-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
|||
22
laravel_app/resources/js/alpine.js
Normal file
22
laravel_app/resources/js/alpine.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import { Livewire, Alpine } from '../../vendor/livewire/livewire/dist/livewire.esm';
|
||||
// import Intersect from "@alpinejs/intersect";
|
||||
import focus from "@alpinejs/focus";
|
||||
// import Clipboard from "@ryangjchandler/alpine-clipboard";
|
||||
// import collapse from "@alpinejs/collapse";
|
||||
import ui from "@alpinejs/ui";
|
||||
Alpine.plugin(ui)
|
||||
Alpine.plugin(focus)
|
||||
// Alpine.plugin(Clipboard);
|
||||
// Alpine.plugin(Intersect);
|
||||
// Alpine.plugin(collapse);
|
||||
import htabs from './history-tabs';
|
||||
htabs(Alpine)
|
||||
|
||||
window.Alpine = Alpine
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
console.log("Alpine Initialized")
|
||||
});
|
||||
|
||||
Livewire.start();
|
||||
|
||||
|
|
@ -1 +1,2 @@
|
|||
import './bootstrap';
|
||||
import('./alpine');
|
||||
|
|
|
|||
167
laravel_app/resources/js/history-tabs.js
Normal file
167
laravel_app/resources/js/history-tabs.js
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
|
||||
export default function (Alpine) {
|
||||
Alpine.directive('htabs', (el, directive) => {
|
||||
if (! directive.value) handleRoot(el, Alpine)
|
||||
else if (directive.value === 'list') handleList(el, Alpine)
|
||||
else if (directive.value === 'tab') handleTab(el, Alpine)
|
||||
else if (directive.value === 'panels') handlePanels(el, Alpine)
|
||||
else if (directive.value === 'panel') handlePanel(el, Alpine)
|
||||
}).before('bind')
|
||||
|
||||
Alpine.magic('htab', el => {
|
||||
let $data = Alpine.$data(el)
|
||||
|
||||
return {
|
||||
get isSelected() {
|
||||
return $data.__selectedIndex === $data.__tabs.indexOf($data.__tabEl)
|
||||
},
|
||||
get isDisabled() {
|
||||
return $data.__isDisabled
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
Alpine.magic('hpanel', el => {
|
||||
let $data = Alpine.$data(el)
|
||||
|
||||
return {
|
||||
get isSelected() {
|
||||
return $data.__selectedIndex === $data.__panels.indexOf($data.__panelEl)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleRoot(el, Alpine) {
|
||||
Alpine.bind(el, {
|
||||
'x-modelable': '__selectedIndex',
|
||||
'x-data'() {
|
||||
return {
|
||||
init() {
|
||||
window.addEventListener('popstate', this.__handlePopState.bind(this));
|
||||
|
||||
queueMicrotask(() => {
|
||||
let defaultIndex = this.__selectedIndex || Number(Alpine.bound(this.$el, 'default-index', 0))
|
||||
let tabs = this.__activeTabs()
|
||||
let clamp = (number, min, max) => Math.min(Math.max(number, min), max)
|
||||
|
||||
this.__selectedIndex = clamp(defaultIndex, 0, tabs.length -1)
|
||||
|
||||
Alpine.effect(() => {
|
||||
this.__manualActivation = Alpine.bound(this.$el, 'manual', false)
|
||||
})
|
||||
|
||||
this.__syncTabWithUrl();
|
||||
})
|
||||
},
|
||||
__tabs: [],
|
||||
__panels: [],
|
||||
__selectedIndex: null,
|
||||
__tabGroupEl: undefined,
|
||||
__manualActivation: false,
|
||||
__addTab(el) { this.__tabs.push(el) },
|
||||
__addPanel(el) { this.__panels.push(el) },
|
||||
__selectTab(el) {
|
||||
if (this.__selectedIndex !== this.__tabs.indexOf(el)) {
|
||||
this.__selectedIndex = this.__tabs.indexOf(el)
|
||||
this.__updateUrl();
|
||||
}
|
||||
},
|
||||
__updateUrl() {
|
||||
const selectedTab = this.__tabs[this.__selectedIndex];
|
||||
const tabName = selectedTab.getAttribute('data-tab-name');
|
||||
const url = new URL(window.location);
|
||||
url.searchParams.set('selected-tab', tabName);
|
||||
window.history.pushState({ tabIndex: this.__selectedIndex }, '', url);
|
||||
},
|
||||
|
||||
__handlePopState() {
|
||||
this.__syncTabWithUrl();
|
||||
},
|
||||
|
||||
__syncTabWithUrl() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const tabName = urlParams.get('selected-tab');
|
||||
const tabIndex = this.__tabs.findIndex(tab => tab.getAttribute('data-tab-name') === tabName);
|
||||
this.__selectedIndex = 0;
|
||||
if (tabIndex >= 0) {
|
||||
this.__selectedIndex = tabIndex;
|
||||
}
|
||||
},
|
||||
__activeTabs() {
|
||||
return this.__tabs.filter(i => !i.__disabled)
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function handleList(el, Alpine) {
|
||||
Alpine.bind(el, {
|
||||
'x-init'() { this.$data.__tabGroupEl = this.$el }
|
||||
})
|
||||
}
|
||||
|
||||
function handleTab(el, Alpine) {
|
||||
Alpine.bind(el, {
|
||||
'x-init'() { if (this.$el.tagName.toLowerCase() === 'button' && !this.$el.hasAttribute('type')) this.$el.type = 'button' },
|
||||
'x-data'() { return {
|
||||
init() {
|
||||
this.__tabEl = this.$el
|
||||
this.$data.__addTab(this.$el)
|
||||
this.__tabEl.__disabled = Alpine.bound(this.$el, 'disabled', false)
|
||||
this.__isDisabled = this.__tabEl.__disabled
|
||||
},
|
||||
__tabEl: undefined,
|
||||
__isDisabled: false,
|
||||
}},
|
||||
'@click'() {
|
||||
if (this.$el.__disabled) return
|
||||
|
||||
this.$data.__selectTab(this.$el)
|
||||
|
||||
this.$el.focus()
|
||||
},
|
||||
'@keydown.enter.prevent.stop'() { this.__selectTab(this.$el) },
|
||||
'@keydown.space.prevent.stop'() { this.__selectTab(this.$el) },
|
||||
'@keydown.home.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).first() },
|
||||
'@keydown.page-up.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).first() },
|
||||
'@keydown.end.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).last() },
|
||||
'@keydown.page-down.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).last() },
|
||||
'@keydown.down.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).withWrapAround().next() },
|
||||
'@keydown.right.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).withWrapAround().next() },
|
||||
'@keydown.up.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).withWrapAround().prev() },
|
||||
'@keydown.left.prevent.stop'() { this.$focus.within(this.$data.__activeTabs()).withWrapAround().prev() },
|
||||
':tabindex'() { return this.$tab.isSelected ? 0 : -1 },
|
||||
'@focus'() {
|
||||
if (this.$data.__manualActivation) {
|
||||
this.$el.focus()
|
||||
} else {
|
||||
if (this.$el.__disabled) return
|
||||
this.$data.__selectTab(this.$el)
|
||||
|
||||
this.$el.focus()
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function handlePanels(el, Alpine) {
|
||||
Alpine.bind(el, {
|
||||
//
|
||||
})
|
||||
}
|
||||
|
||||
function handlePanel(el, Alpine) {
|
||||
Alpine.bind(el, {
|
||||
':tabindex'() { return this.$panel.isSelected ? 0 : -1 },
|
||||
'x-data'() { return {
|
||||
init() {
|
||||
this.__panelEl = this.$el
|
||||
this.$data.__addPanel(this.$el)
|
||||
},
|
||||
__panelEl: undefined,
|
||||
}},
|
||||
'x-show'() { return this.$panel.isSelected },
|
||||
})
|
||||
}
|
||||
27
laravel_app/resources/views/components/badge.blade.php
Normal file
27
laravel_app/resources/views/components/badge.blade.php
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
@props([
|
||||
'status' => 'success',
|
||||
])
|
||||
<?php
|
||||
|
||||
// Define a mapping of status to its corresponding colors
|
||||
$statusToColors = [
|
||||
'success' => ['bg' => 'bg-green-100', 'text' => 'text-green-700'],
|
||||
'error' => ['bg' => 'bg-red-100', 'text' => 'text-red-700'],
|
||||
'warning' => ['bg' => 'bg-yellow-100', 'text' => 'text-yellow-800'],
|
||||
'info' => ['bg' => 'bg-blue-100', 'text' => 'text-blue-700'],
|
||||
'pending' => ['bg' => 'bg-gray-100', 'text' => 'text-gray-600'],
|
||||
];
|
||||
|
||||
// Default to 'success' if the provided status is not in the defined array
|
||||
if (!array_key_exists($status, $statusToColors)) {
|
||||
$status = 'success';
|
||||
}
|
||||
|
||||
// Get the color class for the given status
|
||||
$colorClasses = $statusToColors[$status];
|
||||
|
||||
?>
|
||||
|
||||
<span {{ $attributes }} class="inline-flex items-center rounded-md {{ $colorClasses['bg'] }} px-1.5 py-0.5 text-xs font-medium {{ $colorClasses['text'] }}">
|
||||
{{ $status }}
|
||||
</span>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
@props([
|
||||
'formData',
|
||||
/** @var \App\Livewire\Projects\ProjectManager */
|
||||
'reportManager'
|
||||
])
|
||||
|
||||
<x-modal wire:model.live="showReportModal" {{ $attributes }} >
|
||||
<x-form-modal submit="saveProjectReport" wire:loading.class="opacity-50">
|
||||
<x-slot name="title">
|
||||
{{ __('Project') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
{{ __('Report generator for generating reports') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="year" value="{{ __('Year') }}"/>
|
||||
<x-input id="year" type="text" class="mt-1 block w-full" wire:model.live="formData.year" autofocus/>
|
||||
<x-input-error for="formData.year" class="mt-2"/>
|
||||
</div><div class="col-span-6 sm:col-span-4">
|
||||
<x-label for="week" value="{{ __('Week') }}"/>
|
||||
<x-input id="week" type="text" class="mt-1 block w-full" wire:model.live="formData.week" autofocus/>
|
||||
<x-input-error for="formData.week" class="mt-2"/>
|
||||
<x-input-error for="formData" class="mt-2"/>
|
||||
</div>
|
||||
<div>
|
||||
<span class="whitespace-nowrap">{!! $reportManager->dateRange !!}</span>
|
||||
</div>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="actions">
|
||||
<x-action-message class="mr-3" on="saved">
|
||||
{{ __('Saved.') }}
|
||||
</x-action-message>
|
||||
|
||||
<x-secondary-button class="mr-3"
|
||||
type="button"
|
||||
x-on:click="$wire.showReportModal = false"
|
||||
>
|
||||
{{ __('Cancel') }}
|
||||
</x-secondary-button>
|
||||
<x-button wire:loading.disabled>
|
||||
{{ __('Save') }}
|
||||
</x-button>
|
||||
|
||||
</x-slot>
|
||||
</x-form-modal>
|
||||
</x-modal>
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
<div>
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('download.download-grid')
|
||||
<livewire:download.download-grid :project="$project" />
|
||||
</div>
|
||||
<x-section-border />
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@
|
|||
@endif
|
||||
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
<main class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
{{ $slot }}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@stack('modals')
|
||||
|
||||
@livewireScripts
|
||||
@livewireScriptConfig
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
<!-- API Token List -->
|
||||
<x-slot name="content">
|
||||
<div class="space-y-6">
|
||||
@foreach ($directories as $directory)
|
||||
@foreach ($files as $file)
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="break-all">
|
||||
{!! Illuminate\Support\Carbon::parse($directory)->format('Y-m-d') !!}
|
||||
{{ $file }}
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
<tr>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $report->name }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
@if($report->status == 'pending')
|
||||
<x-badge status="pending" wire:poll.1s=""></x-badge>
|
||||
@else
|
||||
<x-badge :status="$report->status"></x-badge>
|
||||
@endif
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
lindsay.walton@example.com
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">Member</td>
|
||||
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
||||
@if($report->status === 'success')
|
||||
<x-button wire:click="download">Download</x-button>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<x-slot name="form">
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8">
|
||||
<div class="mt-10 sm:mt-0">
|
||||
@livewire('download.download-grid')
|
||||
<livewire:download.download-grid :project="$project"/>
|
||||
</div>
|
||||
<x-section-border />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,52 @@
|
|||
<x-tab-section>
|
||||
<x-slot name="title">Report Details</x-slot>
|
||||
<x-slot name="description">..</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div>
|
||||
|
||||
|
||||
</x-slot>
|
||||
</x-tab-section>
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:items-center">
|
||||
<div class="sm:flex-auto">
|
||||
<h1 class="text-base font-semibold leading-6 text-gray-900">Reports</h1>
|
||||
<p class="mt-2 text-sm text-gray-700"></p>
|
||||
</div>
|
||||
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
||||
<x-button wire:click="openCreateReportModal"
|
||||
class="block rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
|
||||
Create Report
|
||||
</x-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 flow-root">
|
||||
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div class="inline-block min-w-full py-2 align-middle">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">
|
||||
Name
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Status
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Email
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Role
|
||||
</th>
|
||||
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8">
|
||||
<span class="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
@foreach($project->reports()->orderBy('created_at', 'desc')->get() as $report)
|
||||
<livewire:project.report-row :$report :key="$report->id"/>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<x-report-manager-properties-modal :reportManager="$this"/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ class="col-span-6 sm:col-span-4 mt-4 px-4 py-4 font-mono overflow-hidden break-w
|
|||
|
||||
<x-section-border />
|
||||
|
||||
<!-- Manage API Tokens -->
|
||||
<div class="mt-10 sm:mt-0">
|
||||
<x-action-section>
|
||||
<x-slot name="title">
|
||||
|
|
@ -71,7 +70,6 @@ class="col-span-6 sm:col-span-4 mt-4 px-4 py-4 font-mono overflow-hidden break-w
|
|||
|
||||
|
||||
|
||||
<!-- Delete Token Report Modal -->
|
||||
<x-confirmation-modal wire:model.live="confirmingReportDeletion">
|
||||
<x-slot name="title">
|
||||
{{ __('Delete Report') }}
|
||||
|
|
|
|||
|
|
@ -5,64 +5,37 @@
|
|||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div>
|
||||
<div class="max-w-7xl mx-auto py-10 sm:px-6 lg:px-8" x-data="{openTab: 1}">
|
||||
|
||||
<div class="mt-10 sm:mt-0">
|
||||
<div class="flex w-full space-x-6 mb-5 border-b border-secondary max-h-[50px]" selid="tabs">
|
||||
<div :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 1}" selid="tab-question">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 1"
|
||||
>
|
||||
<span>{{ __('Mailing') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="" :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 2}"
|
||||
selid="tab-settings">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 2;"
|
||||
>
|
||||
<span>{{ __('Downloads') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="" :class="{'border-b-2 border-indigo-500 -mb-px text-indigo-500' : openTab === 3}"
|
||||
selid="tab-statistics">
|
||||
<button
|
||||
style="color:inherit"
|
||||
x-on:click="openTab = 3;"
|
||||
>
|
||||
<span>{{ __('Reports') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
<div x-data x-htabs class="flex">
|
||||
<div x-tabs:list class="-mr-px flex items-stretch flex-col">
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="downloads"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Downloads') }}</button>
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="mailing"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Mailing') }}</button>
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="reports"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Reports') }}</button>
|
||||
</div>
|
||||
|
||||
<div x-tabs:panels class="rounded-b-md border border-gray-200 bg-white w-full">
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.download-manager :project="$project" />
|
||||
</section>
|
||||
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 2"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.download-manager', ['project' => $project]);
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 1"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.mailing-manager', ['project' => $project]);
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.mailing-manager :project="$project" />
|
||||
</section>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col flex-1 pb-5 space-y-4 relative" x-show="openTab === 3"
|
||||
x-transition:enter="transition duration-200"
|
||||
x-transition:enter-start="opacity-0 delay-200"
|
||||
x-transition:enter-end="opacity-100"
|
||||
>
|
||||
@livewire('projects.report-manager', ['project' => $project]);
|
||||
</div>
|
||||
</div>
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.report-manager :project="$project" />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
|
|
|||
|
|
@ -29,9 +29,9 @@
|
|||
Route::get('/dashboard', function () {
|
||||
return view('dashboard');
|
||||
})->name('dashboard');
|
||||
|
||||
Route::get('/download', [\App\Http\Controllers\DownloadController::class, 'show'])->name('download');
|
||||
Route::get('/report', [\App\Http\Controllers\ReportController::class, 'index'])->name('report');
|
||||
Route::get('/projects/{project}', [\App\Http\Controllers\ProjectController::class, 'show'])->name('project.show');
|
||||
Route::get('/projects/{projectReport}/download', [\App\Http\Controllers\ProjectReportController::class, 'download'])->name('project.report.download');
|
||||
Route::get('/projects', [\App\Http\Controllers\ProjectController::class, 'index'])->name('project');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ export default {
|
|||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Figtree', ...defaultTheme.fontFamily.sans],
|
||||
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
102
laravel_app/tests/Unit/Models/ProjectReportTest.php
Normal file
102
laravel_app/tests/Unit/Models/ProjectReportTest.php
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Models;
|
||||
|
||||
use App\Models\Project;
|
||||
|
||||
use App\Models\ProjectReport;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProjectReportTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp(); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider weeksAgoProvider
|
||||
*/
|
||||
public function it_can_calculatore_weeksAgo($year, $week, $expected)
|
||||
{
|
||||
Carbon::setTestNow(Carbon::now()->setISODate('2021', '41'));
|
||||
$projectReport = ProjectReport::make([
|
||||
'year' => $year,
|
||||
'week' => $week,
|
||||
]);
|
||||
$this->assertEquals($expected, $projectReport->weeksAgo());
|
||||
}
|
||||
|
||||
public static function weeksAgoProvider()
|
||||
{
|
||||
return [
|
||||
'1 week ago' => [2021, 40, 1],
|
||||
'2 weeks ago' => [2021, 39, 2],
|
||||
'3 weeks ago' => [2021, 38, 3],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_can_get_the_full_path_name()
|
||||
{
|
||||
$project = Project::create([
|
||||
'name' => 'project_name',
|
||||
'download_path' => 'project_download_path',
|
||||
]);
|
||||
$projectReport = $project->reports()->create([
|
||||
'name' => 'name',
|
||||
'year' => 2021,
|
||||
'week' => 41,
|
||||
'path' => 'path/doc.pdf',
|
||||
'status' => 'success',
|
||||
]);
|
||||
$this->assertEquals(storage_path('app/project_download_path/path/doc.pdf'), $projectReport->getFullPathName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider reportDateProvider
|
||||
*/
|
||||
public function it_can_return_the_reportDate($expected, $mail_day, $week, $year)
|
||||
{
|
||||
$project = Project::create([
|
||||
'name' => 'project_name',
|
||||
'download_path' => 'project_download_path',
|
||||
'mail_day' => $mail_day,
|
||||
]);
|
||||
$projectReport = $project->reports()->create([
|
||||
'name' => 'name',
|
||||
'year' => $year,
|
||||
'week' => $week,
|
||||
'path' => 'path/doc.pdf',
|
||||
'status' => 'success',
|
||||
]);
|
||||
$this->assertEquals($expected, $projectReport->getReportDate());
|
||||
}
|
||||
|
||||
|
||||
public static function reportDateProvider()
|
||||
{
|
||||
return [
|
||||
'monday' => ['2023-12-10' , 'monday', 50, 2023],
|
||||
'tuesday' => ['2023-12-11' , 'tuesday', 50, 2023],
|
||||
'wednesday' => ['2023-12-12' , 'wednesday', 50, 2023],
|
||||
'thursday' => ['2023-12-13' , 'thursday', 50, 2023],
|
||||
'friday' => ['2023-12-14' , 'friday', 50, 2023],
|
||||
'saturday' => ['2023-12-15' , 'saturday', 50, 2023],
|
||||
'sunday' => ['2023-12-16' , 'sunday', 50, 2023],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
use App\Models\Project;
|
||||
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ProjectTest extends TestCase
|
||||
|
|
@ -48,4 +50,98 @@ public function when_running_the_seeder_their_are_three_projects(): void
|
|||
$this->seed();
|
||||
$this->assertCount(3, Project::all());
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function when_running_the_seeder_their_are_three_projects_with_the_correct_names(): void
|
||||
{
|
||||
$this->seed();
|
||||
$this->assertEquals('Chemba', Project::find(1)->name);
|
||||
$this->assertEquals('Xinavane', Project::find(2)->name);
|
||||
$this->assertEquals('Kakira', Project::find(3)->name);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function when_running_the_seeder_their_are_three_projects_with_the_correct_download_paths(): void
|
||||
{
|
||||
$this->seed();
|
||||
$this->assertEquals('chemba', Project::find(1)->download_path);
|
||||
$this->assertEquals('xinavane', Project::find(2)->download_path);
|
||||
$this->assertEquals('kakira', Project::find(3)->download_path);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function when_not_all_mosaics_are_present_it_should_return_an_exception()
|
||||
{
|
||||
|
||||
$this->seed();
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('Missing mosaics: week_52_2022.tif, week_51_2021.tif, week_50_2021.tif, week_49_2021.tif');
|
||||
$project = Project::find(1);
|
||||
$lastDate = Carbon::parse('2022-01-01');
|
||||
//$lastDate->getWeekOfYear();
|
||||
$project->allMosaicsPresent($lastDate);
|
||||
}
|
||||
/** @test */
|
||||
public function when_all_mosaics_are_present_it_should_return_true()
|
||||
{
|
||||
$project = Mockery::mock(Project::class)->makePartial();
|
||||
$lastDate = Carbon::parse('2021-01-01');
|
||||
$project->shouldReceive('getMosaicList')->andReturn(
|
||||
collect([
|
||||
"chemba/weekly_mosaic/week_53_2020.tif",
|
||||
"chemba/weekly_mosaic/week_52_2020.tif",
|
||||
"chemba/weekly_mosaic/week_51_2020.tif",
|
||||
"chemba/weekly_mosaic/week_50_2020.tif",
|
||||
]));
|
||||
|
||||
$this->assertTrue($project->allMosaicsPresent($lastDate));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function when_not_mosaics_are_present_it_should_throw_an_exception_listing_the_missing_mosiacs()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('Missing mosaics: week_53_2020.tif');
|
||||
$project = Mockery::mock(Project::class)->makePartial();
|
||||
$lastDate = Carbon::parse('2021-01-01');
|
||||
$project->shouldReceive('getMosaicList')->andReturn(
|
||||
collect([
|
||||
"chemba/weekly_mosaic/week_52_2020.tif",
|
||||
"chemba/weekly_mosaic/week_51_2020.tif",
|
||||
"chemba/weekly_mosaic/week_50_2020.tif",
|
||||
"chemba/weekly_mosaic/week_49_2021.tif",
|
||||
"chemba/weekly_mosaic/week_48_2021.tif",
|
||||
]));
|
||||
|
||||
$project->allMosaicsPresent($lastDate);
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function when_all_mosaics_are_present_is_called_with_future_date_it_should_throw_an_expection()
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('End date is in the future');
|
||||
$this->seed();
|
||||
$project = Project::find(1);
|
||||
Carbon::setTestNow(Carbon::parse('2020-01-01'));
|
||||
$lastDate = Carbon::parse('2021-01-01');
|
||||
// stub getMosiacList() to return a list containing four filenames;
|
||||
($project->allMosaicsPresent($lastDate));
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function getMosiacFileListByEndDate_should_return_four_filenames()
|
||||
{
|
||||
$this->seed();
|
||||
$project = Project::find(1);
|
||||
$lastDate = Carbon::parse('2021-01-01');
|
||||
$list = $project->getMosiacFilenameListByEndDate($lastDate);
|
||||
$this->assertCount(4, $list);
|
||||
$this->assertEquals([
|
||||
"week_53_2020.tif",
|
||||
"week_52_2020.tif",
|
||||
"week_51_2020.tif",
|
||||
"week_50_2020.tif",
|
||||
], $list->toArray());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue