From f22925dc03764501b81125990372643325ae8ceb Mon Sep 17 00:00:00 2001 From: Alexis Gousseau Date: Fri, 31 Mar 2023 17:38:44 +0200 Subject: [PATCH 1/5] add CRUD documents without file --- app/Enums/Documents/TypeEnum.php | 38 + app/Http/Controllers/Bo/AppUserController.php | 48 +- .../Controllers/Bo/DirectoriesController.php | 2 +- .../Controllers/Bo/DocumentController.php | 169 ++++ .../Bo/Documents/StoreAppUserRequest.php | 56 ++ .../Bo/Documents/UpdateAppUserRequest.php | 7 + app/Models/Directory.php | 44 ++ app/Models/Document.php | 144 ++++ app/Providers/RouteServiceProvider.php | 2 + app/Traits/Controllers/UpdateModelStatus.php | 26 + database/factories/DocumentFactory.php | 32 + ...023_04_05_093932_update_document_table.php | 42 + database/seeders/DirectorySeeder.php | 4 +- database/seeders/DocumentSeeder.php | 24 + resources/lang/en/models.php | 1 + resources/lang/fr/models.php | 1 + resources/sass/bo/base/_common.scss | 1 + .../ts/bo/components/AddDocumentComponent.vue | 182 +++++ .../BelongsToManyDropdownComponent.vue | 64 +- .../ts/bo/components/ImageInputComponent.vue | 737 +++++++++--------- .../bo/components/InputTextAutoComponent.vue | 198 ++--- resources/ts/bo/vue-bo.ts | 2 +- resources/ts/utilities/fontawesome.ts | 6 +- resources/views/bo/layouts/nav-menu.blade.php | 8 + .../bo/modules/table-col-sorter.blade.php | 20 +- .../views/bo/pages/app-users/create.blade.php | 2 +- .../views/bo/pages/app-users/edit.blade.php | 2 +- .../views/bo/pages/app-users/form.blade.php | 38 +- .../views/bo/pages/app-users/index.blade.php | 1 + .../views/bo/pages/directories/edit.blade.php | 2 +- .../bo/pages/directories/index.blade.php | 1 + .../views/bo/pages/documents/create.blade.php | 49 ++ .../views/bo/pages/documents/edit.blade.php | 60 ++ .../views/bo/pages/documents/form.blade.php | 56 ++ .../bo/pages/documents/index-list.blade.php | 111 +++ .../views/bo/pages/documents/index.blade.php | 48 ++ routes/web-bo.php | 9 + 37 files changed, 1656 insertions(+), 581 deletions(-) create mode 100644 app/Enums/Documents/TypeEnum.php create mode 100644 app/Http/Controllers/Bo/DocumentController.php create mode 100644 app/Http/Requests/Bo/Documents/StoreAppUserRequest.php create mode 100644 app/Http/Requests/Bo/Documents/UpdateAppUserRequest.php create mode 100644 app/Models/Document.php create mode 100644 app/Traits/Controllers/UpdateModelStatus.php create mode 100644 database/factories/DocumentFactory.php create mode 100644 database/migrations/2023_04_05_093932_update_document_table.php create mode 100644 database/seeders/DocumentSeeder.php create mode 100644 resources/ts/bo/components/AddDocumentComponent.vue create mode 100644 resources/views/bo/pages/documents/create.blade.php create mode 100644 resources/views/bo/pages/documents/edit.blade.php create mode 100644 resources/views/bo/pages/documents/form.blade.php create mode 100644 resources/views/bo/pages/documents/index-list.blade.php create mode 100644 resources/views/bo/pages/documents/index.blade.php diff --git a/app/Enums/Documents/TypeEnum.php b/app/Enums/Documents/TypeEnum.php new file mode 100644 index 0000000..bd3006b --- /dev/null +++ b/app/Enums/Documents/TypeEnum.php @@ -0,0 +1,38 @@ + 1, + 'mp4' => 2, + ]; + } + + /** + * enum labels + * @return array + */ + protected static function labels(): array + { + return [ + 'pdf' => 'PDF', + 'mp4' => 'MP4', + ]; + } +} diff --git a/app/Http/Controllers/Bo/AppUserController.php b/app/Http/Controllers/Bo/AppUserController.php index 59de9a6..8094ecc 100644 --- a/app/Http/Controllers/Bo/AppUserController.php +++ b/app/Http/Controllers/Bo/AppUserController.php @@ -10,7 +10,6 @@ use App\Imports\AppUserImport; use App\Models\AppUser; use App\Models\Directory; use App\Traits\Controllers\ChangesModelOrder; -use Illuminate\Database\Eloquent\Collection; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; @@ -20,11 +19,6 @@ class AppUserController extends Controller { use ChangesModelOrder; - /** - * @var string - */ - protected $nameDirectory = ""; - /** * Display a listing of the resource. * @@ -62,7 +56,8 @@ class AppUserController extends Controller */ public function create() { - $directories = $this->renderDirectories(Directory::where('needAuthorization', 1)->get()); + $directories = Directory::renderDirectories(Directory::where('needAuthorization', 1) + ->orderBy('name', 'ASC')->get()); return view('bo.pages.app-users.create', compact('directories')); } @@ -106,8 +101,9 @@ class AppUserController extends Controller */ public function edit(AppUser $app_user) { - $directories = $this->renderDirectories(Directory::where('needAuthorization', 1)->get()); - $app_user->directories = $this->renderDirectories($app_user->directories); + $directories = Directory::renderDirectories(Directory::where('needAuthorization', 1) + ->orderBy('name', 'ASC')->get()); + $app_user->directories = Directory::renderDirectories($app_user->directories); return view('bo.pages.app-users.edit', [ 'app_userModel' => $app_user, @@ -174,40 +170,6 @@ class AppUserController extends Controller )); } - /** - * Render directories. - * - * @param Collection $directories - * @return array - */ - private function renderDirectories(Collection $directories) - { - foreach ($directories as $k => $directory) { - $this->nameDirectory = ""; - $directories[$k]->name = $this->renameDirectory($directory); - } - return $directories; - } - - /** - * Rename directory. - * - * @param Directory $directory - * @return array - */ - private function renameDirectory(Directory $directory) - { - if (strlen($this->nameDirectory)) { - $this->nameDirectory = $directory->name . " / " . $this->nameDirectory; - } else { - $this->nameDirectory = $directory->name; - } - if (isset($directory->parent)) { - $this->renameDirectory($directory->parent); - } - return $this->nameDirectory; - } - /** * Mass import by CSV. * matricule;lastname;firstname;email diff --git a/app/Http/Controllers/Bo/DirectoriesController.php b/app/Http/Controllers/Bo/DirectoriesController.php index ba46a77..4a4a3bf 100644 --- a/app/Http/Controllers/Bo/DirectoriesController.php +++ b/app/Http/Controllers/Bo/DirectoriesController.php @@ -142,7 +142,7 @@ class DirectoriesController extends Controller * @param mixed $parentId * @return void */ - public function assignOrder(array $directories, $parentId = null) + public function assignOrder(array $directories, mixed $parentId = null) { foreach ($directories as $newDirectory) { $directory = Directory::where('id', $newDirectory['id'])->first(); diff --git a/app/Http/Controllers/Bo/DocumentController.php b/app/Http/Controllers/Bo/DocumentController.php new file mode 100644 index 0000000..08296d8 --- /dev/null +++ b/app/Http/Controllers/Bo/DocumentController.php @@ -0,0 +1,169 @@ +search) { + $this->searchQuery( + $documents, + $request->search, + null, + 'title', + ); + } + + $this->sortQuery($documents); + $searchFields = trans('Titre'); + + $documents = $documents->paginate(10); + + return view('bo.pages.documents.index', compact('documents', 'searchFields')); + } + + /** + * Show the form for creating a new resource. + * + * @return \Illuminate\Http\Response + */ + public function create() + { + $documents = Document::where('status', true)->get(); + $directories = Directory::renderDirectories(Directory::where('needAuthorization', 1) + ->orderBy('name', 'ASC')->get()); + + return view('bo.pages.documents.create', compact('documents', 'directories')); + } + + /** + * Store a newly created resource in storage. + * + * @param \App\Http\Requests\Bo\Document\StoreDocumentRequest $request + * @return \Illuminate\Http\Response + */ + public function store(StoreDocumentRequest $request) + { + return DB::transaction(function () use ($request) { + $document = new Document(); + $document->fill($request->validated()); + + if ($document->saveOrFail()) { + return redirect() + ->route('bo.documents.edit', $document) + ->with('success', trans( + ':model a été créé', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + } + + return redirect() + ->back() + ->with('error', trans( + ':model n\'a pas été créé', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + }); + } + + /** + * Show the form for editing the specified resource. + * + * @param \App\Models\Document $document + * @return \Illuminate\Http\Response + */ + public function edit(Document $document) + { + $documents = Document::where('status', true)->get(); + $directories = Directory::renderDirectories(Directory::where('needAuthorization', 1) + ->orderBy('name', 'ASC')->get()); + + return view('bo.pages.documents.edit', [ + 'documents' => $documents, + 'documentModel' => $document, + 'directories' => $directories + ]); + } + + /** + * Update the specified resource in storage. + * + * @param \App\Http\Requests\Bo\Document\UpdateDocumentRequest $request + * @param \App\Models\Document $document + * @return \Illuminate\Http\Response + */ + public function update(UpdateDocumentRequest $request, Document $document) + { + $params = $request->validated(); + if (\is_null($params['password'])) { + unset($params['password']); + } + return DB::transaction(function () use ($params, $document) { + $document->fill($params); + + if ($document->saveOrFail()) { + return redirect() + ->route('bo.documents.edit', $document) + ->with('success', trans( + ':model a été mis à jour', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + } + return redirect() + ->back() + ->with('error', trans( + ':model n\'a pas été mis à jour', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + }); + } + + /** + * Remove the specified resource from storage. + * + * @param \App\Models\Document $document + * @return \Illuminate\Http\Response + */ + public function destroy(Document $document) + { + if ($document->deleteOrFail()) { + return redirect() + ->route('bo.documents.index') + ->with('warning', trans( + ':model a bien été supprimé', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + } + + return redirect() + ->back() + ->with('error', trans( + ':model n\'a pas été supprimé', + ['model' => Str::singular(trans('models.classes.documents'))] + )); + } +} diff --git a/app/Http/Requests/Bo/Documents/StoreAppUserRequest.php b/app/Http/Requests/Bo/Documents/StoreAppUserRequest.php new file mode 100644 index 0000000..3a70bde --- /dev/null +++ b/app/Http/Requests/Bo/Documents/StoreAppUserRequest.php @@ -0,0 +1,56 @@ +check(); + } + + /** + * Prepare the data for validation. + * + * @return void + */ + protected function prepareForValidation() + { + $this->merge([ + 'status' => $this->status ? true : false, + ]); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'title' => 'required|min:3|max:255', + 'status' => 'required|boolean' + ]; + } + + /** + * Get custom attributes for validator errors. + * + * @return array + */ + public function attributes() + { + return [ + 'title' => \trans('titre'), + 'status' => \trans('statut') + ]; + } +} diff --git a/app/Http/Requests/Bo/Documents/UpdateAppUserRequest.php b/app/Http/Requests/Bo/Documents/UpdateAppUserRequest.php new file mode 100644 index 0000000..fc65616 --- /dev/null +++ b/app/Http/Requests/Bo/Documents/UpdateAppUserRequest.php @@ -0,0 +1,7 @@ +id === 1; } + /** + * Render directories. + * + * @param mixed $directories + * @return array + */ + public static function renderDirectories(mixed $directories) + { + foreach ($directories as $k => $directory) { + $directories[$k]->name = Directory::renameDirectory($directory, ""); + } + return $directories; + } + + /** + * Rename directory. + * + * @param Directory $model + * @param string $nameDirectory + * @return array + */ + private static function renameDirectory(Directory $model, string $nameDirectory) + { + if (strlen($nameDirectory)) { + $nameDirectory = $model->name['fr'] . " / " . $nameDirectory; + } else { + $nameDirectory = $model->name['fr']; + } + if (isset($model->parent)) { + $nameDirectory = $model->renameDirectory($model->parent, $nameDirectory); + } + return $nameDirectory; + } + // * RELATIONSHIPS /** @@ -129,4 +163,14 @@ class Directory extends Model { return $this->morphedByMany(AppUser::class, 'taggable'); } + + /** + * Has Many Relationship Method. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function documents() + { + return $this->hasMany('App\Models\Document', 'directory_id'); + } } diff --git a/app/Models/Document.php b/app/Models/Document.php new file mode 100644 index 0000000..a316af7 --- /dev/null +++ b/app/Models/Document.php @@ -0,0 +1,144 @@ + TypeEnum::class, + ]; + + /** + * Perform any actions required after the model boots. + * + * @return void + */ + protected static function booted() + { + static::creating(function (self $model) { + self::assertFieldIsUnique('title', $model->title); + self::setOrder($model); + }); + } + + // * METHODS + + /** + * Asserts using validation that the field is unique. + * + * @param string $nameField + * @param string $valueField + * @param integer|null $id + * @return void + */ + private static function assertFieldIsUnique(string $nameField, string $valueField, ?int $id = null) + { + $table = (new self())->getTable(); + ToolboxHelper::assertFieldIsUnique($table, $nameField, $valueField, $id); + } + + /** + * Set order after the last element of the list. + * + * @param \Illuminate\Database\Eloquent\Model $model + * @return void + */ + private static function setOrder(Model $model): void + { + $model->order = \intval(self::query()->max('order')) + 1; + } + + /** + * Check if is directory system. + * 1 = Salon + * + * @return boolean + */ + public function getIsSystemAttribute() + { + return $this->id === 1; + } + + // * RELATIONSHIPS + + /** + * One To Many Relationship Method. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function directory() + { + return $this->belongsTo('App\Models\Directory', 'directory_id'); + } + + /** + * One To Many Relationship Method. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function parent() + { + return $this->belongsTo('App\Models\Documents', 'parent_id'); + } + + /** + * Has Many Relationship Method. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function children() + { + return $this->hasMany('App\Models\Documents', 'parent_id'); + } + + /** + * MorphedByMany appusers relation + * + * @return \Illuminate\Database\Eloquent\Relations\MorphedByMany + */ + public function appusers() + { + return $this->morphedByMany(AppUser::class, 'taggable'); + } +} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index b3f993e..0a1d664 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use App\Models\AppUser; +use App\Models\Document; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; use Illuminate\Http\Request; @@ -38,6 +39,7 @@ class RouteServiceProvider extends ServiceProvider }); Route::model('appuser', AppUser::class); + Route::model('document', Document::class); } /** diff --git a/app/Traits/Controllers/UpdateModelStatus.php b/app/Traits/Controllers/UpdateModelStatus.php new file mode 100644 index 0000000..291fe3d --- /dev/null +++ b/app/Traits/Controllers/UpdateModelStatus.php @@ -0,0 +1,26 @@ +status = !$model->status; + $model->saveOrFail(); + return redirect()->back(); + } +} diff --git a/database/factories/DocumentFactory.php b/database/factories/DocumentFactory.php new file mode 100644 index 0000000..3fa97bd --- /dev/null +++ b/database/factories/DocumentFactory.php @@ -0,0 +1,32 @@ + + */ +class DocumentFactory extends Factory +{ + /** + * The name of the factory's corresponding model. + * + * @var string + */ + protected $model = Document::class; + + /** + * Define the model's default state. + * + * @return array + */ + public function definition() + { + return [ + 'title' => $this->faker->unique()->word, + 'parent_id' => null, + ]; + } +} diff --git a/database/migrations/2023_04_05_093932_update_document_table.php b/database/migrations/2023_04_05_093932_update_document_table.php new file mode 100644 index 0000000..25a6347 --- /dev/null +++ b/database/migrations/2023_04_05_093932_update_document_table.php @@ -0,0 +1,42 @@ +dropForeign('documents_directory_foreign'); + $table->renameColumn('directory', 'directory_id'); + $table->foreign(['directory_id'])->references(['id'])->on('directories'); + $table->renameColumn('parent', 'parent_id'); + $table->renameColumn('published', 'status'); + $table->integer('order')->after('published')->comment('Ordonnance des documents.'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('documents', function (Blueprint $table) { + $table->dropForeign('documents_directory_id_foreign'); + $table->renameColumn('parent_id', 'parent'); + $table->foreign(['parent'])->references('id')->on('directories'); + $table->renameColumn('parent_id', 'parent'); + $table->renameColumn('status', 'published'); + $table->dropColumn('order'); + }); + } +} diff --git a/database/seeders/DirectorySeeder.php b/database/seeders/DirectorySeeder.php index 6f0bb43..64a5139 100644 --- a/database/seeders/DirectorySeeder.php +++ b/database/seeders/DirectorySeeder.php @@ -27,7 +27,9 @@ class DirectorySeeder extends Seeder AppUser::each(function (AppUser $model) use ($directories) { $offset = rand(1, 15); $length = rand(1, 2); - $model->directories()->saveMany($directories->slice($offset, $length)); + if (Directory::query()->where('id', $offset)->firstOrFail()->needAuthorization) { + $model->directories()->saveMany($directories->slice($offset, $length)); + } }); } } diff --git a/database/seeders/DocumentSeeder.php b/database/seeders/DocumentSeeder.php new file mode 100644 index 0000000..c1e42d4 --- /dev/null +++ b/database/seeders/DocumentSeeder.php @@ -0,0 +1,24 @@ +make()->each(function (Document $directory) use (&$i) { + $directory->order = $i; + $directory->saveOrFail(); + $i = $i + 1; + }); + } +} diff --git a/resources/lang/en/models.php b/resources/lang/en/models.php index 011065f..97110d2 100644 --- a/resources/lang/en/models.php +++ b/resources/lang/en/models.php @@ -5,6 +5,7 @@ return [ 'dashboard' => 'Dashboard', 'app_users' => 'Application\'s users', 'directories' => 'Directories', + 'documents' => 'Documents', 'users' => 'Users' ] ]; diff --git a/resources/lang/fr/models.php b/resources/lang/fr/models.php index a0b2deb..1656968 100644 --- a/resources/lang/fr/models.php +++ b/resources/lang/fr/models.php @@ -5,6 +5,7 @@ return [ 'dashboard' => 'Tableau de bord', 'app_users' => 'Application utilisateurs', 'directories' => 'Dossiers', + 'documents' => 'Documents', 'users' => 'Utilisateurs' ] ]; diff --git a/resources/sass/bo/base/_common.scss b/resources/sass/bo/base/_common.scss index a2a7dc3..5943504 100644 --- a/resources/sass/bo/base/_common.scss +++ b/resources/sass/bo/base/_common.scss @@ -1,4 +1,5 @@ .need-word-counter { + position: relative; border-radius: 0 0 0.375rem 0.375rem; &-password { diff --git a/resources/ts/bo/components/AddDocumentComponent.vue b/resources/ts/bo/components/AddDocumentComponent.vue new file mode 100644 index 0000000..279de30 --- /dev/null +++ b/resources/ts/bo/components/AddDocumentComponent.vue @@ -0,0 +1,182 @@ + + + + + diff --git a/resources/ts/bo/components/BelongsToManyDropdownComponent.vue b/resources/ts/bo/components/BelongsToManyDropdownComponent.vue index 1d48901..d2edfb2 100644 --- a/resources/ts/bo/components/BelongsToManyDropdownComponent.vue +++ b/resources/ts/bo/components/BelongsToManyDropdownComponent.vue @@ -76,6 +76,33 @@ export default defineComponent({ components: { VueTagsInputCls, }, + data(): { + name: string; + item: string; + selectedItems: CustomTag[]; + allItems: CustomTag[]; + placeholder: string; + min: number; + max: number | null; + fieldName: string; + waitingListObjects: VueTagsInput.IAddArgs[]; + allErrors: Record; + message: string | null; + } { + return { + name: "", + item: "", + selectedItems: [], + allItems: [], + placeholder: "", + min: 0, + max: null, + fieldName: "", + waitingListObjects: [], + allErrors: {}, + message: null, + }; + }, beforeMount() { if (!this.$attrs.json) { throw new Error("this component requires json"); @@ -96,36 +123,9 @@ export default defineComponent({ // * Error parsing this.allErrors = data.errors; }, - data(): { - name: string; - item: string; - selectedItems: Array; - allItems: Array; - placeholder: string; - min: number; - max: number | null; - fieldName: string; - waitingListObjects: Array; - allErrors: Record>; - message: string | null; - } { - return { - name: "", - item: "", - selectedItems: [], - allItems: [], - placeholder: "", - min: 0, - max: null, - fieldName: "", - waitingListObjects: [], - allErrors: {}, - message: null, - }; - }, methods: { - parseTags(selectedItems: Array): Array { - return selectedItems.map((item: CustomTag) => { + parseTags(selectedItems: CustomTag[]): CustomTag[] { + return selectedItems.map((item) => { item.text = String(item.label ?? item.name ?? item.title); item.slug = String(item.slug ?? slugify(item.text)); return item; @@ -153,12 +153,12 @@ export default defineComponent({ * Delete item. * @param newItems */ - changedTags(newItems: Array): void { + changedTags(newItems: CustomTag[]): void { // * Si on enleve un élement if (this.selectedItems.length > newItems.length) { // * On respecte la validation minimale if (newItems.length >= this.min) { - this.selectedItems = newItems as Array; + this.selectedItems = newItems as CustomTag[]; } else { // * Non respect de la validation minimale this.message = this.__("Nombre d'élements minimal atteint."); @@ -169,7 +169,7 @@ export default defineComponent({ } }, tagExists( - items: Array, + items: CustomTag[], tagToCheck: VueTagsInput.ITag ): CustomTag | null { let customTag: CustomTag | null = null; diff --git a/resources/ts/bo/components/ImageInputComponent.vue b/resources/ts/bo/components/ImageInputComponent.vue index f48cef6..8ad6f7e 100644 --- a/resources/ts/bo/components/ImageInputComponent.vue +++ b/resources/ts/bo/components/ImageInputComponent.vue @@ -1,53 +1,54 @@ @@ -133,6 +138,7 @@ import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome"; import { Tooltip } from "bootstrap"; import route from "../../modules/route"; import trans from "../../modules/trans"; +import sweetalertConfirm from "../../modules/sweetalertConfirm"; type DirectoryObject = { id: number; @@ -153,13 +159,15 @@ export default defineComponent({ VueNestableHandle, FontAwesomeIcon, }, - mixins: [route, trans], + mixins: [route, trans, sweetalertConfirm], data(): { intCsrf: string | null | undefined; intId: String; intDirectories: DirectoryObject[]; + intMessage: object | object[] | null; intDisplay: boolean[]; - tooltipList: HTMLButtonElement[]; + intLoading: boolean; + intTooltipList: HTMLButtonElement[]; } { return { intCsrf: document @@ -167,8 +175,10 @@ export default defineComponent({ ?.getAttribute("content"), intId: "", intDirectories: [], + intMessage: null, intDisplay: [], - tooltipList: [], + intLoading: false, + intTooltipList: [], }; }, mounted() { @@ -277,30 +287,16 @@ export default defineComponent({ return route; }, /** - * Return destroy route for a directory. + * Return edit route for a directory. * @param id * @return string */ - getDestroyDirectoryRoute(id: number): string { - const route = this.route("bo.directories.destroy", { + getEditButtonRoute(id: number): string { + const route = this.route("bo.settings.edit", { ID: id, }); if (!route) { - throw new Error("Undefined route bo.directories.destroy"); - } - return route; - }, - /** - * Return authorization route for a directory. - * @param id - * @return string - */ - getAuthorizationDirectoryRoute(id: number): string { - const route = this.route("bo.directories.need-authorization", { - ID: id, - }); - if (!route) { - throw new Error("Undefined route bo.directories.need-authorization"); + throw new Error("Undefined route bo.settings.edit"); } return route; }, @@ -317,6 +313,101 @@ export default defineComponent({ this.updateBootstrapTooltip(); }); }, + /** + * Update authorization for a specific directory. + * @param LaravelModel model + */ + updateAuthorization(model: LaravelModel) { + this.intLoading = true; + const route = this.route("bo.directories.need-authorization", { + ID: model.id as number, + }); + if (!route) { + throw new Error("Undefined route bo.directories.need-authorization"); + } + window.axios + .post(route, { id: model.id }) + .then((reponse) => { + this.intDirectories.forEach((directory, directoryindex) => { + if (directory.id === reponse.data.id) { + this.intDirectories[directoryindex] = reponse.data; + } + }); + this.intLoading = false; + this.$nextTick(() => { + this.updateBootstrapTooltip(); + }); + }) + .catch((error) => { + if (error.response) { + console.error(error.response.data); + } else if (error.request) { + console.error(error.request); + } else { + // Something happened in setting up the request that triggered an Error. + console.error("Error", error.message); + } + }); + }, + /** + * Update authorization for a specific directory. + * @param LaravelModel model + */ + deleteDirectory(e: Event, model: LaravelModel) { + const btnConfirmDelete = this.$refs.confirmDelete as HTMLButtonElement; + (async () => { + const promise = new Promise((resolve: (value: boolean) => void) => { + sweetalertConfirm.methods.confirm( + "Confirmez", + "Êtes vous sure ?", + btnConfirmDelete, + function (response) { + resolve(response.isConfirmed); + }, + { icon: "warning" } + ); + return false; + }); + if (await promise) { + this.intLoading = true; + const route = this.route("bo.directories.destroy", { + ID: model.id as number, + }); + if (!route) { + throw new Error("Undefined route bo.directories.destroy"); + } + window.axios + .post(route, { id: model.id, _method: "DELETE" }) + .then((reponse) => { + if (reponse.data[0] !== undefined) { + this.intDirectories = this.recursiveDir(reponse.data); + } else { + this.intMessage = reponse.data; + setTimeout(() => { + this.intMessage = null; + this.$nextTick(() => { + this.updateBootstrapTooltip(); + }); + }, 6000); + } + this.intLoading = false; + this.$nextTick(() => { + this.updateBootstrapTooltip(); + }); + }) + .catch((error) => { + if (error.response) { + console.error(error.response.data); + } else if (error.request) { + console.error(error.request); + } else { + // Something happened in setting up the request that triggered an Error. + console.error("Error", error.message); + } + }); + } + })(); + }, /** * Update Bootstrap tooltips. */ @@ -326,18 +417,18 @@ export default defineComponent({ ".directories-" + this.intId + " [data-bs=\"tooltip\"]" ) ) as HTMLButtonElement[]; - let tmp = newTooltipList.filter((x) => !this.tooltipList.includes(x)); + let tmp = newTooltipList.filter((x) => !this.intTooltipList.includes(x)); tmp.map((tooltip) => { return new Tooltip(tooltip); }); this.closeBootstrapTooltip(); - this.tooltipList = newTooltipList; + this.intTooltipList = newTooltipList; }, /** * Close all Bootstrap tooltips. */ closeBootstrapTooltip() { - this.tooltipList.forEach((tooltip) => { + this.intTooltipList.forEach((tooltip) => { tooltip.blur(); Tooltip.getInstance(tooltip)?.hide(); }); @@ -345,3 +436,19 @@ export default defineComponent({ }, }); + diff --git a/resources/ts/utilities/fontawesome.ts b/resources/ts/utilities/fontawesome.ts index e2b30cb..680b19b 100644 --- a/resources/ts/utilities/fontawesome.ts +++ b/resources/ts/utilities/fontawesome.ts @@ -40,6 +40,8 @@ import { faCircleCheck, faCircleXmark, faFloppyDisk, + faVideo, + faFile, } from "@fortawesome/free-solid-svg-icons"; config.autoReplaceSvg = false; @@ -79,6 +81,8 @@ library.add(faLockOpen); library.add(faCircleCheck); library.add(faCircleXmark); library.add(faFloppyDisk); +library.add(faFile); +library.add(faVideo); // Front library.add(faChevronLeft); diff --git a/resources/views/bo/layout.blade.php b/resources/views/bo/layout.blade.php index ef242bb..3505608 100644 --- a/resources/views/bo/layout.blade.php +++ b/resources/views/bo/layout.blade.php @@ -7,14 +7,14 @@ @include('bo.layouts.header') -
+
@include('modules.flash-message')
-
+
@include('modules.breadcrumb.breadcrumb-body')
diff --git a/resources/views/bo/layouts/header.blade.php b/resources/views/bo/layouts/header.blade.php index 0884889..a0516fd 100644 --- a/resources/views/bo/layouts/header.blade.php +++ b/resources/views/bo/layouts/header.blade.php @@ -1,4 +1,4 @@ -
-
+ @csrf - @method('PUT') @include('bo.pages.app-users.form')
diff --git a/resources/views/bo/pages/app-users/edit.blade.php b/resources/views/bo/pages/app-users/edit.blade.php index 6215128..003e1a1 100644 --- a/resources/views/bo/pages/app-users/edit.blade.php +++ b/resources/views/bo/pages/app-users/edit.blade.php @@ -44,7 +44,7 @@
- + @csrf @method('PUT') @include('bo.pages.app-users.form', ['model' => $app_userModel]) diff --git a/resources/views/bo/pages/app-users/index-list.blade.php b/resources/views/bo/pages/app-users/index-list.blade.php index 984d069..ccb5291 100644 --- a/resources/views/bo/pages/app-users/index-list.blade.php +++ b/resources/views/bo/pages/app-users/index-list.blade.php @@ -20,21 +20,21 @@ {{ $app_usersModel->lastname }} - + {{ $app_usersModel->firstname }} - + {{ $app_usersModel->email }} @if(!$noOrder or $rst) - + @csrf @@ -45,7 +45,7 @@ @csrf @@ -79,7 +79,7 @@ @endforeach @else - + {{ __('Aucun résultat pour les :models', ['models' => __('models.classes.users')]) }} diff --git a/resources/views/bo/pages/app-users/index.blade.php b/resources/views/bo/pages/app-users/index.blade.php index e643867..2574e81 100644 --- a/resources/views/bo/pages/app-users/index.blade.php +++ b/resources/views/bo/pages/app-users/index.blade.php @@ -19,9 +19,13 @@ action="{{ route('bo.app-users.import') }}" method="POST" enctype="multipart/form-data"> - + @csrf - @@ -38,18 +42,13 @@
@include('bo.modules.search-bar') -
-
- {{ $app_users->withQueryString()->onEachSide(1)->links() }} -
-
-
+
@include('bo.pages.app-users.index-list')
-
+
{{ $app_users->withQueryString()->onEachSide(1)->links() }}
diff --git a/resources/views/bo/pages/dashboard.blade.php b/resources/views/bo/pages/dashboard.blade.php index b7546b7..80433b3 100644 --- a/resources/views/bo/pages/dashboard.blade.php +++ b/resources/views/bo/pages/dashboard.blade.php @@ -5,11 +5,42 @@ @section('breadcrumb', 'no') @section('content') -
-
-
+ @csrf @method('PUT') @include('bo.pages.directories.form', ['model' => $directoryModel]) diff --git a/resources/views/bo/pages/directories/form.blade.php b/resources/views/bo/pages/directories/form.blade.php index afe1ee2..5f68050 100644 --- a/resources/views/bo/pages/directories/form.blade.php +++ b/resources/views/bo/pages/directories/form.blade.php @@ -10,7 +10,7 @@ 'label' => __('Nom du :model en français', ['model' => Str::singular(__('models.classes.directories'))]), 'hasWordCounter' => true, 'name' => 'name[fr]', - 'value' => $directoryModel->name['fr'], + 'value' => $directoryModel->name['fr'] ?? "", 'required' => true, 'model' => $directoryModel ?? null, 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), @@ -31,7 +31,7 @@ 'label' => __('Nom du :model en anglais', ['model' => Str::singular(__('models.classes.directories'))]), 'hasWordCounter' => true, 'name' => 'name[en]', - 'value' => $directoryModel->name['en'], + 'value' => $directoryModel->name['en'] ?? "", 'required' => true, 'model' => $directoryModel ?? null, 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), @@ -52,7 +52,7 @@ 'label' => __('Nom du :model en allemand', ['model' => Str::singular(__('models.classes.directories'))]), 'hasWordCounter' => true, 'name' => 'name[de]', - 'value' => $directoryModel->name['de'], + 'value' => $directoryModel->name['de'] ?? "", 'required' => true, 'model' => $directoryModel ?? null, 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), @@ -73,7 +73,7 @@ 'label' => __('Nom du :model en néerlandais', ['model' => Str::singular(__('models.classes.directories'))]), 'hasWordCounter' => true, 'name' => 'name[nl]', - 'value' => $directoryModel->name['nl'], + 'value' => $directoryModel->name['nl'] ?? "", 'required' => true, 'model' => $directoryModel ?? null, 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), diff --git a/resources/views/bo/pages/directories/index.blade.php b/resources/views/bo/pages/directories/index.blade.php index 5ffaa37..cb8e1e0 100644 --- a/resources/views/bo/pages/directories/index.blade.php +++ b/resources/views/bo/pages/directories/index.blade.php @@ -20,14 +20,12 @@
+ method="POST"> @csrf - @method('PUT')
@include('modules.input-error', [ - 'inputName' => "name", + 'inputName' => "name.fr", 'helperId' => 'directoryNameHelp', 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), ]) diff --git a/resources/views/bo/pages/documents/create.blade.php b/resources/views/bo/pages/documents/create.blade.php index d007db5..d4a2938 100644 --- a/resources/views/bo/pages/documents/create.blade.php +++ b/resources/views/bo/pages/documents/create.blade.php @@ -33,7 +33,7 @@
- + @csrf @method('PUT') @include('bo.pages.documents.form') diff --git a/resources/views/bo/pages/documents/edit.blade.php b/resources/views/bo/pages/documents/edit.blade.php index 92ffd4e..ae1b114 100644 --- a/resources/views/bo/pages/documents/edit.blade.php +++ b/resources/views/bo/pages/documents/edit.blade.php @@ -27,7 +27,7 @@ @method('DELETE') @csrf
- + @csrf @method('PUT') @include('bo.pages.documents.form', ['model' => $documentModel]) diff --git a/resources/views/bo/pages/documents/form.blade.php b/resources/views/bo/pages/documents/form.blade.php index 2b207e5..678b637 100644 --- a/resources/views/bo/pages/documents/form.blade.php +++ b/resources/views/bo/pages/documents/form.blade.php @@ -16,6 +16,43 @@
+ {{-- TAGS --}} +
+
+ {{ __('Étiquettes') }} +
+
+ @include('bo.partials.inputs.pivot-belongs-to-many', [ + 'id' => 'app_userAuthorizedFolders', + 'name' => 'tags', + 'label' => __('Étiquettes associées'), + 'model' => $documentModel ?? null, + 'itemsList' => $tags, + 'itemLimit' => [0,5], + 'placeholder' => __('Recherchez une étiquette'), + 'helper' => __('Sélectionner des étiquettes parmis la liste (0 minimum et 5 maximum).'), + ]) +
+
+
+
+ {{-- STATUS --}} +
+
+ {{ __('Publication') }} +
+
+ @include('bo.partials.inputs.boolean-switch', [ + 'id' => 'documentStatus', + 'name' => 'status', + 'label' => __('État de publication'), + 'model' => $documentModel ?? null, + 'helper' => __('Le document est publié ou non.') + ]) +
+
+
+
@push('scripts') diff --git a/resources/views/bo/pages/documents/index-list.blade.php b/resources/views/bo/pages/documents/index-list.blade.php index b875036..5ac1861 100644 --- a/resources/views/bo/pages/documents/index-list.blade.php +++ b/resources/views/bo/pages/documents/index-list.blade.php @@ -4,59 +4,85 @@ @php $rst = !is_null(request()->rst); $routeName = request()->route()->getName(); - $noOrder = Session::get("$routeName.sort_col") !== 'order' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way")); $noOrder = Session::get("$routeName.sort_col") !== '' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way")); - $cols = ['title' => __('Title'), 'directory_id' => __('Dossier'), 'order' => __('Order')]; + $cols = ['title' => __('Title'), 'directory_id' => __('Dossier'), 'document_id' => __('Document'), 'type' => __('Type'), 'order' => __('Order')]; @endphp @include('bo.modules.table-col-sorter', [ 'cols' => $cols, - 'mobileHide' => [], + 'mobileHide' => [] ]) @if ($documents->count()) @foreach ($documents as $documentModel) - + {{ $documentModel->title }} - - @if(!$documentModel->directory->is_system) + + @if(isset($documentModel->directory->is_system) && !$documentModel->directory->is_system) @endif + + @if(isset($documentModel->document_id)) + + + + @endif + + + @switch($documentModel->type) + @case("mp4") + + + + @break + @case("pdf") + + + + @break + @endswitch + @if(!$noOrder or $rst) - -
- - @csrf - - - -
+ + + @endif @@ -65,7 +91,7 @@ @method('DELETE') @csrf
@include('bo.modules.search-bar') -
-
- {{ $documents->withQueryString()->onEachSide(1)->links() }} -
-
-
+
@include('bo.pages.documents.index-list')
-
+
{{ $documents->withQueryString()->onEachSide(1)->links() }}
diff --git a/resources/views/bo/pages/settings/index-list.blade.php b/resources/views/bo/pages/settings/index-list.blade.php index 49dbcab..725e0fd 100644 --- a/resources/views/bo/pages/settings/index-list.blade.php +++ b/resources/views/bo/pages/settings/index-list.blade.php @@ -58,6 +58,7 @@ ]) @break @case(\App\Enums\SettingTypesEnum::directory()) + @if ($settingModel->value != null)
-
-
- {{ $settings->withQueryString()->onEachSide(1)->links() }} -
-
@endsection diff --git a/resources/views/bo/pages/tags/create.blade.php b/resources/views/bo/pages/tags/create.blade.php new file mode 100644 index 0000000..88cc768 --- /dev/null +++ b/resources/views/bo/pages/tags/create.blade.php @@ -0,0 +1,53 @@ +@extends('bo.layout') + +@section('title', sprintf('%s - %s', Str::singular(__('models.classes.tags')), Str::ucfirst(__('création')))) +@section('description', __('Page de création d\'un nouveau tag de l\'application.')) + +@section('breadcrumb', request()->route()->getName()) + +@section('content') +
+
+
+
+

+ + + + {{ Str::singular(__('models.classes.tags')) }} {{ Str::ucfirst(__('création')) }} +

+
+
+ +
+
+
+
+
+ @csrf + @include('bo.pages.tags.form') +
+
+ +
+
+
+
+
+@endsection diff --git a/resources/views/bo/pages/tags/edit.blade.php b/resources/views/bo/pages/tags/edit.blade.php new file mode 100644 index 0000000..54322fc --- /dev/null +++ b/resources/views/bo/pages/tags/edit.blade.php @@ -0,0 +1,65 @@ +@extends('bo.layout', ['brParam' => $tagModel]) + +@section('title', sprintf('%s - %s %s', Str::singular(__('models.classes.tags')), Str::ucfirst(__('édition')), $tagModel->title)) +@section('description', __('Page d\'édition d\'un tag de l\'application.')) + +@section('breadcrumb', request()->route()->getName()) + +@section('content') +
+
+
+
+

+ + + + {{ Str::singular(__('models.classes.tags')) }} {{ Str::ucfirst(__('édition')) }} +

+
+
+
+ @method('DELETE') + @csrf +
+ + +
+
+
+
+
+
+
+ @csrf + @method('PUT') + @include('bo.pages.tags.form', ['model' => $tagModel]) +
+
+ +
+
+
+
+
+@endsection diff --git a/resources/views/bo/pages/tags/form.blade.php b/resources/views/bo/pages/tags/form.blade.php new file mode 100644 index 0000000..6dd6ec9 --- /dev/null +++ b/resources/views/bo/pages/tags/form.blade.php @@ -0,0 +1,36 @@ +
+ {{-- NAME --}} +
+
+ {{ __('Nom') }} +
+
+ @include('bo.partials.inputs.varchar', [ + 'id' => 'tagName', + 'label' => __('Nom de l\':model', ['model' => Str::singular(__('models.classes.tags'))]), + 'hasWordCounter' => true, + 'name' => 'name', + 'required' => true, + 'model' => $tagModel ?? null, + 'helper' => __('Doit posséder 3 caractères minimum, 255 maximum.'), + 'placeholder' => "Un beau nom" + ]) +
+
+
+
+
+ +@push('scripts') + +@endpush diff --git a/resources/views/bo/pages/tags/index-list.blade.php b/resources/views/bo/pages/tags/index-list.blade.php new file mode 100644 index 0000000..b6ada10 --- /dev/null +++ b/resources/views/bo/pages/tags/index-list.blade.php @@ -0,0 +1,84 @@ +
+ + + @php + $rst = !is_null(request()->rst); + $routeName = request()->route()->getName(); + $noOrder = Session::get("$routeName.sort_col") !== '' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way")); + $cols = ['name' => __('Nom'), 'order' => __('Order')]; + @endphp + @include('bo.modules.table-col-sorter', [ + 'cols' => $cols, + 'mobileHide' => [], + ]) + + + @if ($tags->count()) + @foreach ($tags as $tagModel) + + + @if(!$noOrder or $rst) + + @endif + + + @endforeach + @else + + + + @endif + +
+ {{ $tagModel->name }} + + + + +
+
+ @method('DELETE') + @csrf +
+ + + + +
+
+
+
+ + {{ __('Aucun résultat pour les :models', ['models' => __('models.classes.tags')]) }} + +
+
diff --git a/resources/views/bo/pages/tags/index.blade.php b/resources/views/bo/pages/tags/index.blade.php new file mode 100644 index 0000000..0b948e4 --- /dev/null +++ b/resources/views/bo/pages/tags/index.blade.php @@ -0,0 +1,43 @@ +@extends('bo.layout') + +@section('title', sprintf('%s - %s', __('models.classes.tags'), Str::ucfirst(__('liste')))) +@section('description', __('Page de contôle sur tous les tags de l\'application.')) + +@section('breadcrumb', request()->route()->getName()) + +@section('content') +
+
+
+
+

+ {{ __('models.classes.tags') }} {{ Str::ucfirst(__('liste')) }} +

+
+
+
+ + + +
+
+
+
+
+ @include('bo.modules.search-bar') +
+
+ @include('bo.pages.tags.index-list') +
+
+
+
+ {{ $tags->withQueryString()->onEachSide(1)->links() }} +
+
+
+
+@endsection diff --git a/resources/views/bo/partials/inputs/bigint-foreign-id.blade.php b/resources/views/bo/partials/inputs/bigint-foreign-id.blade.php index a36d13b..3601a6d 100644 --- a/resources/views/bo/partials/inputs/bigint-foreign-id.blade.php +++ b/resources/views/bo/partials/inputs/bigint-foreign-id.blade.php @@ -2,14 +2,15 @@ @endif @include('modules.input-error', [ 'inputName' => $name, - 'helperId' => "{{ $id }}Help", + 'helperId' => $id . "Help", 'helper' => $helper ]) diff --git a/resources/views/bo/partials/inputs/pivot-belongs-to-many.blade.php b/resources/views/bo/partials/inputs/pivot-belongs-to-many.blade.php index 159094b..35c4698 100644 --- a/resources/views/bo/partials/inputs/pivot-belongs-to-many.blade.php +++ b/resources/views/bo/partials/inputs/pivot-belongs-to-many.blade.php @@ -7,8 +7,8 @@ $data = [ 'name' => $name, 'value' => old($name, $model->{$name} ?? []) ?? [], - 'placeholder' => $placeholder, - 'itemsList' => $itemsList, + 'placeholder' => $placeholder ?? "", + 'itemsList' => $itemsList ?? [], 'itemLimit' => $itemLimit ?? null, 'errors' => $errors->getBag('default')->getMessages() ?? [] ]; @@ -16,6 +16,6 @@ $data = [
@include('modules.input-error', [ 'inputName' => $name, - 'helperId' => "{$id}Help", + 'helperId' => $id . "Help", 'helper' => $helper, ]) diff --git a/resources/views/modules/breadcrumb/layout.blade.php b/resources/views/modules/breadcrumb/layout.blade.php index 09528c9..518003e 100644 --- a/resources/views/modules/breadcrumb/layout.blade.php +++ b/resources/views/modules/breadcrumb/layout.blade.php @@ -1,6 +1,6 @@ @if (isset($breadcrumbs)) @unless ($breadcrumbs->isEmpty()) -