feat: ✨ add gitlab tables (labels/issues/milestones)
This commit is contained in:
parent
0fd8682021
commit
b865e75f48
43 changed files with 844 additions and 1264 deletions
|
|
@ -1,249 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Back;
|
||||
|
||||
use App\Http\Requests\Back\GitlabProjects\StoreGitlabProjectRequest;
|
||||
use App\Http\Requests\Back\GitlabProjects\UpdateGitlabProjectRequest;
|
||||
use App\Models\GitlabProject;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
use Uwil\LaravelBackend\Controllers\BackendController;
|
||||
use Uwil\LaravelBackend\Resources\CommonResource;
|
||||
|
||||
/**
|
||||
* Handles CRUD operations for GitlabProject in the backend.
|
||||
*/
|
||||
class GitlabProjectController extends BackendController
|
||||
{
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->authorizeResource(GitlabProject::class);
|
||||
$this->modelName = GitlabProject::modelName();
|
||||
$this->modelPage = GitlabProject::modelPage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function index(Request $request): \Inertia\Response
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder<\App\Models\GitlabProject> $query */
|
||||
$query = GitlabProject::query();
|
||||
|
||||
if ($request->routeIs("{$this->routeName}{$this->modelName}.trash")) {
|
||||
$query = $query->onlyTrashed();
|
||||
}
|
||||
|
||||
/** @var string $search Search field */
|
||||
$search = $request->search;
|
||||
if ($search) {
|
||||
$this->searchQuery(
|
||||
$query,
|
||||
$search,
|
||||
null,
|
||||
'name',
|
||||
);
|
||||
}
|
||||
$searchFields = \implode(', ', [
|
||||
trans('validation.attributes.name'),
|
||||
]);
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($query);
|
||||
|
||||
/** Custom pagination */
|
||||
$models = $this->paginate($query);
|
||||
|
||||
return $this->inertiaRender("back/Pages/$this->modelPage/Index", [
|
||||
'models' => CommonResource::collection($models),
|
||||
'search' => $search,
|
||||
'searchFields' => $searchFields,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function create(GitlabProject $gitlab_project): \Inertia\Response
|
||||
{
|
||||
return $this->inertiaRender("back/Pages/$this->modelPage/Create", [
|
||||
'data' => CommonResource::make($gitlab_project),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a specific resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function show(GitlabProject $gitlab_project): \Inertia\Response
|
||||
{
|
||||
return $this->inertiaRender("back/Pages/$this->modelPage/Show", [
|
||||
'data' => CommonResource::make($gitlab_project),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\GitlabProjects\StoreGitlabProjectRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(StoreGitlabProjectRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$gitlab_project = new GitlabProject();
|
||||
$gitlab_project->fill($request->validated());
|
||||
|
||||
if ($gitlab_project->saveOrFail()) {
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.edit", $gitlab_project)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_created', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_created', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function edit(GitlabProject $gitlab_project): \Inertia\Response
|
||||
{
|
||||
return $this->inertiaRender("back/Pages/$this->modelPage/Edit", [
|
||||
'data' => CommonResource::make($gitlab_project),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource.
|
||||
*
|
||||
* @param \App\Http\Requests\Back\GitlabProjects\UpdateGitlabProjectRequest $request
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(
|
||||
UpdateGitlabProjectRequest $request,
|
||||
GitlabProject $gitlab_project
|
||||
): \Illuminate\Http\RedirectResponse {
|
||||
return DB::transaction(function () use ($request, $gitlab_project) {
|
||||
$gitlab_project->fill($request->validated());
|
||||
|
||||
if ($gitlab_project->saveOrFail()) {
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.edit", $gitlab_project)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_updated', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.edit", $gitlab_project)
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_updated', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate the specified resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Inertia\Response
|
||||
*/
|
||||
public function duplicate(GitlabProject $gitlab_project): \Inertia\Response
|
||||
{
|
||||
$gitlab_project->loadMissing(GitlabProject::$cacheRelations ?? []);
|
||||
$replica = $gitlab_project->replicate();
|
||||
collect($gitlab_project->getRelations())->each(fn($value, $relation) => $replica->setRelation($relation, $value));
|
||||
return $this->create($replica);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the specified resource.
|
||||
*
|
||||
* @param integer $gitlab_project
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function restore(int $gitlab_project): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$gitlab_project = GitlabProject::withTrashed()->findOrFail($gitlab_project);
|
||||
/** @var array<string,string> */
|
||||
$previousQueries = [];
|
||||
\parse_str(\parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries);
|
||||
if ($gitlab_project->restore()) {
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.trash", $previousQueries)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_restored', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_restored', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the specified resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject $gitlab_project
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(GitlabProject $gitlab_project): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
/** @var array<string,string> */
|
||||
$previousQueries = [];
|
||||
\parse_str(\parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries);
|
||||
if ($gitlab_project->delete()) {
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.index", $previousQueries)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the specified resource.
|
||||
*
|
||||
* @param \App\Models\GitlabProject|integer $gitlab_project
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function forceDestroy(GitlabProject|int $gitlab_project): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if (is_int($gitlab_project)) {
|
||||
$gitlab_project = GitlabProject::withTrashed()->findOrFail($gitlab_project);
|
||||
}
|
||||
/** @var array<string,string> */
|
||||
$previousQueries = [];
|
||||
\parse_str(\parse_url(url()->previous(), \PHP_URL_QUERY), $previousQueries);
|
||||
if ($gitlab_project->forceDelete()) {
|
||||
return redirect()->route("{$this->routeName}{$this->modelName}.trash", $previousQueries)
|
||||
->with('success', trans('uwil-backend::crud.messages.has_been_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
return redirect()->back()
|
||||
->with('error', trans('uwil-backend::crud.messages.cannot_be_deleted', [
|
||||
'model' => Str::ucfirst(trans_choice("models.classes.$this->modelName", 1)),
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\GitlabProjects;
|
||||
|
||||
use App\Models\GitlabProject;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/**
|
||||
* Handles authorization and validation for creating a new GitlabProject.
|
||||
*/
|
||||
class StoreGitlabProjectRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::check('create', GitlabProject::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|between:3,255',
|
||||
'url' => 'required|string|url:http,https|unique:gitlab_projects,url',
|
||||
'gitlab_id' => 'required|integer|unique:gitlab_projects,gitlab_id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'name' => trans('validation.custom.name'),
|
||||
'url' => trans('validation.custom.url'),
|
||||
'gitlab_id' => trans('validation.custom.gitlab_id'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Back\GitlabProjects;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
/**
|
||||
* Handles authorization and validation for updating an existing GitlabProject.
|
||||
*/
|
||||
class UpdateGitlabProjectRequest extends StoreGitlabProjectRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
#[\Override]
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::check('update', $this->route('gitlab_project'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
#[\Override]
|
||||
public function rules(): array
|
||||
{
|
||||
/** @var \App\Models\GitlabProject $gitlab_project */
|
||||
$gitlab_project = $this->route('gitlab_project');
|
||||
return array_merge(parent::rules(), [
|
||||
'url' => [
|
||||
'required',
|
||||
'string',
|
||||
'url:http,https',
|
||||
Rule::unique('gitlab_projects', 'url')->ignore($gitlab_project->getRouteKey()),
|
||||
],
|
||||
'gitlab_id' => [
|
||||
'required',
|
||||
'integer',
|
||||
Rule::unique('gitlab_projects', 'gitlab_id')->ignore($gitlab_project->getRouteKey()),
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,11 +11,11 @@ use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
|||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the brand.
|
||||
* @property string $name Name of the brand.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the Brand was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the Brand was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the Brand was deleted.
|
||||
* @property integer $id Primary key of the brand.
|
||||
* @property string $name Name of the brand.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the brand was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the brand was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the brand was deleted.
|
||||
*/
|
||||
class Brand extends Model
|
||||
{
|
||||
|
|
|
|||
105
app/Models/GitlabIssue.php
Normal file
105
app/Models/GitlabIssue.php
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelI18n\Helpers\TranslationHelper;
|
||||
use Uwil\LaravelI18n\Interfaces\TranslatableModel;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Primary key of the gitlab issue.
|
||||
* @property string $name Name of the gitlab issue.
|
||||
* @property string $url Url of the gitlab issue.
|
||||
* @property string $estimate_time Estimate time of the gitlab issue.
|
||||
* @property string $spent_time Spend time of the gitlab issue.
|
||||
* @property string $is_closed Closed status of the gitlab issue.
|
||||
* @property string $gitlab_id Gitlab id of the gitlab issue.
|
||||
* @property string $gitlab_iid Gitlab iid of the gitlab issue.
|
||||
* @property string $milestone_iid Milestone iid of the gitlab issue.
|
||||
* @property string $gitlab_project_id Gitlab project id of the gitlab issue.
|
||||
* @property string $g_created_at Created at date of the gitlab issue.
|
||||
* @property string $g_updated_at Updated at date of the gitlab issue.
|
||||
* @property string $g_closed_at Closed at date of the gitlab issue.
|
||||
* @property string $g_due_date Due at date of the gitlab issue.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab issue was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab issue was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab issue was deleted.
|
||||
*/
|
||||
class GitlabIssue extends Model implements TranslatableModel
|
||||
{
|
||||
use HasActivityLog;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\GitlabIssueFactory> */
|
||||
use HasFactory;
|
||||
use HasTranslations;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
"title",
|
||||
"url",
|
||||
"estimate_time",
|
||||
"spent_time",
|
||||
"is_closed",
|
||||
"gitlab_id",
|
||||
"gitlab_iid",
|
||||
"milestone_iid",
|
||||
"gitlab_project_id",
|
||||
"g_created_at",
|
||||
"g_updated_at",
|
||||
"g_closed_at",
|
||||
"g_due_date",
|
||||
];
|
||||
|
||||
/**
|
||||
* The translatable columns.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public $translatable = [
|
||||
"title",
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_closed' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS.
|
||||
|
||||
/**
|
||||
* Manage model fields.
|
||||
*
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(self $model): void
|
||||
{
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->title, 'title');
|
||||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
}
|
||||
38
app/Models/GitlabIssueLabel.php
Normal file
38
app/Models/GitlabIssueLabel.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
|
||||
/**
|
||||
* @property \Illuminate\Support\Carbon $issue_id Gitlab issue id of the relation.
|
||||
* @property \Illuminate\Support\Carbon $label_id Gitlab label id of the relation.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab issue label was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab issue label was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab issue label was deleted.
|
||||
*/
|
||||
class GitlabIssueLabel extends Model
|
||||
{
|
||||
use HasActivityLog;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\GitlabIssueLabelFactory> */
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The table associated with the model.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $table = 'gitlab_issues_labels';
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'issue_id',
|
||||
'label_id',
|
||||
];
|
||||
}
|
||||
74
app/Models/GitlabLabel.php
Normal file
74
app/Models/GitlabLabel.php
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelI18n\Helpers\TranslationHelper;
|
||||
use Uwil\LaravelI18n\Interfaces\TranslatableModel;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Primary key of the gitlab label.
|
||||
* @property string $name Name of the gitlab label.
|
||||
* @property integer $gitlab_id Gitlab id of the gitlab label.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab label was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab label was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab label was deleted.
|
||||
*/
|
||||
class GitlabLabel extends Model implements TranslatableModel
|
||||
{
|
||||
use HasActivityLog;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\GitlabLabelFactory> */
|
||||
use HasFactory;
|
||||
use HasTranslations;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name',
|
||||
'gitlab_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* The translatable columns.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public $translatable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS.
|
||||
|
||||
/**
|
||||
* Manage model fields.
|
||||
*
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(self $model): void
|
||||
{
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->name, 'name');
|
||||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
}
|
||||
99
app/Models/GitlabMilestone.php
Normal file
99
app/Models/GitlabMilestone.php
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelI18n\Helpers\TranslationHelper;
|
||||
use Uwil\LaravelI18n\Interfaces\TranslatableModel;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Primary key of the gitlab milestone.
|
||||
* @property string $title Title of the gitlab milestone.
|
||||
* @property string $url Url of the gitlab milestone.
|
||||
* @property string $is_closed Closed status of the gitlab milestone.
|
||||
* @property string $gitlab_id Gitlab id of the gitlab milestone.
|
||||
* @property string $gitlab_iid Gitlab iid of the gitlab milestone.
|
||||
* @property string $gitlab_project_id Gitlab project id of the gitlab milestone.
|
||||
* @property string $g_created_at Created at date of the gitlab milestone.
|
||||
* @property string $g_updated_at Updated at date of the gitlab milestone.
|
||||
* @property string $g_closed_at Closed at date of the gitlab milestone.
|
||||
* @property string $g_due_date Due at date of the gitlab milestone.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab milestone was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab milestone was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab milestone was deleted.
|
||||
*/
|
||||
class GitlabMilestone extends Model implements TranslatableModel
|
||||
{
|
||||
use HasActivityLog;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\GitlabMilestoneFactory> */
|
||||
use HasFactory;
|
||||
use HasTranslations;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
"title",
|
||||
"url",
|
||||
"is_closed",
|
||||
"gitlab_id",
|
||||
"gitlab_iid",
|
||||
"gitlab_project_id",
|
||||
"g_created_at",
|
||||
"g_updated_at",
|
||||
"g_closed_at",
|
||||
"g_due_date",
|
||||
];
|
||||
|
||||
/**
|
||||
* The translatable columns.
|
||||
*
|
||||
* @var list<string>
|
||||
*/
|
||||
public $translatable = [
|
||||
"title",
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_closed' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS.
|
||||
|
||||
/**
|
||||
* Manage model fields.
|
||||
*
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(self $model): void
|
||||
{
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->title, 'title');
|
||||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,30 +4,27 @@ namespace App\Models;
|
|||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Uwil\LaravelActivityLogs\Traits\HasActivityLog;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasCache;
|
||||
use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
||||
use Uwil\LaravelI18n\Helpers\TranslationHelper;
|
||||
use Uwil\LaravelI18n\Interfaces\TranslatableModel;
|
||||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Primary key of the gitlab project relation.
|
||||
* @property string $name Name of the gitlab project.
|
||||
* @property string $url Url of the gitlab project.
|
||||
* @property \App\Models\User $gitlab_id Gitlab id of the gitlab project.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab project was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab project was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab project was deleted.
|
||||
* @property integer $id Primary key of the gitlab project.
|
||||
* @property string $name Name of the gitlab project.
|
||||
* @property string $url Url of the gitlab project.
|
||||
* @property string $is_archived Archived status of the gitlab project.
|
||||
* @property integer $gitlab_id Gitlab id of the gitlab project.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the gitlab project was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the gitlab project was updated.
|
||||
* @property-read \Illuminate\Support\Carbon $deleted_at Date the gitlab project was deleted.
|
||||
*/
|
||||
class GitlabProject extends Model
|
||||
class GitlabProject extends Model implements TranslatableModel
|
||||
{
|
||||
use HasActivityLog;
|
||||
use HasCache;
|
||||
/** @use \Illuminate\Database\Eloquent\Factories\HasFactory<\Database\Factories\GitlabProjectFactory> */
|
||||
use HasFactory;
|
||||
use HasModelNaming;
|
||||
use HasTranslations;
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
|
|
@ -37,6 +34,7 @@ class GitlabProject extends Model
|
|||
protected $fillable = [
|
||||
'name',
|
||||
'url',
|
||||
'is_archived',
|
||||
'gitlab_id',
|
||||
];
|
||||
|
||||
|
|
@ -48,4 +46,42 @@ class GitlabProject extends Model
|
|||
public $translatable = [
|
||||
'name',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string,string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'is_archived' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
self::manageFields($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS.
|
||||
|
||||
/**
|
||||
* Manage model fields.
|
||||
*
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function manageFields(self $model): void
|
||||
{
|
||||
TranslationHelper::assertTranslationFieldIsUnique($model, $model->name, 'name');
|
||||
TranslationHelper::validateFallbackTranslations($model);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use App\Models\User;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the gitlab user.
|
||||
* @property integer $id Primary key 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.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
|||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the invoice company.
|
||||
* @property integer $id Primary key of the invoice company.
|
||||
* @property string $name Name of the invoice company.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date the invoice company was created.
|
||||
* @property-read \Illuminate\Support\Carbon $updated_at Date the invoice company was updated.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
|||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the invoice package.
|
||||
* @property integer $id Primary key of the invoice package.
|
||||
* @property string $name Name of the invoice package.
|
||||
* @property string $amount Amount of the invoice package.
|
||||
* @property string $published Published status of the invoice package.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use Uwil\LaravelBackend\Traits\Models\HasModelNaming;
|
|||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the notice.
|
||||
* @property integer $id Primary key of the notice.
|
||||
* @property string $title Title of the notice.
|
||||
* @property string $message Message of the notice.
|
||||
* @property integer $type Type of the notice.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use Uwil\LaravelCommon\Helpers\ToolboxHelper;
|
|||
use Uwil\LaravelI18n\Traits\Models\HasTranslations;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the site.
|
||||
* @property integer $id Primary key of the site.
|
||||
* @property string $name Name of the site.
|
||||
* @property string $url_re7 Re7 url of the site.
|
||||
* @property string $url_prod Prod url of the site.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ namespace App\Models;
|
|||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* @property integer $id Id of the user password.
|
||||
* @property integer $id Primary key of the user password.
|
||||
* @property \App\Models\User $user_id Associated user.
|
||||
* @property string $password Password of the user.
|
||||
* @property-read \Illuminate\Support\Carbon $created_at Date on which the password was created.
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Uwil\LaravelBackend\Policies\Rules\UserStaticRules;
|
||||
use Uwil\LaravelBackend\Support\UserRoleRegistry;
|
||||
|
||||
/**
|
||||
* Handles authorization for GitlabProject model actions.
|
||||
*/
|
||||
class GitlabProjectPolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewAny(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view trash models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function viewTrash(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function view(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function create(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function update(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can duplicate the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function duplicate(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function restore(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can soft delete the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function delete(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||
* @return boolean
|
||||
*/
|
||||
public function forceDelete(Model $authModel): bool
|
||||
{
|
||||
return UserStaticRules::atLeastRole($authModel, UserRoleRegistry::get('conceptor')->value);
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@ namespace App\Providers;
|
|||
|
||||
use App\Enums\NoticeTypeEnum;
|
||||
use App\Models\Brand;
|
||||
use App\Models\GitlabIssue;
|
||||
use App\Models\GitlabLabel;
|
||||
use App\Models\GitlabProject;
|
||||
use App\Models\InvoiceCompany;
|
||||
use App\Models\InvoicePackage;
|
||||
|
|
@ -49,11 +51,6 @@ class AppServiceProvider extends ServiceProvider
|
|||
'viewTrash' => Gate::allows('viewTrash', InvoiceCompany::class),
|
||||
'create' => Gate::allows('create', InvoiceCompany::class),
|
||||
]);
|
||||
InertiaSharedRegistry::add('auth.policies.gitlabProjects', fn () => [
|
||||
'viewAny' => Gate::allows('viewAny', GitlabProject::class),
|
||||
'viewTrash' => Gate::allows('viewTrash', GitlabProject::class),
|
||||
'create' => Gate::allows('create', GitlabProject::class),
|
||||
]);
|
||||
InertiaSharedRegistry::add('auth.policies.sites', fn () => [
|
||||
'viewAny' => Gate::allows('viewAny', Site::class),
|
||||
'viewTrash' => Gate::allows('viewTrash', Site::class),
|
||||
|
|
|
|||
|
|
@ -31,6 +31,34 @@
|
|||
"slevomat/coding-standard": "^8.22"
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "path",
|
||||
"url": "packages/laravel-common",
|
||||
"options": {
|
||||
"symlink": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "packages/laravel-backend",
|
||||
"options": {
|
||||
"symlink": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "packages/laravel-i18n",
|
||||
"options": {
|
||||
"symlink": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "path",
|
||||
"url": "packages/laravel-activity-logs",
|
||||
"options": {
|
||||
"symlink": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://lab.s-web.fr/api/v4/group/23/-/packages/composer/packages.json"
|
||||
|
|
|
|||
44
database/factories/GitlabIssueFactory.php
Normal file
44
database/factories/GitlabIssueFactory.php
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\GitlabIssue;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* Factory for generating GitlabIssue model instances with randomized data.
|
||||
*/
|
||||
class GitlabIssueFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Associated model.
|
||||
*
|
||||
* @var class-string<\App\Models\GitlabIssue>
|
||||
*/
|
||||
protected $model = GitlabIssue::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$isClosed = fake()->boolean(25);
|
||||
return [
|
||||
"title" => fake()->unique()->words(3, true),
|
||||
"url" => fake()->unique()->url(),
|
||||
"estimate_time" => fake()->boolean(75) ? fake()->numberBetween(1, 32) * 900 : 0,
|
||||
"spent_time" => fake()->boolean(75) ? fake()->numberBetween(1, 32) * 900 : 0,
|
||||
"is_closed" => $isClosed,
|
||||
"gitlab_id" => fake()->unique()->numberBetween(1, 1000),
|
||||
"gitlab_iid" => fake()->numberBetween(1, 1000),
|
||||
"milestone_iid" => fake()->boolean(75) ? fake()->numberBetween(1, 1000) : null,
|
||||
"gitlab_project_id" => fake()->unique()->numberBetween(1, 1000),
|
||||
"g_created_at" => fake()->date(),
|
||||
"g_updated_at" => fake()->date(),
|
||||
"g_closed_at" => $isClosed ? fake()->date() : null,
|
||||
"g_due_date" => fake()->boolean(25) ? fake()->date() : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
34
database/factories/GitlabIssueLabelFactory.php
Normal file
34
database/factories/GitlabIssueLabelFactory.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\GitlabIssue;
|
||||
use App\Models\GitlabIssueLabel;
|
||||
use App\Models\GitlabLabel;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* Factory for generating GitlabIssueLabel model instances with randomized data.
|
||||
*/
|
||||
class GitlabIssueLabelFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Associated model.
|
||||
*
|
||||
* @var class-string<\App\Models\GitlabIssueLabel>
|
||||
*/
|
||||
protected $model = GitlabIssueLabel::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'issue_id' => GitlabIssue::factory(),
|
||||
'label_id' => GitlabLabel::factory(),
|
||||
];
|
||||
}
|
||||
}
|
||||
32
database/factories/GitlabLabelFactory.php
Normal file
32
database/factories/GitlabLabelFactory.php
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\GitlabLabel;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* Factory for generating GitlabLabel model instances with randomized data.
|
||||
*/
|
||||
class GitlabLabelFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Associated model.
|
||||
*
|
||||
* @var class-string<\App\Models\GitlabLabel>
|
||||
*/
|
||||
protected $model = GitlabLabel::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"name" => fake()->unique()->words(3, true),
|
||||
"gitlab_id" => fake()->unique()->numberBetween(1, 1000),
|
||||
];
|
||||
}
|
||||
}
|
||||
41
database/factories/GitlabMilestoneFactory.php
Normal file
41
database/factories/GitlabMilestoneFactory.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\GitlabMilestone;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* Factory for generating GitlabMilestone model instances with randomized data.
|
||||
*/
|
||||
class GitlabMilestoneFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Associated model.
|
||||
*
|
||||
* @var class-string<\App\Models\GitlabMilestone>
|
||||
*/
|
||||
protected $model = GitlabMilestone::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
$isClosed = fake()->boolean(25);
|
||||
return [
|
||||
"title" => fake()->words(3, true),
|
||||
"url" => fake()->url(),
|
||||
"is_closed" => $isClosed,
|
||||
"gitlab_id" => fake()->numberBetween(1, 1000),
|
||||
"gitlab_iid" => fake()->numberBetween(1, 1000),
|
||||
"gitlab_project_id" => fake()->numberBetween(1, 1000),
|
||||
"g_created_at" => fake()->date(),
|
||||
"g_updated_at" => fake()->date(),
|
||||
"g_closed_at" => $isClosed ? fake()->date() : null,
|
||||
"g_due_date" => fake()->boolean(25) ? fake()->date() : null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -25,9 +25,10 @@ class GitlabProjectFactory extends Factory
|
|||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
"name" => fake()->unique()->words(3, true),
|
||||
"url" => fake()->unique()->url(),
|
||||
"gitlab_id" => fake()->unique()->numberBetween(1, 1000),
|
||||
"name" => fake()->unique()->words(3, true),
|
||||
"url" => fake()->unique()->url(),
|
||||
"is_archived" => fake()->boolean(25),
|
||||
"gitlab_id" => fake()->unique()->numberBetween(1, 1000),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class SiteFactory extends Factory
|
|||
"url_re7" => fake()->boolean(75) ? fake()->unique()->url() : null,
|
||||
"url_prod" => fake()->boolean(75) ? fake()->unique()->url() : null,
|
||||
"project_manager_id" => fake()->boolean(75) ? $projectManager->getKey() : null,
|
||||
"gitlab_project_id" => fake()->unique()->randomElement(GitlabProject::pluck("id")),
|
||||
"gitlab_project_id" => GitlabProject::factory(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ return new class extends Migration
|
|||
$table->id()->comment('Primary key of the gitlab project relation.');
|
||||
$table->string('name')->comment('Name of the gitlab project.');
|
||||
$table->string('url')->unique()->comment('Url of the gitlab project.');
|
||||
$table->unsignedTinyInteger('is_archived')->comment('Archived status of the gitlab project.');
|
||||
$table->unsignedBigInteger('gitlab_id')->unique()->comment('Gitlab id of the gitlab project.');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the gitlab project was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the gitlab project was updated.');
|
||||
$table->timestamp('deleted_at')->nullable()->comment('Date the gitlab project was deleted.');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_labels', function (Blueprint $table) {
|
||||
$table->id()->comment('Id of the gitlab label.');
|
||||
$table->string('name')->unique()->comment('Name of the gitlab label.');
|
||||
$table->unsignedBigInteger('gitlab_id')->unique()->comment('Gitlab id of the gitlab label.');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the gitlab label was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the gitlab label was updated.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_labels');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_issues', function (Blueprint $table) {
|
||||
$table->id()->comment('Id of the gitlab issue.');
|
||||
$table->string('title')->comment('Title of the gitlab issue.');
|
||||
$table->string('url')->unique()->comment('Url of the gitlab issue.');
|
||||
$table->unsignedInteger('estimate_time')->default(0)->comment('Estimate time of the gitlab issue.');
|
||||
$table->unsignedInteger('spent_time')->default(0)->comment('Spend time of the gitlab issue.');
|
||||
$table->unsignedTinyInteger('is_closed')->comment('Closed status of the gitlab issue.');
|
||||
$table->unsignedInteger('gitlab_id')->unique()->comment('Gitlab id of the gitlab issue.');
|
||||
$table->unsignedInteger('gitlab_iid')->comment('Gitlab iid of the gitlab issue.');
|
||||
$table->unsignedInteger('milestone_iid')->nullable()->comment('Milestone iid of the gitlab issue.');
|
||||
$table->unsignedInteger('gitlab_project_id')->comment('Gitlab project id of the gitlab issue.');
|
||||
$table->date('g_created_at')->comment('Created at date of the gitlab issue.');
|
||||
$table->date('g_updated_at')->comment('Updated at date of the gitlab issue.');
|
||||
$table->date('g_closed_at')->nullable()->comment('Closed at date of the gitlab issue.');
|
||||
$table->date('g_due_date')->nullable()->comment('Due at date of the gitlab issue.');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the gitlab issue was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the gitlab issue was updated.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_issues');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_milestones', function (Blueprint $table) {
|
||||
$table->id()->comment('Id of the gitlab milestone.');
|
||||
$table->string('title')->comment('Title of the gitlab milestone.');
|
||||
$table->string('url')->comment('Url of the gitlab milestone.');
|
||||
$table->unsignedTinyInteger('is_closed')->comment('Closed status of the gitlab milestone.');
|
||||
$table->unsignedInteger('gitlab_id')->comment('Gitlab id of the gitlab milestone.');
|
||||
$table->unsignedInteger('gitlab_iid')->comment('Gitlab iid of the gitlab milestone.');
|
||||
$table->unsignedInteger('gitlab_project_id')->comment('Gitlab project id of the gitlab milestone.');
|
||||
$table->date('g_created_at')->comment('Created at date of the gitlab milestone.');
|
||||
$table->date('g_updated_at')->comment('Updated at date of the gitlab milestone.');
|
||||
$table->date('g_closed_at')->nullable()->comment('Closed at date of the gitlab milestone.');
|
||||
$table->date('g_due_date')->nullable()->comment('Due at date of the gitlab milestone.');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the gitlab milestone was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the gitlab milestone was updated.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_milestones');
|
||||
}
|
||||
};
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('gitlab_issues_labels', function (Blueprint $table) {
|
||||
$table->id()->comment('Id of the relation.');
|
||||
$table->foreignId('issue_id')->comment('Gitlab issue id of the relation.')
|
||||
->constrained('gitlab_issues')->onUpdate('no action')->onDelete('cascade');
|
||||
$table->foreignId('label_id')->comment('Gitlab label id of the relation.')
|
||||
->constrained('gitlab_labels')->onUpdate('no action')->onDelete('cascade');
|
||||
$table->timestamp('created_at')->nullable()->comment('Date the relation was created.');
|
||||
$table->timestamp('updated_at')->nullable()->comment('Date the relation was updated.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('gitlab_issues_labels');
|
||||
}
|
||||
};
|
||||
25
database/seeders/Classic/GitlabIssueLabelSeeder.php
Normal file
25
database/seeders/Classic/GitlabIssueLabelSeeder.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Classic;
|
||||
|
||||
use App\Models\GitlabIssueLabel;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
/**
|
||||
* Seeds the gitlab_issues_labels table.
|
||||
*/
|
||||
class GitlabIssueLabelSeeder extends Seeder
|
||||
{
|
||||
/** @var string $table Associated table to this seeder. */
|
||||
public static string $table = 'gitlab_issues_labels';
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
GitlabIssueLabel::factory(10)->create();
|
||||
}
|
||||
}
|
||||
25
database/seeders/Classic/GitlabIssueSeeder.php
Normal file
25
database/seeders/Classic/GitlabIssueSeeder.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Classic;
|
||||
|
||||
use App\Models\GitlabIssue;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
/**
|
||||
* Seeds the gitlab_issues table.
|
||||
*/
|
||||
class GitlabIssueSeeder extends Seeder
|
||||
{
|
||||
/** @var string $table Associated table to this seeder. */
|
||||
public static string $table = 'gitlab_issues';
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
GitlabIssue::factory(10)->create();
|
||||
}
|
||||
}
|
||||
25
database/seeders/Classic/GitlabLabelSeeder.php
Normal file
25
database/seeders/Classic/GitlabLabelSeeder.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Classic;
|
||||
|
||||
use App\Models\GitlabLabel;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
/**
|
||||
* Seeds the gitlab_labels table.
|
||||
*/
|
||||
class GitlabLabelSeeder extends Seeder
|
||||
{
|
||||
/** @var string $table Associated table to this seeder. */
|
||||
public static string $table = 'gitlab_labels';
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
GitlabLabel::factory(10)->create();
|
||||
}
|
||||
}
|
||||
25
database/seeders/Classic/GitlabMilestoneSeeder.php
Normal file
25
database/seeders/Classic/GitlabMilestoneSeeder.php
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders\Classic;
|
||||
|
||||
use App\Models\GitlabMilestone;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
/**
|
||||
* Seeds the gitlab_milestones table.
|
||||
*/
|
||||
class GitlabMilestoneSeeder extends Seeder
|
||||
{
|
||||
/** @var string $table Associated table to this seeder. */
|
||||
public static string $table = 'gitlab_milestones';
|
||||
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run(): void
|
||||
{
|
||||
GitlabMilestone::factory(10)->create();
|
||||
}
|
||||
}
|
||||
|
|
@ -8,6 +8,8 @@ return [
|
|||
"invoice-packages" => "devis - forfait|devis - forfaits",
|
||||
"invoice-companies" => "devis - société|devis - sociétés",
|
||||
"gitlab-projects" => "gitlab - projet|gitlab - projets",
|
||||
"gitlab-labels" => "gitlab - libellé|gitlab - libellés",
|
||||
"gitlab-issues" => "gitlab - issue|gitlab - issues",
|
||||
"sites" => "site|sites",
|
||||
"brands" => "marque|marques",
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,79 +0,0 @@
|
|||
// * Packages
|
||||
import { FolderGit2Icon } from "lucide-react";
|
||||
import { route } from "ziggy-js";
|
||||
import { Link } from "@inertiajs/react";
|
||||
// * Components shadcn
|
||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||
import { Button } from "@/components/ui/button";
|
||||
// * Other
|
||||
import {
|
||||
filterActions,
|
||||
NavListLinksProps,
|
||||
} from "@/back/Components/Layout/Sidebar/AppSidebar";
|
||||
import { SidebarGroupLink } from "@/back/Components/Layout/Sidebar/SidebarRegistry";
|
||||
import { AuthProp } from "@/back/types/global";
|
||||
import str from "@/hooks/use-string";
|
||||
import { GetTranslation } from "@/lib/utils";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import Views from "@/back/lib/actions";
|
||||
import { AppEnv } from "@/types/global";
|
||||
|
||||
export default function SidebarLinkGitlabProjects(
|
||||
auth: AuthProp,
|
||||
appEnv: AppEnv,
|
||||
): SidebarGroupLink {
|
||||
const modelName = "gitlab-projects";
|
||||
const routeName = appEnv.routes.name;
|
||||
|
||||
// Translations.
|
||||
const transModel = GetTranslation(`models.classes.${modelName}`, {
|
||||
choice: 2,
|
||||
});
|
||||
const transCreate = str(
|
||||
useTrans(`uwil-backend::crud.actions.${Views.CREATION.label}`),
|
||||
)
|
||||
.ucFirst()
|
||||
.value();
|
||||
const transArchives = str(useTrans("uwil-backend::back.archives"))
|
||||
.ucFirst()
|
||||
.value();
|
||||
|
||||
const link: NavListLinksProps = {
|
||||
title: str(transModel).ucFirst().value(),
|
||||
model: modelName,
|
||||
icon: FolderGit2Icon,
|
||||
show: auth.policies.gitlabProjects.viewAny,
|
||||
actions: (model: string) =>
|
||||
filterActions({
|
||||
auth,
|
||||
appEnv,
|
||||
model,
|
||||
items: [
|
||||
auth.policies.gitlabProjects.create && (
|
||||
<DropdownMenuItem key="create" className="p-0">
|
||||
<Button variant="ghost" asChild>
|
||||
<Link href={route(`${routeName}${model}.create`)} className="w-full">
|
||||
{/* eslint-disable-next-line react/jsx-pascal-case */}
|
||||
<Views.CREATION.icon />
|
||||
{transCreate}
|
||||
</Link>
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
),
|
||||
auth.policies.gitlabProjects.viewTrash && (
|
||||
<DropdownMenuItem className="p-0">
|
||||
<Button variant="ghost" asChild>
|
||||
<Link href={route(`${routeName}${model}.trash`)} className="w-full">
|
||||
{/* eslint-disable-next-line react/jsx-pascal-case */}
|
||||
<Views.ARCHIVATION.icon />
|
||||
{transArchives}
|
||||
</Link>
|
||||
</Button>
|
||||
</DropdownMenuItem>
|
||||
),
|
||||
],
|
||||
}),
|
||||
};
|
||||
|
||||
return { link, group: "modules" };
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
// * Packages
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { route } from "ziggy-js";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
// * Other
|
||||
import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
|
||||
import Form from "@/back/Pages/GitlabProjects/Form";
|
||||
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import { Actions, Methods } from "@/back/lib/enums";
|
||||
import { AuthProp, SingleResource } from "@/back/types/global";
|
||||
import { GitlabProjectModel } from "@/back/types/project";
|
||||
import { AppEnv } from "@/types/global";
|
||||
|
||||
export default function Create({
|
||||
data,
|
||||
modelName,
|
||||
}: {
|
||||
data: SingleResource;
|
||||
modelName: string;
|
||||
}) {
|
||||
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
|
||||
const { viewAny } = (usePage().props.auth as AuthProp).policies
|
||||
.gitlabProjects;
|
||||
const model = data.data as GitlabProjectModel;
|
||||
|
||||
// Translations.
|
||||
const transBackToList = useTrans("uwil-backend::back.crud_back_to_list");
|
||||
const transTitle = useTrans(
|
||||
route().current(`${routeName}${modelName}.duplicate`)
|
||||
? "uwil-backend::crud.helpers.duplication_model"
|
||||
: "uwil-backend::crud.helpers.creation_model",
|
||||
{
|
||||
params: {
|
||||
model: useTrans(`models.classes.${modelName}`, {
|
||||
choice: 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const beforeNode = () => {
|
||||
return (
|
||||
viewAny && (
|
||||
<div className="flex justify-end items-center gap-x-1.5">
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${routeName}${modelName}.index`)}
|
||||
content={<ArrowLeftIcon />}
|
||||
tooltipContent={<p>{transBackToList}</p>}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout title={transTitle} beforeNode={beforeNode()}>
|
||||
<Form
|
||||
model={model}
|
||||
modelName={modelName}
|
||||
modelRoute={modelName}
|
||||
action={Actions.STORE}
|
||||
method={Methods.POST}
|
||||
/>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
// * Packages
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { route } from "ziggy-js";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
// * Other
|
||||
import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
|
||||
import ModelActions from "@/back/Components/ModelActions";
|
||||
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
|
||||
import Form from "@/back/Pages/GitlabProjects/Form";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import { Actions, Methods } from "@/back/lib/enums";
|
||||
import { Views } from "@/back/lib/actions";
|
||||
import { AuthProp, SingleResource } from "@/back/types/global";
|
||||
import { GitlabProjectModel } from "@/back/types/project";
|
||||
import { AppEnv } from "@/types/global";
|
||||
|
||||
export default function Edit({
|
||||
data,
|
||||
modelName,
|
||||
}: {
|
||||
data: SingleResource;
|
||||
modelName: string;
|
||||
}) {
|
||||
const routeName = (usePage().props.appEnv as AppEnv).routes.name;
|
||||
const { viewAny } = (usePage().props.auth as AuthProp).policies
|
||||
.gitlabProjects;
|
||||
const model = data.data as GitlabProjectModel;
|
||||
const actionModels = [
|
||||
Views.VISUALIZATION,
|
||||
Views.DUPLICATION,
|
||||
Views.ARCHIVATION,
|
||||
];
|
||||
|
||||
// Translations.
|
||||
const transBackToList = useTrans("uwil-backend::back.crud_back_to_list");
|
||||
const transTitle = useTrans("uwil-backend::crud.helpers.edition_model", {
|
||||
params: {
|
||||
model: useTrans(`models.classes.${modelName}`, {
|
||||
choice: 1,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const beforeNode = () => {
|
||||
return (
|
||||
viewAny && (
|
||||
<div className="flex justify-end items-center gap-x-1.5">
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${routeName}${modelName}.index`)}
|
||||
content={<ArrowLeftIcon />}
|
||||
tooltipContent={<p>{transBackToList}</p>}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout title={transTitle} beforeNode={beforeNode()}>
|
||||
<ModelActions
|
||||
actions={actionModels}
|
||||
modelRoute={modelName}
|
||||
model={model}
|
||||
modelUpdatedAt={model.updated_at?.toString()}
|
||||
/>
|
||||
<Form
|
||||
model={model}
|
||||
modelName={modelName}
|
||||
modelRoute={modelName}
|
||||
action={Actions.UPDATE}
|
||||
method={Methods.PATCH}
|
||||
/>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
// * Packages
|
||||
import { useForm, usePage } from "@inertiajs/react";
|
||||
import { BookTextIcon, ExternalLinkIcon } from "lucide-react";
|
||||
// * Components shadcn
|
||||
//
|
||||
// * Other
|
||||
import FieldsetWrapper from "@/back/Components/FieldsetWrapper";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import InputError from "@/back/Components/InputError";
|
||||
import { GitlabProjectModel } from "@/back/types/project";
|
||||
import SubmitButton from "@/back/Components/SubmitButton";
|
||||
import useCrudSubmit from "@/back/hooks/use-crud-submit";
|
||||
import { AppEnv } from "@/types/global";
|
||||
import SimpleString from "@/back/Components/Inputs/SimpleString";
|
||||
import str from "@/hooks/use-string";
|
||||
import { GetTranslation, isAValidUrl } from "@/lib/utils";
|
||||
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
|
||||
import SimpleNumber from "@/back/Components/Inputs/SimpleNumber";
|
||||
|
||||
export default function Form({
|
||||
model,
|
||||
modelName,
|
||||
modelRoute,
|
||||
action,
|
||||
method,
|
||||
}: {
|
||||
model?: GitlabProjectModel;
|
||||
modelName: string;
|
||||
modelRoute: string;
|
||||
action: string;
|
||||
method: number;
|
||||
}) {
|
||||
const { appEnv } = usePage().props as unknown as {
|
||||
appEnv: AppEnv;
|
||||
};
|
||||
|
||||
// Form section.
|
||||
const { post, setData, data } = useForm({
|
||||
name: model?.name ? model?.name[appEnv.locale] : undefined,
|
||||
url: model?.url ?? undefined,
|
||||
gitlab_id: model?.gitlab_id ?? undefined,
|
||||
});
|
||||
|
||||
const submit = useCrudSubmit({
|
||||
method,
|
||||
modelRoute,
|
||||
modelName,
|
||||
action,
|
||||
model,
|
||||
post,
|
||||
data,
|
||||
modelNameTrans: useTrans(`models.classes.${modelName}`, {
|
||||
choice: 1,
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<form onSubmit={submit} className="grid grid-cols-2 gap-4">
|
||||
<InputError all />
|
||||
<FieldsetWrapper
|
||||
title={useTrans("uwil-backend::back.form_title_global")}
|
||||
icon={<BookTextIcon className="mr-1" />}
|
||||
description={useTrans("uwil-backend::back.form_subtitle_global")}
|
||||
className="sm:grid-cols-2 gap-4"
|
||||
>
|
||||
<SimpleString
|
||||
name="name"
|
||||
label={str(
|
||||
useTrans("uwil-backend::back.form_associate_to", {
|
||||
params: {
|
||||
attribute: useTrans("validation.custom.name"),
|
||||
},
|
||||
choice: 1,
|
||||
}),
|
||||
)
|
||||
.ucFirst()
|
||||
.value()}
|
||||
placeholder="ex: John Doe"
|
||||
value={data.name}
|
||||
setData={setData}
|
||||
/>
|
||||
<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}
|
||||
/>
|
||||
<div className="flex justify-center items-end gap-1.5">
|
||||
<SimpleString
|
||||
name="url"
|
||||
label={str(
|
||||
useTrans("uwil-backend::back.form_associate_to", {
|
||||
params: {
|
||||
attribute: useTrans("validation.custom.url"),
|
||||
},
|
||||
choice: 2,
|
||||
}),
|
||||
)
|
||||
.ucFirst()
|
||||
.value()}
|
||||
type="url"
|
||||
placeholder="ex: https://example.com/"
|
||||
value={data.url}
|
||||
setData={setData}
|
||||
/>
|
||||
{isAValidUrl(data.url) && (
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
content={<ExternalLinkIcon />}
|
||||
tooltipContent={GetTranslation("back.access_url")}
|
||||
link={data.url}
|
||||
externalLink
|
||||
type="button"
|
||||
size="icon"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</FieldsetWrapper>
|
||||
<div className="col-span-2 text-center">
|
||||
<SubmitButton
|
||||
modelTrans={useTrans(`models.classes.${modelName}`, {
|
||||
choice: 1,
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
// * Packages
|
||||
import { route } from "ziggy-js";
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { Row } from "@tanstack/react-table";
|
||||
import { ArchiveIcon, ArrowLeftIcon, PlusIcon } from "lucide-react";
|
||||
// * Components shadcn
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/components/ui/tooltip";
|
||||
// * Other
|
||||
import AuthenticatedLayout from "@/back/Layouts/AuthenticatedLayout";
|
||||
import DataTable from "@/back/Components/Table/DataTable";
|
||||
import DataTableSearch from "@/back/Components/Table/DataTableSearch";
|
||||
import DataTableFilterButton from "@/back/Components/Table/DataTableFilterButton";
|
||||
import SoftdeleteWarning from "@/back/Components/SoftdeleteWarning";
|
||||
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
|
||||
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
|
||||
import { Views } from "@/back/lib/actions";
|
||||
import { AuthProp, Resource } from "@/back/types/global";
|
||||
import str from "@/hooks/use-string";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
|
||||
import { GitlabProjectModel } from "@/back/types/project";
|
||||
import { AppEnv } from "@/types/global";
|
||||
|
||||
const getColumns = () => {
|
||||
return [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: ({ column }: { column: { id: string } }) => (
|
||||
<DataTableFilterButton
|
||||
label={str(GetTranslation(`validation.custom.${column.id}`))
|
||||
.ucFirst()
|
||||
.value()}
|
||||
field={column.id}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }: { row: Row<GitlabProjectModel> }) => (
|
||||
<RenderTranslationCell value={row.getValue("name")} />
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "url",
|
||||
header: ({ column }: { column: { id: string } }) => (
|
||||
<DataTableFilterButton
|
||||
label={str(GetTranslation(`validation.custom.${column.id}`))
|
||||
.ucFirst()
|
||||
.value()}
|
||||
field={column.id}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }: { row: Row<GitlabProjectModel> }) => (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a
|
||||
href={row.getValue("url")}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-primary underline underline-offset-4 hover:opacity-80 transition-opacity rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
>
|
||||
{row.getValue("url")}
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{GetTranslation("back.access_url")}</TooltipContent>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "updated_at",
|
||||
header: ({ column }: { column: { id: string } }) => (
|
||||
<DataTableFilterButton
|
||||
label={str(
|
||||
GetTranslation(`uwil-backend::validation.attributes.${column.id}`),
|
||||
)
|
||||
.ucFirst()
|
||||
.value()}
|
||||
field={column.id}
|
||||
/>
|
||||
),
|
||||
cell: ({ row }: { row: Row<GitlabProjectModel> }) => (
|
||||
<Badge variant="secondary">
|
||||
{GetFormatedDate(row.getValue("updated_at"))}
|
||||
</Badge>
|
||||
),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export default function Index({
|
||||
models,
|
||||
searchFields,
|
||||
modelName,
|
||||
}: {
|
||||
models: Resource;
|
||||
searchFields: string;
|
||||
modelName: string;
|
||||
}) {
|
||||
const { auth, appEnv } = usePage().props as unknown as {
|
||||
auth: AuthProp;
|
||||
appEnv: AppEnv;
|
||||
};
|
||||
const { viewAny, viewTrash, create } = auth.policies.gitlabProjects;
|
||||
const routeName = appEnv.routes.name;
|
||||
const isArchiveRoute = route().current(`${routeName}${modelName}.trash`);
|
||||
const actionModels = isArchiveRoute
|
||||
? [Views.RESTORATION, Views.FORCEDELETION]
|
||||
: [
|
||||
Views.VISUALIZATION,
|
||||
Views.EDITION,
|
||||
Views.DUPLICATION,
|
||||
Views.ARCHIVATION,
|
||||
];
|
||||
const columns = getColumns();
|
||||
|
||||
// Translations.
|
||||
const transModel = useTrans(`models.classes.${modelName}`, { choice: 2 });
|
||||
const transArchiveTitle = useTrans(
|
||||
"uwil-backend::crud.helpers.archives_model",
|
||||
{
|
||||
params: { model: transModel },
|
||||
},
|
||||
);
|
||||
const transTitle = str(isArchiveRoute ? transArchiveTitle : transModel)
|
||||
.ucFirst()
|
||||
.value();
|
||||
const transCrudBackList = useTrans("uwil-backend::back.crud_back_to_list");
|
||||
|
||||
const beforeNode = () => {
|
||||
return (
|
||||
isArchiveRoute &&
|
||||
viewAny && (
|
||||
<div className="flex justify-end items-center gap-x-1.5">
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${routeName}${modelName}.index`)}
|
||||
content={<ArrowLeftIcon />}
|
||||
tooltipContent={<p>{transCrudBackList}</p>}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
const transCrudAddEntry = useTrans("uwil-backend::back.crud_add_entry");
|
||||
const transAccessTo = useTrans("uwil-backend::back.crud_access_to", {
|
||||
params: {
|
||||
target: useTrans("uwil-backend::back.archived_entries"),
|
||||
},
|
||||
});
|
||||
const afterNode = () => {
|
||||
return (
|
||||
!isArchiveRoute && (
|
||||
<div className="flex justify-end items-center gap-x-1.5">
|
||||
{viewTrash && (
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${routeName}${modelName}.trash`)}
|
||||
content={<ArchiveIcon />}
|
||||
tooltipContent={<p>{transAccessTo}</p>}
|
||||
variant="outline"
|
||||
/>
|
||||
)}
|
||||
{create && (
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${routeName}${modelName}.create`)}
|
||||
content={<PlusIcon />}
|
||||
tooltipContent={<p>{transCrudAddEntry}</p>}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout
|
||||
title={transTitle}
|
||||
beforeNode={beforeNode()}
|
||||
afterNode={afterNode()}
|
||||
>
|
||||
{isArchiveRoute && <SoftdeleteWarning />}
|
||||
<DataTableSearch
|
||||
modelRoute={modelName}
|
||||
searchFields={searchFields}
|
||||
isArchiveRoute={isArchiveRoute}
|
||||
/>
|
||||
<DataTable
|
||||
columns={columns}
|
||||
modelRoute={modelName}
|
||||
modelsPaginate={models}
|
||||
actions={actionModels}
|
||||
/>
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
// * Packages
|
||||
import { usePage } from "@inertiajs/react";
|
||||
import { route } from "ziggy-js";
|
||||
import { ArrowLeftIcon } from "lucide-react";
|
||||
// * 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";
|
||||
import ModelActions from "@/back/Components/ModelActions";
|
||||
import BtnOptionnalLinkWithTooltip from "@/back/Components/BtnOptionnalLinkWithTooltip";
|
||||
import { GetFormatedDate, GetTranslation } from "@/lib/utils";
|
||||
import { Views } from "@/back/lib/actions";
|
||||
import { AuthProp, SingleResource } from "@/back/types/global";
|
||||
import str from "@/hooks/use-string";
|
||||
import useTrans from "@/hooks/use-translations";
|
||||
import { TranslationField } from "@/back/types/i18n";
|
||||
import RenderTranslationCell from "@/back/Components/Table/RenderTranslationCell";
|
||||
import { GitlabProjectModel } from "@/back/types/project";
|
||||
import { AppEnv } from "@/types/global";
|
||||
|
||||
const getColumns = () => {
|
||||
return [
|
||||
{
|
||||
accessorKey: "name",
|
||||
header: str(GetTranslation("validation.custom.name")).ucFirst().value(),
|
||||
cell: ({ value }: { value: TranslationField }) => (
|
||||
<RenderTranslationCell value={value} />
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "url",
|
||||
header: str(GetTranslation("validation.custom.url")).ucFirst().value(),
|
||||
cell: ({ value }: { value: string }) => (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<a
|
||||
href={value}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="text-primary underline underline-offset-4 hover:opacity-80 transition-opacity rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
|
||||
>
|
||||
{value}
|
||||
</a>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>{GetTranslation("back.access_url")}</TooltipContent>
|
||||
</Tooltip>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "gitlab_id",
|
||||
header: str(GetTranslation("validation.custom.gitlab_id"))
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: number }) => value,
|
||||
},
|
||||
{
|
||||
accessorKey: "created_at",
|
||||
header: str(
|
||||
GetTranslation("uwil-backend::validation.attributes.created_at"),
|
||||
)
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: string }) => (
|
||||
<Badge variant="secondary">{GetFormatedDate(value)}</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "updated_at",
|
||||
header: str(
|
||||
GetTranslation("uwil-backend::validation.attributes.updated_at"),
|
||||
)
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: string }) => (
|
||||
<Badge variant="secondary">{GetFormatedDate(value)}</Badge>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "deleted_at",
|
||||
header: str(
|
||||
GetTranslation("uwil-backend::validation.attributes.deleted_at"),
|
||||
)
|
||||
.ucFirst()
|
||||
.value(),
|
||||
cell: ({ value }: { value: string }) => (
|
||||
<Badge variant="secondary">{GetFormatedDate(value)}</Badge>
|
||||
),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export default function Show({
|
||||
data,
|
||||
modelName,
|
||||
}: {
|
||||
data: SingleResource;
|
||||
modelName: string;
|
||||
}) {
|
||||
const { auth, appEnv } = usePage().props as unknown as {
|
||||
auth: AuthProp;
|
||||
appEnv: AppEnv;
|
||||
};
|
||||
const { viewAny } = auth.policies.gitlabProjects;
|
||||
const model = data.data as GitlabProjectModel;
|
||||
const actionModels = [Views.EDITION, Views.DUPLICATION, Views.ARCHIVATION];
|
||||
const transTitle = useTrans(
|
||||
"uwil-backend::crud.helpers.visualization_model",
|
||||
{
|
||||
params: {
|
||||
model: useTrans(`models.classes.${modelName}`, {
|
||||
choice: 1,
|
||||
}),
|
||||
},
|
||||
},
|
||||
);
|
||||
const columns = getColumns();
|
||||
|
||||
// Translations.
|
||||
const transCrudBackToList = useTrans("uwil-backend::back.crud_back_to_list");
|
||||
|
||||
const beforeNode = () => {
|
||||
return (
|
||||
viewAny && (
|
||||
<div className="flex justify-end items-center gap-x-1.5">
|
||||
<BtnOptionnalLinkWithTooltip
|
||||
link={route(`${appEnv.routes.name}${modelName}.index`)}
|
||||
content={<ArrowLeftIcon />}
|
||||
tooltipContent={<p>{transCrudBackToList}</p>}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthenticatedLayout title={transTitle} beforeNode={beforeNode()}>
|
||||
<ModelActions
|
||||
actions={actionModels}
|
||||
modelRoute={modelName}
|
||||
model={model}
|
||||
modelUpdatedAt={model.updated_at?.toString()}
|
||||
/>
|
||||
{/* @ts-expect-error Weird error type on cell. */}
|
||||
<DetailsTable columns={columns} model={model} />
|
||||
</AuthenticatedLayout>
|
||||
);
|
||||
}
|
||||
21
resources/ts/back/types/project.d.ts
vendored
21
resources/ts/back/types/project.d.ts
vendored
|
|
@ -32,6 +32,27 @@ type GitlabProjectModel = DefaultModel & {
|
|||
gitlab_id: number;
|
||||
};
|
||||
|
||||
type GitlabLabelModel = DefaultModel & {
|
||||
name: TranslationField;
|
||||
gitlab_id: number;
|
||||
}
|
||||
|
||||
type GitlabIssueModel = DefaultModel & {
|
||||
title: TranslationField;
|
||||
url: string;
|
||||
estimate_time: number;
|
||||
spent_time: number;
|
||||
is_closed: boolean;
|
||||
gitlab_id: number;
|
||||
gitlab_iid: number;
|
||||
milestone_iid: number;
|
||||
gitlab_project_id: number;
|
||||
g_created_at: Date;
|
||||
g_updated_at: Date;
|
||||
g_closed_at: Date|null;
|
||||
g_due_date: Date|null;
|
||||
}
|
||||
|
||||
type SiteModel = DefaultModel & {
|
||||
name: TranslationField;
|
||||
url_re7: string;
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Back\GitlabProjectController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::get('/gitlab-projects/trash', [GitlabProjectController::class, 'index'])
|
||||
->name('gitlab-projects.trash');
|
||||
Route::patch('/gitlab-projects/{gitlab_project}/restore', [GitlabProjectController::class, 'restore'])
|
||||
->name('gitlab-projects.restore');
|
||||
Route::delete('/gitlab-projects/{gitlab_project}/force', [GitlabProjectController::class, 'forceDestroy'])
|
||||
->name('gitlab-projects.forceDestroy');
|
||||
Route::resource('gitlab-projects', GitlabProjectController::class);
|
||||
Route::get('/gitlab-projects/{gitlab_project}/duplicate', [GitlabProjectController::class, 'duplicate'])
|
||||
->name('gitlab-projects.duplicate');
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
<?php
|
||||
|
||||
use Diglactic\Breadcrumbs\Breadcrumbs;
|
||||
use Diglactic\Breadcrumbs\Generator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/** @var string $routeName */
|
||||
$routeName = config('uwil-backend.routes.name');
|
||||
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.index", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}dashboard.index");
|
||||
$trail->push(
|
||||
Str::ucfirst(trans_choice('models.classes.gitlab-projects', \INF)),
|
||||
route("{$routeName}gitlab-projects.index")
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.create", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}gitlab-projects.index");
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.create')),
|
||||
route("{$routeName}gitlab-projects.create"),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.edit", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}gitlab-projects.index");
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.edit')),
|
||||
route("{$routeName}gitlab-projects.edit", [
|
||||
'gitlab_project' => request()->gitlab_project,
|
||||
])
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.duplicate", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}gitlab-projects.index");
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::crud.actions.duplicate')));
|
||||
});
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.show", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}gitlab-projects.index");
|
||||
$trail->push(
|
||||
Str::ucfirst(trans('uwil-backend::crud.actions.visualize')),
|
||||
route("{$routeName}gitlab-projects.show", [
|
||||
'gitlab_project' => request()->gitlab_project,
|
||||
]),
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for("{$routeName}gitlab-projects.trash", function (Generator $trail) use ($routeName) {
|
||||
$trail->parent("{$routeName}gitlab-projects.index");
|
||||
$trail->push(Str::ucfirst(trans('uwil-backend::back.archives')));
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue