Merge branch 'main' of bitbucket.org:studiotem/jandl-taskmanager-app

This commit is contained in:
StudioTem committed 2023-01-16 11:11:21 +01:00
commit 2141a4da7c
39 files changed
+14490 -807

No files matched your search

+13887 -168
View File
File diff suppressed because it is too large. Load diff
+18 -27
View File
@@ -38,9 +38,8 @@
"tasks": [ "tasks": [
{ {
"id": 1, "id": 1,
"task_id": 1, "starts_at": "2023-01-11T08:01:00+00:00",
"starts_at": "2023-01-08T08:01:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"ends_at": "2023-01-08T09:00:00+00:00",
"title": "Task DNES", "title": "Task DNES",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E9FFE6", "master_task_color": "#E9FFE6",
@@ -49,9 +48,8 @@
{ {
"id": 2, "id": 2,
"task_id": 2, "starts_at": "2023-01-12T08:30:00+00:00",
"starts_at": "2023-01-08T08:30:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-08T09:00:00+00:00",
"title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e", "title": "Kratky 30min Lorem ipsum dolor sit amet, consectetur adipiscing e",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
@@ -60,9 +58,8 @@
{ {
"id": 3, "id": 3,
"task_id": 3, "starts_at": "2023-01-12T10:30:00+00:00",
"starts_at": "2023-01-08T10:30:00+00:00", "ends_at": "2023-01-12T10:45:00+00:00",
"ends_at": "2023-01-08T10:45:00+00:00",
"title": "Kratky 15min", "title": "Kratky 15min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -71,9 +68,8 @@
{ {
"id": 4, "id": 4,
"task_id": 4, "starts_at": "2023-01-13T08:00:00+00:00",
"starts_at": "2023-01-08T08:00:00+00:00", "ends_at": "2023-01-13T10:00:00+00:00",
"ends_at": "2023-01-08T10:00:00+00:00",
"title": "Task 2", "title": "Task 2",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#FDE1FF", "master_task_color": "#FDE1FF",
@@ -82,9 +78,8 @@
{ {
"id": 6, "id": 6,
"task_id": 6, "starts_at": "2023-01-13T09:00:00+00:00",
"starts_at": "2023-01-09T09:00:00+00:00", "ends_at": "2023-01-13T12:00:00+00:00",
"ends_at": "2023-01-09T12:00:00+00:00",
"title": "Task 6", "title": "Task 6",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -93,9 +88,8 @@
{ {
"id": 7, "id": 7,
"task_id": 7, "starts_at": "2023-01-13T12:00:00+00:00",
"starts_at": "2023-01-10T12:00:00+00:00", "ends_at": "2023-01-13T16:00:00+00:00",
"ends_at": "2023-01-10T16:00:00+00:00",
"title": "Task 7", "title": "Task 7",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E7DBF8", "master_task_color": "#E7DBF8",
@@ -104,9 +98,8 @@
{ {
"id": 8, "id": 8,
"task_id": 8, "starts_at": "2023-01-14T07:00:00+00:00",
"starts_at": "2023-01-08T07:00:00+00:00", "ends_at": "2023-01-14T09:00:00+00:00",
"ends_at": "2023-01-08T09:00:00+00:00",
"title": "Task 8", "title": "Task 8",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -115,9 +108,8 @@
{ {
"id": 9, "id": 9,
"task_id": 9, "starts_at": "2023-01-14T09:00:00+00:00",
"starts_at": "2023-01-09T09:00:00+00:00", "ends_at": "2023-01-14T12:00:00+00:00",
"ends_at": "2023-01-09T12:00:00+00:00",
"title": "Task 9", "title": "Task 9",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E9FFE6", "master_task_color": "#E9FFE6",
@@ -126,9 +118,8 @@
{ {
"id": 10, "id": 10,
"task_id": 10, "starts_at": "2023-01-14T12:00:00+00:00",
"starts_at": "2023-01-08T12:00:00+00:00", "ends_at": "2023-01-14T13:00:00+00:00",
"ends_at": "2023-01-08T13:00:00+00:00",
"title": "Task 10", "title": "Task 10",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
+21 -33
View File
@@ -10,9 +10,8 @@
"tasks": [ "tasks": [
{ {
"id": 1, "id": 1,
"task_id": 1, "starts_at": "2023-01-12T08:01:00+00:00",
"starts_at": "2023-01-11T08:01:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Task DNES", "title": "Task DNES",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E9FFE6", "master_task_color": "#E9FFE6",
@@ -21,9 +20,8 @@
{ {
"id": 2, "id": 2,
"task_id": 2, "starts_at": "2023-01-12T08:30:00+00:00",
"starts_at": "2023-01-11T08:30:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
@@ -32,9 +30,8 @@
{ {
"id": 3, "id": 3,
"task_id": 3, "starts_at": "2023-01-13T10:30:00+00:00",
"starts_at": "2023-01-11T10:30:00+00:00", "ends_at": "2023-01-13T10:45:00+00:00",
"ends_at": "2023-01-11T10:45:00+00:00",
"title": "Kratky 15min", "title": "Kratky 15min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -51,10 +48,9 @@
"unscheduled_time": 10, "unscheduled_time": 10,
"tasks": [ "tasks": [
{ {
"id": 1, "id": 4,
"task_id": 1, "starts_at": "2023-01-12T08:01:00+00:00",
"starts_at": "2023-01-11T08:01:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Task DNES", "title": "Task DNES",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E9FFE6", "master_task_color": "#E9FFE6",
@@ -62,10 +58,9 @@
}, },
{ {
"id": 2, "id": 5,
"task_id": 2, "starts_at": "2023-01-12T08:30:00+00:00",
"starts_at": "2023-01-11T08:30:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
@@ -73,10 +68,9 @@
}, },
{ {
"id": 3, "id": 6,
"task_id": 3, "starts_at": "2023-01-12T10:30:00+00:00",
"starts_at": "2023-01-11T10:30:00+00:00", "ends_at": "2023-01-12T10:45:00+00:00",
"ends_at": "2023-01-11T10:45:00+00:00",
"title": "Kratky 15min", "title": "Kratky 15min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -94,9 +88,8 @@
"tasks": [ "tasks": [
{ {
"id": 1, "id": 1,
"task_id": 1, "starts_at": "2023-01-13T08:01:00+00:00",
"starts_at": "2023-01-11T08:01:00+00:00", "ends_at": "2023-01-13T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Task DNES", "title": "Task DNES",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#E9FFE6", "master_task_color": "#E9FFE6",
@@ -105,9 +98,8 @@
{ {
"id": 2, "id": 2,
"task_id": 2, "starts_at": "2023-01-12T08:30:00+00:00",
"starts_at": "2023-01-11T08:30:00+00:00", "ends_at": "2023-01-12T09:00:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min", "title": "Kratky 30min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#f27e57", "master_task_color": "#f27e57",
@@ -116,9 +108,8 @@
{ {
"id": 3, "id": 3,
"task_id": 3, "starts_at": "2023-01-13T10:30:00+00:00",
"starts_at": "2023-01-11T10:30:00+00:00", "ends_at": "2023-01-13T10:45:00+00:00",
"ends_at": "2023-01-11T10:45:00+00:00",
"title": "Kratky 15min", "title": "Kratky 15min",
"project_code": "CO-2201", "project_code": "CO-2201",
"master_task_color": "#57e0f2", "master_task_color": "#57e0f2",
@@ -136,7 +127,6 @@
"tasks": [ "tasks": [
{ {
"id": 1, "id": 1,
"task_id": 1,
"starts_at": "2023-01-11T08:01:00+00:00", "starts_at": "2023-01-11T08:01:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Task DNES", "title": "Task DNES",
@@ -147,7 +137,6 @@
{ {
"id": 2, "id": 2,
"task_id": 2,
"starts_at": "2023-01-11T08:30:00+00:00", "starts_at": "2023-01-11T08:30:00+00:00",
"ends_at": "2023-01-11T09:00:00+00:00", "ends_at": "2023-01-11T09:00:00+00:00",
"title": "Kratky 30min", "title": "Kratky 30min",
@@ -158,7 +147,6 @@
{ {
"id": 3, "id": 3,
"task_id": 3,
"starts_at": "2023-01-11T10:30:00+00:00", "starts_at": "2023-01-11T10:30:00+00:00",
"ends_at": "2023-01-11T10:45:00+00:00", "ends_at": "2023-01-11T10:45:00+00:00",
"title": "Kratky 15min", "title": "Kratky 15min",
+1 -1
View File
@@ -31,7 +31,7 @@
}, },
"employee_id": 1, "employee_id": 1,
"duration": 1000000, "duration": 1000000,
"remaining_time": 150, "spent_time": 150,
"is_finished": false, "is_finished": false,
"starts_at": "2022-11-10T11:00:00+00:00", "starts_at": "2022-11-10T11:00:00+00:00",
"ends_at": "2022-11-12T16:00:00+00:00", "ends_at": "2022-11-12T16:00:00+00:00",
@@ -29,11 +29,11 @@
<v-btn class="menu-dropdown" v-bind="props"> <v-btn class="menu-dropdown" v-bind="props">
<div class="d-flex justify-between align-center"> <div class="d-flex justify-between align-center">
<p class="employee-select-avatar d-flex justify-center align-center" @click.stop="$router.push({name: 'Dashboard - User'})"> <p class="employee-select-avatar d-flex justify-center align-center" @click.stop="$router.push({name: 'Dashboard - User'})">
{{ user.user.name.charAt(0) + user.user.surname.charAt(0) }} {{ user.name.charAt(0) + user.surname.charAt(0) }}
</p> </p>
<div> <div>
<span class="employee-name ml-4">{{ `${user.user.name} ${user.user.surname}` }}</span> <span class="employee-name ml-4">{{ `${user.name} ${user.surname}` }}</span>
<v-icon class="ml-3" icon="mdi-chevron-down" size="x-small"></v-icon> <v-icon class="ml-3" icon="mdi-chevron-down" size="x-small"></v-icon>
</div> </div>
</div> </div>
@@ -41,7 +41,7 @@
</template> </template>
<v-list class="text-center"> <v-list class="text-center">
<v-list-item class="cursor-pointer hover-background">Working hours </v-list-item> <v-list-item class="cursor-pointer hover-background" @click.stop="$router.push({name: 'Dashboard - User'})">Profil</v-list-item>
<v-list-item> <v-list-item>
<v-btn class="button" @click="logOut()">Odhlásiť sa</v-btn> <v-btn class="button" @click="logOut()">Odhlásiť sa</v-btn>
</v-list-item> </v-list-item>
@@ -58,6 +58,7 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'
import ZTeamModal from '@/plugins/tm@modal/team/z-team-modal.vue' import ZTeamModal from '@/plugins/tm@modal/team/z-team-modal.vue'
import ZBlockerModal from '@/plugins/tm@modal/blocker/z-blocker-modal.vue' import ZBlockerModal from '@/plugins/tm@modal/blocker/z-blocker-modal.vue'
import ZMasterTaskModal from '@/plugins/tm@modal/master-task/z-master-task-modal.vue' import ZMasterTaskModal from '@/plugins/tm@modal/master-task/z-master-task-modal.vue'
@@ -71,18 +72,13 @@ export default {
ZSubTaskModal ZSubTaskModal
}, },
data() { computed: {
return { ...mapGetters('auth', ['user']),
user: null,
search: ''
}
}, },
async created() { data() {
try { return {
this.user = await this.$axios.get_auth_data('v1/auth/info') search: ''
} catch (error) {
console.log(error)
} }
}, },
@@ -93,7 +89,7 @@ export default {
this.$router.push('/') this.$router.push('/')
this.$toast.success('Boli ste odhlásený') this.$toast.success('Boli ste odhlásený')
} catch (error) { } catch (error) {
this.$toast.error(error.data.error) this.$toast.error(error)
} }
}, },
@@ -1,93 +0,0 @@
.auth-card {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 16px;
padding: 30px;
width: 100%;
max-width: 486px;
margin: auto;
}
.auth-card img {
position: absolute;
right: 60px;
bottom: 188px;
cursor: pointer;
}
.auth-card .button {
color: white !important;
}
.auth-card .v-field {
border-bottom: 1px solid rgba(0, 0, 0, 0);
}
.auth-card .error .v-field {
border-bottom: 1px solid red;
}
@media screen and (max-width: 904px) {
.auth-card {
position: relative;
padding: 0;
border: none;
top: 0;
left: 0;
transform: translate(0, 0);
}
.auth-card h1 {
font-size: 19px;
}
.auth-card p {
font-size: 15px;
}
.auth-card .v-icon {
position: absolute !important;
right: 15px;
}
}
.v-field--variant-solo {
box-shadow: none !important;
border: 1px solid rgba(0, 0, 0, 0.1) !important;
}
.auth-card .error .v-field {
border: 0.5px solid red !important;
}
.error .v-field {
border: 0.5px solid red !important;
}
.error .dp__input {
border: 0.5px solid red !important;
}
.v-input__append {
margin: 0 !important;
}
.v-input__append .v-icon {
position: absolute !important;
right: 45px;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
.error-message {
position: absolute;
top: 50%;
left: 30px;
color: red;
opacity: 0.8;
}
.v-select .v-field--variant-solo {
border: none !important;
}
.v-messages__message {
color: red !important;
}/*# sourceMappingURL=auth.theme.css.map */
@@ -1 +0,0 @@
{"version":3,"sources":["auth.theme.sass","auth.theme.css"],"names":[],"mappings":"AAAA;EACC,kBAAA;EACA,QAAA;EACA,SAAA;EACA,gCAAA;EACA,oCAAA;EACA,mBAAA;EACA,aAAA;EACA,WAAA;EACA,gBAAA;EACA,YAAA;ACCD;ADCC;EACC,kBAAA;EACA,WAAA;EACA,aAAA;EACA,eAAA;ACCF;ADCC;EACC,uBAAA;ACCF;ADCC;EACC,yCAAA;ACCF;ADCC;EACC,4BAAA;ACCF;;ADCA;EACC;IACC,kBAAA;IACA,UAAA;IACA,YAAA;IACA,MAAA;IACA,OAAA;IACA,0BAAA;ECEA;EDAA;IACC,eAAA;ECED;EDAA;IACC,eAAA;ECED;EDAA;IACC,6BAAA;IACA,WAAA;ECED;AACF;ADDA;EACC,2BAAA;EACA,+CAAA;ACGD;;ADDA;EACC,kCAAA;ACID;;ADFA;EACC,kCAAA;ACKD;;ADHA;EACC,kCAAA;ACMD;;ADJA;EACC,oBAAA;ACOD;ADLC;EACC,6BAAA;EACA,WAAA;ACOF;;ADLA;;EAEC,wBAAA;ACQD;;ADNA;EACC,kBAAA;EACA,QAAA;EACA,UAAA;EACA,UAAA;EACA,YAAA;ACSD;;ADPA;EACC,uBAAA;ACUD;;ADRA;EACC,qBAAA;ACWD","file":"auth.theme.css"}
@@ -40,7 +40,7 @@ export default {
await this.$axios.post_data('v1/auth/forgot', this.form) await this.$axios.post_data('v1/auth/forgot', this.form)
this.$router.push({ name: 'Reset password' }) this.$router.push({ name: 'Reset password' })
} catch (error) { } catch (error) {
this.$toast.error(error.data.error) this.$toast.error(error)
} }
} }
} }
@@ -44,7 +44,7 @@ export default {
await this.$axios.post_data('v1/auth/login', this.form) await this.$axios.post_data('v1/auth/login', this.form)
this.$router.push({ name: 'Overview - Ongoing tasks'}) this.$router.push({ name: 'Overview - Ongoing tasks'})
} catch (error) { } catch (error) {
this.$toast.error(error.data.error) this.$toast.error(error)
} }
} }
} }
@@ -49,7 +49,7 @@ export default {
await this.$axios.post_data('v1/auth/reset', this.form) await this.$axios.post_data('v1/auth/reset', this.form)
this.$router.push({ name: 'Login' }) this.$router.push({ name: 'Login' })
} catch (error) { } catch (error) {
this.$toast.error(error.data.error) this.$toast.error(error)
} }
} }
} }
+1 -1
View File
@@ -17,7 +17,7 @@ export default {
return { return {
search: null search: null
} }
}, },
created() { created() {
this.eventBus.on('onSearch', (search) => { this.eventBus.on('onSearch', (search) => {
@@ -25,6 +25,7 @@
> >
<template v-slot:split-label="{ split }"> <template v-slot:split-label="{ split }">
<div class="w-100 h-100 d-flex flex-column"> <div class="w-100 h-100 d-flex flex-column">
<h1 @click="addTimeModal()">Tu mas napojeny modal</h1>
<span v-if="split.date" class="d-flex align-center"> <span v-if="split.date" class="d-flex align-center">
<img v-if="getHeadingDate(split.date) == 'Dnes'" :src="require('./_img/home-icon.svg')" class="mr-2"> <img v-if="getHeadingDate(split.date) == 'Dnes'" :src="require('./_img/home-icon.svg')" class="mr-2">
<p class="weekday-label">{{ getHeadingDate(split.date) }}</p> <p class="weekday-label">{{ getHeadingDate(split.date) }}</p>
@@ -33,6 +34,10 @@
<p class="weekday-label">{{ split.firstName }}</p> <p class="weekday-label">{{ split.firstName }}</p>
</span> </span>
<span v-if="split.date">
<p class="day-name" >{{ split.date.toLocaleDateString('sk-SK', { weekday: 'long' }) }}</p>
</span>
<div v-if="split.unscheduledTime && split.initials" class="unscheduled-time d-flex align-center text-left"> <div v-if="split.unscheduledTime && split.initials" class="unscheduled-time d-flex align-center text-left">
<div class="unscheduled-time-initials d-flex align-center justify-center me-4"> <div class="unscheduled-time-initials d-flex align-center justify-center me-4">
<p>{{split.initials}}</p> <p>{{split.initials}}</p>
@@ -66,7 +71,7 @@
</div> </div>
</div> </div>
<div class="event-footer d-flex"> <div class="event-footer d-flex">
<v-btn rounded class="event-footer-button me-2" :class="{'completed': event.completed}" @click="clickCompleteTask(event)"><img :src="require('./_img/checkmark.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" :class="{'completed': event.completed}" @click="clickCompleteTask(event)"><img :src="require('./_img/checkmark.svg')" alt=""></v-btn>
<v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event.id, true)"><img :src="require('./_img/pencil.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event.id, true)"><img :src="require('./_img/pencil.svg')" alt=""></v-btn>
<v-btn rounded class="event-footer-button me-2" @click.stop="this.showDeleteModal = {task: event}"><img :src="require('./_img/bin.svg')" alt=""></v-btn> <v-btn rounded class="event-footer-button me-2" @click.stop="this.showDeleteModal = {task: event}"><img :src="require('./_img/bin.svg')" alt=""></v-btn>
@@ -83,8 +88,11 @@
</Vue-cal> </Vue-cal>
<Z-sub-task-modal ref="z-sub-task-modal" /> <Z-sub-task-modal ref="z-sub-task-modal" />
<!-- Kravarik: Prerobit modaly na novy sposob -->
<Z-complete-task-modal v-if="showCompleteModal" :visible="showCompleteModal ? true : false" :task="showCompleteModal.task" @completeTask="completeTask" @close="showCompleteModal = null" /> <Z-complete-task-modal v-if="showCompleteModal" :visible="showCompleteModal ? true : false" :task="showCompleteModal.task" @completeTask="completeTask" @close="showCompleteModal = null" />
<Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @deleteTask="deleteTask" @close="showDeleteModal = null" /> <Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @deleteTask="deleteTask" @close="showDeleteModal = null" />
<Z-add-time-task-modal ref="z-add-time-task-modal" />
</div> </div>
</template> </template>
@@ -92,12 +100,15 @@
import ZCompleteTaskModal from '@/plugins/tm@modal/task/z-complete-task-modal.vue' import ZCompleteTaskModal from '@/plugins/tm@modal/task/z-complete-task-modal.vue'
import ZDeleteTaskModal from '@/plugins/tm@modal/task/z-delete-task-modal.vue' import ZDeleteTaskModal from '@/plugins/tm@modal/task/z-delete-task-modal.vue'
import ZSubTaskModal from '@/plugins/tm@modal/sub-task/z-sub-task-modal.vue' import ZSubTaskModal from '@/plugins/tm@modal/sub-task/z-sub-task-modal.vue'
import ZAddTimeTaskModal from '@/plugins/tm@modal/sub-task/z-add-time-task-modal.vue'
export default { export default {
components: { components: {
ZCompleteTaskModal, ZCompleteTaskModal,
ZDeleteTaskModal, ZDeleteTaskModal,
ZSubTaskModal ZSubTaskModal,
ZAddTimeTaskModal
}, },
props: { props: {
@@ -142,13 +153,9 @@ export default {
} }
}, },
mounted() {
// console.log(this.calData.tasks)
},
methods: { methods: {
weekChanged() { weekChanged() {
const scrollContainer = document.getElementsByClassName('vuecal__scrollable-body')[0] const scrollContainer = this.$el.getElementsByClassName('vuecal__scrollable-body')[0]
scrollContainer.scrollLeft = 0 scrollContainer.scrollLeft = 0
}, },
@@ -162,10 +169,12 @@ export default {
}, },
correctMargins() { correctMargins() {
if (!document.getElementsByClassName('vuecal__split-days-headers').length) return if (!this.$el.getElementsByClassName('vuecal__split-days-headers').length)
const heightOfDayHeader = document.getElementsByClassName('vuecal__split-days-headers')[0].clientHeight return
document.getElementsByClassName('vuecal__time-column')[0].style.marginTop = `${heightOfDayHeader}px`
document.getElementsByClassName('vuecal__cells-body')[0].style.marginTop = `${heightOfDayHeader}px` const heightOfDayHeader = this.$el.getElementsByClassName('vuecal__split-days-headers')[0].clientHeight
this.$el.getElementsByClassName('vuecal__time-column')[0].style.marginTop = `${heightOfDayHeader}px`
this.$el.getElementsByClassName('vuecal__cells-body')[0].style.marginTop = `${heightOfDayHeader}px`
}, },
getHeadingDate(value) { getHeadingDate(value) {
@@ -204,7 +213,7 @@ export default {
}, },
clickCompleteTask(event) { clickCompleteTask(event) {
if (event.completed) this.$emit('reopenTask', event.id) if (event.completed) this.completeTask(event.id)
else this.showCompleteModal = {task: event} else this.showCompleteModal = {task: event}
}, },
@@ -216,6 +225,10 @@ export default {
this.$refs['z-sub-task-modal'].create(subTask, editMode) this.$refs['z-sub-task-modal'].create(subTask, editMode)
}, },
addTimeModal() {
this.$refs['z-add-time-task-modal'].showModal()
},
deleteTask(id) { deleteTask(id) {
this.$emit('deleteTask', id) this.$emit('deleteTask', id)
} }
@@ -230,7 +243,7 @@ export default {
.calendar-wrapper .calendar-wrapper
width: 100% width: 100%
height: 100% height: 100%
// padding: 0 20px 0 0 // padding: 0 20px 0 0
&:deep() &:deep()
.vuecal__cells .vuecal__cells
@@ -296,6 +309,12 @@ export default {
font-size: 24px font-size: 24px
font-weight: 700 font-weight: 700
.day-name
text-align: left
font-size: 18px
font-weight: 500
text-transform: capitalize
.unscheduled-time .unscheduled-time
background: rgba(0, 0, 0, 0.04) background: rgba(0, 0, 0, 0.04)
border-radius: 24px border-radius: 24px
@@ -349,9 +368,8 @@ export default {
transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s transition: min-height .4s, height .4s, box-shadow .4s, width .4s, left .4s
&:has(.completed) &:has(.completed)
// filter: grayscale(.9) !important background: rgb(251, 251, 251) !important
// background: rgb(245, 245, 245) !important border: 1px solid #cccccc !important
// border: 1px solid rgb(224, 224, 224) !important
&:has(.non-working-event) &:has(.non-working-event)
background: repeating-linear-gradient(135deg, rgba(215, 215, 215, 1), rgba(215, 215, 215, 1) 1px, rgba(224, 224, 224, 1) 1px, rgba(224, 224, 224, 1) 20px) background: repeating-linear-gradient(135deg, rgba(215, 215, 215, 1), rgba(215, 215, 215, 1) 1px, rgba(224, 224, 224, 1) 1px, rgba(224, 224, 224, 1) 20px)
@@ -1,96 +1,112 @@
<template> <template>
<div id="calendar" class="mb-12"> <div id="calendar" class="mb-12">
<FullCalendar ref="fullCalendar" :options="calendarOptions"/> <V-full-calendar ref="fullCalendar" :options="calendarOptions" />
<Z-master-task-modal ref="z-master-task-modal" /> <Z-master-task-modal ref="z-master-task-modal" />
</div> </div>
</template> </template>
<script> <script>
import FullCalendar from '@fullcalendar/vue3' import VFullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid' import dayGridPlugin from '@fullcalendar/daygrid'
import ZMasterTaskModal from '@/plugins/tm@modal/master-task/z-master-task-modal.vue' import ZMasterTaskModal from '@/plugins/tm@modal/master-task/z-master-task-modal.vue'
export default { export default {
components: { components: {
FullCalendar, VFullCalendar,
ZMasterTaskModal ZMasterTaskModal
}, },
props: ['events', 'month'],
methods: { props: {
editTask(masterTask, editMode) { events: {
this.$refs['z-master-task-modal'].create(masterTask, editMode) required: true
} },
},
computed: { month: {
calendarOptions() { required: true
return { }
plugins: [ dayGridPlugin ], },
initialView: 'dayGridMonth',
headerToolbar: false, computed: {
locale: 'sk', calendarOptions() {
height: 650, return {
firstDay: 1, plugins: [dayGridPlugin],
dayHeaderClassNames: ['w-day-header'], initialView: 'dayGridMonth',
events: this.events, headerToolbar: false,
eventContent: function(eventInfo) { locale: 'sk',
return { html: eventInfo.event.extendedProps.title_html } height: 650,
}, firstDay: 1,
eventClick: (info) => { dayHeaderClassNames: ['w-day-header'],
console.log(info.event._def) events: this.events,
// alert(JSON.stringify(info.event._def)) eventContent: (eventInfo) => {
this.editTask(info.event._def.publicId, false) return { html: eventInfo.event.extendedProps.title_html }
} },
} eventClick: (info) => {
} return this.editTask(info.event._def.publicId, false)
}, }
watch: { }
month(selectedMonth) { }
const currentYear = (new Date()).getFullYear() },
this.$refs.fullCalendar?.getApi().gotoDate(new Date(currentYear, selectedMonth, 1))
} mounted() {
}, const currentYear = new Date().getFullYear()
mounted() { this.calendarOptions.events = this.events
const currentYear = (new Date()).getFullYear() this.$refs.fullCalendar?.getApi().gotoDate(new Date(currentYear, this.month, 1))
this.calendarOptions.events = this.events },
this.$refs.fullCalendar?.getApi().gotoDate(new Date(currentYear, this.month, 1))
} methods: {
editTask(masterTask, editMode) {
this.$refs['z-master-task-modal'].create(masterTask, editMode)
}
},
watch: {
month(selectedMonth) {
const currentYear = new Date().getFullYear()
this.$refs.fullCalendar?.getApi().gotoDate(new Date(currentYear, selectedMonth, 1))
}
},
} }
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
#calendar #calendar
&:deep(.w-day-header) &:deep(.w-day-header)
text-align: left text-align: left
padding-left: 10px padding-left: 10px
&:deep(.fc-daygrid-day-number) &:deep(.fc-daygrid-day-number)
color: black color: black
&:deep(.fc-col-header-cell-cushion) &:deep(.fc-col-header-cell-cushion)
font-size: 20px font-size: 20px
font-weight: 500 font-weight: 500
line-height: 45px line-height: 45px
text-transform: capitalize text-transform: capitalize
color: black color: black
&:deep(.fc-theme-standard .fc-scrollgrid) &:deep(.fc-theme-standard .fc-scrollgrid)
border: none border: none
&:deep(.fc-event-start) &:deep(.fc-event-start)
border-top-left-radius: 30px border-top-left-radius: 30px
border-bottom-left-radius: 30px border-bottom-left-radius: 30px
&:deep(.fc-event-end) &:deep(.fc-event-end)
border-top-right-radius: 30px border-top-right-radius: 30px
border-bottom-right-radius: 30px border-bottom-right-radius: 30px
&:deep(.fc-event) &:deep(.fc-event)
font-size: 12px font-size: 12px
padding-left: 10px padding-left: 10px
margin-top: 5px margin-top: 5px
&:after &:after
background: unset background: unset
&:deep(.fc-day-today) &:deep(.fc-day-today)
background: white background: white
a a
background: #3700B3 background: #3700B3
width: 32px width: 28px
height: 32px color: white
color: white text-align: center
text-align: center border-radius: 50%
border-radius: 50% height: 28px
border: 5px solid white line-height: 27px
line-height: 15px position: relative
</style> padding: 0
margin: 0
border: none
top: 2px
right: 4px
</style>
@@ -1,89 +1,64 @@
<template> <template>
<v-row class="px-10 py-8 subheader"> <v-row class="px-10 py-8 subheader">
<v-select <v-select v-model="filter.selectedProject" class="subheader-input" :items="projects" label="Projekt" variant="outlined"></v-select>
v-model="filter.selectedProject"
class="subheader-input"
:items="projects"
label="Projekt"
variant="outlined"
></v-select>
<v-select <v-select v-model="filter.selectedTeam" class="subheader-input" :items="teams" label="Tím" variant="outlined"></v-select>
v-model="filter.selectedTeam"
class="subheader-input"
:items="teams"
label="Tím"
variant="outlined"
></v-select>
<v-select <v-select v-model="filter.selectedEmployee" class="subheader-input" :items="employees" label="Zamestnanec" variant="outlined"></v-select>
v-model="filter.selectedEmployee"
class="subheader-input"
:items="employees"
label="Zamestnanec"
variant="outlined"
></v-select>
<v-select <v-select v-model="filter.selectedMonth" class="subheader-input" :items="months" label="Mesiac" variant="outlined"></v-select>
v-model="filter.selectedMonth"
class="subheader-input"
:items="months"
label="Mesiac"
variant="outlined"
></v-select>
<div class="subheader-input switch"> <div class="subheader-input switch">
<p class="switch-label">Zobraziť ukončené</p> <p class="switch-label">Zobraziť ukončené</p>
<v-switch <v-switch v-model="filter.showFinishedTasks" color="#6200EE" hide-details></v-switch>
v-model="filter.showFinishedTasks" </div>
color="#6200EE" </v-row>
hide-details
></v-switch>
</div>
</v-row>
</template> </template>
<script> <script>
export default { export default {
data() { emits: ['filterChanged'],
return {
months: [ props: ['projects', 'teams', 'employees'],
{ title: 'Január', value: 0 },
{ title: 'Február', value: 1 }, data() {
{ title: 'Marec', value: 2 }, return {
{ title: 'Apríl', value: 3 }, months: [
{ title: 'Máj', value: 4 }, { title: 'Január', value: 0 },
{ title: 'Jún', value: 5 }, { title: 'Február', value: 1 },
{ title: 'Júl', value: 6 }, { title: 'Marec', value: 2 },
{ title: 'August', value: 7 }, { title: 'Apríl', value: 3 },
{ title: 'September', value: 8 }, { title: 'Máj', value: 4 },
{ title: 'Október', value: 9 }, { title: 'Jún', value: 5 },
{ title: 'November', value: 10 }, { title: 'Júl', value: 6 },
{ title: 'December', value: 11 }, { title: 'August', value: 7 },
], { title: 'September', value: 8 },
filter: { { title: 'Október', value: 9 },
selectedProject: null, { title: 'November', value: 10 },
selectedTeam: null, { title: 'December', value: 11 }
selectedEmployee: null, ],
selectedMonth: (new Date()).getMonth(), filter: {
showFinishedTasks: false selectedProject: null,
} selectedTeam: null,
} selectedEmployee: null,
}, selectedMonth: new Date().getMonth(),
props: ['projects', 'teams', 'employees'], showFinishedTasks: false
emits: ['filterChanged'], }
watch: { }
filter: { },
handler() {
this.$emit('filterChanged', this.filter) watch: {
}, filter: {
deep: true handler() {
} this.$emit('filterChanged', this.filter)
} },
deep: true
}
}
} }
</script> </script>
<style lang="sass" scoped> <style lang="sass" scoped>
// TODO: zjednotit styly ikon v globalnom sass subore // Kravarik: TODO zjednotit styly ikon v globalnom sass subore
// TODO: ↓ // TODO: ↓
.subheader .subheader
max-width: 100% max-width: 100%
@@ -1,55 +1,60 @@
<template> <template>
<div> <div>
<a-project-filter :projects="projects" @filterChanged="onFilterChanged"></a-project-filter> <A-project-filter :projects="projects" @filterChanged="onFilterChanged" />
<a-project-calendar :events="filteredEvents" :month="filter.selectedMonth"></a-project-calendar> <A-project-calendar :events="filteredEvents" :month="filterSettings.selectedMonth" />
</div> </div>
</template> </template>
<script> <script>
import AProjectCalendar from './_components/a-project-calendar.vue' import AProjectCalendar from './_components/a-project-calendar.vue'
import AProjectFilter from './_components/a-project-filter.vue' import AProjectFilter from './_components/a-project-filter.vue'
export default { export default {
components: { components: {
AProjectCalendar, AProjectCalendar,
AProjectFilter AProjectFilter
}, },
data() { data() {
return { return {
filter: { filterSettings: {
selectedEmployee: null, selectedEmployee: null,
selectedMonth: (new Date()).getMonth(), selectedMonth: new Date().getMonth(),
selectedProject: null, selectedProject: null,
selectedTeam: null, selectedTeam: null,
showFinishedTasks: false showFinishedTasks: false
}, },
projects: ['Projekt1', 'Projekt2', 'Projekt3', 'Projekt4'], // Kravarik: Toto je preco hardcodenute?
selectedProject: null, projects: ['Projekt1', 'Projekt2', 'Projekt3', 'Projekt4'],
events: [], selectedProject: null,
filteredEvents: [] events: [],
} filteredEvents: []
}, }
async created() { },
const events = await this.$axios.get_auth_data('v1/overview/projects') async created() {
this.events = events.map(item => ({ try {
id: item.id, const events = await this.$axios.get_auth_data('v1/overview/projects')
title: `${item.project_code} - ${item.name}`, this.events = events.map((item) => ({
title_html: `${item.project_code} - <b>${item.name}</b>`, id: item.id,
start: item.starts_at, title: `${item.project_code} - ${item.name}`,
end: item.deadline, title_html: `${item.project_code} - <b>${item.name}</b>`,
is_finished: item.is_finished, start: item.starts_at,
project_code: item.project_code, end: item.deadline,
backgroundColor: item.color, is_finished: item.is_finished,
borderColor: item.color project_code: item.project_code,
})) backgroundColor: item.color,
this.filteredEvents = this.events.filter(item => !item.is_finished) borderColor: item.color
}, }))
methods: { this.filteredEvents = this.events.filter((item) => !item.is_finished)
// TODO: prepojit filtrovanie na BE } catch (error) {
onFilterChanged(filterValues) { this.$toast.error(error)
this.filter = filterValues }
this.filteredEvents = this.events.filter(item => this.filter.showFinishedTasks || item.is_finished == false) },
} methods: {
} // Kravarik: TODO prepojit filtrovanie na BE
onFilterChanged(filterValues) {
this.filter = filterValues
this.filteredEvents = this.events.filter((item) => this.filter.showFinishedTasks || item.is_finished == false)
}
}
} }
</script> </script>
@@ -3,12 +3,12 @@
<v-select <v-select
v-model="selectedEmployee" v-model="selectedEmployee"
class="subheader-input" class="subheader-input"
:items="employees" :items="employeesNames"
label="Zamestnanec" label="Zamestnanec"
variant="outlined" variant="outlined"
></v-select> ></v-select>
<div class="d-flex date-wrapper"> <div class="d-flex date-wrapper">
<v-btn class="subheader-icon-button prev" variant="outlined" @click="prevWeek()"><img :src="require('./_img/icon-prev.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button prev" variant="outlined" @click="prevWeek()"><img :src="require('@/plugins/tm@dashboard/_components/_img/icon-prev.svg')" alt=""></v-btn>
<v-text-field <v-text-field
class="subheader-input disabled" class="subheader-input disabled"
label="Dátum" label="Dátum"
@@ -16,7 +16,7 @@
variant="outlined" variant="outlined"
append-inner-icon="mdi-calendar-blank-outline" append-inner-icon="mdi-calendar-blank-outline"
></v-text-field> ></v-text-field>
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('./_img/icon-next.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('@/plugins/tm@dashboard/_components/_img/icon-next.svg')" alt=""></v-btn>
</div> </div>
<v-text-field <v-text-field
class="subheader-input disabled" class="subheader-input disabled"
@@ -33,49 +33,73 @@ import { addDays, subDays } from 'date-fns'
export default { export default {
props: { props: {
unscheduledTime: { unscheduledTime: {
type: Number, type: String,
default() { default() {
return 0 return '0'
} }
} }
}, },
data() { data() {
return { return {
employees: ['Foo', 'Bar', 'Fizz', 'Buzz'], employees: [],
selectedDate: "13.11.2022 - 17.11.2022", employeesNames: [],
selectedEmployee: 'Bar', selectedDate: "",
// Kaluza: Napojit funkcnost
selectedEmployee: '',
date: new Date() date: new Date()
} }
}, },
created() {
this.getWeek()
},
computed: { computed: {
time() { time() {
return this.unscheduledTime return this.unscheduledTime
} }
}, },
created() {
this._getData()
},
methods: { methods: {
getWeek() { async _getData() {
await this._getEmployees()
this._getWeek(false)
this.$nextTick(() => {
this.$emit('dataChanged', {firstDay: this.firstDay, employeeId: this.selectedEmployee})
})
},
async _getEmployees() {
this.employees = await this.$axios.get_auth_data('v1/employees')
this.employees.forEach(employee => {
this.employeesNames.push(`${employee.name} ${employee.surname} `)
})
},
_getWeek(emitDataChanged = true) {
this.firstDay = subDays(this.date, 1) this.firstDay = subDays(this.date, 1)
this.lastDay = addDays(this.date, 5) this.lastDay = addDays(this.date, 5)
this.$emit('weekChange', {firstDay: this.firstDay, lastDay: this.lastDay})
this.selectedDate = String(this.firstDay.toLocaleDateString('sk-SK') + ' - ' + this.lastDay.toLocaleDateString('sk-SK')) this.selectedDate = String(this.firstDay.toLocaleDateString('sk-SK') + ' - ' + this.lastDay.toLocaleDateString('sk-SK'))
if (emitDataChanged) this.$emit('dataChanged', {firstDay: this.firstDay, employeeId: this.selectedEmployee})
}, },
prevWeek() { prevWeek() {
this.date = subDays(this.date, 7) this.date = subDays(this.date, 7)
this.getWeek() this._getWeek()
}, },
nextWeek() { nextWeek() {
this.date = addDays(this.date, 7) this.date = addDays(this.date, 7)
this.getWeek() this._getWeek()
}
},
watch: {
selectedEmployee() {
this.$emit('dataChanged', {firstDay: this.firstDay, employeeId: this.selectedEmployee})
} }
} }
} }
+34 -57
View File
@@ -1,25 +1,16 @@
<template> <template>
<div> <div>
<A-task-filter :unscheduledTime="unscheduledTime" @weekChange="getWeekData" /> <A-task-filter :unscheduledTime="unscheduledTime" @dataChanged="getTimelineData" />
<W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!"> <W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!">
<Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @reopenTask="reopenTask" @deleteTask="deleteTask" /> <Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @deleteTask="deleteTask" />
</W-loadable> </W-loadable>
<v-snackbar
v-model="errorToast"
:timeout="2000"
color="red"
:rounded="true"
>
{{ errorToastMessage }}
</v-snackbar>
</div> </div>
</template> </template>
<script> <script>
import ATaskFilter from './_components/a-tasks-filter.vue' import ATaskFilter from './_components/a-tasks-filter.vue'
import ZTimeline from './_components/z-timeline.vue' import ZTimeline from '@/plugins/tm@dashboard/_components/z-timeline.vue'
import { addDays, setHours, setMinutes, setSeconds, differenceInCalendarDays } from 'date-fns' import { addDays, setHours, setMinutes, setSeconds, differenceInCalendarDays } from 'date-fns'
@@ -32,9 +23,6 @@ export default {
data() { data() {
return { return {
timelineData: null, timelineData: null,
errorToast: false,
errorToastMessage: "Nepodarilo sa nacitat data!",
dataLoaded: false,
splitDays: [], splitDays: [],
unscheduledTime: 0, unscheduledTime: 0,
config: { config: {
@@ -45,21 +33,22 @@ export default {
}, },
methods: { methods: {
async getWeekData(week) { async getTimelineData(data) {
this.config.date = week.firstDay this.config.date = data.firstDay
const lastDay = addDays(data.firstDay, 6)
try { try {
this.timelineData = await this.$axios.get_auth_data('v1/overview/tasks') this.timelineData = await this.$axios.get_auth_data('v1/overview/tasks', {firstDay: data.firstDay, lastDay: lastDay, employeeId: data.employeeId})
this.formatData(week.firstDay) this.formatTimelineDataToTimelineFormat(data.firstDay)
this.generateSplits(week.firstDay) this.generateDays(data.firstDay)
this.generateNonWorkingHours(week.firstDay) this.generateNonWorkingHours(data.firstDay)
} catch(error) { } catch (error) {
this.timelineData = {} this.timelineData = {error: error || 'Nepodarilo sa nacitat data!'}
console.error(error) console.error(error)
this.triggerToast("Nepodarilo sa nacitat data!") // console.log(this.$store.getters['auth/user'])
} }
}, },
generateSplits(date) { generateDays(date) {
this.splitDays = [] this.splitDays = []
for (let i = 0; i < 7; i++) { for (let i = 0; i < 7; i++) {
this.splitDays.push({ this.splitDays.push({
@@ -72,7 +61,7 @@ export default {
} }
}, },
formatData(date) { formatTimelineDataToTimelineFormat(date) {
// format events // format events
this.timelineData.tasks.forEach(event => { this.timelineData.tasks.forEach(event => {
event.name = this.timelineData.name event.name = this.timelineData.name
@@ -130,44 +119,32 @@ export default {
this.timelineData.tasks.push(...nonWorkingHours) this.timelineData.tasks.push(...nonWorkingHours)
}, },
triggerToast(message) {
this.errorToastMessage = message
this.errorToast = true
},
async onEventMoved(event) { async onEventMoved(event) {
console.log("drag", event) console.log("drag", event)
// try { const task = this.timelineData.tasks.find(task => task.id == event.event.id)
// const newStartDate = addDays(event.event.start, differenceInCalendarDays(this.splitDays.filter((split) => {return split.id == event.newSplit})[0].date, event.event.start))
// const newEndDate = addDays(event.event.end, differenceInCalendarDays( newStartDate, event.event.start)) try {
// await this.$axios.post_auth_data(`v1/overview/tasks/${event.event.id}`, {start: newStartDate, end: newEndDate}) const newStartDate = addDays(event.event.start, differenceInCalendarDays(this.splitDays.filter((split) => {return split.id == event.newSplit})[0].date, event.event.start))
// } catch(error) { const newEndDate = addDays(event.event.end, differenceInCalendarDays( newStartDate, event.event.start))
// this.triggerToast("Nepodarilo sa presunut ulohu!")
// this.timelineData.tasks.filter(e => { // await this.$axios.post_auth_data(`v1/overview/tasks/${event.event.id}`, {start: newStartDate, end: newEndDate})
// if (e.id == event.event.id) { task.start = newStartDate
// e.start = new Date(event.originalEvent.start) task.end = newEndDate
// e.end = new Date(event.originalEvent.end) task.split = event.newSplit
// } } catch(error) {
// }) this.$toast.error(error)
// }
task.start = new Date(event.originalEvent.start)
task.end = new Date(event.originalEvent.end)
task.split = event.oldSplit
}
}, },
completeTask(id) { completeTask(id) {
this.timelineData.tasks.filter(task => { const task = this.timelineData.tasks.find(task => task.id == id)
if (task.id == id) { task.completed = !task.completed
task.completed = true
}
})
}, },
reopenTask(id) {
this.timelineData.tasks.filter(task => {
if (task.id == id) {
task.completed = false
}
})
},
deleteTask(id) { deleteTask(id) {
this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1) this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1)
} }
@@ -1,14 +1,14 @@
<template> <template>
<v-row class="px-10 py-8 subheader"> <v-row class="px-10 py-8 subheader">
<v-select <v-select
v-model="selectedEmployee" v-model="selectedTeam"
class="subheader-input" class="subheader-input"
:items="employees" :items="teamsNames"
label="Tím" label="Tím"
variant="outlined" variant="outlined"
></v-select> ></v-select>
<div class="d-flex date-wrapper"> <div class="d-flex date-wrapper">
<v-btn class="subheader-icon-button prev" variant="outlined" @click="prevDay()"><img :src="require('../../tasks/_components/_img/icon-prev.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button prev" variant="outlined" @click="prevDay()"><img :src="require('@/plugins/tm@dashboard/_components/_img/icon-prev.svg')" alt=""></v-btn>
<v-text-field <v-text-field
class="subheader-input disabled" class="subheader-input disabled"
label="Dátum" label="Dátum"
@@ -16,7 +16,7 @@
variant="outlined" variant="outlined"
append-inner-icon="mdi-calendar-blank-outline" append-inner-icon="mdi-calendar-blank-outline"
></v-text-field> ></v-text-field>
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextDay()"><img :src="require('../../tasks/_components/_img/icon-next.svg')" alt=""></v-btn> <v-btn class="subheader-icon-button next" variant="outlined" @click="nextDay()"><img :src="require('@/plugins/tm@dashboard/_components/_img/icon-next.svg')" alt=""></v-btn>
</div> </div>
<v-text-field <v-text-field
class="subheader-input disabled" class="subheader-input disabled"
@@ -33,35 +33,54 @@ import { addDays, subDays } from 'date-fns'
export default { export default {
props: { props: {
unscheduledTime: { unscheduledTime: {
type: Number, type: String,
default() { default() {
return 0 return '0'
} }
} }
}, },
data() { data() {
return { return {
employees: ['Foo', 'Bar', 'Fizz', 'Buzz'], teams: [],
teamsNames: [],
// Kaluza: Napojit funkcionalitu
selectedTeam: '',
selectedDate: new Date(), selectedDate: new Date(),
day: new Date(), day: new Date(),
selectedEmployee: 'Bar',
date: new Date() date: new Date()
} }
}, },
created() {
this.getDay()
},
computed: { computed: {
time() { time() {
return this.unscheduledTime return this.unscheduledTime
} }
}, },
created() {
this._getData()
},
methods: { methods: {
getDay() { async _getData() {
await this._getTeams()
this._getDay(false)
this.$nextTick(() => {
this.$emit('dataChanged', {date: this.day, teamId: this.selectedTeam})
})
},
async _getTeams() {
this.teams = await this.$axios.get_auth_data('v1/teams')
this.teams.forEach(team => {
this.teamsNames.push(team.name)
})
},
_getDay(emitDataChanged = true) {
const today = new Date() const today = new Date()
const yesterday = new Date((new Date()).setDate(today.getDate() - 1)) const yesterday = new Date((new Date()).setDate(today.getDate() - 1))
const tomorrow = new Date((new Date()).setDate(today.getDate() + 1)) const tomorrow = new Date((new Date()).setDate(today.getDate() + 1))
@@ -71,17 +90,23 @@ export default {
else if (tomorrow.toLocaleDateString('sk-SK') === this.day.toLocaleDateString('sk-SK')) this.selectedDate = "Zajtra" else if (tomorrow.toLocaleDateString('sk-SK') === this.day.toLocaleDateString('sk-SK')) this.selectedDate = "Zajtra"
else this.selectedDate = String(this.day.toLocaleDateString('sk-SK')) else this.selectedDate = String(this.day.toLocaleDateString('sk-SK'))
this.$emit('dayChanged', this.day) if (emitDataChanged) this.$emit('dataChanged', {date: this.day, teamId: this.selectedTeam})
}, },
prevDay() { prevDay() {
this.day = subDays(this.day, 1) this.day = subDays(this.day, 1)
this.getDay() this._getDay()
}, },
nextDay() { nextDay() {
this.day = addDays(this.day, 1) this.day = addDays(this.day, 1)
this.getDay() this._getDay()
}
},
watch: {
selectedTeam() {
this.$emit('dataChanged', {date: this.day, teamId: this.selectedTeam})
} }
} }
} }
+29 -53
View File
@@ -1,25 +1,16 @@
<template> <template>
<div> <div>
<A-team-filter :unscheduledTime="unscheduledTime" @dayChanged="getDayData" /> <A-team-filter :unscheduledTime="unscheduledTime" @dataChanged="getTimelineData" />
<W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!"> <W-loadable :content="timelineData" class="w-loadable" empty-message="Nepodarilo sa nacitat data!">
<Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @reopenTask="reopenTask" @deleteTask="deleteTask" /> <Z-timeline :calData="timelineData" :calConfig="config" :splits="splitDays" @eventMoved="onEventMoved" @completeTask="completeTask" @deleteTask="deleteTask" />
</W-loadable> </W-loadable>
<v-snackbar
v-model="errorToast"
:timeout="2000"
color="red"
:rounded="true"
>
{{ errorToastMessage }}
</v-snackbar>
</div> </div>
</template> </template>
<script> <script>
import ATeamFilter from './_components/a-team-filter.vue' import ATeamFilter from './_components/a-team-filter.vue'
import ZTimeline from '../tasks/_components/z-timeline.vue' import ZTimeline from '@/plugins/tm@dashboard/_components/z-timeline.vue'
import { setHours, setMinutes, setSeconds } from 'date-fns' import { setHours, setMinutes, setSeconds } from 'date-fns'
@@ -46,26 +37,26 @@ export default {
}, },
methods: { methods: {
async getDayData(date) { async getTimelineData(data) {
this.config.date = date this.config.date = data.date
try { try {
this.timelineData = await this.$axios.get_auth_data('v1/overview/teams') this.timelineData = await this.$axios.get_auth_data('v1/overview/teams', {date: data.date, team: data.teamId})
this.generateSplits() this.generateEmployees()
this.formatData() this.formatTimelineDataToTimelineFormat()
this.generateNonWorkingHours(date) this.generateNonWorkingHours(data.date)
} catch(error) { } catch(error) {
this.timelineData = {} this.timelineData = {error: error || 'Nepodarilo sa nacitat data!'}
console.error(error) console.error(error)
this.triggerToast("Nepodarilo sa nacitat data!")
} }
}, },
generateSplits() { generateEmployees() {
this.splitDays = [] this.splitDays = []
for (let i = 0; i < this.timelineData.length; i++) { for (let i = 0; i < this.timelineData.length; i++) {
this.timelineData[i].splitId = i + 1 this.timelineData[i].splitId = i + 1
this.splitDays.push({ this.splitDays.push({
id: i + 1, id: i + 1,
employeeId: this.timelineData[i].id,
firstName: this.timelineData[i].name, firstName: this.timelineData[i].name,
name: this.timelineData[i].name + " " + this.timelineData[i].surname, name: this.timelineData[i].name + " " + this.timelineData[i].surname,
initials: this.timelineData[i].name.charAt(0).toUpperCase() + this.timelineData[i].surname.charAt(0).toUpperCase(), initials: this.timelineData[i].name.charAt(0).toUpperCase() + this.timelineData[i].surname.charAt(0).toUpperCase(),
@@ -74,7 +65,7 @@ export default {
} }
}, },
formatData() { formatTimelineDataToTimelineFormat() {
this.timelineData.tasks = [] this.timelineData.tasks = []
this.unscheduledTime = 0 this.unscheduledTime = 0
@@ -129,44 +120,29 @@ export default {
this.timelineData.tasks.push(...nonWorkingHours) this.timelineData.tasks.push(...nonWorkingHours)
}, },
triggerToast(message) {
this.errorToastMessage = message
this.errorToast = true
},
async onEventMoved(event) { async onEventMoved(event) {
console.log("drag", event) console.log("drag", event)
// try { const task = this.timelineData.tasks.find(task => task.id == event.event.id)
// const newStartDate = addDays(event.event.start, differenceInCalendarDays(this.splitDays.filter((split) => {return split.id == event.newSplit})[0].date, event.event.start)) const newEmployeeId = this.splitDays.find(split => split.id == event.newSplit).employeeId
// const newEndDate = addDays(event.event.end, differenceInCalendarDays( newStartDate, event.event.start))
// await this.$axios.post_auth_data(`v1/overview/tasks/${event.event.id}`, {start: newStartDate, end: newEndDate}) try {
// } catch(error) { // await this.$axios.post_auth_data(`v1/overview/tasks/${event.event.id}`, {start: newEmployeeId})
// this.triggerToast("Nepodarilo sa presunut ulohu!") task.split = event.newSplit
// this.timelineData.tasks.filter(e => { task.start = event.event.start
// if (e.id == event.event.id) { task.end = event.event.end
// e.start = new Date(event.originalEvent.start) } catch(error) {
// e.end = new Date(event.originalEvent.end) task.split = event.oldSplit
// } task.start = new Date(event.originalEvent.start)
// }) task.end = new Date(event.originalEvent.end)
// } this.$toast.error(error)
}
}, },
completeTask(id) { completeTask(id) {
this.timelineData.tasks.filter(task => { const task = this.timelineData.tasks.find(task => task.id == id)
if (task.id == id) { task.completed = !task.completed
task.completed = true
}
})
}, },
reopenTask(id) {
this.timelineData.tasks.filter(task => {
if (task.id == id) {
task.completed = false
}
})
},
deleteTask(id) { deleteTask(id) {
this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1) this.timelineData.tasks.splice(this.timelineData.tasks.findIndex(item => item.id === id), 1)
} }
@@ -142,7 +142,7 @@ export default {
async save() { async save() {
if (!(await this.v$.$validate())) if (!(await this.v$.$validate()))
return return
try { try {
if (this.blocker.id) if (this.blocker.id)
@@ -132,7 +132,7 @@
<div class="d-flex justify-start"> <div class="d-flex justify-start">
<img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" /> <img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask()"/> <img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask()"/>
</div> </div>
</div> </div>
<v-card-actions class="d-flex flex-column modal-content"> <v-card-actions class="d-flex flex-column modal-content">
@@ -191,7 +191,7 @@
<p class="task-badge px-4 py-2 rounded-pill flex-shrink-0">{{ masterTask.team }}</p> <p class="task-badge px-4 py-2 rounded-pill flex-shrink-0">{{ masterTask.team }}</p>
<div class="d-flex align-center flex-shrink-0 mx-3" v-for="(employee, index) in masterTask.employees" :key="employee.id"> <div class="d-flex align-center flex-shrink-0 mx-3" v-for="(employee, index) in masterTask.employees" :key="employee.id">
<p class="employee-selected-avatar d-flex justify-center align-center"> <p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee.name.charAt(0) + employee.surname.charAt(0) }} {{ employee.name.charAt(0) + employee.surname.charAt(0) }}
</p> </p>
<p class="ml-2" v-html="`${masterTask.employees[index].name} ${masterTask.employees[index].surname}`" /> <p class="ml-2" v-html="`${masterTask.employees[index].name} ${masterTask.employees[index].surname}`" />
</div> </div>
@@ -274,13 +274,13 @@
<td class="w-25">{{ masterTask.name }}</td> <td class="w-25">{{ masterTask.name }}</td>
<td class="d-flex align-center"> <td class="d-flex align-center">
<p class="employee-selected-avatar d-flex justify-center align-center"> <p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee.name.charAt(0) + employee.surname.charAt(0) }} {{ employee.name.charAt(0) + employee.surname.charAt(0) }}
</p> </p>
<p class="ml-2" v-html="`${masterTask.employees[index].name} ${masterTask.employees[index].surname}`" /> <p class="ml-2" v-html="`${masterTask.employees[index].name} ${masterTask.employees[index].surname}`" />
</td> </td>
<td class="task-action"> <td class="task-action">
<div class="d-flex justify-start"> <div class="d-flex justify-start">
<img class="pencil-icon" :src="require('@/plugins/tm@dashboard/tasks/_components/_img/checkmark.svg')" alt="checkmark-icon" :style="{opacity: 0.3}"> <img class="pencil-icon" :src="require('@/plugins/tm@dashboard/_components/_img/checkmark.svg')" alt="checkmark-icon" :style="{opacity: 0.3}">
<img class="pencil-icon ml-2" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}"> <img class="pencil-icon ml-2" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}">
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" :style="{opacity: 0.3}"> <img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" :style="{opacity: 0.3}">
</div> </div>
@@ -353,7 +353,7 @@ export default {
// this.masterTask = await this.$axios.get_auth_data(`v1/master-task/${this.masterTaksId}`) // this.masterTask = await this.$axios.get_auth_data(`v1/master-task/${this.masterTaksId}`)
// this.selectedTeam = `${this.masterTask.team.name} - ${this.masterTask.team.id}`) // this.selectedTeam = `${this.masterTask.team.name} - ${this.masterTask.team.id}`)
} catch (error) { } catch (error) {
console.log(error) this.$toast(error)
} }
}, },
@@ -404,7 +404,6 @@ export default {
async _load(masterTaskId) { async _load(masterTaskId) {
try { try {
this.masterTask = await this.$axios.get_auth_data(`v1/master-tasks/${masterTaskId}`) this.masterTask = await this.$axios.get_auth_data(`v1/master-tasks/${masterTaskId}`)
console.log(this.masterTask)
} catch (error) { } catch (error) {
this.$toast.error(error) this.$toast.error(error)
} }
@@ -433,7 +432,7 @@ export default {
} catch (error) { } catch (error) {
this.$toast.error(error) this.$toast.error(error)
} }
}, },
employeeSelected(selectedOption) { employeeSelected(selectedOption) {
const employee = this.employees.find((empl) => empl.id == selectedOption.key) const employee = this.employees.find((empl) => empl.id == selectedOption.key)
@@ -0,0 +1,70 @@
<template>
<v-dialog v-model="show" max-width="650">
<v-card>
<div class="d-flex justify-space-between align-center">
<h1>Prosím zadajte odpracovaný čas</h1>
<v-icon
@click.stop="close()"
icon="mdi-close"
size="large"
></v-icon>
</div>
<v-card-actions class="mt-10 d-flex justify-start align-center">
<v-text-field
class="modal-input"
label="Odpracovaný čas"
variant="solo"
type="number"
placeholder="h"
append-inner-icon="mdi-timer-outline"
></v-text-field>
</v-card-actions>
<v-btn class="z-btn mt-5">Potvrdiť</v-btn>
</v-card>
</v-dialog>
</template>
<script>
export default {
emits: ['close'],
data() {
return {
visible: false
}
},
methods: {
showModal() {
this.visible = true
},
close() {
this.visible = false
this.$emit('close', this.blocker)
this.blocker = null
},
},
computed: {
show: {
get() {
return this.visible
},
set(value) {
if (!value) this.$emit('close')
}
},
}
}
</script>
<style lang="sass" scoped>
.z-btn
height: 48px !important
h1
font-size: 34px
</style>
@@ -125,7 +125,7 @@
<div class="d-flex justify-start"> <div class="d-flex justify-start">
<img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" /> <img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask()"/> <img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask()"/>
</div> </div>
</div> </div>
<v-card-actions class="d-flex flex-column modal-content"> <v-card-actions class="d-flex flex-column modal-content">
@@ -201,7 +201,7 @@
<v-sheet class="ma-2 d-flex flex-wrap"> <v-sheet class="ma-2 d-flex flex-wrap">
<div class="d-flex align-center mb-2 me-2" v-for="(employee, index) in task.employees" :key="employee.id"> <div class="d-flex align-center mb-2 me-2" v-for="(employee, index) in task.employees" :key="employee.id">
<p class="employee-selected-avatar d-flex justify-center align-center"> <p class="employee-selected-avatar d-flex justify-center align-center">
{{ employee.name.charAt(0) + employee.surname.charAt(0) }} {{ employee.name.charAt(0) + employee.surname.charAt(0) }}
</p> </p>
<p class="ml-2" v-html="`${task.employees[index].name} ${task.employees[index].surname}`" /> <p class="ml-2" v-html="`${task.employees[index].name} ${task.employees[index].surname}`" />
</div> </div>
@@ -241,7 +241,7 @@
<v-col cols="7"> <v-col cols="7">
<v-sheet class="ma-2"> <v-sheet class="ma-2">
<v-text-field <v-text-field
v-model="task.nieco" v-model="task.spent_time"
class="modal-input" class="modal-input"
variant="solo" variant="solo"
type="number" type="number"
@@ -264,7 +264,7 @@
</v-col> </v-col>
<v-col cols="7"> <v-col cols="7">
<v-sheet class="ma-2"> <v-sheet class="ma-2">
<p>{{ task.remaining_time }} h</p> <p>{{ remaining_time }} h</p>
</v-sheet> </v-sheet>
</v-col> </v-col>
</v-row> </v-row>
@@ -345,7 +345,7 @@ export default {
this.masterTasks = await this.$axios.get_auth_data('v1/master-tasks') this.masterTasks = await this.$axios.get_auth_data('v1/master-tasks')
this.employees = await this.$axios.get_auth_data('v1/employees') this.employees = await this.$axios.get_auth_data('v1/employees')
} catch (error) { } catch (error) {
console.log(error) this.$toast(error)
} }
}, },
@@ -424,7 +424,7 @@ export default {
} catch (error) { } catch (error) {
this.$toast.error(error) this.$toast.error(error)
} }
}, },
employeeSelected(selectedOption) { employeeSelected(selectedOption) {
const employee = this.employees.find((empl) => empl.id == selectedOption.key) const employee = this.employees.find((empl) => empl.id == selectedOption.key)
@@ -474,13 +474,13 @@ export default {
formattedStartDate() { formattedStartDate() {
let startDate = moment(this.task.starts_at) let startDate = moment(this.task.starts_at)
let date = startDate.format('DD.MM.yyyy, HH:mm') let date = startDate.format('DD.MM.yyyy, HH:mm')
return date return date
}, },
formattedEndDate() { formattedEndDate() {
let endDate = moment(this.task.ends_at) let endDate = moment(this.task.ends_at)
let date = endDate.format('DD.MM.yyyy, HH:mm') let date = endDate.format('DD.MM.yyyy, HH:mm')
return date return date
} }
}, },
+14 -14
View File
@@ -104,20 +104,6 @@ export default {
}, },
methods: { methods: {
async create(team = null) {
if (team) {
this.team = team
await this._load()
} else {
this.team = {
name: '',
employees: []
}
}
this.visible = true
},
async save() { async save() {
if (!(await this.v$.$validate())) if (!(await this.v$.$validate()))
return return
@@ -134,6 +120,20 @@ export default {
} }
}, },
async create(team = null) {
if (team) {
this.team = team
await this._load()
} else {
this.team = {
name: '',
employees: []
}
}
this.visible = true
},
close() { close() {
this.visible = false this.visible = false
this.$emit('close', this.team) this.$emit('close', this.team)
@@ -33,7 +33,7 @@ export default {
try { try {
this.employees = await this.$axios.get_auth_data('v1/employees') this.employees = await this.$axios.get_auth_data('v1/employees')
} catch (error) { } catch (error) {
console.log(error) this.$toast(error)
} }
}, },
@@ -49,7 +49,7 @@ export default {
return `${employee.name} ${employee.surname}` return `${employee.name} ${employee.surname}`
}) })
return employees return employees
} }
} }
} }
@@ -21,6 +21,7 @@
<img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}"/> <img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}"/>
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="showDeleteModal = { task }" /> <img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="showDeleteModal = { task }" />
<!-- Kravarik: Aj tento modal prerob novym sposobom -->
<Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @close="showDeleteModal = null" /> <Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @close="showDeleteModal = null" />
</div> </div>
</td> </td>
@@ -1,18 +1,12 @@
<template> <template>
<div> <div>
<Z-tasks-search @queryChange="filterOngoingTasks" /> <Z-tasks-search @queryChange="onSearch" />
<W-loadable :content="ongoingTasks"> <W-loadable :content="filteredOngoingTasks" :emptyMessage="searchQuery.length ? 'Neboli nájdené žiadne úlohy' : 'Nenašli sa žiadne záznamy'">
<A-ongoing-table :tasks="filteredOngoingTasks" /> <A-ongoing-table :tasks="filteredOngoingTasks" />
<h6
v-if="filteredOngoingTasks && !filteredOngoingTasks.length"
class="px-4"
>
Aktuálnemu hľadaniu nevyhovujú žiadne prebiehajúce úlohy
</h6>
</W-loadable> </W-loadable>
</div> </div>
</template> </template>
@@ -28,29 +22,38 @@ export default {
data() { data() {
return { return {
ongoingTasks: null, searchQuery: '',
filteredOngoingTasks: [] ongoingTasks: null
}
},
computed: {
filteredOngoingTasks() {
if (!this.ongoingTasks)
return null
if (!this.searchQuery)
return this.ongoingTasks
return this.ongoingTasks.filter((task) => {
return this.filterParams(this.searchQuery, task.title) || this.filterParams(this.searchQuery, task.project_code)
})
} }
}, },
async created() { async created() {
try { try {
this.ongoingTasks = await this.$axios.get_auth_data('v1/overview/ongoing-tasks') this.ongoingTasks = await this.$axios.get_auth_data('v1/overview/ongoing-tasks')
this.filterOngoingTasks()
} catch (error) { } catch (error) {
this.ongoingTasks = error this.ongoingTasks = {error}
this.$toast.error(error)
} }
}, },
methods: { methods: {
filterOngoingTasks(searchQuery) { onSearch(searchQuery) {
if(!searchQuery) return this.filteredOngoingTasks = this.ongoingTasks this.searchQuery = searchQuery
this.filteredOngoingTasks = this.ongoingTasks.filter((task) => {
return this.filterParams(searchQuery, task.title) || this.filterParams(searchQuery, task.project_code)
})
}, },
filterParams(searchQuery, row) { filterParams(searchQuery, row) {
return row.toLowerCase().includes(searchQuery.toLowerCase()) return row.toLowerCase().includes(searchQuery.toLowerCase())
} }
@@ -19,6 +19,7 @@
<img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}"> <img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" :style="{opacity: 0.3}">
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="showDeleteModal = { task }"> <img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="showDeleteModal = { task }">
<!-- Kravarik: Aj tento modal prerob novym sposobom -->
<Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @close="showDeleteModal = null" /> <Z-delete-task-modal v-if="showDeleteModal" :visible="showDeleteModal ? true : false" :task="showDeleteModal.task" @close="showDeleteModal = null" />
</div> </div>
</td> </td>
@@ -1,9 +1,9 @@
<template> <template>
<div> <div>
<Z-tasks-search @queryChange="filterUnscheduledTasks" /> <Z-tasks-search @queryChange="onSearch" />
<W-loadable :content="unscheduledTasks"> <W-loadable :content="filteredUnscheduledTasks" :emptyMessage="searchQuery.length ? 'Neboli nájdené žiadne úlohy' : 'Nenašli sa žiadne záznamy'">
<A-unscheduled-table :tasks="filteredUnscheduledTasks" /> <A-unscheduled-table :tasks="filteredUnscheduledTasks" />
<h6 <h6
v-if="filteredUnscheduledTasks && !filteredUnscheduledTasks.length" v-if="filteredUnscheduledTasks && !filteredUnscheduledTasks.length"
@@ -28,29 +28,38 @@ export default {
data() { data() {
return { return {
unscheduledTasks: null, searchQuery: '',
filteredUnscheduledTasks: [] unscheduledTasks: null
}
},
computed: {
filteredUnscheduledTasks() {
if (!this.unscheduledTasks)
return null
if (!this.searchQuery)
return this.unscheduledTasks
return this.unscheduledTasks.filter((task) => {
return this.filterParams(this.searchQuery, task.title) || this.filterParams(this.searchQuery, task.project_code)
})
} }
}, },
async created() { async created() {
try { try {
this.unscheduledTasks = await this.$axios.get_auth_data('v1/overview/unscheduled-tasks') this.unscheduledTasks = await this.$axios.get_auth_data('v1/overview/unscheduled-tasks')
this.filterUnscheduledTasks()
} catch (error) { } catch (error) {
this.unscheduledTasks = error this.unscheduledTasks = {error}
this.$toast.error(error)
} }
}, },
methods: { methods: {
filterUnscheduledTasks(searchQuery) { onSearch(searchQuery) {
if(!searchQuery) return this.filteredUnscheduledTasks = this.unscheduledTasks this.searchQuery = searchQuery
this.filteredUnscheduledTasks = this.unscheduledTasks.filter((task) => { },
return this.filterParams(searchQuery, task.title) || this.filterParams(searchQuery, task.project_code)
})
},
filterParams(searchQuery, row) { filterParams(searchQuery, row) {
return row.toLowerCase().includes(searchQuery.toLowerCase()) return row.toLowerCase().includes(searchQuery.toLowerCase())
} }
@@ -22,6 +22,7 @@
</v-table> </v-table>
<Z-team-modal ref="z-team-modal" /> <Z-team-modal ref="z-team-modal" />
<!-- Kravarik: Aj tento modal prerob novym sposobom -->
<Z-delete-team-modal v-if="deleteModal" :visible="deleteModal ? true : false" :team="deleteModal.team" @close="(deleteModal = null)" /> <Z-delete-team-modal v-if="deleteModal" :visible="deleteModal ? true : false" :team="deleteModal.team" @close="(deleteModal = null)" />
</div> </div>
</template> </template>
+1 -2
View File
@@ -22,8 +22,7 @@ export default {
try { try {
this.teams = await this.$axios.get_auth_data('http://127.0.0.1:8000/api/v1/teams') this.teams = await this.$axios.get_auth_data('http://127.0.0.1:8000/api/v1/teams')
} catch (error) { } catch (error) {
this.teams = {error: error.data.error} this.teams = {error}
this.$toast.error(error.data.error)
} }
} }
} }
@@ -84,14 +84,6 @@ export default {
...mapGetters('auth', ['user']), ...mapGetters('auth', ['user']),
}, },
created() {
// TEMP
this.$store.dispatch('auth/login', {
email: 'xx@asdasd.asd',
password: 'sdfsdfsdf'
})
},
validations() { validations() {
return { return {
user: { user: {
@@ -108,9 +100,10 @@ export default {
if (!(await this.v$.$validate())) return if (!(await this.v$.$validate())) return
try { try {
await this.$store.dispatch('wAuth/updateUserInfo', this.user) await this.$store.dispatch('wAuth/updateUserInfo', this.user)
this.$toast.success('Profil bol úspešne zmenený') this.$toast.success('Profil bol úspešne zmenený')
} catch (error) { } catch (error) {
this.$toast.error(error.response.data.error) this.$toast.error(error)
} }
}, },
}, },
+14 -23
View File
@@ -4,18 +4,13 @@ import './refreshExpired'
export default { export default {
namespaced: true, namespaced: true,
state: { state: {
status: '', token: localStorage.getItem('wzo_vue_user_token') || '',
_token: localStorage.getItem('wzo_vue_user_token') || '',
user: JSON.parse(localStorage.getItem('wzo_vue_user_user') || '{}'), user: JSON.parse(localStorage.getItem('wzo_vue_user_user') || '{}'),
}, },
mutations: { mutations: {
auth_request(state: any) {
state.status = 'loading'
},
auth_success(state: any, data: any) { auth_success(state: any, data: any) {
state.status = 'success'
if (data.token) { if (data.token) {
state._token = data.token state.token = data.token
localStorage.setItem('wzo_vue_user_token', data.token) localStorage.setItem('wzo_vue_user_token', data.token)
} }
@@ -25,24 +20,21 @@ export default {
} }
}, },
auth_error(state: any) { auth_error(state: any) {
state.status = 'error' state.token = ''
state._token = ''
localStorage.removeItem('wzo_vue_user_token') localStorage.removeItem('wzo_vue_user_token')
localStorage.removeItem('wzo_vue_user_user') localStorage.removeItem('wzo_vue_user_user')
}, },
logout(state: any) { logout(state: any) {
state.status = '' state.token = ''
state._token = ''
state.user = null state.user = null
localStorage.removeItem('wzo_vue_user_token') localStorage.removeItem('wzo_vue_user_token')
localStorage.removeItem('wzo_vue_user_user') localStorage.removeItem('wzo_vue_user_user')
window.open(location.origin, "_self")
} }
}, },
actions: { actions: {
login({commit}: {commit: any}, credentials: any) { login({commit}: {commit: any}, credentials: any) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
commit('auth_request')
axios.post_data('v1/auth/login', credentials) axios.post_data('v1/auth/login', credentials)
.then((response: any) => { .then((response: any) => {
const token = response.token const token = response.token
@@ -81,6 +73,7 @@ export default {
}) })
}) })
}, },
// eslint-disable-next-line
logout({commit}: {commit: any}) { logout({commit}: {commit: any}) {
return new Promise((resolve) => { return new Promise((resolve) => {
axios.post_auth_data('v1/auth/invalidate') axios.post_auth_data('v1/auth/invalidate')
@@ -90,14 +83,16 @@ export default {
}) })
}) })
}, },
forgotPassword(credentials: any) { // eslint-disable-next-line
forgotPassword({commit}: {commit: any}, credentials: any) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios.post_auth_data('v1/auth/forgot', credentials) axios.post_auth_data('v1/auth/forgot', credentials)
.then(response => resolve(response)) .then(response => resolve(response))
.catch(error => reject(error)) .catch(error => reject(error))
}) })
}, },
resetPassword(credentials: any) { // eslint-disable-next-line
resetPassword({commit}: {commit: any}, credentials: any) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
axios.post_auth_data('v1/auth/reset', credentials) axios.post_auth_data('v1/auth/reset', credentials)
.then(response => resolve(response)) .then(response => resolve(response))
@@ -157,17 +152,13 @@ export default {
}, },
getters: { getters: {
isLoggedIn: (state: any) => { isLoggedIn: (state: any) => {
return !!state._token return !!state.token
}, },
// authStatus: (state: any) => {
// return state.status
// },
user: (state: any) => { user: (state: any) => {
return state.user return state.user
},
token: (state: any) => {
return state.token
} }
// token: (state: any) => {
// return state._token
// }
} }
} }