#134 - fill users data for resume #144
| @@ -35,5 +35,6 @@ class AuthServiceProvider extends ServiceProvider | |||||||
|         Gate::define("manageVacationLimits", fn(User $user): bool => $user->role === Role::AdministrativeApprover); |         Gate::define("manageVacationLimits", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("generateTimesheet", fn(User $user): bool => $user->role === Role::AdministrativeApprover); |         Gate::define("generateTimesheet", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|         Gate::define("listMonthlyUsage", fn(User $user): bool => $user->role === Role::AdministrativeApprover); |         Gate::define("listMonthlyUsage", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|  |         Gate::define("manageResumes", fn(User $user): bool => $user->role === Role::AdministrativeApprover); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -20,6 +20,8 @@ class ResumeController extends Controller | |||||||
| { | { | ||||||
|     public function index(): Response |     public function index(): Response | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $resumes = Resume::query() |         $resumes = Resume::query() | ||||||
|             ->paginate(); |             ->paginate(); | ||||||
|  |  | ||||||
| @@ -30,6 +32,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function create(): Response |     public function create(): Response | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $users = User::query() |         $users = User::query() | ||||||
|             ->orderByProfileField("last_name") |             ->orderByProfileField("last_name") | ||||||
|             ->orderByProfileField("first_name") |             ->orderByProfileField("first_name") | ||||||
| @@ -43,6 +47,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function show(Resume $resume, ResumeGenerator $generator): BinaryFileResponseAlias |     public function show(Resume $resume, ResumeGenerator $generator): BinaryFileResponseAlias | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $path = $generator->generate($resume); |         $path = $generator->generate($resume); | ||||||
|  |  | ||||||
|         return response() |         return response() | ||||||
| @@ -52,6 +58,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function store(ResumeRequest $request): RedirectResponse |     public function store(ResumeRequest $request): RedirectResponse | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $resume = new Resume(); |         $resume = new Resume(); | ||||||
|  |  | ||||||
|         if ($request->hasEmployee()) { |         if ($request->hasEmployee()) { | ||||||
| @@ -76,6 +84,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function edit(Resume $resume): Response |     public function edit(Resume $resume): Response | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $users = User::query() |         $users = User::query() | ||||||
|             ->orderByProfileField("last_name") |             ->orderByProfileField("last_name") | ||||||
|             ->orderByProfileField("first_name") |             ->orderByProfileField("first_name") | ||||||
| @@ -90,6 +100,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function update(Resume $resume, ResumeRequest $request): RedirectResponse |     public function update(Resume $resume, ResumeRequest $request): RedirectResponse | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         if ($request->hasEmployee()) { |         if ($request->hasEmployee()) { | ||||||
|             $resume->user()->associate($request->getEmployee()); |             $resume->user()->associate($request->getEmployee()); | ||||||
|         } else { |         } else { | ||||||
| @@ -113,6 +125,8 @@ class ResumeController extends Controller | |||||||
|  |  | ||||||
|     public function destroy(Resume $resume): RedirectResponse |     public function destroy(Resume $resume): RedirectResponse | ||||||
|     { |     { | ||||||
|  |         $this->authorize("manageResumes"); | ||||||
|  |  | ||||||
|         $resume->delete(); |         $resume->delete(); | ||||||
|  |  | ||||||
|         return redirect() |         return redirect() | ||||||
|   | |||||||
| @@ -39,6 +39,7 @@ class HandleInertiaRequests extends Middleware | |||||||
|                 "manageUsers" => $user ? $user->can("manageUsers") : false, |                 "manageUsers" => $user ? $user->can("manageUsers") : false, | ||||||
|                 "listAllVacationRequests" => $user ? $user->can("listAll", VacationRequest::class) : false, |                 "listAllVacationRequests" => $user ? $user->can("listAll", VacationRequest::class) : false, | ||||||
|                 "listMonthlyUsage" => $user ? $user->can("listMonthlyUsage") : false, |                 "listMonthlyUsage" => $user ? $user->can("listMonthlyUsage") : false, | ||||||
|  |                 "manageResumes" => $user ? $user->can("manageResumes") : false, | ||||||
|             ], |             ], | ||||||
|         ]; |         ]; | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ return [ | |||||||
|         VacationTypeConfigRetriever::KEY_IS_VACATION => true, |         VacationTypeConfigRetriever::KEY_IS_VACATION => true, | ||||||
|     ], |     ], | ||||||
|     VacationType::Absence->value => [ |     VacationType::Absence->value => [ | ||||||
|         VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => true, |         VacationTypeConfigRetriever::KEY_TECHNICAL_APPROVAL => false, | ||||||
|         VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => false, |         VacationTypeConfigRetriever::KEY_ADMINISTRATIVE_APPROVAL => false, | ||||||
|         VacationTypeConfigRetriever::KEY_BILLABLE => false, |         VacationTypeConfigRetriever::KEY_BILLABLE => false, | ||||||
|         VacationTypeConfigRetriever::KEY_HAS_LIMIT => false, |         VacationTypeConfigRetriever::KEY_HAS_LIMIT => false, | ||||||
|   | |||||||
| @@ -35,6 +35,7 @@ const technologyLevels = [ | |||||||
|     textColor: 'text-blumilk-400', |     textColor: 'text-blumilk-400', | ||||||
|   }, |   }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
| const languageLevels = [ | const languageLevels = [ | ||||||
|   { |   { | ||||||
|     level: 1, |     level: 1, | ||||||
| @@ -74,9 +75,9 @@ const languageLevels = [ | |||||||
|   { |   { | ||||||
|     level: 6, |     level: 6, | ||||||
|     name: 'C2', |     name: 'C2', | ||||||
|     activeColor: 'bg-gray-600', |     activeColor: 'bg-gray-700', | ||||||
|     backgroundColor: 'bg-gray-200', |     backgroundColor: 'bg-gray-200', | ||||||
|     textColor: 'text-gray-600', |     textColor: 'text-gray-700', | ||||||
|   }, |   }, | ||||||
| ] | ] | ||||||
|  |  | ||||||
|   | |||||||
| @@ -309,7 +309,7 @@ | |||||||
|         <DynamicSection |         <DynamicSection | ||||||
|           v-model="form.technologies" |           v-model="form.technologies" | ||||||
|           header="Technologie" |           header="Technologie" | ||||||
|           add-label="Dodaj technologie" |           add-label="Dodaj technologię" | ||||||
|           @add-item="addTechnology" |           @add-item="addTechnology" | ||||||
|           @remove-item="(index) => form.technologies.splice(index, 1)" |           @remove-item="(index) => form.technologies.splice(index, 1)" | ||||||
|         > |         > | ||||||
| @@ -545,7 +545,7 @@ const languages = [ | |||||||
|   'German', |   'German', | ||||||
| ] | ] | ||||||
|  |  | ||||||
| const form = useForm({ | const form = useForm('createResume',{ | ||||||
|   user: props.users.data[0], |   user: props.users.data[0], | ||||||
|   name: null, |   name: null, | ||||||
|   educations: [], |   educations: [], | ||||||
| @@ -597,7 +597,7 @@ function hasAnyErrorInSection(section, index) { | |||||||
| function submitResume() { | function submitResume() { | ||||||
|   form |   form | ||||||
|     .transform((data) => ({ |     .transform((data) => ({ | ||||||
|       user: data.user.id, |       user: data.user?.id, | ||||||
|       name: data.name, |       name: data.name, | ||||||
|       education: data.educations, |       education: data.educations, | ||||||
|       languages: data.languages.map(language => ({ |       languages: data.languages.map(language => ({ | ||||||
|   | |||||||
| @@ -309,7 +309,7 @@ | |||||||
|         <DynamicSection |         <DynamicSection | ||||||
|           v-model="form.technologies" |           v-model="form.technologies" | ||||||
|           header="Technologie" |           header="Technologie" | ||||||
|           add-label="Dodaj technologie" |           add-label="Dodaj technologię" | ||||||
|           @add-item="addTechnology" |           @add-item="addTechnology" | ||||||
|           @remove-item="(index) => form.technologies.splice(index, 1)" |           @remove-item="(index) => form.technologies.splice(index, 1)" | ||||||
|         > |         > | ||||||
| @@ -444,10 +444,10 @@ | |||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`educations.${index}.startDate`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`educations.${index}.startDate`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`educations.${index}.startDate`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`educations.${index}.startDate`] }" | ||||||
|                 /> |                 /> | ||||||
|                 <p |                 <p | ||||||
|                   v-if="form.errors[`educations.${index}.startDate`]" |                   v-if="form.errors[`projects.${index}.startDate`]" | ||||||
|                   class="mt-2 text-sm text-red-600" |                   class="mt-2 text-sm text-red-600" | ||||||
|                 > |                 > | ||||||
|                   {{ form.errors[`educations.${index}.startDate`] }} |                   {{ form.errors[`projects.${index}.startDate`] }} | ||||||
|                 </p> |                 </p> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
| @@ -467,10 +467,10 @@ | |||||||
|                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`educations.${index}.endDate`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`educations.${index}.endDate`] }" |                   :class="{ 'border-red-300 text-red-900 focus:outline-none focus:ring-red-500 focus:border-red-500': form.errors[`educations.${index}.endDate`], 'focus:ring-blumilk-500 focus:border-blumilk-500 sm:text-sm border-gray-300': !form.errors[`educations.${index}.endDate`] }" | ||||||
|                 /> |                 /> | ||||||
|                 <p |                 <p | ||||||
|                   v-if="form.errors[`educations.${index}.endDate`]" |                   v-if="form.errors[`projects.${index}.endDate`]" | ||||||
|                   class="mt-2 text-sm text-red-600" |                   class="mt-2 text-sm text-red-600" | ||||||
|                 > |                 > | ||||||
|                   {{ form.errors[`educations.${index}.endDate`] }} |                   {{ form.errors[`projects.${index}.endDate`] }} | ||||||
|                 </p> |                 </p> | ||||||
|               </div> |               </div> | ||||||
|             </div> |             </div> | ||||||
| @@ -546,7 +546,7 @@ const languages = [ | |||||||
|   'German', |   'German', | ||||||
| ] | ] | ||||||
|  |  | ||||||
| const form = useForm({ | const form = useForm(`EditResume:${props.resume.id}`,{ | ||||||
|   user: props.users.data.find((user) => user.id === props.resume.user) ?? null, |   user: props.users.data.find((user) => user.id === props.resume.user) ?? null, | ||||||
|   name: props.resume.name ?? null , |   name: props.resume.name ?? null , | ||||||
|   educations: props.resume.education ?? [], |   educations: props.resume.education ?? [], | ||||||
| @@ -604,7 +604,7 @@ function hasAnyErrorInSection(section, index) { | |||||||
| function submitResume() { | function submitResume() { | ||||||
|   form |   form | ||||||
|     .transform((data) => ({ |     .transform((data) => ({ | ||||||
|       user: data.user.id, |       user: data.user?.id, | ||||||
|       name: data.name, |       name: data.name, | ||||||
|       education: data.educations, |       education: data.educations, | ||||||
|       languages: data.languages.map(language => ({ |       languages: data.languages.map(language => ({ | ||||||
|   | |||||||
| @@ -378,7 +378,7 @@ const navigation = computed(() => | |||||||
|       href: '/resumes', |       href: '/resumes', | ||||||
|       section: 'Resumes', |       section: 'Resumes', | ||||||
|       icon: TemplateIcon, |       icon: TemplateIcon, | ||||||
|       can: true, |       can: props.auth.can.manageResumes, | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|   ].filter(item => item.can)) |   ].filter(item => item.can)) | ||||||
|   | |||||||
| @@ -73,5 +73,8 @@ | |||||||
|   "Key no :number has been taken from :user.": "Klucz nr :number został zabrany użytkownikowi :user.", |   "Key no :number has been taken from :user.": "Klucz nr :number został zabrany użytkownikowi :user.", | ||||||
|   "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user.", |   "Key no :number has been given to :user.": "Klucz nr :number został przekazany użytkownikowi :user.", | ||||||
|   ":sender gives key no :key to :recipient": ":sender przekazuje klucz nr :key :recipient", |   ":sender gives key no :key to :recipient": ":sender przekazuje klucz nr :key :recipient", | ||||||
|   ":recipient takes key no :key from :sender": ":recipient zabiera klucz nr :key :sender" |   ":recipient takes key no :key from :sender": ":recipient zabiera klucz nr :key :sender", | ||||||
|  |   "Resume has been updated.": "CV zostało zaktualizowane.", | ||||||
|  |   "Resume has been deleted.": "CV zostało usunięte.", | ||||||
|  |   "Resume has been created.": "CV zostało utworzone." | ||||||
| } | } | ||||||
|   | |||||||
| @@ -18,4 +18,4 @@ return [ | |||||||
|         4 => "Advanced", |         4 => "Advanced", | ||||||
|         5 => "Expert", |         5 => "Expert", | ||||||
|     ], |     ], | ||||||
| ]; | ]; | ||||||
|   | |||||||
| @@ -114,6 +114,43 @@ return [ | |||||||
|     "uploaded" => "Nie udało się wgrać pliku :attribute.", |     "uploaded" => "Nie udało się wgrać pliku :attribute.", | ||||||
|     "url" => "Format pola :attribute jest nieprawidłowy.", |     "url" => "Format pola :attribute jest nieprawidłowy.", | ||||||
|     "uuid" => "Pole :attribute musi być poprawnym identyfikatorem UUID.", |     "uuid" => "Pole :attribute musi być poprawnym identyfikatorem UUID.", | ||||||
|  |     "custom" => [ | ||||||
|  |         "education.*.school" => [ | ||||||
|  |             "required" => "Nazwa szkoły jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "education.*.degree" => [ | ||||||
|  |             "required" => "Stopień jest wymagany.", | ||||||
|  |         ], | ||||||
|  |         "education.*.fieldOfStudy" => [ | ||||||
|  |             "required" => "Kierunek jest wymagany.", | ||||||
|  |         ], | ||||||
|  |         "education.*.startDate" => [ | ||||||
|  |             "required" => "Data rozpoczęcia jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "education.*.endDate" => [ | ||||||
|  |             "required" => "Data zakończenia jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "languages.*.name" => [ | ||||||
|  |             "distinct" => "Języki nie mogą się powtarzać.", | ||||||
|  |             "required" => "Język jest wymagany.", | ||||||
|  |         ], | ||||||
|  |         "technologies.*.name" => [ | ||||||
|  |             "distinct" => "Technologie nie mogą się powtarzać.", | ||||||
|  |             "required" => "Technologia jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "projects.*.description" => [ | ||||||
|  |             "required" => "Opis projektu jest wymagany.", | ||||||
|  |         ], | ||||||
|  |         "projects.*.startDate" => [ | ||||||
|  |             "required" => "Data rozpoczęcia jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "projects.*.endDate" => [ | ||||||
|  |             "required" => "Data zakończenia jest wymagana.", | ||||||
|  |         ], | ||||||
|  |         "projects.*.tasks" => [ | ||||||
|  |             "required" => "Zadania w projekcie są wymagane.", | ||||||
|  |         ], | ||||||
|  |     ], | ||||||
|     "attributes" => [ |     "attributes" => [ | ||||||
|         "to" => "do", |         "to" => "do", | ||||||
|         "from" => "od", |         "from" => "od", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user