This commit is contained in:
EwelinaLasowy 2022-05-16 14:26:32 +02:00
parent c74fc16acd
commit 7158e07920
11 changed files with 73 additions and 16 deletions

View File

@ -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);
} }
} }

View File

@ -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()

View File

@ -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,
], ],
]; ];
} }

View File

@ -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,

View File

@ -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',
}, },
] ]

View File

@ -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 => ({

View File

@ -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 => ({

View File

@ -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))

View File

@ -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."
} }

View File

@ -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",