summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pages/import/history/components/import_history_app.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pages/import/history/components/import_history_app.vue')
-rw-r--r--app/assets/javascripts/pages/import/history/components/import_history_app.vue199
1 files changed, 199 insertions, 0 deletions
diff --git a/app/assets/javascripts/pages/import/history/components/import_history_app.vue b/app/assets/javascripts/pages/import/history/components/import_history_app.vue
new file mode 100644
index 00000000000..557e25f66e2
--- /dev/null
+++ b/app/assets/javascripts/pages/import/history/components/import_history_app.vue
@@ -0,0 +1,199 @@
+<script>
+import { GlButton, GlEmptyState, GlIcon, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui';
+import { s__, __ } from '~/locale';
+import createFlash from '~/flash';
+import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
+import { getProjects } from '~/rest_api';
+import ImportStatus from '~/import_entities/components/import_status.vue';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
+import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { DEFAULT_ERROR } from '../utils/error_messages';
+import ImportErrorDetails from './import_error_details.vue';
+
+const DEFAULT_PER_PAGE = 20;
+const DEFAULT_TH_CLASSES =
+ 'gl-bg-transparent! gl-border-b-solid! gl-border-b-gray-200! gl-border-b-1! gl-p-5!';
+
+const tableCell = (config) => ({
+ thClass: DEFAULT_TH_CLASSES,
+ tdClass: (value, key, item) => {
+ return {
+ // eslint-disable-next-line no-underscore-dangle
+ 'gl-border-b-0!': item._showDetails,
+ };
+ },
+ ...config,
+});
+
+export default {
+ components: {
+ GlButton,
+ GlEmptyState,
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ GlTable,
+ PaginationBar,
+ ImportStatus,
+ ImportErrorDetails,
+ TimeAgo,
+ },
+
+ inject: ['assets'],
+
+ data() {
+ return {
+ loading: true,
+ historyItems: [],
+ paginationConfig: {
+ page: 1,
+ perPage: DEFAULT_PER_PAGE,
+ },
+ pageInfo: {},
+ };
+ },
+
+ fields: [
+ tableCell({
+ key: 'source',
+ label: s__('BulkImport|Source'),
+ thClass: `${DEFAULT_TH_CLASSES} gl-w-30p`,
+ }),
+ tableCell({
+ key: 'destination',
+ label: s__('BulkImport|Destination'),
+ thClass: `${DEFAULT_TH_CLASSES} gl-w-40p`,
+ }),
+ tableCell({
+ key: 'created_at',
+ label: __('Date'),
+ }),
+ tableCell({
+ key: 'status',
+ label: __('Status'),
+ tdAttr: { 'data-qa-selector': 'import_status_indicator' },
+ }),
+ ],
+
+ computed: {
+ hasHistoryItems() {
+ return this.historyItems.length > 0;
+ },
+ },
+
+ watch: {
+ paginationConfig: {
+ handler() {
+ this.loadHistoryItems();
+ },
+ deep: true,
+ immediate: true,
+ },
+ },
+
+ methods: {
+ async loadHistoryItems() {
+ try {
+ this.loading = true;
+ const { data: historyItems, headers } = await getProjects(undefined, {
+ imported: true,
+ simple: false,
+ page: this.paginationConfig.page,
+ per_page: this.paginationConfig.perPage,
+ });
+ this.pageInfo = parseIntPagination(normalizeHeaders(headers));
+ this.historyItems = historyItems;
+ } catch (e) {
+ createFlash({ message: DEFAULT_ERROR, captureError: true, error: e });
+ } finally {
+ this.loading = false;
+ }
+ },
+
+ hasHttpProtocol(url) {
+ try {
+ const parsedUrl = new URL(url);
+ return ['http:', 'https:'].includes(parsedUrl.protocol);
+ } catch (e) {
+ return false;
+ }
+ },
+
+ setPageSize(size) {
+ this.paginationConfig.perPage = size;
+ this.paginationConfig.page = 1;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div
+ class="gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-display-flex gl-align-items-center"
+ >
+ <h1 class="gl-my-0 gl-py-4 gl-font-size-h1">
+ <img :src="assets.gitlabLogo" class="gl-w-6 gl-h-6 gl-mb-2 gl-display-inline gl-mr-2" />
+ {{ s__('BulkImport|Project import history') }}
+ </h1>
+ </div>
+ <gl-loading-icon v-if="loading" size="md" class="gl-mt-5" />
+ <gl-empty-state
+ v-else-if="!hasHistoryItems"
+ :title="s__('BulkImport|No history is available')"
+ :description="s__('BulkImport|Your imported projects will appear here.')"
+ />
+ <template v-else>
+ <gl-table
+ :fields="$options.fields"
+ :items="historyItems"
+ data-qa-selector="import_history_table"
+ class="gl-w-full"
+ >
+ <template #cell(source)="{ item }">
+ <template v-if="item.import_url">
+ <gl-link
+ v-if="hasHttpProtocol(item.import_url)"
+ :href="item.import_url"
+ target="_blank"
+ >
+ {{ item.import_url }}
+ <gl-icon name="external-link" class="gl-vertical-align-middle" />
+ </gl-link>
+ <span v-else>{{ item.import_url }}</span>
+ </template>
+ <span v-else>{{
+ s__('BulkImport|Template / File-based import / GitLab Migration')
+ }}</span>
+ </template>
+ <template #cell(destination)="{ item }">
+ <gl-link :href="item.http_url_to_repo">
+ {{ item.path_with_namespace }}
+ </gl-link>
+ </template>
+ <template #cell(created_at)="{ value }">
+ <time-ago :time="value" />
+ </template>
+ <template #cell(status)="{ item, toggleDetails, detailsShowing }">
+ <import-status :status="item.import_status" class="gl-display-inline-block gl-w-13" />
+ <gl-button
+ v-if="item.import_status === 'failed'"
+ class="gl-ml-3"
+ :selected="detailsShowing"
+ @click="toggleDetails"
+ >{{ __('Details') }}</gl-button
+ >
+ </template>
+ <template #row-details="{ item }">
+ <import-error-details :id="item.id" />
+ </template>
+ </gl-table>
+ <pagination-bar
+ :page-info="pageInfo"
+ class="gl-m-0 gl-mt-3"
+ @set-page="paginationConfig.page = $event"
+ @set-page-size="setPageSize"
+ />
+ </template>
+ </div>
+</template>