Read about our upcoming Code of Conduct on this issue

collapsible_container.vue 4.14 KB
Newer Older
Filipa Lacerda's avatar
Filipa Lacerda committed
1
<script>
2
import { mapActions, mapGetters } from 'vuex';
3
4
5
6
7
8
9
10
import {
  GlLoadingIcon,
  GlButton,
  GlTooltipDirective,
  GlModal,
  GlModalDirective,
  GlEmptyState,
} from '@gitlab/ui';
11
12
13
14
import createFlash from '~/flash';
import Tracking from '~/tracking';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import Icon from '~/vue_shared/components/icon.vue';
15
import TableRegistry from './table_registry.vue';
16
17
import { DELETE_REPO_ERROR_MESSAGE } from '../constants';
import { __ } from '~/locale';
18

19
20
21
export default {
  name: 'CollapsibeContainerRegisty',
  components: {
22
23
    ClipboardButton,
    TableRegistry,
24
    GlLoadingIcon,
Filipa Lacerda's avatar
Filipa Lacerda committed
25
26
    GlButton,
    Icon,
27
    GlModal,
28
    GlEmptyState,
29
30
  },
  directives: {
Filipa Lacerda's avatar
Filipa Lacerda committed
31
    GlTooltip: GlTooltipDirective,
32
    GlModal: GlModalDirective,
33
  },
34
  mixins: [Tracking.mixin()],
35
36
37
38
  props: {
    repo: {
      type: Object,
      required: true,
39
    },
40
41
42
43
  },
  data() {
    return {
      isOpen: false,
44
      modalId: `confirm-repo-deletion-modal-${this.repo.id}`,
45
46
47
      tracking: {
        label: 'registry_repository_delete',
      },
48
49
    };
  },
Filipa Lacerda's avatar
Filipa Lacerda committed
50
  computed: {
51
    ...mapGetters(['isDeleteDisabled']),
Filipa Lacerda's avatar
Filipa Lacerda committed
52
53
54
    iconName() {
      return this.isOpen ? 'angle-up' : 'angle-right';
    },
55
56
57
    canDeleteRepo() {
      return this.repo.canDelete && !this.isDeleteDisabled;
    },
Filipa Lacerda's avatar
Filipa Lacerda committed
58
  },
59
  methods: {
60
    ...mapActions(['fetchRepos', 'fetchList', 'deleteItem']),
61
62
    toggleRepo() {
      this.isOpen = !this.isOpen;
63

64
      if (this.isOpen) {
Filipa Lacerda's avatar
Filipa Lacerda committed
65
        this.fetchList({ repo: this.repo });
66
67
68
      }
    },
    handleDeleteRepository() {
69
      this.track('confirm_delete');
70
      return this.deleteItem(this.repo)
71
        .then(() => {
72
          createFlash(__('This container registry has been scheduled for deletion.'), 'notice');
73
74
          this.fetchRepos();
        })
75
        .catch(() => createFlash(DELETE_REPO_ERROR_MESSAGE));
76
    },
77
78
  },
};
Filipa Lacerda's avatar
Filipa Lacerda committed
79
80
81
82
</script>

<template>
  <div class="container-image">
Filipa Lacerda's avatar
Filipa Lacerda committed
83
    <div class="container-image-head">
Filipa Lacerda's avatar
Filipa Lacerda committed
84
      <gl-button class="js-toggle-repo btn-link align-baseline" @click="toggleRepo">
85
86
        <icon :name="iconName" />
        {{ repo.name }}
Filipa Lacerda's avatar
Filipa Lacerda committed
87
      </gl-button>
88

89
90
      <clipboard-button
        v-if="repo.location"
91
        :text="repo.location"
92
        :title="repo.location"
93
        css-class="btn-default btn-transparent btn-clipboard"
Filipa Lacerda's avatar
Filipa Lacerda committed
94
      />
95

Clement Ho's avatar
Clement Ho committed
96
      <div class="controls d-none d-sm-block float-right">
Filipa Lacerda's avatar
Filipa Lacerda committed
97
        <gl-button
98
          v-if="canDeleteRepo"
Filipa Lacerda's avatar
Filipa Lacerda committed
99
          v-gl-tooltip
100
          v-gl-modal="modalId"
Filipa Lacerda's avatar
Filipa Lacerda committed
101
102
          :title="s__('ContainerRegistry|Remove repository')"
          :aria-label="s__('ContainerRegistry|Remove repository')"
103
          class="js-remove-repo btn-inverted"
Filipa Lacerda's avatar
Filipa Lacerda committed
104
          variant="danger"
105
          @click="track('click_button')"
Filipa Lacerda's avatar
Filipa Lacerda committed
106
        >
Filipa Lacerda's avatar
Filipa Lacerda committed
107
108
          <icon name="remove" />
        </gl-button>
109
      </div>
110
    </div>
111

112
    <gl-loading-icon v-if="repo.isLoading" size="md" class="append-bottom-20" />
113

Mike Greiling's avatar
Mike Greiling committed
114
    <div v-else-if="!repo.isLoading && isOpen" class="container-image-tags">
115
      <table-registry v-if="repo.list.length" :repo="repo" :can-delete-repo="canDeleteRepo" />
116
117
118
119
120
121
122
123
124
125
126
127
      <gl-empty-state
        v-else
        :title="s__('ContainerRegistry|This image has no active tags')"
        :description="
          s__(
            `ContainerRegistry|The last tag related to this image was recently removed.
            This empty image and any associated data will be automatically removed as part of the regular Garbage Collection process.
            If you have any questions, contact your administrator.`,
          )
        "
        class="mx-auto my-0"
      />
128
    </div>
129
130
131
132
133
    <gl-modal
      ref="deleteModal"
      :modal-id="modalId"
      ok-variant="danger"
      @ok="handleDeleteRepository"
134
      @cancel="track('cancel_delete')"
135
    >
136
137
138
139
140
141
142
143
144
145
146
147
148
      <template v-slot:modal-title>{{ s__('ContainerRegistry|Remove repository') }}</template>
      <p
        v-html="
          sprintf(
            s__(
              'ContainerRegistry|You are about to remove repository <b>%{title}</b>. Once you confirm, this repository will be permanently deleted.',
            ),
            { title: repo.name },
          )
        "
      ></p>
      <template v-slot:modal-ok>{{ __('Remove') }}</template>
    </gl-modal>
Filipa Lacerda's avatar
Filipa Lacerda committed
149
150
  </div>
</template>