From 39b464388c323c99501e36d670a05aa58fed0f49 Mon Sep 17 00:00:00 2001 From: Adrian Hopek Date: Mon, 21 Feb 2022 16:09:45 +0100 Subject: [PATCH] #39 - generate timesheet (#56) * #39 - wip * #39 - fix * #39 - wip * #39 - wip * #39 - wip * Update app/Domain/Enums/Month.php Co-authored-by: Marcin Tracz * #39 - cr fixes Co-authored-by: EwelinaLasowy Co-authored-by: Marcin Tracz --- app/Domain/CalendarGenerator.php | 28 +- app/Domain/Enums/Month.php | 53 ++ app/Domain/TimesheetExport.php | 37 + app/Domain/TimesheetPerUserSheet.php | 222 ++++++ .../Http/Controllers/TimesheetController.php | 35 + .../VacationCalendarController.php | 14 +- composer.json | 1 + composer.lock | 696 +++++++++++++++--- config/excel.php | 104 +++ resources/js/Pages/Calendar.vue | 27 +- resources/lang/pl.json | 6 + routes/web.php | 5 +- 12 files changed, 1085 insertions(+), 143 deletions(-) create mode 100644 app/Domain/Enums/Month.php create mode 100644 app/Domain/TimesheetExport.php create mode 100644 app/Domain/TimesheetPerUserSheet.php create mode 100644 app/Infrastructure/Http/Controllers/TimesheetController.php create mode 100644 config/excel.php diff --git a/app/Domain/CalendarGenerator.php b/app/Domain/CalendarGenerator.php index f1d72f2..052e10c 100644 --- a/app/Domain/CalendarGenerator.php +++ b/app/Domain/CalendarGenerator.php @@ -4,9 +4,8 @@ declare(strict_types=1); namespace Toby\Domain; -use Carbon\CarbonImmutable; -use Carbon\CarbonInterface; use Carbon\CarbonPeriod; +use Illuminate\Support\Carbon; use Illuminate\Support\Collection; use Toby\Domain\Enums\VacationRequestState; use Toby\Eloquent\Helpers\YearPeriodRetriever; @@ -20,33 +19,16 @@ class CalendarGenerator ) { } - public function generate(YearPeriod $yearPeriod, string $month): array + public function generate(Carbon $month): array { - $date = CarbonImmutable::create($yearPeriod->year, $this->monthNameToNumber($month)); - $period = CarbonPeriod::create($date->startOfMonth(), $date->endOfMonth()); + $period = CarbonPeriod::create($month->copy()->startOfMonth(), $month->copy()->endOfMonth()); + $yearPeriod = YearPeriod::findByYear($month->year); + $holidays = $yearPeriod->holidays()->pluck("date"); return $this->generateCalendar($period, $holidays); } - protected function monthNameToNumber($name): int - { - return match ($name) { - default => CarbonInterface::JANUARY, - "february" => CarbonInterface::FEBRUARY, - "march" => CarbonInterface::MARCH, - "april" => CarbonInterface::APRIL, - "may" => CarbonInterface::MAY, - "june" => CarbonInterface::JUNE, - "july" => CarbonInterface::JULY, - "august" => CarbonInterface::AUGUST, - "september" => CarbonInterface::SEPTEMBER, - "october" => CarbonInterface::OCTOBER, - "november" => CarbonInterface::NOVEMBER, - "december" => CarbonInterface::DECEMBER, - }; - } - protected function generateCalendar(CarbonPeriod $period, Collection $holidays): array { $calendar = []; diff --git a/app/Domain/Enums/Month.php b/app/Domain/Enums/Month.php new file mode 100644 index 0000000..a6d2921 --- /dev/null +++ b/app/Domain/Enums/Month.php @@ -0,0 +1,53 @@ + CarbonInterface::JANUARY, + self::February => CarbonInterface::FEBRUARY, + self::March => CarbonInterface::MARCH, + self::April => CarbonInterface::APRIL, + self::May => CarbonInterface::MAY, + self::June => CarbonInterface::JUNE, + self::July => CarbonInterface::JULY, + self::August => CarbonInterface::AUGUST, + self::September => CarbonInterface::SEPTEMBER, + self::October => CarbonInterface::OCTOBER, + self::November => CarbonInterface::NOVEMBER, + self::December => CarbonInterface::DECEMBER, + }; + } + + public static function current(): Month + { + return Month::from(Str::lower(Carbon::now()->englishMonth)); + } + + public static function fromNameOrCurrent(string $name): Month + { + return Month::tryFrom($name) ?? Month::current(); + } +} diff --git a/app/Domain/TimesheetExport.php b/app/Domain/TimesheetExport.php new file mode 100644 index 0000000..f0ed480 --- /dev/null +++ b/app/Domain/TimesheetExport.php @@ -0,0 +1,37 @@ +users + ->map(fn(User $user) => new TimesheetPerUserSheet($user, $this->month)) + ->toArray(); + } + + public function forUsers(Collection $users): static + { + $this->users = $users; + + return $this; + } + + public function forMonth(Carbon $month): static + { + $this->month = $month; + + return $this; + } +} diff --git a/app/Domain/TimesheetPerUserSheet.php b/app/Domain/TimesheetPerUserSheet.php new file mode 100644 index 0000000..7563473 --- /dev/null +++ b/app/Domain/TimesheetPerUserSheet.php @@ -0,0 +1,222 @@ +user->fullName; + } + + public function headings(): array + { + $types = VacationType::cases(); + + $headings = [ + __("Date"), + __("Day of week"), + __("Start date"), + __("End date"), + __("Worked hours"), + ]; + + foreach ($types as $type) { + $headings[] = $type->label(); + } + + return $headings; + } + + public function generator(): Generator + { + $period = CarbonPeriod::create($this->month->copy()->startOfMonth(), $this->month->copy()->endOfMonth()); + $vacations = $this->getVacationsForPeriod($this->user, $period); + $holidays = $this->getHolidaysForPeriod($period); + + foreach ($period as $day) { + $vacationsForDay = $vacations->get($day->toDateString(), new Collection()); + $workedThisDay = $this->checkIfWorkedThisDay($day, $holidays, $vacationsForDay); + + $row = [ + Date::dateTimeToExcel($day), + $day->translatedFormat("l"), + $workedThisDay ? $this->toExcelTime(Carbon::createFromTime(static::START_HOUR)) : null, + $workedThisDay ? $this->toExcelTime(Carbon::createFromTime(static::END_HOUR)) : null, + $workedThisDay ? static::HOURS_PER_DAY : null, + ]; + + foreach (VacationType::cases() as $type) { + $row[] = $vacationsForDay->has($type->value) ? static::HOURS_PER_DAY : null; + } + + yield $row; + } + } + + public function styles(Worksheet $sheet): void + { + $lastRow = $sheet->getHighestRow(); + $lastColumn = $sheet->getHighestColumn(); + + $sheet->getStyle("A1:{$lastColumn}1") + ->getFont()->setBold(true); + + $sheet->getStyle("A1:{$lastColumn}1") + ->getAlignment() + ->setVertical(Alignment::VERTICAL_CENTER); + + $sheet->getStyle("A1:{$lastColumn}1") + ->getFill() + ->setFillType(Fill::FILL_SOLID) + ->getStartColor() + ->setRGB("D9D9D9"); + + $sheet->getStyle("C1:{$lastColumn}{$lastRow}") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $sheet->getStyle("A2:A{$lastRow}") + ->getNumberFormat() + ->setFormatCode(NumberFormat::FORMAT_DATE_DDMMYYYY); + + $sheet->getStyle("C1:D{$lastRow}") + ->getNumberFormat() + ->setFormatCode(NumberFormat::FORMAT_DATE_TIME3); + + $sheet->getStyle("A2:A{$lastRow}") + ->getFont() + ->setBold(true); + + for ($i = 2; $i < $lastRow; $i++) { + $date = Date::excelToDateTimeObject($sheet->getCell("A{$i}")->getValue()); + + if (Carbon::createFromInterface($date)->isWeekend()) { + $sheet->getStyle("A{$i}:{$lastColumn}{$i}") + ->getFill() + ->setFillType(Fill::FILL_SOLID) + ->getStartColor() + ->setRGB("FEE2E2"); + } + } + + $sheet->getStyle("A1:{$lastColumn}{$lastRow}") + ->getBorders() + ->getAllBorders() + ->setBorderStyle(Border::BORDER_THIN) + ->getColor() + ->setRGB("B7B7B7"); + } + + public static function afterSheet(AfterSheet $event): void + { + $sheet = $event->getSheet(); + $lastRow = $sheet->getDelegate()->getHighestRow(); + + $sheet->append([ + __("Sum:"), + null, + null, + null, + "=SUM(E2:E{$lastRow})", + ]); + + $lastRow++; + + $sheet->getDelegate()->getStyle("A{$lastRow}") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_RIGHT); + + $sheet->getDelegate()->getStyle("A{$lastRow}") + ->getFont() + ->setBold(true); + + $sheet->getDelegate()->getStyle("E{$lastRow}") + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_CENTER); + + $sheet->getDelegate()->mergeCells("A{$lastRow}:D{$lastRow}"); + + $sheet->getDelegate()->getStyle("A{$lastRow}:E{$lastRow}") + ->getBorders() + ->getAllBorders() + ->setBorderStyle(Border::BORDER_THIN) + ->getColor() + ->setRGB("B7B7B7"); + } + + protected function getVacationsForPeriod(User $user, CarbonPeriod $period): Collection + { + return $user->vacations() + ->with("vacationRequest") + ->whereBetween("date", [$period->start, $period->end]) + ->whereRelation("vacationRequest", "state", VacationRequestState::Approved->value) + ->get() + ->groupBy( + [ + fn(Vacation $vacation) => $vacation->date->toDateString(), + fn(Vacation $vacation) => $vacation->vacationRequest->type->value, + ], + ); + } + + protected function getHolidaysForPeriod(CarbonPeriod $period): Collection + { + return Holiday::query() + ->whereBetween("date", [$period->start, $period->end]) + ->pluck("date"); + } + + protected function toExcelTime(Carbon $time): float + { + $excelTimestamp = Date::dateTimeToExcel($time); + $excelDate = floor($excelTimestamp); + + return $excelTimestamp - $excelDate; + } + + protected function checkIfWorkedThisDay(CarbonInterface $day, Collection $holidays, Collection $vacations): bool + { + return $day->isWeekday() && $holidays->doesntContain($day) && $vacations->isEmpty(); + } +} diff --git a/app/Infrastructure/Http/Controllers/TimesheetController.php b/app/Infrastructure/Http/Controllers/TimesheetController.php new file mode 100644 index 0000000..9f7fcd7 --- /dev/null +++ b/app/Infrastructure/Http/Controllers/TimesheetController.php @@ -0,0 +1,35 @@ +selected(); + $carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber()); + + $users = User::query() + ->orderBy("last_name") + ->orderBy("first_name") + ->get(); + + $filename = "{$carbonMonth->translatedFormat("F Y")}.xlsx"; + + $timesheet = (new TimesheetExport()) + ->forMonth($carbonMonth) + ->forUsers($users); + + return Excel::download($timesheet, $filename); + } +} diff --git a/app/Infrastructure/Http/Controllers/VacationCalendarController.php b/app/Infrastructure/Http/Controllers/VacationCalendarController.php index d37cce6..ec7a33a 100644 --- a/app/Infrastructure/Http/Controllers/VacationCalendarController.php +++ b/app/Infrastructure/Http/Controllers/VacationCalendarController.php @@ -4,11 +4,10 @@ declare(strict_types=1); namespace Toby\Infrastructure\Http\Controllers; -use Illuminate\Http\Request; use Illuminate\Support\Carbon; -use Illuminate\Support\Str; use Inertia\Response; use Toby\Domain\CalendarGenerator; +use Toby\Domain\Enums\Month; use Toby\Eloquent\Helpers\YearPeriodRetriever; use Toby\Eloquent\Models\User; use Toby\Infrastructure\Http\Resources\UserResource; @@ -16,22 +15,25 @@ use Toby\Infrastructure\Http\Resources\UserResource; class VacationCalendarController extends Controller { public function index( - Request $request, YearPeriodRetriever $yearPeriodRetriever, CalendarGenerator $calendarGenerator, + ?string $month = null, ): Response { - $month = Str::lower($request->query("month", Carbon::now()->englishMonth)); + $month = Month::fromNameOrCurrent((string)$month); + $yearPeriod = $yearPeriodRetriever->selected(); + $carbonMonth = Carbon::create($yearPeriod->year, $month->toCarbonNumber()); + $users = User::query() ->orderBy("last_name") ->orderBy("first_name") ->get(); - $calendar = $calendarGenerator->generate($yearPeriod, $month); + $calendar = $calendarGenerator->generate($carbonMonth); return inertia("Calendar", [ "calendar" => $calendar, - "currentMonth" => $month, + "currentMonth" => $month->value, "users" => UserResource::collection($users), ]); } diff --git a/composer.json b/composer.json index 92a4bdb..5c28597 100644 --- a/composer.json +++ b/composer.json @@ -18,6 +18,7 @@ "laravel/telescope": "^4.6", "laravel/tinker": "^2.5", "lasserafn/php-initial-avatar-generator": "^4.2", + "maatwebsite/excel": "^3.1", "spatie/laravel-google-calendar": "^3.5" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 6733691..bf41929 100644 --- a/composer.lock +++ b/composer.lock @@ -4,64 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c0f36b87659921d0b7db0464b5d79ed5", + "content-hash": "09609461b05d589abb8bc0cbac9c653c", "packages": [ - { - "name": "asm89/stack-cors", - "version": "v2.1.1", - "source": { - "type": "git", - "url": "https://github.com/asm89/stack-cors.git", - "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/asm89/stack-cors/zipball/73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", - "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", - "shasum": "" - }, - "require": { - "php": "^7.2|^8.0", - "symfony/http-foundation": "^4|^5|^6", - "symfony/http-kernel": "^4|^5|^6" - }, - "require-dev": { - "phpunit/phpunit": "^7|^9", - "squizlabs/php_codesniffer": "^3.5" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.1-dev" - } - }, - "autoload": { - "psr-4": { - "Asm89\\Stack\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Alexander", - "email": "iam.asm89@gmail.com" - } - ], - "description": "Cross-origin resource sharing library and stack middleware", - "homepage": "https://github.com/asm89/stack-cors", - "keywords": [ - "cors", - "stack" - ], - "support": { - "issues": "https://github.com/asm89/stack-cors/issues", - "source": "https://github.com/asm89/stack-cors/tree/v2.1.1" - }, - "time": "2022-01-18T09:12:03+00:00" - }, { "name": "azuyalabs/yasumi", "version": "2.5.0", @@ -709,6 +653,57 @@ ], "time": "2021-10-11T09:18:27+00:00" }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.14.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/12ab42bd6e742c70c0a52f7b82477fcd44e64b75", + "reference": "12ab42bd6e742c70c0a52f7b82477fcd44e64b75", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "HTMLPurifier": "library/" + }, + "files": [ + "library/HTMLPurifier.composer.php" + ], + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.14.0" + }, + "time": "2021-12-25T01:21:49+00:00" + }, { "name": "firebase/php-jwt", "version": "v5.5.1", @@ -768,25 +763,23 @@ }, { "name": "fruitcake/laravel-cors", - "version": "v2.0.5", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/fruitcake/laravel-cors.git", - "reference": "3a066e5cac32e2d1cdaacd6b961692778f37b5fc" + "reference": "361d71f00a0eea8b74da26ae75d0d207c53aa5b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/3a066e5cac32e2d1cdaacd6b961692778f37b5fc", - "reference": "3a066e5cac32e2d1cdaacd6b961692778f37b5fc", + "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/361d71f00a0eea8b74da26ae75d0d207c53aa5b3", + "reference": "361d71f00a0eea8b74da26ae75d0d207c53aa5b3", "shasum": "" }, "require": { - "asm89/stack-cors": "^2.0.1", + "fruitcake/php-cors": "^1", "illuminate/contracts": "^6|^7|^8|^9", "illuminate/support": "^6|^7|^8|^9", - "php": ">=7.2", - "symfony/http-foundation": "^4|^5|^6", - "symfony/http-kernel": "^4.3.4|^5|^6" + "php": ">=7.2" }, "require-dev": { "laravel/framework": "^6|^7.24|^8", @@ -797,7 +790,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-master": "2.1-dev" }, "laravel": { "providers": [ @@ -833,7 +826,7 @@ ], "support": { "issues": "https://github.com/fruitcake/laravel-cors/issues", - "source": "https://github.com/fruitcake/laravel-cors/tree/v2.0.5" + "source": "https://github.com/fruitcake/laravel-cors/tree/v2.1.0" }, "funding": [ { @@ -845,7 +838,78 @@ "type": "github" } ], - "time": "2022-01-03T14:53:04+00:00" + "time": "2022-02-19T14:17:28+00:00" + }, + { + "name": "fruitcake/php-cors", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/php-cors.git", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/php-cors/zipball/58571acbaa5f9f462c9c77e911700ac66f446d4e", + "reference": "58571acbaa5f9f462c9c77e911700ac66f446d4e", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "symfony/http-foundation": "^4.4|^5.4|^6" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "phpunit/phpunit": "^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barryvdh", + "email": "barryvdh@gmail.com" + } + ], + "description": "Cross-origin resource sharing library for the Symfony HttpFoundation", + "homepage": "https://github.com/fruitcake/php-cors", + "keywords": [ + "cors", + "laravel", + "symfony" + ], + "support": { + "issues": "https://github.com/fruitcake/php-cors/issues", + "source": "https://github.com/fruitcake/php-cors/tree/v1.2.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2022-02-20T15:07:15+00:00" }, { "name": "google/apiclient", @@ -920,7 +984,7 @@ }, { "name": "google/apiclient-services", - "version": "v0.235.0", + "version": "v0.236.0", "source": { "type": "git", "url": "https://github.com/googleapis/google-api-php-client-services.git", @@ -958,7 +1022,7 @@ ], "support": { "issues": "https://github.com/googleapis/google-api-php-client-services/issues", - "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.235.0" + "source": "https://github.com/googleapis/google-api-php-client-services/tree/v0.236.0" }, "time": "2022-02-07T14:04:26+00:00" }, @@ -1437,12 +1501,12 @@ } }, "autoload": { - "psr-4": { - "Inertia\\": "src" - }, "files": [ "./helpers.php" - ] + ], + "psr-4": { + "Inertia\\": "src" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2632,6 +2696,262 @@ }, "time": "2021-08-15T23:05:49+00:00" }, + { + "name": "maatwebsite/excel", + "version": "3.1.36", + "source": { + "type": "git", + "url": "https://github.com/SpartnerNL/Laravel-Excel.git", + "reference": "eb31f30d72c51c3fb11644b636945accbe50404f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SpartnerNL/Laravel-Excel/zipball/eb31f30d72c51c3fb11644b636945accbe50404f", + "reference": "eb31f30d72c51c3fb11644b636945accbe50404f", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/support": "5.8.*|^6.0|^7.0|^8.0|^9.0", + "php": "^7.0|^8.0", + "phpoffice/phpspreadsheet": "^1.18" + }, + "require-dev": { + "orchestra/testbench": "^6.0|^7.0", + "predis/predis": "^1.1" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Maatwebsite\\Excel\\ExcelServiceProvider" + ], + "aliases": { + "Excel": "Maatwebsite\\Excel\\Facades\\Excel" + } + } + }, + "autoload": { + "psr-4": { + "Maatwebsite\\Excel\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Patrick Brouwers", + "email": "patrick@spartner.nl" + } + ], + "description": "Supercharged Excel exports and imports in Laravel", + "keywords": [ + "PHPExcel", + "batch", + "csv", + "excel", + "export", + "import", + "laravel", + "php", + "phpspreadsheet" + ], + "support": { + "issues": "https://github.com/SpartnerNL/Laravel-Excel/issues", + "source": "https://github.com/SpartnerNL/Laravel-Excel/tree/3.1.36" + }, + "funding": [ + { + "url": "https://laravel-excel.com/commercial-support", + "type": "custom" + }, + { + "url": "https://github.com/patrickbrouwers", + "type": "github" + } + ], + "time": "2022-01-27T18:34:20+00:00" + }, + { + "name": "maennchen/zipstream-php", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/maennchen/ZipStream-PHP.git", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/c4c5803cc1f93df3d2448478ef79394a5981cc58", + "reference": "c4c5803cc1f93df3d2448478ef79394a5981cc58", + "shasum": "" + }, + "require": { + "myclabs/php-enum": "^1.5", + "php": ">= 7.1", + "psr/http-message": "^1.0", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "ext-zip": "*", + "guzzlehttp/guzzle": ">= 6.3", + "mikey179/vfsstream": "^1.6", + "phpunit/phpunit": ">= 7.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "ZipStream\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paul Duncan", + "email": "pabs@pablotron.org" + }, + { + "name": "Jonatan Männchen", + "email": "jonatan@maennchen.ch" + }, + { + "name": "Jesse Donat", + "email": "donatj@gmail.com" + }, + { + "name": "András Kolesár", + "email": "kolesar@kolesar.hu" + } + ], + "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.", + "keywords": [ + "stream", + "zip" + ], + "support": { + "issues": "https://github.com/maennchen/ZipStream-PHP/issues", + "source": "https://github.com/maennchen/ZipStream-PHP/tree/master" + }, + "funding": [ + { + "url": "https://opencollective.com/zipstream", + "type": "open_collective" + } + ], + "time": "2020-05-30T13:11:16+00:00" + }, + { + "name": "markbaker/complex", + "version": "3.0.1", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPComplex.git", + "reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPComplex/zipball/ab8bc271e404909db09ff2d5ffa1e538085c0f22", + "reference": "ab8bc271e404909db09ff2d5ffa1e538085c0f22", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Complex\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@lange.demon.co.uk" + } + ], + "description": "PHP Class for working with complex numbers", + "homepage": "https://github.com/MarkBaker/PHPComplex", + "keywords": [ + "complex", + "mathematics" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPComplex/issues", + "source": "https://github.com/MarkBaker/PHPComplex/tree/3.0.1" + }, + "time": "2021-06-29T15:32:53+00:00" + }, + { + "name": "markbaker/matrix", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/MarkBaker/PHPMatrix.git", + "reference": "c66aefcafb4f6c269510e9ac46b82619a904c576" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/MarkBaker/PHPMatrix/zipball/c66aefcafb4f6c269510e9ac46b82619a904c576", + "reference": "c66aefcafb4f6c269510e9ac46b82619a904c576", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", + "phpcompatibility/php-compatibility": "^9.0", + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "^4.0", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.3", + "sebastian/phpcpd": "^4.0", + "squizlabs/php_codesniffer": "^3.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Matrix\\": "classes/src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mark Baker", + "email": "mark@demon-angel.eu" + } + ], + "description": "PHP Class for working with matrices", + "homepage": "https://github.com/MarkBaker/PHPMatrix", + "keywords": [ + "mathematics", + "matrix", + "vector" + ], + "support": { + "issues": "https://github.com/MarkBaker/PHPMatrix/issues", + "source": "https://github.com/MarkBaker/PHPMatrix/tree/3.0.0" + }, + "time": "2021-07-01T19:01:15+00:00" + }, { "name": "meyfa/php-svg", "version": "v0.9.1", @@ -2781,6 +3101,66 @@ ], "time": "2021-10-01T21:08:31+00:00" }, + { + "name": "myclabs/php-enum", + "version": "1.8.3", + "source": { + "type": "git", + "url": "https://github.com/myclabs/php-enum.git", + "reference": "b942d263c641ddb5190929ff840c68f78713e937" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/php-enum/zipball/b942d263c641ddb5190929ff840c68f78713e937", + "reference": "b942d263c641ddb5190929ff840c68f78713e937", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.3 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "squizlabs/php_codesniffer": "1.*", + "vimeo/psalm": "^4.6.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "MyCLabs\\Enum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP Enum contributors", + "homepage": "https://github.com/myclabs/php-enum/graphs/contributors" + } + ], + "description": "PHP Enum implementation", + "homepage": "http://github.com/myclabs/php-enum", + "keywords": [ + "enum" + ], + "support": { + "issues": "https://github.com/myclabs/php-enum/issues", + "source": "https://github.com/myclabs/php-enum/tree/1.8.3" + }, + "funding": [ + { + "url": "https://github.com/mnapoli", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/php-enum", + "type": "tidelift" + } + ], + "time": "2021-07-05T08:18:36+00:00" + }, { "name": "nesbot/carbon", "version": "2.57.0", @@ -3360,6 +3740,110 @@ }, "time": "2021-12-17T14:08:35+00:00" }, + { + "name": "phpoffice/phpspreadsheet", + "version": "1.22.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PhpSpreadsheet.git", + "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PhpSpreadsheet/zipball/3a9e29b4f386a08a151a33578e80ef1747037a48", + "reference": "3a9e29b4f386a08a151a33578e80ef1747037a48", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-fileinfo": "*", + "ext-gd": "*", + "ext-iconv": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "ext-xml": "*", + "ext-xmlreader": "*", + "ext-xmlwriter": "*", + "ext-zip": "*", + "ext-zlib": "*", + "ezyang/htmlpurifier": "^4.13", + "maennchen/zipstream-php": "^2.1", + "markbaker/complex": "^3.0", + "markbaker/matrix": "^3.0", + "php": "^7.3 || ^8.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0", + "psr/simple-cache": "^1.0" + }, + "require-dev": { + "dealerdirect/phpcodesniffer-composer-installer": "dev-master", + "dompdf/dompdf": "^1.0", + "friendsofphp/php-cs-fixer": "^3.2", + "jpgraph/jpgraph": "^4.0", + "mpdf/mpdf": "8.0.17", + "phpcompatibility/php-compatibility": "^9.3", + "phpstan/phpstan": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^8.5 || ^9.0", + "squizlabs/php_codesniffer": "^3.6", + "tecnickcom/tcpdf": "^6.4" + }, + "suggest": { + "dompdf/dompdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)", + "jpgraph/jpgraph": "Option for rendering charts, or including charts with PDF or HTML Writers", + "mpdf/mpdf": "Option for rendering PDF with PDF Writer", + "tecnickcom/tcpdf": "Option for rendering PDF with PDF Writer (doesn't yet support PHP8)" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\PhpSpreadsheet\\": "src/PhpSpreadsheet" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Maarten Balliauw", + "homepage": "https://blog.maartenballiauw.be" + }, + { + "name": "Mark Baker", + "homepage": "https://markbakeruk.net" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net" + }, + { + "name": "Erik Tilt" + }, + { + "name": "Adrien Crivelli" + } + ], + "description": "PHPSpreadsheet - Read, Create and Write Spreadsheet documents in PHP - Spreadsheet engine", + "homepage": "https://github.com/PHPOffice/PhpSpreadsheet", + "keywords": [ + "OpenXML", + "excel", + "gnumeric", + "ods", + "php", + "spreadsheet", + "xls", + "xlsx" + ], + "support": { + "issues": "https://github.com/PHPOffice/PhpSpreadsheet/issues", + "source": "https://github.com/PHPOffice/PhpSpreadsheet/tree/1.22.0" + }, + "time": "2022-02-18T12:57:07+00:00" + }, { "name": "phpoption/phpoption", "version": "1.8.1", @@ -3906,25 +4390,25 @@ }, { "name": "psr/simple-cache", - "version": "3.0.0", + "version": "1.0.1", "source": { "type": "git", "url": "https://github.com/php-fig/simple-cache.git", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865" + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/764e0b3939f5ca87cb904f570ef9be2d78a07865", - "reference": "764e0b3939f5ca87cb904f570ef9be2d78a07865", + "url": "https://api.github.com/repos/php-fig/simple-cache/zipball/408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", + "reference": "408d5eafb83c57f6365a3ca330ff23aa4a5fa39b", "shasum": "" }, "require": { - "php": ">=8.0.0" + "php": ">=5.3.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "1.0.x-dev" } }, "autoload": { @@ -3939,7 +4423,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "https://www.php-fig.org/" + "homepage": "http://www.php-fig.org/" } ], "description": "Common interfaces for simple caching", @@ -3951,9 +4435,9 @@ "simple-cache" ], "support": { - "source": "https://github.com/php-fig/simple-cache/tree/3.0.0" + "source": "https://github.com/php-fig/simple-cache/tree/master" }, - "time": "2021-10-29T13:26:27+00:00" + "time": "2017-10-23T01:57:42+00:00" }, { "name": "psy/psysh", @@ -7445,16 +7929,16 @@ }, { "name": "phar-io/version", - "version": "3.1.1", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "15a90844ad40f127afd244c0cad228de2a80052a" + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/15a90844ad40f127afd244c0cad228de2a80052a", - "reference": "15a90844ad40f127afd244c0cad228de2a80052a", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", "shasum": "" }, "require": { @@ -7490,9 +7974,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/3.1.1" + "source": "https://github.com/phar-io/version/tree/3.2.1" }, - "time": "2022-02-07T21:56:48+00:00" + "time": "2022-02-21T01:04:05+00:00" }, { "name": "php-webdriver/webdriver", @@ -7788,16 +8272,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.10", + "version": "9.2.11", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687" + "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/d5850aaf931743067f4bfc1ae4cbd06468400687", - "reference": "d5850aaf931743067f4bfc1ae4cbd06468400687", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/665a1ac0a763c51afc30d6d130dac0813092b17f", + "reference": "665a1ac0a763c51afc30d6d130dac0813092b17f", "shasum": "" }, "require": { @@ -7853,7 +8337,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.10" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.11" }, "funding": [ { @@ -7861,7 +8345,7 @@ "type": "github" } ], - "time": "2021-12-05T09:12:13+00:00" + "time": "2022-02-18T12:46:09+00:00" }, { "name": "phpunit/php-file-iterator", @@ -8106,16 +8590,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.5.13", + "version": "9.5.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "597cb647654ede35e43b137926dfdfef0fb11743" + "reference": "1883687169c017d6ae37c58883ca3994cfc34189" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/597cb647654ede35e43b137926dfdfef0fb11743", - "reference": "597cb647654ede35e43b137926dfdfef0fb11743", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1883687169c017d6ae37c58883ca3994cfc34189", + "reference": "1883687169c017d6ae37c58883ca3994cfc34189", "shasum": "" }, "require": { @@ -8193,7 +8677,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.13" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.14" }, "funding": [ { @@ -8205,7 +8689,7 @@ "type": "github" } ], - "time": "2022-01-24T07:33:35+00:00" + "time": "2022-02-18T12:54:07+00:00" }, { "name": "sebastian/cli-parser", @@ -9299,16 +9783,16 @@ }, { "name": "spatie/ignition", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "617c41d1bf675d95a7bd9adc826ba93d43affe7f" + "reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/617c41d1bf675d95a7bd9adc826ba93d43affe7f", - "reference": "617c41d1bf675d95a7bd9adc826ba93d43affe7f", + "url": "https://api.github.com/repos/spatie/ignition/zipball/6b7bb804f4834b080f5ac941f6ac6800a485011e", + "reference": "6b7bb804f4834b080f5ac941f6ac6800a485011e", "shasum": "" }, "require": { @@ -9366,7 +9850,7 @@ "type": "github" } ], - "time": "2022-02-16T09:02:42+00:00" + "time": "2022-02-17T21:40:47+00:00" }, { "name": "spatie/laravel-ignition", diff --git a/config/excel.php b/config/excel.php new file mode 100644 index 0000000..216664a --- /dev/null +++ b/config/excel.php @@ -0,0 +1,104 @@ + [ + "chunk_size" => 1000, + "pre_calculate_formulas" => false, + "strict_null_comparison" => false, + "csv" => [ + "delimiter" => ",", + "enclosure" => '"', + "line_ending" => PHP_EOL, + "use_bom" => false, + "include_separator_line" => false, + "excel_compatibility" => false, + "output_encoding" => "", + ], + "properties" => [ + "creator" => "", + "lastModifiedBy" => "", + "title" => "", + "description" => "", + "subject" => "", + "keywords" => "", + "category" => "", + "manager" => "", + "company" => "", + ], + ], + + "imports" => [ + "read_only" => true, + "ignore_empty" => false, + "heading_row" => [ + "formatter" => "slug", + ], + "csv" => [ + "delimiter" => ",", + "enclosure" => '"', + "escape_character" => "\\", + "contiguous" => false, + "input_encoding" => "UTF-8", + ], + "properties" => [ + "creator" => "", + "lastModifiedBy" => "", + "title" => "", + "description" => "", + "subject" => "", + "keywords" => "", + "category" => "", + "manager" => "", + "company" => "", + ], + ], + "extension_detector" => [ + "xlsx" => Excel::XLSX, + "xlsm" => Excel::XLSX, + "xltx" => Excel::XLSX, + "xltm" => Excel::XLSX, + "xls" => Excel::XLS, + "xlt" => Excel::XLS, + "ods" => Excel::ODS, + "ots" => Excel::ODS, + "slk" => Excel::SLK, + "xml" => Excel::XML, + "gnumeric" => Excel::GNUMERIC, + "htm" => Excel::HTML, + "html" => Excel::HTML, + "csv" => Excel::CSV, + "tsv" => Excel::TSV, + "pdf" => Excel::DOMPDF, + ], + "value_binder" => [ + "default" => DefaultValueBinder::class, + ], + + "cache" => [ + "driver" => "memory", + "batch" => [ + "memory_limit" => 60000, + ], + "illuminate" => [ + "store" => null, + ], + ], + "transactions" => [ + "handler" => "db", + "db" => [ + "connection" => null, + ], + ], + + "temporary_files" => [ + "local_path" => storage_path("framework/cache/laravel-excel"), + "remote_disk" => null, + "remote_prefix" => null, + "force_resync_remote" => null, + ], +]; diff --git a/resources/js/Pages/Calendar.vue b/resources/js/Pages/Calendar.vue index 1415b0a..1a8e095 100644 --- a/resources/js/Pages/Calendar.vue +++ b/resources/js/Pages/Calendar.vue @@ -1,10 +1,20 @@