Skip to content

Commit 4eed410

Browse files
committed
1.0.0-beta.6: UI bugfixes, some QoL changes
- removed requirement that internship must not begin in past, for application form at Student - UI bugfixs cardbox allocation - some text edits - admins will now see e-mail stored in engine when re-sending emails 1.0.0-beta.6
1 parent b98ca33 commit 4eed410

15 files changed

+80
-81
lines changed

src/components/AsideMenu/AsideMenuItem.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ const menuClick = (event) => {
9797
class="flex cursor-pointer transition-all duration-150"
9898
:class="[componentClass, isCompact ? 'justify-center' : 'justify-start', item.color == 'info' ? 'hover:bg-fipu_dark_blue' : 'hover:bg-gray-900/75']">
9999
<BaseIcon v-if="item.icon" :path="item.icon" class="flex-none transition-all duration-300" :w="isCompact ? 'w-8 lg:w-16' : 'w-8'" :size="item.size ? item.size : 18" :class="[vSlot && vSlot.isExactActive ? asideMenuItemActiveStyle : asideMenuItemInactiveStyle, { relative: item.updateMark }, item.color == 'info' ? 'text-slate-800' : '']">
100-
<UpdateMark v-if="(item.updateMark && adminStore.dashboard_data.waiting_for_allocation > 0) || adminStore.dashboard_data.b_waiting_for_assignment_approval > 0" :color="item.updateMark" :position="isCompact ? 'top-0 left-5 md:left-9' : 'top-0 left-5'" />
100+
<UpdateMark v-if="item.updateMark && (adminStore.dashboard_data.waiting_for_allocation > 0 || adminStore.dashboard_data.b_waiting_for_assignment_approval > 0 || adminStore.dashboard_data.waiting_for_mark > 0)" :color="item.updateMark" :position="isCompact ? 'top-0 left-5 md:left-9' : 'top-0 left-5'" />
101101
</BaseIcon>
102102
103103
<span class="line-clamp-1 text-clip transition-all duration-300" :class="[{ '': isCompact, '': !hasSub }, vSlot && vSlot.isExactActive ? asideMenuItemActiveStyle : asideMenuItemInactiveStyle, isCompact ? (item.menu == undefined ? 'w-52 lg:w-0' : 'w-40 lg:w-0') : 'w-40', item.color == 'info' ? 'font-medium text-slate-900 hover:underline' : '']">

src/components/BPMN/BpmnDiagram.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,9 @@ function applyCustomStyling(highlightColor, highlightElementId, viewer) {
205205
}
206206
}
207207
}
208+
208209
// must be tested
210+
209211
// Animate the highlighting in order
210212
directPath.forEach((element, index) => {
211213
setTimeout(
@@ -216,8 +218,8 @@ function applyCustomStyling(highlightColor, highlightElementId, viewer) {
216218
applyHighlight(element, "highlight");
217219
}
218220
219-
// If the element is a Gateway, apply highlights to all outgoing connections
220-
if (element.type === "bpmn:ParallelGateway" || element.type === "bpmn:ExclusiveGateway") {
221+
// If the element is a ParallelGateway, apply highlights to all outgoing connections
222+
if (element.type === "bpmn:ParallelGateway") {
221223
const outgoing = element.outgoing || [];
222224
outgoing.forEach((connection) => {
223225
applyHighlight(connection.target, "highlight-previous");

src/components/Cardbox/CardBoxAllocation.vue

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,9 @@
44

55
<div class="sm:flex sm:justify-between sm:gap-4">
66
<div>
7-
<h1 class="text-lg font-bold sm:text-2xl">
7+
<h1 class="text-xl font-bold sm:text-2xl">
88
{{ props.data.id_zadatak }}
99
</h1>
10-
<h3 class="text-lg font-bold sm:text-xl">
11-
{{ truncatedDescription }}
12-
</h3>
13-
1410
<p class="mt-1 text-xs font-medium text-gray-600 dark:text-gray-200">
1511
{{ props.data["Poslodavac"][0]["value"] }}:
1612
{{ props.data.poslodavac_email }}
@@ -23,7 +19,7 @@
2319
</div>
2420

2521
<div>
26-
<p class="text-sm text-gray-500 dark:text-gray-300">
22+
<p class="mt-4 text-sm text-gray-500 dark:text-gray-300 sm:mt-0">
2723
{{ props.data.opis_zadatka }}
2824
</p>
2925
</div>

src/components/Cardbox/CardBoxModal.vue

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import BaseButtons from "@/components/Base/BaseButtons.vue";
44
import BaseButton from "@/components/Base/BaseButton.vue";
55
import OverlayLayer from "@/components/OverlayLayer.vue";
66
import CardBox from "@/components/Cardbox/CardBox.vue";
7-
import { computed, onMounted } from "vue";
7+
import { computed, watch } from "vue";
88
99
const props = defineProps({
1010
title: {
@@ -49,6 +49,14 @@ const value = computed({
4949
set: (value) => emit("update:modelValue", value),
5050
});
5151
52+
watch(value, (newValue) => {
53+
if (newValue) {
54+
document.body.style.overflow = "hidden";
55+
} else {
56+
document.body.style.overflow = "";
57+
}
58+
});
59+
5260
const confirmCancel = (mode) => {
5361
value.value = false;
5462
emit(mode);
@@ -76,14 +84,16 @@ window.addEventListener("keydown", (e) => {
7684
'mobile-fullscreen': !isLogout,
7785
}"
7886
is-modal>
79-
<CardBoxComponentTitle :title="title"> </CardBoxComponentTitle>
87+
<div class="modal-content">
88+
<CardBoxComponentTitle :title="title"></CardBoxComponentTitle>
8089

81-
<slot v-if="modelValue != null" :assignment="modelValue"></slot>
90+
<slot v-if="modelValue != null" :assignment="modelValue"></slot>
8291

83-
<BaseButtons class="justify-center">
84-
<BaseButton v-if="hasConfirm" :label="buttonLabel" :color="button" :disabled="disabledCondition" @click="confirm" />
85-
<BaseButton v-if="hasCancel" label="Natrag" :color="button" outline @click="cancel" />
86-
</BaseButtons>
92+
<BaseButtons class="justify-center">
93+
<BaseButton v-if="hasConfirm" :label="buttonLabel" :color="button" :disabled="disabledCondition" @click="confirm" />
94+
<BaseButton v-if="hasCancel" label="Natrag" :color="button" outline @click="cancel" />
95+
</BaseButtons>
96+
</div>
8797
</CardBox>
8898
</OverlayLayer>
8999
</template>
@@ -102,13 +112,19 @@ window.addEventListener("keydown", (e) => {
102112
max-height: 100vh;
103113
top: 0;
104114
left: 0;
105-
right: 0;
106-
bottom: 0;
107115
position: fixed;
108116
margin: 0;
109117
border-radius: 0;
110118
overflow-y: auto;
111-
padding: 1rem;
119+
}
120+
121+
/* Center the content inside the modal */
122+
.modal-content {
123+
display: flex;
124+
flex-direction: column;
125+
justify-content: center;
126+
align-items: center;
127+
min-height: 100%;
112128
}
113129
}
114130
</style>

src/components/Internship/Student_DnevnikPrakseForm.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ async function submit_diary_form() {
106106
<br />
107107
<SectionTitleLineWithButton :icon="mdiNotebook" main title="Dnevnik prakse"></SectionTitleLineWithButton>
108108
<p><b>Nakon što se završili praksu</b> i ispunili sve vaše obaveze, predajete dnevnik prakse skupa s ispunjenom potvrdom o obavljenoj praksi.</p>
109-
<p>Potvrdu ispunjava vaš mentor, vi predajete PDF sken ispunjene potvrde.</p>
109+
<p>Potvrdu ispunjava vaš mentor, vi predajete PDF sken (ili digitalno potpisani PDF) ispunjene potvrde.</p>
110110
<p>Dnevnik prakse je potrebno predati prije prijave ispitnog roka.</p>
111111
<br />
112112
<p>
@@ -129,7 +129,7 @@ async function submit_diary_form() {
129129
</FormField>
130130

131131
<FormField
132-
label="PDF sken ispunjene potvrde o obavljenoj praksi"
132+
label="PDF ispunjene potvrde o obavljenoj praksi"
133133
help="obavezno PDF format
134134
"
135135
horizontal>

src/components/Internship/Student_PrijavnicaForm.vue

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ const rules = {
9393
student_email: {
9494
required: helpers.withMessage("Polje je obavezno", required),
9595
email: helpers.withMessage("Molimo unesite ispravnu e-mail adresu", email),
96-
isUnipuEmail: helpers.withMessage("E-mail mora biti UNIPU adresa", isUnipuEmail),
9796
},
9897
mentor_ime: {
9998
required: helpers.withMessage("Polje je obavezno", required),
@@ -117,13 +116,6 @@ const rules = {
117116
pocetak_prakse: {
118117
required: helpers.withMessage("Polje je obavezno", required),
119118
120-
dateMustBeAfterCurrentDate: helpers.withMessage("Datum početka ne može biti u prošlosti", (value) => {
121-
const currentDate = new Date();
122-
const selectedDate = new Date(value);
123-
124-
return !(selectedDate <= currentDate);
125-
}),
126-
127119
dateMustBeBeforeKrajPrakse: helpers.withMessage("Datum početka ne može biti nakon datuma završetka", (value) => {
128120
const krajPrakseDate = new Date(form.kraj_prakse);
129121
const selectedDate = new Date(value);

src/router/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ router.beforeEach((to, from, next) => {
2222

2323
const requiresAuth = to.matched.some((record) => record.meta.requiresAuth);
2424
const requiresAdmin = to.matched.some((record) => record.meta.requiresAdmin);
25-
//console.log("to", to, "from", from, "next", next);
2625

2726
// Handle redirection from root path
2827
if (to.path === "/") {

src/router/routes.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ const routes = [
175175
component: () => import("@/views/NewAssignmentFormPublic.vue"),
176176
},
177177
{
178-
path: "/error",
179-
name: "ErrorView",
178+
path: "/:pathMatch(.*)*", // Vue 3 wildcard route
179+
name: "ne postoji",
180180
component: () => import("@/views/common/ErrorView.vue"),
181181
},
182182
];

src/stores/admin_store.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ export const useAdminStore = defineStore("admin", {
8686
selectedEvents: [] as any[], // Assuming events are not yet typed
8787
events: [] as Event[], // Typed array of Event
8888
relativeToNowTimestmap: true,
89-
filterActiveInstances: true,
90-
filterFinishedInstances: true,
89+
filterActiveInstances: false,
90+
91+
filterFinishedInstances: false,
9192
availableAssignmentsFilter: true,
9293

9394
filterModelA: "AB",

src/stores/main_store.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export interface Assignment {
1212

1313
export const useMainStore = defineStore("main", {
1414
state: () => ({
15-
praksa_version: "1.0.0-beta.5",
15+
praksa_version: "1.0.0-beta.6",
1616
academicYear: "2024/2025",
1717
voditelj_prakse: "doc. dr. sc. Ivan Lorencin",
1818

@@ -65,7 +65,6 @@ export const useMainStore = defineStore("main", {
6565

6666
actions: {
6767
async fetchCurrentUser(): Promise<void> {
68-
console.log("Fetching current user");
6968
try {
7069
let sessionStorageToken;
7170
try {
@@ -258,7 +257,7 @@ export const useMainStore = defineStore("main", {
258257
},
259258
persist: {
260259
storage: sessionStorage,
261-
omit: ["assignments", "checkedAssignments", "praksa_version"],
260+
omit: ["assignments", "checkedAssignments"],
262261
debug: true,
263262
},
264263
});

src/views/EvaluationView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const updateDisabledCondition = (allFilled) => {
101101

102102
<p class="mb-4">Molimo da nakon što evaluirate studenta (bilo to kroz intervju, tehnički ispit ili pak bez procesa selekcije) potvrdite prihvaćate li studenta za obavljanje prakse u Vašem poduzeću.</p>
103103

104-
<FormDynamic v-if="pendingTaskInfo != null" v-model="formDynamicValues" class="mb-4" :form-fields="pendingTaskInfo.form_fields" :variables="instanceInfo.variables" :documentation="pendingTaskInfo.documentation" @all-fields-filled="updateDisabledCondition" />
104+
<FormDynamic v-if="pendingTaskInfo != null" v-model="formDynamicValues" class="mb-4 rounded-md p-1" :form-fields="pendingTaskInfo.form_fields" :variables="instanceInfo.variables" :documentation="pendingTaskInfo.documentation" @all-fields-filled="updateDisabledCondition" />
105105

106106
<BaseButton v-if="formDynamicValues['kandidat_odobren']" class="mb-4" label="Potvrdi" :loading="isLoading" color="fipu_blue" @disabled="disabledCondition" @click="handleNewInstance()" />
107107
</div>

src/views/admin/DashboardView.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ const toggleDateType = () => {
222222
</div>
223223

224224
<div class="flex flex-row">
225-
<div class="mb-4"><PillTag class="cursor-pointer" :left="false" :icon="adminStore.filterActiveInstances ? mdiAccountGroup : mdiAccountMultiple" :color="adminStore.filterActiveInstances ? 'info' : 'success'" :label="adminStore.filterActiveInstances ? 'Sve instance' : 'Samo aktivne'" @click="toggleActiveEventsFilter" /></div>
225+
<div class="mb-4"><PillTag class="cursor-pointer" :left="false" :icon="adminStore.filterActiveInstances ? mdiAccountGroup : mdiAccountMultiple" :color="adminStore.filterActiveInstances ? 'info' : 'success'" :label="adminStore.filterActiveInstances ? 'Sve instance' : 'Aktivne instance'" @click="toggleActiveEventsFilter" /></div>
226226
</div>
227227
<div class="flex flex-row">
228228
<div class="mb-4"><PillTag class="cursor-pointer" :icon="adminStore.filterModelState === 'A' ? mdiAlphaACircle : adminStore.filterModelState === 'B' ? mdiAlphaBCircleOutline : mdiAbTesting" :color="adminStore.filterModelState === 'A' ? 'danger' : adminStore.filterModelState === 'B' ? 'success' : 'info'" :label="adminStore.filterModelState === 'A' ? 'Model A' : adminStore.filterModelState === 'B' ? 'Model B' : 'Modeli AB'" @click="toggleModelEventsFilter" /></div>

src/views/admin/StudentsInternshipView.vue

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,12 @@ async function handleProcessDiagram() {
7979
}
8080
8181
const route = useRoute();
82+
8283
// Load data based on process_instance_id from the route
8384
async function loadDataForStudent() {
8485
const id = route.params.process_instance_id;
8586
if (id) {
8687
const student = { process_instance_id: id };
87-
8888
process_instance_data.value = await adminStore.getProcessInstanceData(student);
8989
}
9090
}
@@ -130,16 +130,24 @@ const toggleBetweenModelsFilter = () => {
130130
}
131131
};
132132
133+
let email_postData = ref(null);
134+
let email_template = ref(null);
135+
let email_to = ref(null);
136+
133137
async function sendAnAdditionalEmail() {
134-
let { postData, template, to } = getPostDataForSendEmail();
138+
//let { postData, template, to } = getPostDataForSendEmail();
139+
140+
let postData = email_postData.value;
141+
let template = email_template.value;
142+
let to = email_to.value;
135143
136144
if (newEmail.value) {
137145
to = newEmail.value;
138146
}
139147
140148
if (postData && template && to) {
141149
await adminStore.sendAnAdditionalEmail(postData, to, template);
142-
snackBarStore.pushMessage("Email je uspješno poslan!", "success");
150+
snackBarStore.pushMessage("Dodatni email uspješno poslan!", "success");
143151
modal_send_task.value = false;
144152
}
145153
}
@@ -148,6 +156,17 @@ watch(() => route.params.process_instance_id, loadDataForStudent, {
148156
immediate: true,
149157
});
150158
159+
watch(modal_send_task, (newValue) => {
160+
let { postData, template, to } = getPostDataForSendEmail();
161+
email_postData.value = postData;
162+
email_template.value = template;
163+
email_to.value = to;
164+
165+
if (newValue) {
166+
newEmail.value = to;
167+
}
168+
});
169+
151170
onMounted(async () => {
152171
await adminStore.getStudents();
153172
});
@@ -170,7 +189,7 @@ onMounted(loadDataForStudent);
170189
<SectionMain>
171190
<SectionTitleLineWithButton :icon="mdiAccountMultiple" title="Studenti u procesu prakse" button-enabled main @click="bpmn_help_modal = true"> </SectionTitleLineWithButton>
172191
<div class="flex flex-row">
173-
<div class="mb-4"><PillTag class="cursor-pointer" :left="false" :icon="adminStore.filterFinishedInstances ? mdiAccountGroup : mdiAccountMultiple" :color="adminStore.filterFinishedInstances ? 'info' : 'success'" :label="adminStore.filterFinishedInstances ? 'Sve instance' : 'Samo aktivne'" @click="toggleActiveEventsFilter" /></div>
192+
<div class="mb-4"><PillTag class="cursor-pointer" :left="false" :icon="adminStore.filterFinishedInstances ? mdiAccountGroup : mdiAccountMultiple" :color="adminStore.filterFinishedInstances ? 'info' : 'success'" :label="adminStore.filterFinishedInstances ? 'Sve instance' : 'Aktivne instance'" @click="toggleActiveEventsFilter" /></div>
174193
<div class="mb-4"><PillTag class="cursor-pointer" :icon="adminStore.filterModelState === 'A' ? mdiAlphaACircle : adminStore.filterModelState === 'B' ? mdiAlphaBCircleOutline : mdiAbTesting" :color="adminStore.filterModelState === 'A' ? 'danger' : adminStore.filterModelState === 'B' ? 'success' : 'info'" :label="adminStore.filterModelState === 'A' ? 'Model A' : adminStore.filterModelState === 'B' ? 'Model B' : 'Modeli AB'" @click="toggleBetweenModelsFilter" /></div>
175194
</div>
176195

@@ -201,8 +220,8 @@ onMounted(loadDataForStudent);
201220
</CardBoxModal>
202221

203222
<CardBoxModal v-if="modal_send_task" v-model="modal_send_task" :title="'Ponovno slanje emaila'" has-cancel button-label="Pošalji" @confirm="sendAnAdditionalEmail()">
204-
<p class="">E-mail je već poslan koristeći kroz BPMN engine, no možete ga poslati ponovo pritiskom na 'Pošalji'</p>
205-
<p class="mb-2">Dodatno, možete unijeti e-mail te poslati na novu adresu. Ako želite poslati na adresu pohranjenu u <i>logovima enginea</i>, ostavite prazno.</p>
223+
<p class="">E-mail je već poslan putem BPMN enginea, ali ga možete ponovo poslati klikom na gumb 'Pošalji'.</p>
224+
<p class="mb-2">Ispod je prikazan e-mail koji je pohranjen u BPMN engineu, no možete unijeti novi e-mail u polje ispod i poslati ga, u tom slučaju, e-mail u engineu neće biti izmijenjen.</p>
206225

207226
<FormField label="Novi E-mail">
208227
<FormControl v-model="newEmail" :icon-left="mdiAccount" name="email" autocomplete="email" />

src/views/common/ErrorView.vue

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
<script setup>
2-
import SectionFullScreen from "@/components/Section/SectionFullScreen.vue";
3-
import CardBox from "@/components/Cardbox/CardBox.vue";
2+
import BaseButton from "../../components/Base/BaseButton.vue";
3+
import { router } from "@/router";
44
</script>
55

66
<template>
7-
<SectionFullScreen v-slot="{ cardClass }" bg="blue">
8-
<CardBox class="rounded-lg" :class="cardClass">
9-
<div class="space-y-3">
10-
<h1 class="text-2xl">❌ Nešto se zeznulo. Sorry!</h1>
11-
<p>Aplikacija ne radi. Vjerojatno radimo na tome, probaj refreshati!</p>
7+
<section class="bg-white dark:bg-gray-900">
8+
<div class="mx-auto max-w-screen-xl px-4 py-8 lg:px-6 lg:py-16">
9+
<div class="mx-auto max-w-screen-sm text-center">
10+
<h1 class="dark:text-primary-500 mb-4 text-7xl font-extrabold tracking-tight text-fipu_blue lg:text-9xl">404</h1>
11+
<p class="mb-4 text-3xl font-bold tracking-tight text-gray-900 dark:text-white md:text-4xl">Stranica ne postoji.</p>
12+
<p class="mb-4 text-lg font-light text-gray-500 dark:text-gray-400">Stranica koju ste zatražili ne postoji, vjerojatno je greška u URL-u!</p>
13+
<BaseButton label="Vrati me na početnu" color="fipu_blue" outline @click="router.push('/')" />
1214
</div>
13-
</CardBox>
14-
</SectionFullScreen>
15+
</div>
16+
</section>
1517
</template>

src/views/student/ProcessStateViewStudent.vue

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -92,33 +92,6 @@ function getPostDataForSendEmail() {
9292
};
9393
}
9494
95-
const toggleActiveEventsFilter = () => {
96-
adminStore.filterFinishedInstances = !adminStore.filterFinishedInstances;
97-
};
98-
99-
async function sendAnAdditionalEmail() {
100-
let { postData, template, to } = getPostDataForSendEmail();
101-
102-
if (newEmail.value) {
103-
to = newEmail.value;
104-
}
105-
106-
if (postData && template && to) {
107-
await adminStore.sendAnAdditionalEmail(postData, to, template);
108-
snackBarStore.pushMessage("Email je uspješno poslan!", "success");
109-
modal_send_task.value = false;
110-
}
111-
}
112-
113-
async function handleNewInstance() {
114-
adminStore.handleNewInstance(process_instance_data.value.id, process_instance_data.value.pending[0], formDynamicValues.value);
115-
if (UserTaskMappings.getTaskProperty(process_instance_data.value.pending[0], "snackbar_msg")) {
116-
snackBarStore.pushMessage(UserTaskMappings.getTaskProperty(process_instance_data.value.pending[0], "snackbar_msg"), UserTaskMappings.getTaskProperty(process_instance_data.value.pending[0], "snackbar_color"));
117-
}
118-
await Utils.wait(2);
119-
location.reload();
120-
}
121-
12295
const process_instance_id = ref(null);
12396
const bpmn_model = ref(null);
12497

0 commit comments

Comments
 (0)