feat: ✨ add sites and gitlab users relations to user model
This commit is contained in:
parent
9377912810
commit
f00f67ae49
14 changed files with 620 additions and 31 deletions
62
app/Http/Controllers/Back/UserController.php
Normal file
62
app/Http/Controllers/Back/UserController.php
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Uwil\LaravelBackend\Controllers\UserController as BackendUserController;
|
||||
|
||||
/**
|
||||
* Handles CRUD operations for Site in the backend.
|
||||
*/
|
||||
class UserController extends BackendUserController
|
||||
{
|
||||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $callback
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(
|
||||
Request $request,
|
||||
mixed $callback = null,
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return parent::store($request, function ($request, $user) {
|
||||
$validatedData = $request->validated();
|
||||
$user->sites()->syncWithoutDetaching(Arr::get($validatedData, 'sites'));
|
||||
if (Arr::get($validatedData, 'gitlab_id')) {
|
||||
$user->gitlabUser()->create([
|
||||
'gitlab_id' => Arr::get($validatedData, 'gitlab_id'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param mixed $user
|
||||
* @param mixed $callback
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
Request $request,
|
||||
mixed $user,
|
||||
mixed $callback = null,
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return parent::update($request, $user, function ($request, $user) {
|
||||
$validatedData = $request->validated();
|
||||
$user->sites()->sync(Arr::get($validatedData, 'sites'));
|
||||
if (Arr::get($validatedData, 'gitlab_id')) {
|
||||
$user->gitlabUser()->updateOrCreate(
|
||||
['user_id' => $user->id],
|
||||
['gitlab_id' => $validatedData['gitlab_id']],
|
||||
);
|
||||
} else {
|
||||
$user->gitlabUser()->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
namespace App\Http\Requests\Back\Users\Concerns;
|
||||
|
||||
use Uwil\LaravelBackend\Support\UserRoleRegistry;
|
||||
|
||||
/**
|
||||
* Shared validation rules for user requests.
|
||||
*/
|
||||
trait HasUserRequestRules
|
||||
{
|
||||
/**
|
||||
* Resolve role flags from the current request input.
|
||||
*
|
||||
* @return array{isClient:boolean,isProjectManager:boolean,isDevelopper:boolean}
|
||||
*/
|
||||
private function resolveRoleFlags(): array
|
||||
{
|
||||
$role = $this->input('role');
|
||||
return [
|
||||
'isClient' => $role === UserRoleRegistry::get('client')->value,
|
||||
'isProjectManager' => $role === UserRoleRegistry::get('project-manager')->value,
|
||||
'isDevelopper' => $role === UserRoleRegistry::get('developper')->value,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function extraPrepareForValidation(): void
|
||||
{
|
||||
[
|
||||
'isClient' => $isClient,
|
||||
'isProjectManager' => $isProjectManager,
|
||||
'isDevelopper' => $isDevelopper,
|
||||
] = $this->resolveRoleFlags();
|
||||
|
||||
$this->merge([
|
||||
'gitlab_id' => $isProjectManager || $isDevelopper ? $this->input('gitlab_id') : null,
|
||||
'sites' => $isClient ? $this->input('sites') : null,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extra validation rules.
|
||||
*
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
protected function extraRules(): array
|
||||
{
|
||||
[
|
||||
'isClient' => $isClient,
|
||||
'isProjectManager' => $isProjectManager,
|
||||
'isDevelopper' => $isDevelopper,
|
||||
] = $this->resolveRoleFlags();
|
||||
|
||||
return [
|
||||
'gitlab_id' => $isProjectManager || $isDevelopper ? 'required|integer|min:1' : 'nullable|integer|min:1',
|
||||
'sites' => $isClient ? 'required|array' : 'nullable|array',
|
||||
'sites.*' => 'integer|exists:sites,id|distinct',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extra attributes.
|
||||
*
|
||||
* @return array<string,string>
|
||||
*/
|
||||
protected function extraAttributes(): array
|
||||
{
|
||||
return [
|
||||
'gitlab_id' => trans('validation.custom.gitlab_id'),
|
||||
'sites' => trans_choice('models.classes.sites', \INF),
|
||||
];
|
||||
}
|
||||
}
|
||||
48
app/Http/Requests/Back/Users/StoreUserRequest.php
Normal file
48
app/Http/Requests/Back/Users/StoreUserRequest.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\Users;
|
||||
|
||||
use App\Http\Requests\Back\Users\Concerns\HasUserRequestRules;
|
||||
use Uwil\LaravelBackend\Requests\Users\StoreUserRequest as BackendStoreUserRequest;
|
||||
|
||||
/**
|
||||
* Handles authorization and validation for creating a new user.
|
||||
*/
|
||||
class StoreUserRequest extends BackendStoreUserRequest
|
||||
{
|
||||
use HasUserRequestRules;
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\Override]
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
parent::prepareForValidation();
|
||||
$this->extraPrepareForValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
#[\Override]
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(parent::rules(), $this->extraRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
#[\Override]
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(parent::attributes(), $this->extraAttributes());
|
||||
}
|
||||
}
|
||||
48
app/Http/Requests/Back/Users/UpdateUserRequest.php
Normal file
48
app/Http/Requests/Back/Users/UpdateUserRequest.php
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\Users;
|
||||
|
||||
use App\Http\Requests\Back\Users\Concerns\HasUserRequestRules;
|
||||
use Uwil\LaravelBackend\Requests\Users\UpdateUserRequest as BackendUpdateUserRequest;
|
||||
|
||||
/**
|
||||
* Handles authorization and validation for creating a new user.
|
||||
*/
|
||||
class UpdateUserRequest extends BackendUpdateUserRequest
|
||||
{
|
||||
use HasUserRequestRules;
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
#[\Override]
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
parent::prepareForValidation();
|
||||
$this->extraPrepareForValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
#[\Override]
|
||||
public function rules(): array
|
||||
{
|
||||
return array_merge(parent::rules(), $this->extraRules());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
#[\Override]
|
||||
public function attributes(): array
|
||||
{
|
||||
return array_merge(parent::attributes(), $this->extraAttributes());
|
||||
}
|
||||
}
|
||||
39
app/Models/GitlabUser.php
Normal file
39
app/Models/GitlabUser.php
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the gitlab user.
|
||||
* @property integer $user_id Gitlab id of the user.
|
||||
* @property integer $gitlab_id Id of the user.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab user was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab user was updated.
|
||||
*/
|
||||
class GitlabUser extends Model
|
||||
{
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
#[\Override]
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'gitlab_id',
|
||||
];
|
||||
|
||||
// * RELATIONSHIPS.
|
||||
|
||||
/**
|
||||
* Get user of the gitlab id.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<\App\Models\User,\App\Models\GitlabUser>
|
||||
*/
|
||||
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
|
|
@ -3,14 +3,18 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Mails\Auth\LinkResetPasswordMail;
|
||||
use App\Models\GitlabUser;
|
||||
use App\Models\UserPassword;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Uwil\LaravelBackend\Models\User as BackendUser;
|
||||
|
||||
/**
|
||||
* Extends the package User model with password-based authentication support.
|
||||
* Extends the package User model with some additionnal data.
|
||||
*
|
||||
* @property-read \App\Models\UserPassword|null $userPassword Associated password.
|
||||
* @property-read \App\Models\UserPassword|null $userPassword User's associated password.
|
||||
* @property-read \App\Models\GitlabUser|null $gitlabUser User's associated gitlab id.
|
||||
* @property-read \App\Models\Site|null $sites User's associated sites.
|
||||
* @see \Uwil\LaravelBackend\Models\User For all other properties and methods.
|
||||
*/
|
||||
class User extends BackendUser
|
||||
|
|
@ -20,11 +24,37 @@ class User extends BackendUser
|
|||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
#[\Override]
|
||||
public static $cacheRelations = [
|
||||
'userPassword',
|
||||
'gitlabUser',
|
||||
'sites',
|
||||
];
|
||||
|
||||
/**
|
||||
* Except some fields to the user model fill.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
#[\Override]
|
||||
public static $exceptFromFill = [
|
||||
'gitlab_id',
|
||||
'sites',
|
||||
];
|
||||
|
||||
/**
|
||||
* Relations should be share to views.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\Override]
|
||||
public static function propsRelations(): array
|
||||
{
|
||||
return [
|
||||
'gitlabUser',
|
||||
'sites' => fn($q) => $q->withoutGlobalScope(SoftDeletingScope::class),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the password for authentication.
|
||||
* Retrieves the hashed password from the related user_passwords table.
|
||||
|
|
@ -70,7 +100,17 @@ class User extends BackendUser
|
|||
}
|
||||
|
||||
/**
|
||||
* Get sites associated to the brand.
|
||||
* Get the user's associated gitlab id.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne<\App\Models\GitlabUser,\App\Models\User>
|
||||
*/
|
||||
public function gitlabUser(): \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
{
|
||||
return $this->hasOne(GitlabUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get sites associated to the user.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany<\App\Models\Site>
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -32,14 +32,20 @@ return [
|
|||
|
||||
/**
|
||||
*--------------------------------------------------------------------------
|
||||
* Models
|
||||
* User
|
||||
*--------------------------------------------------------------------------
|
||||
*
|
||||
* This option may be used when overriding the User model.
|
||||
* - user: class.
|
||||
* This options may be used when overriding the User model.
|
||||
* - model: class.
|
||||
* - store: class.
|
||||
* - update: class.
|
||||
*/
|
||||
|
||||
'models' => [
|
||||
'user' => \App\Models\User::class,
|
||||
'user' => [
|
||||
'model' => \App\Models\User::class,
|
||||
'requests' => [
|
||||
'store' => \App\Http\Requests\Back\Users\StoreUserRequest::class,
|
||||
'update' => \App\Http\Requests\Back\Users\UpdateUserRequest::class,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_users', function (Blueprint $table) {
|
||||
$table->id()->comment('Id of the gitlab user.');
|
||||
$table->unsignedBigInteger('gitlab_id')->unique()->comment('Gitlab id of the user.');
|
||||
$table->foreignId('user_id')->unique()->comment('Id of the user.')->constrained()->cascadeOnDelete();
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the gitlab user was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the gitlab user was updated.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_users');
|
||||
}
|
||||
};
|
||||
|
|
@ -3,11 +3,15 @@
|
|||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
"your_field" => "Votre :field",
|
||||
"model_archived" => ":model est actuellement archivé|:model est actuellement archivée",
|
||||
"access_url" => "Accéder à l'url",
|
||||
"form_title_urls" => "URLs d'accès",
|
||||
"form_subtitle_urls" => "Renseigner les liens de recette et de production liés à ce modèle de données.",
|
||||
"select_element" => "Sélectionner :element",
|
||||
"urls" => "URLs",
|
||||
"your_field" => "Votre :field",
|
||||
"model_archived" => ":model est actuellement archivé|:model est actuellement archivée",
|
||||
"access_url" => "Accéder à l'url",
|
||||
"form_title_urls" => "URLs d'accès",
|
||||
"form_subtitle_urls" => "Renseigner les liens de recette et de production liés à ce modèle de données.",
|
||||
"select_element" => "Sélectionner :element",
|
||||
"urls" => "URLs",
|
||||
"form_title_sites" => "Associations",
|
||||
"form_subtitle_sites" => "Modifier les sites accessibles à ce modèle de données.",
|
||||
"form_title_git" => "Intégration",
|
||||
"form_subtitle_git" => "Modifier l'identifiant de l'utilisateur Gitlab.",
|
||||
];
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
// * Packages
|
||||
import { useForm, usePage } from "@inertiajs/react";
|
||||
import { BookTextIcon, EyeIcon } from "lucide-react";
|
||||
import { BookTextIcon, CableIcon, EyeIcon, GitGraphIcon } from "lucide-react";
|
||||
// * Other
|
||||
import SimpleString from "@/back/Components/Inputs/SimpleString";
|
||||
import SimpleSwitch from "@/back/Components/Inputs/SimpleSwitch";
|
||||
import SimpleNumber from "@/back/Components/Inputs/SimpleNumber";
|
||||
import EnumSelect from "@/back/Components/Inputs/EnumSelect";
|
||||
import { ModelSelect } from "@/back/Components/Inputs/ModelSelect";
|
||||
import FieldsetWrapper from "@/back/Components/FieldsetWrapper";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import str from "@/hooks/use-string";
|
||||
|
|
@ -12,6 +14,7 @@ import InputError from "@/back/Components/InputError";
|
|||
import { AuthProp, UserModel } from "@/back/types/global";
|
||||
import SubmitButton from "@/back/Components/SubmitButton";
|
||||
import useCrudSubmit from "@/back/hooks/use-crud-submit";
|
||||
import { extractIdsFromDatabasePivotRelation } from "@/lib/mapPivotOptions";
|
||||
|
||||
export default function Form({
|
||||
model,
|
||||
|
|
@ -28,7 +31,9 @@ export default function Form({
|
|||
}) {
|
||||
const userModel = (usePage().props.auth as AuthProp).user;
|
||||
const enumUserRole = usePage().props.enumUserRole as UserModel["role"][];
|
||||
const isConceptor = enumUserRole.find((role) => role.name === "conceptor");
|
||||
const getEnumRoleValue = (name: string) =>
|
||||
enumUserRole.find((role) => role.name === name)?.value;
|
||||
|
||||
const filterRoles = (value: number) => {
|
||||
return (
|
||||
Object.entries(enumUserRole)
|
||||
|
|
@ -43,9 +48,11 @@ export default function Form({
|
|||
first_name: model?.first_name,
|
||||
last_name: model?.last_name,
|
||||
email: model?.email,
|
||||
role: model && model.role ? model.role.value : undefined,
|
||||
sites: extractIdsFromDatabasePivotRelation(model?.sites),
|
||||
gitlab_id: model?.gitlab_user?.gitlab_id,
|
||||
published: model?.published ?? false,
|
||||
published_at: model?.published_at,
|
||||
role: model && model.role ? model.role.value : undefined,
|
||||
});
|
||||
|
||||
const submit = useCrudSubmit({
|
||||
|
|
@ -140,26 +147,105 @@ export default function Form({
|
|||
.ucFirst()
|
||||
.value()}
|
||||
placeholder="ex: john.doe@gmail.com"
|
||||
disabled={!isConceptor!.value}
|
||||
wordCounter={Boolean(isConceptor!.value)}
|
||||
value={!isConceptor!.value ? model?.email : data.email}
|
||||
disabled={!(userModel.role.value === getEnumRoleValue("conceptor"))}
|
||||
wordCounter={userModel.role.value === getEnumRoleValue("conceptor")}
|
||||
value={
|
||||
userModel.role.value === getEnumRoleValue("conceptor")
|
||||
? model?.email
|
||||
: data.email
|
||||
}
|
||||
setData={setData}
|
||||
/>
|
||||
{Boolean(isConceptor!.value) && (
|
||||
{userModel.role.value === getEnumRoleValue("conceptor") && (
|
||||
<EnumSelect
|
||||
name="role"
|
||||
options={
|
||||
model?.role && userModel.role.value !== isConceptor!.value
|
||||
model?.role &&
|
||||
userModel.role.value !== getEnumRoleValue("conceptor")
|
||||
? filterRoles(model?.role.value)
|
||||
: enumUserRole
|
||||
}
|
||||
label={transAssociateToRole}
|
||||
selected={data.role ? data.role : undefined}
|
||||
setData={(name, value) => setData(name, value?.value ?? value)}
|
||||
setData={(name, value) => {
|
||||
setData(name, value?.value ?? value);
|
||||
// Reset sites if not client.
|
||||
if (value?.value !== getEnumRoleValue("client")) {
|
||||
setData("sites", []);
|
||||
}
|
||||
// Reset gitlab_id if not project-manager or developper.
|
||||
if (
|
||||
value?.value !== getEnumRoleValue("project-manager") &&
|
||||
value?.value !== getEnumRoleValue("developper")
|
||||
) {
|
||||
setData("gitlab_id", undefined);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</FieldsetWrapper>
|
||||
{userModel.role.value === isConceptor!.value &&
|
||||
{userModel.role.value === getEnumRoleValue("conceptor") &&
|
||||
data.role === getEnumRoleValue("client") && (
|
||||
<FieldsetWrapper
|
||||
title={useTrans("back.form_title_sites")}
|
||||
icon={<CableIcon className="mr-1" />}
|
||||
description={useTrans("back.form_subtitle_sites")}
|
||||
>
|
||||
<ModelSelect
|
||||
name="sites"
|
||||
targetModel="sites"
|
||||
field="name"
|
||||
label={str(
|
||||
useTrans("uwil-backend::back.form_associate_to", {
|
||||
params: {
|
||||
attribute: useTrans("models.classes.sites", {
|
||||
choice: 2,
|
||||
}),
|
||||
},
|
||||
choice: 1,
|
||||
}),
|
||||
)
|
||||
.ucFirst()
|
||||
.value()}
|
||||
placeholder="ex: John Doe"
|
||||
defaultValues={data.sites}
|
||||
setData={setData}
|
||||
maxCount={10}
|
||||
hideSelectAll={true}
|
||||
required={true}
|
||||
multiple={true}
|
||||
closeButtonVisible={true}
|
||||
/>
|
||||
</FieldsetWrapper>
|
||||
)}
|
||||
{userModel.role.value === getEnumRoleValue("conceptor") &&
|
||||
(data.role === getEnumRoleValue("project-manager") ||
|
||||
data.role === getEnumRoleValue("developper")) && (
|
||||
<FieldsetWrapper
|
||||
title={useTrans("back.form_title_git")}
|
||||
icon={<GitGraphIcon className="mr-1" />}
|
||||
description={useTrans("back.form_subtitle_git")}
|
||||
inline
|
||||
>
|
||||
<SimpleNumber
|
||||
name="gitlab_id"
|
||||
label={str(
|
||||
useTrans("uwil-backend::back.form_associate_to", {
|
||||
params: {
|
||||
attribute: useTrans("validation.custom.gitlab_id"),
|
||||
},
|
||||
choice: 1,
|
||||
}),
|
||||
)
|
||||
.ucFirst()
|
||||
.value()}
|
||||
placeholder="ex: 100"
|
||||
value={data.gitlab_id}
|
||||
setData={setData}
|
||||
/>
|
||||
</FieldsetWrapper>
|
||||
)}
|
||||
{userModel.role.value === getEnumRoleValue("conceptor") &&
|
||||
userModel.email !== model?.email && (
|
||||
<FieldsetWrapper
|
||||
title={transFormTitleVisibility}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
// * Packages
|
||||
import { ArrowLeftIcon, CheckIcon, MailIcon, XIcon } from "lucide-react";
|
||||
import {
|
||||
ArrowLeftIcon,
|
||||
CheckIcon,
|
||||
GlobeIcon,
|
||||
MailIcon,
|
||||
TriangleAlertIcon,
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { route } from "ziggy-js";
|
||||
// * Components shadcn
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
// * Other
|
||||
import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
|
||||
import DetailsTable from "@/back/Components/Table/DetailsTable";
|
||||
|
|
@ -14,9 +26,23 @@ import { GetFormatedDate, GetTranslation } from "@/lib/utils";
|
|||
import { AuthProp, SingleResource, UserModel } from "@/back/types/global";
|
||||
import str from "@/hooks/use-string";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import { AppEnv } from "@/types/global";
|
||||
import { GitlabUser, SiteModel } from "@/back/types/project";
|
||||
|
||||
const getColumns = () => {
|
||||
return [
|
||||
const getColumns = (
|
||||
appEnv: AppEnv,
|
||||
viewAnySites: boolean,
|
||||
enumUserRole: UserModel["role"][],
|
||||
model: UserModel,
|
||||
) => {
|
||||
const getEnumRoleValue = (name: string) =>
|
||||
enumUserRole.find((role) => role.name === name)?.value;
|
||||
|
||||
const isClient = model.role?.value === getEnumRoleValue("client");
|
||||
const isGitlabUser =
|
||||
model.role?.value === getEnumRoleValue("project-manager") ||
|
||||
model.role?.value === getEnumRoleValue("developper");
|
||||
const columns = [
|
||||
{
|
||||
accessorKey: "first_name",
|
||||
header: str(
|
||||
|
|
@ -61,6 +87,101 @@ const getColumns = () => {
|
|||
</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "sites",
|
||||
header: str(GetTranslation("models.classes.sites", { choice: 2 }))
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: Array<SiteModel> }) => {
|
||||
if (value.length) {
|
||||
const projectData = (siteModel: SiteModel) => (
|
||||
<span>{siteModel.name[appEnv.locale]}</span>
|
||||
);
|
||||
return (
|
||||
<div className="flex flex-row flex-wrap justify-start items-center gap-1.5">
|
||||
{value.map((siteModel) => {
|
||||
let content = (
|
||||
<div className="flex flex-row justify-start items-center">
|
||||
<Badge variant="outline">{projectData(siteModel)}</Badge>
|
||||
{siteModel.deleted_at !== null && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<TriangleAlertIcon
|
||||
size={15}
|
||||
className="text-destructive ms-1"
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{GetTranslation("back.model_archived", {
|
||||
params: {
|
||||
model: str(
|
||||
GetTranslation(
|
||||
"models.classes.gitlab-projects",
|
||||
{
|
||||
choice: 1,
|
||||
},
|
||||
),
|
||||
)
|
||||
.ucFirst()
|
||||
.value(),
|
||||
},
|
||||
choice: 1,
|
||||
})}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
if (viewAnySites && siteModel.deleted_at === null) {
|
||||
content = (
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route("back.sites.show", siteModel)}
|
||||
content={
|
||||
<>
|
||||
<GlobeIcon />
|
||||
{projectData(siteModel)}
|
||||
</>
|
||||
}
|
||||
tooltipContent={
|
||||
<p>
|
||||
{GetTranslation("uwil-backend::back.access_model", {
|
||||
params: {
|
||||
model: GetTranslation("models.classes.sites", {
|
||||
choice: 1,
|
||||
}),
|
||||
},
|
||||
})}
|
||||
</p>
|
||||
}
|
||||
type="button"
|
||||
size="default"
|
||||
variant="secondary"
|
||||
/>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="flex flex-row flex-wrap justify-start items-center gap-1.5">
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<p className="text-muted-foreground italic m-0">
|
||||
{GetTranslation("uwil-backend::back.table_not_known")}
|
||||
</p>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "gitlab_user",
|
||||
header: str(GetTranslation("validation.custom.gitlab_id"))
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: GitlabUser }) => value.gitlab_id,
|
||||
},
|
||||
{
|
||||
accessorKey: "published",
|
||||
header: str(GetTranslation("uwil-backend::validation.custom.published"))
|
||||
|
|
@ -124,6 +245,13 @@ const getColumns = () => {
|
|||
),
|
||||
},
|
||||
];
|
||||
|
||||
return columns.filter((column) => {
|
||||
if (column.accessorKey === "role" && isClient) return false;
|
||||
if (column.accessorKey === "sites" && !isClient) return false;
|
||||
if (column.accessorKey === "gitlab_user" && !isGitlabUser) return false;
|
||||
return true;
|
||||
});
|
||||
};
|
||||
|
||||
export default function Show({
|
||||
|
|
@ -133,13 +261,16 @@ export default function Show({
|
|||
data: SingleResource;
|
||||
modelName: string;
|
||||
}) {
|
||||
const { auth } = usePage().props as unknown as {
|
||||
const { auth, appEnv, enumUserRole } = usePage().props as unknown as {
|
||||
auth: AuthProp;
|
||||
appEnv: AppEnv;
|
||||
enumUserRole: UserModel["role"][];
|
||||
};
|
||||
const { viewAny } = auth.policies.users;
|
||||
const { viewAny: viewAnySites } = auth.policies.sites;
|
||||
const model = data.data as UserModel;
|
||||
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
|
||||
const columns = getColumns();
|
||||
const columns = getColumns(appEnv, viewAnySites, enumUserRole, model);
|
||||
|
||||
// Translations.
|
||||
const transTitle = useTrans(
|
||||
|
|
|
|||
4
resources/ts/back/types/global.d.ts
vendored
4
resources/ts/back/types/global.d.ts
vendored
|
|
@ -1,6 +1,8 @@
|
|||
// * Packages
|
||||
import { AxiosInstance } from "axios";
|
||||
import { ElementType } from "react";
|
||||
// * Other
|
||||
import { GitlabUser, SiteModel } from "@/back/types/project";
|
||||
|
||||
// Policy related types.
|
||||
type ModelPolicy = {
|
||||
|
|
@ -25,6 +27,8 @@ type UserModel = DefaultModel & {
|
|||
last_name: string;
|
||||
email: string;
|
||||
role: { value: number; label: string; name: string };
|
||||
sites: Array<SiteModel>;
|
||||
gitlab_user: GitlabUser;
|
||||
published: boolean;
|
||||
published_at: Date;
|
||||
};
|
||||
|
|
|
|||
8
resources/ts/back/types/project.d.ts
vendored
8
resources/ts/back/types/project.d.ts
vendored
|
|
@ -18,6 +18,14 @@ type InvoiceCompanyModel = DefaultModel & {
|
|||
name: TranslationField;
|
||||
};
|
||||
|
||||
type GitlabUser = {
|
||||
id: number;
|
||||
gitlab_id: number;
|
||||
user_id: number;
|
||||
created_at: Date;
|
||||
updated_at: Date;
|
||||
}
|
||||
|
||||
type GitlabProjectModel = DefaultModel & {
|
||||
name: TranslationField;
|
||||
url: string;
|
||||
|
|
|
|||
6
routes/back/users.php
Normal file
6
routes/back/users.php
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Back\UserController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::resource('users', UserController::class);
|
||||
Loading…
Add table
Reference in a new issue