Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-14 09:09:22 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-14 09:09:22 +0300
commit067b3d04573d1473dbc6c81ef775d70c6636ff3f (patch)
treee05bfa986e49c1527fa93f03b2592f0c1a3da735 /app/assets/javascripts/sidebar
parentef9eff8e7e1b38f48a354f90ecaeeb67da35b08c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/sidebar')
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/graphql/cache_update.js20
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/graphql/mutations/delete_timelog.mutation.graphql5
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/report.vue90
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue1
4 files changed, 106 insertions, 10 deletions
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/graphql/cache_update.js b/app/assets/javascripts/sidebar/components/time_tracking/graphql/cache_update.js
new file mode 100644
index 00000000000..70177d84b1b
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/time_tracking/graphql/cache_update.js
@@ -0,0 +1,20 @@
+import produce from 'immer';
+
+export function removeTimelogFromStore(store, deletedTimelogId, query, variables) {
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ draftData.issuable.timelogs.nodes = draftData.issuable.timelogs.nodes.filter(
+ ({ id }) => id !== deletedTimelogId,
+ );
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+}
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/graphql/mutations/delete_timelog.mutation.graphql b/app/assets/javascripts/sidebar/components/time_tracking/graphql/mutations/delete_timelog.mutation.graphql
new file mode 100644
index 00000000000..17bbad1acb1
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/time_tracking/graphql/mutations/delete_timelog.mutation.graphql
@@ -0,0 +1,5 @@
+mutation deleteTimelog($input: TimelogDeleteInput!) {
+ timelogDelete(input: $input) {
+ errors
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
index b4c4c31bd7a..79ef5a32474 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue
@@ -1,11 +1,13 @@
<script>
-import { GlLoadingIcon, GlTableLite } from '@gitlab/ui';
+import { GlLoadingIcon, GlTableLite, GlButton, GlTooltipDirective } from '@gitlab/ui';
import createFlash from '~/flash';
import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { formatDate, parseSeconds, stringifyTime } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
+import { __, s__ } from '~/locale';
import { timelogQueries } from '~/sidebar/constants';
+import deleteTimelogMutation from './graphql/mutations/delete_timelog.mutation.graphql';
+import { removeTimelogFromStore } from './graphql/cache_update';
const TIME_DATE_FORMAT = 'mmmm d, yyyy, HH:MM ("UTC:" o)';
@@ -13,6 +15,10 @@ export default {
components: {
GlLoadingIcon,
GlTableLite,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
},
inject: ['issuableType'],
props: {
@@ -27,7 +33,7 @@ export default {
},
},
data() {
- return { report: [], isLoading: true };
+ return { report: [], isLoading: true, removingIds: [] };
},
apollo: {
report: {
@@ -35,9 +41,7 @@ export default {
return timelogQueries[this.issuableType].query;
},
variables() {
- return {
- id: convertToGraphQLId(this.getGraphQLEntityType(), this.issuableId),
- };
+ return this.getQueryVariables();
},
update(data) {
this.isLoading = false;
@@ -48,10 +52,23 @@ export default {
},
},
},
+ computed: {
+ deleteButtonTooltip() {
+ return s__('TimeTracking|Delete time spent');
+ },
+ },
methods: {
+ isDeletingTimelog(timelogId) {
+ return this.removingIds.includes(timelogId);
+ },
isIssue() {
return this.issuableType === 'issue';
},
+ getQueryVariables() {
+ return {
+ id: convertToGraphQLId(this.getGraphQLEntityType(), this.issuableId),
+ };
+ },
getGraphQLEntityType() {
return this.isIssue() ? TYPE_ISSUE : TYPE_MERGE_REQUEST;
},
@@ -76,12 +93,44 @@ export default {
stringifyTime(parseSeconds(seconds, { limitToHours: this.limitToHours }))
);
},
+ deleteTimelog(timelogId) {
+ this.removingIds.push(timelogId);
+ this.$apollo
+ .mutate({
+ mutation: deleteTimelogMutation,
+ variables: { input: { id: timelogId } },
+ update: (store) => {
+ removeTimelogFromStore(
+ store,
+ timelogId,
+ timelogQueries[this.issuableType].query,
+ this.getQueryVariables(),
+ );
+ },
+ })
+ .then(({ data }) => {
+ if (data.timelogDelete?.errors?.length) {
+ throw new Error(data.timelogDelete.errors[0]);
+ }
+ })
+ .catch((error) => {
+ createFlash({
+ message: s__('TimeTracking|An error occurred while removing the timelog.'),
+ captureError: true,
+ error,
+ });
+ })
+ .finally(() => {
+ this.removingIds.splice(this.removingIds.indexOf(timelogId), 1);
+ });
+ },
},
fields: [
- { key: 'spentAt', label: __('Spent At'), sortable: true, tdClass: 'gl-w-quarter' },
+ { key: 'spentAt', label: __('Spent at'), sortable: true, tdClass: 'gl-w-quarter' },
{ key: 'user', label: __('User'), sortable: true },
- { key: 'timeSpent', label: __('Time Spent'), sortable: true, tdClass: 'gl-w-15' },
- { key: 'summary', label: __('Summary / Note'), sortable: true },
+ { key: 'timeSpent', label: __('Time spent'), sortable: true, tdClass: 'gl-w-15' },
+ { key: 'summary', label: __('Summary / note'), sortable: true },
+ { key: 'actions', label: '', tdClass: 'gl-w-10' },
],
};
</script>
@@ -110,7 +159,28 @@ export default {
<template #cell(summary)="{ item: { summary, note } }">
<div>{{ getSummary(summary, note) }}</div>
</template>
- <template #foot(note)>&nbsp;</template>
+ <template #foot(summary)>&nbsp;</template>
+
+ <template
+ #cell(actions)="{
+ item: {
+ id,
+ userPermissions: { adminTimelog },
+ },
+ }"
+ >
+ <div v-if="adminTimelog">
+ <gl-button
+ v-gl-tooltip="{ title: deleteButtonTooltip }"
+ category="secondary"
+ icon="remove"
+ data-testid="deleteButton"
+ :loading="isDeletingTimelog(id)"
+ @click="deleteTimelog(id)"
+ />
+ </div>
+ </template>
+ <template #foot(actions)>&nbsp;</template>
</gl-table-lite>
</div>
</template>
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index 057bb9f0100..e39d9f9fb49 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -252,6 +252,7 @@ export default {
size="lg"
:title="__('Time tracking report')"
:hide-footer="true"
+ @hide="refresh"
>
<time-tracking-report :limit-to-hours="limitToHours" :issuable-id="issuableId" />
</gl-modal>