Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
817de15424
commit
a075011d5b
|
|
@ -103,19 +103,6 @@ Layout/ArgumentAlignment:
|
|||
- 'ee/app/services/external_status_checks/create_service.rb'
|
||||
- 'ee/app/services/external_status_checks/destroy_service.rb'
|
||||
- 'ee/app/services/external_status_checks/update_service.rb'
|
||||
- 'ee/db/geo/post_migrate/20210217020154_add_unique_index_on_container_repository_registry.rb'
|
||||
- 'ee/db/geo/post_migrate/20210217020156_add_unique_index_on_terraform_state_version_registry.rb'
|
||||
- 'ee/lib/ee/gitlab/import_sources.rb'
|
||||
- 'ee/lib/ee/gitlab/middleware/read_only/controller.rb'
|
||||
- 'ee/lib/ee/gitlab/scim/group/deprovisioning_service.rb'
|
||||
- 'ee/lib/ee/gitlab/usage_data.rb'
|
||||
- 'ee/lib/elastic/latest/commit_config.rb'
|
||||
- 'ee/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary.rb'
|
||||
- 'ee/lib/gitlab/auth/smartcard/base.rb'
|
||||
- 'ee/lib/gitlab/elastic/indexer.rb'
|
||||
- 'ee/lib/gitlab/geo/git_ssh_proxy.rb'
|
||||
- 'ee/lib/gitlab/geo/replicator.rb'
|
||||
- 'ee/lib/gitlab/graphql/aggregations/epics/epic_node.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/scim/params_parser_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/scim/provisioning_service_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/usage/service_ping_report_spec.rb'
|
||||
|
|
|
|||
|
|
@ -64,19 +64,6 @@ Layout/FirstHashElementIndentation:
|
|||
- 'ee/spec/graphql/types/vulnerability_response_type_spec.rb'
|
||||
- 'ee/spec/helpers/billing_plans_helper_spec.rb'
|
||||
- 'ee/spec/helpers/groups/security_features_helper_spec.rb'
|
||||
- 'ee/spec/helpers/projects/security/discover_helper_spec.rb'
|
||||
- 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
|
||||
- 'ee/spec/lib/audit/compliance_framework_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/audit/external_status_check_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/audit/project_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/audit/project_ci_cd_setting_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/audit/project_setting_changes_auditor_spec.rb'
|
||||
- 'ee/spec/lib/ee/api/entities/experiment_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/auth/ldap/access_levels_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/background_migration/backfill_project_statistics_storage_size_without_uploads_size_spec.rb'
|
||||
- 'ee/spec/lib/ee/gitlab/ci/parsers/security/common_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/parsers/security/dast_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/ci/reports/coverage_fuzzing/report_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/geo/log_cursor/lease_spec.rb'
|
||||
- 'ee/spec/lib/gitlab/graphql/aggregations/epics/lazy_epic_aggregate_spec.rb'
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ $(document).on('markdown-preview:show', (e, $form) => {
|
|||
if (!$previewButton.parents('.js-vue-markdown-field').length) {
|
||||
$previewButton.val('edit');
|
||||
$previewButton.children('span.gl-button-text').text(__('Continue editing'));
|
||||
$previewButton.addClass('gl-shadow-none! gl-bg-transparent!');
|
||||
$previewButton.addClass('!gl-shadow-none gl-bg-transparent!');
|
||||
}
|
||||
|
||||
// toggle content
|
||||
|
|
@ -196,7 +196,7 @@ $(document).on('click', previewButtonSelector, function (e) {
|
|||
$(document).on('mousedown', previewButtonSelector, function (e) {
|
||||
e.preventDefault();
|
||||
const $form = $(this).closest('form');
|
||||
$form.find(previewButtonSelector).removeClass('gl-shadow-none! gl-bg-transparent!');
|
||||
$form.find(previewButtonSelector).removeClass('!gl-shadow-none gl-bg-transparent!');
|
||||
});
|
||||
|
||||
$(document).on('mouseenter', previewButtonSelector, function (e) {
|
||||
|
|
|
|||
|
|
@ -1,12 +1,5 @@
|
|||
<script>
|
||||
import {
|
||||
GlLabel,
|
||||
GlTooltip,
|
||||
GlTooltipDirective,
|
||||
GlIcon,
|
||||
GlLoadingIcon,
|
||||
GlSprintf,
|
||||
} from '@gitlab/ui';
|
||||
import { GlLabel, GlTooltipDirective, GlIcon, GlLoadingIcon } from '@gitlab/ui';
|
||||
import { sortBy } from 'lodash';
|
||||
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
|
||||
import { isScopedLabel, convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
|
||||
|
|
@ -24,7 +17,6 @@ import IssueTimeEstimate from './issue_time_estimate.vue';
|
|||
|
||||
export default {
|
||||
components: {
|
||||
GlTooltip,
|
||||
GlLabel,
|
||||
GlLoadingIcon,
|
||||
GlIcon,
|
||||
|
|
@ -34,11 +26,12 @@ export default {
|
|||
IssueCardWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
|
||||
IssueIteration: () => import('ee_component/boards/components/issue_iteration.vue'),
|
||||
IssuableBlockedIcon,
|
||||
GlSprintf,
|
||||
WorkItemTypeIcon,
|
||||
IssueMilestone,
|
||||
IssueHealthStatus: () =>
|
||||
import('ee_component/related_items_tree/components/issue_health_status.vue'),
|
||||
EpicCountables: () =>
|
||||
import('ee_else_ce/vue_shared/components/epic_countables/epic_countables.vue'),
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
|
|
@ -142,9 +135,6 @@ export default {
|
|||
shouldRenderEpicCountables() {
|
||||
return this.isEpicBoard && this.hasChildren;
|
||||
},
|
||||
shouldRenderEpicProgress() {
|
||||
return this.totalWeight > 0;
|
||||
},
|
||||
showLabelFooter() {
|
||||
return this.isShowingLabels && this.item.labels.find(this.showLabel);
|
||||
},
|
||||
|
|
@ -164,19 +154,17 @@ export default {
|
|||
}
|
||||
return __('Blocked issue');
|
||||
},
|
||||
descendantCounts() {
|
||||
return this.item.descendantCounts;
|
||||
},
|
||||
descendantWeightSum() {
|
||||
return this.item.descendantWeightSum;
|
||||
},
|
||||
totalEpicsCount() {
|
||||
return this.item.descendantCounts.openedEpics + this.item.descendantCounts.closedEpics;
|
||||
return this.descendantCounts.openedEpics + this.descendantCounts.closedEpics;
|
||||
},
|
||||
totalIssuesCount() {
|
||||
return this.item.descendantCounts.openedIssues + this.item.descendantCounts.closedIssues;
|
||||
},
|
||||
totalWeight() {
|
||||
return (
|
||||
this.item.descendantWeightSum.openedIssues + this.item.descendantWeightSum.closedIssues
|
||||
);
|
||||
},
|
||||
totalProgress() {
|
||||
return Math.round((this.item.descendantWeightSum.closedIssues / this.totalWeight) * 100);
|
||||
return this.descendantCounts.openedIssues + this.descendantCounts.closedIssues;
|
||||
},
|
||||
showReferencePath() {
|
||||
return this.isGroupBoard && this.itemReferencePath;
|
||||
|
|
@ -321,83 +309,16 @@ export default {
|
|||
</span>
|
||||
{{ itemId }}
|
||||
</span>
|
||||
<span v-if="shouldRenderEpicCountables" data-testid="epic-countables">
|
||||
<gl-tooltip :target="() => $refs.countBadge">
|
||||
<p v-if="allowSubEpics" class="gl-font-weight-bold gl-m-0">
|
||||
{{ __('Epics') }} •
|
||||
<span class="gl-font-weight-normal">
|
||||
<gl-sprintf :message="__('%{openedEpics} open, %{closedEpics} closed')">
|
||||
<template #openedEpics>{{ item.descendantCounts.openedEpics }}</template>
|
||||
<template #closedEpics>{{ item.descendantCounts.closedEpics }}</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</p>
|
||||
<p class="gl-font-weight-bold gl-m-0">
|
||||
{{ __('Issues') }} •
|
||||
<span class="gl-font-weight-normal">
|
||||
<gl-sprintf :message="__('%{openedIssues} open, %{closedIssues} closed')">
|
||||
<template #openedIssues>{{ item.descendantCounts.openedIssues }}</template>
|
||||
<template #closedIssues>{{ item.descendantCounts.closedIssues }}</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</p>
|
||||
<p class="gl-font-weight-bold gl-m-0">
|
||||
{{ __('Total weight') }} •
|
||||
<span class="gl-font-weight-normal" data-testid="epic-countables-total-weight">
|
||||
{{ totalWeight }}
|
||||
</span>
|
||||
</p>
|
||||
</gl-tooltip>
|
||||
|
||||
<gl-tooltip
|
||||
v-if="shouldRenderEpicProgress"
|
||||
:target="() => $refs.progressBadge"
|
||||
data-testid="epic-progress-tooltip"
|
||||
>
|
||||
<p class="gl-font-weight-bold gl-m-0">
|
||||
{{ __('Progress') }} •
|
||||
<span class="gl-font-weight-normal" data-testid="epic-progress-tooltip-content">
|
||||
<gl-sprintf
|
||||
:message="__('%{completedWeight} of %{totalWeight} weight completed')"
|
||||
>
|
||||
<template #completedWeight>{{
|
||||
item.descendantWeightSum.closedIssues
|
||||
}}</template>
|
||||
<template #totalWeight>{{ totalWeight }}</template>
|
||||
</gl-sprintf>
|
||||
</span>
|
||||
</p>
|
||||
</gl-tooltip>
|
||||
|
||||
<span
|
||||
ref="countBadge"
|
||||
class="board-card-info gl-mr-0 gl-pr-0 gl-pl-3 gl-text-secondary gl-cursor-help"
|
||||
>
|
||||
<span v-if="allowSubEpics" class="gl-mr-3">
|
||||
<gl-icon name="epic" />
|
||||
{{ totalEpicsCount }}
|
||||
</span>
|
||||
<span class="gl-mr-3" data-testid="epic-countables-counts-issues">
|
||||
<gl-icon name="issues" />
|
||||
{{ totalIssuesCount }}
|
||||
</span>
|
||||
<span class="gl-mr-3" data-testid="epic-countables-weight-issues">
|
||||
<gl-icon name="weight" />
|
||||
{{ totalWeight }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="shouldRenderEpicProgress"
|
||||
ref="progressBadge"
|
||||
class="board-card-info gl-pl-0 gl-text-secondary gl-cursor-help"
|
||||
>
|
||||
<span class="gl-mr-3" data-testid="epic-progress">
|
||||
<gl-icon name="progress" />
|
||||
{{ totalProgress }}%
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
<epic-countables
|
||||
v-if="shouldRenderEpicCountables"
|
||||
:allow-sub-epics="allowSubEpics"
|
||||
:opened-epics-count="descendantCounts.openedEpics"
|
||||
:closed-epics-count="descendantCounts.closedEpics"
|
||||
:opened-issues-count="descendantCounts.openedIssues"
|
||||
:closed-issues-count="descendantCounts.closedIssues"
|
||||
:opened-issues-weight="descendantWeightSum.openedIssues"
|
||||
:closed-issues-weight="descendantWeightSum.closedIssues"
|
||||
/>
|
||||
<span v-if="!isEpicBoard">
|
||||
<issue-card-weight
|
||||
v-if="validIssueWeight(item)"
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default {
|
|||
: ['gl-border-l-0!', ...this.$options.styles.flatLeftBorder];
|
||||
},
|
||||
buttonShadowClass() {
|
||||
return this.isExpandBtnFocus ? '' : 'gl-shadow-none!';
|
||||
return this.isExpandBtnFocus ? '' : '!gl-shadow-none';
|
||||
},
|
||||
buttonId() {
|
||||
return `js-linked-pipeline-${this.pipeline.id}`;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ export default {
|
|||
this.editor
|
||||
.chain()
|
||||
.focus()
|
||||
.updateAttributes(this.node.type, {
|
||||
.updateAttributes(this.node.type.name, {
|
||||
width: this.$refs.image.width,
|
||||
height: this.$refs.image.height,
|
||||
})
|
||||
|
|
@ -103,6 +103,8 @@ export default {
|
|||
></span>
|
||||
<img
|
||||
ref="image"
|
||||
draggable="true"
|
||||
data-drag-handle
|
||||
:src="node.attrs.src"
|
||||
:alt="node.attrs.alt"
|
||||
:title="node.attrs.title"
|
||||
|
|
|
|||
|
|
@ -11,28 +11,10 @@ export default {
|
|||
GlLink,
|
||||
},
|
||||
props: {
|
||||
getPos: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
editor: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
node: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dragData: {},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isStaleUploadedMedia() {
|
||||
|
|
@ -53,9 +35,17 @@ export default {
|
|||
:src="node.attrs.src"
|
||||
controls="true"
|
||||
data-setup="{}"
|
||||
draggable="true"
|
||||
data-drag-handle=""
|
||||
:data-title="node.attrs.title || node.attrs.alt"
|
||||
/>
|
||||
<gl-link :href="node.attrs.src" class="with-attachment-icon" target="_blank">
|
||||
<gl-link
|
||||
:href="node.attrs.src"
|
||||
class="with-attachment-icon"
|
||||
target="_blank"
|
||||
draggable="true"
|
||||
data-drag-handle=""
|
||||
>
|
||||
{{ node.attrs.title || node.attrs.alt }}
|
||||
</gl-link>
|
||||
</node-view-wrapper>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ const resolveImageEl = (element) =>
|
|||
element.nodeName === 'IMG' ? element : element.querySelector('img');
|
||||
|
||||
export default Image.extend({
|
||||
draggable: true,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
...this.parent?.(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import ListItem from '@tiptap/extension-list-item';
|
||||
|
||||
export default ListItem.extend({
|
||||
draggable: true,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
...this.parent?.(),
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import { TaskItem } from '@tiptap/extension-task-item';
|
|||
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
|
||||
|
||||
export default TaskItem.extend({
|
||||
draggable: true,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
...this.parent?.(),
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ export default {
|
|||
<gl-dropdown
|
||||
:text="__('Recent searches')"
|
||||
class="filtered-search-history-dropdown-wrapper"
|
||||
toggle-class="filtered-search-history-dropdown-toggle-button gl-shadow-none! gl-border-r-gray-200! gl-border-1! gl-rounded-0!"
|
||||
toggle-class="filtered-search-history-dropdown-toggle-button !gl-shadow-none gl-border-r-gray-200! gl-border-1! gl-rounded-0!"
|
||||
:disabled="loading"
|
||||
>
|
||||
<div v-if="!$options.hasLocalStorage" class="gl-px-5">
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default {
|
|||
:class="{
|
||||
'disabled-content': !filesLength,
|
||||
}"
|
||||
class="gl-shadow-none!"
|
||||
class="!gl-shadow-none"
|
||||
category="tertiary"
|
||||
icon="remove-all"
|
||||
data-placement="bottom"
|
||||
|
|
|
|||
|
|
@ -307,7 +307,7 @@ export default {
|
|||
</ul>
|
||||
</gl-collapse>
|
||||
<gl-button
|
||||
class="gl-text-decoration-none! gl-shadow-none! gl-mt-3"
|
||||
class="gl-text-decoration-none! !gl-shadow-none gl-mt-3"
|
||||
data-testid="accordion-button"
|
||||
variant="link"
|
||||
@click="toggleErrorExpansion"
|
||||
|
|
|
|||
|
|
@ -438,7 +438,7 @@ export default {
|
|||
</ul>
|
||||
</gl-collapse>
|
||||
<gl-button
|
||||
class="gl-text-decoration-none! gl-shadow-none! gl-mt-3"
|
||||
class="gl-text-decoration-none! !gl-shadow-none gl-mt-3"
|
||||
data-testid="accordion-button"
|
||||
variant="link"
|
||||
@click="toggleErrorExpansion"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { GlTabs, GlTab, GlBadge, GlButton } from '@gitlab/ui';
|
|||
// eslint-disable-next-line no-restricted-imports
|
||||
import { mapState } from 'vuex';
|
||||
import { queryToObject } from '~/lib/utils/url_utility';
|
||||
import { MEMBER_TYPES, TABS, ACTIVE_TAB_QUERY_PARAM_NAME } from 'ee_else_ce/members/constants';
|
||||
import { MEMBER_TYPES, ACTIVE_TAB_QUERY_PARAM_NAME } from 'ee_else_ce/members/constants';
|
||||
import { TABS } from 'ee_else_ce/members/tabs_metadata';
|
||||
import MembersApp from './app.vue';
|
||||
|
||||
const countComputed = (state, namespace) => state[namespace]?.pagination?.totalItems || 0;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import { GlFilteredSearchToken } from '@gitlab/ui';
|
|||
import { __, s__ } from '~/locale';
|
||||
import { OPERATORS_IS } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
|
||||
import PlaceholdersTabApp from './components/placeholders/app.vue';
|
||||
|
||||
// Overridden in EE
|
||||
export const EE_GROUPS_APP_OPTIONS = {};
|
||||
export const EE_PROJECTS_APP_OPTIONS = {};
|
||||
|
|
@ -184,38 +182,6 @@ export const TAB_QUERY_PARAM_VALUES = Object.freeze({
|
|||
placeholder: 'placeholders',
|
||||
});
|
||||
|
||||
// Overridden in EE
|
||||
export const TABS = [
|
||||
{
|
||||
namespace: MEMBER_TYPES.user,
|
||||
title: __('Members'),
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.group,
|
||||
title: __('Groups'),
|
||||
attrs: { 'data-testid': 'groups-list-tab' },
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.group,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.invite,
|
||||
title: s__('Members|Pending invitations'),
|
||||
requiredPermissions: ['canManageMembers'],
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.invite,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.accessRequest,
|
||||
title: __('Access requests'),
|
||||
requiredPermissions: ['canManageAccessRequests'],
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.accessRequest,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.placeholder,
|
||||
title: s__('UserMapping|Placeholders'),
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.placeholder,
|
||||
component: PlaceholdersTabApp,
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* This user state value comes from the User model
|
||||
* see the state machine in app/models/user.rb
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Vuex from 'vuex';
|
|||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import { parseDataAttributes } from '~/members/utils';
|
||||
import { TABS } from 'ee_else_ce/members/constants';
|
||||
import { TABS } from 'ee_else_ce/members/tabs_metadata';
|
||||
import MembersTabs from './components/members_tabs.vue';
|
||||
import membersStore from './store';
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
import { __, s__ } from '~/locale';
|
||||
import PlaceholdersTabApp from './components/placeholders/app.vue';
|
||||
import { MEMBER_TYPES, TAB_QUERY_PARAM_VALUES } from './constants';
|
||||
|
||||
// Overridden in EE
|
||||
export const TABS = [
|
||||
{
|
||||
namespace: MEMBER_TYPES.user,
|
||||
title: __('Members'),
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.group,
|
||||
title: __('Groups'),
|
||||
attrs: { 'data-testid': 'groups-list-tab' },
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.group,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.invite,
|
||||
title: s__('Members|Pending invitations'),
|
||||
requiredPermissions: ['canManageMembers'],
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.invite,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.accessRequest,
|
||||
title: __('Access requests'),
|
||||
requiredPermissions: ['canManageAccessRequests'],
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.accessRequest,
|
||||
},
|
||||
{
|
||||
namespace: MEMBER_TYPES.placeholder,
|
||||
title: s__('UserMapping|Placeholders'),
|
||||
queryParamValue: TAB_QUERY_PARAM_VALUES.placeholder,
|
||||
component: PlaceholdersTabApp,
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
<script>
|
||||
import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { n__ } from '~/locale';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlBadge,
|
||||
},
|
||||
directives: {
|
||||
GlTooltip: GlTooltipDirective,
|
||||
},
|
||||
props: {
|
||||
mergeRequest: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
hasApprovers() {
|
||||
return this.mergeRequest.approvedBy.nodes.length;
|
||||
},
|
||||
tooltipTitle() {
|
||||
return n__('%d approver', '%d approvers', this.mergeRequest.approvedBy.nodes.length);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-badge v-if="hasApprovers" v-gl-tooltip="tooltipTitle" icon="approval" variant="success">
|
||||
{{ __('Approved') }}
|
||||
</gl-badge>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,99 @@
|
|||
import MergeRequest from './merge_request.vue';
|
||||
|
||||
const mockMergeRequest = {
|
||||
reference: '!123456',
|
||||
titleHtml: 'Merge request title',
|
||||
webUrl: '#',
|
||||
author: {
|
||||
name: 'John Smith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
},
|
||||
milestone: {
|
||||
title: '17.0',
|
||||
},
|
||||
labels: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/992791',
|
||||
color: '#428BCA',
|
||||
title: 'Deliverable',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/3103452',
|
||||
color: '#E44D2A',
|
||||
title: 'devops::create',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/2975007',
|
||||
color: '#F0AD4E',
|
||||
title: 'feature::enhancement',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/3412464',
|
||||
color: '#3cb371',
|
||||
title: 'frontend',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/16934793',
|
||||
color: '#A8D695',
|
||||
title: 'group::code review',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/14918378',
|
||||
color: '#F0AD4E',
|
||||
title: 'section::dev',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/10230929',
|
||||
color: '#009966',
|
||||
title: 'type::feature',
|
||||
description: 'Label description',
|
||||
},
|
||||
],
|
||||
},
|
||||
assignees: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/User/1',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
],
|
||||
},
|
||||
reviewers: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/User/1',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/User/2',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
],
|
||||
},
|
||||
userDiscussionsCount: 5,
|
||||
createdAt: '2024-04-22T10:13:09Z',
|
||||
updatedAt: '2024-04-19T14:34:42Z',
|
||||
};
|
||||
|
||||
const Template = (_, { argTypes }) => {
|
||||
return {
|
||||
components: { MergeRequest },
|
||||
|
|
@ -15,106 +109,25 @@ export default {
|
|||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
mergeRequest: mockMergeRequest,
|
||||
};
|
||||
|
||||
export const WithApprovalNeeded = Template.bind({});
|
||||
WithApprovalNeeded.args = {
|
||||
mergeRequest: {
|
||||
reference: '!123456',
|
||||
titleHtml: 'Merge request title',
|
||||
webUrl: '#',
|
||||
author: {
|
||||
name: 'John Smith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
},
|
||||
milestone: {
|
||||
title: '17.0',
|
||||
},
|
||||
labels: {
|
||||
...mockMergeRequest,
|
||||
approved: false,
|
||||
approvalsRequired: 4,
|
||||
approvalsLeft: 2,
|
||||
approvedBy: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/992791',
|
||||
color: '#428BCA',
|
||||
title: 'Deliverable',
|
||||
description: 'Label description',
|
||||
id: 1,
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/3103452',
|
||||
color: '#E44D2A',
|
||||
title: 'devops::create',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/2975007',
|
||||
color: '#F0AD4E',
|
||||
title: 'feature::enhancement',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/3412464',
|
||||
color: '#3cb371',
|
||||
title: 'frontend',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/16934793',
|
||||
color: '#A8D695',
|
||||
title: 'group::code review',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/14918378',
|
||||
color: '#F0AD4E',
|
||||
title: 'section::dev',
|
||||
description: 'Label description',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/GroupLabel/10230929',
|
||||
color: '#009966',
|
||||
title: 'type::feature',
|
||||
description: 'Label description',
|
||||
id: 2,
|
||||
},
|
||||
],
|
||||
},
|
||||
assignees: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/User/1',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
],
|
||||
},
|
||||
reviewers: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'gid://gitlab/User/1',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
{
|
||||
id: 'gid://gitlab/User/2',
|
||||
avatarUrl: '',
|
||||
name: 'John Smith',
|
||||
username: 'jsmith',
|
||||
webUrl: 'https://gitlab.com/root',
|
||||
webPath: '/root',
|
||||
},
|
||||
],
|
||||
},
|
||||
headPipeline: {
|
||||
id: 'gid://gitlab/Ci::Pipeline/1',
|
||||
detailedStatus: {
|
||||
id: 'success-1',
|
||||
icon: 'status_success',
|
||||
text: 'Passed',
|
||||
detailsPath: '/',
|
||||
},
|
||||
},
|
||||
userDiscussionsCount: 5,
|
||||
createdAt: '2024-04-22T10:13:09Z',
|
||||
updatedAt: '2024-04-19T14:34:42Z',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlLink, GlSprintf, GlIcon, GlLabel, GlTooltipDirective } from '@gitlab/ui';
|
||||
import ApprovalCount from 'ee_component/merge_request_dashboard/components/approval_count.vue';
|
||||
import { __, sprintf } from '~/locale';
|
||||
import isShowingLabelsQuery from '~/graphql_shared/client/is_showing_labels.query.graphql';
|
||||
import SafeHtml from '~/vue_shared/directives/safe_html';
|
||||
|
|
@ -23,6 +24,7 @@ export default {
|
|||
CiIcon,
|
||||
TimeAgoTooltip,
|
||||
UserAvatarLink,
|
||||
ApprovalCount,
|
||||
},
|
||||
directives: {
|
||||
SafeHtml,
|
||||
|
|
@ -115,6 +117,12 @@ export default {
|
|||
:class="{ 'gl-mr-2': index !== mergeRequest.reviewers.nodes.length - 1 }"
|
||||
/>
|
||||
</li>
|
||||
<li
|
||||
v-if="mergeRequest.approvalsRequired || mergeRequest.approved"
|
||||
class="gl-ml-4 gl-display-flex gl-align-self-center"
|
||||
>
|
||||
<approval-count :merge-request="mergeRequest" />
|
||||
</li>
|
||||
<li
|
||||
v-if="mergeRequest.userDiscussionsCount"
|
||||
v-gl-tooltip="__('Comments')"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#import "~/graphql_shared/fragments/label.fragment.graphql"
|
||||
#import "~/graphql_shared/fragments/milestone.fragment.graphql"
|
||||
#import "~/graphql_shared/fragments/ci_icon.fragment.graphql"
|
||||
#import "ee_else_ce/merge_request_dashboard/queries/merge_request_approval.fragment.graphql"
|
||||
|
||||
fragment MergeRequestDashboardFragment on MergeRequest {
|
||||
id
|
||||
|
|
@ -38,4 +39,5 @@ fragment MergeRequestDashboardFragment on MergeRequest {
|
|||
userDiscussionsCount
|
||||
createdAt
|
||||
updatedAt
|
||||
...MergeRequestApprovalFragment
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
fragment MergeRequestApprovalFragment on MergeRequest {
|
||||
approved
|
||||
approvedBy {
|
||||
nodes {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<gl-disclosure-dropdown
|
||||
placement="right"
|
||||
placement="bottom-end"
|
||||
category="tertiary"
|
||||
:aria-label="__('More actions')"
|
||||
icon="ellipsis_v"
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ export default {
|
|||
modal-id="fork-sync-conflicts-modal"
|
||||
:text="instructionsStep1"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-shadow-none! gl-bg-transparent! gl-flex-shrink-0"
|
||||
class="!gl-shadow-none gl-bg-transparent! gl-flex-shrink-0"
|
||||
/>
|
||||
</div>
|
||||
<p>
|
||||
|
|
@ -112,7 +112,7 @@ export default {
|
|||
modal-id="fork-sync-conflicts-modal"
|
||||
:text="instructionsStep2"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-shadow-none! gl-bg-transparent! gl-flex-shrink-0"
|
||||
class="!gl-shadow-none gl-bg-transparent! gl-flex-shrink-0"
|
||||
/>
|
||||
</div>
|
||||
<p>
|
||||
|
|
@ -127,7 +127,7 @@ export default {
|
|||
modal-id="fork-sync-conflicts-modal"
|
||||
:text="$options.instructionsStep3"
|
||||
:title="$options.i18n.copyToClipboard"
|
||||
class="gl-shadow-none! gl-bg-transparent! gl-flex-shrink-0 gl-ml-3"
|
||||
class="!gl-shadow-none gl-bg-transparent! gl-flex-shrink-0 gl-ml-3"
|
||||
/>
|
||||
</div>
|
||||
<template #modal-footer>
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ export default {
|
|||
regexButtonHighlightClass() {
|
||||
return {
|
||||
'gl-bg-blue-50!': this.regexButtonState,
|
||||
'gl-shadow-none!': !this.regexButtonState,
|
||||
'!gl-shadow-none': !this.regexButtonState,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ export default {
|
|||
category="secondary"
|
||||
data-testid="subscribe-button"
|
||||
:title="notificationTooltip"
|
||||
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! gl-shadow-none!"
|
||||
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! !gl-shadow-none"
|
||||
@click="toggleSubscribed"
|
||||
>
|
||||
<gl-icon :name="notificationIcon" :size="16" :class="{ 'gl-fill-blue-500': subscribed }" />
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ export default {
|
|||
:title="tootltipTitle"
|
||||
category="tertiary"
|
||||
type="reset"
|
||||
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! gl-shadow-none!"
|
||||
class="sidebar-collapsed-icon sidebar-collapsed-container gl-rounded-0! !gl-shadow-none"
|
||||
@click.stop.prevent="toggleTodo"
|
||||
>
|
||||
<gl-icon :class="{ 'todo-undone': hasTodo }" :name="collapsedButtonIcon" />
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export default {
|
|||
<template>
|
||||
<gl-disclosure-dropdown
|
||||
:items="items"
|
||||
placement="center"
|
||||
placement="bottom"
|
||||
@shown="$emit('shown')"
|
||||
@hidden="$emit('hidden')"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ export default {
|
|||
ITEM_LOADING: {
|
||||
id: 'loading',
|
||||
text: 'loading',
|
||||
extraAttrs: { disabled: true, class: 'gl-shadow-none!' },
|
||||
extraAttrs: { disabled: true, class: '!gl-shadow-none' },
|
||||
},
|
||||
ITEM_EMPTY: {
|
||||
id: 'empty',
|
||||
text: s__('Organization|No organizations available to switch to.'),
|
||||
extraAttrs: { disabled: true, class: 'gl-shadow-none! gl-text-secondary' },
|
||||
extraAttrs: { disabled: true, class: '!gl-shadow-none gl-text-secondary' },
|
||||
},
|
||||
i18n: {
|
||||
currentOrganization: s__('Organization|Current organization'),
|
||||
|
|
@ -135,7 +135,7 @@ export default {
|
|||
<gl-disclosure-dropdown
|
||||
:items="items"
|
||||
class="gl-display-block"
|
||||
placement="center"
|
||||
placement="bottom"
|
||||
@shown="onShown"
|
||||
>
|
||||
<template #toggle>
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ export default {
|
|||
right
|
||||
:data-testid="`terraform-state-actions-${state.name}`"
|
||||
:disabled="loading"
|
||||
toggle-class="gl-px-3! gl-shadow-none!"
|
||||
toggle-class="gl-px-3! !gl-shadow-none"
|
||||
>
|
||||
<template #button-content>
|
||||
<gl-icon class="gl-mr-0" name="ellipsis_v" />
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ export default {
|
|||
<clipboard-button
|
||||
:text="mergeInfo1"
|
||||
:title="$options.i18n.copyCommands"
|
||||
class="gl-shadow-none! gl-bg-transparent! gl-flex-shrink-0"
|
||||
class="!gl-shadow-none gl-bg-transparent! gl-flex-shrink-0"
|
||||
/>
|
||||
</div>
|
||||
<p v-if="reviewingDocsPath">
|
||||
|
|
@ -181,7 +181,7 @@ export default {
|
|||
<clipboard-button
|
||||
:text="mergeInfo2"
|
||||
:title="$options.i18n.copyCommands"
|
||||
class="gl-shadow-none! gl-bg-transparent! gl-flex-shrink-0"
|
||||
class="!gl-shadow-none gl-bg-transparent! gl-flex-shrink-0"
|
||||
/>
|
||||
</div>
|
||||
</gl-modal>
|
||||
|
|
|
|||
|
|
@ -7,15 +7,17 @@ export default {
|
|||
components: { HoverBadge },
|
||||
i18n: {
|
||||
badgeLabel: s__('BetaBadge|Beta'),
|
||||
popoverTitle: s__("BetaBadge|What's Beta?"),
|
||||
popoverTitle: s__("BetaBadge|What's a beta?"),
|
||||
descriptionParagraph: s__(
|
||||
"BetaBadge|A Beta feature is not production-ready, but is unlikely to change drastically before it's released. We encourage users to try Beta features and provide feedback.",
|
||||
"BetaBadge|A beta feature is not yet production-ready, but is ready for testing and unlikely to change significantly before it's released.",
|
||||
),
|
||||
listIntroduction: s__('BetaBadge|A Beta feature:'),
|
||||
listItemStability: s__('BetaBadge|May be unstable.'),
|
||||
listItemDataLoss: s__('BetaBadge|Should not cause data loss.'),
|
||||
listItemReasonableEffort: s__('BetaBadge|Is supported by a commercially reasonable effort.'),
|
||||
listItemNearCompletion: s__('BetaBadge|Is complete or near completion.'),
|
||||
listIntroduction: s__('BetaBadge|Beta features:'),
|
||||
listItemStability: s__('BetaBadge|Have a low risk of data loss, but might still be unstable.'),
|
||||
listItemReasonableEffort: s__(
|
||||
'BetaBadge|Are supported on a commercially-reasonable effort basis.',
|
||||
),
|
||||
listItemNearCompletion: s__('BetaBadge|Have a near complete user experience.'),
|
||||
listItemTestAgreement: s__('BetaBadge|Are subject to the GitLab Testing Agreement.'),
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
|
|
@ -48,9 +50,9 @@ export default {
|
|||
|
||||
<ul class="gl-pl-4">
|
||||
<li>{{ $options.i18n.listItemStability }}</li>
|
||||
<li>{{ $options.i18n.listItemDataLoss }}</li>
|
||||
<li>{{ $options.i18n.listItemReasonableEffort }}</li>
|
||||
<li>{{ $options.i18n.listItemNearCompletion }}</li>
|
||||
<li>{{ $options.i18n.listItemTestAgreement }}</li>
|
||||
</ul>
|
||||
</hover-badge>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ export default {
|
|||
components: { HoverBadge },
|
||||
i18n: {
|
||||
badgeLabel: s__('ExperimentBadge|Experiment'),
|
||||
popoverTitle: s__("ExperimentBadge|What's an Experiment?"),
|
||||
popoverTitle: s__("ExperimentBadge|What's an experiment?"),
|
||||
descriptionParagraph: s__(
|
||||
"ExperimentBadge|An Experiment is a feature that's in the process of being developed. It's not production-ready. We encourage users to try Experimental features and provide feedback.",
|
||||
'ExperimentBadge|An experiment is not yet production-ready, but is released for initial testing and feedback during development.',
|
||||
),
|
||||
listIntroduction: s__('ExperimentBadge|An Experiment:'),
|
||||
listItemStability: s__('ExperimentBadge|May be unstable.'),
|
||||
listItemDataLoss: s__('ExperimentBadge|Can cause data loss.'),
|
||||
listItemNoSupport: s__('ExperimentBadge|Has no support and might not be documented.'),
|
||||
listItemCanBeRemoved: s__('ExperimentBadge|Can be removed at any time.'),
|
||||
listIntroduction: s__('ExperimentBadge|Experiments:'),
|
||||
listItemStability: s__('ExperimentBadge|Might be unstable or cause data loss.'),
|
||||
listItemNoSupport: s__('ExperimentBadge|Are not supported and might not be documented.'),
|
||||
listItemCanBeRemoved: s__('ExperimentBadge|Could be changed or removed at any time.'),
|
||||
listItemTestAgreement: s__('ExperimentBadge|Are subject to the GitLab Testing Agreement.'),
|
||||
},
|
||||
props: {
|
||||
size: {
|
||||
|
|
@ -35,9 +35,9 @@ export default {
|
|||
|
||||
<ul class="gl-pl-4">
|
||||
<li>{{ $options.i18n.listItemStability }}</li>
|
||||
<li>{{ $options.i18n.listItemDataLoss }}</li>
|
||||
<li>{{ $options.i18n.listItemNoSupport }}</li>
|
||||
<li>{{ $options.i18n.listItemCanBeRemoved }}</li>
|
||||
<li>{{ $options.i18n.listItemTestAgreement }}</li>
|
||||
</ul>
|
||||
</hover-badge>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -158,13 +158,13 @@ export default {
|
|||
>
|
||||
<a
|
||||
v-if="showBlameLink"
|
||||
class="gl-select-none gl-shadow-none! file-line-blame gl-mx-n2"
|
||||
class="gl-select-none !gl-shadow-none file-line-blame gl-mx-n2"
|
||||
:href="`${blamePath}#L${line}`"
|
||||
></a>
|
||||
<a
|
||||
:id="`L${line}`"
|
||||
:key="line"
|
||||
class="gl-select-none gl-shadow-none! file-line-num"
|
||||
class="gl-select-none !gl-shadow-none file-line-num"
|
||||
:href="`#L${line}`"
|
||||
:data-line-number="line"
|
||||
@click="scrollToLine(`#LC${line}`)"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
<script>
|
||||
export default {};
|
||||
</script>
|
||||
<template>
|
||||
<!-- This is intentionally left blank -->
|
||||
<div></div>
|
||||
</template>
|
||||
|
|
@ -221,7 +221,7 @@ export default {
|
|||
<div class="gl-w-full gl-display-flex gl-flex-direction-row gl-justify-content-space-between">
|
||||
<div class="gl-display-flex gl-flex-direction-row gl-align-items-center gl-w-full">
|
||||
<gl-button
|
||||
class="collapsible-card-btn gl-display-flex gl-text-decoration-none gl-reset-color! gl-hover-text-blue-800! gl-shadow-none!"
|
||||
class="collapsible-card-btn gl-display-flex gl-text-decoration-none gl-reset-color! gl-hover-text-blue-800! !gl-shadow-none"
|
||||
:aria-label="filename"
|
||||
variant="link"
|
||||
category="tertiary"
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@ export default {
|
|||
class="gl-p-0! gl-absolute gl-z-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
|
||||
>
|
||||
<a
|
||||
class="gl-select-none gl-shadow-none! file-line-blame gl-mx-n2 gl-flex-grow-1"
|
||||
class="gl-select-none !gl-shadow-none file-line-blame gl-mx-n2 gl-flex-grow-1"
|
||||
:href="`${blamePath}${pageSearchString}#L${number}`"
|
||||
></a>
|
||||
<a
|
||||
:id="`L${number}`"
|
||||
class="gl-select-none gl-shadow-none! file-line-num"
|
||||
class="gl-select-none !gl-shadow-none file-line-num"
|
||||
:href="`#L${number}`"
|
||||
:data-line-number="number"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -92,13 +92,13 @@ export default {
|
|||
class="gl-p-0! gl-z-3 diff-line-num gl-border-r gl-display-flex line-links line-numbers"
|
||||
>
|
||||
<a
|
||||
class="gl-select-none gl-shadow-none! file-line-blame"
|
||||
class="gl-select-none !gl-shadow-none file-line-blame"
|
||||
data-event-tracking="click_chunk_blame_on_blob_page"
|
||||
:href="`${blamePath}${pageSearchString}#L${calculateLineNumber(index)}`"
|
||||
></a>
|
||||
<a
|
||||
:id="`L${calculateLineNumber(index)}`"
|
||||
class="gl-select-none gl-shadow-none! file-line-num"
|
||||
class="gl-select-none !gl-shadow-none file-line-num"
|
||||
:href="`#L${calculateLineNumber(index)}`"
|
||||
:data-line-number="calculateLineNumber(index)"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ export default {
|
|||
v-gl-tooltip.hover.left
|
||||
category="tertiary"
|
||||
size="small"
|
||||
class="gl-float-right gutter-toggle toggle-right-sidebar-button js-toggle-right-sidebar-button gl-shadow-none!"
|
||||
class="gl-float-right gutter-toggle toggle-right-sidebar-button js-toggle-right-sidebar-button !gl-shadow-none"
|
||||
:class="collapsedToggleClass"
|
||||
data-testid="toggle-right-sidebar-button"
|
||||
:icon="toggleIcon"
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ export default {
|
|||
return data.workspace?.workItemTypes?.nodes;
|
||||
},
|
||||
skip() {
|
||||
return !this.canUpdate;
|
||||
return !this.canUpdate || this.workItemType !== WORK_ITEM_TYPE_VALUE_KEY_RESULT;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import toast from '~/vue_shared/plugins/global_toast';
|
|||
import { isLoggedIn } from '~/lib/utils/common_utils';
|
||||
|
||||
import updateWorkItemNotificationsMutation from '../graphql/update_work_item_notifications.mutation.graphql';
|
||||
import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
|
||||
|
||||
const ICON_ON = 'notifications';
|
||||
const ICON_OFF = 'notifications-off';
|
||||
|
|
@ -58,22 +57,6 @@ export default {
|
|||
emailsDisabled: false,
|
||||
};
|
||||
},
|
||||
apollo: {
|
||||
workItemTypes: {
|
||||
query: projectWorkItemTypesQuery,
|
||||
variables() {
|
||||
return {
|
||||
fullPath: this.fullPath,
|
||||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.workspace?.workItemTypes?.nodes;
|
||||
},
|
||||
skip() {
|
||||
return !this.canUpdate;
|
||||
},
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
notificationTooltip() {
|
||||
return this.subscribedToNotifications
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#import "./work_item.fragment.graphql"
|
||||
|
||||
query groupNamespaceLevel($fullPath: ID!, $iid: String!) {
|
||||
query groupWorkItem($fullPath: ID!, $iid: String!) {
|
||||
workspace: namespace(fullPath: $fullPath) {
|
||||
id
|
||||
workItem(iid: $iid) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#import "./work_item.fragment.graphql"
|
||||
|
||||
query projectNamespaceLevel($fullPath: ID!, $iid: String!) {
|
||||
query projectWorkItem($fullPath: ID!, $iid: String!) {
|
||||
workspace: namespace(fullPath: $fullPath) {
|
||||
id
|
||||
workItem(iid: $iid) {
|
||||
|
|
|
|||
|
|
@ -62,3 +62,15 @@ div[style*='margin: 16px 0'] {
|
|||
}
|
||||
}
|
||||
|
||||
ul.users-list {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
ul.users-list li {
|
||||
display: inline-block;
|
||||
padding-right: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -202,6 +202,18 @@ ul.wiki-pages-list.content-list {
|
|||
}
|
||||
}
|
||||
|
||||
.wiki-templates-list {
|
||||
li {
|
||||
padding-left: $gl-spacing-scale-4 !important;
|
||||
padding-right: $gl-spacing-scale-4 !important;
|
||||
|
||||
li {
|
||||
padding-left: $gl-spacing-scale-2 !important;
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.drawio-editor {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ module WikiActions
|
|||
end
|
||||
|
||||
def templates
|
||||
@wiki_entries_count = templates_list.total_count
|
||||
@wiki_entries = WikiDirectory.group_pages(templates_list, templates: true)
|
||||
|
||||
render 'shared/wikis/templates'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,16 @@
|
|||
|
||||
module Emails
|
||||
module MergeRequests
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
override_layout_lookup_table.merge!({
|
||||
merge_when_pipeline_succeeds_email: 'mailer',
|
||||
approved_merge_request_email: 'mailer',
|
||||
unapproved_merge_request_email: 'mailer'
|
||||
})
|
||||
end
|
||||
|
||||
def new_merge_request_email(recipient_id, merge_request_id, reason = nil)
|
||||
setup_merge_request_mail(merge_request_id, recipient_id, present: true)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,11 @@ module Emails
|
|||
VERIFICATION_EMAIL_TIMEOUT = 7
|
||||
|
||||
included do
|
||||
layout 'service_desk',
|
||||
only: [:service_desk_thank_you_email, :service_desk_new_note_email, :service_desk_new_participant_email]
|
||||
override_layout_lookup_table.merge!({
|
||||
service_desk_thank_you_email: 'service_desk',
|
||||
service_desk_new_note_email: 'service_desk',
|
||||
service_desk_new_participant_email: 'service_desk'
|
||||
})
|
||||
end
|
||||
|
||||
def service_desk_thank_you_email(issue_id)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ class Notify < ApplicationMailer
|
|||
include ReminderEmailsHelper
|
||||
include IssuablesHelper
|
||||
|
||||
mattr_accessor :override_layout_lookup_table, default: {}
|
||||
|
||||
include Emails::Shared
|
||||
include Emails::Issues
|
||||
include Emails::MergeRequests
|
||||
|
|
@ -40,6 +42,8 @@ class Notify < ApplicationMailer
|
|||
helper InProductMarketingHelper
|
||||
helper RegistrationsHelper
|
||||
|
||||
layout :determine_layout
|
||||
|
||||
def test_email(recipient_email, subject, body)
|
||||
mail_with_locale(
|
||||
to: recipient_email,
|
||||
|
|
@ -70,6 +74,10 @@ class Notify < ApplicationMailer
|
|||
|
||||
private
|
||||
|
||||
def determine_layout
|
||||
override_layout_lookup_table[action_name&.to_sym]
|
||||
end
|
||||
|
||||
# Return an email address that displays the name of the sender.
|
||||
# Override sender_email if you want to hard replace the sender address (e.g. custom email for Service Desk)
|
||||
def sender(sender_id, send_from_user_email: false, sender_name: nil, sender_email: nil)
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ class NamespaceSetting < ApplicationRecord
|
|||
validates :enabled_git_access_protocol, inclusion: { in: enabled_git_access_protocols.keys }
|
||||
validates :default_branch_protection_defaults, json_schema: { filename: 'default_branch_protection_defaults' }
|
||||
validates :default_branch_protection_defaults, bytesize: { maximum: -> { DEFAULT_BRANCH_PROTECTIONS_DEFAULT_MAX_SIZE } }
|
||||
validates :remove_dormant_members, inclusion: { in: [false] }, if: :subgroup?
|
||||
validates :remove_dormant_members_period, numericality: { only_integer: true, greater_than_or_equal_to: 90 }
|
||||
|
||||
validate :allow_mfa_for_group
|
||||
validate :allow_resource_access_token_creation_for_group
|
||||
|
|
@ -112,14 +114,18 @@ class NamespaceSetting < ApplicationRecord
|
|||
self.default_branch_name = default_branch_name.presence
|
||||
end
|
||||
|
||||
def subgroup?
|
||||
!!namespace&.subgroup?
|
||||
end
|
||||
|
||||
def allow_mfa_for_group
|
||||
if namespace&.subgroup? && allow_mfa_for_subgroups == false
|
||||
if subgroup? && allow_mfa_for_subgroups == false
|
||||
errors.add(:allow_mfa_for_subgroups, _('is not allowed since the group is not top-level group.'))
|
||||
end
|
||||
end
|
||||
|
||||
def allow_resource_access_token_creation_for_group
|
||||
if namespace&.subgroup? && !resource_access_token_creation_allowed
|
||||
if subgroup? && !resource_access_token_creation_allowed
|
||||
errors.add(:resource_access_token_creation_allowed, _('is not allowed since the group is not top-level group.'))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RemoteMirrors # rubocop:disable Gitlab/BoundedContexts -- https://gitlab.com/gitlab-org/gitlab/-/issues/462816
|
||||
class UpdateService < BaseService
|
||||
def execute(remote_mirror)
|
||||
return ServiceResponse.error(message: _('Access Denied')) unless allowed?
|
||||
return ServiceResponse.error(message: _('Remote mirror is missing')) unless remote_mirror
|
||||
return ServiceResponse.error(message: _('Project mismatch')) unless remote_mirror.project == project
|
||||
|
||||
if remote_mirror.update(allowed_attributes)
|
||||
ServiceResponse.success(payload: { remote_mirror: remote_mirror })
|
||||
else
|
||||
ServiceResponse.error(message: remote_mirror.errors)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def allowed_attributes
|
||||
RemoteMirrors::Attributes.new(params).allowed
|
||||
end
|
||||
|
||||
def allowed?
|
||||
Ability.allowed?(current_user, :admin_remote_mirror, project)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -15,6 +15,12 @@
|
|||
= stylesheet_link_tag 'mailer.css'
|
||||
%body
|
||||
= yield :preview_text
|
||||
-# Test stub for RSpec testing of Notify and associated modules
|
||||
-# Sometimes we override the choosen layout via `determine_layout` in our Notify mailer
|
||||
-# but ActionMailer doesn't support testing layout in pure Ruby so this HTML comment is
|
||||
-# used for testing the determined layout
|
||||
- if Rails.env.test?
|
||||
/ determine_layout returned template mailer
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0" }
|
||||
%tbody
|
||||
%tr.line
|
||||
|
|
|
|||
|
|
@ -3,6 +3,6 @@
|
|||
%td
|
||||
%img.footer-logo{ alt: "GitLab", src: image_url('mailers/gitlab_logo_black_text.png') }
|
||||
%div
|
||||
= notification_reason_text(show_manage_notifications_link: true, show_help_link: true, format: :html)
|
||||
= notification_reason_text(show_manage_notifications_link: true, show_help_link: true, unsubscribe_url: @unsubscribe_url, format: :html)
|
||||
|
||||
= render 'layouts/mailer'
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@
|
|||
= universal_stylesheet_link_tag 'notify'
|
||||
= yield :head
|
||||
%body
|
||||
-# Test stub for RSpec testing of Notify and associated modules
|
||||
-# Sometimes we override the choosen layout via `determine_layout` in our Notify mailer
|
||||
-# but ActionMailer doesn't support testing layout in pure Ruby so this HTML comment is
|
||||
-# used for testing the determined layout
|
||||
- if Rails.env.test?
|
||||
/ determine_layout returned template notify
|
||||
.content
|
||||
= html_header_message
|
||||
= yield
|
||||
|
|
|
|||
|
|
@ -16,6 +16,12 @@
|
|||
= yield :head
|
||||
%body
|
||||
= html_header_message
|
||||
-# Test stub for RSpec testing of Notify and associated modules
|
||||
-# Sometimes we override the choosen layout via `determine_layout` in our Notify mailer
|
||||
-# but ActionMailer doesn't support testing layout in pure Ruby so this HTML comment is
|
||||
-# used for testing the determined layout
|
||||
- if Rails.env.test?
|
||||
/ determine_layout returned template service_desk
|
||||
.content
|
||||
= yield
|
||||
.footer{ style: "margin-top: 10px;" }
|
||||
|
|
|
|||
|
|
@ -1,151 +1,75 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
%html{ lang: I18n.locale }
|
||||
%head
|
||||
%meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }/
|
||||
%meta{ content: "width=device-width, initial-scale=1", name: "viewport" }/
|
||||
%meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }/
|
||||
%title= message.subject
|
||||
:css
|
||||
/* CLIENT-SPECIFIC STYLES */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; }
|
||||
|
||||
/* iOS BLUE LINKS */
|
||||
a[x-apple-data-detectors] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
/* ANDROID MARGIN HACK */
|
||||
body { margin:0 !important; }
|
||||
div[style*="margin: 16px 0"] { margin:0 !important; }
|
||||
|
||||
@media only screen and (max-width: 639px) {
|
||||
body, #body {
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper {
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper > tbody > tr > td {
|
||||
border-left: 0 !important;
|
||||
border-right: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding-left: 10px !important;
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul.users-list {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
ul.users-list li {
|
||||
display: inline-block;
|
||||
padding-right: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
%body{ style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;height:100%;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0", style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;" }
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr.line
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }
|
||||
%tr.header
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
= header_logo
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:640px;margin:0 auto;border-collapse:separate;border-spacing:0;" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
%span
|
||||
- if @merge_request.respond_to? :approvals_required
|
||||
= s_('Notify|Merge request was approved (%{approvals}/%{required_approvals})') % { approvals: @merge_request.approvals.count, required_approvals: @merge_request.approvals_required }
|
||||
- else
|
||||
= s_('Notify|Merge request was approved')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @approved_by)
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _("Project")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Branch")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#ffffff;text-align:left;padding:18px 25px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.content{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;border-collapse:separate;border-spacing:0;" }
|
||||
%tbody
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
%span
|
||||
- if @merge_request.respond_to? :approvals_required
|
||||
= s_('Notify|Merge request was approved (%{approvals}/%{required_approvals})') % { approvals: @merge_request.approvals.count, required_approvals: @merge_request.approvals_required }
|
||||
- else
|
||||
= s_('Notify|Merge request was approved')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was approved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @approved_by)
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _("Project")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Branch")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Author")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24, only_path: false), style: "display:block;border-radius:12px;vertical-align:bottom;", width: "24", alt: "Avatar" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _("Author")
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24, only_path: false), style: "display:block;border-radius:12px;vertical-align:bottom;", width: "24", alt: "Avatar" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
- if Gitlab.ee?
|
||||
-# EE-specific start
|
||||
= render 'layouts/mailer/additional_text'
|
||||
-# EE-specific end
|
||||
|
||||
%tr.footer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%img{ alt: "GitLab", src: image_url('mailers/gitlab_logo_black_text.png'), style: "display:block;margin:0 auto 1em;", width: "90" }/
|
||||
%div
|
||||
= notification_reason_text(show_manage_notifications_link: true, show_help_link: true, format: :html)
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
- if Gitlab.ee?
|
||||
-# EE-specific start
|
||||
= render 'layouts/mailer/additional_text'
|
||||
-# EE-specific end
|
||||
- if @target_url
|
||||
= email_action @target_url
|
||||
|
|
|
|||
|
|
@ -1,151 +1,75 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
%html{ lang: I18n.locale }
|
||||
%head
|
||||
%meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }
|
||||
%meta{ content: "width=device-width, initial-scale=1", name: "viewport" }
|
||||
%meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }
|
||||
%title= message.subject
|
||||
:css
|
||||
/* CLIENT-SPECIFIC STYLES */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; }
|
||||
|
||||
/* iOS BLUE LINKS */
|
||||
a[x-apple-data-detectors] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
/* ANDROID MARGIN HACK */
|
||||
body { margin:0 !important; }
|
||||
div[style*="margin: 16px 0"] { margin:0 !important; }
|
||||
|
||||
@media only screen and (max-width: 639px) {
|
||||
body, #body {
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper {
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper > tbody > tr > td {
|
||||
border-left: 0 !important;
|
||||
border-right: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding-left: 10px !important;
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul.users-list {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
ul.users-list li {
|
||||
display: inline-block;
|
||||
padding-right: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
%body{ style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;height:100%;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0", style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;" }
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr.line
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }
|
||||
%tr.header
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
= header_logo
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:640px;margin:0 auto;border-collapse:separate;border-spacing:0;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#ffffff;text-align:left;padding:18px 25px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.content{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;border-collapse:separate;border-spacing:0;" }
|
||||
%tbody
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#31af64;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
%span= _('Merge request was set to auto-merge')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
%span{ style: "font-weight: 600;color:#333333;" }= _('Merge request')
|
||||
%a{ href: merge_request_url(@merge_request), style: "font-weight: 600;color:#3777b0;text-decoration:none" }= @merge_request.to_reference
|
||||
%span= _('was set to auto-merge by')
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@mwps_set_by, 24, only_path: false), style: "border-radius:12px;margin-left:3px;vertical-align:bottom;", width: "24", alt: "Avatar" }
|
||||
%a.muted{ href: user_url(@mwps_set_by), style: "color:#333333;text-decoration:none;" }
|
||||
= @mwps_set_by.name
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _('Project')
|
||||
-# haml-lint:disable NoPlainNodes
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Branch')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Author')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24, only_path: false), style: "display:block;border-radius:12px;margin:0;", width: "24", alt: "Avatar" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✓", height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-check-green-inverted.gif'), style: "display:block;", width: "13" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
%span= _('Merge request was set to auto-merge')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
%span{ style: "font-weight: 600;color:#333333;" }= _('Merge request')
|
||||
%a{ href: merge_request_url(@merge_request), style: "font-weight: 600;color:#3777b0;text-decoration:none" }= @merge_request.to_reference
|
||||
%span= _('was set to auto-merge by')
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@mwps_set_by, 24, only_path: false), style: "border-radius:12px;margin-left:3px;vertical-align:bottom;", width: "24", alt: "Avatar" }
|
||||
%a.muted{ href: user_url(@mwps_set_by), style: "color:#333333;text-decoration:none;" }
|
||||
= @mwps_set_by.name
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }= _('Project')
|
||||
-# haml-lint:disable NoPlainNodes
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Branch')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }= _('Author')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24, only_path: false), style: "display:block;border-radius:12px;margin:0;", width: "24", alt: "Avatar" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
|
||||
= render_if_exists 'layouts/mailer/additional_text'
|
||||
|
||||
%tr.footer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%img{ alt: "GitLab", src: image_url('mailers/gitlab_logo_black_text.png'), style: "display:block;margin:0 auto 1em;", width: "90" }
|
||||
%div
|
||||
= notification_reason_text(show_manage_notifications_link: true, show_help_link: true, format: :html)
|
||||
= render_if_exists 'layouts/mailer/additional_text'
|
||||
- if @target_url
|
||||
= email_action @target_url
|
||||
|
|
|
|||
|
|
@ -1,154 +1,79 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
%html{ lang: I18n.locale }
|
||||
%head
|
||||
%meta{ content: "text/html; charset=UTF-8", "http-equiv" => "Content-Type" }/
|
||||
%meta{ content: "width=device-width, initial-scale=1", name: "viewport" }/
|
||||
%meta{ content: "IE=edge", "http-equiv" => "X-UA-Compatible" }/
|
||||
%title= message.subject
|
||||
:css
|
||||
/* CLIENT-SPECIFIC STYLES */
|
||||
body, table, td, a { -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table, td { mso-table-lspace: 0pt; mso-table-rspace: 0pt; }
|
||||
img { -ms-interpolation-mode: bicubic; }
|
||||
|
||||
/* iOS BLUE LINKS */
|
||||
a[x-apple-data-detectors] {
|
||||
color: inherit !important;
|
||||
text-decoration: none !important;
|
||||
font-size: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
}
|
||||
|
||||
/* ANDROID MARGIN HACK */
|
||||
body { margin:0 !important; }
|
||||
div[style*="margin: 16px 0"] { margin:0 !important; }
|
||||
|
||||
@media only screen and (max-width: 639px) {
|
||||
body, #body {
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper {
|
||||
width: 100% !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
table.wrapper > tbody > tr > td {
|
||||
border-left: 0 !important;
|
||||
border-right: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
padding-left: 10px !important;
|
||||
padding-right: 10px !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul.users-list {
|
||||
list-style: none;
|
||||
padding: 0px;
|
||||
display: block;
|
||||
margin-top: 0px;
|
||||
}
|
||||
ul.users-list li {
|
||||
display: inline-block;
|
||||
padding-right: 12px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
%body{ style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;height:100%;font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table#body{ border: "0", cellpadding: "0", cellspacing: "0", style: "background-color:#fafafa;margin:0;padding:0;text-align:center;min-width:640px;width:100%;" }
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr.line
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#6b4fbb;height:4px;font-size:4px;line-height:4px;" }
|
||||
%tr.header
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
= header_logo
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;" }
|
||||
%table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:640px;margin:0 auto;border-collapse:separate;border-spacing:0;" }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✗", height: "13", src: image_url('mailers/approval/icon-x-orange-inverted.gif'), style: "display:block;", width: "13" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
- if @merge_request.respond_to? :approvals_required
|
||||
%span
|
||||
= s_('Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})') % {approvals_count: @merge_request.approvals.count, approvals_required: @merge_request.approvals_required}
|
||||
- else
|
||||
%span
|
||||
= s_('Notify|Merge request was unapproved')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @unapproved_by)
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
||||
= _('Project')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||
= _('Branch')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;background-color:#ffffff;text-align:left;padding:18px 25px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.content{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;border-collapse:separate;border-spacing:0;" }
|
||||
%tbody
|
||||
%tr.success
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:10px;border-radius:3px;font-size:14px;line-height:1.3;text-align:center;overflow:hidden;color:#ffffff;background-color:#FC6D26;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;margin:0 auto;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;padding-right:5px;" }
|
||||
%img{ alt: "✗", height: "13", src: image_url('mailers/approval/icon-x-orange-inverted.gif'), style: "display:block;", width: "13" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;vertical-align:middle;color:#ffffff;text-align:center;" }
|
||||
- if @merge_request.respond_to? :approvals_required
|
||||
%span
|
||||
= s_('Notify|Merge request was unapproved (%{approvals_count}/%{approvals_required})') % {approvals_count: @merge_request.approvals.count, approvals_required: @merge_request.approvals_required}
|
||||
- else
|
||||
%span
|
||||
= s_('Notify|Merge request was unapproved')
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;line-height:1.4;text-align:center;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;width:100%;" }
|
||||
%tbody
|
||||
%tr{ style: 'width:100%;' }
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;text-align:center;" }
|
||||
%img{ src: image_url('mailers/approval/icon-merge-request-gray.gif'), style: "height:18px;width:18px;margin-bottom:2px;vertical-align:bottom;", alt: "Merge request icon" }
|
||||
= s_('Notify|%{mr_highlight}Merge request%{highlight_end} %{mr_link} %{reviewer_highlight}was unapproved by%{highlight_end} %{reviewer_avatar} %{reviewer_link}').html_safe % merge_request_hash_param(@merge_request, @unapproved_by)
|
||||
%tr.spacer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;height:18px;font-size:18px;line-height:18px;" }
|
||||
|
||||
%tr.section
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:0 15px;border:1px solid #ededed;border-radius:3px;overflow:hidden;" }
|
||||
%table.info{ border: "0", cellpadding: "0", cellspacing: "0", style: "width:100%;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;" }
|
||||
= _('Project')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;" }
|
||||
- namespace_name = @project.group ? @project.group.name : @project.namespace.owner.name
|
||||
- namespace_url = @project.group ? group_url(@project.group) : user_url(@project.namespace.owner)
|
||||
%a.muted{ href: namespace_url, style: "color:#333333;text-decoration:none;" }
|
||||
= namespace_name
|
||||
\/
|
||||
%a.muted{ href: project_url(@project), style: "color:#333333;text-decoration:none;" }
|
||||
= @project.name
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||
= _('Branch')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||
= _('Author')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24), style: "display:block;border-radius:12px;vertical-align:bottom;", width: "24", alt: "Avatar" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img{ height: "13", src: image_url('mailers/ci_pipeline_notif_v1/icon-branch-gray.gif'), style: "display:block;", width: "13", alt: "Branch icon" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%span.muted{ style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.source_branch
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;border-top:1px solid #ededed;" }
|
||||
= _('Author')
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;color:#8c8c8c;font-weight:300;padding:14px 0;margin:0;color:#333333;font-weight:400;width:75%;padding-left:5px;border-top:1px solid #ededed;" }
|
||||
%table.img{ border: "0", cellpadding: "0", cellspacing: "0", style: "border-collapse:collapse;" }
|
||||
%tbody
|
||||
%tr
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;padding-right:5px;" }
|
||||
%img.avatar{ height: "24", src: avatar_icon_for_user(@merge_request.author, 24), style: "display:block;border-radius:12px;vertical-align:bottom;", width: "24", alt: "Avatar" }/
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;font-size:15px;line-height:1.4;vertical-align:middle;" }
|
||||
%a.muted{ href: user_url(@merge_request.author), style: "color:#333333;text-decoration:none;" }
|
||||
= @merge_request.author.name
|
||||
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
- if Gitlab.ee?
|
||||
-# EE-specific start
|
||||
= render 'layouts/mailer/additional_text'
|
||||
-# EE-specific end
|
||||
- if @merge_request.assignees.any?
|
||||
= render 'users_list', users: @merge_request.assignees, user_label: assignees_label(@merge_request, include_value: false)
|
||||
|
||||
%tr.footer
|
||||
%td{ style: "font-family:'Helvetica Neue',Helvetica,Arial,sans-serif;padding:25px 0;font-size:13px;line-height:1.6;color:#5c5c5c;" }
|
||||
%img{ alt: "GitLab", src: image_url('mailers/gitlab_logo_black_text.png'), style: "display:block;margin:0 auto 1em;", width: "90" }/
|
||||
%div
|
||||
= notification_reason_text(show_manage_notifications_link: true, show_help_link: true, format: :html)
|
||||
- if @merge_request.reviewers.any?
|
||||
= render 'users_list', users: @merge_request.reviewers, user_label: reviewers_label(@merge_request, include_value: false)
|
||||
- if Gitlab.ee?
|
||||
-# EE-specific start
|
||||
= render 'layouts/mailer/additional_text'
|
||||
-# EE-specific end
|
||||
- if @target_url
|
||||
= email_action @target_url
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { auto_collapse: true, always_show_toggle: true, signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class(is_merge_request)} #{'right-sidebar-merge-requests' if is_merge_request}", 'aria-live' => 'polite', 'aria-label': issuable_type }
|
||||
.issuable-sidebar{ class: "#{'is-merge-request' if is_merge_request}" }
|
||||
.issuable-sidebar-header{ class: "#{'gl-pb-2! gl-md-display-flex gl-justify-content-end gl-lg-display-none!' if is_merge_request}" }
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: "gutter-toggle gl-float-right js-sidebar-toggle has-tooltip gl-shadow-none! gl-display-block #{'gl-mt-2' if notifications_todos_buttons_enabled?}" , type: 'button', 'aria-label' => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }) do
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: "gutter-toggle gl-float-right js-sidebar-toggle has-tooltip !gl-shadow-none gl-display-block #{'gl-mt-2' if notifications_todos_buttons_enabled?}" , type: 'button', 'aria-label' => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }) do
|
||||
= sidebar_gutter_toggle_icon
|
||||
- if signed_in
|
||||
- if !is_merge_request
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
%li{ class: 'gl-display-flex!' }
|
||||
%div
|
||||
= link_to wiki_page.human_title, wiki_page_path(@wiki, wiki_page), data: { testid: 'wiki-page-link', qa_page_name: wiki_page.slug }
|
||||
%small.gl-pr-2 (#{wiki_page.format})
|
||||
%li{ class: '!gl-px-5' }
|
||||
.gl-flex.gl-items-center.gl-justify-between.gl-gap-5
|
||||
.gl-flex.gl-items-baseline.gl-gap-5.gl-w-full
|
||||
.gl-flex.gl-items-baseline.gl-grow.gl-gap-2
|
||||
= link_to wiki_page.human_title, wiki_page_path(@wiki, wiki_page), data: { testid: 'wiki-page-link', qa_page_name: wiki_page.slug }
|
||||
= render Pajamas::BadgeComponent.new(wiki_page.format, variant: 'muted', class: 'gl-ml-2')
|
||||
- if wiki_page.last_version
|
||||
%small.gl-text-secondary= (s_("Last edited %{date}") % { date: time_ago_with_tooltip(wiki_page.last_version.authored_date) }).html_safe
|
||||
- if can?(current_user, :create_wiki, @wiki) && wiki_page.template?
|
||||
= render Pajamas::ButtonComponent.new(category: :secondary, icon: 'pencil', href: wiki_page_path(@wiki, wiki_page, action: :edit), button_options: { title: s_('Edit template') })
|
||||
.gl-flex-grow-1.gl-text-right
|
||||
- if wiki_page.last_version
|
||||
%small
|
||||
= (s_("Last edited %{date}") % { date: time_ago_with_tooltip(wiki_page.last_version.authored_date) }).html_safe
|
||||
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, icon: 'pencil', size: 'small', href: wiki_page_path(@wiki, wiki_page, action: :edit), button_options: { title: s_('Edit template'), class: 'has-tooltip' })
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
= render Pajamas::ButtonComponent.new(icon: 'plus', size: :small, href: "#{wiki_path}/{new_page_title}", button_options: { class: 'wiki-list-create-child-button gl-bg-transparent! gl-hover-bg-gray-50! gl-focus-bg-gray-50! gl-absolute gl-top-1/2 -gl-translate-y-1/2 gl-cursor-pointer gl-right-2' })
|
||||
= link_to wiki_path, data: { testid: 'wiki-dir-page-link', qa_page_name: wiki_directory.title } do
|
||||
= wiki_directory.title
|
||||
%ul{ class: '!gl-pl-7' }
|
||||
%ul{ class: '!gl-pl-5' }
|
||||
- wiki_directory.entries.each do |entry|
|
||||
= render partial: entry.to_partial_path, object: entry, locals: { context: context }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- breadcrumb_title(@page.template? ? s_("Wiki|New Template") : s_("Wiki|New Page")) unless @page.persisted?
|
||||
- breadcrumb_title(@page.template? ? s_("Wiki|New template") : s_("Wiki|New page")) unless @page.persisted?
|
||||
- wiki_page_title @page, @page.persisted? ? _('Edit') : _('New')
|
||||
- add_page_specific_style 'page_bundles/wiki'
|
||||
- @gfm_form = true
|
||||
|
|
@ -15,9 +15,9 @@
|
|||
= link_to_wiki_page @page
|
||||
%span.gl-text-secondary
|
||||
·
|
||||
= @page.template? ? s_("Wiki|Edit Template") : s_("Wiki|Edit Page")
|
||||
= @page.template? ? s_("Wiki|Edit template") : s_("Wiki|Edit page")
|
||||
- else
|
||||
= @page.template? ? s_("Wiki|New Template") : s_("Wiki|New Page")
|
||||
= @page.template? ? s_("Wiki|New template") : s_("Wiki|New page")
|
||||
|
||||
= render 'shared/wikis/form', uploads_path: wiki_attachment_upload_url
|
||||
|
||||
|
|
|
|||
|
|
@ -3,23 +3,34 @@
|
|||
- page_title s_("Wiki|Templates"), _("Wiki")
|
||||
- add_page_specific_style 'page_bundles/wiki'
|
||||
|
||||
.wiki-page-header.top-area.flex-column.flex-lg-row
|
||||
%h1.page-title.gl-font-size-h-display.gl-flex-grow-1
|
||||
= s_("Wiki|Wiki Templates")
|
||||
.wiki-page-header.gl-flex.gl-items-center{ class: '!gl-mt-5' }
|
||||
%h1.gl-heading-1.gl-grow{ class: '!gl-mb-0' }
|
||||
= s_("Wiki|Wiki templates")
|
||||
|
||||
.nav-controls.pb-md-3.pb-lg-0
|
||||
= link_button_to wiki_page_path(@wiki, "#{Wiki::TEMPLATES_DIR}/#{SecureRandom.uuid}", random_title: true), variant: :confirm do
|
||||
= s_("Wiki|New template")
|
||||
|
||||
.dropdown.inline.wiki-sort-dropdown
|
||||
.btn-group{ role: 'group' }
|
||||
= wiki_sort_controls(@wiki, params[:direction], action: :templates)
|
||||
|
||||
%ul.wiki-pages-list.content-list
|
||||
- if @templates_list.empty?
|
||||
%li.no-wiki-pages
|
||||
= s_("Wiki|No templates found")
|
||||
- @wiki_entries.each do |entry|
|
||||
= render partial: entry.to_partial_path, object: entry, locals: { context: 'pages' }
|
||||
= render Pajamas::CardComponent.new(card_options: { class: 'gl-new-card' }, header_options: { class: 'gl-new-card-header' }, body_options: { class: 'gl-new-card-body gl-px-0' }) do |c|
|
||||
- c.with_header do
|
||||
.gl-new-card-title-wrapper.gl-flex-col
|
||||
%h3.gl-new-card-title
|
||||
= s_("Wiki|Templates")
|
||||
.gl-new-card-count
|
||||
= sprite_icon('template', css_class: 'gl-mr-2')
|
||||
= @wiki_entries_count
|
||||
|
||||
= paginate @templates_list, theme: 'gitlab'
|
||||
.gl-new-card-actions
|
||||
= render Pajamas::ButtonComponent.new(href: wiki_page_path(@wiki, "#{Wiki::TEMPLATES_DIR}/#{SecureRandom.uuid}", random_title: true), size: :small) do
|
||||
= s_("Wiki|New template")
|
||||
- c.with_body do
|
||||
%ul.wiki-pages-list.content-list.wiki-templates-list
|
||||
- if @templates_list.empty?
|
||||
%li.no-wiki-pages{ class: '!gl-px-5' }
|
||||
= s_("Wiki|No templates found")
|
||||
- @wiki_entries.each do |entry|
|
||||
= render partial: entry.to_partial_path, object: entry, locals: { context: 'pages' }
|
||||
|
||||
.gl-pt-3
|
||||
= paginate @templates_list, theme: 'gitlab'
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
name: vulnerability_report_advanced_filtering
|
||||
feature_issue_url: https://gitlab.com/groups/gitlab-org/-/epics/3429
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140984
|
||||
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17353
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/437128
|
||||
milestone: '16.9'
|
||||
group: group::threat insights
|
||||
type: beta
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: use_remote_service_update_service
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/455517
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/149707
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/461556
|
||||
milestone: '17.1'
|
||||
group: group::source code
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -107,6 +107,15 @@ module.exports = {
|
|||
9: '.9',
|
||||
10: '1',
|
||||
},
|
||||
// TODO: Backport to GitLab UI
|
||||
zIndex: {
|
||||
0: '0',
|
||||
1: '1',
|
||||
2: '2',
|
||||
3: '3',
|
||||
200: '200',
|
||||
9999: '9999',
|
||||
},
|
||||
// These extends probably should be moved to GitLab UI:
|
||||
extend: {
|
||||
// TODO: Backport to GitLab UI. This should be part of the default colors config.
|
||||
|
|
@ -164,13 +173,6 @@ module.exports = {
|
|||
limited: '1006px',
|
||||
'1/2': '50%',
|
||||
},
|
||||
zIndex: {
|
||||
1: '1',
|
||||
2: '2',
|
||||
3: '3',
|
||||
200: '200',
|
||||
9999: '9999',
|
||||
},
|
||||
transitionProperty: {
|
||||
stroke: 'stroke',
|
||||
'stroke-opacity': 'stroke-opacity',
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ classes:
|
|||
- Elastic::ReindexingSlice
|
||||
feature_categories:
|
||||
- global_search
|
||||
description: TODO
|
||||
description: Used to track status of Zero downtime reindexing tasks in Elasticsearch or OpenSearch
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55681
|
||||
milestone: '13.12'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442660
|
||||
gitlab_schema: gitlab_main_cell
|
||||
exempt_from_sharding: true # data is specific to each cell's Elasticsearch cluster, no customer data
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRemoveDormantMembersToNamespaceSettings < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.1'
|
||||
|
||||
def change
|
||||
add_column :namespace_settings, :remove_dormant_members, :boolean, default: false, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRemoveDormantMembersPeriodToNamespaceSettings < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.1'
|
||||
|
||||
def change
|
||||
add_column :namespace_settings, :remove_dormant_members_period, :integer, default: 90, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
16e65c1c310ed5cb4b4f4c2f0bc83bb180b0688d476ecfd84bea681f6b115588
|
||||
|
|
@ -0,0 +1 @@
|
|||
d4fc6dd79a6e7b535037551858d261db1e7470380e9f2d9d154af25e0c44b71d
|
||||
|
|
@ -12138,6 +12138,8 @@ CREATE TABLE namespace_settings (
|
|||
lock_duo_features_enabled boolean DEFAULT false NOT NULL,
|
||||
disable_personal_access_tokens boolean DEFAULT false NOT NULL,
|
||||
enable_auto_assign_gitlab_duo_pro_seats boolean DEFAULT false NOT NULL,
|
||||
remove_dormant_members boolean DEFAULT false NOT NULL,
|
||||
remove_dormant_members_period integer DEFAULT 90 NOT NULL,
|
||||
CONSTRAINT check_0ba93c78c7 CHECK ((char_length(default_branch_name) <= 255)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_alertlist_size CHECK ((cardinality(unique_project_download_limit_alertlist) <= 100)),
|
||||
CONSTRAINT namespace_settings_unique_project_download_limit_allowlist_size CHECK ((cardinality(unique_project_download_limit_allowlist) <= 100))
|
||||
|
|
|
|||
|
|
@ -203,6 +203,57 @@ Gitlab::Llm::AiGateway::Client.new(User.first).stream(prompt: [{role: "user", co
|
|||
|
||||
If you can't fetch the response, check `graphql_json.log`, `sidekiq_json.log`, `llm.log` or `modelgateway_debug.log` if it contains error information.
|
||||
|
||||
#### Optional: Test with OIDC authentication
|
||||
|
||||
In production environment, AI Gateway verifies that the JWT sent by client request is signed by the authentic OIDC provider.
|
||||
To test this authentication and authorization flow with scopes/unit-primitives, you can take the following optional step.
|
||||
|
||||
Apply the following config to AI Gateway:
|
||||
|
||||
```shell
|
||||
# <AI-Gateway-root>/.env
|
||||
AIGW_AUTH__BYPASS_EXTERNAL=false
|
||||
AIGW_GITLAB_URL=<your-gdk-url> # e.g. http://gdk.test:3000/ ... This instance behaves as a OIDC provider.
|
||||
```
|
||||
|
||||
Apply the following config to GDK:
|
||||
|
||||
```shell
|
||||
# <GDK-root>/env.runit
|
||||
GITLAB_SIMULATE_SAAS=1
|
||||
```
|
||||
|
||||
and `gdk update`.
|
||||
|
||||
You can test a request from Rails console:
|
||||
|
||||
```shell
|
||||
# Open a terminal and login to Rails console:
|
||||
gdk rails console
|
||||
```
|
||||
|
||||
Try requests from GitLab-Rails to AI Gateway. Example:
|
||||
|
||||
```ruby
|
||||
# Optionally, you should allow the local requests since your AI Gateway is running in localhost.
|
||||
Gitlab::CurrentSettings.update(allow_local_requests_from_web_hooks_and_services: true)
|
||||
|
||||
Gitlab::Llm::VertexAi::Client.new(User.first, unit_primitive: 'explain_vulnerability').chat(content: "Hi, how are you?")
|
||||
Gitlab::Llm::VertexAi::Client.new(User.first, unit_primitive: 'explain_vulnerability').messages_chat(content: [{"author": "user", "content": "Hi, how are you?"}])
|
||||
Gitlab::Llm::VertexAi::Client.new(User.first, unit_primitive: 'explain_vulnerability').code_completion(content: {"prefix": "print('Hello", "suffix": ""})
|
||||
```
|
||||
|
||||
Here is the underlying process happening per request:
|
||||
|
||||
1. GitLab-Rails generates a new JWT with a given scope (e.g. `duo_chat`).
|
||||
1. GitLab-Rails requets to AI Gateway with the JWT (bearer token in `Authorization` HTTP header).
|
||||
1. AI Gateway decodes the JWT with the JWKS issued by the GitLab-Rails. If it's successfuly, the request is authenticated.
|
||||
1. AI Gateway verifies if the `scopes` claim in the JWT satisfies the target endpoint's scope requirement.
|
||||
Required scope varies per endpoint (e.g. `/v1/chat/agent` requires `duo_chat`, `/v2/code/suggestions` requires `code_suggestions`).
|
||||
|
||||
NOTE:
|
||||
If you want to test as self-managed GitLab instance, you need to set up Customer Dot as described in the above section.
|
||||
|
||||
### SaaS-only features
|
||||
|
||||
These features do not use the AI Gateway and instead reach out to the LLM provider directly because they are not yet following the [architecture blueprint](../../architecture/blueprints/ai_gateway/index.md). [We are planning on](https://gitlab.com/groups/gitlab-org/-/epics/13024) moving these features to our self managed offering, so any features developed under this setup will be migrated over time.
|
||||
|
|
@ -238,7 +289,7 @@ GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[
|
|||
1. Go to the group with the Ultimate license.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand the **Permissions and group features** section.
|
||||
1. Enable **Experiment & Beta features**.
|
||||
1. Enable **Use experiment and beta features**.
|
||||
1. Enable the specific feature flag for the feature you want to test.
|
||||
1. You can use Rake task `rake gitlab:duo:enable_feature_flags` to enable all feature flags that are assigned to group AI Framework.
|
||||
1. Setup [AI Gateway](#test-ai-features-with-ai-gateway-locally).
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ To turn on GitLab Duo experiment and beta features for a top-level group:
|
|||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Permissions and group features**.
|
||||
1. Under **Experiment and Beta features**, select the **Use Experiment and Beta features** checkbox.
|
||||
1. Under **Experiment and beta features**, select the **Use experiment and beta features** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
This setting [cascades to all projects](../user/project/merge_requests/approvals/settings.md#cascade-settings-from-the-instance-or-top-level-group)
|
||||
|
|
|
|||
|
|
@ -153,6 +153,7 @@ When transferring groups, note:
|
|||
- If the immediate parent group's visibility is lower than the group's current visibility, visibility levels for subgroups and projects change to match the new parent group's visibility.
|
||||
- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this leaves the group without an owner. In this case, the user transferring the group becomes the group's owner.
|
||||
- Transfers fail if the group is a top-level group and [npm packages](../packages/npm_registry/index.md) following the [naming convention](../packages/npm_registry/index.md#naming-convention) exist in any of the projects in the group, or in any of its subgroups.
|
||||
- `container_registry` images in the archived projects must be deleted before the transfer. For more information, see the [troubleshooting section](troubleshooting.md#missing-or-insufficient-permission-delete-button-disabled).
|
||||
- Existing packages that use a group-level endpoint (Maven, NuGet, PyPI, Composer, and Debian) need to be updated per the package's steps for setting up the group level endpoint.
|
||||
- Existing package names need to be updated if the package uses an instance level endpoint ([Maven](../packages/maven_repository/index.md#naming-convention), [npm](../packages/npm_registry/index.md#naming-convention), [Conan](../packages/conan_repository/index.md#package-recipe-naming-convention-for-instance-remotes)) and the group was moved to another root level namespace.
|
||||
- Top-level groups that have a subscription on GitLab.com cannot be transferred. To make the transfer possible, the top-level group's subscription must be removed first. Then the top-level group can be transferred as a subgroup to another top-level group.
|
||||
|
|
|
|||
|
|
@ -99,3 +99,11 @@ This error typically occurs when the user you're trying to remove is part of an
|
|||
- Recommended. Remove the user directly from the invited group, if you have access to the group.
|
||||
|
||||
The feature request to **Update `billable_members` endpoint to include invited group** is currently being worked on. For more information, see [issue 386583](https://gitlab.com/gitlab-org/gitlab/-/issues/386583)
|
||||
|
||||
## Missing or insufficient permission, delete button disabled
|
||||
|
||||
This error typically occurs when a user attempts to remove the `container_registry` images from the archived projects during group transfer. To solve this error:
|
||||
|
||||
1. Unarchive the project.
|
||||
1. Delete the `container_registry` images.
|
||||
1. Archive the project.
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ These group-level settings are available for top-level groups and cascade to all
|
|||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand the **Permissions and group features** section.
|
||||
1. Check **Use Experiment and Beta features** checkbox.
|
||||
1. Check **Use experiment and beta features** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### Project-level settings
|
||||
|
|
|
|||
|
|
@ -356,31 +356,6 @@ You can disable following and being followed by other users.
|
|||
NOTE:
|
||||
When this feature is being disabled, all current followed/following connections are deleted.
|
||||
|
||||
## Exact code search
|
||||
|
||||
### Enable exact code search
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** GitLab.com, Self-managed
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049) as a [beta](../../policy/experiment-beta-support.md#beta) in GitLab 15.9 [with flags](../../administration/feature_flags.md) named `index_code_with_zoekt` and `search_code_with_zoekt`. Disabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/388519) in GitLab 16.6.
|
||||
> - Feature flags `index_code_with_zoekt` and `search_code_with_zoekt` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148378) in GitLab 17.1.
|
||||
|
||||
WARNING:
|
||||
This feature is in [beta](../../policy/experiment-beta-support.md#beta) and subject to change without notice.
|
||||
For more information, see [epic 9404](https://gitlab.com/groups/gitlab-org/-/epics/9404).
|
||||
|
||||
To enable exact code search in GitLab:
|
||||
|
||||
1. On the left sidebar, select your avatar.
|
||||
1. Select **Edit profile**.
|
||||
1. Select **Preferences**.
|
||||
1. Clear the **Enable advanced code search** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## View a user's activity
|
||||
|
||||
GitLab tracks [user contribution activity](contributions_calendar.md).
|
||||
|
|
|
|||
|
|
@ -309,6 +309,32 @@ To customize the time format:
|
|||
1. Under **Time format**, select either the **System**, **12-hour**, or **24-hour** option.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## Enable exact code search
|
||||
|
||||
DETAILS:
|
||||
**Tier:** Premium, Ultimate
|
||||
**Offering:** GitLab.com, Self-managed
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049) as a [beta](../../policy/experiment-beta-support.md#beta) in GitLab 15.9 [with flags](../../administration/feature_flags.md) named `index_code_with_zoekt` and `search_code_with_zoekt`. Disabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/388519) in GitLab 16.6.
|
||||
> - Feature flags `index_code_with_zoekt` and `search_code_with_zoekt` [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/148378) in GitLab 17.1.
|
||||
|
||||
WARNING:
|
||||
This feature is in [beta](../../policy/experiment-beta-support.md#beta) and subject to change without notice.
|
||||
For more information, see [epic 9404](https://gitlab.com/groups/gitlab-org/-/epics/9404).
|
||||
|
||||
You can use [exact code search](../search/exact_code_search.md) instead of
|
||||
[advanced search](../search/advanced_search.md) to search for code in GitLab.
|
||||
|
||||
To enable exact code search:
|
||||
|
||||
1. On the left sidebar, select your avatar.
|
||||
1. Select **Preferences**.
|
||||
1. Go to the **Exact code search** section.
|
||||
1. Select the **Enable exact code search** checkbox.
|
||||
1. Select **Save changes**.
|
||||
|
||||
## User identities in CI job JSON web tokens
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/387537) in GitLab 16.0.
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ Users with at least the Developer role can create new wiki pages:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Select **Plan > Wiki**.
|
||||
1. Select **New page** on this page, or any other wiki page.
|
||||
1. Select **Wiki actions {ellipsis_v} > New page** on this page, or any other wiki page.
|
||||
1. Select a content format.
|
||||
1. Add a title for your new page. Page titles use
|
||||
[special characters](#special-characters-in-page-titles) for subdirectories and formatting,
|
||||
|
|
@ -96,7 +96,7 @@ locally:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Select **Plan > Wiki**.
|
||||
1. On the right sidebar, select **Clone repository**.
|
||||
1. Select **Wiki actions {ellipsis_v} > Clone repository**.
|
||||
1. Follow the on-screen instructions.
|
||||
|
||||
Files you add to your wiki locally must use one of the following
|
||||
|
|
@ -212,7 +212,7 @@ Prerequisites:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your project or group.
|
||||
1. Select **Plan > Wiki**.
|
||||
1. On the right sidebar, select **Templates**.
|
||||
1. Select **Wiki actions {ellipsis_v} > Templates**.
|
||||
1. Select **New Template**.
|
||||
1. Enter template title, format and content, as if creating a regular wiki page.
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ WARNING:
|
|||
This feature is in [beta](../../policy/experiment-beta-support.md#beta) and subject to change without notice.
|
||||
For more information, see [epic 9404](https://gitlab.com/groups/gitlab-org/-/epics/9404).
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must [enable exact code search](../profile/preferences.md#enable-exact-code-search) in user preferences.
|
||||
|
||||
With exact code search, you can use regular expression and exact match modes
|
||||
to search for code in all GitLab or in a specific project.
|
||||
|
||||
|
|
|
|||
|
|
@ -145,20 +145,32 @@ module API
|
|||
put ':id/remote_mirrors/:mirror_id' do
|
||||
mirror = find_remote_mirror
|
||||
|
||||
mirror_params = declared_params(include_missing: false)
|
||||
mirror_params[:id] = mirror_params.delete(:mirror_id)
|
||||
if Feature.enabled?(:use_remote_service_update_service, user_project)
|
||||
service = ::RemoteMirrors::UpdateService.new(
|
||||
user_project,
|
||||
current_user,
|
||||
declared_params(include_missing: false)
|
||||
)
|
||||
|
||||
verify_mirror_branches_setting(mirror_params)
|
||||
update_params = { remote_mirrors_attributes: mirror_params }
|
||||
result = service.execute(mirror)
|
||||
|
||||
result = ::Projects::UpdateService
|
||||
.new(user_project, current_user, update_params)
|
||||
.execute
|
||||
render_api_error!(result.message, 400) if result.error?
|
||||
|
||||
if result[:status] == :success
|
||||
present mirror.reset, with: Entities::RemoteMirror
|
||||
present result.payload[:remote_mirror], with: Entities::RemoteMirror
|
||||
else
|
||||
render_api_error!(result[:message], 400)
|
||||
mirror_params = declared_params(include_missing: false)
|
||||
mirror_params[:id] = mirror_params.delete(:mirror_id)
|
||||
|
||||
verify_mirror_branches_setting(mirror_params)
|
||||
update_params = { remote_mirrors_attributes: mirror_params }
|
||||
|
||||
result = ::Projects::UpdateService
|
||||
.new(user_project, current_user, update_params)
|
||||
.execute
|
||||
|
||||
render_api_error!(result[:message], 400) unless result[:status] == :success
|
||||
|
||||
present mirror.reset, with: Entities::RemoteMirror
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2102,10 +2102,10 @@ msgstr ""
|
|||
msgid "AIPoweredSM|Enable %{link_start}AI-powered features%{link_end} for this instance."
|
||||
msgstr ""
|
||||
|
||||
msgid "AIPoweredSM|Enable Experiment and Beta AI-powered features"
|
||||
msgid "AIPoweredSM|Enable GitLab Duo features"
|
||||
msgstr ""
|
||||
|
||||
msgid "AIPoweredSM|Enable GitLab Duo features"
|
||||
msgid "AIPoweredSM|Enable experiment and beta AI-powered features"
|
||||
msgstr ""
|
||||
|
||||
msgid "AIPoweredSM|Enforce Duo features setting for all subgroups"
|
||||
|
|
@ -7685,6 +7685,9 @@ msgstr ""
|
|||
msgid "Autosave|Note"
|
||||
msgstr ""
|
||||
|
||||
msgid "Availability"
|
||||
msgstr ""
|
||||
|
||||
msgid "Available"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -8000,34 +8003,28 @@ msgstr ""
|
|||
msgid "Beta"
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|A Beta feature is not production-ready, but is unlikely to change drastically before it's released. We encourage users to try Beta features and provide feedback."
|
||||
msgid "BetaBadge|A beta feature is not yet production-ready, but is ready for testing and unlikely to change significantly before it's released."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|A Beta feature:"
|
||||
msgid "BetaBadge|Are subject to the GitLab Testing Agreement."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|A Beta feature: "
|
||||
msgid "BetaBadge|Are supported on a commercially-reasonable effort basis."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|Beta"
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|Is complete or near completion."
|
||||
msgid "BetaBadge|Beta features:"
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|Is supported by a commercially reasonable effort."
|
||||
msgid "BetaBadge|Have a low risk of data loss, but might still be unstable."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|May be unstable."
|
||||
msgid "BetaBadge|Have a near complete user experience."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|Should not cause data loss."
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|What's Beta?"
|
||||
msgstr ""
|
||||
|
||||
msgid "BetaBadge|What's a Beta?"
|
||||
msgid "BetaBadge|What's a beta?"
|
||||
msgstr ""
|
||||
|
||||
msgid "BeyondIdentityService|API Token. User must have access to `git-commit-signing` endpoint."
|
||||
|
|
@ -21285,28 +21282,28 @@ msgstr ""
|
|||
msgid "Experiment features' settings not allowed."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|An Experiment is a feature that's in the process of being developed. It's not production-ready. We encourage users to try Experimental features and provide feedback."
|
||||
msgid "ExperimentBadge|An experiment is not yet production-ready, but is released for initial testing and feedback during development."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|An Experiment:"
|
||||
msgid "ExperimentBadge|Are not supported and might not be documented."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|Can be removed at any time."
|
||||
msgid "ExperimentBadge|Are subject to the GitLab Testing Agreement."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|Can cause data loss."
|
||||
msgid "ExperimentBadge|Could be changed or removed at any time."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|Experiment"
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|Has no support and might not be documented."
|
||||
msgid "ExperimentBadge|Experiments:"
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|May be unstable."
|
||||
msgid "ExperimentBadge|Might be unstable or cause data loss."
|
||||
msgstr ""
|
||||
|
||||
msgid "ExperimentBadge|What's an Experiment?"
|
||||
msgid "ExperimentBadge|What's an experiment?"
|
||||
msgstr ""
|
||||
|
||||
msgid "Experiments"
|
||||
|
|
@ -25081,7 +25078,7 @@ msgstr ""
|
|||
msgid "GroupSelect|Select a group"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings| %{link_start}What do Experiment and Beta mean?%{link_end}"
|
||||
msgid "GroupSettings| %{link_start}What do experiment and beta mean?%{link_end}"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|After the instance reaches the user cap, any user who is added or requests access must be approved by an administrator. Leave empty for an unlimited user cap. If you change the user cap to unlimited, you must re-enable %{project_sharing_docs_link_start}project sharing%{link_end} and %{group_sharing_docs_link_start}group sharing%{link_end}."
|
||||
|
|
@ -25192,7 +25189,7 @@ msgstr ""
|
|||
msgid "GroupSettings|Experiment"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Experiment and Beta features"
|
||||
msgid "GroupSettings|Experiment and beta features"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Export group"
|
||||
|
|
@ -25315,7 +25312,7 @@ msgstr ""
|
|||
msgid "GroupSettings|Use Duo features"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Use Experiment and Beta features"
|
||||
msgid "GroupSettings|Use experiment and beta features"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupSettings|Users can create %{link_start_project}project access tokens%{link_end} and %{link_start_group}group access tokens%{link_end} in this group"
|
||||
|
|
@ -39025,7 +39022,7 @@ msgstr ""
|
|||
msgid "Preferences|Enable Gitpod integration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Enable Zoekt code search"
|
||||
msgid "Preferences|Enable exact code search"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Enable extension marketplace"
|
||||
|
|
@ -39043,6 +39040,9 @@ msgstr ""
|
|||
msgid "Preferences|Enable keyboard shortcuts"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Exact code search"
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Failed to save preferences."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -39115,7 +39115,7 @@ msgstr ""
|
|||
msgid "Preferences|Turns on or off the ability to follow or be followed by other users."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Turns on or off the preference to search with Zoekt instead of Elasticsearch."
|
||||
msgid "Preferences|Use exact code search instead of advanced search to search for code in GitLab."
|
||||
msgstr ""
|
||||
|
||||
msgid "Preferences|Use relative times"
|
||||
|
|
@ -40255,6 +40255,9 @@ msgstr ""
|
|||
msgid "Project milestone"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project mismatch"
|
||||
msgstr ""
|
||||
|
||||
msgid "Project must have default branch"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42947,6 +42950,9 @@ msgstr ""
|
|||
msgid "Remote"
|
||||
msgstr ""
|
||||
|
||||
msgid "Remote mirror is missing"
|
||||
msgstr ""
|
||||
|
||||
msgid "Remote object has no absolute path."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -58665,16 +58671,10 @@ msgstr ""
|
|||
msgid "WikiPage|Write your content or drag files here…"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|Edit Page"
|
||||
msgid "Wiki|Edit page"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|Edit Template"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|New Page"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|New Template"
|
||||
msgid "Wiki|Edit template"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|New page"
|
||||
|
|
@ -58713,10 +58713,10 @@ msgstr ""
|
|||
msgid "Wiki|Wiki Pages"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|Wiki Templates"
|
||||
msgid "Wiki|Wiki actions"
|
||||
msgstr ""
|
||||
|
||||
msgid "Wiki|Wiki actions"
|
||||
msgid "Wiki|Wiki templates"
|
||||
msgstr ""
|
||||
|
||||
msgid "Will be created"
|
||||
|
|
@ -59250,6 +59250,12 @@ msgstr ""
|
|||
msgid "Workspaces|Agents connect workspaces to your Kubernetes cluster. To create a workspace with an allowed agent, group members must have at least the Developer role."
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|All agents"
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|Allowed Agents"
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|Cancel"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -59352,7 +59358,10 @@ msgstr ""
|
|||
msgid "Workspaces|The branch, tag, or commit hash GitLab uses to create your workspace."
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|This group has no available agents. Select the All agents tab and allow at least one agent."
|
||||
msgid "Workspaces|This group has no agents. Start by creating an agent."
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|This group has no available agents. Select the %{strongStart}All agents%{strongEnd} tab and allow at least one agent."
|
||||
msgstr ""
|
||||
|
||||
msgid "Workspaces|To create a workspace, add a devfile to this project. A devfile is a configuration file for your workspace."
|
||||
|
|
@ -60697,6 +60706,9 @@ msgstr ""
|
|||
msgid "added a Zoom call to this issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "agents"
|
||||
msgstr ""
|
||||
|
||||
msgid "ago"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -60932,6 +60944,9 @@ msgstr ""
|
|||
msgid "cannot be enabled until a valid credit card is on file"
|
||||
msgstr ""
|
||||
|
||||
msgid "cannot be enabled until identity verification is completed"
|
||||
msgstr ""
|
||||
|
||||
msgid "cannot be used because it belongs to a compromised private key. Stop using this key and generate a new one."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ module QA
|
|||
element 'approve-access-request-button'
|
||||
end
|
||||
|
||||
base.view 'app/assets/javascripts/members/constants.js' do
|
||||
base.view 'app/assets/javascripts/members/tabs_metadata.js' do
|
||||
element 'groups-list-tab'
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ RSpec.describe 'new navigation for everyone callout', :js, feature_category: :na
|
|||
end
|
||||
|
||||
context 'when user dismisses callout' do
|
||||
it 'hides callout' do
|
||||
it 'hides callout', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/454405' do
|
||||
expect(page).to have_content callout_title
|
||||
|
||||
page.within(find('[data-feature-id="new_nav_for_everyone_callout"]')) do
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ describe('Linked pipeline', () => {
|
|||
`(
|
||||
'applies the class on $activateEventName and removes it on $deactivateEventName',
|
||||
async ({ activateEventName, deactivateEventName }) => {
|
||||
const shadowClass = 'gl-shadow-none!';
|
||||
const shadowClass = '!gl-shadow-none';
|
||||
|
||||
expect(findExpandButton().classes()).toContain(shadowClass);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import { NodeViewWrapper } from '@tiptap/vue-2';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import ImageWrapper from '~/content_editor/components/wrappers/image.vue';
|
||||
import { createTestEditor, mockChainedCommands } from '../../test_utils';
|
||||
import '~/content_editor/services/upload_helpers';
|
||||
|
||||
jest.mock('~/content_editor/services/upload_helpers', () => ({
|
||||
uploadingStates: {
|
||||
image12: true,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('content/components/wrappers/image_spec', () => {
|
||||
let wrapper;
|
||||
|
|
@ -22,7 +30,7 @@ describe('content/components/wrappers/image_spec', () => {
|
|||
|
||||
it('renders an image with the given attributes', () => {
|
||||
createWrapper({
|
||||
type: 'image',
|
||||
type: { name: 'image' },
|
||||
attrs: { src: 'image.png', alt: 'My Image', width: 200, height: 200 },
|
||||
});
|
||||
|
||||
|
|
@ -34,8 +42,17 @@ describe('content/components/wrappers/image_spec', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('marks the image as draggable', () => {
|
||||
createWrapper({ type: { name: 'image' }, attrs: { src: 'image.png', alt: 'My Image' } });
|
||||
|
||||
expect(findImage().attributes()).toMatchObject({
|
||||
draggable: 'true',
|
||||
'data-drag-handle': '',
|
||||
});
|
||||
});
|
||||
|
||||
it('sets width and height to auto if not provided', () => {
|
||||
createWrapper({ type: 'image', attrs: { src: 'image.png', alt: 'My Image' } });
|
||||
createWrapper({ type: { name: 'image' }, attrs: { src: 'image.png', alt: 'My Image' } });
|
||||
|
||||
expect(findImage().attributes()).toMatchObject({
|
||||
src: 'image.png',
|
||||
|
|
@ -45,8 +62,26 @@ describe('content/components/wrappers/image_spec', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('hides the wrapper component if it is a stale upload', () => {
|
||||
createWrapper({
|
||||
type: { name: 'image' },
|
||||
attrs: { src: 'image.png', alt: 'My Image', uploading: 'image12' },
|
||||
});
|
||||
|
||||
expect(wrapper.findComponent(NodeViewWrapper).attributes('style')).toBe('display: none;');
|
||||
});
|
||||
|
||||
it('does not hide the wrapper component if the upload is not stale', () => {
|
||||
createWrapper({
|
||||
type: { name: 'image' },
|
||||
attrs: { src: 'image.png', alt: 'My Image', uploading: 'image13' },
|
||||
});
|
||||
|
||||
expect(wrapper.findComponent(NodeViewWrapper).attributes('style')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('renders corner resize handles', () => {
|
||||
createWrapper({ type: 'image', attrs: { src: 'image.png', alt: 'My Image' } });
|
||||
createWrapper({ type: { name: 'image' }, attrs: { src: 'image.png', alt: 'My Image' } });
|
||||
|
||||
expect(findHandle('nw').exists()).toBe(true);
|
||||
expect(findHandle('ne').exists()).toBe(true);
|
||||
|
|
@ -68,7 +103,7 @@ describe('content/components/wrappers/image_spec', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
createWrapper({
|
||||
type: 'image',
|
||||
type: { name: 'image' },
|
||||
attrs: { src: 'image.png', alt: 'My Image', width: 400, height: 100 },
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
import { GlLink } from '@gitlab/ui';
|
||||
import { NodeViewWrapper } from '@tiptap/vue-2';
|
||||
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import PlayableWrapper from '~/content_editor/components/wrappers/playable.vue';
|
||||
|
||||
jest.mock('~/content_editor/services/upload_helpers', () => ({
|
||||
uploadingStates: {
|
||||
audio12: true,
|
||||
video12: true,
|
||||
},
|
||||
}));
|
||||
|
||||
describe('content/components/wrappers/playable_spec', () => {
|
||||
let wrapper;
|
||||
|
||||
const createWrapper = (node = {}) => {
|
||||
wrapper = shallowMountExtended(PlayableWrapper, {
|
||||
propsData: {
|
||||
node,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const findMedia = (type) => wrapper.find(`[as="${type}"]`);
|
||||
|
||||
describe.each`
|
||||
type | src | alt | title
|
||||
${'video'} | ${'video.mp4'} | ${'My Video'} | ${'My Video 1'}
|
||||
${'audio'} | ${'audio.mp3'} | ${'My Audio'} | ${'My Audio 1'}
|
||||
`('for mediaType=$type', ({ type, src, alt, title }) => {
|
||||
beforeEach(() => {
|
||||
createWrapper({ type: { name: type }, attrs: { src, alt, title } });
|
||||
});
|
||||
|
||||
it(`renders a ${type} element with the given attributes`, () => {
|
||||
expect(findMedia(type).attributes()).toMatchObject({ src, 'data-title': title });
|
||||
});
|
||||
|
||||
it('renders alt as title if title is not provided', () => {
|
||||
createWrapper({ type: { name: type }, attrs: { src, alt } });
|
||||
|
||||
expect(findMedia(type).attributes('data-title')).toEqual(alt);
|
||||
});
|
||||
|
||||
it(`marks the ${type} element as draggable`, () => {
|
||||
expect(findMedia(type).attributes()).toMatchObject({
|
||||
draggable: 'true',
|
||||
'data-drag-handle': '',
|
||||
});
|
||||
});
|
||||
|
||||
it(`renders a gl-link with the link to the ${type}`, () => {
|
||||
expect(wrapper.findComponent(GlLink).attributes()).toMatchObject({
|
||||
class: 'with-attachment-icon',
|
||||
href: src,
|
||||
target: '_blank',
|
||||
});
|
||||
});
|
||||
|
||||
it('marks the gl-link as draggable', () => {
|
||||
expect(wrapper.findComponent(GlLink).attributes()).toMatchObject({
|
||||
draggable: 'true',
|
||||
'data-drag-handle': '',
|
||||
});
|
||||
});
|
||||
|
||||
it('hides the wrapper component if it is a stale upload', () => {
|
||||
createWrapper({
|
||||
type: { name: type },
|
||||
attrs: { src, alt, uploading: `${type}12` },
|
||||
});
|
||||
|
||||
expect(wrapper.findComponent(NodeViewWrapper).attributes('style')).toBe('display: none;');
|
||||
});
|
||||
|
||||
it('does not hide the wrapper component if the upload is not stale', () => {
|
||||
createWrapper({
|
||||
type: { name: type },
|
||||
attrs: { src, alt, uploading: `${type}13` },
|
||||
});
|
||||
|
||||
expect(wrapper.findComponent(NodeViewWrapper).attributes('style')).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -20,6 +20,10 @@ describe('content_editor/extensions/image', () => {
|
|||
}));
|
||||
});
|
||||
|
||||
it('sets the draggable option to true', () => {
|
||||
expect(Image.config.draggable).toBe(true);
|
||||
});
|
||||
|
||||
it('adds data-canonical-src attribute when rendering to HTML', () => {
|
||||
const initialDoc = doc(
|
||||
p(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import ListItem from '~/content_editor/extensions/list_item';
|
||||
|
||||
describe('content_editor/extensions/list_item', () => {
|
||||
it('sets the draggable option to true', () => {
|
||||
expect(ListItem.config.draggable).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import Playable from '~/content_editor/extensions/playable';
|
||||
|
||||
describe('content_editor/extensions/playable', () => {
|
||||
it('sets the draggable option to true', () => {
|
||||
expect(Playable.config.draggable).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
@ -23,6 +23,10 @@ describe('content_editor/extensions/task_item', () => {
|
|||
}));
|
||||
});
|
||||
|
||||
it('sets the draggable option to true', () => {
|
||||
expect(TaskItem.config.draggable).toBe(true);
|
||||
});
|
||||
|
||||
it('renders a regular task item for non-inapplicable items', () => {
|
||||
const initialDoc = doc(taskList(taskItem(p('foo'))));
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlBadge } from '@gitlab/ui';
|
||||
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
|
||||
import ApprovalCount from '~/merge_request_dashboard/components/approval_count.vue';
|
||||
|
||||
let wrapper;
|
||||
|
||||
function createComponent(propsData = {}) {
|
||||
wrapper = shallowMount(ApprovalCount, {
|
||||
propsData,
|
||||
directives: {
|
||||
GlTooltip: createMockDirective('gl-tooltip'),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const findBadge = () => wrapper.findComponent(GlBadge);
|
||||
const findTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
|
||||
|
||||
describe('Merge request dashboard approval count FOSS component', () => {
|
||||
it('does not render badge when merge request is not approved', () => {
|
||||
createComponent({
|
||||
mergeRequest: { approvedBy: { nodes: [] } },
|
||||
});
|
||||
|
||||
expect(findBadge().exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('renders badge when merge request is approved', () => {
|
||||
createComponent({
|
||||
mergeRequest: { approvedBy: { nodes: ['approved'] } },
|
||||
});
|
||||
|
||||
expect(findBadge().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it.each`
|
||||
approvers | tooltipTitle
|
||||
${[1]} | ${'1 approver'}
|
||||
${[1, 2]} | ${'2 approvers'}
|
||||
`('renders badge with correct tooltip title', ({ approvers, tooltipTitle }) => {
|
||||
createComponent({
|
||||
mergeRequest: { approvedBy: { nodes: approvers } },
|
||||
});
|
||||
|
||||
expect(findTooltip().value).toBe(tooltipTitle);
|
||||
});
|
||||
});
|
||||
|
|
@ -26,6 +26,12 @@ export function createMockMergeRequest(mergeRequest = {}) {
|
|||
userDiscussionsCount: 0,
|
||||
createdAt: '',
|
||||
updatedAt: '',
|
||||
approved: false,
|
||||
approvalsRequired: 0,
|
||||
approvalsLeft: null,
|
||||
approvedBy: {
|
||||
nodes: [],
|
||||
},
|
||||
__typename: 'MergeRequest',
|
||||
...mergeRequest,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -13,27 +13,27 @@ exports[`Beta badge component renders the badge 1`] = `
|
|||
class="gl-popover"
|
||||
>
|
||||
<p>
|
||||
A Beta feature is not production-ready, but is unlikely to change drastically before it's released. We encourage users to try Beta features and provide feedback.
|
||||
A beta feature is not yet production-ready, but is ready for testing and unlikely to change significantly before it's released.
|
||||
</p>
|
||||
<p
|
||||
class="gl-mb-0"
|
||||
>
|
||||
A Beta feature:
|
||||
Beta features:
|
||||
</p>
|
||||
<ul
|
||||
class="gl-pl-4"
|
||||
>
|
||||
<li>
|
||||
May be unstable.
|
||||
Have a low risk of data loss, but might still be unstable.
|
||||
</li>
|
||||
<li>
|
||||
Should not cause data loss.
|
||||
Are supported on a commercially-reasonable effort basis.
|
||||
</li>
|
||||
<li>
|
||||
Is supported by a commercially reasonable effort.
|
||||
Have a near complete user experience.
|
||||
</li>
|
||||
<li>
|
||||
Is complete or near completion.
|
||||
Are subject to the GitLab Testing Agreement.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,27 +13,27 @@ exports[`Experiment badge component renders the badge 1`] = `
|
|||
class="gl-popover"
|
||||
>
|
||||
<p>
|
||||
An Experiment is a feature that's in the process of being developed. It's not production-ready. We encourage users to try Experimental features and provide feedback.
|
||||
An experiment is not yet production-ready, but is released for initial testing and feedback during development.
|
||||
</p>
|
||||
<p
|
||||
class="gl-mb-0"
|
||||
>
|
||||
An Experiment:
|
||||
Experiments:
|
||||
</p>
|
||||
<ul
|
||||
class="gl-pl-4"
|
||||
>
|
||||
<li>
|
||||
May be unstable.
|
||||
Might be unstable or cause data loss.
|
||||
</li>
|
||||
<li>
|
||||
Can cause data loss.
|
||||
Are not supported and might not be documented.
|
||||
</li>
|
||||
<li>
|
||||
Has no support and might not be documented.
|
||||
Could be changed or removed at any time.
|
||||
</li>
|
||||
<li>
|
||||
Can be removed at any time.
|
||||
Are subject to the GitLab Testing Agreement.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
|
|||
class="diff-line-num gl-display-flex line-links"
|
||||
>
|
||||
<a
|
||||
class="file-line-blame gl-mx-n2 gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-blame gl-mx-n2 gl-select-none"
|
||||
href="/blame/foo-bar#L1"
|
||||
/>
|
||||
<a
|
||||
class="file-line-num gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-num gl-select-none"
|
||||
data-line-number="1"
|
||||
href="#L1"
|
||||
id="reference-0"
|
||||
|
|
@ -28,11 +28,11 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
|
|||
class="diff-line-num gl-display-flex line-links"
|
||||
>
|
||||
<a
|
||||
class="file-line-blame gl-mx-n2 gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-blame gl-mx-n2 gl-select-none"
|
||||
href="/blame/foo-bar#L2"
|
||||
/>
|
||||
<a
|
||||
class="file-line-num gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-num gl-select-none"
|
||||
data-line-number="2"
|
||||
href="#L2"
|
||||
id="reference-1"
|
||||
|
|
@ -44,11 +44,11 @@ exports[`Blob Simple Viewer component rendering matches the snapshot 1`] = `
|
|||
class="diff-line-num gl-display-flex line-links"
|
||||
>
|
||||
<a
|
||||
class="file-line-blame gl-mx-n2 gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-blame gl-mx-n2 gl-select-none"
|
||||
href="/blame/foo-bar#L3"
|
||||
/>
|
||||
<a
|
||||
class="file-line-num gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-num gl-select-none"
|
||||
data-line-number="3"
|
||||
href="#L3"
|
||||
id="reference-2"
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ exports[`Chunk component rendering isHighlighted is true renders line numbers 1`
|
|||
data-testid="line-numbers"
|
||||
>
|
||||
<a
|
||||
class="file-line-blame gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-blame gl-select-none"
|
||||
data-event-tracking="click_chunk_blame_on_blob_page"
|
||||
href="some/blame/path.js#L71"
|
||||
/>
|
||||
<a
|
||||
class="file-line-num gl-select-none gl-shadow-none!"
|
||||
class="!gl-shadow-none file-line-num gl-select-none"
|
||||
data-line-number="71"
|
||||
href="#L71"
|
||||
id="reference-0"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
is_expected.to have_html_part_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge_request_unmergeable_email' do
|
||||
|
|
@ -73,6 +77,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
is_expected.to have_html_part_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#closed_merge_request_email' do
|
||||
|
|
@ -103,6 +111,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
expect(subject.text_part).to have_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merged_merge_request_email' do
|
||||
|
|
@ -135,6 +147,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
expect(subject.text_part).to have_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge_request_status_email' do
|
||||
|
|
@ -167,6 +183,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
expect(subject.text_part).to have_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#merge_when_pipeline_succeeds_email" do
|
||||
|
|
@ -185,6 +205,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
is_expected.to have_html_part_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template mailer')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#approved_merge_request_email' do
|
||||
|
|
@ -200,6 +224,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
is_expected.to have_html_part_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template mailer')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#unapproved_merge_request_email' do
|
||||
|
|
@ -215,6 +243,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
is_expected.to have_html_part_content(reviewer.name)
|
||||
end
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template mailer')
|
||||
end
|
||||
end
|
||||
|
||||
describe "#resolved_all_discussions_email" do
|
||||
|
|
@ -223,6 +255,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
it "includes the name of the resolver" do
|
||||
expect(subject).to have_body_text current_user_sanitized
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template notify')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#merge_requests_csv_email' do
|
||||
|
|
@ -255,6 +291,10 @@ RSpec.describe Emails::MergeRequests do
|
|||
|
||||
it { expect(subject).to have_content('attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15 MiB.') }
|
||||
end
|
||||
|
||||
it "uses the correct layout template" do
|
||||
is_expected.to have_html_part_content('determine_layout returned template mailer')
|
||||
end
|
||||
end
|
||||
|
||||
def expect_sender(user)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue