diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-27 21:11:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-27 21:11:02 +0300 |
commit | bd746eebdc82ea3731b38cd903a999569ff3b8be (patch) | |
tree | a5b9a018e89a20f53de13055bf975b62b8ccd595 /app | |
parent | 0407f1573d1b3468f9fdcdd363996acc9d3052b1 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
7 files changed, 188 insertions, 248 deletions
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js index 78e3f934183..97d8b206307 100644 --- a/app/assets/javascripts/blob_edit/edit_blob.js +++ b/app/assets/javascripts/blob_edit/edit_blob.js @@ -16,8 +16,10 @@ export default class EditBlob { constructor(options) { this.options = options; this.configureMonacoEditor(); + this.isMarkdown = this.options.isMarkdown; + this.markdownLivePreviewOpened = false; - if (this.options.isMarkdown) { + if (this.isMarkdown) { this.fetchMarkdownExtension(); } @@ -104,6 +106,13 @@ export default class EditBlob { this.$editModeLinks.on('click', (e) => this.editModeLinkClickHandler(e)); } + toggleMarkdownPreview(toOpen) { + if (toOpen !== this.markdownLivePreviewOpened) { + this.editor.markdownPreview?.eventEmitter.fire(); + this.markdownLivePreviewOpened = !this.markdownLivePreviewOpened; + } + } + editModeLinkClickHandler(e) { e.preventDefault(); @@ -115,25 +124,29 @@ export default class EditBlob { currentLink.parent().addClass('active hover'); - this.$editModePanes.hide(); - - currentPane.show(); - - if (paneId === '#preview') { - this.$toggleButton.hide(); - axios - .post(currentLink.data('previewUrl'), { - content: this.editor.getValue(), - }) - .then(({ data }) => { - currentPane.empty().append(data); - currentPane.renderGFM(); - }) - .catch(() => - createAlert({ - message: BLOB_PREVIEW_ERROR, - }), - ); + if (this.isMarkdown) { + this.toggleMarkdownPreview(paneId === '#preview'); + } else { + this.$editModePanes.hide(); + + currentPane.show(); + + if (paneId === '#preview') { + this.$toggleButton.hide(); + axios + .post(currentLink.data('previewUrl'), { + content: this.editor.getValue(), + }) + .then(({ data }) => { + currentPane.empty().append(data); + currentPane.renderGFM(); + }) + .catch(() => + createAlert({ + message: BLOB_PREVIEW_ERROR, + }), + ); + } } this.$toggleButton.show(); diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js index 999e91eed19..dd4a7a689d7 100644 --- a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js +++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js @@ -1,4 +1,4 @@ -import { KeyMod, KeyCode } from 'monaco-editor'; +import { KeyMod, KeyCode, Emitter } from 'monaco-editor'; import { debounce } from 'lodash'; import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants'; import { createAlert } from '~/flash'; @@ -56,6 +56,7 @@ export class EditorMarkdownPreviewExtension { layoutChangeListener: undefined, path: setupOptions.previewMarkdownPath, actionShowPreviewCondition: instance.createContextKey('toggleLivePreview', true), + eventEmitter: new Emitter(), }; this.toolbarButtons = []; @@ -71,6 +72,8 @@ export class EditorMarkdownPreviewExtension { EditorMarkdownPreviewExtension.resizePreviewLayout(instance, newWidth); } }); + + this.preview.eventEmitter.event(this.togglePreview.bind(this, instance)); } onBeforeUnuse(instance) { @@ -187,6 +190,31 @@ export class EditorMarkdownPreviewExtension { }); } + togglePreview(instance) { + if (!this.preview?.el) { + this.preview.el = setupDomElement({ injectToEl: instance.getDomNode().parentElement }); + } + this.togglePreviewLayout(instance); + this.togglePreviewPanel(instance); + + this.preview.actionShowPreviewCondition.set(!this.preview.actionShowPreviewCondition.get()); + + if (!this.preview?.shown) { + this.preview.modelChangeListener = instance.onDidChangeModelContent( + debounce(this.fetchPreview.bind(this, instance), EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY), + ); + } else { + this.preview.modelChangeListener.dispose(); + } + + this.preview.shown = !this.preview?.shown; + if (instance.toolbar) { + instance.toolbar.updateItem(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID, { + selected: this.preview.shown, + }); + } + } + provides() { return { markdownPreview: this.preview, @@ -195,33 +223,7 @@ export class EditorMarkdownPreviewExtension { setupPreviewAction: (instance) => this.setupPreviewAction(instance), - togglePreview: (instance) => { - if (!this.preview?.el) { - this.preview.el = setupDomElement({ injectToEl: instance.getDomNode().parentElement }); - } - this.togglePreviewLayout(instance); - this.togglePreviewPanel(instance); - - this.preview.actionShowPreviewCondition.set(!this.preview.actionShowPreviewCondition.get()); - - if (!this.preview?.shown) { - this.preview.modelChangeListener = instance.onDidChangeModelContent( - debounce( - this.fetchPreview.bind(this, instance), - EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY, - ), - ); - } else { - this.preview.modelChangeListener.dispose(); - } - - this.preview.shown = !this.preview?.shown; - if (instance.toolbar) { - instance.toolbar.updateItem(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID, { - selected: this.preview.shown, - }); - } - }, + togglePreview: (instance) => this.togglePreview(instance), }; } } diff --git a/app/assets/javascripts/invite_members/components/invite_members_modal.vue b/app/assets/javascripts/invite_members/components/invite_members_modal.vue index a334f5e4bf7..f61e822bf7e 100644 --- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue +++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue @@ -18,7 +18,8 @@ import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants'; import { getParameterValues } from '~/lib/utils/url_utility'; import { n__, sprintf } from '~/locale'; import { - CLOSE_TO_LIMIT_COUNT, + CLOSE_TO_LIMIT_VARIANT, + REACHED_LIMIT_VARIANT, USERS_FILTER_ALL, INVITE_MEMBERS_FOR_TASK, MEMBER_MODAL_LABELS, @@ -174,27 +175,11 @@ export default { isOnLearnGitlab() { return this.source === LEARN_GITLAB; }, - closeToLimit() { - if (this.usersLimitDataset.freeUsersLimit && this.usersLimitDataset.membersCount) { - return ( - this.usersLimitDataset.membersCount >= - this.usersLimitDataset.freeUsersLimit - CLOSE_TO_LIMIT_COUNT - ); - } - - return false; - }, - reachedLimit() { - if (this.usersLimitDataset.freeUsersLimit && this.usersLimitDataset.membersCount) { - return this.usersLimitDataset.membersCount >= this.usersLimitDataset.freeUsersLimit; - } - - return false; + showUserLimitNotification() { + return this.usersLimitDataset.reachedLimit || this.usersLimitDataset.closeToDashboardLimit; }, - formGroupDescription() { - return this.reachedLimit - ? this.$options.labels.placeHolderDisabled - : this.$options.labels.placeHolder; + limitVariant() { + return this.usersLimitDataset.reachedLimit ? REACHED_LIMIT_VARIANT : CLOSE_TO_LIMIT_VARIANT; }, errorList() { return Object.entries(this.invalidMembers).map(([member, error]) => { @@ -385,13 +370,11 @@ export default { :help-link="helpLink" :label-intro-text="labelIntroText" :label-search-field="$options.labels.searchField" - :form-group-description="formGroupDescription" + :form-group-description="$options.labels.placeHolder" :invalid-feedback-message="invalidFeedbackMessage" :is-loading="isLoading" :new-users-to-invite="newUsersToInvite" :root-group-id="rootId" - :close-to-limit="closeToLimit" - :reached-limit="reachedLimit" :users-limit-dataset="usersLimitDataset" @reset="resetFields" @submit="sendInvite" @@ -448,9 +431,8 @@ export default { </template> </gl-alert> <user-limit-notification - v-else - :close-to-limit="closeToLimit" - :reached-limit="reachedLimit" + v-else-if="showUserLimitNotification" + :limit-variant="limitVariant" :users-limit-dataset="usersLimitDataset" /> </template> diff --git a/app/assets/javascripts/invite_members/components/invite_modal_base.vue b/app/assets/javascripts/invite_members/components/invite_modal_base.vue index f917ebc35c2..e3511a49fc5 100644 --- a/app/assets/javascripts/invite_members/components/invite_modal_base.vue +++ b/app/assets/javascripts/invite_members/components/invite_modal_base.vue @@ -8,7 +8,6 @@ import { GlLink, GlSprintf, GlFormInput, - GlIcon, } from '@gitlab/ui'; import Tracking from '~/tracking'; import { sprintf } from '~/locale'; @@ -20,11 +19,8 @@ import { INVITE_BUTTON_TEXT, INVITE_BUTTON_TEXT_DISABLED, CANCEL_BUTTON_TEXT, - CANCEL_BUTTON_TEXT_DISABLED, HEADER_CLOSE_LABEL, ON_SHOW_TRACK_LABEL, - ON_CLOSE_TRACK_LABEL, - ON_SUBMIT_TRACK_LABEL, } from '../constants'; const DEFAULT_SLOT = 'default'; @@ -48,7 +44,6 @@ export default { GlDropdownItem, GlSprintf, GlFormInput, - GlIcon, ContentTransition, }, mixins: [Tracking.mixin()], @@ -131,16 +126,6 @@ export default { required: false, default: false, }, - closeToLimit: { - type: Boolean, - required: false, - default: false, - }, - reachedLimit: { - type: Boolean, - required: false, - default: false, - }, usersLimitDataset: { type: Object, required: false, @@ -175,20 +160,17 @@ export default { }, actionPrimary() { return { - text: this.reachedLimit ? INVITE_BUTTON_TEXT_DISABLED : this.submitButtonText, + text: this.submitButtonText, attributes: { variant: 'confirm', - disabled: this.reachedLimit ? false : this.submitDisabled, - loading: this.reachedLimit ? false : this.isLoading, + disabled: this.submitDisabled, + loading: this.isLoading, 'data-qa-selector': 'invite_button', - ...(this.reachedLimit && { href: this.usersLimitDataset.membersPath }), }, }; }, actionCancel() { - if (this.reachedLimit && this.usersLimitDataset.userNamespace) return undefined; - - if (this.closeToLimit && this.usersLimitDataset.userNamespace) { + if (this.usersLimitDataset.closeToDashboardLimit && this.usersLimitDataset.userNamespace) { return { text: INVITE_BUTTON_TEXT_DISABLED, attributes: { @@ -200,13 +182,9 @@ export default { } return { - text: this.reachedLimit ? CANCEL_BUTTON_TEXT_DISABLED : this.cancelButtonText, - ...(this.reachedLimit && { attributes: { href: this.usersLimitDataset.purchasePath } }), + text: this.cancelButtonText, }; }, - selectLabelClass() { - return `col-form-label ${this.reachedLimit ? 'gl-text-gray-500' : ''}`; - }, }, watch: { selectedAccessLevel: { @@ -226,23 +204,19 @@ export default { this.$emit('reset'); }, onShowModal() { - if (this.reachedLimit) { + if (this.usersLimitDataset.reachedLimit) { this.track('render', { category: 'default', label: ON_SHOW_TRACK_LABEL }); } }, onCloseModal(e) { - if (this.preventCancelDefault || this.reachedLimit) { + if (this.preventCancelDefault) { e.preventDefault(); } else { this.onReset(); this.$refs.modal.hide(); } - if (this.reachedLimit) { - this.track('click_button', { category: 'default', label: ON_CLOSE_TRACK_LABEL }); - } else { - this.$emit('cancel'); - } + this.$emit('cancel'); }, changeSelectedItem(item) { this.selectedAccessLevel = item; @@ -251,14 +225,10 @@ export default { // We never want to hide when submitting e.preventDefault(); - if (this.reachedLimit) { - this.track('click_button', { category: 'default', label: ON_SUBMIT_TRACK_LABEL }); - } else { - this.$emit('submit', { - accessLevel: this.selectedAccessLevel, - expiresAt: this.selectedDate, - }); - } + this.$emit('submit', { + accessLevel: this.selectedAccessLevel, + expiresAt: this.selectedDate, + }); }, }, HEADER_CLOSE_LABEL, @@ -311,71 +281,63 @@ export default { <gl-form-group :invalid-feedback="invalidFeedbackMessage" :state="exceptionState" + :description="formGroupDescription" data-testid="members-form-group" > - <template #description> - <gl-icon v-if="reachedLimit" name="lock" /> - {{ formGroupDescription }} - </template> - - <label :id="selectLabelId" :class="selectLabelClass">{{ labelSearchField }}</label> - <gl-form-input v-if="reachedLimit" data-testid="disabled-input" disabled /> - <slot v-else name="select" v-bind="{ exceptionState, labelId: selectLabelId }"></slot> + <label :id="selectLabelId" class="col-form-label">{{ labelSearchField }}</label> + <slot name="select" v-bind="{ exceptionState, labelId: selectLabelId }"></slot> </gl-form-group> - <template v-if="!reachedLimit"> - <label class="gl-font-weight-bold">{{ $options.ACCESS_LEVEL }}</label> - - <div class="gl-mt-2 gl-w-half gl-xs-w-full"> - <gl-dropdown - class="gl-shadow-none gl-w-full" - data-qa-selector="access_level_dropdown" - v-bind="$attrs" - :text="selectedRoleName" - > - <template v-for="(key, item) in accessLevels"> - <gl-dropdown-item - :key="key" - active-class="is-active" - is-check-item - :is-checked="key === selectedAccessLevel" - @click="changeSelectedItem(key)" - > - <div>{{ item }}</div> - </gl-dropdown-item> - </template> - </gl-dropdown> - </div> + <label class="gl-font-weight-bold">{{ $options.ACCESS_LEVEL }}</label> + <div class="gl-mt-2 gl-w-half gl-xs-w-full"> + <gl-dropdown + class="gl-shadow-none gl-w-full" + data-qa-selector="access_level_dropdown" + v-bind="$attrs" + :text="selectedRoleName" + > + <template v-for="(key, item) in accessLevels"> + <gl-dropdown-item + :key="key" + active-class="is-active" + is-check-item + :is-checked="key === selectedAccessLevel" + @click="changeSelectedItem(key)" + > + <div>{{ item }}</div> + </gl-dropdown-item> + </template> + </gl-dropdown> + </div> - <div class="gl-mt-2 gl-w-half gl-xs-w-full"> - <gl-sprintf :message="$options.READ_MORE_TEXT"> - <template #link="{ content }"> - <gl-link :href="helpLink" target="_blank">{{ content }}</gl-link> - </template> - </gl-sprintf> - </div> + <div class="gl-mt-2 gl-w-half gl-xs-w-full"> + <gl-sprintf :message="$options.READ_MORE_TEXT"> + <template #link="{ content }"> + <gl-link :href="helpLink" target="_blank">{{ content }}</gl-link> + </template> + </gl-sprintf> + </div> - <label class="gl-mt-5 gl-display-block" for="expires_at">{{ - $options.ACCESS_EXPIRE_DATE - }}</label> - <div class="gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block"> - <gl-datepicker - v-model="selectedDate" - class="gl-display-inline!" - :min-date="minDate" - :target="null" - > - <template #default="{ formattedDate }"> - <gl-form-input - class="gl-w-full" - :value="formattedDate" - :placeholder="__(`YYYY-MM-DD`)" - /> - </template> - </gl-datepicker> - </div> - <slot name="form-after"></slot> - </template> + <label class="gl-mt-5 gl-display-block" for="expires_at">{{ + $options.ACCESS_EXPIRE_DATE + }}</label> + <div class="gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block"> + <gl-datepicker + v-model="selectedDate" + class="gl-display-inline!" + :min-date="minDate" + :target="null" + > + <template #default="{ formattedDate }"> + <gl-form-input + class="gl-w-full" + :value="formattedDate" + :placeholder="__(`YYYY-MM-DD`)" + /> + </template> + </gl-datepicker> + </div> + <slot name="form-after"></slot> </template> <template v-for="{ key } in extraSlots" #[key]> diff --git a/app/assets/javascripts/invite_members/components/user_limit_notification.vue b/app/assets/javascripts/invite_members/components/user_limit_notification.vue index c3d9d959ef6..515dd3de319 100644 --- a/app/assets/javascripts/invite_members/components/user_limit_notification.vue +++ b/app/assets/javascripts/invite_members/components/user_limit_notification.vue @@ -5,9 +5,10 @@ import { n__, sprintf } from '~/locale'; import { WARNING_ALERT_TITLE, DANGER_ALERT_TITLE, - REACHED_LIMIT_MESSAGE, REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE, + REACHED_LIMIT_VARIANT, CLOSE_TO_LIMIT_MESSAGE, + CLOSE_TO_LIMIT_VARIANT, } from '../constants'; export default { @@ -15,87 +16,71 @@ export default { components: { GlAlert, GlSprintf, GlLink }, inject: ['name'], props: { - closeToLimit: { - type: Boolean, - required: true, - }, - reachedLimit: { - type: Boolean, + limitVariant: { + type: String, required: true, }, usersLimitDataset: { type: Object, - required: false, - default: () => ({}), + required: true, }, }, computed: { - freeUsersLimit() { - return this.usersLimitDataset.freeUsersLimit; - }, - membersCount() { - return this.usersLimitDataset.membersCount; - }, - newTrialRegistrationPath() { - return this.usersLimitDataset.newTrialRegistrationPath; - }, - purchasePath() { - return this.usersLimitDataset.purchasePath; - }, - warningAlertTitle() { - return sprintf(WARNING_ALERT_TITLE, { - count: this.freeUsersLimit - this.membersCount, - members: this.pluralMembers(this.freeUsersLimit - this.membersCount), - name: this.name, - }); - }, - dangerAlertTitle() { - return sprintf(DANGER_ALERT_TITLE, { - count: this.freeUsersLimit, - members: this.pluralMembers(this.freeUsersLimit), - name: this.name, - }); - }, - variant() { - return this.reachedLimit ? 'danger' : 'warning'; - }, - title() { - return this.reachedLimit ? this.dangerAlertTitle : this.warningAlertTitle; - }, - message() { - if (this.reachedLimit) { - return this.$options.i18n.reachedLimitUpgradeSuggestionMessage; - } - - return this.$options.i18n.closeToLimitMessage; + limitAttributes() { + return { + [CLOSE_TO_LIMIT_VARIANT]: { + variant: 'warning', + title: this.title(WARNING_ALERT_TITLE, this.usersLimitDataset.remainingSeats), + message: CLOSE_TO_LIMIT_MESSAGE, + }, + [REACHED_LIMIT_VARIANT]: { + variant: 'danger', + title: this.title(DANGER_ALERT_TITLE, this.usersLimitDataset.freeUsersLimit), + message: REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE, + }, + }; }, }, methods: { - pluralMembers(count) { - return n__('member', 'members', count); + title(titleTemplate, count) { + return sprintf(titleTemplate, { + count, + members: n__('member', 'members', count), + name: this.name, + }); }, }, - i18n: { - reachedLimitMessage: REACHED_LIMIT_MESSAGE, - reachedLimitUpgradeSuggestionMessage: REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE, - closeToLimitMessage: CLOSE_TO_LIMIT_MESSAGE, - }, }; </script> <template> <gl-alert - v-if="reachedLimit || closeToLimit" - :variant="variant" + :variant="limitAttributes[limitVariant].variant" :dismissible="false" - :title="title" + :title="limitAttributes[limitVariant].title" > - <gl-sprintf :message="message"> + <gl-sprintf :message="limitAttributes[limitVariant].message"> <template #trialLink="{ content }"> - <gl-link :href="newTrialRegistrationPath" class="gl-label-link">{{ content }}</gl-link> + <gl-link + :href="usersLimitDataset.newTrialRegistrationPath" + class="gl-label-link" + data-track-action="click_link" + :data-track-label="`start_trial_user_limit_notification_${limitVariant}`" + data-testid="trial-link" + > + {{ content }} + </gl-link> </template> <template #upgradeLink="{ content }"> - <gl-link :href="purchasePath" class="gl-label-link">{{ content }}</gl-link> + <gl-link + :href="usersLimitDataset.purchasePath" + class="gl-label-link" + data-track-action="click_link" + :data-track-label="`upgrade_user_limit_notification_${limitVariant}`" + data-testid="upgrade-link" + > + {{ content }} + </gl-link> </template> </gl-sprintf> </gl-alert> diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js index f502e1ea369..de7b1019782 100644 --- a/app/assets/javascripts/invite_members/constants.js +++ b/app/assets/javascripts/invite_members/constants.js @@ -1,6 +1,5 @@ import { s__ } from '~/locale'; -export const CLOSE_TO_LIMIT_COUNT = 2; export const SEARCH_DELAY = 200; export const VALID_TOKEN_BACKGROUND = 'gl-bg-green-100'; export const INVALID_TOKEN_BACKGROUND = 'gl-bg-red-100'; @@ -40,9 +39,6 @@ export const MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT = s__( ); export const MEMBERS_SEARCH_FIELD = s__('InviteMembersModal|Username or email address'); export const MEMBERS_PLACEHOLDER = s__('InviteMembersModal|Select members or type email addresses'); -export const MEMBERS_PLACEHOLDER_DISABLED = s__( - 'InviteMembersModal|This feature is disabled until this group has space for more members.', -); export const MEMBERS_TASKS_TO_BE_DONE_TITLE = s__( 'InviteMembersModal|Create issues for your new team member to work on (optional)', ); @@ -110,7 +106,6 @@ export const MEMBER_MODAL_LABELS = { }, searchField: MEMBERS_SEARCH_FIELD, placeHolder: MEMBERS_PLACEHOLDER, - placeHolderDisabled: MEMBERS_PLACEHOLDER_DISABLED, tasksToBeDone: { title: MEMBERS_TASKS_TO_BE_DONE_TITLE, noProjects: MEMBERS_TASKS_TO_BE_DONE_NO_PROJECTS, @@ -139,9 +134,7 @@ export const GROUP_MODAL_LABELS = { }; export const LEARN_GITLAB = 'learn_gitlab'; -export const ON_SHOW_TRACK_LABEL = 'locked_modal_viewed'; -export const ON_CLOSE_TRACK_LABEL = 'explore_paid_plans_clicked'; -export const ON_SUBMIT_TRACK_LABEL = 'manage_members_clicked'; +export const ON_SHOW_TRACK_LABEL = 'over_limit_modal_viewed'; export const WARNING_ALERT_TITLE = s__( 'InviteMembersModal|You only have space for %{count} more %{members} in %{name}', @@ -150,13 +143,16 @@ export const DANGER_ALERT_TITLE = s__( "InviteMembersModal|You've reached your %{count} %{members} limit for %{name}", ); +export const REACHED_LIMIT_VARIANT = 'reached'; +export const CLOSE_TO_LIMIT_VARIANT = 'close'; + export const REACHED_LIMIT_MESSAGE = s__( - 'InviteMembersModal|You cannot add more members, but you can remove members who no longer need access.', + 'InviteMembersModal|To invite new users to this namespace, you must remove existing users. You can still add existing namespace users.', ); export const REACHED_LIMIT_UPGRADE_SUGGESTION_MESSAGE = REACHED_LIMIT_MESSAGE.concat( s__( - 'InviteMembersModal| To get more members and access to additional paid features, an owner of the group can start a trial or upgrade to a paid tier.', + 'InviteMembersModal| To get more members, the owner of this namespace can %{trialLinkStart}start a trial%{trialLinkEnd} or %{upgradeLinkStart}upgrade%{upgradeLinkEnd} to a paid tier.', ), ); diff --git a/app/assets/javascripts/projects/compare/components/app.vue b/app/assets/javascripts/projects/compare/components/app.vue index 271694863e8..e4d5e5bd233 100644 --- a/app/assets/javascripts/projects/compare/components/app.vue +++ b/app/assets/javascripts/projects/compare/components/app.vue @@ -131,7 +131,7 @@ export default { <revision-card data-testid="sourceRevisionCard" :refs-project-path="to.refsProjectPath" - revision-text="Source" + :revision-text="__('Source')" params-name="to" :params-branch="to.revision" :projects="to.projects" @@ -160,7 +160,7 @@ export default { <revision-card data-testid="targetRevisionCard" :refs-project-path="from.refsProjectPath" - revision-text="Target" + :revision-text="__('Target')" params-name="from" :params-branch="from.revision" :projects="from.projects" |