diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-08-19 12:08:42 +0300 |
commit | b76ae638462ab0f673e5915986070518dd3f9ad3 (patch) | |
tree | bdab0533383b52873be0ec0eb4d3c66598ff8b91 /app/assets/javascripts/sidebar | |
parent | 434373eabe7b4be9593d18a585fb763f1e5f1a6f (diff) |
Add latest changes from gitlab-org/gitlab@14-2-stable-eev14.2.0-rc42
Diffstat (limited to 'app/assets/javascripts/sidebar')
16 files changed, 105 insertions, 38 deletions
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue index 98fc0b0a783..2a237e7ace0 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_avatar_link.vue @@ -1,6 +1,6 @@ <script> import { GlTooltipDirective, GlLink } from '@gitlab/ui'; -import { __, sprintf } from '~/locale'; +import { __ } from '~/locale'; import { isUserBusy } from '~/set_status_modal/utils'; import AssigneeAvatar from './assignee_avatar.vue'; @@ -32,10 +32,9 @@ const generateAssigneeTooltip = ({ } if (tooltipHasName && statusInformation.length) { - return sprintf(__('%{name} %{status}'), { - name, - status: statusInformation.map(paranthesize).join(' '), - }); + const status = statusInformation.map(paranthesize).join(' '); + + return `${name} ${status}`; } return name; diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue index 4b3b22f6db3..d9c5edc91f1 100644 --- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue +++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue @@ -50,7 +50,7 @@ export default { <gl-loading-icon v-if="loading" size="sm" inline class="align-bottom" /> <a v-if="editable" - class="js-sidebar-dropdown-toggle edit-link float-right" + class="js-sidebar-dropdown-toggle edit-link btn gl-text-gray-900! gl-ml-auto hide-collapsed btn-default btn-sm gl-button btn-default-tertiary float-right" href="#" data-test-id="edit-link" data-track-event="click_edit_button" diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue index b7832ca679c..55179947756 100644 --- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue +++ b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue @@ -55,12 +55,13 @@ export default { }, getUpdateVariables(dropdownLabels) { const currentLabelIds = this.selectedLabels.map((label) => label.id); - const userAddedLabelIds = dropdownLabels - .filter((label) => label.set) - .map((label) => label.id); - const userRemovedLabelIds = dropdownLabels - .filter((label) => !label.set) - .map((label) => label.id); + const dropdownLabelIds = dropdownLabels.map((label) => label.id); + const userAddedLabelIds = this.glFeatures.labelsWidget + ? difference(dropdownLabelIds, currentLabelIds) + : dropdownLabels.filter((label) => label.set).map((label) => label.id); + const userRemovedLabelIds = this.glFeatures.labelsWidget + ? difference(currentLabelIds, dropdownLabelIds) + : dropdownLabels.filter((label) => !label.set).map((label) => label.id); const labelIds = difference(union(currentLabelIds, userAddedLabelIds), userRemovedLabelIds); @@ -155,7 +156,7 @@ export default { :labels-manage-path="labelsManagePath" :labels-select-in-progress="isLabelsSelectInProgress" :selected-labels="selectedLabels" - :variant="$options.sidebar" + :variant="$options.variant" data-qa-selector="labels_block" @onDropdownClose="handleDropdownClose" @onLabelRemove="handleLabelRemove" diff --git a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue index 81ee0a73739..19543d0927a 100644 --- a/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue +++ b/app/assets/javascripts/sidebar/components/lock/issuable_lock_form.vue @@ -90,7 +90,7 @@ export default { {{ sprintf(__('Lock %{issuableDisplayName}'), { issuableDisplayName: issuableDisplayName }) }} <a v-if="isEditable" - class="float-right lock-edit" + class="float-right lock-edit btn gl-text-gray-900! gl-ml-auto hide-collapsed btn-default btn-sm gl-button btn-default-tertiary gl-mr-n2" href="#" data-testid="edit-link" data-track-event="click_edit_button" diff --git a/app/assets/javascripts/sidebar/components/participants/participants.vue b/app/assets/javascripts/sidebar/components/participants/participants.vue index 650aa603f18..ad4bfe5b665 100644 --- a/app/assets/javascripts/sidebar/components/participants/participants.vue +++ b/app/assets/javascripts/sidebar/components/participants/participants.vue @@ -33,6 +33,11 @@ export default { required: false, default: true, }, + lazy: { + type: Boolean, + required: false, + default: true, + }, }, data() { return { @@ -95,7 +100,7 @@ export default { <gl-loading-icon v-if="loading" size="sm" /> <span v-else data-testid="collapsed-count"> {{ participantCount }} </span> </div> - <div v-if="showParticipantLabel" class="title hide-collapsed gl-mb-2"> + <div v-if="showParticipantLabel" class="title hide-collapsed gl-mb-2 gl-line-height-20"> <gl-loading-icon v-if="loading" size="sm" :inline="true" /> {{ participantLabel }} </div> @@ -107,10 +112,11 @@ export default { > <a :href="participant.web_url || participant.webUrl" class="author-link"> <user-avatar-image - :lazy="true" + :lazy="lazy" :img-src="participant.avatar_url || participant.avatarUrl" :size="24" :tooltip-text="participant.name" + :img-alt="participant.name" css-classes="avatar-inline" tooltip-placement="bottom" /> diff --git a/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue b/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue index 9927a0f9114..39f72b251c7 100644 --- a/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue +++ b/app/assets/javascripts/sidebar/components/participants/sidebar_participants_widget.vue @@ -64,6 +64,7 @@ export default { :loading="isLoading" :participants="participants" :number-of-less-participants="7" + :lazy="false" class="block participants" /> </template> diff --git a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue index 295027186cc..1243603805a 100644 --- a/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue +++ b/app/assets/javascripts/sidebar/components/reviewers/reviewer_title.vue @@ -38,7 +38,7 @@ export default { <gl-loading-icon v-if="loading" size="sm" inline class="align-bottom" /> <a v-if="editable" - class="js-sidebar-dropdown-toggle edit-link float-right" + class="js-sidebar-dropdown-toggle edit-link btn gl-text-gray-900! gl-ml-auto hide-collapsed btn-default btn-sm gl-button btn-default-tertiary float-right" href="#" data-track-event="click_edit_button" data-track-label="right_sidebar" diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue index fdf63c23552..5dc93476120 100644 --- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue +++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue @@ -23,6 +23,7 @@ export default { GlLink, SeverityToken, }, + inject: ['canUpdate'], props: { projectPath: { type: String, @@ -153,6 +154,7 @@ export default { > {{ $options.i18n.SEVERITY }} <gl-link + v-if="canUpdate" data-testid="editButton" href="#" @click="toggleFormDropdown" diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue index 2e00a23de7c..8ccc0102c3d 100644 --- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue +++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue @@ -13,6 +13,7 @@ import { import createFlash from '~/flash'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { IssuableType } from '~/issue_show/constants'; +import { timeFor } from '~/lib/utils/datetime_utility'; import { __, s__, sprintf } from '~/locale'; import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue'; import { @@ -22,6 +23,7 @@ import { issuableAttributesQueries, noAttributeId, defaultEpicSort, + epicIidPattern, } from '~/sidebar/constants'; export default { @@ -118,17 +120,37 @@ export default { return query; }, skip() { + if (this.isEpic && this.searchTerm.startsWith('&') && this.searchTerm.length < 2) { + return true; + } + return !this.editing; }, debounce: 250, variables() { - return { + if (!this.isEpic) { + return { + fullPath: this.attrWorkspacePath, + title: this.searchTerm, + state: this.$options.IssuableAttributeState[this.issuableAttribute], + }; + } + + const variables = { fullPath: this.attrWorkspacePath, - title: this.searchTerm, - in: this.searchTerm && this.issuableAttribute === IssuableType.Epic ? 'TITLE' : undefined, state: this.$options.IssuableAttributeState[this.issuableAttribute], - sort: this.issuableAttribute === IssuableType.Epic ? defaultEpicSort : null, + sort: defaultEpicSort, }; + + if (epicIidPattern.test(this.searchTerm)) { + const matches = this.searchTerm.match(epicIidPattern); + variables.iidStartsWith = matches.groups.iid; + } else if (this.searchTerm !== '') { + variables.in = 'TITLE'; + variables.title = this.searchTerm; + } + + return variables; }, update(data) { if (data?.workspace) { @@ -183,6 +205,9 @@ export default { attributeTypeIcon() { return this.icon || this.issuableAttribute; }, + tooltipText() { + return timeFor(this.currentAttribute?.dueDate); + }, i18n() { return { noAttribute: sprintf(s__('DropdownWidget|No %{issuableAttribute}'), { @@ -214,6 +239,9 @@ export default { ), }; }, + isEpic() { + return this.issuableAttribute === IssuableType.Epic; + }, }, methods: { updateAttribute(attributeId) { @@ -322,6 +350,7 @@ export default { :currentAttribute="currentAttribute" > <gl-link + v-gl-tooltip="tooltipText" class="gl-text-gray-900! gl-font-weight-bold" :href="attributeUrl" :data-qa-selector="`${issuableAttribute}_link`" diff --git a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue index 7c496cc422a..89aa03fd954 100644 --- a/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue +++ b/app/assets/javascripts/sidebar/components/sidebar_editable_item.vue @@ -132,8 +132,9 @@ export default { <slot name="collapsed-right"></slot> <gl-button v-if="canUpdate && !initialLoading && canEdit" - variant="link" - class="gl-text-gray-900! gl-hover-text-blue-800! gl-ml-auto hide-collapsed" + category="tertiary" + size="small" + class="gl-text-gray-900! gl-ml-auto hide-collapsed gl-mr-n2" data-testid="edit-button" :data-track-event="tracking.event" :data-track-label="tracking.label" diff --git a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue index d1a5685fdd3..7c157fe2775 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/help_state.vue @@ -1,6 +1,5 @@ <script> -/* eslint-disable vue/no-v-html */ -import { GlButton } from '@gitlab/ui'; +import { GlButton, GlSafeHtmlDirective } from '@gitlab/ui'; import { joinPaths } from '~/lib/utils/url_utility'; import { sprintf, s__ } from '../../../locale'; @@ -9,15 +8,16 @@ export default { components: { GlButton, }, + directives: { + SafeHtml: GlSafeHtmlDirective, + }, computed: { href() { return joinPaths(gon.relative_url_root || '', '/help/user/project/time_tracking.md'); }, estimateText() { return sprintf( - s__( - 'estimateCommand|%{slash_command} will update the estimated time with the latest command.', - ), + s__('estimateCommand|%{slash_command} overwrites the total estimated time.'), { slash_command: '<code>/estimate</code>', }, @@ -26,7 +26,7 @@ export default { }, spendText() { return sprintf( - s__('spendCommand|%{slash_command} will update the sum of the time spent.'), + s__('spendCommand|%{slash_command} adds or subtracts time already spent.'), { slash_command: '<code>/spend</code>', }, @@ -41,9 +41,9 @@ export default { <div data-testid="helpPane" class="time-tracking-help-state"> <div class="time-tracking-info"> <h4>{{ __('Track time with quick actions') }}</h4> - <p>{{ __('Quick actions can be used in the issues description and comment boxes.') }}</p> - <p v-html="estimateText"></p> - <p v-html="spendText"></p> + <p>{{ __('Quick actions can be used in description and comment boxes.') }}</p> + <p v-safe-html="estimateText"></p> + <p v-safe-html="spendText"></p> <gl-button :href="href">{{ __('Learn more') }}</gl-button> </div> </div> diff --git a/app/assets/javascripts/sidebar/components/time_tracking/report.vue b/app/assets/javascripts/sidebar/components/time_tracking/report.vue index 8a14998910b..d4a8abb81a8 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/report.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/report.vue @@ -62,8 +62,8 @@ export default { formatDate(date) { return formatDate(date, TIME_DATE_FORMAT); }, - getNote(note) { - return note?.body; + getSummary(summary, note) { + return summary ?? note?.body; }, getTotalTimeSpent() { const seconds = this.report.reduce((acc, item) => acc + item.timeSpent, 0); @@ -81,7 +81,7 @@ export default { { key: 'spentAt', label: __('Spent At'), sortable: true }, { key: 'user', label: __('User'), sortable: true }, { key: 'timeSpent', label: __('Time Spent'), sortable: true }, - { key: 'note', label: __('Note'), sortable: true }, + { key: 'summary', label: __('Summary / Note'), sortable: true }, ], }; </script> @@ -107,8 +107,8 @@ export default { <div>{{ getTotalTimeSpent() }}</div> </template> - <template #cell(note)="{ item: { note } }"> - <div>{{ getNote(note) }}</div> + <template #cell(summary)="{ item: { summary, note } }"> + <div>{{ getSummary(summary, note) }}</div> </template> <template #foot(note)> </template> </gl-table> diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js index 08ee4379c0c..fd43fb80b7f 100644 --- a/app/assets/javascripts/sidebar/constants.js +++ b/app/assets/javascripts/sidebar/constants.js @@ -48,6 +48,8 @@ export const ASSIGNEES_DEBOUNCE_DELAY = DEFAULT_DEBOUNCE_AND_THROTTLE_MS; export const defaultEpicSort = 'TITLE_ASC'; +export const epicIidPattern = /^&(?<iid>\d+)$/; + export const assigneesQueries = { [IssuableType.Issue]: { query: getIssueAssignees, diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js index dd1b439c482..031472a7d20 100644 --- a/app/assets/javascripts/sidebar/mount_sidebar.js +++ b/app/assets/javascripts/sidebar/mount_sidebar.js @@ -24,6 +24,7 @@ import SidebarDropdownWidget from '~/sidebar/components/sidebar_dropdown_widget. import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue'; import { apolloProvider } from '~/sidebar/graphql'; import trackShowInviteMemberLink from '~/sidebar/track_invite_members'; +import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants'; import Translate from '../vue_shared/translate'; import SidebarAssignees from './components/assignees/sidebar_assignees.vue'; import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue'; @@ -256,6 +257,7 @@ export function mountSidebarLabels() { allowLabelEdit: parseBoolean(el.dataset.canEdit), allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels), initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels), + variant: DropdownVariant.Sidebar, }, render: (createElement) => createElement(SidebarLabels), }); @@ -493,7 +495,7 @@ function mountSeverityComponent() { return false; } - const { fullPath, iid, severity } = getSidebarOptions(); + const { fullPath, iid, severity, editable } = getSidebarOptions(); return new Vue({ el: severityContainerEl, @@ -501,6 +503,9 @@ function mountSeverityComponent() { components: { SidebarSeverity, }, + provide: { + canUpdate: editable, + }, render: (createElement) => createElement('sidebar-severity', { props: { diff --git a/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql b/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql new file mode 100644 index 00000000000..dceab61ed26 --- /dev/null +++ b/app/assets/javascripts/sidebar/queries/group_milestones.query.graphql @@ -0,0 +1,20 @@ +#import "./milestone.fragment.graphql" + +query groupMilestones($fullPath: ID!, $title: String, $state: MilestoneStateEnum) { + workspace: group(fullPath: $fullPath) { + __typename + id + attributes: milestones( + searchTitle: $title + state: $state + sort: EXPIRED_LAST_DUE_DATE_ASC + first: 20 + includeAncestors: true + ) { + nodes { + ...MilestoneFragment + state + } + } + } +} diff --git a/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql b/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql index 2ffd58a2da1..d4f7e703692 100644 --- a/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql +++ b/app/assets/javascripts/sidebar/queries/milestone.fragment.graphql @@ -2,5 +2,6 @@ fragment MilestoneFragment on Milestone { id title webUrl: webPath + dueDate expired } |