summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/admin
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-05-19 15:44:42 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2021-05-19 15:44:42 +0000
commit4555e1b21c365ed8303ffb7a3325d773c9b8bf31 (patch)
tree5423a1c7516cffe36384133ade12572cf709398d /app/assets/javascripts/admin
parente570267f2f6b326480d284e0164a6464ba4081bc (diff)
downloadgitlab-ce-4555e1b21c365ed8303ffb7a3325d773c9b8bf31.tar.gz
Add latest changes from gitlab-org/gitlab@13-12-stable-eev13.12.0-rc42
Diffstat (limited to 'app/assets/javascripts/admin')
-rw-r--r--app/assets/javascripts/admin/users/components/actions/delete.vue12
-rw-r--r--app/assets/javascripts/admin/users/components/actions/delete_with_contributions.vue12
-rw-r--r--app/assets/javascripts/admin/users/components/actions/shared/shared_delete_action.vue5
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unblock.vue4
-rw-r--r--app/assets/javascripts/admin/users/components/usage_ping_disabled.vue48
-rw-r--r--app/assets/javascripts/admin/users/components/user_actions.vue5
-rw-r--r--app/assets/javascripts/admin/users/components/users_table.vue66
-rw-r--r--app/assets/javascripts/admin/users/graphql/queries/get_users_group_counts.query.graphql8
-rw-r--r--app/assets/javascripts/admin/users/index.js30
-rw-r--r--app/assets/javascripts/admin/users/tabs.js32
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;