debian-mirror-gitlab/app/assets/javascripts/time_tracking/components/timelogs_app.vue
2023-06-20 00:43:36 +05:30

229 lines
5.9 KiB
Vue

<script>
import * as Sentry from '@sentry/browser';
import {
GlButton,
GlFormGroup,
GlFormInput,
GlLoadingIcon,
GlKeysetPagination,
GlDatepicker,
} from '@gitlab/ui';
import { createAlert } from '~/alert';
import { formatTimeSpent } from '~/lib/utils/datetime_utility';
import { s__ } from '~/locale';
import getTimelogsQuery from './queries/get_timelogs.query.graphql';
import TimelogsTable from './timelogs_table.vue';
const ENTRIES_PER_PAGE = 20;
// Define initial dates to current date and time
const INITIAL_TO_DATE = new Date();
const INITIAL_FROM_DATE = new Date();
// Set the initial 'from' date to 30 days before the current date
INITIAL_FROM_DATE.setDate(INITIAL_TO_DATE.getDate() - 30);
export default {
components: {
GlButton,
GlFormGroup,
GlFormInput,
GlLoadingIcon,
GlKeysetPagination,
GlDatepicker,
TimelogsTable,
},
props: {
limitToHours: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
projectId: null,
groupId: null,
username: null,
timeSpentFrom: INITIAL_FROM_DATE,
timeSpentTo: INITIAL_TO_DATE,
cursor: {
first: ENTRIES_PER_PAGE,
after: null,
last: null,
before: null,
},
queryVariables: {
startDate: INITIAL_FROM_DATE,
endDate: INITIAL_TO_DATE,
projectId: null,
groupId: null,
username: null,
},
pageInfo: {},
report: [],
totalSpentTime: 0,
};
},
apollo: {
report: {
query: getTimelogsQuery,
variables() {
return {
...this.queryVariables,
...this.cursor,
};
},
update({ timelogs: { nodes = [], pageInfo = {}, totalSpentTime = 0 } = {} }) {
this.pageInfo = pageInfo;
this.totalSpentTime = totalSpentTime;
return nodes;
},
error(error) {
createAlert({ message: s__('TimeTrackingReport|Something went wrong. Please try again.') });
Sentry.captureException(error);
},
},
},
computed: {
isLoading() {
return this.$apollo.queries.report.loading;
},
showPagination() {
return this.pageInfo?.hasPreviousPage || this.pageInfo?.hasNextPage;
},
formattedTotalSpentTime() {
return formatTimeSpent(this.totalSpentTime, this.limitToHours);
},
},
methods: {
nullIfBlank(value) {
return value === '' ? null : value;
},
runReport() {
this.cursor = {
first: ENTRIES_PER_PAGE,
after: null,
last: null,
before: null,
};
this.queryVariables = {
startDate: this.nullIfBlank(this.timeSpentFrom),
endDate: this.nullIfBlank(this.timeSpentTo),
projectId: this.nullIfBlank(this.projectId),
groupId: this.nullIfBlank(this.groupId),
username: this.nullIfBlank(this.username),
};
},
nextPage(item) {
this.cursor = {
first: ENTRIES_PER_PAGE,
after: item,
last: null,
before: null,
};
},
prevPage(item) {
this.cursor = {
first: null,
after: null,
last: ENTRIES_PER_PAGE,
before: item,
};
},
clearTimeSpentFromDate() {
this.timeSpentFrom = null;
},
clearTimeSpentToDate() {
this.timeSpentTo = null;
},
},
i18n: {
username: s__('TimeTrackingReport|Username'),
from: s__('TimeTrackingReport|From'),
to: s__('TimeTrackingReport|To'),
runReport: s__('TimeTrackingReport|Run report'),
totalTimeSpentText: s__('TimeTrackingReport|Total time spent: '),
},
};
</script>
<template>
<div class="gl-display-flex gl-flex-direction-column gl-gap-5 gl-mt-5">
<form
class="gl-display-flex gl-flex-direction-column gl-md-flex-direction-row gl-gap-3"
@submit.prevent="runReport"
>
<gl-form-group
:label="$options.i18n.username"
label-for="timelog-form-username"
class="gl-mb-0 gl-md-form-input-md gl-w-full"
>
<gl-form-input
id="timelog-form-username"
v-model="username"
data-testid="form-username"
class="gl-w-full"
/>
</gl-form-group>
<gl-form-group
key="time-spent-from"
:label="$options.i18n.from"
class="gl-mb-0 gl-md-form-input-md gl-w-full"
>
<gl-datepicker
v-model="timeSpentFrom"
:target="null"
show-clear-button
autocomplete="off"
data-testid="form-from-date"
class="gl-max-w-full!"
@clear="clearTimeSpentFromDate"
/>
</gl-form-group>
<gl-form-group
key="time-spent-to"
:label="$options.i18n.to"
class="gl-mb-0 gl-md-form-input-md gl-w-full"
>
<gl-datepicker
v-model="timeSpentTo"
:target="null"
show-clear-button
autocomplete="off"
data-testid="form-to-date"
class="gl-max-w-full!"
@clear="clearTimeSpentToDate"
/>
</gl-form-group>
<gl-button
class="gl-align-self-end gl-w-full gl-md-w-auto"
variant="confirm"
@click="runReport"
>{{ $options.i18n.runReport }}</gl-button
>
</form>
<div
v-if="!isLoading"
data-testid="table-container"
class="gl-display-flex gl-flex-direction-column"
>
<div v-if="report.length" class="gl-display-flex gl-gap-2 gl-border-t gl-py-4">
<span class="gl-font-weight-bold">{{ $options.i18n.totalTimeSpentText }}</span>
<span data-testid="total-time-spent-container">{{ formattedTotalSpentTime }}</span>
</div>
<timelogs-table :limit-to-hours="limitToHours" :entries="report" />
<gl-keyset-pagination
v-if="showPagination"
v-bind="pageInfo"
class="gl-mt-3 gl-align-self-center"
@prev="prevPage"
@next="nextPage"
/>
</div>
<gl-loading-icon v-else size="lg" class="gl-mt-5" />
</div>
</template>