diff --git a/README.md b/README.md index 65d13b7..e1386e9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ -# TODO +# Support +## Gitlab Intégration +Le token de groupe pour l'intégration est valable 1 an max + +Il faut le renouveler ici : https://lab.s-web.fr/groups/ldc-web/projets/-/settings/access_tokens et le nommer SW Intégration + +## TODO - App\Models\Message:booted(): investigate why this make errors on prod, diff --git a/app/Enums/Credit/EstimationTimeEnum.php b/app/Enums/Credit/EstimationTimeEnum.php new file mode 100644 index 0000000..86fb130 --- /dev/null +++ b/app/Enums/Credit/EstimationTimeEnum.php @@ -0,0 +1,49 @@ +name => "Une demi-heure", + self::hour->name => "Une heure", + self::hourAndHalf->name => "Une heure et demie", + self::twoHours->name => "Deux heures", + self::twoHoursAndHalf->name => "Deux heures et demie", + self::threeHours->name => "Trois heures", + self::twoHoursAndHalf->name => "Trois heures et demie", + self::fourHours->name => "Quatre heures", + self::fourHoursAndHalf->name => "Quatre heures et demie", + self::fiveHours->name => "Cinq heures", + self::fiveHoursAndHalf->name => "Cinq heures et demie", + self::sixHours->name => "Six heures", + self::sixHoursAndHalf->name => "Six heures et demie", + self::sevenHours->name => "Sept heures", + self::sevenHoursAndHalf->name => "Sept heures et demi", + self::eightHours->name => "Huit heures", + ]; +} diff --git a/app/Enums/Tickets/TicketFileTypeEnum.php b/app/Enums/Tickets/TicketFileTypeEnum.php new file mode 100644 index 0000000..7665508 --- /dev/null +++ b/app/Enums/Tickets/TicketFileTypeEnum.php @@ -0,0 +1,67 @@ +name => "Fichier png", + self::jpeg->name => "Fichier jpeg", + self::jpg->name => "Fichier jpg", + self::pdf->name => "Fichier pdf", + self::pptx->name => "Fichier pptx", + self::docx->name => "Fichier docx", + self::xlsx->name => "Fichier xlsx", + self::csv->name => "Fichier csv", + ]; + + /** + * Custom added mimes type definition + */ + private const MIMETYPE = [ + self::png->name => 'image/png', + self::jpeg->name => 'image/jpeg', + self::jpg->name => 'image/jpeg', + self::pdf->name => 'application/pdf', + self::pptx->name => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + self::docx->name => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + self::xlsx->name => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + self::csv->name => 'text/csv', + ]; + + /** + * Get Class + * + * @return string + */ + public function mimetypes(): string + { + return self::MIMETYPE[$this->name]; + } + + /** + * Get enum classes + * + * @return array + */ + public static function toMimetypes(): array + { + return self::MIMETYPE; + } +} diff --git a/app/Enums/Users/GitlabUsersEnum.php b/app/Enums/Users/GitlabUsersEnum.php index 5a6d2d3..9a6777f 100644 --- a/app/Enums/Users/GitlabUsersEnum.php +++ b/app/Enums/Users/GitlabUsersEnum.php @@ -9,12 +9,14 @@ enum GitlabUsersEnum: int use BaseEnum; // Each user is associated to his ID on gitlab. - case olivier = 11; + case olivier = 11; + case sebastien = 15; /** * Optionnal labels definition */ private const LABELS = [ - self::olivier->name => "Olivier LEGAT", + self::olivier->name => "Olivier LEGAT", + self::sebastien->name => "Sebastien Hattry", ]; } diff --git a/app/Http/Controllers/Bo/TicketController.php b/app/Http/Controllers/Bo/TicketController.php index 8894d6d..2584f3f 100644 --- a/app/Http/Controllers/Bo/TicketController.php +++ b/app/Http/Controllers/Bo/TicketController.php @@ -139,7 +139,7 @@ class TicketController extends Controller 'ticket' => $ticket, 'messages' => $messages, 'isSubscribed' => $isSubscribed - ]); + ]); } /** @@ -182,16 +182,17 @@ class TicketController extends Controller $ticket = new Ticket($request->validated()); - /** @var \Illuminate\Http\UploadedFile|null */ - $fileTicket = $request->file_ticket; - /** @var \Illuminate\Http\UploadedFile|null */ - $fileTicket2 = $request->file_ticket2; - - if ($fileTicket) { - $ticket->file = FileStorageHelper::storeFile($ticket, $fileTicket); - } - if ($fileTicket2) { - $ticket->file2 = FileStorageHelper::storeFile($ticket, $fileTicket2); + /** @var array<\Illuminate\Http\UploadedFile> */ + $fileTickets = $request->file_tickets ?? []; + if (count($fileTickets) > 0) { + foreach ($fileTickets as $key => $file) { + if ($key === 0) { + $ticket->file = FileStorageHelper::storeFile($ticket, $file); + } else { + $fileNumber = 'file' . $key + 1; + $ticket->$fileNumber = FileStorageHelper::storeFile($ticket, $file); + } + } } $ticket->user()->associate(auth()->user()); @@ -256,18 +257,18 @@ class TicketController extends Controller /** @var \App\Models\Site */ $site = Site::findOrFail($request->site_id); - /** @var \Illuminate\Http\UploadedFile|null */ - $fileTicket = $request->file_ticket; - /** @var \Illuminate\Http\UploadedFile|null */ - $fileTicket2 = $request->file_ticket2; - - if ($fileTicket) { - $ticket->file = FileStorageHelper::storeFile($ticket, $fileTicket); + /** @var null|array<\Illuminate\Http\UploadedFile> */ + $fileTickets = $request->file_tickets; + if (isset($fileTickets) && count($fileTickets) > 0) { + foreach ($fileTickets as $key => $file) { + if ($key === 0) { + $ticket->file = FileStorageHelper::storeFile($ticket, $file); + } else { + $fileNumber = 'file' . $key + 1; + $ticket->$fileNumber = FileStorageHelper::storeFile($ticket, $file); + } + } } - if ($fileTicket2) { - $ticket->file2 = FileStorageHelper::storeFile($ticket, $fileTicket2); - } - $ticket->labels()->sync($request->labels); @@ -313,9 +314,8 @@ class TicketController extends Controller try { return DB::transaction(function () use ($request, $ticket) { /** @var \Illuminate\Http\UploadedFile|null */ - $fileMessage = $request->file_message; - - $message = new Message($request->validated()); + $filesMessage = $request->file_messages; + $message = new Message($request->validated()); $message->user()->associate(auth()->user()); $message->ticket()->associate($ticket); @@ -330,12 +330,21 @@ class TicketController extends Controller $user->subscriptions()->detach($ticket->id); } + if (isset($filesMessage) and $filesMessage) { + foreach ($filesMessage as $key => $singleFile) { + if ($key === 0) { + $message->file = FileStorageHelper::storeFile($message, $singleFile); + $message->saveOrFail(); + } else { + $fileNumber = 'file' . $key + 1; + $message->$fileNumber = FileStorageHelper::storeFile($message, $singleFile); + $message->saveOrFail(); + } + } + } + $message->saveOrFail(); - if ($fileMessage) { - $message->file = FileStorageHelper::storeFile($message, $fileMessage); - $message->saveOrFail(); - } return back() ->with('success', trans('Votre message à été ajouté')); }); @@ -539,8 +548,13 @@ class TicketController extends Controller Session::has('tickets.sort_col') and Session::has('tickets.sort_way') and in_array(Session::get('tickets.sort_col'), [ - 'id', 'site_id', 'created_at', 'created_by', - 'type', 'status', 'assigned_to' + 'id', + 'site_id', + 'created_at', + 'created_by', + 'type', + 'status', + 'assigned_to' ]) ) { $tickets->orderBy( @@ -599,7 +613,7 @@ class TicketController extends Controller }); } //end foreach } //end if - }, 'text', 'title', 'file', 'file2'); + }, 'text', 'title', 'file', 'file2', 'file3', 'file4', 'file5'); } /** @@ -648,14 +662,11 @@ class TicketController extends Controller }; try { - if (!\is_null($ticket->file)) { - $uploadedFile = GitLab::projects()->uploadFile($gitlabRepoId, $ticket->file); - $description .= $this->formatGitlabFiles($ticket, $uploadedFile, 1); - } - - if (!\is_null($ticket->file2)) { - $uploadedFile2 = GitLab::projects()->uploadFile($gitlabRepoId, $ticket->file2); - $description .= $this->formatGitlabFiles($ticket, $uploadedFile2, 2); + foreach ($ticket->getFiles() as $key => $file) { + if (!\is_null($file)) { + $uploadedFile = GitLab::projects()->uploadFile($gitlabRepoId, $file); + $description .= $this->formatGitlabFiles($ticket, $uploadedFile, $key + 1); + } } $issue = GitLab::issues()->create($gitlabRepoId, [ @@ -665,7 +676,7 @@ class TicketController extends Controller 'c-support', $cLabel ]), - 'assignee_id' => GitlabUsersEnum::olivier, + 'assignee_id' => GitlabUsersEnum::sebastien, ]); } catch (\Exception $e) { \report($e); @@ -694,7 +705,7 @@ class TicketController extends Controller */ private function formatGitlabFiles(Ticket $ticket, array $uploadedFile, int $fileNb) { - if (Str::endsWith($ticket->file, ['jpg', 'png', 'jpeg'])) { + if (Str::endsWith($ticket->file, ['jpg', 'png', 'jpeg', 'pptx', 'docx', 'xslx', 'csv'])) { $file = \sprintf( "![Fichier joint %d](%s)", $fileNb, diff --git a/app/Http/Requests/Bo/CreateMessage.php b/app/Http/Requests/Bo/CreateMessage.php index 995bcb3..5031dc5 100644 --- a/app/Http/Requests/Bo/CreateMessage.php +++ b/app/Http/Requests/Bo/CreateMessage.php @@ -39,7 +39,7 @@ class CreateMessage extends FormRequest { $this->merge([ 'subscribe' => $this->subscribe ? true : false, - 'type' => $this->is_private ? MessageTypeEnum::private->value : MessageTypeEnum::public->value + 'type' => $this->is_private ? MessageTypeEnum::private->value : MessageTypeEnum::public->value ]); } @@ -53,13 +53,11 @@ class CreateMessage extends FormRequest /** @var \App\Models\User */ $user = auth()->user(); return [ - 'subscribe' => 'required|boolean', - 'message' => 'required|min:' . ($user->isAdmin() ? '5' : '20'), - 'file_message' => 'sometimes|mimes:jpeg,jpg,png,pdf|max:2048', - 'type' => [ - 'required', - new Enum(MessageTypeEnum::class) - ] + 'subscribe' => 'required|boolean', + 'message' => 'required|min:' . ($user->isAdmin() ? '5' : '20'), + 'file_messages' => 'sometimes|array', + 'file_messages.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf|max:2048', + 'type' => ['required', new Enum(MessageTypeEnum::class)] ]; } } diff --git a/app/Http/Requests/Bo/Credit/CreateEstimateRequest.php b/app/Http/Requests/Bo/Credit/CreateEstimateRequest.php index 0aa3dd7..da90770 100644 --- a/app/Http/Requests/Bo/Credit/CreateEstimateRequest.php +++ b/app/Http/Requests/Bo/Credit/CreateEstimateRequest.php @@ -33,14 +33,18 @@ class CreateEstimateRequest extends FormRequest $ticket = $this->ticket; return [ 'amount' => [ - 'required', 'numeric', 'gt:0', function ($attribute, $value, $fail) { - if ((\floatval($value) * 1000) % 125 !== 0) { - $fail("$attribute doit être un multiple de 125 (soit 0.125)"); + 'required', + 'numeric', + 'gt:0', + function ($attribute, $value, $fail) { + if (fmod((\floatval($value) * 1000), 62.5) !== 0.0) { + $fail("$attribute doit être un multiple de 62.5 (soit 0.0625)"); } } ], 'credit_account_id' => [ - 'required', 'exists:credit_accounts,id', + 'required', + 'exists:credit_accounts,id', function ($attribute, $value, $fail) use ($ticket) { /** @var \App\Models\Credit\Account|null */ $account = Account::whereId($value)->first(); @@ -57,11 +61,11 @@ class CreateEstimateRequest extends FormRequest * * @return array */ - public function messages(): array + public function attributes(): array { return [ 'amount' => 'Montant', - 'credit_account_id' => 'Compte' + 'credit_account_id' => 'Compte à débiter' ]; } } diff --git a/app/Http/Requests/Bo/EraseCellContentRequest.php b/app/Http/Requests/Bo/EraseCellContentRequest.php deleted file mode 100644 index 3e149be..0000000 --- a/app/Http/Requests/Bo/EraseCellContentRequest.php +++ /dev/null @@ -1,37 +0,0 @@ -check() and $this->ajax(); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules() - { - return [ - 'id' => 'required|exists:week_plannings,id', - 'day' => 'required|numeric', - 'row' => [ - 'required', - new Enum(TableRowEnum::class) - ], - ]; - } -} diff --git a/app/Http/Requests/Bo/Invoices/StoreInvoiceRequest.php b/app/Http/Requests/Bo/Invoices/StoreInvoiceRequest.php index 0bb858d..6a4d839 100644 --- a/app/Http/Requests/Bo/Invoices/StoreInvoiceRequest.php +++ b/app/Http/Requests/Bo/Invoices/StoreInvoiceRequest.php @@ -28,7 +28,7 @@ class StoreInvoiceRequest extends FormRequest protected function prepareForValidation() { $this->merge([ - 'tasks' => request()->tasks ? \collect(json_decode(request()->tasks)) + 'tasks' => request()->tasks ? \collect(json_decode(request()->tasks)) ->map(function ($task) { return \array_intersect_key((array)$task, Invoice::getTaskStructure()); })->toArray() : [], @@ -44,24 +44,24 @@ class StoreInvoiceRequest extends FormRequest public function rules() { return [ - 'firstname' => 'required|string|min:3|max:255', - 'lastname' => 'required|string|min:3|max:255', - 'object' => 'required|string|min:3|max:255', - 'tasks' => 'required|array|min:1', - 'tasks.*' => 'required|array', - 'tasks.*.days' => 'required|numeric', + 'firstname' => 'required|string|min:3|max:255', + 'lastname' => 'required|string|min:3|max:255', + 'object' => 'required|string|min:3|max:255', + 'tasks' => 'required|array|min:1', + 'tasks.*' => 'required|array', + 'tasks.*.days' => 'required|numeric', 'tasks.*.amount' => 'required|numeric', - 'tasks.*.desc' => 'required|string|min:10', - 'tasks.*.type' => [ + 'tasks.*.desc' => 'required|string|min:10', + 'tasks.*.type' => [ 'required', new Enum(TaskTypeEnum::class) ], 'tasks.*.package' => 'required_if:tasks.*.type,' . TaskTypeEnum::package->value . '|nullable|exists:packages,id', - 'comment' => 'sometimes|nullable|string|min:15', - 'show_days' => 'required|boolean', - 'site_id' => 'required|integer|exists:sites,id', - 'company_id' => 'required|integer|exists:companies,id', - 'invoiced_to_id' => 'required|integer|exists:companies,id', + 'comment' => 'sometimes|nullable|string|min:15', + 'show_days' => 'required|boolean', + 'site_id' => 'required|integer|exists:sites,id', + 'company_id' => 'required|integer|exists:companies,id', + 'invoiced_to_id' => 'required|integer|exists:companies,id', ]; } diff --git a/app/Http/Requests/Bo/Invoices/UpdateInvoiceRequest.php b/app/Http/Requests/Bo/Invoices/UpdateInvoiceRequest.php index cf39a53..fe65552 100644 --- a/app/Http/Requests/Bo/Invoices/UpdateInvoiceRequest.php +++ b/app/Http/Requests/Bo/Invoices/UpdateInvoiceRequest.php @@ -21,11 +21,11 @@ class UpdateInvoiceRequest extends StoreInvoiceRequest $rules = array_merge($rules, parent::rules()); } $rules = array_merge($rules, [ - 'comment' => 'sometimes|nullable|string|min:15', - 'sent_client_date' => 'required_with:signed_date,sent_accounting_date|sometimes|nullable|date', - 'signed_date' => 'required_with:sent_accounting_date|sometimes|nullable|date', + 'comment' => 'sometimes|nullable|string|min:15', + 'sent_client_date' => 'required_with:signed_date,sent_accounting_date|sometimes|nullable|date', + 'signed_date' => 'required_with:sent_accounting_date|sometimes|nullable|date', 'sent_accounting_date' => 'sometimes|nullable|date', - 'status' => [ + 'status' => [ 'required', new Enum(InvoiceStatusEnum::class), //phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed diff --git a/app/Http/Requests/Bo/SetCellContentRequest.php b/app/Http/Requests/Bo/SetCellContentRequest.php deleted file mode 100644 index a2f608f..0000000 --- a/app/Http/Requests/Bo/SetCellContentRequest.php +++ /dev/null @@ -1,68 +0,0 @@ -merge([ - 'model' => $this->model ?? null, - 'foreign' => $this->foreign ?? null, - 'text' => $this->text ?? '' - ]); - return auth()->check() and $this->ajax(); - } - - /** - * Get the validation rules that apply to the request. - * - * @return array - */ - public function rules(): array - { - return [ - 'id' => 'required|exists:week_plannings,id', - 'day' => 'required|numeric', - 'row' => [ - 'required', - new Enum(TableRowEnum::class) - ], - 'type' => [ - 'required', - new Enum(CellTypeEnum::class) - ], - 'CellModelEnum' => \sprintf( - 'nullable', - new Enum(CellModelEnum::class) - ), - 'foreign' => 'required_with:CellModelEnum|nullable|numeric', - 'text' => 'required|string|min:5|max:90' - ]; - } - - /** - * Get custom attributes for validator errors. - * - * @return array - */ - public function attributes(): array - { - return [ - 'CellModelEnum' => 'Type d\'élément lié', - 'foreign' => 'Élément lié', - 'text' => 'Description courte' - ]; - } -} diff --git a/app/Http/Requests/Bo/StoreTicket.php b/app/Http/Requests/Bo/StoreTicket.php index 753984a..41a512c 100644 --- a/app/Http/Requests/Bo/StoreTicket.php +++ b/app/Http/Requests/Bo/StoreTicket.php @@ -96,13 +96,13 @@ class StoreTicket extends FormRequest } } ], - 'text' => 'required|string|min:40', - 'title' => 'required|string|between:3,255', - 'file_ticket' => 'mimes:jpeg,jpg,png,pdf|max:2048', - 'file_ticket2' => 'mimes:jpeg,jpg,png,pdf|max:2048', - 'is_internal' => 'required|boolean', - 'labels' => 'sometimes|array', - 'labels.*' => [ + 'text' => 'required|string|min:40', + 'title' => 'required|string|between:3,255', + 'file_tickets' => 'sometimes|array', + 'file_tickets.*' => 'mimes:pptx,docx,xlsx,csv,txt,jpeg,jpg,png,pdf|max:2048', + 'is_internal' => 'required|boolean', + 'labels' => 'sometimes|array', + 'labels.*' => [ // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed 'required', 'exists:labels,id', function ($attribute, $value, $fail) use ($user) { if (!$user->can('assignLabels', Ticket::class)) { diff --git a/app/Lib/Helpers/ToolboxHelper.php b/app/Lib/Helpers/ToolboxHelper.php index 68bd885..507eadc 100644 --- a/app/Lib/Helpers/ToolboxHelper.php +++ b/app/Lib/Helpers/ToolboxHelper.php @@ -68,6 +68,18 @@ class ToolboxHelper return \preg_match('/(\.png|\.jpg|\.jpeg|\.gif)$/', $url, $m) === 1; } + /** + * Check uri points to pdf file + * + * @param string $url + * @return boolean + */ + public static function isPdfFile(string $url): bool + { + $m = []; + return \preg_match('/(\.pdf)$/', $url, $m) === 1; + } + /** * Strip scheme (https) on oembed urls * Only embed allowed are for MP4 self hosted videos right now @@ -339,7 +351,7 @@ class ToolboxHelper ): Builder { $currentLocale = app()->currentLocale(); $locales = collect(config('app.locales')) - ->mapWithKeys(fn (string $locale) => [$locale => $locale]); + ->mapWithKeys(fn(string $locale) => [$locale => $locale]); if (!$locales->has($defaultLocale)) { // * Remove default locale. $locales->pull($defaultLocale); @@ -357,7 +369,7 @@ class ToolboxHelper $q->whereRaw("JSON_EXTRACT({$column}, '$.{$currentLocale}') = '{$value}'"); } // * Query any other locale - $locales->each(fn ($locale) => $q->orWhereRaw( + $locales->each(fn($locale) => $q->orWhereRaw( "JSON_EXTRACT({$column}, '$.{$locale}') = '{$value}'" )); }); @@ -449,7 +461,10 @@ class ToolboxHelper $fileFullPath = self::getUploadedFileFullPath($value, $useStorage); if ( !\in_array(self::getUploadedFileMimeType($value, $useStorage), [ - 'image/jpeg', 'image/jpg', 'image/png', 'image/gif' + 'image/jpeg', + 'image/jpg', + 'image/png', + 'image/gif' ]) ) { $fail(trans(':attribute doit être une image de type \'image/jpeg,image/jpg,image/png,image/gif\'', [ diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php index 136672f..460ef6d 100644 --- a/app/Models/Ticket.php +++ b/app/Models/Ticket.php @@ -44,9 +44,9 @@ class Ticket extends Model * @var array */ protected $casts = [ - 'is_internal' => 'bool', - 'type' => TicketTypeEnum::class, - 'status' => TicketStatusEnum::class, + 'is_internal' => 'bool', + 'type' => TicketTypeEnum::class, + 'status' => TicketStatusEnum::class, 'last_activity' => 'timestamp', ]; @@ -275,4 +275,20 @@ class Ticket extends Model Str::limit(\preg_replace('/[[:cntrl:]]+/', '', $ticket->text), 35), ); } + + /** + * Get an array of all files columns of the ticket. + * + * @return array + */ + public function getFiles(): array + { + return [ + $this->file, + $this->file2, + $this->file3, + $this->file4, + $this->file5, + ]; + } } diff --git a/database/factories/InvoiceFactory.php b/database/factories/InvoiceFactory.php index d41b89c..cb1f232 100644 --- a/database/factories/InvoiceFactory.php +++ b/database/factories/InvoiceFactory.php @@ -70,7 +70,7 @@ class InvoiceFactory extends Factory \mt_srand(); $lines = \mt_rand(2, 9); for ($i = 0; $i < $lines; $i++) { - $days = 0.125 * $this->faker->numberBetween(1, 4); + $days = 0.0625 * $this->faker->numberBetween(1, 4); $type = \collect(TaskTypeEnum::cases())->random(); $amount = 0; switch ($type) { diff --git a/database/migrations/2024_07_19_150414_add_files_to_tickets_table.php b/database/migrations/2024_07_19_150414_add_files_to_tickets_table.php new file mode 100644 index 0000000..a3e3ace --- /dev/null +++ b/database/migrations/2024_07_19_150414_add_files_to_tickets_table.php @@ -0,0 +1,36 @@ +string('file3')->after('file2')->nullable()->comment('Pièce jointes n°3'); + $table->string('file4')->after('file3')->nullable()->comment('Pièce jointes n°4'); + $table->string('file5')->after('file4')->nullable()->comment('Pièce jointes n°5'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::table('tickets', function (Blueprint $table) { + $table->dropColumn('file3'); + $table->dropColumn('file4'); + $table->dropColumn('file5'); + }); + } +}; diff --git a/database/migrations/2024_07_19_151553_add_files_to_messages_table.php b/database/migrations/2024_07_19_151553_add_files_to_messages_table.php new file mode 100644 index 0000000..f3ec4c1 --- /dev/null +++ b/database/migrations/2024_07_19_151553_add_files_to_messages_table.php @@ -0,0 +1,34 @@ +string('file2')->after('file')->nullable()->comment('Pièce jointes n°2'); + $table->string('file3')->after('file2')->nullable()->comment('Pièce jointes n°3'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('messages', function (Blueprint $table) { + $table->dropColumn('file2'); + $table->dropColumn('file3'); + }); + } +}; diff --git a/package-lock.json b/package-lock.json index 73a6148..572ab94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "support-web", + "name": "srcs", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/resources/ts/bo/components/InvoiceTasksComponent.vue b/resources/ts/bo/components/InvoiceTasksComponent.vue index 93b573f..92015a7 100644 --- a/resources/ts/bo/components/InvoiceTasksComponent.vue +++ b/resources/ts/bo/components/InvoiceTasksComponent.vue @@ -82,7 +82,7 @@ v-model="task.days" @change="updateAmount(index)" type="number" - step="0.125" + step="0.0625" > diff --git a/resources/views/bo/pages/invoices/show.blade.php b/resources/views/bo/pages/invoices/show.blade.php index 2288e51..283e992 100644 --- a/resources/views/bo/pages/invoices/show.blade.php +++ b/resources/views/bo/pages/invoices/show.blade.php @@ -56,9 +56,9 @@ @foreach ($invoiceModel->tasks as $task) {!! nl2br($task['desc']) !!} - {{ $task['type'] }} + {{ \App\Enums\Invoices\TaskTypeEnum::make($task['type'])->label() }} {{ $task['days'] }} - {{ $task['amount'] }} + {{ $task['amount'] }}€ @endforeach @@ -67,7 +67,7 @@ {{ Str::ucfirst(__('validation.attributes.total')) }} - {{ $invoiceModel->total }} + {{ $invoiceModel->total }}€ {{ Str::ucfirst(__('validation.attributes.total_days')) }} diff --git a/resources/views/bo/pages/tickets/form-inputs.blade.php b/resources/views/bo/pages/tickets/form-inputs.blade.php index 0abe56d..cbdeea1 100644 --- a/resources/views/bo/pages/tickets/form-inputs.blade.php +++ b/resources/views/bo/pages/tickets/form-inputs.blade.php @@ -105,26 +105,23 @@ -

Fichier joint 1

-
- - @if (isset($ticket) and $ticket->file !== null) -
-
- -
- @endif -
-

Fichier joint 2

-
- - @if (isset($ticket) and $ticket->file2 !== null) -
-
- -
- @endif -
+ +@for ($i = 1; $i < 6; $i++) +

Fichier joint {{ $i }}

+
+ + @if (isset($ticket) and $ticket->file !== null) + @php + $fileNumber = 'file'. $i; + @endphp +
+ +
+ @endif +
+
+@endfor + @can('changeInternalStatus', App\Model\Ticket::class)
is_internal)) checked @endif> diff --git a/resources/views/bo/pages/tickets/index.blade.php b/resources/views/bo/pages/tickets/index.blade.php index 9d73db6..6642a15 100644 --- a/resources/views/bo/pages/tickets/index.blade.php +++ b/resources/views/bo/pages/tickets/index.blade.php @@ -225,100 +225,102 @@
- @if ($ticket->file !== null) - + @php + $ticket_files = $ticket->getFiles(); + @endphp + @foreach ($ticket_files as $key => $file) + @if ($file !== null && (\App\Lib\Helpers\ToolboxHelper::isImageFile($file) || \App\Lib\Helpers\ToolboxHelper::isPdfFile($file))) + + + @break @endif - @if ($ticket->file2 !== null) - + @endforeach + {{-- Modal du ticket --}} + + + + @if (auth()->user()->isAdmin()) + + @endif + @can('changeStatus', $ticket) + @if (!$ticket->status->equals(\App\Enums\Tickets\TicketStatusEnum::archived)) +
+ @method('PUT') + @csrf + +
@endif - {{-- Modal du ticket --}} - - - - @if (auth()->user()->isAdmin()) - - @endif - @can('changeStatus', $ticket) - @if (!$ticket->status->equals(\App\Enums\Tickets\TicketStatusEnum::archived)) -
- @method('PUT') - @csrf - -
- @endif + @endcan +
+
+
+ + +
+ + + @endforeach + + + {{ $tickets->withQueryString()->links() }} + @endsection diff --git a/resources/views/bo/pages/tickets/show.blade.php b/resources/views/bo/pages/tickets/show.blade.php index dd99bad..4d590bb 100644 --- a/resources/views/bo/pages/tickets/show.blade.php +++ b/resources/views/bo/pages/tickets/show.blade.php @@ -5,271 +5,288 @@ @section('bodyClass', 'content ticketsShow') @section('content') -
-

- - {{ $ticket->full_name }} - @if ($ticket->is_internal)@endif - {{ $ticket->type->label() }} -

-
- @can('suscribeToTicket', $ticket) -
- @csrf -
- - -
- @push('scripts') - - @endpush -
- @endcan - @can('assignTo', $ticket) -
- @csrf -
- - - @push('scripts') - - @endpush -
-
- @endcan - @can('changeStatus', $ticket) -
- @csrf -
- - - @push('scripts') - - @endpush -
-
- @endcan - @if($ticket->status->equals(\App\Enums\Tickets\TicketStatusEnum::archived)) - @can('reopen', $ticket) -
- @csrf - -
- @endcan - @endif -
-
-@can('assignLabels', App\Models\Ticket::class) -
-
- @foreach ($ticket->labels as $label) - {{ $label->name }} - @endforeach -
-
-@endcan -
-@if($ticket->estimation) -@include('estimations.pendingCard', ['ticket' => $ticket, 'estimation' => $ticket->estimation]) -
-@endif -
-

- {{ __('Suivi') }} - @can('createMessage', $ticket) - - - @endcan - @can('estimate', $ticket) - {{ __('Estimation') }} - @endcan -

- @foreach ($messages as $message) - @if ( - $message->type->equals(\App\Enums\MessageTypeEnum::public) || - (Auth::user()->can('createPrivateMessage', $ticket)) - ) - @if ($message->user_id === null) -
- {!! nl2br(clean($message->message)) !!} - Le {{ \Carbon\Carbon::parse($message->created_at)->format('d/m/Y à H:i')}} - ({{ __('Message système') }}) -
+ @endif +
+ @can('createGitlabIssue', $ticket) +
+ @csrf + +
@else -
- @if ($message->type->equals(\App\Enums\MessageTypeEnum::private)) -    - @endif - {!! \App\Lib\Helpers\ToolboxHelper::plainToHtml($message->message) !!} - @if ($message->file !== null) -
file))data-fslightbox="gallery" @endif href="{{ asset($message->file) }}" target="_blank">Ouvrir la pièce jointe
- @endif

- - {!! __('Créé le :date par :userName', [ - 'date' => \Carbon\Carbon::parse($message->created_at)->format('d/m/Y à H:i'), - 'userName' => $message->user ? $message->user->name : __('Utilisateur supprimé') - ]) !!} - - @if($message->user_id === Auth::user()->id) - @can('updateMessage', $ticket, $message) - - + @can('isAdmin') + @if (!\is_null($ticket->gitlab_issue)) +
+

+ {{ __("Lien vers l'issue Gitlab : ") }} + {{ __('Ouvrir') }} +

+ @endif @endcan - @endif -
- @endif - @endif - @endforeach -
-
-
-

{{__('Description') }}

-

{!! clean(\App\Lib\Helpers\ToolboxHelper::plainToHtml($ticket->text)) !!}

- {!! __('Créé le :date par :userName', [ - 'date' => \Carbon\Carbon::parse($ticket->created_at)->format('d/m/Y à H:i'), - 'userName' => $ticket->user ? $ticket->user->name : __('Utilisateur supprimé') - ]) !!} -
-@if (!is_null($ticket->file) or !is_null($ticket->file2)) -
-
-

{{ __('Pièces jointes') }}

- -
-@endif -@can('createGitlabIssue', $ticket) -
- @csrf - -
-@else - @can('isAdmin') - @if (!\is_null($ticket->gitlab_issue)) -
-

- {{ __("Lien vers l'issue Gitlab : ")}} - {{ __("Ouvrir") }} -

- @endif - @endcan -@endcan -@endsection + @endcan + @endsection diff --git a/resources/views/estimations/form-inputs.blade.php b/resources/views/estimations/form-inputs.blade.php index 50c9131..c467b0a 100644 --- a/resources/views/estimations/form-inputs.blade.php +++ b/resources/views/estimations/form-inputs.blade.php @@ -1,6 +1,6 @@
- + @include('modules.input-error', [ 'inputName' => 'amount', 'helperId' => 'amountHelper' , 'helper' => __('Le montant en homme jour estimé.') ])