diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 18:44:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-19 18:44:42 +0300 |
commit | 4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch) | |
tree | 5423a1c7516cffe36384133ade12572cf709398d /app/assets/javascripts/admin | |
parent | e570267f2f6b326480d284e0164a6464ba4081bc (diff) |
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'app/assets/javascripts/admin')
10 files changed, 111 insertions, 111 deletions
diff --git a/app/assets/javascripts/admin/users/components/actions/delete.vue b/app/assets/javascripts/admin/users/components/actions/delete.vue index 725d3dbf388..6f4f272154a 100644 --- a/app/assets/javascripts/admin/users/components/actions/delete.vue +++ b/app/assets/javascripts/admin/users/components/actions/delete.vue @@ -14,12 +14,22 @@ export default { type: Object, required: true, }, + oncallSchedules: { + type: Array, + required: false, + default: () => [], + }, }, }; </script> <template> - <shared-delete-action modal-type="delete" :username="username" :paths="paths"> + <shared-delete-action + modal-type="delete" + :username="username" + :paths="paths" + :oncall-schedules="oncallSchedules" + > <slot></slot> </shared-delete-action> </template> diff --git a/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue b/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue index 0ae15bfbebb..82b09c04ab2 100644 --- a/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue +++ b/app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue @@ -14,12 +14,22 @@ export default { type: Object, required: true, }, + oncallSchedules: { + type: Array, + required: false, + default: () => [], + }, }, }; </script> <template> - <shared-delete-action modal-type="delete-with-contributions" :username="username" :paths="paths"> + <shared-delete-action + modal-type="delete-with-contributions" + :username="username" + :paths="paths" + :oncall-schedules="oncallSchedules" + > <slot></slot> </shared-delete-action> </template> diff --git a/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue b/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue index 9107d9ccdd9..b3b68442e80 100644 --- a/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue +++ b/app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue @@ -18,6 +18,10 @@ export default { type: String, required: true, }, + oncallSchedules: { + type: Array, + required: true, + }, }, computed: { modalAttributes() { @@ -26,6 +30,7 @@ export default { 'data-delete-user-url': this.paths.delete, 'data-gl-modal-action': this.modalType, 'data-username': this.username, + 'data-oncall-schedules': JSON.stringify(this.oncallSchedules), }; }, }, diff --git a/app/assets/javascripts/admin/users/components/actions/unblock.vue b/app/assets/javascripts/admin/users/components/actions/unblock.vue index f2b501caf09..d4c0f900c94 100644 --- a/app/assets/javascripts/admin/users/components/actions/unblock.vue +++ b/app/assets/javascripts/admin/users/components/actions/unblock.vue @@ -23,9 +23,7 @@ export default { 'data-method': 'put', 'data-modal-attributes': JSON.stringify({ title: sprintf(s__('AdminUsers|Unblock user %{username}?'), { username: this.username }), - message: s__( - 'AdminUsers|You can always unblock their account, their data will remain intact.', - ), + message: s__('AdminUsers|You can always block their account again if needed.'), okVariant: 'confirm', okTitle: s__('AdminUsers|Unblock'), }), diff --git a/app/assets/javascripts/admin/users/components/usage_ping_disabled.vue b/app/assets/javascripts/admin/users/components/usage_ping_disabled.vue deleted file mode 100644 index 5da38495010..00000000000 --- a/app/assets/javascripts/admin/users/components/usage_ping_disabled.vue +++ /dev/null @@ -1,48 +0,0 @@ -<script> -import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui'; - -export default { - components: { - GlEmptyState, - GlSprintf, - GlLink, - }, - inject: { - svgPath: { - default: '', - }, - docsLink: { - default: '', - }, - primaryButtonPath: { - default: '', - }, - }, -}; -</script> -<template> - <gl-empty-state - class="js-empty-state" - :title="__('Activate user activity analysis')" - :svg-path="svgPath" - :primary-button-text="__('Turn on usage ping')" - :primary-button-link="primaryButtonPath" - > - <template #description> - <gl-sprintf - :message=" - __( - 'Turn on %{strongStart}usage ping%{strongEnd} to activate analysis of user activity, known as %{docLinkStart}Cohorts%{docLinkEnd}.', - ) - " - > - <template #docLink="{ content }"> - <gl-link :href="docsLink" target="_blank">{{ content }}</gl-link> - </template> - <template #strong="{ content }" - ><strong>{{ content }}</strong></template - > - </gl-sprintf> - </template> - </gl-empty-state> -</template> diff --git a/app/assets/javascripts/admin/users/components/user_actions.vue b/app/assets/javascripts/admin/users/components/user_actions.vue index e92c97b54a3..b782526e6be 100644 --- a/app/assets/javascripts/admin/users/components/user_actions.vue +++ b/app/assets/javascripts/admin/users/components/user_actions.vue @@ -70,14 +70,14 @@ export default { </script> <template> - <div class="gl-display-flex gl-justify-content-end"> + <div class="gl-display-flex gl-justify-content-end" :data-testid="`user-actions-${user.id}`"> <gl-button v-if="hasEditAction" data-testid="edit" :href="userPaths.edit">{{ $options.i18n.edit }}</gl-button> <gl-dropdown v-if="hasDropdownActions" - data-testid="actions" + data-testid="dropdown-toggle" right class="gl-ml-2" icon="settings" @@ -109,6 +109,7 @@ export default { :key="action" :paths="userPaths" :username="user.name" + :oncall-schedules="user.oncallSchedules" :data-testid="`delete-${action}`" > {{ $options.i18n[action] }} diff --git a/app/assets/javascripts/admin/users/components/users_table.vue b/app/assets/javascripts/admin/users/components/users_table.vue index 8b41a063abc..2fd96e38f8e 100644 --- a/app/assets/javascripts/admin/users/components/users_table.vue +++ b/app/assets/javascripts/admin/users/components/users_table.vue @@ -1,7 +1,10 @@ <script> -import { GlTable } from '@gitlab/ui'; -import { __ } from '~/locale'; +import { GlSkeletonLoader, GlTable } from '@gitlab/ui'; +import createFlash from '~/flash'; +import { convertNodeIdsFromGraphQLIds } from '~/graphql_shared/utils'; +import { s__, __ } from '~/locale'; import UserDate from '~/vue_shared/components/user_date.vue'; +import getUsersGroupCountsQuery from '../graphql/queries/get_users_group_counts.query.graphql'; import UserActions from './user_actions.vue'; import UserAvatar from './user_avatar.vue'; @@ -11,6 +14,7 @@ const thWidthClass = (width) => `gl-w-${width}p ${DEFAULT_TH_CLASSES}`; export default { components: { + GlSkeletonLoader, GlTable, UserAvatar, UserActions, @@ -26,6 +30,45 @@ export default { required: true, }, }, + data() { + return { + groupCounts: [], + }; + }, + apollo: { + groupCounts: { + query: getUsersGroupCountsQuery, + variables() { + return { + usernames: this.users.map((user) => user.username), + }; + }, + update(data) { + const nodes = data?.users?.nodes || []; + const parsedIds = convertNodeIdsFromGraphQLIds(nodes); + + return parsedIds.reduce((acc, { id, groupCount }) => { + acc[id] = groupCount || 0; + return acc; + }, {}); + }, + error(error) { + createFlash({ + message: this.$options.i18n.groupCountFetchError, + captureError: true, + error, + }); + }, + skip() { + return !this.users.length; + }, + }, + }, + i18n: { + groupCountFetchError: s__( + 'AdminUsers|Could not load user group counts. Please refresh the page to try again.', + ), + }, fields: [ { key: 'name', @@ -38,6 +81,11 @@ export default { thClass: thWidthClass(10), }, { + key: 'groupCount', + label: __('Groups'), + thClass: thWidthClass(10), + }, + { key: 'createdAt', label: __('Created on'), thClass: thWidthClass(15), @@ -50,7 +98,7 @@ export default { { key: 'settings', label: '', - thClass: thWidthClass(20), + thClass: thWidthClass(10), }, ], }; @@ -64,6 +112,7 @@ export default { :empty-text="s__('AdminUsers|No users found')" show-empty stacked="md" + data-qa-selector="user_row_content" > <template #cell(name)="{ item: user }"> <user-avatar :user="user" :admin-user-path="paths.adminUser" /> @@ -77,6 +126,17 @@ export default { <user-date :date="lastActivityOn" show-never /> </template> + <template #cell(groupCount)="{ item: { id } }"> + <div :data-testid="`user-group-count-${id}`"> + <gl-skeleton-loader v-if="$apollo.loading" :width="40" :lines="1" /> + <span v-else>{{ groupCounts[id] }}</span> + </div> + </template> + + <template #cell(projectsCount)="{ item: { id, projectsCount } }"> + <div :data-testid="`user-project-count-${id}`">{{ projectsCount }}</div> + </template> + <template #cell(settings)="{ item: user }"> <user-actions :user="user" :paths="paths" /> </template> diff --git a/app/assets/javascripts/admin/users/graphql/queries/get_users_group_counts.query.graphql b/app/assets/javascripts/admin/users/graphql/queries/get_users_group_counts.query.graphql new file mode 100644 index 00000000000..0d8e199f16e --- /dev/null +++ b/app/assets/javascripts/admin/users/graphql/queries/get_users_group_counts.query.graphql @@ -0,0 +1,8 @@ +query getUsersGroupCounts($usernames: [String!]) { + users(usernames: $usernames) { + nodes { + id + groupCount + } + } +} diff --git a/app/assets/javascripts/admin/users/index.js b/app/assets/javascripts/admin/users/index.js index 0365d054fc9..54c8edc080b 100644 --- a/app/assets/javascripts/admin/users/index.js +++ b/app/assets/javascripts/admin/users/index.js @@ -1,7 +1,14 @@ import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import AdminUsersApp from './components/app.vue'; -import UsagePingDisabled from './components/usage_ping_disabled.vue'; + +Vue.use(VueApollo); + +const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient({}, { assumeImmutableResults: true }), +}); export const initAdminUsersApp = (el = document.querySelector('#js-admin-users-app')) => { if (!el) { @@ -12,6 +19,7 @@ export const initAdminUsersApp = (el = document.querySelector('#js-admin-users-a return new Vue({ el, + apolloProvider, render: (createElement) => createElement(AdminUsersApp, { props: { @@ -21,23 +29,3 @@ export const initAdminUsersApp = (el = document.querySelector('#js-admin-users-a }), }); }; - -export const initCohortsEmptyState = (el = document.querySelector('#js-cohorts-empty-state')) => { - if (!el) { - return false; - } - - const { emptyStateSvgPath, enableUsagePingLink, docsLink } = el.dataset; - - return new Vue({ - el, - provide: { - svgPath: emptyStateSvgPath, - primaryButtonPath: enableUsagePingLink, - docsLink, - }, - render(h) { - return h(UsagePingDisabled); - }, - }); -}; diff --git a/app/assets/javascripts/admin/users/tabs.js b/app/assets/javascripts/admin/users/tabs.js deleted file mode 100644 index cbaab7df4e9..00000000000 --- a/app/assets/javascripts/admin/users/tabs.js +++ /dev/null @@ -1,32 +0,0 @@ -import Api from '~/api'; -import { historyPushState } from '~/lib/utils/common_utils'; -import { mergeUrlParams } from '~/lib/utils/url_utility'; - -const COHORTS_PANE = 'cohorts'; -const COHORTS_PANE_TAB_CLICK_EVENT = 'i_analytics_cohorts'; - -const tabClickHandler = (e) => { - const { hash } = e.currentTarget; - - let tab = null; - - if (hash === `#${COHORTS_PANE}`) { - tab = COHORTS_PANE; - Api.trackRedisHllUserEvent(COHORTS_PANE_TAB_CLICK_EVENT); - } - - const newUrl = mergeUrlParams({ tab }, window.location.href); - historyPushState(newUrl); -}; - -const initTabs = () => { - const tabLinks = document.querySelectorAll('.js-users-tab-item a'); - - if (tabLinks.length) { - tabLinks.forEach((tabLink) => { - tabLink.addEventListener('click', (e) => tabClickHandler(e)); - }); - } -}; - -export default initTabs; |