Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-06-19 15:09:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-06-19 15:09:51 +0300
commiteef2437c0a359ec3437d31d1b1ea959e54c71458 (patch)
tree92ea24b2d26a057881171827e777604780838633 /app
parent021a832cb8e90a0305452381ccf4ce15dc5e0ebd (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue9
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_header.vue2
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_managers_table.vue6
-rw-r--r--app/assets/javascripts/ci/runner/components/runner_status_badge.vue20
-rw-r--r--app/assets/javascripts/ci/runner/graphql/show/runner_manager_shared.fragment.graphql1
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_note.vue6
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_note_actions.vue44
-rw-r--r--app/assets/javascripts/work_items/components/work_item_actions.vue61
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue4
-rw-r--r--app/assets/javascripts/work_items/constants.js13
-rw-r--r--app/assets/javascripts/work_items/graphql/notes/work_item_note.fragment.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.fragment.graphql3
-rw-r--r--app/assets/stylesheets/fonts.scss2
-rw-r--r--app/models/ci/build.rb15
14 files changed, 176 insertions, 12 deletions
diff --git a/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue b/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue
index 149c69e5307..e287e4e17d1 100644
--- a/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue
+++ b/app/assets/javascripts/ci/runner/components/cells/runner_status_cell.vue
@@ -22,6 +22,12 @@ export default {
paused() {
return this.runner.paused;
},
+ contactedAt() {
+ return this.runner.contactedAt;
+ },
+ status() {
+ return this.runner.status;
+ },
},
};
</script>
@@ -29,7 +35,8 @@ export default {
<template>
<div>
<runner-status-badge
- :runner="runner"
+ :contacted-at="contactedAt"
+ :status="status"
class="gl-display-inline-block gl-max-w-full gl-text-truncate"
/>
<runner-paused-badge
diff --git a/app/assets/javascripts/ci/runner/components/runner_header.vue b/app/assets/javascripts/ci/runner/components/runner_header.vue
index 61d8d264601..f46e894bf2e 100644
--- a/app/assets/javascripts/ci/runner/components/runner_header.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_header.vue
@@ -38,7 +38,7 @@ export default {
<div>
<h1 class="gl-font-size-h-display gl-my-0">{{ name }}</h1>
<div class="gl-display-flex gl-align-items-flex-start gl-gap-3 gl-flex-wrap gl-mt-3">
- <runner-status-badge :runner="runner" />
+ <runner-status-badge :contacted-at="runner.contactedAt" :status="runner.status" />
<runner-type-badge :type="runner.runnerType" />
<span v-if="runner.createdAt">
<gl-sprintf :message="__('%{locked} created %{timeago}')">
diff --git a/app/assets/javascripts/ci/runner/components/runner_managers_table.vue b/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
index d1d5d0432f2..10790c398b0 100644
--- a/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_managers_table.vue
@@ -5,6 +5,7 @@ import { s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { tableField } from '../utils';
import { I18N_STATUS_NEVER_CONTACTED } from '../constants';
+import RunnerStatusBadge from './runner_status_badge.vue';
export default {
name: 'RunnerManagersTable',
@@ -13,6 +14,7 @@ export default {
TimeAgo,
HelpPopover,
GlIntersperse,
+ RunnerStatusBadge,
RunnerUpgradeStatusIcon: () =>
import('ee_component/ci/runner/components/runner_upgrade_status_icon.vue'),
},
@@ -25,6 +27,7 @@ export default {
},
fields: [
tableField({ key: 'systemId', label: s__('Runners|System ID') }),
+ tableField({ key: 'status', label: s__('Runners|Status') }),
tableField({ key: 'version', label: s__('Runners|Version') }),
tableField({ key: 'ipAddress', label: s__('Runners|IP Address') }),
tableField({ key: 'executorName', label: s__('Runners|Executor') }),
@@ -48,6 +51,9 @@ export default {
{{ s__('Runners|The unique ID for each runner that uses this configuration.') }}
</help-popover>
</template>
+ <template #cell(status)="{ item = {} }">
+ <runner-status-badge :contacted-at="item.contactedAt" :status="item.status" />
+ </template>
<template #cell(version)="{ item = {} }">
{{ item.version }}
<template v-if="item.revision">({{ item.revision }})</template>
diff --git a/app/assets/javascripts/ci/runner/components/runner_status_badge.vue b/app/assets/javascripts/ci/runner/components/runner_status_badge.vue
index d084408781e..c2c52bd756a 100644
--- a/app/assets/javascripts/ci/runner/components/runner_status_badge.vue
+++ b/app/assets/javascripts/ci/runner/components/runner_status_badge.vue
@@ -26,21 +26,27 @@ export default {
GlTooltip: GlTooltipDirective,
},
props: {
- runner: {
- required: true,
- type: Object,
+ contactedAt: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ status: {
+ type: String,
+ required: false,
+ default: null,
},
},
computed: {
contactedAtTimeAgo() {
- if (this.runner.contactedAt) {
- return getTimeago().format(this.runner.contactedAt);
+ if (this.contactedAt) {
+ return getTimeago().format(this.contactedAt);
}
// Prevent "just now" from being rendered, in case data is missing.
return __('never');
},
badge() {
- switch (this.runner?.status) {
+ switch (this.status) {
case STATUS_ONLINE:
return {
icon: 'status-active',
@@ -68,7 +74,7 @@ export default {
variant: 'warning',
label: I18N_STATUS_STALE,
// runner may have contacted (or not) and be stale: consider both cases.
- tooltip: this.runner.contactedAt
+ tooltip: this.contactedAt
? this.timeAgoTooltip(I18N_STALE_TIMEAGO_TOOLTIP)
: I18N_STALE_NEVER_CONTACTED_TOOLTIP,
};
diff --git a/app/assets/javascripts/ci/runner/graphql/show/runner_manager_shared.fragment.graphql b/app/assets/javascripts/ci/runner/graphql/show/runner_manager_shared.fragment.graphql
index 008ec91b5d9..ead005d1252 100644
--- a/app/assets/javascripts/ci/runner/graphql/show/runner_manager_shared.fragment.graphql
+++ b/app/assets/javascripts/ci/runner/graphql/show/runner_manager_shared.fragment.graphql
@@ -1,6 +1,7 @@
fragment CiRunnerManagerShared on CiRunnerManager {
id
systemId
+ status
version
revision
executorName
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_note.vue b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
index f3b21dacfe9..7ad424868c6 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_note.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
@@ -154,6 +154,9 @@ export default {
isWorkItemAuthor() {
return getIdFromGraphQLId(this.workItem?.author?.id) === getIdFromGraphQLId(this.author.id);
},
+ projectName() {
+ return this.workItem?.project?.name;
+ },
},
apollo: {
workItem: {
@@ -329,6 +332,9 @@ export default {
:can-report-abuse="!isCurrentUserAuthorOfNote"
:is-work-item-author="isWorkItemAuthor"
:work-item-type="workItemType"
+ :is-author-contributor="note.authorIsContributor"
+ :max-access-level-of-author="note.maxAccessLevelOfAuthor"
+ :project-name="projectName"
@startReplying="showReplyForm"
@startEditing="startEditing"
@error="($event) => $emit('error', $event)"
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_note_actions.vue b/app/assets/javascripts/work_items/components/notes/work_item_note_actions.vue
index a9dc800ae73..b32a8c78c93 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_note_actions.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_note_actions.vue
@@ -84,6 +84,21 @@ export default {
required: false,
default: false,
},
+ isAuthorContributor: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ maxAccessLevelOfAuthor: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ projectName: {
+ type: String,
+ required: false,
+ default: '',
+ },
},
computed: {
assignUserActionText() {
@@ -96,6 +111,17 @@ export default {
workItemType: this.workItemType.toLowerCase(),
});
},
+ displayMemberBadgeText() {
+ return sprintf(__('This user has the %{access} role in the %{name} project.'), {
+ access: this.maxAccessLevelOfAuthor.toLowerCase(),
+ name: this.projectName,
+ });
+ },
+ displayContributorBadgeText() {
+ return sprintf(__('This user has previously committed to the %{name} project.'), {
+ name: this.projectName,
+ });
+ },
},
methods: {
@@ -140,6 +166,24 @@ export default {
>
{{ __('Author') }}
</user-access-role-badge>
+ <user-access-role-badge
+ v-if="maxAccessLevelOfAuthor"
+ v-gl-tooltip
+ class="gl-mr-3 gl-display-none gl-sm-display-block"
+ :title="displayMemberBadgeText"
+ data-testid="max-access-level-badge"
+ >
+ {{ maxAccessLevelOfAuthor }}
+ </user-access-role-badge>
+ <user-access-role-badge
+ v-else-if="isAuthorContributor"
+ v-gl-tooltip
+ class="gl-mr-3 gl-display-none gl-sm-display-block"
+ :title="displayContributorBadgeText"
+ data-testid="contributor-badge"
+ >
+ {{ __('Contributor') }}
+ </user-access-role-badge>
<emoji-picker
v-if="showAwardEmoji && glFeatures.workItemsMvc2"
toggle-class="note-action-button note-emoji-button btn-icon btn-default-tertiary"
diff --git a/app/assets/javascripts/work_items/components/work_item_actions.vue b/app/assets/javascripts/work_items/components/work_item_actions.vue
index 9c6ce7ab702..76a04bede61 100644
--- a/app/assets/javascripts/work_items/components/work_item_actions.vue
+++ b/app/assets/javascripts/work_items/components/work_item_actions.vue
@@ -8,11 +8,14 @@ import {
GlModalDirective,
GlToggle,
} from '@gitlab/ui';
+
import * as Sentry from '@sentry/browser';
-import { s__ } from '~/locale';
+
+import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
import toast from '~/vue_shared/plugins/global_toast';
import { isLoggedIn } from '~/lib/utils/common_utils';
+
import {
sprintfWorkItem,
I18N_WORK_ITEM_DELETE,
@@ -22,10 +25,15 @@ import {
TEST_ID_NOTIFICATIONS_TOGGLE_FORM,
TEST_ID_DELETE_ACTION,
TEST_ID_PROMOTE_ACTION,
+ TEST_ID_COPY_CREATE_NOTE_EMAIL_ACTION,
+ TEST_ID_COPY_REFERENCE_ACTION,
WIDGET_TYPE_NOTIFICATIONS,
I18N_WORK_ITEM_ERROR_CONVERTING,
WORK_ITEM_TYPE_VALUE_KEY_RESULT,
WORK_ITEM_TYPE_VALUE_OBJECTIVE,
+ I18N_WORK_ITEM_COPY_CREATE_NOTE_EMAIL,
+ I18N_WORK_ITEM_ERROR_COPY_REFERENCE,
+ I18N_WORK_ITEM_ERROR_COPY_EMAIL,
} from '../constants';
import updateWorkItemNotificationsMutation from '../graphql/update_work_item_notifications.mutation.graphql';
import convertWorkItemMutation from '../graphql/work_item_convert.mutation.graphql';
@@ -38,6 +46,9 @@ export default {
notifications: s__('WorkItem|Notifications'),
notificationOn: s__('WorkItem|Notifications turned on.'),
notificationOff: s__('WorkItem|Notifications turned off.'),
+ copyReference: __('Copy reference'),
+ referenceCopied: __('Reference copied'),
+ emailAddressCopied: __('Email address copied'),
},
components: {
GlDropdown,
@@ -55,6 +66,8 @@ export default {
notificationsToggleTestId: TEST_ID_NOTIFICATIONS_TOGGLE_ACTION,
notificationsToggleFormTestId: TEST_ID_NOTIFICATIONS_TOGGLE_FORM,
confidentialityTestId: TEST_ID_CONFIDENTIALITY_TOGGLE_ACTION,
+ copyReferenceTestId: TEST_ID_COPY_REFERENCE_ACTION,
+ copyCreateNoteEmailTestId: TEST_ID_COPY_CREATE_NOTE_EMAIL_ACTION,
deleteActionTestId: TEST_ID_DELETE_ACTION,
promoteActionTestId: TEST_ID_PROMOTE_ACTION,
inject: ['fullPath'],
@@ -99,6 +112,21 @@ export default {
required: false,
default: false,
},
+ workItemReference: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ workItemCreateNoteEmail: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ isModal: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
apollo: {
workItemTypes: {
@@ -122,6 +150,15 @@ export default {
deleteWorkItem: sprintfWorkItem(I18N_WORK_ITEM_DELETE, this.workItemType),
areYouSureDelete: sprintfWorkItem(I18N_WORK_ITEM_ARE_YOU_SURE_DELETE, this.workItemType),
convertError: sprintfWorkItem(I18N_WORK_ITEM_ERROR_CONVERTING, this.workItemType),
+ copyCreateNoteEmail: sprintfWorkItem(
+ I18N_WORK_ITEM_COPY_CREATE_NOTE_EMAIL,
+ this.workItemType,
+ ),
+ copyReferenceError: sprintfWorkItem(I18N_WORK_ITEM_ERROR_COPY_REFERENCE, this.workItemType),
+ copyCreateNoteEmailError: sprintfWorkItem(
+ I18N_WORK_ITEM_ERROR_COPY_EMAIL,
+ this.workItemType,
+ ),
};
},
canPromoteToObjective() {
@@ -142,6 +179,12 @@ export default {
},
},
methods: {
+ copyToClipboard(text, message) {
+ if (this.isModal) {
+ navigator.clipboard.writeText(text);
+ }
+ toast(message);
+ },
handleToggleWorkItemConfidentiality() {
this.track('click_toggle_work_item_confidentiality');
this.$emit('toggleWorkItemConfidentiality', !this.isConfidential);
@@ -287,6 +330,22 @@ export default {
: $options.i18n.enableTaskConfidentiality
}}</gl-dropdown-item
>
+ </template>
+ <gl-dropdown-item
+ ref="workItemReference"
+ :data-testid="$options.copyReferenceTestId"
+ :data-clipboard-text="workItemReference"
+ @click="copyToClipboard(workItemReference, $options.i18n.referenceCopied)"
+ >{{ $options.i18n.copyReference }}</gl-dropdown-item
+ >
+ <template v-if="$options.isLoggedIn && workItemCreateNoteEmail">
+ <gl-dropdown-item
+ ref="workItemCreateNoteEmail"
+ :data-testid="$options.copyCreateNoteEmailTestId"
+ :data-clipboard-text="workItemCreateNoteEmail"
+ @click="copyToClipboard(workItemCreateNoteEmail, $options.i18n.emailAddressCopied)"
+ >{{ i18n.copyCreateNoteEmail }}</gl-dropdown-item
+ >
<gl-dropdown-divider v-if="canDelete" />
</template>
<gl-dropdown-item
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index ad759bc69e9..1ac40fe7dcb 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -515,7 +515,6 @@ export default {
@error="updateError = $event"
/>
<work-item-actions
- v-if="canUpdate || canDelete"
:work-item-id="workItem.id"
:subscribed-to-notifications="workItemNotificationsSubscribed"
:work-item-type="workItemType"
@@ -524,6 +523,9 @@ export default {
:can-update="canUpdate"
:is-confidential="workItem.confidential"
:is-parent-confidential="parentWorkItemConfidentiality"
+ :work-item-reference="workItem.reference"
+ :work-item-create-note-email="workItem.createNoteEmail"
+ :is-modal="isModal"
@deleteWorkItem="$emit('deleteWorkItem', { workItemType, workItemId: workItem.id })"
@toggleWorkItemConfidentiality="toggleConfidentiality"
@error="updateError = $event"
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
index 6710c762c2e..f3beaebf403 100644
--- a/app/assets/javascripts/work_items/constants.js
+++ b/app/assets/javascripts/work_items/constants.js
@@ -92,6 +92,17 @@ export const I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_TOOLTIP = s__(
'WorkItem|A non-confidential %{workItemType} cannot be assigned to a confidential parent %{parentWorkItemType}.',
);
+export const I18N_WORK_ITEM_ERROR_COPY_REFERENCE = s__(
+ 'WorkItem|Something went wrong while copying the %{workItemType} reference. Please try again.',
+);
+export const I18N_WORK_ITEM_ERROR_COPY_EMAIL = s__(
+ 'WorkItem|Something went wrong while copying the %{workItemType} email address. Please try again.',
+);
+
+export const I18N_WORK_ITEM_COPY_CREATE_NOTE_EMAIL = s__(
+ 'WorkItem|Copy %{workItemType} email address',
+);
+
export const sprintfWorkItem = (msg, workItemTypeArg, parentWorkItemType = '') => {
const workItemType = workItemTypeArg || s__('WorkItem|Work item');
return capitalizeFirstCharacter(
@@ -217,6 +228,8 @@ export const TEST_ID_NOTIFICATIONS_TOGGLE_ACTION = 'notifications-toggle-action'
export const TEST_ID_NOTIFICATIONS_TOGGLE_FORM = 'notifications-toggle-form';
export const TEST_ID_DELETE_ACTION = 'delete-action';
export const TEST_ID_PROMOTE_ACTION = 'promote-action';
+export const TEST_ID_COPY_REFERENCE_ACTION = 'copy-reference-action';
+export const TEST_ID_COPY_CREATE_NOTE_EMAIL_ACTION = 'copy-create-note-email-action';
export const ADD = 'ADD';
export const MARK_AS_DONE = 'MARK_AS_DONE';
diff --git a/app/assets/javascripts/work_items/graphql/notes/work_item_note.fragment.graphql b/app/assets/javascripts/work_items/graphql/notes/work_item_note.fragment.graphql
index 973c6fde474..c8b7d379074 100644
--- a/app/assets/javascripts/work_items/graphql/notes/work_item_note.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/notes/work_item_note.fragment.graphql
@@ -10,6 +10,8 @@ fragment WorkItemNote on Note {
createdAt
lastEditedAt
url
+ authorIsContributor
+ maxAccessLevelOfAuthor
lastEditedBy {
...User
webPath
diff --git a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
index 02243baf28d..20a8d127e7d 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.fragment.graphql
@@ -11,10 +11,13 @@ fragment WorkItem on WorkItem {
createdAt
updatedAt
closedAt
+ reference(full: true)
+ createNoteEmail
project {
id
fullPath
archived
+ name
}
author {
...Author
diff --git a/app/assets/stylesheets/fonts.scss b/app/assets/stylesheets/fonts.scss
index 369f7072aa4..bc49d17fcbb 100644
--- a/app/assets/stylesheets/fonts.scss
+++ b/app/assets/stylesheets/fonts.scss
@@ -21,6 +21,7 @@ Usage:
*/
@font-face {
font-family: 'GitLab Mono';
+ font-weight: 100 900;
font-display: optional;
font-style: normal;
src: font-url('gitlab-mono/GitLabMono.woff2') format('woff2');
@@ -28,6 +29,7 @@ Usage:
@font-face {
font-family: 'GitLab Mono';
+ font-weight: 100 900;
font-display: optional;
font-style: italic;
src: font-url('gitlab-mono/GitLabMono-Italic.woff2') format('woff2');
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 27a6fc84209..bb1bfe8c889 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -1258,7 +1258,7 @@ module Ci
def id_tokens_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
id_tokens.each do |var_name, token_data|
- token = Gitlab::Ci::JwtV2.for_build(self, aud: token_data['aud'])
+ token = Gitlab::Ci::JwtV2.for_build(self, aud: expanded_id_token_aud(token_data['aud']))
variables.append(key: var_name, value: token, public: false, masked: true)
end
@@ -1267,6 +1267,19 @@ module Ci
end
end
+ def expanded_id_token_aud(aud)
+ return unless aud
+
+ strong_memoize_with(:expanded_id_token_aud, aud) do
+ # `aud` can be a string or an array of strings.
+ if aud.is_a?(Array)
+ aud.map { |x| ExpandVariables.expand(x, -> { scoped_variables.sort_and_expand_all }) }
+ else
+ ExpandVariables.expand(aud, -> { scoped_variables.sort_and_expand_all })
+ end
+ end
+ end
+
def cache_for_online_runners(&block)
Rails.cache.fetch(
['has-online-runners', id],