![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/ts.corals.io/frontend/components/TimesheetCalender/ |
<template> <div> <div class="mb-5"> <div class="d-md-block d-none"> <c-overlay :show="showLoader"> <b-card no-body class="card-overflow mb-1"> <b-card-header header-tag="header"> <div class="row no-gutters"> <div class="col-md-3"></div> <div class="col-md-9 d-flex"> <div v-for="(day,index) in getDays" :key="'day_'+index" class="week-day"> {{ day.short_name }} {{ (day.title).split(', ')[1] }} </div> </div> </div> </b-card-header> <b-card-body> <template v-if="weekDays.length" v-for="(row,index) in weekDays"> <div class="row no-gutters"> <div class="col-md-3"> <a href="#" v-if="row.showDeleteAction" @click.prevent="removeRow(index)" class="text-danger clear-item-btn"> <fa icon="times"/> </a> <strong class="d-block">{{ row.client_name }} - {{ row.project }}</strong> <small class="d-block" v-if="$isAdmin()">{{ row.user }}</small> <small>{{ row.activity }}</small> </div> <div class="col-md-9 d-flex"> <div v-for="(day_times,date) in row.weekRowEntries" class="week-day"> <div v-for="(day_time,indexDay) in day_times" class="d-flex justify-content-around align-items-center"> <vue-timepicker v-model="day_time.time" class="d-block p-1" input-class="form-control" hour-label="Hours" minute-label="Minutes" format="HH:mm" :minute-interval="5" drop-direction="auto" input-width="100px" advanced-keyboard manual-input close-on-complete placeholder="HH:MM"/> <a :id="`description_${index}-${date}-${indexDay}`"> <fa v-if="!day_time.description" :icon="['far','sticky-note']" :class="(day_time.time.HH || day_time.time.mm) ? 'text-danger' : 'text-success'"/> <fa v-else icon="sticky-note" class="text-success"/> </a> <b-popover :target="`description_${index}-${date}-${indexDay}`" placement="bottomright"> <div class="d-flex"> <corals-textarea :form="form" field="" label="Description" v-model="day_time.description" required/> <a href="#" @click.prevent="closeDescription" class="text-danger "> <fa icon="times"/> </a> </div> </b-popover> </div> </div> </div> </div> <hr/> </template> <template v-if="!weekDays.length"> <div class="p-5"> <h4 class="text-center"> No Entries yet! </h4> </div> </template> </b-card-body> </b-card> </c-overlay> </div> <div class="d-md-none d-block"> <hr/> <div v-for="(day,indexD) in getDays"> <div> <strong>{{ day.title }}</strong> <hr style="width:50%;text-align:left;margin-left:0;"/> </div> <template v-if="weekDays.length" v-for="(row,indexW) in weekDays"> <div class="row"> <div class="col-7"> <a href="#" v-if="row.showDeleteAction" @click.prevent="removeRow(indexW)" class="text-danger clear-item-btn"> <fa icon="times"/> </a> <div> <strong class="d-block">{{ row.client_name }} - {{ row.project }}</strong> <small class="d-block" v-if="$isAdmin()">{{ row.user }}</small> <small>{{ row.activity }}</small> </div> </div> <div class="col-5"> <div v-for="(day_time,indexDay) in row.weekRowEntries[day.date]" class="d-flex justify-content-around align-items-center"> <vue-timepicker v-model="day_time.time" class="d-block p-1" input-class="form-control" hour-label="Hours" minute-label="Minutes" format="HH:mm" :minute-interval="5" drop-direction="auto" input-width="100px" advanced-keyboard manual-input close-on-complete placeholder="HH:MM"/> <a :id="`description_${indexD}-${indexW}-${day_time.date}-${indexDay}`"> <fa v-if="!day_time.description" :icon="['far','sticky-note']" :class="(day_time.time.HH || day_time.time.mm) ? 'text-danger' : 'text-success'"/> <fa v-else icon="sticky-note" class="text-success"/> </a> <b-popover :target="`description_${indexD}-${indexW}-${day_time.date}-${indexDay}`" placement="bottomleft"> <div class="d-flex"> <corals-textarea :form="form" field="" label="Description" v-model="day_time.description" required/> <a href="#" @click.prevent="closeDescription" class="text-danger "> <fa icon="times"/> </a> </div> </b-popover> </div> </div> </div> <hr/> </template> </div> </div> <div class="row mt-3"> <div class="col-md-12"> <button :disabled="weekDays.length === 0" class="btn btn-success" @click.prevent="saveWeek"> <fa icon="save"/> Save </button> </div> </div> </div> <template v-if="showCreateRowModal"> <b-modal hide-footer visible content-class="shadow" :title-html="modalTitle" @hidden="onModalHidden" no-close-on-backdrop :id="rowModalId" size="md"> <div class="row"> <div class="col-md-12"> <c-overlay :show="!form.isReady"> <div class="row"> <div class="col-md-10"> <corals-select :form="form" required label="Project" field="project_id" :options="getProjectOptions" @input="loadProjectRelatedFormData(form.project_id)"/> <corals-select :form="form" required label="Activity" field="activity_id" :options="getActivitiesOptions"/> <corals-select v-if="$isAdmin()" :form="form" label="User" field="user_id" :options="getUsersOptions" required/> </div> </div> <div class="text-right"> <button type="submit" class="btn btn-sm btn-primary" @click.prevent="submitRow" :disabled="!form.isReady"> {{ modalTitle }} </button> <button @click.prevent="$bvModal.hide(rowModalId)" class="btn btn-sm btn-secondary" :disabled="!form.isReady">Close </button> </div> </c-overlay> </div> </div> </b-modal> </template> </div> </template> <script> import COverlay from "@/components/layout/COverlay"; import CoralsSelect from "@/components/CoralsForm/CoralsSelect"; import VueTimepicker from 'vue2-timepicker'; export default { name: "week", inject: ['fetchNewWeek', 'removeRowWeek', 'onModalHidden'], components: {COverlay, CoralsSelect, VueTimepicker}, props: { showLoader: { required: true }, days: { required: true }, weekDays: { required: true }, showCreateRowModal: { required: true, }, }, data() { return { active_options: 1, modalTitle: 'Create row', rowModalId: 'row-modal', activities: [], users: [], form: this.$form({ activity_id: '', project_id: '', user_id: this.$auth.user.id }, {fetchFormDataURL: 'timesheet/entries/get-form-data', model: 'entry'}) } }, mounted() { }, methods: { getActivitiesOrProjectsOptions(arrayData) { let resultsData = []; let DataGroups = []; let activeObjects = []; if (!this.active_options) { activeObjects = arrayData.filter((object => object['group'] !== true)); DataGroups = arrayData.filter((group => group['group'] === true)); } else { activeObjects = arrayData.filter((object => (object['is_active'] === 1 || object['status'] === 'active') && object['group'] !== true)); DataGroups = arrayData.filter((group => group['group'] === true && group['status'] === 'active')); } DataGroups.forEach(group => { group['is_group_empty'] = true; resultsData.push(group); activeObjects.filter(activeObject => { if (group['code'] === activeObject['group']) { group['is_group_empty'] = false; resultsData.push(activeObject); } }); }); return resultsData; }, loadProjectRelatedFormData(project_id) { if (!project_id) { this.activities = [] this.users = [] return; } this.form.isReady = false; let url = `timesheet/entries/get-form-data?project_id=${project_id}`; this.$axios.get(url).then(({data: response}) => { this.activities = response.data.activities this.users = response.data.users }).finally(() => { this.form.isReady = true; }); }, submitRow() { let daysTimes = {}; for (let i = 0; i < this.days.length; i++) { let time = { HH: '', mm: '' } let day = this.days[i].date; daysTimes[day] = [{'entryId': '', 'date': this.days[i].date, 'time': time, 'description': ''}]; } let project = (this.form.getFormData('projects')).filter((project) => { return project.value === this.form.project_id }); let activity = this.getActivitiesOptions.filter((activity) => { return activity.value === this.form.activity_id }); let user = this.getUsersOptions.filter((user) => { return user.id === this.form.user_id }); let record = { 'activity_id': this.form.activity_id, 'activity': activity[0].label, 'project_id': this.form.project_id, 'project': project[0].label, 'user_id': this.form.user_id, 'user': (user[0].label).split(', ')[0], 'showDeleteAction': true, 'weekRowEntries': daysTimes, }; this.weekDays.push(record) this.$bvModal.hide(this.rowModalId); }, removeRow(rowIndex) { let result = []; this.weekDays.forEach((arr, index) => { if (index != rowIndex) { result.push(arr); } }); this.removeRowWeek(result); }, saveWeek() { let week = this.weekDays; let selectedDate = this.$route.query.date; let invalid_data = false; week.forEach((arr) => { for (let day in arr.weekRowEntries) { arr.weekRowEntries[day].forEach((entry) => { if (!entry.description && (entry.time.HH || entry.time.mm)) { invalid_data = true; } }) } }); if (invalid_data) { this.$toast.error('Please make sure the entries description set'); } else { this.$axios.post(`timesheet/timesheet-calender/save-week`, { week: week }).then(response => { this.fetchNewWeek(selectedDate); this.$toast.success(response.data.message); }) .catch(err => { console.error(err); }); } }, closeDescription() { this.$root.$emit('bv::hide::popover'); }, }, watch: {}, computed: { getDays() { return this.days; }, getProjectOptions() { return this.getActivitiesOrProjectsOptions(this.form.getFormData('projects')); }, getActivitiesOptions() { let activities = this.activities.length ? this.activities : this.form.getFormData('activities'); return this.getActivitiesOrProjectsOptions(activities); }, getUsersOptions() { let users = this.users.length ? this.users : this.form.getFormData('users'); if (!this.active_options) { return users } return users.filter(user => (user['status'] === 'active')); }, }, } </script> <style scoped> .week-day { width: 130px; } .clear-item-btn { position: absolute; top: 0; left: -15px; } @media (max-width: 768px) { .clear-item-btn { top: -15px; left: 5px; } } </style>