diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-25 09:09:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-09-25 09:09:42 +0300 |
commit | 654281e682c684c9d62778a71ab067b3679b4ee9 (patch) | |
tree | ec4b15bb0814f03e6331327dbfddc3d73c74962e /app | |
parent | c916c6f79b74dd3daf9bdbd7a9fdcb545237d46e (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
11 files changed, 221 insertions, 10 deletions
diff --git a/app/assets/javascripts/issue_show/utils/parse_data.js b/app/assets/javascripts/issue_show/utils/parse_data.js index 9edf87f4c87..f2d1650fed1 100644 --- a/app/assets/javascripts/issue_show/utils/parse_data.js +++ b/app/assets/javascripts/issue_show/utils/parse_data.js @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/browser'; import { sanitize } from '~/lib/dompurify'; // We currently load + parse the data from the issue app and related merge request @@ -7,10 +8,9 @@ export const parseIssuableData = () => { try { if (cachedParsedData) return cachedParsedData; - const initialDataEl = document.getElementById('js-issuable-app-initial-data'); - - const parsedData = JSON.parse(initialDataEl.textContent.replace(/"/g, '"')); + const initialDataEl = document.getElementById('js-issuable-app'); + const parsedData = JSON.parse(initialDataEl.dataset.initial); parsedData.initialTitleHtml = sanitize(parsedData.initialTitleHtml); parsedData.initialDescriptionHtml = sanitize(parsedData.initialDescriptionHtml); @@ -18,7 +18,7 @@ export const parseIssuableData = () => { return parsedData; } catch (e) { - console.error(e); // eslint-disable-line no-console + Sentry.captureException(e); return {}; } diff --git a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue index 1ccf5e9e032..6776a9ebb22 100644 --- a/app/assets/javascripts/self_monitor/components/self_monitor_form.vue +++ b/app/assets/javascripts/self_monitor/components/self_monitor_form.vue @@ -1,7 +1,7 @@ <script> /* eslint-disable vue/no-v-html */ import Vue from 'vue'; -import { GlFormGroup, GlDeprecatedButton, GlModal, GlToast, GlToggle } from '@gitlab/ui'; +import { GlFormGroup, GlButton, GlModal, GlToast, GlToggle } from '@gitlab/ui'; import { mapState, mapActions } from 'vuex'; import { __, s__, sprintf } from '~/locale'; import { visitUrl, getBaseURL } from '~/lib/utils/url_utility'; @@ -11,7 +11,7 @@ Vue.use(GlToast); export default { components: { GlFormGroup, - GlDeprecatedButton, + GlButton, GlModal, GlToggle, }, @@ -123,7 +123,7 @@ export default { <h4 class="js-section-header"> {{ s__('SelfMonitoring|Self monitoring') }} </h4> - <gl-deprecated-button class="js-settings-toggle">{{ __('Expand') }}</gl-deprecated-button> + <gl-button class="js-settings-toggle">{{ __('Expand') }}</gl-button> <p class="js-section-sub-header"> {{ s__('SelfMonitoring|Enable or disable instance self monitoring') }} </p> @@ -146,6 +146,7 @@ export default { :ok-title="__('Delete project')" :cancel-title="__('Cancel')" ok-variant="danger" + category="primary" @ok="deleteProject" @cancel="hideSelfMonitorModal" > diff --git a/app/assets/javascripts/vue_shared/components/members/avatars/group_avatar.vue b/app/assets/javascripts/vue_shared/components/members/avatars/group_avatar.vue new file mode 100644 index 00000000000..12b748f9ab6 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/avatars/group_avatar.vue @@ -0,0 +1,34 @@ +<script> +import { GlAvatarLink, GlAvatarLabeled } from '@gitlab/ui'; +import { AVATAR_SIZE } from '../constants'; + +export default { + name: 'GroupAvatar', + avatarSize: AVATAR_SIZE, + components: { GlAvatarLink, GlAvatarLabeled }, + props: { + member: { + type: Object, + required: true, + }, + }, + computed: { + group() { + return this.member.sharedWithGroup; + }, + }, +}; +</script> + +<template> + <gl-avatar-link :href="group.webUrl"> + <gl-avatar-labeled + :label="group.fullName" + :src="group.avatarUrl" + :alt="group.fullName" + :size="$options.avatarSize" + :entity-name="group.name" + :entity-id="group.id" + /> + </gl-avatar-link> +</template> diff --git a/app/assets/javascripts/vue_shared/components/members/avatars/invite_avatar.vue b/app/assets/javascripts/vue_shared/components/members/avatars/invite_avatar.vue new file mode 100644 index 00000000000..28654a60860 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/avatars/invite_avatar.vue @@ -0,0 +1,32 @@ +<script> +import { GlAvatarLabeled } from '@gitlab/ui'; +import { AVATAR_SIZE } from '../constants'; + +export default { + name: 'InviteAvatar', + avatarSize: AVATAR_SIZE, + components: { GlAvatarLabeled }, + props: { + member: { + type: Object, + required: true, + }, + }, + computed: { + invite() { + return this.member.invite; + }, + }, +}; +</script> + +<template> + <gl-avatar-labeled + :label="invite.email" + :src="invite.avatarUrl" + :alt="invite.email" + :size="$options.avatarSize" + :entity-name="invite.email" + :entity-id="member.id" + /> +</template> diff --git a/app/assets/javascripts/vue_shared/components/members/avatars/user_avatar.vue b/app/assets/javascripts/vue_shared/components/members/avatars/user_avatar.vue new file mode 100644 index 00000000000..3d61cdff747 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/avatars/user_avatar.vue @@ -0,0 +1,55 @@ +<script> +import { GlAvatarLink, GlAvatarLabeled, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui'; +import { __ } from '~/locale'; +import { AVATAR_SIZE } from '../constants'; + +export default { + name: 'UserAvatar', + avatarSize: AVATAR_SIZE, + orphanedUserLabel: __('Orphaned member'), + components: { GlAvatarLink, GlAvatarLabeled }, + directives: { + SafeHtml, + }, + props: { + member: { + type: Object, + required: true, + }, + }, + computed: { + user() { + return this.member.user; + }, + }, +}; +</script> + +<template> + <gl-avatar-link + v-if="user" + class="js-user-link" + :href="user.webUrl" + :data-user-id="user.id" + :data-username="user.username" + > + <gl-avatar-labeled + :label="user.name" + :sub-label="`@${user.username}`" + :src="user.avatarUrl" + :alt="user.name" + :size="$options.avatarSize" + :entity-name="user.name" + :entity-id="user.id" + /> + </gl-avatar-link> + + <gl-avatar-labeled + v-else + :label="$options.orphanedUserLabel" + :alt="$options.orphanedUserLabel" + :size="$options.avatarSize" + :entity-name="$options.orphanedUserLabel" + :entity-id="member.id" + /> +</template> diff --git a/app/assets/javascripts/vue_shared/components/members/constants.js b/app/assets/javascripts/vue_shared/components/members/constants.js index 1d257d6874a..5c6bb0cf9bd 100644 --- a/app/assets/javascripts/vue_shared/components/members/constants.js +++ b/app/assets/javascripts/vue_shared/components/members/constants.js @@ -53,3 +53,12 @@ export const FIELDS = [ tdClass: 'col-actions', }, ]; + +export const AVATAR_SIZE = 48; + +export const MEMBER_TYPES = { + user: 'user', + group: 'group', + invite: 'invite', + accessRequest: 'accessRequest', +}; diff --git a/app/assets/javascripts/vue_shared/components/members/table/member_avatar.vue b/app/assets/javascripts/vue_shared/components/members/table/member_avatar.vue new file mode 100644 index 00000000000..3abd86fa37f --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/table/member_avatar.vue @@ -0,0 +1,31 @@ +<script> +import { kebabCase } from 'lodash'; +import UserAvatar from '../avatars/user_avatar.vue'; +import InviteAvatar from '../avatars/invite_avatar.vue'; +import GroupAvatar from '../avatars/group_avatar.vue'; + +export default { + name: 'MemberAvatar', + components: { UserAvatar, InviteAvatar, GroupAvatar, AccessRequestAvatar: UserAvatar }, + props: { + memberType: { + type: String, + required: true, + }, + member: { + type: Object, + required: true, + }, + }, + computed: { + avatarComponent() { + // eslint-disable-next-line @gitlab/require-i18n-strings + return `${kebabCase(this.memberType)}-avatar`; + }, + }, +}; +</script> + +<template> + <component :is="avatarComponent" :member="member" /> +</template> diff --git a/app/assets/javascripts/vue_shared/components/members/table/members_table.vue b/app/assets/javascripts/vue_shared/components/members/table/members_table.vue index 72aa9b6ccb2..7b6a87eaae1 100644 --- a/app/assets/javascripts/vue_shared/components/members/table/members_table.vue +++ b/app/assets/javascripts/vue_shared/components/members/table/members_table.vue @@ -3,11 +3,15 @@ import { mapState } from 'vuex'; import { GlTable } from '@gitlab/ui'; import { FIELDS } from '../constants'; import initUserPopovers from '~/user_popovers'; +import MemberAvatar from './member_avatar.vue'; +import MembersTableCell from './members_table_cell.vue'; export default { name: 'MembersTable', components: { GlTable, + MemberAvatar, + MembersTableCell, }, computed: { ...mapState(['members', 'tableFields']), @@ -33,6 +37,12 @@ export default { :empty-text="__('No members found')" show-empty > + <template #cell(account)="{ item: member }"> + <members-table-cell #default="{ memberType }" :member="member"> + <member-avatar :member-type="memberType" :member="member" /> + </members-table-cell> + </template> + <template #cell(source)> <!-- Temporarily empty --> </template> diff --git a/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue b/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue new file mode 100644 index 00000000000..3a9c69154ce --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/members/table/members_table_cell.vue @@ -0,0 +1,40 @@ +<script> +import { MEMBER_TYPES } from '../constants'; + +export default { + name: 'MembersTableCell', + props: { + member: { + type: Object, + required: true, + }, + }, + computed: { + isGroup() { + return Boolean(this.member.sharedWithGroup); + }, + isInvite() { + return Boolean(this.member.invite); + }, + isAccessRequest() { + return Boolean(this.member.requestedAt); + }, + memberType() { + if (this.isGroup) { + return MEMBER_TYPES.group; + } else if (this.isInvite) { + return MEMBER_TYPES.invite; + } else if (this.isAccessRequest) { + return MEMBER_TYPES.accessRequest; + } + + return MEMBER_TYPES.user; + }, + }, + render() { + return this.$scopedSlots.default({ + memberType: this.memberType, + }); + }, +}; +</script> diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue index 0b763aa4b72..ae66780b974 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue @@ -112,6 +112,7 @@ export default { this.currentHighlightItem += 1; } else if (e.keyCode === ENTER_KEY_CODE && this.currentHighlightItem > -1) { this.updateSelectedLabels([this.visibleLabels[this.currentHighlightItem]]); + this.searchKey = ''; } else if (e.keyCode === ESC_KEY_CODE) { this.toggleDropdownContents(); } diff --git a/app/views/projects/issues/show.html.haml b/app/views/projects/issues/show.html.haml index 01bd73508e4..4e6b0064057 100644 --- a/app/views/projects/issues/show.html.haml +++ b/app/views/projects/issues/show.html.haml @@ -62,9 +62,7 @@ .issue-details.issuable-details .detail-page-description.content-block - -# haml-lint:disable InlineJavaScript - %script#js-issuable-app-initial-data{ type: "application/json" }= issuable_initial_data(@issue).to_json - #js-issuable-app + #js-issuable-app{ data: { initial: issuable_initial_data(@issue).to_json} } .title-container %h2.title= markdown_field(@issue, :title) - if @issue.description.present? |