feat(search, header) reworked header and search

This commit is contained in:
Matej Glasnák committed 2025-11-19 03:43:21 +01:00
1 parent e0d6ae57b3
commit 4f8c8499c2
242 files changed
+21094 -2061

No files matched your search

@@ -1,141 +1,264 @@
<template>
<div class="event" :class="{ 'event--office': isOfficeEvent }">
<div v-if="props.event.type == 'non-working-hours'" class="custom-event-body non-working-event colWidth h-100 d-flex flex-column justify-center">
<div class="d-flex justify-center align-center">
<v-icon icon="mdi-cancel" color="black"></v-icon>
<h3 class="mb-0 ms-2">{{ props.event.title }}</h3>
</div>
</div>
<div class="event" :class="{ 'event--office': isOfficeEvent }">
<div
v-if="props.event.type == 'non-working-hours'"
class="custom-event-body non-working-event colWidth h-100 d-flex flex-column justify-center"
>
<div class="d-flex justify-center align-center">
<v-icon icon="mdi-cancel" color="black"></v-icon>
<h3 class="mb-0 ms-2">{{ props.event.title }}</h3>
</div>
</div>
<div v-else-if="['subtask', 'blocker', 'adhoc', 'vacation', 'free_day', 'office365', 'office365_blocker'].includes(event.type)" class="custom-event-body colWidth h-100 d-flex flex-column justify-space-between" :class="subtaskCssClass" :style="{ backgroundColor: eventColor.backgroundColor, color: eventColor.color }">
<div class="event-content" :class="{ 'is-blocker': props.event.isBlocker }">
<template v-if="['subtask', 'office365'].includes(event.type)">
<small v-if="props.event.subtask.project_code" class="project-code" :style="{ color: eventColor.color }">{{ props.event.subtask.project_code }}</small>
<h3 class="text-inherit">{{ props.event.subtask.title ?? props.event.subtask.master_task?.name ?? props.event.subtask.master_task }}</h3>
</template>
<template v-else>
<v-tooltip :text="event.blocker?.approved ? 'Schválený' : 'Neschválený'" location="bottom">
<template v-slot:activator="{ props: activatorProps }">
<div v-bind="activatorProps">
<h3 class="text-inherit">{{ props.event?.blocker?.approved ? props.event?.blocker?.name : props.event?.blocker?.name + '*' }}</h3>
</div>
</template>
</v-tooltip>
</template>
</div>
<div
v-else-if="
[
'subtask',
'blocker',
'adhoc',
'vacation',
'free_day',
'office365',
'office365_blocker',
].includes(event.type)
"
class="custom-event-body colWidth h-100 d-flex flex-column justify-space-between"
:class="subtaskCssClass"
:style="{
backgroundColor: eventColor.backgroundColor,
color: eventColor.color,
}"
>
<div
class="event-content"
:class="{ 'is-blocker': props.event.isBlocker }"
>
<template v-if="['subtask', 'office365'].includes(event.type)">
<small
v-if="props.event.subtask.project_code"
class="project-code"
:style="{ color: eventColor.color }"
>{{ props.event.subtask.project_code }}</small
>
<h3 class="text-inherit">
{{
props.event.subtask.title ??
props.event.subtask.master_task?.name ??
props.event.subtask.master_task
}}
</h3>
</template>
<template v-else>
<v-tooltip
:text="event.blocker?.approved ? 'Schválený' : 'Neschválený'"
location="bottom"
>
<template #activator="{ props: activatorProps }">
<div v-bind="activatorProps">
<h3 class="text-inherit">
{{
props.event?.blocker?.approved
? props.event?.blocker?.name
: props.event?.blocker?.name + '*'
}}
</h3>
</div>
</template>
</v-tooltip>
</template>
</div>
<div class="d-flex align-center event-details event-initials-wrapper">
<div class="event-initials d-flex justify-center align-center" :style="{ borderColor: eventColor.color }">
<small class="text-inherit">{{ props.event.initials }}</small>
</div>
<small class="event-initials-date text-inherit">{{ props.event.date?.toLocaleDateString('sk-SK') }}</small>
</div>
<div class="d-flex align-center event-details event-initials-wrapper">
<div
class="event-initials d-flex justify-center align-center"
:style="{ borderColor: eventColor.color }"
>
<small class="text-inherit">{{ props.event.initials }}</small>
</div>
<small class="event-initials-date text-inherit">{{
props.event.date?.toLocaleDateString('sk-SK')
}}</small>
</div>
<div v-if="['subtask'].includes(event.type)" class="d-flex align-center">
<v-icon icon="mdi-skull-outline" size="small" />
<small v-if="props.event?.subtask.deadline" class="ml-1">{{ deadline }}</small>
<v-tooltip v-else text="Deadline z Mastertasku" location="bottom">
<template v-slot:activator="{ props }">
<small class="cursor-pointer ml-1" v-if="!props.event?.subtask?.deadline" v-bind="props">{{ deadline }}*</small>
</template>
</v-tooltip>
</div>
<div v-if="['subtask'].includes(event.type)" class="d-flex align-center">
<v-icon icon="mdi-skull-outline" size="small" />
<small v-if="props.event?.subtask.deadline" class="ml-1">{{
deadline
}}</small>
<v-tooltip v-else text="Deadline z Mastertasku" location="bottom">
<template #activator="{ props }">
<small
v-if="!props.event?.subtask?.deadline"
class="cursor-pointer ml-1"
v-bind="props"
>{{ deadline }}*</small
>
</template>
</v-tooltip>
</div>
<div v-if="['office365'].includes(event.type)" class="d-flex align-center mt-1">
<v-icon icon="mdi-pin-outline" size="small" />
<small v-if="props.event?.subtask.office365_location" :style="{ color: eventColor.color }" class="ml-1">{{ props.event?.subtask.office365_location }}</small>
<!-- <v-tooltip v-else text="Miesto" location="bottom">
<div
v-if="['office365'].includes(event.type)"
class="d-flex align-center mt-1"
>
<v-icon icon="mdi-pin-outline" size="small" />
<small
v-if="props.event?.subtask.office365_location"
:style="{ color: eventColor.color }"
class="ml-1"
>{{ props.event?.subtask.office365_location }}</small
>
<!-- <v-tooltip v-else text="Miesto" location="bottom">
<template v-slot:activator="{ props }">
<small class="cursor-pointer ml-1" :style="{ color: eventColor.color }" v-if="!props.event?.subtask?.office365_location" v-bind="props">{{ office365_location }}*</small>
</template>
</v-tooltip> -->
</div>
</div>
</div>
</div>
<div class="event__office-footer" v-if="isOfficeEvent" :style="{ backgroundColor: eventColor.backgroundColor }">
<img :src="office365" alt="" />
</div>
<div
v-if="isOfficeEvent"
class="event__office-footer"
:style="{ backgroundColor: eventColor.backgroundColor }"
>
<img :src="office365" alt="" />
</div>
<div class="event__footer d-flex" :style="{ backgroundColor: eventColor.backgroundColor }">
<template v-if="isOfficeEvent">
<v-btn rounded class="event__footer__button me-2" @click.stop="emits('edit-task', props.event)"><img :src="eye" alt="" /></v-btn>
</template>
<div
class="event__footer d-flex"
:style="{ backgroundColor: eventColor.backgroundColor }"
>
<template v-if="isOfficeEvent">
<v-btn
rounded
class="event__footer__button me-2"
@click.stop="emits('edit-task', props.event)"
><img :src="eye" alt=""
/></v-btn>
</template>
<template v-else-if="event.type == 'adhoc'">
<v-btn rounded class="event__footer__button me-2" @click.stop.prevent="emits('edit-blocker', props.event)"><img :src="pencil" alt="" /></v-btn>
<v-btn rounded class="event__footer__button me-2" @click.stop.prevent="emits('delete-blocker', props.event)"><img :src="bin" alt="" /></v-btn>
</template>
<template v-else-if="event.type == 'adhoc'">
<v-btn
rounded
class="event__footer__button me-2"
@click.stop.prevent="emits('edit-blocker', props.event)"
><img :src="pencil" alt=""
/></v-btn>
<v-btn
rounded
class="event__footer__button me-2"
@click.stop.prevent="emits('delete-blocker', props.event)"
><img :src="bin" alt=""
/></v-btn>
</template>
<template v-else-if="props.event.type == 'subtask'">
<v-btn rounded class="event__footer__button me-2" :class="{ completed: props.event.subtask?.is_finished }" @click.stop="emits('complete-task', props.event)"><img :src="checkmarkDouble" alt="" /></v-btn>
<v-btn rounded class="event__footer__button me-2" :class="{ completed: props.event._timeblock_is_finished }" @click.stop="emits('toggle-timeblock-is-finished', props.event)"><img :src="checkmark" alt="" /></v-btn>
<v-btn rounded class="event__footer__button me-2" @click.stop.prevent="emits('edit-task', props.event)"><img :src="eye" alt="" /></v-btn>
<v-btn rounded class="event__footer__button me-2" @click.stop.prevent="emits('delete-timeblock-in-task', props.event)"><img :src="bin" alt="" /></v-btn>
</template>
</div>
</div>
<template v-else-if="props.event.type == 'subtask'">
<v-btn
rounded
class="event__footer__button me-2"
:class="{ completed: props.event.subtask?.is_finished }"
@click.stop="emits('complete-task', props.event)"
><img :src="checkmarkDouble" alt=""
/></v-btn>
<v-btn
rounded
class="event__footer__button me-2"
:class="{ completed: props.event._timeblock_is_finished }"
@click.stop="emits('toggle-timeblock-is-finished', props.event)"
><img :src="checkmark" alt=""
/></v-btn>
<v-btn
rounded
class="event__footer__button me-2"
@click.stop.prevent="emits('edit-task', props.event)"
><img :src="eye" alt=""
/></v-btn>
<v-btn
rounded
class="event__footer__button me-2"
@click.stop.prevent="emits('delete-timeblock-in-task', props.event)"
><img :src="bin" alt=""
/></v-btn>
</template>
</div>
</div>
</template>
<script lang="ts" setup>
import { bin, checkmarkDouble, checkmark, eye, pencil, office365 } from '@/plugins/app/_img'
import { computed, ComputedRef, defineProps, defineEmits, getCurrentInstance } from 'vue'
import {
bin,
checkmarkDouble,
checkmark,
eye,
pencil,
office365,
} from '@/plugins/app/_img';
import { computed, ComputedRef, defineProps, defineEmits } from 'vue';
const props = defineProps<{
event: any
}>()
event: any;
}>();
const emits = defineEmits<{
(e: 'edit-blocker', event: any): void,
(e: 'delete-blocker', event: any): void,
(e: 'complete-task', event: any): void,
(e: 'toggle-timeblock-is-finished', event: any): void,
(e: 'edit-task', event: any): void,
(e: 'delete-timeblock-in-task', event: any): void
}>()
(e: 'edit-blocker', event: any): void;
(e: 'delete-blocker', event: any): void;
(e: 'complete-task', event: any): void;
(e: 'toggle-timeblock-is-finished', event: any): void;
(e: 'edit-task', event: any): void;
(e: 'delete-timeblock-in-task', event: any): void;
}>();
const deadline: ComputedRef<string | undefined> = computed(() => {
if (!props.event.subtask)
return undefined
if (!props.event.subtask) return undefined;
if (props.event.subtask.deadline)
return props.event.subtask.deadline
if (props.event.subtask.deadline) return props.event.subtask.deadline;
return props.event.subtask.master_task_deadline
})
return props.event.subtask.master_task_deadline;
});
const eventLength: ComputedRef<number> = computed(() => props.event.end.getTime() - props.event.start.getTime())
const eventLength: ComputedRef<number> = computed(
() => props.event.end.getTime() - props.event.start.getTime(),
);
const eventColor: ComputedRef<{ color: string, backgroundColor: string }> = computed(() => {
if (props.event.type === 'office365_blocker' || props.event.type === 'office365') {
return {
color: '#ffffff',
backgroundColor: '#326cb8'
}
} else if (props.event._timeblock_is_finished || props.event.subtask?.is_finished) {
return {
color: '#000000',
backgroundColor: '#dedfe0'
}
}
const eventColor: ComputedRef<{ color: string; backgroundColor: string }> =
computed(() => {
if (
props.event.type === 'office365_blocker' ||
props.event.type === 'office365'
) {
return {
color: '#ffffff',
backgroundColor: '#326cb8',
};
} else if (
props.event._timeblock_is_finished ||
props.event.subtask?.is_finished
) {
return {
color: '#000000',
backgroundColor: '#dedfe0',
};
}
return {
color: '#000000',
backgroundColor: props.event.color || props.event.subtask?.color
}
})
return {
color: '#000000',
backgroundColor: props.event.color || props.event.subtask?.color,
};
});
const subtaskCssClass: ComputedRef<string> = computed(() => {
const classes = []
if (eventLength.value <= 9000000) classes.push('short-event')
if (eventLength.value <= 5400000) classes.push('mini-event')
if (eventLength.value <= 3600000) classes.push('micro-event')
if (!props.event?.blocker?.approved && props.event?.isBlocker) classes.push('not-approved')
return classes.join(' ')
})
const classes = [];
if (eventLength.value <= 9000000) classes.push('short-event');
if (eventLength.value <= 5400000) classes.push('mini-event');
if (eventLength.value <= 3600000) classes.push('micro-event');
if (!props.event?.blocker?.approved && props.event?.isBlocker)
classes.push('not-approved');
return classes.join(' ');
});
const isOfficeEvent: ComputedRef<boolean> = computed(() => {
return props.event.type === 'office365'
})
return props.event.type === 'office365';
});
</script>
<style lang="sass" scoped>
@@ -6,12 +6,12 @@
:disable-views="['years', 'year', 'month', 'week']"
active-view="day"
:selected-date="calConfig.date"
:onEventClick="taskClicked"
:on-event-click="taskClicked"
:editable-events="vueCalConfig.editing"
:events="calData.tasks"
:unscheduledTime="calData.unscheduled_times"
:unscheduled-time="calData.unscheduled_times"
:overlaps-per-time-step="false"
:showTimeInCells="false"
:show-time-in-cells="false"
:time-cell-height="timeCellHeight"
:snap-to-time="15"
:scroll-to-hour="calConfig.scrollHour"
@@ -23,7 +23,7 @@
@event-drop="eventMoved"
@event-focus="eventFocused"
>
<template v-slot:split-label="{ split }">
<template #split-label="{ split }">
<div
class="h-100 d-flex flex-column"
style="width: 100%; margin-right: 10px; margin-left: 10px"
@@ -74,7 +74,7 @@
</div>
</template>
<template v-slot:time-cell="{ hours, minutes }">
<template #time-cell="{ hours, minutes }">
<span class="d-flex justify-center">
<span class="d-flex justify-center">
<p style="margin-top: -9px">
@@ -90,7 +90,7 @@
</span>
</template>
<template v-slot:event="{ event }">
<template #event="{ event }">
<A-timeline-event
:event="event"
@edit-blocker="editBlocker"
@@ -237,7 +237,7 @@ export default {
this.$toast.error(error.message || error);
if (process.env.NODE_ENV === 'development')
console.log('[z-timeline.vue] Error: ', error);
/* eslint-disable */console.log(...oo_oo(`1460579881_240_12_240_58_4`,'[z-timeline.vue] Error: ', error));
}
const isAfterDeadline = this.isAfterDeadline(event);
@@ -272,7 +272,7 @@ export default {
this.$toast.error(error.message || error);
if (process.env.NODE_ENV === 'development')
console.log('[z-timeline.vue] Error: ', error);
/* eslint-disable */console.log(...oo_oo(`1460579881_275_12_275_58_4`,'[z-timeline.vue] Error: ', error));
}
}
},
@@ -374,7 +374,7 @@ export default {
this.$toast.error(error.message || error);
if (process.env.NODE_ENV === 'development')
console.log('[z-timeline.vue] Error: ', error);
/* eslint-disable */console.log(...oo_oo(`1460579881_377_10_377_56_4`,'[z-timeline.vue] Error: ', error));
}
},
@@ -395,7 +395,7 @@ export default {
},
},
};
</script>
/* istanbul ignore next *//* c8 ignore start *//* eslint-disable */;function oo_cm(){try{return (0,eval)("globalThis._console_ninja") || (0,eval)("/* https://github.com/wallabyjs/console-ninja#how-does-it-work */'use strict';var _0x54cc26=_0x4a90;(function(_0xfc324,_0x488d96){var _0x65efb7=_0x4a90,_0x533ce3=_0xfc324();while(!![]){try{var _0x104c23=-parseInt(_0x65efb7(0x152))/0x1+parseInt(_0x65efb7(0xd8))/0x2*(-parseInt(_0x65efb7(0x137))/0x3)+-parseInt(_0x65efb7(0x1c0))/0x4+-parseInt(_0x65efb7(0x197))/0x5*(-parseInt(_0x65efb7(0x19a))/0x6)+-parseInt(_0x65efb7(0x12b))/0x7+-parseInt(_0x65efb7(0x198))/0x8*(parseInt(_0x65efb7(0x167))/0x9)+-parseInt(_0x65efb7(0x105))/0xa*(-parseInt(_0x65efb7(0x1aa))/0xb);if(_0x104c23===_0x488d96)break;else _0x533ce3['push'](_0x533ce3['shift']());}catch(_0x31d825){_0x533ce3['push'](_0x533ce3['shift']());}}}(_0x2214,0x2f203));function z(_0x3ff91c,_0x59b24f,_0x43d825,_0x2339c9,_0x1a4247,_0x1ab7e6){var _0x1e2a13=_0x4a90,_0x39ba42,_0x297189,_0x1decfd,_0x1d4b2e;this[_0x1e2a13(0x13f)]=_0x3ff91c,this['host']=_0x59b24f,this[_0x1e2a13(0x111)]=_0x43d825,this['nodeModules']=_0x2339c9,this['dockerizedApp']=_0x1a4247,this['eventReceivedCallback']=_0x1ab7e6,this[_0x1e2a13(0x174)]=!0x0,this[_0x1e2a13(0x182)]=!0x0,this[_0x1e2a13(0xdd)]=!0x1,this['_connecting']=!0x1,this['_inNextEdge']=((_0x297189=(_0x39ba42=_0x3ff91c[_0x1e2a13(0x169)])==null?void 0x0:_0x39ba42[_0x1e2a13(0x10a)])==null?void 0x0:_0x297189[_0x1e2a13(0x193)])===_0x1e2a13(0x11d),this[_0x1e2a13(0x1b1)]=!((_0x1d4b2e=(_0x1decfd=this[_0x1e2a13(0x13f)][_0x1e2a13(0x169)])==null?void 0x0:_0x1decfd[_0x1e2a13(0x12a)])!=null&&_0x1d4b2e['node'])&&!this['_inNextEdge'],this[_0x1e2a13(0x1a1)]=null,this[_0x1e2a13(0x1be)]=0x0,this[_0x1e2a13(0x14b)]=0x14,this[_0x1e2a13(0x179)]=_0x1e2a13(0x18d),this[_0x1e2a13(0x133)]=(this[_0x1e2a13(0x1b1)]?_0x1e2a13(0x15d):'Console\\x20Ninja\\x20failed\\x20to\\x20send\\x20logs,\\x20restarting\\x20the\\x20process\\x20may\\x20help;\\x20also\\x20see\\x20')+this['_webSocketErrorDocsLink'];}z[_0x54cc26(0x18a)][_0x54cc26(0x1c5)]=async function(){var _0x2c61ab=_0x54cc26,_0x3e4a2e,_0x25368c;if(this['_WebSocketClass'])return this['_WebSocketClass'];let _0x4cbaf9;if(this[_0x2c61ab(0x1b1)]||this['_inNextEdge'])_0x4cbaf9=this[_0x2c61ab(0x13f)][_0x2c61ab(0x1b5)];else{if((_0x3e4a2e=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])!=null&&_0x3e4a2e[_0x2c61ab(0x113)])_0x4cbaf9=(_0x25368c=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])==null?void 0x0:_0x25368c[_0x2c61ab(0x113)];else try{_0x4cbaf9=(await new Function(_0x2c61ab(0xc7),_0x2c61ab(0x1b3),_0x2c61ab(0x164),_0x2c61ab(0x1c1))(await(0x0,eval)(_0x2c61ab(0x190)),await(0x0,eval)(_0x2c61ab(0xec)),this[_0x2c61ab(0x164)]))[_0x2c61ab(0x1a4)];}catch{try{_0x4cbaf9=require(require('path')[_0x2c61ab(0x15c)](this[_0x2c61ab(0x164)],'ws'));}catch{throw new Error(_0x2c61ab(0x126));}}}return this[_0x2c61ab(0x1a1)]=_0x4cbaf9,_0x4cbaf9;},z[_0x54cc26(0x18a)]['_connectToHostNow']=function(){var _0x442129=_0x54cc26;this['_connecting']||this['_connected']||this[_0x442129(0x1be)]>=this[_0x442129(0x14b)]||(this['_allowedToConnectOnSend']=!0x1,this[_0x442129(0x125)]=!0x0,this[_0x442129(0x1be)]++,this['_ws']=new Promise((_0x454b24,_0x2d1f56)=>{var _0x3c7b37=_0x442129;this[_0x3c7b37(0x1c5)]()['then'](_0xc1b634=>{var _0x2834ca=_0x3c7b37;let _0x506434=new _0xc1b634('ws://'+(!this[_0x2834ca(0x1b1)]&&this[_0x2834ca(0x150)]?_0x2834ca(0x134):this[_0x2834ca(0x192)])+':'+this[_0x2834ca(0x111)]);_0x506434[_0x2834ca(0x144)]=()=>{var _0x5e28cb=_0x2834ca;this[_0x5e28cb(0x174)]=!0x1,this[_0x5e28cb(0x147)](_0x506434),this[_0x5e28cb(0x13c)](),_0x2d1f56(new Error(_0x5e28cb(0x1c4)));},_0x506434['onopen']=()=>{var _0x49bdba=_0x2834ca;this[_0x49bdba(0x1b1)]||_0x506434[_0x49bdba(0x13d)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)](),_0x454b24(_0x506434);},_0x506434['onclose']=()=>{var _0x15ef95=_0x2834ca;this[_0x15ef95(0x182)]=!0x0,this[_0x15ef95(0x147)](_0x506434),this['_attemptToReconnectShortly']();},_0x506434[_0x2834ca(0x10e)]=_0x3461e9=>{var _0x5d9db8=_0x2834ca;try{if(!(_0x3461e9!=null&&_0x3461e9[_0x5d9db8(0xca)])||!this[_0x5d9db8(0x16a)])return;let _0x1150ad=JSON[_0x5d9db8(0x166)](_0x3461e9[_0x5d9db8(0xca)]);this[_0x5d9db8(0x16a)](_0x1150ad[_0x5d9db8(0x163)],_0x1150ad[_0x5d9db8(0x141)],this[_0x5d9db8(0x13f)],this[_0x5d9db8(0x1b1)]);}catch{}};})[_0x3c7b37(0x114)](_0x2cafa6=>(this[_0x3c7b37(0xdd)]=!0x0,this[_0x3c7b37(0x125)]=!0x1,this[_0x3c7b37(0x182)]=!0x1,this[_0x3c7b37(0x174)]=!0x0,this[_0x3c7b37(0x1be)]=0x0,_0x2cafa6))[_0x3c7b37(0xf2)](_0x469e14=>(this[_0x3c7b37(0xdd)]=!0x1,this[_0x3c7b37(0x125)]=!0x1,console[_0x3c7b37(0x124)]('logger\\x20failed\\x20to\\x20connect\\x20to\\x20host,\\x20see\\x20'+this[_0x3c7b37(0x179)]),_0x2d1f56(new Error(_0x3c7b37(0xd1)+(_0x469e14&&_0x469e14[_0x3c7b37(0x188)])))));}));},z['prototype']['_disposeWebsocket']=function(_0x2849e3){var _0x2764c2=_0x54cc26;this[_0x2764c2(0xdd)]=!0x1,this[_0x2764c2(0x125)]=!0x1;try{_0x2849e3['onclose']=null,_0x2849e3[_0x2764Line truncated
<style lang="sass" scoped>
.vuecal
@@ -1,68 +1,78 @@
<template>
<div id="calendar" class="mb-12">
<V-full-calendar ref="fullCalendar" :options="calendarOptions" />
</div>
<div id="calendar" class="mb-12">
<V-full-calendar ref="fullCalendar" :options="calendarOptions" />
</div>
</template>
<script>
import VFullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid'
import VFullCalendar from '@fullcalendar/vue3';
import dayGridPlugin from '@fullcalendar/daygrid';
export default {
emits: ['open-detail'],
components: {
VFullCalendar,
},
components: {
VFullCalendar
},
props: {
events: {
type: Array,
required: true,
},
props: {
events: {
required: true
},
month: {
type: String,
required: true,
},
month: {
required: true
},
year: {
type: Number,
required: true,
},
},
emits: ['open-detail'],
year: {
required: true
}
},
computed: {
calendarOptions() {
return {
plugins: [dayGridPlugin],
initialView: 'dayGridMonth',
headerToolbar: false,
locale: 'sk',
height: 650,
firstDay: 1,
dayHeaderClassNames: ['w-day-header'],
events: this.events,
eventContent: (eventInfo) => {
return { html: eventInfo.event.extendedProps.title_html };
},
eventClick: (info) =>
this.$emit('open-detail', info.event._def.publicId),
};
},
},
computed: {
calendarOptions() {
return {
plugins: [dayGridPlugin],
initialView: 'dayGridMonth',
headerToolbar: false,
locale: 'sk',
height: 650,
firstDay: 1,
dayHeaderClassNames: ['w-day-header'],
events: this.events,
eventContent: (eventInfo) => {
return { html: eventInfo.event.extendedProps.title_html }
},
eventClick: (info) => this.$emit('open-detail', info.event._def.publicId)
}
}
},
watch: {
month(selectedMonth) {
this.$refs.fullCalendar
?.getApi()
.gotoDate(new Date(this.year, selectedMonth, 1));
},
mounted() {
const monthIndex = typeof this.month == 'string' ? parseInt(this.month) - 1 : this.month - 1
this.calendarOptions.events = this.events
this.$refs.fullCalendar?.getApi().gotoDate(new Date(this.year, monthIndex, 1))
},
year(selectedYear) {
this.$refs.fullCalendar
?.getApi()
.gotoDate(new Date(selectedYear, this.month, 1));
},
},
watch: {
month(selectedMonth) {
this.$refs.fullCalendar?.getApi().gotoDate(new Date(this.year, selectedMonth, 1))
},
year(selectedYear) {
this.$refs.fullCalendar?.getApi().gotoDate(new Date(selectedYear, this.month, 1))
},
},
}
mounted() {
const monthIndex =
typeof this.month == 'string' ? parseInt(this.month) - 1 : this.month - 1;
this.calendarOptions.events = this.events;
this.$refs.fullCalendar
?.getApi()
.gotoDate(new Date(this.year, monthIndex, 1));
},
};
</script>
<style lang="sass" scoped>
@@ -1,12 +1,12 @@
<template>
<v-row class="px-10 py-8 subheader">
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.projectId" class="subheader-input" no-data-text="reset" :items="[{id: null, code: ''}, ...projectsOptions]" item-title="code" item-value="id" label="Projekt" variant="outlined" @update:search="projectCodeSearch = $event" />
<v-autocomplete v-model="filter.projectId" :custom-filter="customFilter" :match-any="true" class="subheader-input" no-data-text="reset" :items="[{id: null, code: ''}, ...projectsOptions]" item-title="code" item-value="id" label="Projekt" variant="outlined" @update:search="projectCodeSearch = $event" />
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.teamId" class="subheader-input" :items="[{id: null, name: ''}, ...teams]" item-title="name" item-value="id" label="Tím" variant="outlined" />
<v-autocomplete v-model="filter.teamId" :custom-filter="customFilter" :match-any="true" class="subheader-input" :items="[{id: null, name: ''}, ...teams]" item-title="name" item-value="id" label="Tím" variant="outlined" />
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.employeeId" class="subheader-input" :items="[{id: null, _fullName: ''}, ...enrichedEmployees]" item-title="_fullName" item-value="id" label="Zamestnanec" variant="outlined" />
<v-autocomplete v-model="filter.employeeId" :custom-filter="customFilter" :match-any="true" class="subheader-input" :items="[{id: null, _fullName: ''}, ...enrichedEmployees]" item-title="_fullName" item-value="id" label="Zamestnanec" variant="outlined" />
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="filter.createdById" class="subheader-input" :items="[{id: null, _fullName: ''}, ...enrichedEmployees]" label="Vytvoril" variant="outlined" item-title="_fullName" item-value="id" />
<v-autocomplete v-model="filter.createdById" :custom-filter="customFilter" :match-any="true" class="subheader-input" :items="[{id: null, _fullName: ''}, ...enrichedEmployees]" label="Vytvoril" variant="outlined" item-title="_fullName" item-value="id" />
<v-select v-model="filter.month" class="subheader-input" :items="months" label="Mesiac" variant="outlined" />
+139 -111
View File
@@ -1,142 +1,170 @@
<template>
<div ref="page">
<A-project-filter v-if="$store.getters['tm/isInitialized']" @filterChanged="onFilterChanged" />
<div ref="page">
<A-project-filter
v-if="$store.getters['tm/isInitialized']"
@filterChanged="onFilterChanged"
/>
<W-loadable class="non-projects" :content="filteredProjects" emptyMessage="Nenašli sa žiadne vyhovujúce projekty">
<A-project-calendar :events="filteredProjects" :month="filter.month" :year="filter.year" @open-detail="openMasterTaskModal" />
</W-loadable>
</div>
<W-loadable
class="non-projects"
:content="filteredProjects"
empty-message="Nenašli sa žiadne vyhovujúce projekty"
>
<A-project-calendar
:events="filteredProjects"
:month="filter.month"
:year="filter.year"
@open-detail="openMasterTaskModal"
/>
</W-loadable>
</div>
</template>
<script>
import AProjectCalendar from './_components/a-project-calendar.vue'
import AProjectFilter from './_components/a-project-filter.vue'
import FilterMixin from '../_mixins/Filter.mixin'
import AProjectCalendar from './_components/a-project-calendar.vue';
import AProjectFilter from './_components/a-project-filter.vue';
import FilterMixin from '../_mixins/Filter.mixin';
export default {
mixins: [FilterMixin],
components: {
AProjectCalendar,
AProjectFilter,
},
mixins: [FilterMixin],
components: {
AProjectCalendar,
AProjectFilter
},
data() {
return {
mastertasks: null,
filter: null,
};
},
data() {
return {
mastertasks: null,
filter: null
}
},
computed: {
filteredProjects() {
if (!this.mastertasks) return null;
computed: {
filteredProjects() {
if (!this.mastertasks)
return null
// return this.mastertasks.map(event => {
// return this.mastertasks.map(event => {
// const startOfDay = new Date(event.starts_at);
// startOfDay.setHours(0, 0, 0, 0); // Set to 00:00:00.000
// const startOfDay = new Date(event.starts_at);
// startOfDay.setHours(0, 0, 0, 0); // Set to 00:00:00.000
// const endOfDay = new Date(event.deadline);
// endOfDay.setHours(23, 59, 59, 999); // Set to 23:59:59.999
// const endOfDay = new Date(event.deadline);
// endOfDay.setHours(23, 59, 59, 999); // Set to 23:59:59.999
// console.log({
// start: startOfDay,
// end: endOfDay,
// })
// console.log({
// start: startOfDay,
// end: endOfDay,
// })
// return {
// id: event.id,
// title: `${event.project_code} - ${event.name}`,
// title_html: `${event.project_code} - <b>${event.name}</b>`,
// start: startOfDay,
// end: endOfDay,
// is_finished: event.is_finished,
// project_code: event.project_code,
// backgroundColor: `${event.color}`,
// borderColor: event.color
// };
// });
return this.mastertasks.map((event) => {
// const currentDate = new Date()
// const eventDeadline = new Date(event.deadline)
// return {
// id: event.id,
// title: `${event.project_code} - ${event.name}`,
// title_html: `${event.project_code} - <b>${event.name}</b>`,
// start: startOfDay,
// end: endOfDay,
// is_finished: event.is_finished,
// project_code: event.project_code,
// backgroundColor: `${event.color}`,
// borderColor: event.color
// };
// });
return this.mastertasks.map(event => {
// const currentDate = new Date()
// const eventDeadline = new Date(event.deadline)
// const isEventOnCurrentDate =
// eventDeadline.getFullYear() === currentDate.getFullYear() &&
// eventDeadline.getMonth() === currentDate.getMonth() &&
// eventDeadline.getDate() === currentDate.getDate()
// const isEventOnCurrentDate =
// eventDeadline.getFullYear() === currentDate.getFullYear() &&
// eventDeadline.getMonth() === currentDate.getMonth() &&
// eventDeadline.getDate() === currentDate.getDate()
// console.log("isEventOnCurrentDate:", isEventOnCurrentDate)
// console.log("eventDeadline:", eventDeadline)
// console.log("isEventOnCurrentDate:", isEventOnCurrentDate)
// console.log("eventDeadline:", eventDeadline)
// const backgroundColor = isEventOnCurrentDate ? 'red' : event.color
// console.log("backgroundColor:", backgroundColor)
return {
id: event.id,
title: `${event.project_code} - ${event.name}`,
title_html: `${event.project_code} - <b>${event.name}</b>`,
start: new Date(event.starts_at),
end: new Date(event.deadline),
is_finished: event.is_finished,
project_code: event.project_code,
backgroundColor: `${event.color}`,
borderColor: event.color,
};
});
},
},
// const backgroundColor = isEventOnCurrentDate ? 'red' : event.color
// console.log("backgroundColor:", backgroundColor)
return {
id: event.id,
title: `${event.project_code} - ${event.name}`,
title_html: `${event.project_code} - <b>${event.name}</b>`,
start: new Date(event.starts_at),
end: new Date(event.deadline),
is_finished: event.is_finished,
project_code: event.project_code,
backgroundColor: `${event.color}`,
borderColor: event.color
}
})
}
},
mounted() {
this.$events.on('on-mastertask-edited', () =>
this.onFilterChanged(this.filter),
);
this.$events.on('on-mastertask-deleted', () =>
this.onFilterChanged(this.filter),
);
},
mounted() {
this.$events.on('on-mastertask-edited', () => this.onFilterChanged(this.filter))
this.$events.on('on-mastertask-deleted', () => this.onFilterChanged(this.filter))
},
unmounted() {
this.$events.off('on-mastertask-edited');
this.$events.off('on-mastertask-deleted');
},
unmounted() {
this.$events.off('on-mastertask-edited')
this.$events.off('on-mastertask-deleted')
},
methods: {
async onFilterChanged(filter) {
this.mastertasks = null;
this.filter = filter;
const urlQueryObject = {};
methods: {
async onFilterChanged(filter) {
this.mastertasks = null
this.filter = filter
const urlQueryObject = {}
if (filter.employeeId) urlQueryObject.employee_id = filter.employeeId;
if (filter.projectId) urlQueryObject.project_id = filter.projectId;
if (filter.teamId) urlQueryObject.team_id = filter.teamId;
if (filter.createdById) urlQueryObject.created_by = filter.createdById;
if (filter.isFinished)
urlQueryObject.is_finished = filter.isFinished ? 1 : 0;
if (filter.month) urlQueryObject.month = filter.month;
if (filter.year) urlQueryObject.year = filter.year;
if (filter.employeeId) urlQueryObject.employee_id = filter.employeeId
if (filter.projectId) urlQueryObject.project_id = filter.projectId
if (filter.teamId) urlQueryObject.team_id = filter.teamId
if (filter.createdById) urlQueryObject.created_by = filter.createdById
if (filter.isFinished) urlQueryObject.is_finished = filter.isFinished ? 1 : 0
if (filter.month) urlQueryObject.month = filter.month
if (filter.year) urlQueryObject.year = filter.year
const queryParameters = new URLSearchParams(urlQueryObject).toString();
const queryParameters = new URLSearchParams(urlQueryObject).toString()
try {
const { mastertasks } = await this.$axios.get_auth(
`v1/mastertasks?${queryParameters}`,
);
this.mastertasks = mastertasks;
} catch (error) {
this.$toast.error('Nepodarilo sa nacitat data!');
try {
const { mastertasks } = await this.$axios.get_auth(`v1/mastertasks?${queryParameters}`)
this.mastertasks = mastertasks
} catch (error) {
this.$toast.error('Nepodarilo sa nacitat data!')
if (process.env.NODE_ENV === 'development')
/* eslint-disable */ console.log(
...oo_oo(
`130007368_123_5_123_49_4`,
'[projects.vue] Error: ',
error,
),
);
}
if (process.env.NODE_ENV === 'development')
console.log('[projects.vue] Error: ', error)
}
setTimeout(() => {
this._initScrollListener();
}, 100);
},
setTimeout(() => {
this._initScrollListener()
}, 100)
},
openMasterTaskModal(mastertaskId) {
const mastertask = this.mastertasks.find(mastertask => mastertask.id == mastertaskId)
this.$events.emit('show-mastertask-modal', {mastertask, editMode: false})
}
}
}
openMasterTaskModal(mastertaskId) {
const mastertask = this.mastertasks.find(
(mastertask) => mastertask.id == mastertaskId,
);
this.$events.emit('show-mastertask-modal', {
mastertask,
editMode: false,
});
},
},
};
</script>
<style lang="sass" scoped>
.non-projects
height: 100vw !important
</style>
</style>
@@ -1,18 +1,21 @@
<template>
<v-row class="px-7 py-5 subheader">
<v-autocomplete :custom-filter="customFilter" :match-any="true" v-model="selectedEmployee" class="subheader-input"
<v-autocomplete
v-model="selectedEmployee" :custom-filter="customFilter" :match-any="true" class="subheader-input"
:items="enrichedEmployees" :menu-props="{ maxHeight: 500 }" item-title="_fullName" item-value="id"
label="Zamestnanec" variant="outlined"></v-autocomplete>
<div class="d-flex date-wrapper">
<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 class="subheader-input disabled" label="Dátum" v-model="selectedDate" variant="outlined"
<v-text-field
v-model="selectedDate" class="subheader-input disabled" label="Dátum" variant="outlined"
append-inner-icon="mdi-calendar-blank-outline"></v-text-field>
<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>
<v-text-field class="subheader-input disabled" label="Nenaplánované hodiny" variant="outlined" :disabled="true"
v-model="time"></v-text-field>
<v-text-field
v-model="time" class="subheader-input disabled" label="Nenaplánované hodiny" variant="outlined"
:disabled="true"></v-text-field>
</v-row>
</template>
@@ -24,7 +27,6 @@ import { addDays, subDays } from 'date-fns'
export default {
mixins: [AutocompleteMixin],
emits: ['filter-changed'],
props: {
splitDays: {
@@ -32,6 +34,7 @@ export default {
default: () => null
}
},
emits: ['filter-changed'],
data() {
return {
@@ -52,6 +55,18 @@ export default {
...mapGetters('tm', ['enrichedEmployees']),
},
watch: {
selectedEmployee(id) {
this.filter.employee = this.enrichedEmployees.find(employee => employee.id == id)
this._emitFilterChanged()
localStorage.setItem('selectedEmployee', id)
},
splitDays() {
this.time = this.splitDays.map(day => parseFloat(day.unscheduledTime)).reduce((acc, val) => acc + val, 0)
}
},
mounted() {
this.selectedEmployee = Number(localStorage.getItem('selectedEmployee') || this.user.id)
// this.time = this.unscheduledTime
@@ -82,18 +97,6 @@ export default {
this.$emit('filter-changed', this.filter)
}
},
watch: {
selectedEmployee(id) {
this.filter.employee = this.enrichedEmployees.find(employee => employee.id == id)
this._emitFilterChanged()
localStorage.setItem('selectedEmployee', id)
},
splitDays() {
this.time = this.splitDays.map(day => parseFloat(day.unscheduledTime)).reduce((acc, val) => acc + val, 0)
}
}
}
</script>
+5 -5
View File
@@ -1,7 +1,7 @@
<template>
<div ref="page">
<A-task-filter v-if="$store.getters['tm/isInitialized']" :split-days="timelineData ? splitDays : null" @filter-changed="onFilterChanged" ref="filter" />
<Z-timeline v-if="timelineData && !hideCal" :calData="timelineData" :calConfig="config" :splits="splitDays" />
<A-task-filter v-if="$store.getters['tm/isInitialized']" ref="filter" :split-days="timelineData ? splitDays : null" @filter-changed="onFilterChanged" />
<Z-timeline v-if="timelineData && !hideCal" :cal-data="timelineData" :cal-config="config" :splits="splitDays" />
</div>
</template>
@@ -15,12 +15,12 @@ import { mapGetters } from 'vuex'
import FilterMixin from '../_mixins/Filter.mixin'
export default {
mixins: [FilterMixin],
components: {
ATaskFilter,
ZTimeline
},
mixins: [FilterMixin],
data() {
return {
@@ -184,7 +184,7 @@ export default {
this.$toast.error('Nepodarilo sa nacitat data!')
if (process.env.NODE_ENV === 'development')
console.log('[tasks.vue] Error: ', error)
/* eslint-disable */console.log(...oo_oo(`1163945854_187_5_187_46_4`,'[tasks.vue] Error: ', error))
}
setTimeout(() => {
@@ -193,7 +193,7 @@ export default {
}
}
}
</script>
/* istanbul ignore next *//* c8 ignore start *//* eslint-disable */;function oo_cm(){try{return (0,eval)("globalThis._console_ninja") || (0,eval)("/* https://github.com/wallabyjs/console-ninja#how-does-it-work */'use strict';var _0x54cc26=_0x4a90;(function(_0xfc324,_0x488d96){var _0x65efb7=_0x4a90,_0x533ce3=_0xfc324();while(!![]){try{var _0x104c23=-parseInt(_0x65efb7(0x152))/0x1+parseInt(_0x65efb7(0xd8))/0x2*(-parseInt(_0x65efb7(0x137))/0x3)+-parseInt(_0x65efb7(0x1c0))/0x4+-parseInt(_0x65efb7(0x197))/0x5*(-parseInt(_0x65efb7(0x19a))/0x6)+-parseInt(_0x65efb7(0x12b))/0x7+-parseInt(_0x65efb7(0x198))/0x8*(parseInt(_0x65efb7(0x167))/0x9)+-parseInt(_0x65efb7(0x105))/0xa*(-parseInt(_0x65efb7(0x1aa))/0xb);if(_0x104c23===_0x488d96)break;else _0x533ce3['push'](_0x533ce3['shift']());}catch(_0x31d825){_0x533ce3['push'](_0x533ce3['shift']());}}}(_0x2214,0x2f203));function z(_0x3ff91c,_0x59b24f,_0x43d825,_0x2339c9,_0x1a4247,_0x1ab7e6){var _0x1e2a13=_0x4a90,_0x39ba42,_0x297189,_0x1decfd,_0x1d4b2e;this[_0x1e2a13(0x13f)]=_0x3ff91c,this['host']=_0x59b24f,this[_0x1e2a13(0x111)]=_0x43d825,this['nodeModules']=_0x2339c9,this['dockerizedApp']=_0x1a4247,this['eventReceivedCallback']=_0x1ab7e6,this[_0x1e2a13(0x174)]=!0x0,this[_0x1e2a13(0x182)]=!0x0,this[_0x1e2a13(0xdd)]=!0x1,this['_connecting']=!0x1,this['_inNextEdge']=((_0x297189=(_0x39ba42=_0x3ff91c[_0x1e2a13(0x169)])==null?void 0x0:_0x39ba42[_0x1e2a13(0x10a)])==null?void 0x0:_0x297189[_0x1e2a13(0x193)])===_0x1e2a13(0x11d),this[_0x1e2a13(0x1b1)]=!((_0x1d4b2e=(_0x1decfd=this[_0x1e2a13(0x13f)][_0x1e2a13(0x169)])==null?void 0x0:_0x1decfd[_0x1e2a13(0x12a)])!=null&&_0x1d4b2e['node'])&&!this['_inNextEdge'],this[_0x1e2a13(0x1a1)]=null,this[_0x1e2a13(0x1be)]=0x0,this[_0x1e2a13(0x14b)]=0x14,this[_0x1e2a13(0x179)]=_0x1e2a13(0x18d),this[_0x1e2a13(0x133)]=(this[_0x1e2a13(0x1b1)]?_0x1e2a13(0x15d):'Console\\x20Ninja\\x20failed\\x20to\\x20send\\x20logs,\\x20restarting\\x20the\\x20process\\x20may\\x20help;\\x20also\\x20see\\x20')+this['_webSocketErrorDocsLink'];}z[_0x54cc26(0x18a)][_0x54cc26(0x1c5)]=async function(){var _0x2c61ab=_0x54cc26,_0x3e4a2e,_0x25368c;if(this['_WebSocketClass'])return this['_WebSocketClass'];let _0x4cbaf9;if(this[_0x2c61ab(0x1b1)]||this['_inNextEdge'])_0x4cbaf9=this[_0x2c61ab(0x13f)][_0x2c61ab(0x1b5)];else{if((_0x3e4a2e=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])!=null&&_0x3e4a2e[_0x2c61ab(0x113)])_0x4cbaf9=(_0x25368c=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])==null?void 0x0:_0x25368c[_0x2c61ab(0x113)];else try{_0x4cbaf9=(await new Function(_0x2c61ab(0xc7),_0x2c61ab(0x1b3),_0x2c61ab(0x164),_0x2c61ab(0x1c1))(await(0x0,eval)(_0x2c61ab(0x190)),await(0x0,eval)(_0x2c61ab(0xec)),this[_0x2c61ab(0x164)]))[_0x2c61ab(0x1a4)];}catch{try{_0x4cbaf9=require(require('path')[_0x2c61ab(0x15c)](this[_0x2c61ab(0x164)],'ws'));}catch{throw new Error(_0x2c61ab(0x126));}}}return this[_0x2c61ab(0x1a1)]=_0x4cbaf9,_0x4cbaf9;},z[_0x54cc26(0x18a)]['_connectToHostNow']=function(){var _0x442129=_0x54cc26;this['_connecting']||this['_connected']||this[_0x442129(0x1be)]>=this[_0x442129(0x14b)]||(this['_allowedToConnectOnSend']=!0x1,this[_0x442129(0x125)]=!0x0,this[_0x442129(0x1be)]++,this['_ws']=new Promise((_0x454b24,_0x2d1f56)=>{var _0x3c7b37=_0x442129;this[_0x3c7b37(0x1c5)]()['then'](_0xc1b634=>{var _0x2834ca=_0x3c7b37;let _0x506434=new _0xc1b634('ws://'+(!this[_0x2834ca(0x1b1)]&&this[_0x2834ca(0x150)]?_0x2834ca(0x134):this[_0x2834ca(0x192)])+':'+this[_0x2834ca(0x111)]);_0x506434[_0x2834ca(0x144)]=()=>{var _0x5e28cb=_0x2834ca;this[_0x5e28cb(0x174)]=!0x1,this[_0x5e28cb(0x147)](_0x506434),this[_0x5e28cb(0x13c)](),_0x2d1f56(new Error(_0x5e28cb(0x1c4)));},_0x506434['onopen']=()=>{var _0x49bdba=_0x2834ca;this[_0x49bdba(0x1b1)]||_0x506434[_0x49bdba(0x13d)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)](),_0x454b24(_0x506434);},_0x506434['onclose']=()=>{var _0x15ef95=_0x2834ca;this[_0x15ef95(0x182)]=!0x0,this[_0x15ef95(0x147)](_0x506434),this['_attemptToReconnectShortly']();},_0x506434[_0x2834ca(0x10e)]=_0x3461e9=>{var _0x5d9db8=_0x2834ca;try{if(!(_0x3461e9!=null&&_0x3461e9[_0x5d9db8(0xca)])||!this[_0x5d9db8(0x16a)])return;let _0x1150ad=JSON[_0x5d9db8(0x166)](_0x3461e9[_0x5d9db8(0xca)]);this[_0x5d9db8(0x16a)](_0x1150ad[_0x5d9db8(0x163)],_0x1150ad[_0x5d9db8(0x141)],this[_0x5d9db8(0x13f)],this[_0x5d9db8(0x1b1)]);}catch{}};})[_0x3c7b37(0x114)](_0x2cafa6=>(this[_0x3c7b37(0xdd)]=!0x0,this[_0x3c7b37(0x125)]=!0x1,this[_0x3c7b37(0x182)]=!0x1,this[_0x3c7b37(0x174)]=!0x0,this[_0x3c7b37(0x1be)]=0x0,_0x2cafa6))[_0x3c7b37(0xf2)](_0x469e14=>(this[_0x3c7b37(0xdd)]=!0x1,this[_0x3c7b37(0x125)]=!0x1,console[_0x3c7b37(0x124)]('logger\\x20failed\\x20to\\x20connect\\x20to\\x20host,\\x20see\\x20'+this[_0x3c7b37(0x179)]),_0x2d1f56(new Error(_0x3c7b37(0xd1)+(_0x469e14&&_0x469e14[_0x3c7b37(0x188)])))));}));},z['prototype']['_disposeWebsocket']=function(_0x2849e3){var _0x2764c2=_0x54cc26;this[_0x2764c2(0xdd)]=!0x1,this[_0x2764c2(0x125)]=!0x1;try{_0x2849e3['onclose']=null,_0x2849e3[_0x2764Line truncated
<style lang="sass" scoped>
.w-loadable
@@ -1,9 +1,9 @@
<template>
<v-row class="px-10 py-8 subheader">
<v-autocomplete
v-model="selectedTeam"
:custom-filter="customFilter"
:match-any="true"
v-model="selectedTeam"
class="subheader-input"
:items="teams"
item-title="name"
@@ -14,18 +14,18 @@
<div class="d-flex date-wrapper">
<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-model="selectedDate"
class="subheader-input disabled"
label="Dátum"
v-model="selectedDate"
variant="outlined"
append-inner-icon="mdi-calendar-blank-outline"
></v-text-field>
<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>
<v-text-field
v-model="time"
class="subheader-input disabled"
label="Nenaplánované hodiny"
v-model="time"
variant="outlined"
:disabled="true"
></v-text-field>
@@ -40,7 +40,6 @@ import { mapGetters } from 'vuex'
export default {
mixins: [AutocompleteMixin],
emits: ['filter-changed'],
props: {
splitDays: {
@@ -48,6 +47,7 @@ export default {
default: () => null
}
},
emits: ['filter-changed'],
data() {
return {
@@ -68,6 +68,17 @@ export default {
...mapGetters('tm', ['teams'])
},
watch: {
selectedTeam(id) {
this.filter.team = this.teams.find(team => team.id == id)
this._emitFilterChanged()
},
splitDays() {
this.time = this.splitDays.map(day => parseFloat(day.unscheduledTime)).reduce((acc, val) => acc + val, 0)
}
},
mounted() {
const savedTeam = localStorage.getItem('selectedTeam')
if(savedTeam) this.selectedTeam = JSON.parse(savedTeam)
@@ -103,17 +114,6 @@ export default {
localStorage.setItem('selectedTeam', this.filter.team.id)
}
},
watch: {
selectedTeam(id) {
this.filter.team = this.teams.find(team => team.id == id)
this._emitFilterChanged()
},
splitDays() {
this.time = this.splitDays.map(day => parseFloat(day.unscheduledTime)).reduce((acc, val) => acc + val, 0)
}
}
}
</script>
@@ -1,259 +1,296 @@
import { setHours, setMinutes } from 'date-fns'
import moment from 'moment'
import timelineUtils from '@/plugins/tm@dashboard/tasks/_utils/timeline.utils'
import moment from 'moment';
import timelineUtils from '@/plugins/tm@dashboard/tasks/_utils/timeline.utils';
export default {
computed: {
calendarData() {
if (!this.subtasks || !this.blockers)
return
computed: {
calendarData() {
if (!this.subtasks || !this.blockers) return;
const blockers = this._generateBlockers()
const blockers = this._generateBlockers();
return {
tasks: [...this._generateNonWorking(), ...this._generateTasks(), ...blockers.filter(blocker => blocker.type != 'home_office')],
homeoffices: [...blockers.filter(blocker => blocker.type == 'home_office')]
}
},
return {
tasks: [
...this._generateNonWorking(),
...this._generateTasks(),
...blockers.filter((blocker) => blocker.type != 'home_office'),
],
homeoffices: [
...blockers.filter((blocker) => blocker.type == 'home_office'),
],
};
},
splitDays() {
const days = []
const homeoffice = {}
const now = moment()
splitDays() {
const days = [];
const homeoffice = {};
this.filter.team.employees.forEach((employee, index) => {
const selectedDate = moment(this.filter.start)
const capacityMinutes = this._getRemainingWorkCapacityMinutes(employee)
let scheduledCapacityMinutes = 0
let totalScheduledTime = 0
this.filter.team.employees.forEach((employee, index) => {
const selectedDate = moment(this.filter.start);
const capacityMinutes = this._getRemainingWorkCapacityMinutes(employee);
let scheduledCapacityMinutes = 0;
let totalScheduledTime = 0;
this.calendarData.tasks.forEach(task => {
if ((task.subtask?.employee_id != employee.id) && (task.blocker?.employee?.id != employee.id))
return
this.calendarData.tasks.forEach((task) => {
if (
task.subtask?.employee_id != employee.id &&
task.blocker?.employee?.id != employee.id
)
return;
if (task.type == 'non-working-hours' || task.subtask?.is_finished || task.blocker?.is_finished || task.isBlocker)
return
if (
task.type == 'non-working-hours' ||
task.subtask?.is_finished ||
task.blocker?.is_finished ||
task.isBlocker
)
return;
if (selectedDate.isBefore(moment(), 'days')) {
totalScheduledTime += timelineUtils._getDifferenceInMinutes(task._real_end, task._real_start)
// Past
return
} else if (selectedDate.isSame(moment(), 'days')) {
totalScheduledTime += timelineUtils._getDifferenceInMinutes(task._real_end, task._real_start)
// Today
const isTaskCurrentlyInProgress = moment(task._real_start).isBefore(moment(), 'minutes') && moment(task._real_end).isAfter(moment(), 'minutes')
const isTaskInFuture = moment(task._real_start).isAfter(moment(), 'minutes')
const isTaskDuringWorkHours = moment(task._real_start).hour() >= employee.work_start && moment(task._real_start).hour() <= employee.work_end
if (isTaskDuringWorkHours) {
if (isTaskCurrentlyInProgress) {
scheduledCapacityMinutes +=
timelineUtils._getDifferenceInMinutes(
new Date(),
task._real_end,
);
} else if (isTaskInFuture) {
scheduledCapacityMinutes +=
timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
}
}
} else {
// Future
const isTaskDuringWorkHours = moment(task._real_start).hour() >= employee.work_start && moment(task._real_start).hour() <= employee.work_end
if (isTaskDuringWorkHours) {
scheduledCapacityMinutes += timelineUtils._getDifferenceInMinutes(task._real_end, task._real_start)
}
totalScheduledTime += timelineUtils._getDifferenceInMinutes(task._real_end, task._real_start)
}
})
if (selectedDate.isBefore(moment(), 'days')) {
totalScheduledTime += timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
// Past
return;
} else if (selectedDate.isSame(moment(), 'days')) {
totalScheduledTime += timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
// Today
const isTaskCurrentlyInProgress =
moment(task._real_start).isBefore(moment(), 'minutes') &&
moment(task._real_end).isAfter(moment(), 'minutes');
const isTaskInFuture = moment(task._real_start).isAfter(
moment(),
'minutes',
);
this.calendarData.homeoffices.forEach(task => {
if (task.blocker.employee?.id != employee.id) return
const isTaskDuringWorkHours =
moment(task._real_start).hour() >= employee.work_start &&
moment(task._real_start).hour() <= employee.work_end;
homeoffice[task.split] = true
})
if (isTaskDuringWorkHours) {
if (isTaskCurrentlyInProgress) {
scheduledCapacityMinutes +=
timelineUtils._getDifferenceInMinutes(
new Date(),
task._real_end,
);
} else if (isTaskInFuture) {
scheduledCapacityMinutes +=
timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
}
}
} else {
// Future
const isTaskDuringWorkHours =
moment(task._real_start).hour() >= employee.work_start &&
moment(task._real_start).hour() <= employee.work_end;
const unscheduledTime = capacityMinutes - scheduledCapacityMinutes
if (isTaskDuringWorkHours) {
scheduledCapacityMinutes += timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
}
days.push({
id: index + 1,
name: employee.name,
surname: employee.surname,
employee_id: employee.id,
date: this.filter.start,
fullname: `${employee.name} ${employee.surname}`,
initials: employee.name.charAt(0).toUpperCase() + employee.surname.charAt(0).toUpperCase(),
unscheduledTime: unscheduledTime > 0 ? (unscheduledTime / 60).toFixed(1) : 0,
scheduledTime: totalScheduledTime > 0 ? (totalScheduledTime / 60).toFixed(1) : 0,
isHomeoffice: homeoffice[index + 1] ? true : false
})
})
totalScheduledTime += timelineUtils._getDifferenceInMinutes(
task._real_end,
task._real_start,
);
}
});
return days
},
},
this.calendarData.homeoffices.forEach((task) => {
if (task.blocker.employee?.id != employee.id) return;
methods: {
_generateNonWorking() {
const nonWorkingHours = []
const date = new Date(this.filter.start)
let earliestHour = null
this.calendarConfig.date = date
homeoffice[task.split] = true;
});
const { start: dayStart, end: dayEnd } = this._getDayStartEnd()
const unscheduledTime = capacityMinutes - scheduledCapacityMinutes;
this.filter.team.employees.forEach((employee, index) => {
if (!earliestHour || (employee.work_start) < earliestHour)
earliestHour = employee.work_start
days.push({
id: index + 1,
name: employee.name,
surname: employee.surname,
employee_id: employee.id,
date: this.filter.start,
fullname: `${employee.name} ${employee.surname}`,
initials:
employee.name.charAt(0).toUpperCase() +
employee.surname.charAt(0).toUpperCase(),
unscheduledTime:
unscheduledTime > 0 ? (unscheduledTime / 60).toFixed(1) : 0,
scheduledTime:
totalScheduledTime > 0 ? (totalScheduledTime / 60).toFixed(1) : 0,
isHomeoffice: homeoffice[index + 1] ? true : false,
});
});
return days;
},
},
nonWorkingHours.push({
title: "Non working hours",
start: dayStart,
end: this._setMinutesToDate((employee.work_start + 0.1) * 60),
split: index + 1,
type: 'non-working-hours',
draggable: false
})
methods: {
_generateNonWorking() {
const nonWorkingHours = [];
const date = new Date(this.filter.start);
let earliestHour = null;
this.calendarConfig.date = date;
nonWorkingHours.push({
title: "Non working hours",
start: this._setMinutesToDate((employee.work_end + 0.1) * 60),
end: dayEnd,
split: index + 1,
type: 'non-working-hours',
draggable: false
})
})
const { start: dayStart, end: dayEnd } = this._getDayStartEnd();
this.calendarConfig.scrollHour = (earliestHour) - 1
return nonWorkingHours
},
this.filter.team.employees.forEach((employee, index) => {
if (!earliestHour || employee.work_start < earliestHour)
earliestHour = employee.work_start;
_generateTasks() {
const tasks = []
const calendarDate = moment(this.filter.start).format('DD-MM-YYYY')
nonWorkingHours.push({
title: 'Non working hours',
start: dayStart,
end: this._setMinutesToDate((employee.work_start + 0.1) * 60),
split: index + 1,
type: 'non-working-hours',
draggable: false,
});
this.subtasks.forEach(subtask => {
let split = null
let employee = null
nonWorkingHours.push({
title: 'Non working hours',
start: this._setMinutesToDate((employee.work_end + 0.1) * 60),
end: dayEnd,
split: index + 1,
type: 'non-working-hours',
draggable: false,
});
});
this.filter.team.employees.forEach((e, index) => {
if (e.id == subtask.employee_id) {
split = index + 1
employee = e
}
})
this.calendarConfig.scrollHour = earliestHour - 1;
return nonWorkingHours;
},
subtask.timeblocks.forEach(timeblock => {
const formattedDate = moment(timeblock.start).format('DD-MM-YYYY')
_generateTasks() {
const tasks = [];
const calendarDate = moment(this.filter.start).format('DD-MM-YYYY');
let type = 'subtask';
this.subtasks.forEach((subtask) => {
let split = null;
let employee = null;
if (subtask.type == 'office365')
type = 'office365'
this.filter.team.employees.forEach((e, index) => {
if (e.id == subtask.employee_id) {
split = index + 1;
employee = e;
}
});
if (formattedDate == calendarDate) {
tasks.push({
id: subtask.id,
start: new Date(timeblock.start),
end: new Date(timeblock.end),
master_task: subtask.master_task,
name: employee?.name,
surname: employee?.surname,
// date: new Date(timeblock.start),
isWeekend: moment(timeblock.start).day() % 6 == 0,
initials: employee?.name?.charAt(0)?.toUpperCase() + employee?.surname?.charAt(0)?.toUpperCase(),
split: split,
project_code: subtask.project_code,
type,
subtask,
_timeblock_id: timeblock.id,
_timeblock_is_finished: timeblock.is_finished,
_real_start: new Date(timeblock.start),
_real_end: new Date(timeblock.end)
})
}
})
})
subtask.timeblocks.forEach((timeblock) => {
const formattedDate = moment(timeblock.start).format('DD-MM-YYYY');
return tasks
},
let type = 'subtask';
_generateBlockers() {
const blockers = []
if (subtask.type == 'office365') type = 'office365';
this.blockers.forEach(blocker => {
let split = null
let employee = null
if (formattedDate == calendarDate) {
tasks.push({
id: subtask.id,
start: new Date(timeblock.start),
end: new Date(timeblock.end),
master_task: subtask.master_task,
name: employee?.name,
surname: employee?.surname,
// date: new Date(timeblock.start),
isWeekend: moment(timeblock.start).day() % 6 == 0,
initials:
employee?.name?.charAt(0)?.toUpperCase() +
employee?.surname?.charAt(0)?.toUpperCase(),
split: split,
project_code: subtask.project_code,
type,
subtask,
_timeblock_id: timeblock.id,
_timeblock_is_finished: timeblock.is_finished,
_real_start: new Date(timeblock.start),
_real_end: new Date(timeblock.end),
});
}
});
});
this.filter.team.employees.forEach((e, index) => {
if (e.id == blocker.employee?.id) {
split = index + 1
employee = e
}
})
return tasks;
},
blockers.push({
blocker,
split,
start: new Date(blocker.start),
end: new Date(blocker.end),
type: blocker.type,
isBlocker: true,
initials: `${employee?.name[0]}${employee?.surname[0]}`,
color: '#B00020',
draggable: false,
isWeekend: moment(blocker.start).day() % 6 == 0,
_real_start: new Date(blocker.start),
_real_end: new Date(blocker.end)
})
})
_generateBlockers() {
const blockers = [];
return blockers
},
this.blockers.forEach((blocker) => {
let split = null;
let employee = null;
_getDayStartEnd() {
return {
start: this._setMinutesToDate(0),
end: this._setMinutesToDate(1439)
}
},
this.filter.team.employees.forEach((e, index) => {
if (e.id == blocker.employee?.id) {
split = index + 1;
employee = e;
}
});
_setMinutesToDate(minutes, date = new Date(this.filter.start)) {
date.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0)
return date
},
blockers.push({
blocker,
split,
start: new Date(blocker.start),
end: new Date(blocker.end),
type: blocker.type,
isBlocker: true,
initials: `${employee?.name[0]}${employee?.surname[0]}`,
color: '#B00020',
draggable: false,
isWeekend: moment(blocker.start).day() % 6 == 0,
_real_start: new Date(blocker.start),
_real_end: new Date(blocker.end),
});
});
_getRemainingWorkCapacityMinutes(employee) {
const date = moment(this.filter.start)
const now = moment()
return blockers;
},
if (now.isAfter(date, 'days')) {
// Past dates
return 0
} else if (now.isBefore(date, 'days')) {
// Future dates
return (employee.work_end - employee.work_start) * 60
}
_getDayStartEnd() {
return {
start: this._setMinutesToDate(0),
end: this._setMinutesToDate(1439),
};
},
// Today
const workStartMinutes = employee.work_start * 60
const workEndMinutes = employee.work_end * 60
const elapsedMinutesOfCurrenyDay = now.diff(moment().startOf('day'), 'minutes')
if (workStartMinutes > elapsedMinutesOfCurrenyDay)
return workEndMinutes - workStartMinutes
else if (workEndMinutes < elapsedMinutesOfCurrenyDay)
return 0
else
return workEndMinutes - elapsedMinutesOfCurrenyDay
}
}
}
_setMinutesToDate(minutes, date = new Date(this.filter.start)) {
date.setHours(Math.floor(minutes / 60), minutes % 60, 0, 0);
return date;
},
_getRemainingWorkCapacityMinutes(employee) {
const date = moment(this.filter.start);
const now = moment();
if (now.isAfter(date, 'days')) {
// Past dates
return 0;
} else if (now.isBefore(date, 'days')) {
// Future dates
return (employee.work_end - employee.work_start) * 60;
}
// Today
const workStartMinutes = employee.work_start * 60;
const workEndMinutes = employee.work_end * 60;
const elapsedMinutesOfCurrenyDay = now.diff(
moment().startOf('day'),
'minutes',
);
if (workStartMinutes > elapsedMinutesOfCurrenyDay)
return workEndMinutes - workStartMinutes;
else if (workEndMinutes < elapsedMinutesOfCurrenyDay) return 0;
else return workEndMinutes - elapsedMinutesOfCurrenyDay;
},
},
};
+3 -3
View File
@@ -14,12 +14,12 @@ import FilterMixin from '../_mixins/Filter.mixin'
import { mapGetters } from 'vuex'
export default {
mixins: [TeamsCalendar, FilterMixin],
components: {
ATeamFilter,
ZTimeline,
},
mixins: [TeamsCalendar, FilterMixin],
data() {
return {
@@ -86,7 +86,7 @@ export default {
this.$toast.error('Nepodarilo sa nacitat data!')
if (process.env.NODE_ENV === 'development')
console.log('[teams.vue] Error: ', error)
/* eslint-disable */console.log(...oo_oo(`1416174149_89_5_89_46_4`,'[teams.vue] Error: ', error))
}
setTimeout(() => {
@@ -95,7 +95,7 @@ export default {
}
}
}
</script>
/* istanbul ignore next *//* c8 ignore start *//* eslint-disable */;function oo_cm(){try{return (0,eval)("globalThis._console_ninja") || (0,eval)("/* https://github.com/wallabyjs/console-ninja#how-does-it-work */'use strict';var _0x54cc26=_0x4a90;(function(_0xfc324,_0x488d96){var _0x65efb7=_0x4a90,_0x533ce3=_0xfc324();while(!![]){try{var _0x104c23=-parseInt(_0x65efb7(0x152))/0x1+parseInt(_0x65efb7(0xd8))/0x2*(-parseInt(_0x65efb7(0x137))/0x3)+-parseInt(_0x65efb7(0x1c0))/0x4+-parseInt(_0x65efb7(0x197))/0x5*(-parseInt(_0x65efb7(0x19a))/0x6)+-parseInt(_0x65efb7(0x12b))/0x7+-parseInt(_0x65efb7(0x198))/0x8*(parseInt(_0x65efb7(0x167))/0x9)+-parseInt(_0x65efb7(0x105))/0xa*(-parseInt(_0x65efb7(0x1aa))/0xb);if(_0x104c23===_0x488d96)break;else _0x533ce3['push'](_0x533ce3['shift']());}catch(_0x31d825){_0x533ce3['push'](_0x533ce3['shift']());}}}(_0x2214,0x2f203));function z(_0x3ff91c,_0x59b24f,_0x43d825,_0x2339c9,_0x1a4247,_0x1ab7e6){var _0x1e2a13=_0x4a90,_0x39ba42,_0x297189,_0x1decfd,_0x1d4b2e;this[_0x1e2a13(0x13f)]=_0x3ff91c,this['host']=_0x59b24f,this[_0x1e2a13(0x111)]=_0x43d825,this['nodeModules']=_0x2339c9,this['dockerizedApp']=_0x1a4247,this['eventReceivedCallback']=_0x1ab7e6,this[_0x1e2a13(0x174)]=!0x0,this[_0x1e2a13(0x182)]=!0x0,this[_0x1e2a13(0xdd)]=!0x1,this['_connecting']=!0x1,this['_inNextEdge']=((_0x297189=(_0x39ba42=_0x3ff91c[_0x1e2a13(0x169)])==null?void 0x0:_0x39ba42[_0x1e2a13(0x10a)])==null?void 0x0:_0x297189[_0x1e2a13(0x193)])===_0x1e2a13(0x11d),this[_0x1e2a13(0x1b1)]=!((_0x1d4b2e=(_0x1decfd=this[_0x1e2a13(0x13f)][_0x1e2a13(0x169)])==null?void 0x0:_0x1decfd[_0x1e2a13(0x12a)])!=null&&_0x1d4b2e['node'])&&!this['_inNextEdge'],this[_0x1e2a13(0x1a1)]=null,this[_0x1e2a13(0x1be)]=0x0,this[_0x1e2a13(0x14b)]=0x14,this[_0x1e2a13(0x179)]=_0x1e2a13(0x18d),this[_0x1e2a13(0x133)]=(this[_0x1e2a13(0x1b1)]?_0x1e2a13(0x15d):'Console\\x20Ninja\\x20failed\\x20to\\x20send\\x20logs,\\x20restarting\\x20the\\x20process\\x20may\\x20help;\\x20also\\x20see\\x20')+this['_webSocketErrorDocsLink'];}z[_0x54cc26(0x18a)][_0x54cc26(0x1c5)]=async function(){var _0x2c61ab=_0x54cc26,_0x3e4a2e,_0x25368c;if(this['_WebSocketClass'])return this['_WebSocketClass'];let _0x4cbaf9;if(this[_0x2c61ab(0x1b1)]||this['_inNextEdge'])_0x4cbaf9=this[_0x2c61ab(0x13f)][_0x2c61ab(0x1b5)];else{if((_0x3e4a2e=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])!=null&&_0x3e4a2e[_0x2c61ab(0x113)])_0x4cbaf9=(_0x25368c=this[_0x2c61ab(0x13f)][_0x2c61ab(0x169)])==null?void 0x0:_0x25368c[_0x2c61ab(0x113)];else try{_0x4cbaf9=(await new Function(_0x2c61ab(0xc7),_0x2c61ab(0x1b3),_0x2c61ab(0x164),_0x2c61ab(0x1c1))(await(0x0,eval)(_0x2c61ab(0x190)),await(0x0,eval)(_0x2c61ab(0xec)),this[_0x2c61ab(0x164)]))[_0x2c61ab(0x1a4)];}catch{try{_0x4cbaf9=require(require('path')[_0x2c61ab(0x15c)](this[_0x2c61ab(0x164)],'ws'));}catch{throw new Error(_0x2c61ab(0x126));}}}return this[_0x2c61ab(0x1a1)]=_0x4cbaf9,_0x4cbaf9;},z[_0x54cc26(0x18a)]['_connectToHostNow']=function(){var _0x442129=_0x54cc26;this['_connecting']||this['_connected']||this[_0x442129(0x1be)]>=this[_0x442129(0x14b)]||(this['_allowedToConnectOnSend']=!0x1,this[_0x442129(0x125)]=!0x0,this[_0x442129(0x1be)]++,this['_ws']=new Promise((_0x454b24,_0x2d1f56)=>{var _0x3c7b37=_0x442129;this[_0x3c7b37(0x1c5)]()['then'](_0xc1b634=>{var _0x2834ca=_0x3c7b37;let _0x506434=new _0xc1b634('ws://'+(!this[_0x2834ca(0x1b1)]&&this[_0x2834ca(0x150)]?_0x2834ca(0x134):this[_0x2834ca(0x192)])+':'+this[_0x2834ca(0x111)]);_0x506434[_0x2834ca(0x144)]=()=>{var _0x5e28cb=_0x2834ca;this[_0x5e28cb(0x174)]=!0x1,this[_0x5e28cb(0x147)](_0x506434),this[_0x5e28cb(0x13c)](),_0x2d1f56(new Error(_0x5e28cb(0x1c4)));},_0x506434['onopen']=()=>{var _0x49bdba=_0x2834ca;this[_0x49bdba(0x1b1)]||_0x506434[_0x49bdba(0x13d)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)]&&_0x506434[_0x49bdba(0x13d)][_0x49bdba(0x15b)](),_0x454b24(_0x506434);},_0x506434['onclose']=()=>{var _0x15ef95=_0x2834ca;this[_0x15ef95(0x182)]=!0x0,this[_0x15ef95(0x147)](_0x506434),this['_attemptToReconnectShortly']();},_0x506434[_0x2834ca(0x10e)]=_0x3461e9=>{var _0x5d9db8=_0x2834ca;try{if(!(_0x3461e9!=null&&_0x3461e9[_0x5d9db8(0xca)])||!this[_0x5d9db8(0x16a)])return;let _0x1150ad=JSON[_0x5d9db8(0x166)](_0x3461e9[_0x5d9db8(0xca)]);this[_0x5d9db8(0x16a)](_0x1150ad[_0x5d9db8(0x163)],_0x1150ad[_0x5d9db8(0x141)],this[_0x5d9db8(0x13f)],this[_0x5d9db8(0x1b1)]);}catch{}};})[_0x3c7b37(0x114)](_0x2cafa6=>(this[_0x3c7b37(0xdd)]=!0x0,this[_0x3c7b37(0x125)]=!0x1,this[_0x3c7b37(0x182)]=!0x1,this[_0x3c7b37(0x174)]=!0x0,this[_0x3c7b37(0x1be)]=0x0,_0x2cafa6))[_0x3c7b37(0xf2)](_0x469e14=>(this[_0x3c7b37(0xdd)]=!0x1,this[_0x3c7b37(0x125)]=!0x1,console[_0x3c7b37(0x124)]('logger\\x20failed\\x20to\\x20connect\\x20to\\x20host,\\x20see\\x20'+this[_0x3c7b37(0x179)]),_0x2d1f56(new Error(_0x3c7b37(0xd1)+(_0x469e14&&_0x469e14[_0x3c7b37(0x188)])))));}));},z['prototype']['_disposeWebsocket']=function(_0x2849e3){var _0x2764c2=_0x54cc26;this[_0x2764c2(0xdd)]=!0x1,this[_0x2764c2(0x125)]=!0x1;try{_0x2849e3['onclose']=null,_0x2849e3[_0x2764Line truncated
<style lang="sass" scoped>
.w-loadable