diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-04 18:12:14 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-10-04 18:12:14 +0300 |
commit | e9ab4187093f05b873b32045295eeb580c97cdce (patch) | |
tree | 74f41f843e6addc0e17d4da877366f90e7f2fc68 /app/assets | |
parent | 0327ce54a7e315b3aa6f80cc4e540fbb6792f2e3 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets')
8 files changed, 310 insertions, 6 deletions
diff --git a/app/assets/javascripts/api/bulk_imports_api.js b/app/assets/javascripts/api/bulk_imports_api.js new file mode 100644 index 00000000000..d636cfdff0b --- /dev/null +++ b/app/assets/javascripts/api/bulk_imports_api.js @@ -0,0 +1,7 @@ +import { buildApiUrl } from '~/api/api_utils'; +import axios from '~/lib/utils/axios_utils'; + +const BULK_IMPORT_ENTITIES_PATH = '/api/:version/bulk_imports/entities'; + +export const getBulkImportsHistory = (params) => + axios.get(buildApiUrl(BULK_IMPORT_ENTITIES_PATH), { params }); diff --git a/app/assets/javascripts/import_entities/components/pagination_bar.vue b/app/assets/javascripts/import_entities/components/pagination_bar.vue new file mode 100644 index 00000000000..33bd3e08bb1 --- /dev/null +++ b/app/assets/javascripts/import_entities/components/pagination_bar.vue @@ -0,0 +1,90 @@ +<script> +import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui'; +import { __ } from '~/locale'; +import PaginationLinks from '~/vue_shared/components/pagination_links.vue'; + +const DEFAULT_PAGE_SIZES = [20, 50, 100]; + +export default { + components: { + PaginationLinks, + GlDropdown, + GlDropdownItem, + GlIcon, + GlSprintf, + }, + props: { + pageInfo: { + required: true, + type: Object, + }, + pageSizes: { + required: false, + type: Array, + default: () => DEFAULT_PAGE_SIZES, + }, + itemsCount: { + required: true, + type: Number, + }, + }, + + computed: { + humanizedTotal() { + return this.pageInfo.total >= 1000 ? __('1000+') : this.pageInfo.total; + }, + + paginationInfo() { + const { page, perPage } = this.pageInfo; + const start = (page - 1) * perPage + 1; + const end = start + this.itemsCount - 1; + + return { start, end }; + }, + }, + + methods: { + setPage(page) { + this.$emit('set-page', page); + }, + }, +}; +</script> + +<template> + <div class="gl-display-flex gl-align-items-center"> + <pagination-links :change="setPage" :page-info="pageInfo" class="gl-m-0" /> + <gl-dropdown category="tertiary" class="gl-ml-auto"> + <template #button-content> + <span class="gl-font-weight-bold"> + <gl-sprintf :message="__('%{count} items per page')"> + <template #count> + {{ pageInfo.perPage }} + </template> + </gl-sprintf> + </span> + <gl-icon class="gl-button-icon dropdown-chevron" name="chevron-down" /> + </template> + <gl-dropdown-item v-for="size in pageSizes" :key="size" @click="$emit('set-page-size', size)"> + <gl-sprintf :message="__('%{count} items per page')"> + <template #count> + {{ size }} + </template> + </gl-sprintf> + </gl-dropdown-item> + </gl-dropdown> + <div class="gl-ml-2" data-testid="information"> + <gl-sprintf :message="s__('BulkImport|Showing %{start}-%{end} of %{total}')"> + <template #start> + {{ paginationInfo.start }} + </template> + <template #end> + {{ paginationInfo.end }} + </template> + <template #total> + {{ humanizedTotal }} + </template> + </gl-sprintf> + </div> + </div> +</template> diff --git a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/usage_statistics.js b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/usage_statistics.js index 4c312a008cb..68849857d0f 100644 --- a/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/usage_statistics.js +++ b/app/assets/javascripts/pages/admin/application_settings/metrics_and_profiling/usage_statistics.js @@ -1,7 +1,7 @@ import { __ } from '~/locale'; export const HELPER_TEXT_SERVICE_PING_DISABLED = __( - 'To enable Registration Features, make sure "Enable service ping" is checked.', + 'To enable Registration Features, first enable Service Ping.', ); export const HELPER_TEXT_SERVICE_PING_ENABLED = __( diff --git a/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue new file mode 100644 index 00000000000..ec3cf4a8a92 --- /dev/null +++ b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue @@ -0,0 +1,176 @@ +<script> +import { GlButton, GlEmptyState, GlLink, GlLoadingIcon, GlTable } from '@gitlab/ui'; + +import { s__, __ } from '~/locale'; +import createFlash from '~/flash'; +import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils'; +import { joinPaths } from '~/lib/utils/url_utility'; +import { getBulkImportsHistory } from '~/rest_api'; +import ImportStatus from '~/import_entities/components/import_status.vue'; +import PaginationBar from '~/import_entities/components/pagination_bar.vue'; +import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue'; + +import { DEFAULT_ERROR } from '../utils/error_messages'; + +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, + GlLink, + GlLoadingIcon, + GlTable, + PaginationBar, + ImportStatus, + TimeAgo, + }, + + data() { + return { + loading: true, + historyItems: [], + paginationConfig: { + page: 1, + perPage: DEFAULT_PER_PAGE, + }, + pageInfo: {}, + }; + }, + + fields: [ + tableCell({ + key: 'source_full_path', + label: s__('BulkImport|Source group'), + thClass: `${DEFAULT_TH_CLASSES} gl-w-30p`, + }), + tableCell({ + key: 'destination_name', + label: s__('BulkImport|New group'), + 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 getBulkImportsHistory({ + 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; + } + }, + + getDestinationUrl({ destination_name: name, destination_namespace: namespace }) { + return [namespace, name].filter(Boolean).join('/'); + }, + + getFullDestinationUrl(params) { + return joinPaths(gon.relative_url_root || '', this.getDestinationUrl(params)); + }, + }, + + gitlabLogo: window.gon.gitlab_logo, +}; +</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="$options.gitlabLogo" class="gl-w-6 gl-h-6 gl-mb-2 gl-display-inline gl-mr-2" /> + {{ s__('BulkImport|Group 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 groups 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(destination_name)="{ item }"> + <gl-link :href="getFullDestinationUrl(item)" target="_blank"> + {{ getDestinationUrl(item) }} + </gl-link> + </template> + <template #cell(created_at)="{ value }"> + <time-ago :time="value" /> + </template> + <template #cell(status)="{ value, item, toggleDetails, detailsShowing }"> + <import-status :status="value" class="gl-display-inline-block gl-w-13" /> + <gl-button + v-if="item.failures.length" + class="gl-ml-3" + :selected="detailsShowing" + @click="toggleDetails" + >{{ __('Details') }}</gl-button + > + </template> + <template #row-details="{ item }"> + <pre>{{ item.failures }}</pre> + </template> + </gl-table> + <pagination-bar + :page-info="pageInfo" + :items-count="historyItems.length" + class="gl-m-0 gl-mt-3" + @set-page="paginationConfig.page = $event" + @set-page-size="paginationConfig.perPage = $event" + /> + </template> + </div> +</template> diff --git a/app/assets/javascripts/pages/import/bulk_imports/history/index.js b/app/assets/javascripts/pages/import/bulk_imports/history/index.js new file mode 100644 index 00000000000..5a67aa99baa --- /dev/null +++ b/app/assets/javascripts/pages/import/bulk_imports/history/index.js @@ -0,0 +1,15 @@ +import Vue from 'vue'; +import BulkImportHistoryApp from './components/bulk_imports_history_app.vue'; + +function mountImportHistoryApp(mountElement) { + if (!mountElement) return undefined; + + return new Vue({ + el: mountElement, + render(createElement) { + return createElement(BulkImportHistoryApp); + }, + }); +} + +mountImportHistoryApp(document.querySelector('#import-history-mount-element')); diff --git a/app/assets/javascripts/pages/import/bulk_imports/history/utils/error_messages.js b/app/assets/javascripts/pages/import/bulk_imports/history/utils/error_messages.js new file mode 100644 index 00000000000..24669e22ade --- /dev/null +++ b/app/assets/javascripts/pages/import/bulk_imports/history/utils/error_messages.js @@ -0,0 +1,3 @@ +import { __ } from '~/locale'; + +export const DEFAULT_ERROR = __('Something went wrong on our end.'); diff --git a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue index 7fd63acbede..ed30198244f 100644 --- a/app/assets/javascripts/performance_bar/components/performance_bar_app.vue +++ b/app/assets/javascripts/performance_bar/components/performance_bar_app.vue @@ -124,9 +124,6 @@ export default { const fileName = this.requests[0].truncatedUrl; return `${fileName}_perf_bar_${Date.now()}.json`; }, - flamegraphPath() { - return mergeUrlParams({ performance_bar: 'flamegraph' }, window.location.href); - }, }, mounted() { this.currentRequest = this.requestId; @@ -135,6 +132,12 @@ export default { changeCurrentRequest(newRequestId) { this.currentRequest = newRequestId; }, + flamegraphPath(mode) { + return mergeUrlParams( + { performance_bar: 'flamegraph', stackprof_mode: mode }, + window.location.href, + ); + }, }, safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] }, }; @@ -180,8 +183,17 @@ export default { }}</a> </div> <div v-if="currentRequest.details" id="peek-flamegraph" class="view"> - <a class="gl-text-blue-200" :href="flamegraphPath">{{ - s__('PerformanceBar|Flamegraph') + <span class="gl-text-white-200">{{ s__('PerformanceBar|Flamegraph with mode:') }}</span> + <a class="gl-text-blue-200" :href="flamegraphPath('wall')">{{ + s__('PerformanceBar|wall') + }}</a> + / + <a class="gl-text-blue-200" :href="flamegraphPath('cpu')">{{ + s__('PerformanceBar|cpu') + }}</a> + / + <a class="gl-text-blue-200" :href="flamegraphPath('object')">{{ + s__('PerformanceBar|object') }}</a> </div> <a v-if="statsUrl" class="gl-text-blue-200 view" :href="statsUrl">{{ diff --git a/app/assets/javascripts/rest_api.js b/app/assets/javascripts/rest_api.js index 61fe89f4f7e..29642b6633f 100644 --- a/app/assets/javascripts/rest_api.js +++ b/app/assets/javascripts/rest_api.js @@ -2,6 +2,7 @@ export * from './api/groups_api'; export * from './api/projects_api'; export * from './api/user_api'; export * from './api/markdown_api'; +export * from './api/bulk_imports_api'; // Note: It's not possible to spy on methods imported from this file in // Jest tests. |