Add support for training courses
This commit is contained in:
parent
7be73d06ba
commit
37b7951b64
|
@ -44,6 +44,56 @@ class DocumentsController extends Controller
|
|||
return response()->file(storage_path('app/public/' . $document->file_path));
|
||||
}
|
||||
|
||||
function addTrainingCourse(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'user' => ['required', 'integer', 'exists:users,id'],
|
||||
'type' => ['required', 'integer', 'exists:training_course_types,id'],
|
||||
'date' => ['required', 'date'],
|
||||
'doc_number' => ['required', 'string', 'max:255'],
|
||||
'file' => [
|
||||
File::types('application/pdf')
|
||||
->max(50 * 1024)
|
||||
]
|
||||
]);
|
||||
|
||||
if($request->user()->id != $request->input('user') && !$request->user()->hasPermission("users-add-training-course")) abort(401);
|
||||
if($request->user()->id == $request->input('user') && !$request->user()->hasPermission("user-add-training-course")) abort(401);
|
||||
|
||||
$document = new Document();
|
||||
$document->type = 'training_course';
|
||||
$document->doc_type = $request->input('type');
|
||||
$document->doc_number = $request->input('doc_number');
|
||||
$document->user = $request->input('user');
|
||||
$document->added_by = auth()->user()->id;
|
||||
if($request->hasFile('file')) {
|
||||
$fileName = time() . '_' . $request->file->getClientOriginalName();
|
||||
$filePath = $request->file('file')->storeAs('training_courses', $fileName, 'public');
|
||||
|
||||
$documentFile = new DocumentFile();
|
||||
$documentFile->uuid = Str::uuid()->toString();
|
||||
$documentFile->type = 'training_course';
|
||||
$documentFile->file_path = $filePath;
|
||||
$documentFile->uploadedBy()->associate(auth()->user());
|
||||
$documentFile->save();
|
||||
|
||||
$document->documentFile()->associate($documentFile);
|
||||
}
|
||||
$document->date = $request->input('date');
|
||||
$document->save();
|
||||
|
||||
return response()->json([
|
||||
"id" => $document->id
|
||||
]);
|
||||
}
|
||||
|
||||
function serveTrainingCourse($uuid)
|
||||
{
|
||||
$document = DocumentFile::where('uuid', $uuid)->firstOrFail();
|
||||
|
||||
return response()->file(storage_path('app/public/' . $document->file_path));
|
||||
}
|
||||
|
||||
function addMedicalExamination(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\TrainingCourseType;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Utils\Logger;
|
||||
|
||||
class TrainingCourseTypeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
if(!$request->user()->hasPermission("users-read") && !$request->user()->hasPermission("user-read")) abort(401);
|
||||
User::where('id', $request->user()->id)->update(['last_access' => now()]);
|
||||
|
||||
return response()->json(
|
||||
TrainingCourseType::get()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new TrainingCourseType.
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
if(!$request->user()->hasPermission("users-add-training-course") && !$request->user()->hasPermission("user-add-training-course")) abort(401);
|
||||
$trainingCourseType = new TrainingCourseType();
|
||||
$trainingCourseType->name = $request->name;
|
||||
$trainingCourseType->save();
|
||||
|
||||
Logger::log("Aggiunto tipo di corso di formazione ($trainingCourseType->name)");
|
||||
|
||||
return response()->json(
|
||||
$trainingCourseType
|
||||
);
|
||||
}
|
||||
}
|
|
@ -70,6 +70,27 @@ class UserController extends Controller
|
|||
$user->driving_license = $dl_tmp[0];
|
||||
}
|
||||
|
||||
$tc_tmp = Document::where('documents.user', $user->id)
|
||||
->where('documents.type', 'training_course')
|
||||
->leftJoin('document_files', 'document_files.id', '=', 'documents.document_file_id')
|
||||
->leftJoin('training_course_types', 'training_course_types.id', '=', 'documents.doc_type')
|
||||
->select('documents.doc_number as doc_number', 'documents.date', 'document_files.uuid as doc_uuid', 'training_course_types.name as type')
|
||||
->get();
|
||||
|
||||
if($tc_tmp->count() > 0) {
|
||||
$user->training_courses = $tc_tmp;
|
||||
foreach($user->training_courses as $tc) {
|
||||
if(!is_null($tc->doc_uuid)) {
|
||||
$tc->doc_url = URL::temporarySignedRoute(
|
||||
'training_course_serve', now()->addHours(1), ['uuid' => $tc->doc_uuid]
|
||||
);
|
||||
unset($tc->doc_uuid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$user->training_courses = [];
|
||||
}
|
||||
|
||||
$me_tmp = Document::where('documents.user', $user->id)
|
||||
->where('documents.type', 'medical_examination')
|
||||
->leftJoin('document_files', 'document_files.id', '=', 'documents.document_file_id')
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class TrainingCourseType extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $timestamps = false;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'name'
|
||||
];
|
||||
}
|
|
@ -13,21 +13,21 @@ return [
|
|||
|
||||
'roles_structure' => [
|
||||
'superadmin' => [
|
||||
'users' => 'c,r,u,d,i,b,h,sc,sd,ame',
|
||||
'users' => 'c,r,u,d,i,b,h,sc,sd,atc,ame',
|
||||
'user' => 'u,h,sc,sd',
|
||||
'services' => 'c,r,u,d',
|
||||
'trainings' => 'c,r,u,d',
|
||||
'alerts' => 'c,r,u',
|
||||
],
|
||||
'admin' => [
|
||||
'users' => 'c,r,u,d,i,b,h,sc,sd,ame',
|
||||
'users' => 'c,r,u,d,i,b,h,sc,sd,atc,ame',
|
||||
'user' => 'u,h,sc,sd',
|
||||
'services' => 'c,r,u,d',
|
||||
'trainings' => 'c,r,u,d',
|
||||
'alerts' => 'c,r,u',
|
||||
],
|
||||
'chief' => [
|
||||
'users' => 'r,u,sc,sd,ame',
|
||||
'users' => 'r,u,sc,sd,atc,ame',
|
||||
'user' => 'u',
|
||||
'services' => 'c,r,u,d',
|
||||
'trainings' => 'c,r,u,d',
|
||||
|
@ -53,6 +53,7 @@ return [
|
|||
'h' => 'hide',
|
||||
'sc' => 'set-chief',
|
||||
'sd' => 'set-driver',
|
||||
'atc' => 'add-training-course',
|
||||
'ame' => 'add-medical-examination'
|
||||
]
|
||||
];
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
<?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('training_course_types', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name')->unique();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::dropIfExists('training_course_types');
|
||||
}
|
||||
};
|
|
@ -13,6 +13,7 @@ use App\Http\Controllers\ServiceController;
|
|||
use App\Http\Controllers\StatsController;
|
||||
use App\Http\Controllers\PlacesController;
|
||||
use App\Http\Controllers\ServiceTypeController;
|
||||
use App\Http\Controllers\TrainingCourseTypeController;
|
||||
use App\Http\Controllers\TrainingController;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
@ -50,8 +51,12 @@ Route::middleware('auth:sanctum')->group( function () {
|
|||
Route::put('/users/{user}', [UserController::class, 'update']);
|
||||
|
||||
Route::post('/documents/driving_license', [DocumentsController::class, 'uploadDrivingLicenseScan']);
|
||||
Route::post('/documents/training_course', [DocumentsController::class, 'addTrainingCourse']);
|
||||
Route::post('/documents/medical_examination', [DocumentsController::class, 'addMedicalExamination']);
|
||||
|
||||
Route::get('/training_course_types', [TrainingCourseTypeController::class, 'index']);
|
||||
Route::post('/training_course_types', [TrainingCourseTypeController::class, 'create']);
|
||||
|
||||
Route::get('/schedules', [ScheduleSlotsController::class, 'index']);
|
||||
Route::post('/schedules', [ScheduleSlotsController::class, 'store']);
|
||||
|
||||
|
@ -91,6 +96,7 @@ Route::middleware('auth:sanctum')->group( function () {
|
|||
|
||||
Route::middleware('signed')->group( function () {
|
||||
Route::get('/documents/driving_license/{uuid}', [DocumentsController::class, 'serveDrivingLicenseScan'])->name('driving_license_scan_serve');
|
||||
Route::get('/documents/training_course/{uuid}', [DocumentsController::class, 'serveTrainingCourse'])->name('training_course_serve');
|
||||
Route::get('/documents/medical_examination/{uuid}', [DocumentsController::class, 'serveMedicalExamination'])->name('medical_examination_serve');
|
||||
});
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
<input formControlName="certifier" type="text" class="form-control" id="me_certifier">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="dl_scan" class="form-label">{{ 'upload_medical_examination_certificate'|translate|ftitlecase }} (<u>{{ 'optional'|translate|uppercase }}</u>, <i>.pdf</i>)</label>
|
||||
<input class="form-control" type="file" id="dl_scan" (change)="onMedicalExaminationCertificateSelected($event)">
|
||||
<label for="me_cert" class="form-label">{{ 'upload_medical_examination_certificate'|translate|ftitlecase }} (<u>{{ 'optional'|translate|uppercase }}</u>, <i>.pdf</i>)</label>
|
||||
<input class="form-control" type="file" id="me_cert" (change)="onMedicalExaminationCertificateSelected($event)">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
<div class="modal-header">
|
||||
<h4 class="modal-title pull-left" translate>training_course_modal.title</h4>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close close pull-right"
|
||||
[attr.aria-label]="'close' | translate | ftitlecase"
|
||||
(click)="bsModalRef.hide()"
|
||||
>
|
||||
<span aria-hidden="true" class="visually-hidden">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form [formGroup]="form" (submit)="formSubmit()" class="row g-3">
|
||||
<div class="col-12">
|
||||
<label for="tc_type">{{ 'type'|translate|ftitlecase }}</label>
|
||||
<div class="input-group has-validation">
|
||||
<select formControlName="type" class="form-control mr-2" id="tc_type">
|
||||
<option selected disabled translate>select_type</option>
|
||||
<option *ngFor="let type of types" value="{{ type.id }}">{{ type.name }}</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" type="button" tabindex="-1" (click)="addingType = true">
|
||||
{{ 'add'|translate|ftitlecase }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-2 mt-2" *ngIf="addingType">
|
||||
<input type="text" class="form-control" [placeholder]="'type'|translate|titlecase" [(ngModel)]="newType"
|
||||
[ngModelOptions]="{standalone: true}">
|
||||
<button class="btn btn-secondary" type="button" (click)="addType()">{{ 'submit'|translate|ftitlecase }}</button>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="tc_date" class="form-label">{{ 'date'|translate|ftitlecase }}</label>
|
||||
<input formControlName="date" type="text" class="form-control" [placeholder]="'press_to_select_a_date'|translate|ftitlecase" id="tc_date" bsDatepicker [bsConfig]="{ adaptivePosition: true, dateInputFormat: 'DD/MM/YYYY' }" [maxDate]="dateMaxDate">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="tc_doc_number">{{ 'training_course_modal.doc_number'|translate|ftitlecase }}</label>
|
||||
<input formControlName="doc_number" type="text" class="form-control" id="tc_doc_number">
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label for="tc_scan" class="form-label">{{ 'upload_training_course_doc'|translate|ftitlecase }} (<u>{{ 'optional'|translate|uppercase }}</u>, <i>.pdf</i>)</label>
|
||||
<input class="form-control" type="file" id="tc_scan" (change)="onTrainingCourseDocumentSelected($event)">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" (click)="formSubmit()">
|
||||
{{ "add" | translate | ftitlecase }}
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary" (click)="bsModalRef.hide()">
|
||||
{{ "close" | translate }}
|
||||
</button>
|
||||
</div>
|
|
@ -0,0 +1,132 @@
|
|||
import { Component, OnInit, EventEmitter } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { BsModalRef } from 'ngx-bootstrap/modal';
|
||||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
import { AuthService } from 'src/app/_services/auth.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import Swal from 'sweetalert2';
|
||||
|
||||
@Component({
|
||||
selector: 'modal-add-training-course',
|
||||
templateUrl: './modal-add-training-course.component.html',
|
||||
styleUrls: ['./modal-add-training-course.component.scss']
|
||||
})
|
||||
export class ModalAddTrainingCourseComponent implements OnInit {
|
||||
userId: number = 0;
|
||||
|
||||
form: FormGroup = this.formBuilder.group({
|
||||
type: [0, [Validators.required]],
|
||||
date: [null, [Validators.required]],
|
||||
doc_number: [null, [Validators.required]],
|
||||
file: [null]
|
||||
});
|
||||
|
||||
dateMaxDate = new Date();
|
||||
expirationDateMinDate = new Date(new Date().setDate(new Date().getDate() + 1)); //Tomorrow
|
||||
allowedImageTypes = ["application/pdf"];
|
||||
maxImageSize = 1024 * 1024 * 50; //50MB
|
||||
|
||||
addingType = false;
|
||||
newType = "";
|
||||
types: any[] = [];
|
||||
|
||||
submitEvents: EventEmitter<any> = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
public bsModalRef: BsModalRef,
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiClientService,
|
||||
public auth: AuthService,
|
||||
private translateService: TranslateService
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.api.get("training_course_types").then((response) => {
|
||||
this.types = response;
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
addType() {
|
||||
this.addingType = false;
|
||||
this.api.post("training_course_types", { name: this.newType }).then((response) => {
|
||||
this.types.push(response);
|
||||
this.form.patchValue({
|
||||
type: response.id
|
||||
});
|
||||
}).catch((err) => {
|
||||
Swal.fire({
|
||||
title: this.translateService.instant("error_title"),
|
||||
text: err.error.message,
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Ok'
|
||||
});
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
onTrainingCourseDocumentSelected(event: any) {
|
||||
const file: File = event.target.files[0];
|
||||
|
||||
if (file) {
|
||||
if(!this.allowedImageTypes.includes(file.type)) {
|
||||
event.target.value = null;
|
||||
Swal.fire({
|
||||
title: this.translateService.instant("error_title"),
|
||||
text: this.translateService.instant("validation.document_format_not_supported"),
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Ok'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if(file.size > this.maxImageSize) {
|
||||
event.target.value = null;
|
||||
Swal.fire({
|
||||
title: this.translateService.instant("error_title"),
|
||||
text: this.translateService.instant("validation.file_too_big"),
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Ok'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = (_event) => {
|
||||
this.form.patchValue({
|
||||
file
|
||||
});
|
||||
this.form.get('file')?.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
formSubmit() {
|
||||
const formValues = this.form.value;
|
||||
formValues.date = formValues.date ? new Date(formValues.date).toISOString() : null;
|
||||
|
||||
console.log(formValues);
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('user', this.userId.toString());
|
||||
formData.append('type', formValues.type);
|
||||
formData.append('date', formValues.date);
|
||||
formData.append('doc_number', formValues.doc_number);
|
||||
if(formValues.file) formData.append('file', formValues.file, formValues.file.name);
|
||||
|
||||
this.api.post("documents/training_course", formData).then((response) => {
|
||||
console.log(response);
|
||||
this.bsModalRef.hide();
|
||||
this.submitEvents.emit();
|
||||
}).catch((err) => {
|
||||
Swal.fire({
|
||||
title: this.translateService.instant("error_title"),
|
||||
text: err.error.message,
|
||||
icon: 'error',
|
||||
confirmButtonText: 'Ok'
|
||||
});
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { TranslationModule } from '../../translation.module';
|
||||
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
|
||||
import { FirstLetterUppercasePipe } from 'src/app/_pipes/first-letter-uppercase.pipe';
|
||||
|
||||
import { ModalAddTrainingCourseComponent } from './modal-add-training-course.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
ModalAddTrainingCourseComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslationModule,
|
||||
BsDatepickerModule.forRoot(),
|
||||
FirstLetterUppercasePipe
|
||||
],
|
||||
exports: [
|
||||
ModalAddTrainingCourseComponent
|
||||
]
|
||||
})
|
||||
export class ModalAddTrainingCourseModule { }
|
|
@ -78,7 +78,7 @@
|
|||
<br>
|
||||
<div class="input-group has-validation">
|
||||
<select formControlName="type" [class.is-invalid]="!isFieldValid('type')" class="form-control mr-2">
|
||||
<option selected disabled translate>edit_service.select_type</option>
|
||||
<option selected disabled translate>select_type</option>
|
||||
<option *ngFor="let service_type of types" value="{{ service_type.id }}">{{ service_type.name }}</option>
|
||||
</select>
|
||||
<button class="btn btn-outline-secondary" type="button" tabindex="-1" (click)="addingType = true">
|
||||
|
@ -89,7 +89,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="input-group mb-2 mt-2" *ngIf="addingType">
|
||||
<input type="text" class="form-control" [placeholder]="'type'|translate" [(ngModel)]="newType"
|
||||
<input type="text" class="form-control" [placeholder]="'type'|translate|titlecase" [(ngModel)]="newType"
|
||||
[ngModelOptions]="{standalone: true}">
|
||||
<button class="btn btn-secondary" type="button" (click)="addType()">{{ 'submit'|translate|ftitlecase }}</button>
|
||||
</div>
|
||||
|
|
|
@ -147,40 +147,39 @@
|
|||
</div>
|
||||
</form>
|
||||
|
||||
<ng-container *ngIf="false">
|
||||
<hr>
|
||||
|
||||
<div class="text-center">
|
||||
<h3>Corsi di formazione</h3>
|
||||
<button disabled class="btn btn-sm btn-outline-info m-2">
|
||||
<i class="fas fa-download"></i> LIFM
|
||||
<h3>{{ 'training_courses'|translate|uppercase }}</h3>
|
||||
<button *ngIf="!hideTCAddBtn" class="btn btn-sm btn-outline-success m-2" (click)="openModalAddTrainingCourse()">
|
||||
<i class="fas fa-plus"></i> {{ 'add'|translate|ftitlecase }}
|
||||
</button>
|
||||
<table class="mx-auto table table-striped table-bordered table-responsive">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>TIPOLOGIA</th>
|
||||
<th>NOME</th>
|
||||
<th>DATA</th>
|
||||
<th>SCADENZA</th>
|
||||
<th>CERT.</th>
|
||||
<th>{{ 'type'|translate|uppercase }}</th>
|
||||
<th>{{ 'date'|translate|uppercase }}</th>
|
||||
<th>{{ 'training_course_modal.doc_number'|translate|uppercase }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr *ngIf="false">
|
||||
<td>TIPOCORSO</td>
|
||||
<td>Nome</td>
|
||||
<td>31/12/2024</td>
|
||||
<td>31/12/2027</td>
|
||||
<tr *ngFor="let row of user.training_courses">
|
||||
<td>{{ row.type }}</td>
|
||||
<td>{{ row.date | date:'dd/MM/YYYY' }}</td>
|
||||
<td>
|
||||
<a href=''><i class='fas fa-graduation-cap'></i></a>
|
||||
<ng-container *ngIf="row.doc_url">
|
||||
<a [href]='row.doc_url' target="_blank">{{ row.doc_number }}</a>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!row.doc_url">
|
||||
{{ row.doc_number }}
|
||||
</ng-container>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<hr>
|
||||
|
||||
|
@ -204,8 +203,8 @@
|
|||
<td>{{ row.date | date:'dd/MM/YYYY' }}</td>
|
||||
<td>{{ row.certifier }}</td>
|
||||
<td>{{ row.expiration_date | date:'dd/MM/YYYY' }}</td>
|
||||
<td *ngIf="!hideMECertCol && row.cert_url">
|
||||
<a [href]='row.cert_url' target="_blank"><i class='fas fa-clipboard-list'></i></a>
|
||||
<td *ngIf="!hideMECertCol">
|
||||
<a *ngIf="row.cert_url" [href]='row.cert_url' target="_blank"><i class='fas fa-clipboard-list'></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
|
|
@ -4,6 +4,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|||
import { ApiClientService } from 'src/app/_services/api-client.service';
|
||||
import { AuthService } from 'src/app/_services/auth.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { ModalAddTrainingCourseComponent } from 'src/app/_components/modal-add-traning-course/modal-add-training-course.component';
|
||||
import { ModalAddMedicalExaminationComponent } from 'src/app/_components/modal-add-medical-examination/modal-add-medical-examination.component';
|
||||
import { BsModalService } from 'ngx-bootstrap/modal';
|
||||
import Swal from 'sweetalert2';
|
||||
|
@ -44,6 +45,7 @@ export class EditUserComponent implements OnInit {
|
|||
boot_size: ['']
|
||||
});
|
||||
|
||||
hideTCAddBtn = true;
|
||||
hideMECertCol = true;
|
||||
hideMEAddBtn = true;
|
||||
birthdayMaxDate = new Date(new Date().setFullYear(new Date().getFullYear() - 18)); //18 years ago
|
||||
|
@ -141,6 +143,9 @@ export class EditUserComponent implements OnInit {
|
|||
let canHide = this.id == this.auth.profile.id ?
|
||||
this.auth.profile.can('user-hide') :
|
||||
this.auth.profile.can('users-hide');
|
||||
let canAddTrainingCourse = this.id == this.auth.profile.id ?
|
||||
this.auth.profile.can('user-add-training-course') :
|
||||
this.auth.profile.can('users-add-training-course');
|
||||
let canAddMedicalExamination = this.id == this.auth.profile.id ?
|
||||
this.auth.profile.can('user-add-medical-examination') :
|
||||
this.auth.profile.can('users-add-medical-examination');
|
||||
|
@ -149,6 +154,7 @@ export class EditUserComponent implements OnInit {
|
|||
if(!canSetDriver) this.profileForm.get('driver')?.disable();
|
||||
if(!canBan) this.profileForm.get('banned')?.disable();
|
||||
if(!canHide) this.profileForm.get('hidden')?.disable();
|
||||
this.hideTCAddBtn = !canAddTrainingCourse;
|
||||
this.hideMEAddBtn = !canAddMedicalExamination;
|
||||
}
|
||||
|
||||
|
@ -237,6 +243,23 @@ export class EditUserComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
openModalAddTrainingCourse() {
|
||||
const modalReference = this.modalService.show(ModalAddTrainingCourseComponent, {
|
||||
initialState: {
|
||||
userId: this.id
|
||||
}
|
||||
});
|
||||
modalReference.content?.submitEvents.subscribe(() => {
|
||||
//Refresh user data after modal is closed
|
||||
this.api.get(`users/${this.id}`).then((response) => {
|
||||
this.user = response;
|
||||
console.log(response);
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
openModalAddMedicalExamination() {
|
||||
const modalReference = this.modalService.show(ModalAddMedicalExaminationComponent, {
|
||||
initialState: {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { CommonModule } from '@angular/common';
|
|||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BsDatepickerModule } from 'ngx-bootstrap/datepicker';
|
||||
import { BackBtnModule } from '../../_components/back-btn/back-btn.module';
|
||||
import { ModalAddTrainingCourseModule } from 'src/app/_components/modal-add-traning-course/modal-add-training-course.module';
|
||||
import { ModalAddMedicalExaminationModule } from 'src/app/_components/modal-add-medical-examination/modal-add-medical-examination.module';
|
||||
import { TranslationModule } from '../../translation.module';
|
||||
import { FirstLetterUppercasePipe } from 'src/app/_pipes/first-letter-uppercase.pipe';
|
||||
|
@ -22,6 +23,7 @@ import { EditUserComponent } from './edit-user.component';
|
|||
ReactiveFormsModule,
|
||||
BsDatepickerModule.forRoot(),
|
||||
BackBtnModule,
|
||||
ModalAddTrainingCourseModule,
|
||||
ModalAddMedicalExaminationModule,
|
||||
TranslationModule,
|
||||
FirstLetterUppercasePipe
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
"select_end_datetime": "Select end date and time for the service",
|
||||
"insert_code": "Insert service code",
|
||||
"other_crew_members": "Other crew members",
|
||||
"select_type": "Select a type",
|
||||
"select_service_type": "Select a service type",
|
||||
"type_added_successfully": "Type added successfully",
|
||||
"service_added_successfully": "Service added successfully",
|
||||
|
@ -110,6 +109,10 @@
|
|||
"user_info_modal": {
|
||||
"title": "User info"
|
||||
},
|
||||
"training_course_modal": {
|
||||
"title": "Add training course",
|
||||
"doc_number": "document number"
|
||||
},
|
||||
"medical_examination_modal": {
|
||||
"title": "Add medical examination"
|
||||
},
|
||||
|
@ -126,6 +129,7 @@
|
|||
"warning": "warning",
|
||||
"press_for_more_info": "press here for more info",
|
||||
"update_availability_schedule": "Update availability schedule",
|
||||
"select_type": "Select a type",
|
||||
"save_changes": "Save changes",
|
||||
"close": "Close",
|
||||
"monday": "Monday",
|
||||
|
@ -168,10 +172,12 @@
|
|||
"driving_license_scan": "driving license scan",
|
||||
"upload_scan": "upload scan",
|
||||
"upload_medical_examination_certificate": "upload medical examination certificate",
|
||||
"upload_training_course_doc": "upload training course document",
|
||||
"clothings": "clothings",
|
||||
"suit_size": "suit size",
|
||||
"boot_size": "boot size",
|
||||
"medical_examinations": "medical examinations",
|
||||
"training_courses": "training courses",
|
||||
"date": "date",
|
||||
"expiration_date": "expiration date",
|
||||
"certifier": "certifier",
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
"select_end_datetime": "Seleziona data e ora di fine dell'intervento",
|
||||
"insert_code": "Inserisci il progressivo dell'intervento",
|
||||
"other_crew_members": "Altri membri della squadra",
|
||||
"select_type": "Seleziona una tipologia",
|
||||
"select_service_type": "Seleziona una tipologia di intervento",
|
||||
"type_already_exists": "La tipologia è già presente",
|
||||
"type_added_successfully": "Tipologia aggiunta con successo",
|
||||
|
@ -111,6 +110,10 @@
|
|||
"user_info_modal": {
|
||||
"title": "Scheda utente"
|
||||
},
|
||||
"training_course_modal": {
|
||||
"title": "Aggiungi corso di formazione",
|
||||
"doc_number": "numero Ordine del Giorno"
|
||||
},
|
||||
"medical_examination_modal": {
|
||||
"title": "Aggiungi visita medica"
|
||||
},
|
||||
|
@ -125,6 +128,7 @@
|
|||
"warning": "attenzione",
|
||||
"press_for_more_info": "premi qui per informazioni",
|
||||
"update_availability_schedule": "Aggiorna programmazione disponibilità",
|
||||
"select_type": "Seleziona una tipologia",
|
||||
"save_changes": "Salva modifiche",
|
||||
"close": "Chiudi",
|
||||
"monday": "Lunedì",
|
||||
|
@ -167,10 +171,12 @@
|
|||
"driving_license_scan": "scansione patente",
|
||||
"upload_scan": "carica scansione",
|
||||
"upload_medical_examination_certificate": "carica certificato visita medica",
|
||||
"upload_training_course_doc": "carica Ordine del Giorno",
|
||||
"clothings": "indumenti",
|
||||
"suit_size": "taglia tuta",
|
||||
"boot_size": "taglia scarponi",
|
||||
"medical_examinations": "visite mediche",
|
||||
"training_courses": "corsi di formazione",
|
||||
"date": "data",
|
||||
"expiration_date": "data di scadenza",
|
||||
"certifier": "ente/certificatore",
|
||||
|
|
Loading…
Reference in New Issue