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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-03-16 15:10:54 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-03-16 15:10:54 +0300
commitf01d3c8c095e70981ffc1d20c050c153f3766421 (patch)
tree1f072a51c12791df3847fd90bd8e6a369631e990 /app
parentcb20cd86e45ad06b0dc43562c0a1121c3e505c36 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue2
-rw-r--r--app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue1
-rw-r--r--app/assets/javascripts/admin/abuse_reports/components/app.vue11
-rw-r--r--app/assets/javascripts/admin/broadcast_messages/components/message_form.vue37
-rw-r--r--app/assets/javascripts/admin/broadcast_messages/constants.js1
-rw-r--r--app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue1
-rw-r--r--app/assets/javascripts/ci/runner/components/registration/registration_instructions.vue2
-rw-r--r--app/assets/javascripts/diffs/store/getters.js6
-rw-r--r--app/assets/javascripts/related_issues/components/related_issuable_input.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue75
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue63
-rw-r--r--app/assets/javascripts/work_items/components/widget_wrapper.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue29
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue14
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue4
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue4
-rw-r--r--app/assets/javascripts/work_items/router/index.js2
-rw-r--r--app/assets/stylesheets/framework/forms.scss19
-rw-r--r--app/assets/stylesheets/framework/timeline.scss1
-rw-r--r--app/assets/stylesheets/page_bundles/issuable.scss15
-rw-r--r--app/assets/stylesheets/page_bundles/work_items.scss13
-rw-r--r--app/controllers/admin/broadcast_messages_controller.rb2
-rw-r--r--app/controllers/groups/children_controller.rb24
-rw-r--r--app/models/commit_status.rb1
-rw-r--r--app/views/admin/broadcast_messages/_preview.html.haml3
-rw-r--r--app/views/projects/commit/diff_files.html.haml6
-rw-r--r--app/views/projects/diffs/_diffs.html.haml4
29 files changed, 236 insertions, 115 deletions
diff --git a/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue b/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
index f7e3675c983..a4211002f71 100644
--- a/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
+++ b/app/assets/javascripts/admin/abuse_reports/components/abuse_report_row.vue
@@ -29,7 +29,7 @@ export default {
</script>
<template>
- <list-item>
+ <list-item data-testid="abuse-report-row">
<template #left-primary>
<div class="gl-font-weight-normal" data-testid="title">{{ title }}</div>
</template>
diff --git a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
index 8726cd2f6fa..b60fe3ae9b8 100644
--- a/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
+++ b/app/assets/javascripts/admin/abuse_reports/components/abuse_reports_filtered_search_bar.vue
@@ -102,6 +102,7 @@ export default {
:initial-filter-value="initialFilterValue"
:initial-sort-by="initialSortBy"
:sort-options="$options.sortOptions"
+ data-testid="abuse-reports-filtered-search-bar"
@onFilter="handleFilter"
@onSort="handleSort"
/>
diff --git a/app/assets/javascripts/admin/abuse_reports/components/app.vue b/app/assets/javascripts/admin/abuse_reports/components/app.vue
index a3e04b16ff9..e1e75a4f8d0 100644
--- a/app/assets/javascripts/admin/abuse_reports/components/app.vue
+++ b/app/assets/javascripts/admin/abuse_reports/components/app.vue
@@ -1,5 +1,5 @@
<script>
-import { GlPagination } from '@gitlab/ui';
+import { GlEmptyState, GlPagination } from '@gitlab/ui';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import FilteredSearchBar from './abuse_reports_filtered_search_bar.vue';
import AbuseReportRow from './abuse_report_row.vue';
@@ -9,6 +9,7 @@ export default {
components: {
AbuseReportRow,
FilteredSearchBar,
+ GlEmptyState,
GlPagination,
},
props: {
@@ -37,7 +38,13 @@ export default {
<div>
<filtered-search-bar />
- <abuse-report-row v-for="(report, index) in abuseReports" :key="index" :report="report" />
+ <gl-empty-state v-if="abuseReports.length == 0" :title="s__('AbuseReports|No reports found')" />
+ <abuse-report-row
+ v-for="(report, index) in abuseReports"
+ v-else
+ :key="index"
+ :report="report"
+ />
<gl-pagination
v-if="showPagination"
diff --git a/app/assets/javascripts/admin/broadcast_messages/components/message_form.vue b/app/assets/javascripts/admin/broadcast_messages/components/message_form.vue
index b52b7f6cdeb..65aa4cba074 100644
--- a/app/assets/javascripts/admin/broadcast_messages/components/message_form.vue
+++ b/app/assets/javascripts/admin/broadcast_messages/components/message_form.vue
@@ -15,13 +15,22 @@ import { s__ } from '~/locale';
import { createAlert, VARIANT_DANGER } from '~/alert';
import { redirectTo } from '~/lib/utils/url_utility';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { BROADCAST_MESSAGES_PATH, THEMES, TYPES, TYPE_BANNER } from '../constants';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import {
+ BROADCAST_MESSAGES_PATH,
+ MESSAGES_PREVIEW_PATH,
+ THEMES,
+ TYPES,
+ TYPE_BANNER,
+} from '../constants';
import MessageFormGroup from './message_form_group.vue';
import DatetimePicker from './datetime_picker.vue';
const FORM_HEADERS = { headers: { 'Content-Type': 'application/json; charset=utf-8' } };
export default {
+ DEFAULT_DEBOUNCE_AND_THROTTLE_MS,
name: 'MessageForm',
components: {
DatetimePicker,
@@ -36,6 +45,9 @@ export default {
GlFormTextarea,
MessageFormGroup,
},
+ directives: {
+ SafeHtml,
+ },
mixins: [glFeatureFlagsMixin()],
inject: ['targetAccessLevelOptions'],
i18n: {
@@ -81,6 +93,7 @@ export default {
})),
startsAt: new Date(this.broadcastMessage.startsAt.getTime()),
endsAt: new Date(this.broadcastMessage.endsAt.getTime()),
+ renderedMessage: '',
};
},
computed: {
@@ -91,7 +104,7 @@ export default {
return this.message.trim() === '';
},
messagePreview() {
- return this.messageBlank ? this.$options.i18n.messagePlaceholder : this.message;
+ return this.messageBlank ? this.$options.i18n.messagePlaceholder : this.renderedMessage;
},
isAddForm() {
return !this.broadcastMessage.id;
@@ -114,6 +127,11 @@ export default {
});
},
},
+ watch: {
+ message() {
+ this.renderPreview();
+ },
+ },
methods: {
async onSubmit() {
this.loading = true;
@@ -140,13 +158,25 @@ export default {
}
return true;
},
+
+ async renderPreview() {
+ try {
+ const res = await axios.post(MESSAGES_PREVIEW_PATH, this.formPayload, FORM_HEADERS);
+ this.renderedMessage = res.data;
+ } catch (e) {
+ this.renderedMessage = '';
+ }
+ },
+ },
+ safeHtmlConfig: {
+ ADD_TAGS: ['use'],
},
};
</script>
<template>
<gl-form @submit.prevent="onSubmit">
<gl-broadcast-message class="gl-my-6" :type="type" :theme="theme" :dismissible="dismissable">
- {{ messagePreview }}
+ <div v-safe-html:[$options.safeHtmlConfig]="messagePreview"></div>
</gl-broadcast-message>
<message-form-group :label="$options.i18n.message" label-for="message-textarea">
@@ -154,6 +184,7 @@ export default {
id="message-textarea"
v-model="message"
size="sm"
+ :debounce="$options.DEFAULT_DEBOUNCE_AND_THROTTLE_MS"
:placeholder="$options.i18n.messagePlaceholder"
/>
</message-form-group>
diff --git a/app/assets/javascripts/admin/broadcast_messages/constants.js b/app/assets/javascripts/admin/broadcast_messages/constants.js
index 6250d5a943d..323ac6857f6 100644
--- a/app/assets/javascripts/admin/broadcast_messages/constants.js
+++ b/app/assets/javascripts/admin/broadcast_messages/constants.js
@@ -1,6 +1,7 @@
import { s__ } from '~/locale';
export const BROADCAST_MESSAGES_PATH = '/admin/broadcast_messages';
+export const MESSAGES_PREVIEW_PATH = '/admin/broadcast_messages/preview';
export const TYPE_BANNER = 'banner';
export const TYPE_NOTIFICATION = 'notification';
diff --git a/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue b/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
index 694ab7b526e..ff182c61ccf 100644
--- a/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
+++ b/app/assets/javascripts/ci/runner/components/registration/platforms_drawer.vue
@@ -88,6 +88,7 @@ export default {
:open="open"
:header-height="drawerHeightOffset"
:z-index="$options.DRAWER_Z_INDEX"
+ data-testid="runner-platforms-drawer"
@close="onClose"
>
<template #title>
diff --git a/app/assets/javascripts/ci/runner/components/registration/registration_instructions.vue b/app/assets/javascripts/ci/runner/components/registration/registration_instructions.vue
index c2b7b9aea8a..ee9ca5dc08c 100644
--- a/app/assets/javascripts/ci/runner/components/registration/registration_instructions.vue
+++ b/app/assets/javascripts/ci/runner/components/registration/registration_instructions.vue
@@ -97,7 +97,7 @@ export default {
"
>
<template #link="{ content }">
- <gl-link @click="toggleDrawer">{{ content }}</gl-link>
+ <gl-link data-testid="runner-install-link" @click="toggleDrawer">{{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/diffs/store/getters.js b/app/assets/javascripts/diffs/store/getters.js
index f530c05ae1e..10a6a872fe4 100644
--- a/app/assets/javascripts/diffs/store/getters.js
+++ b/app/assets/javascripts/diffs/store/getters.js
@@ -90,6 +90,12 @@ export const getDiffFileDiscussions = (state, getters, rootState, rootGetters) =
export const getDiffFileByHash = (state) => (fileHash) =>
state.diffFiles.find((file) => file.file_hash === fileHash);
+export function isTreePathLoaded(state) {
+ return (path) => {
+ return Boolean(state.treeEntries[path]?.diffLoaded);
+ };
+}
+
export const flatBlobsList = (state) =>
Object.values(state.treeEntries).filter((f) => f.type === 'blob');
diff --git a/app/assets/javascripts/related_issues/components/related_issuable_input.vue b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
index 8d6a3110f35..1846b9cf8f4 100644
--- a/app/assets/javascripts/related_issues/components/related_issuable_input.vue
+++ b/app/assets/javascripts/related_issues/components/related_issuable_input.vue
@@ -182,7 +182,7 @@ export default {
<div
ref="issuableFormWrapper"
:class="{ focus: isInputFocused }"
- class="add-issuable-form-input-wrapper form-control gl-field-error-outline gl-h-auto gl-p-3 gl-pb-2"
+ class="add-issuable-form-input-wrapper form-control gl-field-error-outline gl-h-auto gl-px-3 gl-pt-2 gl-pb-0"
role="button"
@click="onIssuableFormWrapperClick"
>
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index dbfbd35b9b6..18503720814 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -2,6 +2,11 @@ import { s__ } from '~/locale';
import { helpPagePath } from '~/helpers/help_page_helper';
import { stateToComponentMap as classStateMap, stateKey } from './stores/state_maps';
+export const FOUR_MINUTES_IN_MS = 1000 * 60 * 4;
+
+export const STATE_QUERY_POLLING_INTERVAL_DEFAULT = 5000;
+export const STATE_QUERY_POLLING_INTERVAL_BACKOFF = 2;
+
export const SUCCESS = 'success';
export const WARNING = 'warning';
export const INFO = 'info';
diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
index 8867478654a..bbad2c13220 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
@@ -1,5 +1,5 @@
<script>
-import { isEmpty } from 'lodash';
+import { isEmpty, clamp } from 'lodash';
import {
registerExtension,
registeredExtensions,
@@ -10,7 +10,6 @@ import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_wid
import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_store';
import { stateToComponentMap as classState } from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
import { createAlert } from '~/alert';
-import { secondsToMilliseconds } from '~/lib/utils/datetime_utility';
import notify from '~/lib/utils/notify';
import { sprintf, s__, __ } from '~/locale';
import Project from '~/pages/projects/project';
@@ -44,7 +43,13 @@ import UnresolvedDiscussionsState from './components/states/unresolved_discussio
import WorkInProgressState from './components/states/work_in_progress.vue';
import ExtensionsContainer from './components/extensions/container';
import WidgetContainer from './components/widget/app.vue';
-import { STATE_MACHINE, stateToComponentMap } from './constants';
+import {
+ STATE_MACHINE,
+ stateToComponentMap,
+ STATE_QUERY_POLLING_INTERVAL_DEFAULT,
+ STATE_QUERY_POLLING_INTERVAL_BACKOFF,
+ FOUR_MINUTES_IN_MS,
+} from './constants';
import eventHub from './event_hub';
import mergeRequestQueryVariablesMixin from './mixins/merge_request_query_variables';
import getStateQuery from './queries/get_state.query.graphql';
@@ -99,6 +104,7 @@ export default {
apollo: {
state: {
query: getStateQuery,
+ notifyOnNetworkStatusChange: true,
manual: true,
skip() {
return !this.mr;
@@ -106,10 +112,19 @@ export default {
variables() {
return this.mergeRequestQueryVariables;
},
- result({ data: { project } }) {
- if (project) {
- this.mr.setGraphqlData(project);
- this.loading = false;
+ pollInterval() {
+ return this.pollInterval;
+ },
+ result(response) {
+ if (!response.loading) {
+ this.pollInterval = this.apolloStateQueryPollingInterval;
+
+ if (response.data?.project) {
+ this.mr.setGraphqlData(response.data.project);
+ this.loading = false;
+ }
+ } else {
+ this.checkStatus(undefined, undefined, false);
}
},
subscribeToMore: {
@@ -158,9 +173,27 @@ export default {
loading: true,
recomputeComponentName: 0,
issuableId: false,
+ startingPollInterval: STATE_QUERY_POLLING_INTERVAL_DEFAULT,
+ pollInterval: STATE_QUERY_POLLING_INTERVAL_DEFAULT,
};
},
computed: {
+ apolloStateQueryMaxPollingInterval() {
+ return this.startingPollInterval + FOUR_MINUTES_IN_MS;
+ },
+ apolloStateQueryPollingInterval() {
+ if (this.startingPollInterval < 0) {
+ return 0;
+ }
+
+ const unboundedInterval = STATE_QUERY_POLLING_INTERVAL_BACKOFF * this.pollInterval;
+
+ return clamp(
+ unboundedInterval,
+ this.startingPollInterval,
+ this.apolloStateQueryMaxPollingInterval,
+ );
+ },
shouldRenderApprovals() {
return this.mr.state !== 'nothingToMerge';
},
@@ -284,7 +317,8 @@ export default {
mounted() {
MRWidgetService.fetchInitialData()
.then(({ data, headers }) => {
- this.startingPollInterval = Number(headers['POLL-INTERVAL']);
+ this.startingPollInterval =
+ Number(headers['POLL-INTERVAL']) || STATE_QUERY_POLLING_INTERVAL_DEFAULT;
this.initWidget(data);
})
.catch(() =>
@@ -295,9 +329,6 @@ export default {
},
beforeDestroy() {
eventHub.$off('mr.discussion.updated', this.checkStatus);
- if (this.pollingInterval) {
- this.pollingInterval.destroy();
- }
if (this.deploymentsInterval) {
this.deploymentsInterval.destroy();
@@ -332,7 +363,6 @@ export default {
this.initPostMergeDeploymentsPolling();
}
- this.initPolling();
this.bindEventHubListeners();
eventHub.$on('mr.discussion.updated', this.checkStatus);
@@ -363,8 +393,10 @@ export default {
createService(store) {
return new MRWidgetService(this.getServiceEndpoints(store));
},
- checkStatus(cb, isRebased) {
- this.$apollo.queries.state.refetch();
+ checkStatus(cb, isRebased, refetch = true) {
+ if (refetch) {
+ this.$apollo.queries.state.refetch();
+ }
return this.service
.checkStatus()
@@ -389,17 +421,6 @@ export default {
}
return Promise.resolve();
},
- initPolling() {
- if (this.startingPollInterval <= 0) return;
-
- this.pollingInterval = new SmartInterval({
- callback: this.checkStatus,
- startingInterval: this.startingPollInterval,
- maxInterval: this.startingPollInterval + secondsToMilliseconds(4 * 60),
- hiddenInterval: secondsToMilliseconds(6 * 60),
- incrementByFactorOf: 2,
- });
- },
initDeploymentsPolling() {
this.deploymentsInterval = this.deploymentsPoll(this.fetchPreMergeDeployments);
},
@@ -476,10 +497,10 @@ export default {
notify.notifyMe(title, message, this.mr.gitlabLogo);
},
resumePolling() {
- this.pollingInterval?.resume();
+ this.$apollo.queries.state.startPolling(this.pollInterval);
},
stopPolling() {
- this.pollingInterval?.stopTimer();
+ this.$apollo.queries.state.stopPolling();
},
bindEventHubListeners() {
eventHub.$on('MRWidgetUpdateRequested', (cb) => {
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue
index f010fb1b5ce..1396d19d679 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_comment_form.vue
@@ -96,30 +96,41 @@ export default {
</script>
<template>
- <form class="common-note-form gfm-form js-main-target-form gl-flex-grow-1">
- <markdown-editor
- :value="commentText"
- :render-markdown-path="markdownPreviewPath"
- :markdown-docs-path="$options.constantOptions.markdownDocsPath"
- :form-field-props="formFieldProps"
- data-testid="work-item-add-comment"
- class="gl-mb-3"
- autofocus
- @input="setCommentText"
- @keydown.meta.enter="$emit('submitForm', commentText)"
- @keydown.ctrl.enter="$emit('submitForm', commentText)"
- @keydown.esc.stop="cancelEditing"
- />
- <gl-button
- category="primary"
- variant="confirm"
- data-testid="confirm-button"
- :loading="isSubmitting"
- @click="$emit('submitForm', commentText)"
- >{{ commentButtonText }}
- </gl-button>
- <gl-button data-testid="cancel-button" category="primary" class="gl-ml-3" @click="cancelEditing"
- >{{ __('Cancel') }}
- </gl-button>
- </form>
+ <div class="timeline-content">
+ <div class="timeline-discussion-body">
+ <div class="note-body">
+ <form class="common-note-form gfm-form js-main-target-form gl-flex-grow-1">
+ <markdown-editor
+ :value="commentText"
+ :render-markdown-path="markdownPreviewPath"
+ :markdown-docs-path="$options.constantOptions.markdownDocsPath"
+ :form-field-props="formFieldProps"
+ data-testid="work-item-add-comment"
+ class="gl-mb-3"
+ autofocus
+ use-bottom-toolbar
+ @input="setCommentText"
+ @keydown.meta.enter="$emit('submitForm', commentText)"
+ @keydown.ctrl.enter="$emit('submitForm', commentText)"
+ @keydown.esc.stop="cancelEditing"
+ />
+ <gl-button
+ category="primary"
+ variant="confirm"
+ data-testid="confirm-button"
+ :loading="isSubmitting"
+ @click="$emit('submitForm', commentText)"
+ >{{ commentButtonText }}
+ </gl-button>
+ <gl-button
+ data-testid="cancel-button"
+ category="primary"
+ class="gl-ml-3"
+ @click="cancelEditing"
+ >{{ __('Cancel') }}
+ </gl-button>
+ </form>
+ </div>
+ </div>
+ </div>
</template>
diff --git a/app/assets/javascripts/work_items/components/widget_wrapper.vue b/app/assets/javascripts/work_items/components/widget_wrapper.vue
index ba1470f97cd..db36b4e1bbe 100644
--- a/app/assets/javascripts/work_items/components/widget_wrapper.vue
+++ b/app/assets/javascripts/work_items/components/widget_wrapper.vue
@@ -73,7 +73,7 @@ export default {
<div
v-if="isOpen"
class="gl-bg-gray-10 gl-rounded-bottom-left-base gl-rounded-bottom-right-base"
- :class="{ 'gl-px-5 gl-py-4': !error }"
+ :class="{ 'gl-p-3': !error }"
data-testid="widget-body"
>
<slot name="body"></slot>
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 3f5e1c74c31..ad7a54aaf16 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -115,11 +115,6 @@ export default {
required: false,
default: null,
},
- modal: {
- type: Object,
- required: false,
- default: null,
- },
},
data() {
const workItemId = getParameterByName('work_item_id');
@@ -707,20 +702,16 @@ export default {
@removeChild="removeChild"
@show-modal="openInModal"
/>
- <template v-if="workItemsMvcEnabled">
- <work-item-notes
- v-if="workItemNotes"
- :work-item-id="workItem.id"
- :query-variables="queryVariables"
- :full-path="fullPath"
- :fetch-by-iid="fetchByIid"
- :work-item-type="workItemType"
- :is-modal="isModal"
- class="gl-pt-5"
- @error="updateError = $event"
- @has-notes="updateHasNotes"
- />
- </template>
+ <work-item-notes
+ v-if="workItemNotes"
+ :work-item-id="workItem.id"
+ :query-variables="queryVariables"
+ :full-path="fullPath"
+ :fetch-by-iid="fetchByIid"
+ :work-item-type="workItemType"
+ class="gl-pt-5"
+ @error="updateError = $event"
+ />
<gl-empty-state
v-if="error"
:title="$options.i18n.fetchErrorTitle"
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue
index 620d86bb363..d119cdc2785 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_link_child.vue
@@ -109,7 +109,9 @@ export default {
return this.isItemOpen ? __('Created') : __('Closed');
},
childPath() {
- return `/${this.projectPath}/-/work_items/${this.childItem.iid}?iid_path=true`;
+ return `${gon?.relative_url_root || ''}/${this.projectPath}/-/work_items/${
+ this.childItem.iid
+ }?iid_path=true`;
},
hasChildren() {
return this.getWidgetByType(this.childItem, WIDGET_TYPE_HIERARCHY)?.hasChildren;
@@ -171,7 +173,7 @@ export default {
<template>
<div>
<div
- class="gl-display-flex gl-align-items-flex-start gl-mb-3"
+ class="gl-display-flex gl-align-items-flex-start"
:class="{ 'gl-ml-6': canHaveChildren && !hasChildren && hasIndirectChildren }"
>
<gl-button
@@ -181,18 +183,20 @@ export default {
:aria-label="chevronTooltip"
:icon="chevronType"
category="tertiary"
+ size="small"
:loading="isLoadingChildren"
class="gl-px-0! gl-py-3! gl-mr-3"
data-testid="expand-child"
@click="toggleItem"
/>
<div
- class="gl-relative gl-display-flex gl-flex-grow-1 gl-overflow-break-word gl-min-w-0 gl-bg-white gl-py-3 gl-px-4 gl-border gl-border-gray-100 gl-rounded-base gl-line-height-32"
+ class="work-item-link-child gl-relative gl-display-flex gl-flex-grow-1 gl-overflow-break-word gl-min-w-0 gl-pl-3 gl-pr-2 gl-rounded-base"
+ :class="[hasMetadata ? 'gl-py-3' : 'gl-py-0']"
data-testid="links-child"
>
<span
:id="`stateIcon-${childItem.id}`"
- class="gl-mr-3"
+ class="gl-cursor-help gl-mr-3 gl-line-height-32"
:class="{ 'gl-display-flex': hasMetadata }"
data-testid="item-status-icon"
>
@@ -239,7 +243,7 @@ export default {
<work-item-link-child-metadata
v-if="hasMetadata"
:metadata-widgets="metadataWidgets"
- class="gl-mt-3"
+ class="gl-mt-1"
/>
</div>
<div
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
index d7e54ea1eb0..8f0e429234f 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
@@ -334,11 +334,11 @@ export default {
</gl-dropdown>
</template>
<template #body>
- <gl-loading-icon v-if="isLoading" color="dark" class="gl-my-3" />
+ <gl-loading-icon v-if="isLoading" color="dark" class="gl-my-2" />
<template v-else>
<div v-if="isChildrenEmpty && !isShownAddForm && !error" data-testid="links-empty">
- <p class="gl-mb-0 gl-text-gray-500">
+ <p class="gl-px-3 gl-py-2 gl-mb-0 gl-text-gray-500">
{{ $options.i18n.emptyStateMessage }}
</p>
</div>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
index 5169a77dd33..af475496075 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
@@ -340,7 +340,7 @@ export default {
<template>
<gl-form
- class="gl-bg-white gl-mb-3 gl-p-4 gl-border gl-border-gray-100 gl-rounded-base"
+ class="gl-bg-white gl-mt-1 gl-mb-3 gl-p-4 gl-border gl-border-gray-100 gl-rounded-base"
@submit.prevent="addOrCreateMethod"
>
<gl-alert v-if="error" variant="danger" class="gl-mb-3" @dismiss="unsetError">
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
index 1aa4a433a58..fb3ed7af736 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_menu.vue
@@ -11,8 +11,8 @@ export default {
</script>
<template>
- <span class="gl-ml-2">
- <gl-dropdown category="tertiary" toggle-class="btn-icon" :right="true">
+ <span class="gl-ml-5">
+ <gl-dropdown category="tertiary" toggle-class="btn-icon btn-sm" :right="true">
<template #button-content>
<gl-icon name="ellipsis_v" :size="14" />
</template>
diff --git a/app/assets/javascripts/work_items/router/index.js b/app/assets/javascripts/work_items/router/index.js
index 777badeb5be..8d67bcaf84f 100644
--- a/app/assets/javascripts/work_items/router/index.js
+++ b/app/assets/javascripts/work_items/router/index.js
@@ -11,6 +11,6 @@ export function createRouter(fullPath) {
return new VueRouter({
routes: routes(),
mode: 'history',
- base: joinPaths(fullPath, '-', 'work_items'),
+ base: joinPaths(gon?.relative_url_root, fullPath, '-', 'work_items'),
});
}
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index b685a27b216..b6ac4939a9c 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -289,3 +289,22 @@ label {
.input-group-text {
max-height: $input-height;
}
+
+.add-issuable-form-input-wrapper {
+ &.focus {
+ border-color: var(--gray-700, $gray-700);
+
+ input {
+ @include gl-shadow-none;
+ }
+ }
+
+ .gl-show-field-errors &.form-control:not(textarea) {
+ height: auto;
+ }
+}
+
+.add-issuable-form-input-wrapper.focus,
+.issue-token-remove-button:focus {
+ @include gl-focus;
+}
diff --git a/app/assets/stylesheets/framework/timeline.scss b/app/assets/stylesheets/framework/timeline.scss
index 32e9bba8712..699693bd354 100644
--- a/app/assets/stylesheets/framework/timeline.scss
+++ b/app/assets/stylesheets/framework/timeline.scss
@@ -31,6 +31,7 @@
&:not(.note-form).internal-note .timeline-content,
&:not(.note-form).draft-note .timeline-content {
background-color: $orange-50 !important;
+ border-radius: 3px;
}
.timeline-entry-inner {
diff --git a/app/assets/stylesheets/page_bundles/issuable.scss b/app/assets/stylesheets/page_bundles/issuable.scss
index 7321da1526d..6ec6a282329 100644
--- a/app/assets/stylesheets/page_bundles/issuable.scss
+++ b/app/assets/stylesheets/page_bundles/issuable.scss
@@ -139,21 +139,6 @@
}
}
-.add-issuable-form-input-wrapper {
- &.focus {
- border-color: var(--gray-700, $gray-700);
- @include gl-focus;
-
- input {
- @include gl-shadow-none;
- }
- }
-
- .gl-show-field-errors &.form-control:not(textarea) {
- height: auto;
- }
-}
-
/*
* Following overrides are done to prevent
* legacy dropdown styles from influencing
diff --git a/app/assets/stylesheets/page_bundles/work_items.scss b/app/assets/stylesheets/page_bundles/work_items.scss
index 5f6883623b2..00c86c46ac8 100644
--- a/app/assets/stylesheets/page_bundles/work_items.scss
+++ b/app/assets/stylesheets/page_bundles/work_items.scss
@@ -87,6 +87,19 @@
}
}
+.work-item-link-child {
+ @include gl-border-1;
+ @include gl-border-solid;
+ @include gl-border-transparent;
+ @include gl-rounded-base;
+
+ &:hover,
+ &:focus-within {
+ @include gl-bg-white;
+ @include gl-border-gray-50;
+ }
+}
+
// sticky error placement for errors in modals , by default it is 83px for full view
#work-item-detail-modal {
.flash-container.flash-container-page.sticky {
diff --git a/app/controllers/admin/broadcast_messages_controller.rb b/app/controllers/admin/broadcast_messages_controller.rb
index d641a26c9fb..654b8309937 100644
--- a/app/controllers/admin/broadcast_messages_controller.rb
+++ b/app/controllers/admin/broadcast_messages_controller.rb
@@ -72,7 +72,7 @@ module Admin
def preview
@broadcast_message = BroadcastMessage.new(broadcast_message_params)
- render partial: 'admin/broadcast_messages/preview'
+ render plain: render_broadcast_message(@broadcast_message), status: :ok
end
protected
diff --git a/app/controllers/groups/children_controller.rb b/app/controllers/groups/children_controller.rb
index fb3a86d5219..ca3be1542aa 100644
--- a/app/controllers/groups/children_controller.rb
+++ b/app/controllers/groups/children_controller.rb
@@ -5,6 +5,8 @@ module Groups
extend ::Gitlab::Utils::Override
before_action :group
+ before_action :validate_per_page
+
skip_cross_project_access_check :index
feature_category :subgroups
@@ -44,7 +46,7 @@ module Groups
@children = GroupDescendantsFinder.new(
current_user: current_user,
parent_group: parent,
- params: params.to_unsafe_h
+ params: group_descendants_params
).execute.page(params[:page])
end
@@ -54,5 +56,25 @@ module Groups
def has_project_list?
true
end
+
+ def group_descendants_params
+ @group_descendants_params ||= params.to_unsafe_h.compact
+ end
+
+ def validate_per_page
+ return unless group_descendants_params.key?(:per_page)
+
+ per_page = begin
+ Integer(group_descendants_params[:per_page])
+ rescue ArgumentError, TypeError
+ 0
+ end
+
+ respond_to do |format|
+ format.json do
+ render status: :bad_request, json: { message: 'per_page does not have a valid value' } if per_page < 1
+ end
+ end
+ end
end
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index a5f938dc1c7..604ca7e3a1a 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -10,6 +10,7 @@ class CommitStatus < Ci::ApplicationRecord
include TaggableQueries
self.table_name = 'ci_builds'
+ self.primary_key = :id
partitionable scope: :pipeline
belongs_to :user
diff --git a/app/views/admin/broadcast_messages/_preview.html.haml b/app/views/admin/broadcast_messages/_preview.html.haml
deleted file mode 100644
index 56168926a6e..00000000000
--- a/app/views/admin/broadcast_messages/_preview.html.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-.js-broadcast-banner-message-preview
- = render "shared/broadcast_message", { message: @broadcast_message, preview: true } do
- = _('Your message here')
diff --git a/app/views/projects/commit/diff_files.html.haml b/app/views/projects/commit/diff_files.html.haml
index 0c52c1a15a4..7287d10a109 100644
--- a/app/views/projects/commit/diff_files.html.haml
+++ b/app/views/projects/commit/diff_files.html.haml
@@ -1 +1,5 @@
-= render partial: 'projects/diffs/file', collection: diffs.diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
+- diff_files = conditionally_paginate_diff_files(diffs, paginate: true, page: params[:page], per: Projects::CommitController::COMMIT_DIFFS_PER_PAGE)
+
+= render partial: 'projects/diffs/file', collection: diff_files, as: :diff_file, locals: { project: diffs.project, environment: environment, diff_page_context: 'is-commit' }
+
+= paginate(diff_files, theme: "gitlab", params: { action: :show })
diff --git a/app/views/projects/diffs/_diffs.html.haml b/app/views/projects/diffs/_diffs.html.haml
index 8ff6d348d95..03e26fd4456 100644
--- a/app/views/projects/diffs/_diffs.html.haml
+++ b/app/views/projects/diffs/_diffs.html.haml
@@ -3,7 +3,7 @@
- can_create_note = !@diff_notes_disabled && can?(current_user, :create_note, diffs.project)
- diff_page_context = local_assigns.fetch(:diff_page_context, nil)
- load_diff_files_async = Feature.enabled?(:async_commit_diff_files, @project) && diff_page_context == "is-commit"
-- paginate_diffs = local_assigns.fetch(:paginate_diffs, false) && !load_diff_files_async
+- paginate_diffs = local_assigns.fetch(:paginate_diffs, false)
- paginate_diffs_per_page = local_assigns.fetch(:paginate_diffs_per_page, nil)
- page = local_assigns.fetch(:page, nil)
- diff_files = conditionally_paginate_diff_files(diffs, paginate: paginate_diffs, page: page, per: paginate_diffs_per_page)
@@ -32,7 +32,7 @@
.files{ data: { can_create_note: can_create_note } }
- if load_diff_files_async
- - url = url_for(safe_params.merge(action: 'diff_files'))
+ - url = url_for(safe_params.merge(action: 'diff_files', page: page))
.js-diffs-batch{ data: { diff_files_path: url } }
= gl_loading_icon(size: "md", css_class: "gl-mt-4")
- else