Merge branch 'multiple-updates' into 'laravel-10'

Multiple updates

See merge request ldc-web/projets/laravel-base-project!32
This commit is contained in:
Vincent BRIDIER 2024-01-31 15:12:09 +00:00
commit 5720dbe9d4
17 changed files with 93 additions and 175 deletions

View file

@ -8,6 +8,7 @@ use Carbon\Carbon;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Illuminate\Support\Str;
class UserCreate extends Command
{
@ -200,18 +201,22 @@ class UserCreate extends Command
try {
$tmp = $this->choice(
'Select his role',
[RoleEnum::conceptor->label(), RoleEnum::admin->label(), RoleEnum::visitor->label()],
RoleEnum::visitor->label(),
[
Str::ucFirst(RoleEnum::conceptor->label()),
Str::ucFirst(RoleEnum::admin->label()),
Str::ucFirst(RoleEnum::visitor->label())
],
Str::ucFirst(RoleEnum::visitor->label()),
$maxAttempts = null,
$allowMultipleSelections = false
);
if ($tmp === RoleEnum::conceptor->label()) {
if ($tmp === Str::ucFirst(RoleEnum::conceptor->label())) {
$tmp = RoleEnum::conceptor;
}
if ($tmp === RoleEnum::admin->label()) {
if ($tmp === Str::ucFirst(RoleEnum::admin->label())) {
$tmp = RoleEnum::admin;
}
if ($tmp === RoleEnum::visitor->label()) {
if ($tmp === Str::ucFirst(RoleEnum::visitor->label())) {
$tmp = RoleEnum::visitor;
}
$validator = Validator::make(['role' => $tmp], [

View file

@ -26,7 +26,7 @@ class UpdateStaticPageRequest extends FormRequest
public function prepareForValidation(): void
{
$this->merge([
'content' => (string)Str::of($this->input('content'))
'content' => Str::of($this->input('content'))->value()
]);
}

View file

@ -3,6 +3,7 @@
namespace App\Http\Requests\Bo\Users;
use App\Enums\Users\RoleEnum;
use App\Models\User;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Gate;
use Illuminate\Validation\Rules\Enum;

View file

@ -1,6 +1,16 @@
// * LAYOUT
body {
> nav {
.navbar-toggler.collapsed .navbar-toggler-icon-close {
display: none;
}
.navbar-toggler:not(.collapsed) .navbar-toggler-icon {
display: inline;
}
}
> main {
min-height: calc(100vh - #{$bo-header-height} - #{$bo-footer-height});
margin-top: $bo-header-height;

View file

@ -10,7 +10,7 @@
type="button"
:title="visible ? __('vue.PasswordVisibility.hide') : __('vue.PasswordVisibility.show')"
data-bs="tooltip"
data-bs-toggle="tooltip"
>
<FontAwesomeIcon
@ -30,13 +30,13 @@
<script lang="ts">
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import { Tooltip } from "bootstrap";
import { defineComponent } from "vue";
import bsTooltips from "./../../modules/bsTooltips";
import trans from "./../../modules/trans";
export default defineComponent({
name: "PasswordVisibility",
mixins: [trans],
mixins: [bsTooltips, trans],
components: { FontAwesomeIcon },
data(): {
inputId: string;
@ -68,7 +68,7 @@ export default defineComponent({
}
this.input = this.input as HTMLInputElement;
this.$nextTick(() => {
this.updateBootstrapTooltip();
this.initTooltips();
});
},
methods: {
@ -97,32 +97,7 @@ export default defineComponent({
this.visible = false;
}
this.$nextTick(() => {
this.updateBootstrapTooltip();
});
},
/**
* Update Bootstrap tooltips.
*/
updateBootstrapTooltip() {
let newTooltipList = [].slice.call(
document.querySelectorAll(
".password-visibility-" + this.inputId + " [data-bs=\"tooltip\"]"
)
) as HTMLButtonElement[];
let tmp = newTooltipList.filter((x) => !this.tooltipList.includes(x));
tmp.map((tooltip) => {
return new Tooltip(tooltip);
});
this.closeBootstrapTooltip();
this.tooltipList = newTooltipList;
},
/**
* Close all Bootstrap tooltips.
*/
closeBootstrapTooltip() {
this.tooltipList.forEach((tooltip) => {
tooltip.blur();
Tooltip.getInstance(tooltip)?.hide();
this.initTooltips();
});
},
},

View file

@ -1,10 +1,7 @@
import { config, dom, library } from "@fortawesome/fontawesome-svg-core";
import {
faArrowAltCircleDown,
faArrowAltCircleUp,
faArrowDown,
faArrowLeft,
faArrowLeftLong,
faArrowRight,
faArrowRightFromBracket,
faArrowUp,
@ -12,14 +9,10 @@ import {
faArrowsAltV,
faBackspace,
faBan,
faCheck,
faChevronLeft,
faChevronRight,
faCircleCheck,
faCircleExclamation,
faCircleInfo,
faCircleNotch,
faCircleXmark,
faCopy,
faCrop,
faEraser,
@ -35,17 +28,15 @@ import {
faSearch,
faSearchMinus,
faSearchPlus,
faSliders,
faSyncAlt,
faTimes,
faTrash,
faUndoAlt,
faWandMagic
faWandMagic,
faXmark
} from "@fortawesome/free-solid-svg-icons";
config.autoReplaceSvg = false;
library.add(faEraser);
library.add(faArrowLeftLong);
library.add(faPlus);
library.add(faTrash);
library.add(faEye);
@ -53,7 +44,6 @@ library.add(faEyeSlash);
library.add(faFolderOpen);
library.add(faCrop);
library.add(faQuestionCircle);
library.add(faCheck);
library.add(faUndoAlt);
library.add(faRedoAlt);
library.add(faSyncAlt);
@ -67,26 +57,17 @@ library.add(faArrowsAltH);
library.add(faArrowsAltV);
library.add(faWandMagic);
library.add(faPencil);
library.add(faTimes);
library.add(faBackspace);
library.add(faSearch);
library.add(faArrowRightFromBracket);
library.add(faArrowAltCircleDown);
library.add(faArrowAltCircleUp);
library.add(faCircleCheck);
library.add(faCircleXmark);
library.add(faCopy);
library.add(faListUl);
library.add(faBan);
library.add(faCircleExclamation);
library.add(faCircleInfo);
library.add(faPaintRoller);
// Front
library.add(faXmark);
library.add(faChevronLeft);
library.add(faChevronRight);
library.add(faCircleXmark);
library.add(faCircleNotch);
library.add(faSliders);
dom.watch();

View file

@ -1,90 +1,19 @@
import { dom, library, config } from "@fortawesome/fontawesome-svg-core";
import { config, dom, library } from "@fortawesome/fontawesome-svg-core";
import {
faEraser,
faArrowLeftLong,
faPlus,
faTrash,
faEye,
faFolderOpen,
faCrop,
faQuestionCircle,
faCheck,
faUndoAlt,
faRedoAlt,
faSyncAlt,
faSearchPlus,
faSearchMinus,
faArrowLeft,
faArrowRight,
faArrowUp,
faArrowDown,
faArrowsAltH,
faArrowsAltV,
faWandMagic,
faPencil,
faTimes,
faBackspace,
faSearch,
faArrowRightFromBracket,
faArrowAltCircleDown,
faArrowAltCircleUp,
faChevronLeft,
faChevronRight,
faCircleNotch,
faSliders,
faCircleCheck,
faCircleXmark,
faCopy,
faListUl,
faBan,
faEyeSlash,
faCircleExclamation,
faCircleInfo
faCircleInfo,
faCirclePlay,
faCircleXmark,
faQuestionCircle
} from "@fortawesome/free-solid-svg-icons";
config.autoReplaceSvg = false;
library.add(faEraser);
library.add(faArrowLeftLong);
library.add(faPlus);
library.add(faTrash);
library.add(faEye);
library.add(faEyeSlash);
library.add(faFolderOpen);
library.add(faCrop);
library.add(faQuestionCircle);
library.add(faCheck);
library.add(faUndoAlt);
library.add(faRedoAlt);
library.add(faSyncAlt);
library.add(faSearchPlus);
library.add(faSearchMinus);
library.add(faArrowLeft);
library.add(faArrowRight);
library.add(faArrowUp);
library.add(faArrowDown);
library.add(faArrowsAltH);
library.add(faArrowsAltV);
library.add(faWandMagic);
library.add(faPencil);
library.add(faTimes);
library.add(faBackspace);
library.add(faSearch);
library.add(faArrowRightFromBracket);
library.add(faArrowAltCircleDown);
library.add(faArrowAltCircleUp);
library.add(faCircleCheck);
library.add(faCircleXmark);
library.add(faCopy);
library.add(faListUl);
library.add(faBan);
library.add(faCircleExclamation);
library.add(faCircleInfo);
// Front
library.add(faChevronLeft);
library.add(faChevronRight);
library.add(faCircleXmark);
library.add(faCircleNotch);
library.add(faSliders);
library.add(faCirclePlay);
library.add(faQuestionCircle);
dom.watch();

View file

@ -4,12 +4,11 @@ let tooltips: Array<bootstrap.Tooltip> = [];
export default {
methods: {
/**
* Initialize all Bootstrap tooltips.
*/
initTooltips() {
// Disable tooltips on reboot.
tooltips.forEach((tooltip) => {
tooltip.disable();
tooltip.hide();
});
this.disableBootstrapTooltip();
tooltips = [].slice
.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"))
.map(function (tooltipTriggerEl) {
@ -22,5 +21,25 @@ export default {
});
});
},
/**
* Disable all Bootstrap tooltips.
*/
disableBootstrapTooltip() {
tooltips.forEach((tooltip) => {
tooltip.disable();
tooltip.hide();
});
},
/**
* Close all Bootstrap tooltips.
*/
closeBootstrapTooltip() {
[].slice
.call(document.querySelectorAll("[data-bs-toggle=\"tooltip\"]"))
.forEach((tooltip: HTMLElement) => {
tooltip.blur();
window.bootstrap.Tooltip.getInstance(tooltip)?.hide();
});
},
},
};

View file

@ -5,9 +5,10 @@
{{ config('app.name', 'Laravel') }}
</a>
@auth
<button class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" type="button"
<button class="navbar-toggler collapsed" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" type="button"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
<i class="navbar-toggler-icon-close fa-solid fa-xmark fa-xl px-1"></i>
</button>
@endauth
@ -18,10 +19,11 @@
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ms-auto">
<!-- Bootstrap themes -->
<li class="nav-item dropdown @auth border-end @endauth">
<li class="nav-item dropdown @auth border-lg-end @endauth">
<button class="btn nav-link dropdown-toggle d-flex align-items-center h-100 flex-row border-0 pe-3"
data-bs-toggle="dropdown" type="button" aria-expanded="false">
<i class="fa-solid fa-paint-roller"></i>
<i class="d-none d-lg-block fa-solid fa-paint-roller"></i>
<span class="d-lg-none">{{ __('Thème') }}</span>
</button>
<form class="dropdown-menu dropdown-menu-end text-center" id="theme-selector" action="{{ route('bo.theme.set') }}"
method="POST">
@ -52,9 +54,9 @@
<!-- Authentication Links -->
@auth
<li class="nav-item dropdown">
<button class="btn nav-link dropdown-toggle d-flex align-items-center h-100 flex-row border-0 ps-3" id="navbarDropdown"
data-bs-toggle="dropdown" type="button">
<div class="d-flex flex-column align-items-end lh-1">
<button class="btn nav-link dropdown-toggle d-flex align-items-center h-100 ps-lg-3 flex-row border-0"
id="navbarDropdown" data-bs-toggle="dropdown" type="button">
<div class="d-flex flex-column align-items-start align-items-lg-end lh-1">
<span
class="fw-bold">{{ auth('backend')->user()->first_name }}&nbsp;{{ auth('backend')->user()->last_name }}</span>
<small class="text-secondary-body">{{ Str::of(auth('backend')->user()->role->label())->ucFirst() }}</small>

View file

@ -1,5 +1,5 @@
@auth('backend')
<ul class="navbar-nav me-auto">
<ul class="navbar-nav border-top border-lg-0 mt-lg-0 me-auto mt-2">
<li class="nav-item">
<a class="nav-link @if (request()->routeIs('bo.dashboard')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.dashboard') }}"
title="{{ __('Revenir à l\'accueil') }}">
@ -25,17 +25,18 @@
<ol class="dropdown-menu">
@can('viewAny', \App\Models\User::class)
<li>
<a class="dropdown-item @if (request()->routeIs('bo.users.*')) active @endif" data-bs-toggle="tooltip"
href="{{ route('bo.users.index') }}"
<a class="dropdown-item text-lg-start @if (request()->routeIs('bo.users.*')) active @endif p-2 text-center"
data-bs-toggle="tooltip" href="{{ route('bo.users.index') }}"
title="{{ __('crud.helpers.list_all', ['model' => Str::plural(__('models.classes.user'))]) }}">
{{ Str::of(__('models.classes.user'))->plural()->ucfirst() }}
</a>
</li>
@endcan
@can('isConceptor')
<hr class="dropdown-divider m-0">
<li>
<a class="dropdown-item @if (request()->routeIs('bo.activity_logs.*')) active @endif" data-bs-toggle="tooltip"
href="{{ route('bo.activity_logs.index') }}"
<a class="dropdown-item text-lg-start @if (request()->routeIs('bo.activity_logs.*')) active @endif p-2 text-center"
data-bs-toggle="tooltip" href="{{ route('bo.activity_logs.index') }}"
title="{{ __('crud.helpers.list_all', ['model' => trans_choice('models.classes.activity_log', '*')]) }}">
{{ Str::of(trans_choice('models.classes.activity_log', '*'))->ucfirst() }}
</a>

View file

@ -27,6 +27,7 @@
@csrf
@method('PUT')
@include('bo.pages.static_pages.form')
@include('bo.partials.script-button-clone')
<div class="row">
<div class="col text-center">
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"

View file

@ -147,17 +147,3 @@
<p><b>{{ __('* Champs obligatoires') }}</b></p>
</div>
</div>
@push('scripts')
<script nonce="{{ $nonce }}">
document.addEventListener("DOMContentLoaded", () => {
// Submit button clone.
const submit = document.getElementById('formSubmit')
submitClone = document.getElementById('formSubmitClone');
submitClone.addEventListener('click', (event) => {
event.preventDefault();
submit.click('');
})
});
</script>
@endpush

View file

@ -24,6 +24,7 @@
<form action="{{ route('bo.users.store') }}" method="POST" enctype="multipart/form-data">
@csrf
@include('bo.pages.users.form')
@include('bo.partials.script-button-clone')
<div class="row mt-3">
<div class="col text-center">
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"

View file

@ -40,6 +40,7 @@
@csrf
@method('PUT')
@include('bo.pages.users.form')
@include('bo.partials.script-button-clone')
<div class="row">
<div class="col text-center">
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"

View file

@ -148,14 +148,6 @@
@push('scripts')
<script nonce="{{ $nonce }}">
document.addEventListener("DOMContentLoaded", () => {
// Submit button clone.
const submit = document.getElementById('formSubmit')
submitClone = document.getElementById('formSubmitClone');
submitClone.addEventListener('click', (event) => {
event.preventDefault();
submit.click('');
})
// If we edit the password, the confirmation is required.
const passwordInput = document.getElementById('userPassword');
const confirmPasswordInput = document.getElementById('userPassword_confirmation');

View file

@ -0,0 +1,12 @@
@push('scripts')
<script nonce="{{ $nonce }}">
document.addEventListener("DOMContentLoaded", () => {
const submit = document.getElementById('formSubmit')
submitClone = document.getElementById('formSubmitClone');
submitClone.addEventListener('click', (event) => {
event.preventDefault();
submit.click('');
})
});
</script>
@endpush

View file

@ -44,7 +44,9 @@ Route::prefix('bo')
'edit' => 'static_pages.edit',
'update' => 'static_pages.update',
])->parameters(['pages' => 'static_page'])
->only(['index', 'edit', 'update']);
->only(['index', 'edit', 'update'])
->withoutMiddleware('htmlsanitize')
->middleware(['htmlsanitize:content']);
Route::middleware('can:isConceptor')->group(function () {
// * ACTIVITY LOGS.