mirror of
https://bitbucket.org/studiotem/jandl-taskmanager-app.git
synced 2026-10-21 14:29:34 +00:00
Merge branch 'main' of bitbucket.org:studiotem/jandl-taskmanager-app
This commit is contained in:
commit
7dfc6db0d7
41 files changed
+198
-137
No files matched your search
@@ -1,4 +1,5 @@
|
|||||||
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
|
||||||
|
import store from '@/store'
|
||||||
|
|
||||||
const routes: Array<RouteRecordRaw> = [
|
const routes: Array<RouteRecordRaw> = [
|
||||||
{
|
{
|
||||||
@@ -16,17 +17,20 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: '/auth/login',
|
path: '/auth/login',
|
||||||
name: 'Login',
|
name: 'Login',
|
||||||
component: () => import('@/plugins/lib@auth/login/login.vue')
|
component: () => import('@/plugins/lib@auth/login/login.vue'),
|
||||||
|
meta: {requiresAuth: false}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth/forgot-password',
|
path: '/auth/forgot-password',
|
||||||
name: 'Forgot password',
|
name: 'Forgot password',
|
||||||
component: () => import('@/plugins/lib@auth/forgot-password/forgot-password.vue')
|
component: () => import('@/plugins/lib@auth/forgot-password/forgot-password.vue'),
|
||||||
|
meta: {requiresAuth: false}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth/reset-password',
|
path: '/auth/reset-password',
|
||||||
name: 'Reset password',
|
name: 'Reset password',
|
||||||
component: () => import('@/plugins/lib@auth/reset-password/reset-password.vue')
|
component: () => import('@/plugins/lib@auth/reset-password/reset-password.vue'),
|
||||||
|
meta: {requiresAuth: false}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
@@ -45,50 +49,50 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: '/app/dashboard/tasks',
|
path: '/app/dashboard/tasks',
|
||||||
name: 'Dashboard - Tasks',
|
name: 'Dashboard - Tasks',
|
||||||
meta: { title: 'Tasks' },
|
meta: { title: 'Tasks', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@dashboard/tasks/tasks.vue')
|
component: () => import('@/plugins/tm@dashboard/tasks/tasks.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/dashboard/teams',
|
path: '/app/dashboard/teams',
|
||||||
name: 'Dashboard - Teams',
|
name: 'Dashboard - Teams',
|
||||||
meta: { title: 'Teams Overview' },
|
meta: { title: 'Teams Overview', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@dashboard/teams/teams.vue')
|
component: () => import('@/plugins/tm@dashboard/teams/teams.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/dashboard/projects',
|
path: '/app/dashboard/projects',
|
||||||
name: 'Dashboard - Projects',
|
name: 'Dashboard - Projects',
|
||||||
meta: { title: 'Projects overview' },
|
meta: { title: 'Projects overview', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@dashboard/projects/projects.vue')
|
component: () => import('@/plugins/tm@dashboard/projects/projects.vue')
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '/app/overview/unscheduled',
|
path: '/app/overview/unscheduled',
|
||||||
name: 'Overview - Unscheduled tasks',
|
name: 'Overview - Unscheduled tasks',
|
||||||
meta: { title: 'Unscheduled tasks' },
|
meta: { title: 'Unscheduled tasks', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@overview/tasks-unscheduled/tasks-unscheduled.vue')
|
component: () => import('@/plugins/tm@overview/tasks-unscheduled/tasks-unscheduled.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/overview/ongoing',
|
path: '/app/overview/ongoing',
|
||||||
name: 'Overview - Ongoing tasks',
|
name: 'Overview - Ongoing tasks',
|
||||||
meta: { title: 'Ongoing tasks' },
|
meta: { title: 'Ongoing tasks', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@overview/tasks-ongoing/tasks-ongoing.vue')
|
component: () => import('@/plugins/tm@overview/tasks-ongoing/tasks-ongoing.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/overview/teams',
|
path: '/app/overview/teams',
|
||||||
name: 'Overview - Teams',
|
name: 'Overview - Teams',
|
||||||
meta: { title: 'Teams' },
|
meta: { title: 'Teams', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@overview/teams/teams.vue')
|
component: () => import('@/plugins/tm@overview/teams/teams.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/dashboard/user',
|
path: '/app/dashboard/user',
|
||||||
name: 'Dashboard - User',
|
name: 'Dashboard - User',
|
||||||
meta: { title: 'Profile' },
|
meta: { title: 'Profile', requiresAuth: true },
|
||||||
component: () => import('@/plugins/tm@profile/profile/my-profile.vue')
|
component: () => import('@/plugins/tm@profile/profile/my-profile.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/app/search',
|
path: '/app/search',
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
meta: { title: 'Search Results' },
|
meta: { title: 'Search Results', requiresAuth: true },
|
||||||
component: () => import('@/plugins/lib@search/search/search.vue')
|
component: () => import('@/plugins/lib@search/search/search.vue')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -98,7 +102,8 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
{
|
{
|
||||||
path: '/:catchAll(.*)',
|
path: '/:catchAll(.*)',
|
||||||
name: '404',
|
name: '404',
|
||||||
component: () => import('@/plugins/w@screen/404/404.vue')
|
component: () => import('@/plugins/w@screen/404/404.vue'),
|
||||||
|
meta: {requiresAuth: null}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -107,4 +112,22 @@ const router = createRouter({
|
|||||||
routes
|
routes
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.beforeEach((to, from, next) => {
|
||||||
|
const isLoggedIn = store.getters['auth/isLoggedIn']
|
||||||
|
|
||||||
|
if (to.meta.requiresAuth === true) {
|
||||||
|
if (isLoggedIn)
|
||||||
|
return next()
|
||||||
|
else
|
||||||
|
return next({name: 'Login'})
|
||||||
|
} else if (to.meta.requiresAuth === false) {
|
||||||
|
if (!isLoggedIn)
|
||||||
|
return next()
|
||||||
|
else
|
||||||
|
return next({name: 'Dashboard - Tasks'})
|
||||||
|
} else {
|
||||||
|
return next({name: 'Login'})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
File renamed without changes.
File renamed without changes.
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="ionicon" viewBox="0 0 512 512"><title>Eye</title><path d="M255.66 112c-77.94 0-157.89 45.11-220.83 135.33a16 16 0 00-.27 17.77C82.92 340.8 161.8 400 255.66 400c92.84 0 173.34-59.38 221.79-135.25a16.14 16.14 0 000-17.47C428.89 172.28 347.8 112 255.66 112z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="32"/><circle cx="256" cy="256" r="80" fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="32"/></svg>
|
||||||
|
After Width: | Height: | Size: 518 B |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -6,7 +6,7 @@
|
|||||||
<h1>{{ $route.meta.title }}</h1>
|
<h1>{{ $route.meta.title }}</h1>
|
||||||
|
|
||||||
<div class="d-flex justify-end align-center w-100 header-sm">
|
<div class="d-flex justify-end align-center w-100 header-sm">
|
||||||
<img class="search-icon" :src="require('@/plugins/app/_layout/app/_img/search-icon.svg')" alt="search-icon" />
|
<img class="search-icon" :src="require('@/plugins/app/_img/icons/search.svg')" alt="search-icon" />
|
||||||
<input class="search-input mx-2" v-model="search" type="text" placeholder="Search" @click="$router.push({name: 'Search'})" @keyup="$events.emit('onSearch', search)" />
|
<input class="search-input mx-2" v-model="search" type="text" placeholder="Search" @click="$router.push({name: 'Search'})" @keyup="$events.emit('onSearch', search)" />
|
||||||
|
|
||||||
<v-menu>
|
<v-menu>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<ion-content>
|
<ion-content>
|
||||||
<img
|
<img
|
||||||
class="py-5 px-5 cursor-pointer"
|
class="py-5 px-5 cursor-pointer"
|
||||||
:src="require('@/plugins/app/_layout/_img/jandl-logo.svg')"
|
:src="require('@/plugins/app/_img/jandl-logo.svg')"
|
||||||
alt="jandl-logo"
|
alt="jandl-logo"
|
||||||
@click="refreshPage()"
|
@click="refreshPage()"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<header class="login-header-border ">
|
<header class="login-header-border ">
|
||||||
<v-container>
|
<v-container>
|
||||||
<img :src="require('@/plugins/app/_layout/_img/jandl-logo.svg')" alt="jandl-logo">
|
<img :src="require('@/plugins/app/_img/jandl-logo.svg')" alt="jandl-logo">
|
||||||
</v-container>
|
</v-container>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -5,17 +5,24 @@
|
|||||||
margin-left: 12px
|
margin-left: 12px
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
max-height: 32px
|
||||||
|
max-width: 32px
|
||||||
.pencil-icon
|
.pencil-icon
|
||||||
padding: 10px
|
padding: 10px
|
||||||
background: rgba(0, 0, 0, 0.04)
|
background: rgba(0, 0, 0, 0.04)
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
cursor: pointer
|
cursor: pointer
|
||||||
|
max-height: 32px
|
||||||
|
max-width: 32px
|
||||||
|
|
||||||
.status-badge
|
.status-badge
|
||||||
background: #F2E7FE
|
background: #F2E7FE
|
||||||
color: #7F39FB
|
color: #7F39FB
|
||||||
width: fit-content
|
width: fit-content
|
||||||
|
|
||||||
|
.hover
|
||||||
|
cursor: pointer !important
|
||||||
|
|
||||||
.task-badge
|
.task-badge
|
||||||
background: rgba(0, 0, 0, 0.04)
|
background: rgba(0, 0, 0, 0.04)
|
||||||
width: fit-content
|
width: fit-content
|
||||||
|
|||||||
@@ -14,9 +14,9 @@
|
|||||||
</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/_components/_img/checkmark.svg')" alt="checkmark-icon">
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/checkmark.svg')" alt="checkmark-icon">
|
||||||
<img class="pencil-icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon">
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon">
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon">
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon">
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
<td>{{ team.name }}</td>
|
<td>{{ team.name }}</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@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editTeam(team)" />
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editTeam(team)" />
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTeam(team)" />
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="deleteTeam(team)" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import axios from '@/plugins/w@custom/axios/models/axios'
|
import axios from '@/plugins/w@custom/axios/models/axios'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
import ax from 'axios'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
|
|
||||||
@@ -25,10 +23,10 @@ export default {
|
|||||||
state.employees = employees
|
state.employees = employees
|
||||||
|
|
||||||
// TODO: Remove
|
// TODO: Remove
|
||||||
const employee = employees.find(employee => employee.email == 'zachariah.vonrueden@jandl.sk')
|
// const employee = employees.find(employee => employee.email == 'zachariah.vonrueden@jandl.sk')
|
||||||
store.commit('auth/auth_success', {
|
// store.commit('auth/auth_success', {
|
||||||
user: employee
|
// user: employee
|
||||||
})
|
// })
|
||||||
},
|
},
|
||||||
|
|
||||||
set_teams(state: any, teams: any) {
|
set_teams(state: any, teams: any) {
|
||||||
@@ -67,6 +65,7 @@ export default {
|
|||||||
update_subtask(state: any, subtask: any) {
|
update_subtask(state: any, subtask: any) {
|
||||||
state.unscheduledSubtasks = state.unscheduledSubtasks.map(st => st.id == subtask.id ? subtask : st)
|
state.unscheduledSubtasks = state.unscheduledSubtasks.map(st => st.id == subtask.id ? subtask : st)
|
||||||
state.ongoingSubtasks = state.ongoingSubtasks.map(st => st.id == subtask.id ? subtask : st)
|
state.ongoingSubtasks = state.ongoingSubtasks.map(st => st.id == subtask.id ? subtask : st)
|
||||||
|
|
||||||
state.mastertasks = state.mastertasks.map(mastertask => {
|
state.mastertasks = state.mastertasks.map(mastertask => {
|
||||||
mastertask.subtasks = mastertask.subtasks.map(st => st.id == subtask.id ? subtask : st)
|
mastertask.subtasks = mastertask.subtasks.map(st => st.id == subtask.id ? subtask : st)
|
||||||
return mastertask
|
return mastertask
|
||||||
@@ -76,6 +75,7 @@ export default {
|
|||||||
delete_subtask(state: any, subtask: any) {
|
delete_subtask(state: any, subtask: any) {
|
||||||
state.unscheduledSubtasks = state.unscheduledSubtasks.filter(st => st.id != subtask.id)
|
state.unscheduledSubtasks = state.unscheduledSubtasks.filter(st => st.id != subtask.id)
|
||||||
state.ongoingSubtasks = state.ongoingSubtasks.filter(st => st.id != subtask.id)
|
state.ongoingSubtasks = state.ongoingSubtasks.filter(st => st.id != subtask.id)
|
||||||
|
|
||||||
state.mastertasks = state.mastertasks.map(mastertask => {
|
state.mastertasks = state.mastertasks.map(mastertask => {
|
||||||
mastertask.subtasks = mastertask.subtasks.filter(st => st.id != subtask.id)
|
mastertask.subtasks = mastertask.subtasks.filter(st => st.id != subtask.id)
|
||||||
return mastertask
|
return mastertask
|
||||||
|
|||||||
@@ -26,11 +26,11 @@
|
|||||||
<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">
|
||||||
<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('@/plugins/app/_img/icons/home.svg')" class="mr-2">
|
||||||
<p class="weekday-label">{{ getHeadingDate(split.date) }}</p>
|
<p class="weekday-label">{{ getHeadingDate(split.date) }}</p>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="d-flex align-center">
|
<span v-else class="d-flex align-center">
|
||||||
<p class="weekday-label">{{ split.firstName }}</p>
|
<p class="weekday-label">{{ split.name }}</p>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span v-if="split.date">
|
<span v-if="split.date">
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<p>{{ split.initials }}</p>
|
<p>{{ split.initials }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="mb-0 mt-0 unscheduled-time-name">{{split.name}}</p>
|
<p class="mb-0 mt-0 unscheduled-time-name">{{split.fullname}}</p>
|
||||||
<h1 class="mb-0 mt-0">{{split.unscheduledTime}} h</h1>
|
<h1 class="mb-0 mt-0">{{split.unscheduledTime}} h</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -58,26 +58,26 @@
|
|||||||
|
|
||||||
<template v-slot:event="{ event }">
|
<template v-slot:event="{ event }">
|
||||||
<!-- <div v-if="!event.nonWorking" @click.stop="editTask(event.id)" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}"> -->
|
<!-- <div v-if="!event.nonWorking" @click.stop="editTask(event.id)" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}"> -->
|
||||||
<div v-if="!event.nonWorking" class="w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}">
|
<div v-if="!event.nonWorking" class="custom-event-body w-100 h-100 d-flex flex-column justify-space-between" :class="{'short-event' : getEventLenght(event) <= 9000000, 'mini-event' : getEventLenght(event) <= 5400000, 'micro-event' : getEventLenght(event) <= 3600000}" :style="{backgroundColor: event.subtask.color}">
|
||||||
<div class="event-content">
|
<div class="event-content">
|
||||||
<small v-if="(event.subtask.project_code && !event.is_blocker)" class="project-code">{{ event.subtask.project_code }}</small>
|
<small v-if="(event.subtask.project_code && !event.is_blocker)" class="project-code">{{ event.subtask.project_code }}</small>
|
||||||
<h3>{{ event.subtask.master_task?.name || event.subtask.master_task }}</h3>
|
<h3>{{ event.subtask.master_task?.name || event.subtask.master_task }}</h3>
|
||||||
<div class="d-flex align-center event-details event-initials-wrapper">
|
<div class="d-flex align-center event-details event-initials-wrapper">
|
||||||
<div class="event-initials d-flex justify-center align-center">
|
<div class="event-initials d-flex justify-center align-center">
|
||||||
<small>{{ getUserInitials(event) }}</small>
|
<small>{{ event.initials }}</small>
|
||||||
</div>
|
</div>
|
||||||
<small class="event-initials-date">{{ event.start.toLocaleDateString('sk-SK') }}</small>
|
<small class="event-initials-date">{{ event.start.toLocaleDateString('sk-SK') }}</small>
|
||||||
</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.subtask.is_finished}" @click.stop="completeTask(event)"><img :src="require('./_img/checkmark.svg')" alt=""></v-btn>
|
<v-btn rounded class="event-footer-button me-2" :class="{'completed': event.subtask.is_finished}" @click.stop="completeTask(event)"><img :src="require('@/plugins/app/_img/icons/checkmark.svg')" alt=""></v-btn>
|
||||||
<v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event, true)"><img :src="require('./_img/pencil.svg')" alt=""></v-btn>
|
<v-btn rounded class="event-footer-button me-2" @click.stop="editTask(event)"><img :src="require('@/plugins/app/_img/icons/eye.svg')" alt=""></v-btn>
|
||||||
<v-btn rounded class="event-footer-button me-2" @click.stop="deleteTask(event)"><img :src="require('./_img/bin.svg')" alt=""></v-btn>
|
<v-btn rounded class="event-footer-button me-2" @click.stop="deleteTask(event)"><img :src="require('@/plugins/app/_img/icons/bin.svg')" alt=""></v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else class="non-working-event w-100 h-100 d-flex flex-column justify-center">
|
<div v-else class="custom-event-body non-working-event w-100 h-100 d-flex flex-column justify-center">
|
||||||
<div class="d-flex justify-center align-center">
|
<div class="d-flex justify-center align-center">
|
||||||
<v-icon icon="mdi-cancel" color="black"></v-icon>
|
<v-icon icon="mdi-cancel" color="black"></v-icon>
|
||||||
<h3 class="mb-0 ms-2">{{ event.title }}</h3>
|
<h3 class="mb-0 ms-2">{{ event.title }}</h3>
|
||||||
@@ -189,10 +189,6 @@ export default {
|
|||||||
return date.toLocaleDateString('sk-SK')
|
return date.toLocaleDateString('sk-SK')
|
||||||
},
|
},
|
||||||
|
|
||||||
getUserInitials(event) {
|
|
||||||
return event.name.charAt(0).toUpperCase() + event.surname.charAt(0).toUpperCase()
|
|
||||||
},
|
|
||||||
|
|
||||||
getEventLenght(event) {
|
getEventLenght(event) {
|
||||||
return event.end.getTime() - event.start.getTime()
|
return event.end.getTime() - event.start.getTime()
|
||||||
},
|
},
|
||||||
@@ -356,12 +352,15 @@ export default {
|
|||||||
|
|
||||||
.vuecal__event
|
.vuecal__event
|
||||||
border-radius: 16px
|
border-radius: 16px
|
||||||
padding: 20px 10px
|
// padding: 20px 10px
|
||||||
text-align: left
|
text-align: left
|
||||||
background: rgba(248, 248, 248, 1)
|
background: rgba(248, 248, 248, 1)
|
||||||
min-height: 40px
|
min-height: 40px
|
||||||
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
|
||||||
|
|
||||||
|
.custom-event-body
|
||||||
|
padding: 20px 10px
|
||||||
|
|
||||||
&:has(.completed)
|
&:has(.completed)
|
||||||
background: rgb(251, 251, 251) !important
|
background: rgb(251, 251, 251) !important
|
||||||
border: 1px solid #cccccc !important
|
border: 1px solid #cccccc !important
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
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('@/plugins/tm@dashboard/_components/_img/icon-prev.svg')" alt=""></v-btn>
|
<v-btn class="subheader-icon-button prev" variant="outlined" @click="prevWeek()"><img :src="require('@/plugins/app/_img/icons/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"
|
||||||
@@ -18,7 +18,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('@/plugins/tm@dashboard/_components/_img/icon-next.svg')" alt=""></v-btn>
|
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextWeek()"><img :src="require('@/plugins/app/_img/icons/icon-next.svg')" alt=""></v-btn>
|
||||||
</div>
|
</div>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
class="subheader-input disabled"
|
class="subheader-input disabled"
|
||||||
|
|||||||
@@ -40,8 +40,6 @@ export default {
|
|||||||
start: addDays(new Date(timeblock.start), diffInDays),
|
start: addDays(new Date(timeblock.start), diffInDays),
|
||||||
end: addDays(new Date(timeblock.end), diffInDays),
|
end: addDays(new Date(timeblock.end), diffInDays),
|
||||||
master_task: subtask.master_task,
|
master_task: subtask.master_task,
|
||||||
name: employee.name,
|
|
||||||
surname: employee.surname,
|
|
||||||
date: new Date(timeblock.start),
|
date: new Date(timeblock.start),
|
||||||
isWeekend: this.isWeekend(timeblock.start),
|
isWeekend: this.isWeekend(timeblock.start),
|
||||||
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
|
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
|
||||||
@@ -80,5 +78,11 @@ export default {
|
|||||||
|
|
||||||
_getSplitFromDate(date, start) {
|
_getSplitFromDate(date, start) {
|
||||||
return differenceInCalendarDays(new Date(date), new Date(start)) * (-1) + 1
|
return differenceInCalendarDays(new Date(date), new Date(start)) * (-1) + 1
|
||||||
|
},
|
||||||
|
|
||||||
|
_getDifferenceInHours(date1, date2) {
|
||||||
|
let diff =(date1.getTime() - date2.getTime()) / 1000;
|
||||||
|
diff /= (60 * 60)
|
||||||
|
return Math.abs(Math.round(diff))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ import { addDays, subDays } from 'date-fns'
|
|||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import timelineUtils from './_utils/timeline.utils'
|
import timelineUtils from './_utils/timeline.utils'
|
||||||
|
import tmUtils from '@/plugins/tm@_utils/tm.utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -33,13 +34,24 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
splitDays() {
|
splitDays() {
|
||||||
const days = []
|
const days = []
|
||||||
|
const workingHours = {}
|
||||||
|
|
||||||
|
this.timelineData.tasks.forEach(task => {
|
||||||
|
if (!workingHours[task.split])
|
||||||
|
workingHours[task.split] = 0
|
||||||
|
|
||||||
|
if (task.nonWorking || task.subtask.is_finished)
|
||||||
|
return
|
||||||
|
|
||||||
|
workingHours[task.split] += timelineUtils._getDifferenceInHours(task.end, task.start)
|
||||||
|
})
|
||||||
|
|
||||||
for (let i = 0; i < 7; i++) {
|
for (let i = 0; i < 7; i++) {
|
||||||
days.push({
|
days.push({
|
||||||
id: i + 1,
|
id: i + 1,
|
||||||
name: this.filter.employee.name + " " + this.filter.employee.surname,
|
fullname: `${this.filter.employee.name} ${this.filter.employee.surname}`,
|
||||||
initials: this.filter.employee.name.charAt(0).toUpperCase() + this.filter.employee.surname.charAt(0).toUpperCase(),
|
initials: this.filter.employee.name.charAt(0).toUpperCase() + this.filter.employee.surname.charAt(0).toUpperCase(),
|
||||||
unscheduledTime: this.timelineData.unscheduledTime,
|
unscheduledTime: workingHours[i + 1],
|
||||||
date: addDays(this.filter.start, i),
|
date: addDays(this.filter.start, i),
|
||||||
isWeekend: timelineUtils.isWeekend(addDays(this.filter.start, i))
|
isWeekend: timelineUtils.isWeekend(addDays(this.filter.start, i))
|
||||||
})
|
})
|
||||||
@@ -95,6 +107,7 @@ export default {
|
|||||||
try {
|
try {
|
||||||
const { subtasks } = await this.$axios.get_auth(`v1/subtasks?${queryParameters}`)
|
const { subtasks } = await this.$axios.get_auth(`v1/subtasks?${queryParameters}`)
|
||||||
this.config.scrollHour = this.filter.employee.work_start - 1
|
this.config.scrollHour = this.filter.employee.work_start - 1
|
||||||
|
this.config.date = this.filter.start
|
||||||
this.subtasks = subtasks
|
this.subtasks = subtasks
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$toast.error('Nepodarilo sa nacitat data!')
|
this.$toast.error('Nepodarilo sa nacitat data!')
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
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('@/plugins/tm@dashboard/_components/_img/icon-prev.svg')" alt=""></v-btn>
|
<v-btn class="subheader-icon-button prev" variant="outlined" @click="prevDay()"><img :src="require('@/plugins/app/_img/icons/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"
|
||||||
@@ -18,13 +18,14 @@
|
|||||||
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('@/plugins/tm@dashboard/_components/_img/icon-next.svg')" alt=""></v-btn>
|
<v-btn class="subheader-icon-button next" variant="outlined" @click="nextDay()"><img :src="require('@/plugins/app/_img/icons/icon-next.svg')" alt=""></v-btn>
|
||||||
</div>
|
</div>
|
||||||
<v-text-field
|
<v-text-field
|
||||||
class="subheader-input disabled"
|
class="subheader-input disabled"
|
||||||
label="Nenaplánované hodiny"
|
label="Nenaplánované hodiny"
|
||||||
v-model="time"
|
v-model="time"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
|
:disabled="true"
|
||||||
></v-text-field>
|
></v-text-field>
|
||||||
</v-row>
|
</v-row>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -10,8 +10,9 @@
|
|||||||
import ATeamFilter from './_components/a-team-filter.vue'
|
import ATeamFilter from './_components/a-team-filter.vue'
|
||||||
import ZTimeline from '@/plugins/tm@dashboard/_components/z-timeline.vue'
|
import ZTimeline from '@/plugins/tm@dashboard/_components/z-timeline.vue'
|
||||||
|
|
||||||
import { setHours, setMinutes } from 'date-fns'
|
import { setHours, setMinutes, addDays } from 'date-fns'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
import timelineUtils from '../tasks/_utils/timeline.utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -35,30 +36,36 @@ export default {
|
|||||||
const days = []
|
const days = []
|
||||||
|
|
||||||
this.filter.team.employees.forEach((employee, index) => {
|
this.filter.team.employees.forEach((employee, index) => {
|
||||||
|
let workingHours = 0
|
||||||
|
|
||||||
|
this.timelineData.tasks.forEach(task => {
|
||||||
|
if (task?.subtask?.employee_id == employee.id)
|
||||||
|
workingHours += timelineUtils._getDifferenceInHours(task.end, task.start)
|
||||||
|
})
|
||||||
|
|
||||||
days.push({
|
days.push({
|
||||||
id: index,
|
id: index + 1,
|
||||||
name: `${employee.name} ${employee.surname}`,
|
name: employee.name,
|
||||||
|
fullname: `${employee.name} ${employee.surname}`,
|
||||||
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
|
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
|
||||||
unscheduledTime: 111
|
unscheduledTime: workingHours
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
return days
|
return days
|
||||||
},
|
},
|
||||||
|
|
||||||
unscheduledTime() {
|
|
||||||
return 222
|
|
||||||
// if (!this.subtasks) return 0
|
|
||||||
|
|
||||||
// return timelineUtils.getUnscheduledTime(this.subtasks)
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
timelineData() {
|
timelineData() {
|
||||||
if (!this.subtasks)
|
if (!this.subtasks)
|
||||||
return
|
return
|
||||||
|
|
||||||
console.log([...this._generateNonWorking(), ...this._generateTasks()])
|
// let unscheduledTime = 0
|
||||||
|
// const tasks = [...this._generateNonWorking(), ...this._generateTasks()]
|
||||||
|
|
||||||
|
// tasks.forEach(task => {
|
||||||
|
// if (!task.nonWorking)
|
||||||
|
// workingHours += timelineUtils._getDifferenceInHours(task.end, task.start)
|
||||||
|
// })
|
||||||
|
|
||||||
return {
|
return {
|
||||||
unscheduledTime: 333,
|
unscheduledTime: 333,
|
||||||
@@ -79,7 +86,7 @@ export default {
|
|||||||
|
|
||||||
this.filter.team.employees.forEach((e, index) => {
|
this.filter.team.employees.forEach((e, index) => {
|
||||||
if (e.id == subtask.employee_id) {
|
if (e.id == subtask.employee_id) {
|
||||||
split = index
|
split = index + 1
|
||||||
employee = e
|
employee = e
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -93,11 +100,11 @@ export default {
|
|||||||
start: new Date(timeblock.start),
|
start: new Date(timeblock.start),
|
||||||
end: new Date(timeblock.end),
|
end: new Date(timeblock.end),
|
||||||
master_task: subtask.master_task,
|
master_task: subtask.master_task,
|
||||||
name: employee.name,
|
name: employee?.name,
|
||||||
surname: employee.surname,
|
surname: employee?.surname,
|
||||||
// date: new Date(timeblock.start),
|
// date: new Date(timeblock.start),
|
||||||
isWeekend: moment(timeblock.start).day() % 6 == 0,
|
isWeekend: moment(timeblock.start).day() % 6 == 0,
|
||||||
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
|
initials: employee?.name?.charAt(0)?.toUpperCase() + employee?.surname?.charAt(0)?.toUpperCase(),
|
||||||
split: split,
|
split: split,
|
||||||
project_code: subtask.project_code,
|
project_code: subtask.project_code,
|
||||||
subtask: subtask,
|
subtask: subtask,
|
||||||
@@ -112,8 +119,9 @@ export default {
|
|||||||
|
|
||||||
_generateNonWorking() {
|
_generateNonWorking() {
|
||||||
const tasks = []
|
const tasks = []
|
||||||
let earliestStartHour = null
|
|
||||||
const date = new Date(this.filter.start)
|
const date = new Date(this.filter.start)
|
||||||
|
let earliestStartHour = null
|
||||||
|
this.config.date = date
|
||||||
|
|
||||||
this.filter.team.employees.forEach((employee, index) => {
|
this.filter.team.employees.forEach((employee, index) => {
|
||||||
if (!earliestStartHour || employee.work_start < earliestStartHour)
|
if (!earliestStartHour || employee.work_start < earliestStartHour)
|
||||||
@@ -123,7 +131,7 @@ export default {
|
|||||||
title: "Non working hours",
|
title: "Non working hours",
|
||||||
start: setMinutes(setHours(date, 0), 0),
|
start: setMinutes(setHours(date, 0), 0),
|
||||||
end: setMinutes(setHours(date, employee.work_start), 0),
|
end: setMinutes(setHours(date, employee.work_start), 0),
|
||||||
split: index,
|
split: index + 1,
|
||||||
nonWorking: true,
|
nonWorking: true,
|
||||||
draggable: false
|
draggable: false
|
||||||
})
|
})
|
||||||
@@ -132,7 +140,7 @@ export default {
|
|||||||
title: "Non working hours",
|
title: "Non working hours",
|
||||||
start: setMinutes(setHours(date, employee.work_end), 0),
|
start: setMinutes(setHours(date, employee.work_end), 0),
|
||||||
end: setMinutes(setHours(date, 23), 59),
|
end: setMinutes(setHours(date, 23), 59),
|
||||||
split: index,
|
split: index + 1,
|
||||||
nonWorking: true,
|
nonWorking: true,
|
||||||
draggable: false
|
draggable: false
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -15,10 +15,10 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="task-action">
|
<td class="task-action">
|
||||||
<div class="d-flex justify-start">
|
<div class="d-flex justify-start">
|
||||||
<img v-if="task.is_finished" class="pencil-icon is-finished" :src="require('@/plugins/tm@dashboard/_components/_img/checkmark.svg')" alt="checkmark-icon" @click.stop="clickCompleteTask(task)">
|
<img v-if="task.is_finished" class="pencil-icon is-finished" :src="require('@/plugins/app/_img/icons/checkmark.svg')" alt="checkmark-icon" @click.stop="clickCompleteTask(task)">
|
||||||
<img v-if="!task.is_finished" class="pencil-icon" :src="require('@/plugins/tm@dashboard/_components/_img/checkmark.svg')" alt="checkmark-icon" @click.stop="clickCompleteTask(task)">
|
<img v-if="!task.is_finished" class="pencil-icon" :src="require('@/plugins/app/_img/icons/checkmark.svg')" alt="checkmark-icon" @click.stop="clickCompleteTask(task)">
|
||||||
<img class="pencil-icon ml-2" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="openEditTaskModal(task)">
|
<img class="pencil-icon ml-2" :src="require('@/plugins/app/_img/icons/eye.svg')" alt="pencil-icon" @click.stop="openTaskModal(task)">
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="openDeleteTaskModal(task)">
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="openDeleteTaskModal(task)">
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -59,26 +59,12 @@ export default {
|
|||||||
this.$events.emit('show-delete-task-modal', { task })
|
this.$events.emit('show-delete-task-modal', { task })
|
||||||
},
|
},
|
||||||
|
|
||||||
openEditTaskModal(task) {
|
openTaskModal(task) {
|
||||||
this.$events.emit('show-task-modal', { task, editMode: false })
|
this.$events.emit('show-task-modal', { task, editMode: false })
|
||||||
},
|
},
|
||||||
|
|
||||||
async clickCompleteTask(task) {
|
async clickCompleteTask(subtask) {
|
||||||
if (!task.is_finished) {
|
this.$events.emit('show-complete-task-modal', { subtask })
|
||||||
this.openCompleteTaskModal(task)
|
|
||||||
} else {
|
|
||||||
task.is_finished = !task.is_finished
|
|
||||||
try {
|
|
||||||
await this.$axios.patch_auth(`v1/subtasks/${task.id}`, task)
|
|
||||||
this.$emit('reopenTask', task)
|
|
||||||
} catch (error) {
|
|
||||||
this.$toast.error(error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
openCompleteTaskModal(task) {
|
|
||||||
this.$events.emit('show-complete-task-modal', { task })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default {
|
|||||||
|
|
||||||
async deleteMasterTask() {
|
async deleteMasterTask() {
|
||||||
try {
|
try {
|
||||||
await this.$axios.delete(`v1/mastertasks/${this.masterTask.id}`)
|
await this.$axios.delete_auth(`v1/mastertasks/${this.masterTask.id}`)
|
||||||
this.$emit('on-master-task-deleted', this.masterTask)
|
this.$emit('on-master-task-deleted', this.masterTask)
|
||||||
this.closeModal()
|
this.closeModal()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -48,8 +48,8 @@
|
|||||||
<div class="d-flex justify-space-between align-center modal-header border-bottom pb-4">
|
<div class="d-flex justify-space-between align-center modal-header border-bottom pb-4">
|
||||||
<h1>{{ masterTask.name }}</h1>
|
<h1>{{ masterTask.name }}</h1>
|
||||||
<div class="d-flex justify-start">
|
<div class="d-flex justify-start">
|
||||||
<img class="icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
|
<img class="icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
|
||||||
<img class="icon trash" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="openDeleteMasterTaskModal(masterTask)" />
|
<img class="icon trash" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="openDeleteMasterTaskModal(masterTask)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<v-btn class="button primary" @click="save()">Ukončiť mastertask</v-btn>
|
<v-btn class="button primary" @click="save()">Ukončiť mastertask</v-btn>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<A-tasks-table :tasks="masterTask.subtasks" :employees="employees" />
|
<A-tasks-table :tasks="masterTask.subtasks" :employees="enrichedEmployees" />
|
||||||
|
|
||||||
<div class="d-flex align-center ">
|
<div class="d-flex align-center ">
|
||||||
<v-btn class="subtask-btn w-100" @click="addTask()" ><v-icon class="mx-1" icon="mdi-plus" />Pridať task</v-btn>
|
<v-btn class="subtask-btn w-100" @click="addTask()" ><v-icon class="mx-1" icon="mdi-plus" />Pridať task</v-btn>
|
||||||
@@ -90,6 +90,7 @@ import '@vueup/vue-quill/dist/vue-quill.snow.css'
|
|||||||
import SelectsMixin from './_mixins/selects.mixin'
|
import SelectsMixin from './_mixins/selects.mixin'
|
||||||
import ATasksTable from './_components/a-tasks-table.vue'
|
import ATasksTable from './_components/a-tasks-table.vue'
|
||||||
import AMastertaskDescription from './_components/a-mastertask-description.vue'
|
import AMastertaskDescription from './_components/a-mastertask-description.vue'
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// MIXINS
|
// MIXINS
|
||||||
@@ -115,15 +116,20 @@ export default {
|
|||||||
visible: false,
|
visible: false,
|
||||||
errorUtils,
|
errorUtils,
|
||||||
v$: useVuelidate(),
|
v$: useVuelidate(),
|
||||||
teams: null,
|
|
||||||
projects: null,
|
|
||||||
employees: null,
|
|
||||||
masterTask: null,
|
masterTask: null,
|
||||||
showAddEmployeeInput: false,
|
showAddEmployeeInput: false,
|
||||||
date: null,
|
date: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
...mapGetters('tm', [
|
||||||
|
'teams',
|
||||||
|
'projects',
|
||||||
|
'enrichedEmployees'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
|
||||||
validations() {
|
validations() {
|
||||||
return {
|
return {
|
||||||
masterTask: {
|
masterTask: {
|
||||||
@@ -170,11 +176,6 @@ export default {
|
|||||||
this.masterTask = null
|
this.masterTask = null
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.teams = await this.$axios.get_auth_data('v1/teams')
|
|
||||||
this.projects = await this.$axios.get_auth_data('v1/projects')
|
|
||||||
const employees = await this.$axios.get_auth_data('v1/employees')
|
|
||||||
this.employees = tmUtils.enrichEmployeesByFullName(employees)
|
|
||||||
|
|
||||||
if (masterTask?.id) {
|
if (masterTask?.id) {
|
||||||
this.masterTask = await this.$axios.get_auth_data(`v1/mastertasks/${masterTask.id}`)
|
this.masterTask = await this.$axios.get_auth_data(`v1/mastertasks/${masterTask.id}`)
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</v-col>
|
</v-col>
|
||||||
<v-col cols="7">
|
<v-col cols="7">
|
||||||
<v-sheet class="py-3">
|
<v-sheet class="py-3">
|
||||||
<p class="task-badge px-4 py-2 rounded-pill">
|
<p class="task-badge px-4 py-2 rounded-pill hover" @click="openMastertask()" :style="{backgroundColor: color}">
|
||||||
{{ name }}
|
{{ name }}
|
||||||
</p>
|
</p>
|
||||||
</v-sheet>
|
</v-sheet>
|
||||||
@@ -20,10 +20,29 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
|
emits: ['close-modal'],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
name: {
|
name: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
openMastertask() {
|
||||||
|
this.$emit('close-modal')
|
||||||
|
this.$events.emit('show-master-task-modal', {masterTask: {id: this.id}, editMode: false})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ export default {
|
|||||||
async _update(task) {
|
async _update(task) {
|
||||||
try {
|
try {
|
||||||
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${task.id}`, task)
|
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${task.id}`, task)
|
||||||
|
this.$store.commit('tm/update_subtask', subtask)
|
||||||
this.closeModal()
|
this.closeModal()
|
||||||
this.$events.emit('on-subtask-edited', subtask)
|
this.$events.emit('on-subtask-edited', subtask)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
<v-card>
|
<v-card>
|
||||||
<div class="d-flex justify-space-between align-center">
|
<div class="d-flex justify-space-between align-center">
|
||||||
<h1>Pridať dátum</h1>
|
<h1>Pridať dátum</h1>
|
||||||
<v-icon @click.stop="clsoeModal()" icon="mdi-close" size="large"></v-icon>
|
<v-icon @click.stop="closeModal()" icon="mdi-close" size="large"></v-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-card-actions class="mt-10 d-flex flex-column modal-content">
|
<v-card-actions class="mt-10 d-flex flex-column modal-content">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<A-mastertask-name :name="task.master_task.name" />
|
<A-mastertask-name :name="task.master_task?.name || task.master_task" :id="task.master_task.id" :color="task.master_task.color" @close-modal="$emit('close-modal')" />
|
||||||
<A-mastertask-status :status="task.is_finished" />
|
<A-mastertask-status :status="task.is_finished" />
|
||||||
<A-task-timeblocks :timeblocks="task.timeblocks" :task="task" />
|
<A-task-timeblocks :timeblocks="task.timeblocks" :task="task" />
|
||||||
<A-task-assigned-employee :employee="task.employee" />
|
<A-task-assigned-employee :employee="task.employee" />
|
||||||
@@ -22,6 +22,8 @@ import ATaskDescription from './_components/a-task-description.vue'
|
|||||||
import ZFiles from '@/plugins/tm@modal/_components/z-files.vue'
|
import ZFiles from '@/plugins/tm@modal/_components/z-files.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
emits: ['close-modal'],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
ZFiles,
|
ZFiles,
|
||||||
AMastertaskName,
|
AMastertaskName,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<v-dialog v-model="visible" max-width="750">
|
<v-dialog v-model="visible" max-width="750">
|
||||||
<v-card>
|
<v-card>
|
||||||
<div class="d-flex justify-space-between align-center">
|
<div class="d-flex justify-space-between align-center">
|
||||||
<h1>Ste si istý, že chcete {{ this.subtask.is_finished ? 'dokončiť' : 'otvoriť' }} task, z masterTasku <b>{{ subtask?.master_task }}</b>?</h1>
|
<h1>Ste si istý, že chcete {{ subtask.is_finished ? 'znovu otvoriť' : 'dokončiť' }} task, z masterTasku <b>{{ subtask?.master_task?.name || subtask.master_task }}</b>?</h1>
|
||||||
<v-icon
|
<v-icon
|
||||||
@click.stop="visible = false"
|
@click.stop="visible = false"
|
||||||
icon="mdi-close"
|
icon="mdi-close"
|
||||||
@@ -36,12 +36,13 @@ export default {
|
|||||||
|
|
||||||
async complete() {
|
async complete() {
|
||||||
try {
|
try {
|
||||||
const tempSubtask = {...this.subtask, is_finished: !this.subtask.is_finished}
|
const tempSubtask = {...this.subtask, is_finished: this.subtask.is_finished ? 0 : 1}
|
||||||
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${tempSubtask.id}`, tempSubtask)
|
const { subtask } = await this.$axios.put_auth(`v1/subtasks/${tempSubtask.id}`, tempSubtask)
|
||||||
|
|
||||||
this.visible = false
|
this.visible = false
|
||||||
|
this.$store.dispatch('tm/loadMastertasks')
|
||||||
this.$store.commit('tm/update_subtask', subtask)
|
this.$store.dispatch('tm/loadUnscheduledSubtasks')
|
||||||
|
this.$store.dispatch('tm/loadOngoingSubtasks')
|
||||||
this.$emit('on-subtask-edited', subtask)
|
this.$emit('on-subtask-edited', subtask)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$toast.error(error)
|
this.$toast.error(error)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default {
|
|||||||
|
|
||||||
async deleteTask() {
|
async deleteTask() {
|
||||||
try {
|
try {
|
||||||
await this.$axios.delete(`v1/subtasks/${this.task.id}`)
|
await this.$axios.delete_auth(`v1/subtasks/${this.task.id}`)
|
||||||
|
|
||||||
this.$store.commit('tm/delete_subtask', this.task)
|
this.$store.commit('tm/delete_subtask', this.task)
|
||||||
this.$emit('on-task-deleted', this.task)
|
this.$emit('on-task-deleted', this.task)
|
||||||
|
|||||||
@@ -34,17 +34,18 @@
|
|||||||
<div class="d-flex justify-space-between align-center modal-header border-bottom pb-4">
|
<div class="d-flex justify-space-between align-center modal-header border-bottom pb-4">
|
||||||
<h1>{{ task.title }}</h1>
|
<h1>{{ task.title }}</h1>
|
||||||
<div class="d-flex justify-start">
|
<div class="d-flex justify-start">
|
||||||
<img class="icon" :src="require('@/plugins/tm@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
|
<img class="icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editMode = !editMode" />
|
||||||
<img class="icon trash" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="openDeleteTaskModal(task)" />
|
<img class="icon trash" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="openDeleteTaskModal(task)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<v-card-actions class="d-flex flex-column modal-content">
|
<v-card-actions class="d-flex flex-column modal-content">
|
||||||
<div class="w-100">
|
<div class="w-100">
|
||||||
<Z-task-readonly-info :task="task" />
|
<Z-task-readonly-info :task="task" @close-modal="closeModal" />
|
||||||
|
|
||||||
<div class="d-flex justify-start align-center mt-8">
|
<div class="d-flex justify-start align-center mt-8">
|
||||||
<v-btn class="done-btn" @click.stop="task.is_finished = 1; save()">Dokončené</v-btn>
|
<v-btn class="done-btn" v-if="!task.is_finished" @click.stop="showCompleteTaskModal()">Dokončiť</v-btn>
|
||||||
|
<v-btn class="button secondary" v-else @click.stop="showCompleteTaskModal()">Znovu otvoriť</v-btn>
|
||||||
<v-btn class="button secondary" @click="save()">Uložiť zmeny</v-btn>
|
<v-btn class="button secondary" @click="save()">Uložiť zmeny</v-btn>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -214,6 +215,10 @@ export default {
|
|||||||
this.$events.emit("show-delete-task-modal", { task })
|
this.$events.emit("show-delete-task-modal", { task })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showCompleteTaskModal() {
|
||||||
|
this.$events.emit('show-complete-task-modal', { subtask: this.task })
|
||||||
|
},
|
||||||
|
|
||||||
filesUploaded(files) {
|
filesUploaded(files) {
|
||||||
this.task.files = files
|
this.task.files = files
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M5.33329 13.3334V13.8334C5.4659 13.8334 5.59308 13.7807 5.68685 13.6869L5.33329 13.3334ZM2.66663 13.3334H2.16663C2.16663 13.6095 2.39048 13.8334 2.66663 13.8334V13.3334ZM2.66663 10.6667L2.31307 10.3132C2.2193 10.4069 2.16663 10.5341 2.16663 10.6667H2.66663ZM10.1952 3.13813L10.5488 3.49169V3.49169L10.1952 3.13813ZM11.138 3.13813L10.7845 3.49169V3.49169L11.138 3.13813ZM12.8619 4.86199L13.2154 4.50844V4.50844L12.8619 4.86199ZM12.8619 5.8048L12.5083 5.45125L12.8619 5.8048ZM5.33329 12.8334H2.66663V13.8334H5.33329V12.8334ZM3.16663 13.3334V10.6667H2.16663V13.3334H3.16663ZM3.02018 11.0203L10.5488 3.49169L9.84167 2.78458L2.31307 10.3132L3.02018 11.0203ZM10.7845 3.49169L12.5083 5.21554L13.2154 4.50844L11.4916 2.78458L10.7845 3.49169ZM12.5083 5.45125L4.97974 12.9798L5.68685 13.6869L13.2154 6.15835L12.5083 5.45125ZM12.5083 5.21554C12.5734 5.28063 12.5734 5.38616 12.5083 5.45125L13.2154 6.15835C13.6711 5.70274 13.6711 4.96405 13.2154 4.50844L12.5083 5.21554ZM10.5488 3.49169C10.6139 3.4266 10.7194 3.4266 10.7845 3.49169L11.4916 2.78458C11.036 2.32897 10.2973 2.32897 9.84167 2.78458L10.5488 3.49169Z" fill="#14181F"/>
|
|
||||||
<path d="M8 5.33325L10.6667 7.99992" stroke="#14181F" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -1,7 +0,0 @@
|
|||||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M9.33337 6.66675L9.33337 11.3334" stroke="#14181F" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M6.66663 6.66675L6.66663 11.3334" stroke="#14181F" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M4 4V3.5C3.72386 3.5 3.5 3.72386 3.5 4H4ZM12 4H12.5C12.5 3.72386 12.2761 3.5 12 3.5V4ZM4 4.5H12V3.5H4V4.5ZM11.5 4V13.3333H12.5V4H11.5ZM11.3333 13.5H4.66667V14.5H11.3333V13.5ZM4.5 13.3333V4H3.5V13.3333H4.5ZM4.66667 13.5C4.57462 13.5 4.5 13.4254 4.5 13.3333H3.5C3.5 13.9777 4.02233 14.5 4.66667 14.5V13.5ZM11.5 13.3333C11.5 13.4254 11.4254 13.5 11.3333 13.5V14.5C11.9777 14.5 12.5 13.9777 12.5 13.3333H11.5Z" fill="#14181F"/>
|
|
||||||
<path d="M2.66663 4H13.3333" stroke="#14181F" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
<path d="M10.6667 4V4.5C10.9429 4.5 11.1667 4.27614 11.1667 4H10.6667ZM5.33337 4H4.83337C4.83337 4.27614 5.05723 4.5 5.33337 4.5V4ZM6.00004 2.5H10V1.5H6.00004V2.5ZM10.1667 2.66667V4H11.1667V2.66667H10.1667ZM10.6667 3.5H5.33337V4.5H10.6667V3.5ZM5.83337 4V2.66667H4.83337V4H5.83337ZM10 2.5C10.0921 2.5 10.1667 2.57462 10.1667 2.66667H11.1667C11.1667 2.02233 10.6444 1.5 10 1.5V2.5ZM6.00004 1.5C5.35571 1.5 4.83337 2.02233 4.83337 2.66667H5.83337C5.83337 2.57462 5.90799 2.5 6.00004 2.5V1.5Z" fill="#14181F"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -13,13 +13,14 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr class="cursor-pointer" v-for="task in tasks" :key="task.id" @click.stop="editTask(task, false)">
|
<tr class="cursor-pointer" v-for="task in tasks" :key="task.id" @click.stop="editTask(task, false)">
|
||||||
<td>{{ task.project_code }}</td>
|
<td>{{ task.project_code }}</td>
|
||||||
<td>{{ task.master_task }}</td>
|
<td>{{ task.master_task?.name || task.master_task }}</td>
|
||||||
<td>{{ task.duration }} h</td>
|
<td>{{ task.duration }} h</td>
|
||||||
<td>{{ task.duration - task.spent_time }} h</td>
|
<td>{{ task.duration - task.spent_time }} h</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@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editTask(task, true)" />
|
<img class="pencil-icon mr-3" :src="require('@/plugins/app/_img/icons/eye.svg')" alt="pencil-icon" @click.stop="editTask(task, false)">
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask(task)" />
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editTask(task, true)" />
|
||||||
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="deleteTask(task)" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default {
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
return this.ongoingSubtasks.filter(subtask => {
|
return this.ongoingSubtasks.filter(subtask => {
|
||||||
return this.filterParams(this.searchQuery, subtask.master_task) || this.filterParams(this.searchQuery, subtask.project_code)
|
return this.filterParams(this.searchQuery, subtask.master_task?.name || subtask.master_task) || this.filterParams(this.searchQuery, subtask.project_code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,12 +13,13 @@
|
|||||||
<tr class="cursor-pointer" v-for="task in tasks" :key="task.id" @click.stop="editTask(task, false)">
|
<tr class="cursor-pointer" v-for="task in tasks" :key="task.id" @click.stop="editTask(task, false)">
|
||||||
|
|
||||||
<td>{{ task.project_code }}</td>
|
<td>{{ task.project_code }}</td>
|
||||||
<td>{{ task.master_task }}</td>
|
<td>{{ task.master_task?.name || task.master_task }}</td>
|
||||||
<td>{{ task.spent_time }} h</td>
|
<td>{{ task.spent_time }} h</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@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editTask(task, true)">
|
<img class="pencil-icon mr-3" :src="require('@/plugins/app/_img/icons/eye.svg')" alt="pencil-icon" @click.stop="editTask(task, false)">
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTask(task)">
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editTask(task, true)">
|
||||||
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="deleteTask(task)">
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default {
|
|||||||
return null
|
return null
|
||||||
|
|
||||||
return this.unscheduledSubtasks.filter(subtask => {
|
return this.unscheduledSubtasks.filter(subtask => {
|
||||||
return this.filterParams(this.searchQuery, subtask.master_task) || this.filterParams(this.searchQuery, subtask.project_code)
|
return this.filterParams(this.searchQuery, subtask.master_task?.name || subtask.master_task) || this.filterParams(this.searchQuery, subtask.project_code)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
<td>{{ team.name }}</td>
|
<td>{{ team.name }}</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@overview/_img/pencil-icon.svg')" alt="pencil-icon" @click.stop="editTeam(team)" />
|
<img class="pencil-icon" :src="require('@/plugins/app/_img/icons/pencil.svg')" alt="pencil-icon" @click.stop="editTeam(team)" />
|
||||||
<img class="trash-icon" :src="require('@/plugins/tm@overview/_img/trash-icon.svg')" alt="trash-icon" @click.stop="deleteTeam(team)" />
|
<img class="trash-icon" :src="require('@/plugins/app/_img/icons/bin.svg')" alt="trash-icon" @click.stop="deleteTeam(team)" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import axios from '@/plugins/w/axios/models/axios'
|
import axios from '@/plugins/w/axios/models/axios'
|
||||||
import './refreshExpired'
|
// import './refreshExpired'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
@@ -35,7 +35,7 @@ export default {
|
|||||||
actions: {
|
actions: {
|
||||||
login({commit}: {commit: any}, credentials: any) {
|
login({commit}: {commit: any}, credentials: any) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
axios.post('v1/tokens/create', credentials)
|
axios.post('v1/tokens/create', {data: credentials})
|
||||||
.then((response: any) => {
|
.then((response: any) => {
|
||||||
console.log(response)
|
console.log(response)
|
||||||
const token = response.token
|
const token = response.token
|
||||||
|
|||||||
Reference in new issue
Block a user