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>2021-10-09 00:09:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-10-09 00:09:48 +0300
commit59e6c2df22c69baa791529db3326e68c9de10b54 (patch)
treeaa75309a037a6031c38f8ccd9afe53cbcd519355 /app
parente7527f548681e4f9efd32f9c3da937ad74c68948 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/content_editor/components/top_toolbar.vue9
-rw-r--r--app/assets/javascripts/content_editor/components/wrappers/details.vue33
-rw-r--r--app/assets/javascripts/content_editor/extensions/details.js36
-rw-r--r--app/assets/javascripts/content_editor/extensions/details_content.js25
-rw-r--r--app/assets/javascripts/content_editor/services/create_content_editor.js4
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js12
-rw-r--r--app/assets/javascripts/design_management/pages/design/index.vue2
-rw-r--r--app/assets/javascripts/design_management/pages/index.vue2
-rw-r--r--app/assets/javascripts/design_management/utils/cache_update.js2
-rw-r--r--app/assets/javascripts/design_management/utils/error_messages.js72
-rw-r--r--app/assets/javascripts/pages/sessions/new/oauth_remember_me.js2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue14
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js11
-rw-r--r--app/assets/stylesheets/components/content_editor.scss36
-rw-r--r--app/assets/stylesheets/framework/forms.scss8
-rw-r--r--app/assets/stylesheets/framework/typography.scss10
-rw-r--r--app/assets/stylesheets/page_bundles/signup.scss8
-rw-r--r--app/assets/stylesheets/pages/login.scss5
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss6
-rw-r--r--app/assets/stylesheets/startup/startup-signin.scss44
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss4
-rw-r--r--app/helpers/startupjs_helper.rb7
-rw-r--r--app/views/devise/sessions/_new_base.html.haml6
-rw-r--r--app/views/devise/shared/_omniauth_box.html.haml10
-rw-r--r--app/views/devise/shared/_signup_omniauth_provider_list.haml8
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers.haml2
-rw-r--r--app/views/devise/shared/_signup_omniauth_providers_top.haml2
-rw-r--r--app/views/layouts/_startup_js.html.haml5
30 files changed, 283 insertions, 118 deletions
diff --git a/app/assets/javascripts/content_editor/components/top_toolbar.vue b/app/assets/javascripts/content_editor/components/top_toolbar.vue
index 82a449ae6af..89182b3a09f 100644
--- a/app/assets/javascripts/content_editor/components/top_toolbar.vue
+++ b/app/assets/javascripts/content_editor/components/top_toolbar.vue
@@ -112,6 +112,15 @@ export default {
@execute="trackToolbarControlExecution"
/>
<toolbar-button
+ data-testid="details"
+ content-type="details"
+ icon-name="details-block"
+ class="gl-mx-2"
+ editor-command="toggleDetails"
+ :label="__('Add a collapsible section')"
+ @execute="trackToolbarControlExecution"
+ />
+ <toolbar-button
data-testid="horizontal-rule"
content-type="horizontalRule"
icon-name="dash"
diff --git a/app/assets/javascripts/content_editor/components/wrappers/details.vue b/app/assets/javascripts/content_editor/components/wrappers/details.vue
new file mode 100644
index 00000000000..aff15ac3e53
--- /dev/null
+++ b/app/assets/javascripts/content_editor/components/wrappers/details.vue
@@ -0,0 +1,33 @@
+<script>
+import { NodeViewWrapper, NodeViewContent } from '@tiptap/vue-2';
+
+export default {
+ name: 'DetailsWrapper',
+ components: {
+ NodeViewWrapper,
+ NodeViewContent,
+ },
+ props: {
+ node: {
+ type: Object,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ open: true,
+ };
+ },
+};
+</script>
+<template>
+ <node-view-wrapper class="gl-display-flex">
+ <div
+ class="details-toggle-icon"
+ data-testid="details-toggle-icon"
+ :class="{ 'is-open': open }"
+ @click="open = !open"
+ ></div>
+ <node-view-content as="ul" class="details-content" :class="{ 'is-open': open }" />
+ </node-view-wrapper>
+</template>
diff --git a/app/assets/javascripts/content_editor/extensions/details.js b/app/assets/javascripts/content_editor/extensions/details.js
new file mode 100644
index 00000000000..e3d54ed01fd
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/details.js
@@ -0,0 +1,36 @@
+import { Node } from '@tiptap/core';
+import { VueNodeViewRenderer } from '@tiptap/vue-2';
+import { wrappingInputRule } from 'prosemirror-inputrules';
+import DetailsWrapper from '../components/wrappers/details.vue';
+
+export const inputRegex = /^\s*(<details>)$/;
+
+export default Node.create({
+ name: 'details',
+ content: 'detailsContent+',
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ group: 'block list',
+
+ parseHTML() {
+ return [{ tag: 'details' }];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['ul', HTMLAttributes, 0];
+ },
+
+ addNodeView() {
+ return VueNodeViewRenderer(DetailsWrapper);
+ },
+
+ addInputRules() {
+ return [wrappingInputRule(inputRegex, this.type)];
+ },
+
+ addCommands() {
+ return {
+ setDetails: () => ({ commands }) => commands.wrapInList('details'),
+ toggleDetails: () => ({ commands }) => commands.toggleList('details', 'detailsContent'),
+ };
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/details_content.js b/app/assets/javascripts/content_editor/extensions/details_content.js
new file mode 100644
index 00000000000..fb6c49d91aa
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/details_content.js
@@ -0,0 +1,25 @@
+import { Node } from '@tiptap/core';
+import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
+
+export default Node.create({
+ name: 'detailsContent',
+ content: 'block+',
+ defining: true,
+
+ parseHTML() {
+ return [
+ { tag: '*', consuming: false, context: 'details/', priority: PARSE_HTML_PRIORITY_HIGHEST },
+ ];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['li', HTMLAttributes, 0];
+ },
+
+ addKeyboardShortcuts() {
+ return {
+ Enter: () => this.editor.commands.splitListItem('detailsContent'),
+ 'Shift-Tab': () => this.editor.commands.liftListItem('detailsContent'),
+ };
+ },
+});
diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js
index 0471adf67e9..3b4fda26a36 100644
--- a/app/assets/javascripts/content_editor/services/create_content_editor.js
+++ b/app/assets/javascripts/content_editor/services/create_content_editor.js
@@ -10,6 +10,8 @@ import Code from '../extensions/code';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import DescriptionItem from '../extensions/description_item';
import DescriptionList from '../extensions/description_list';
+import Details from '../extensions/details';
+import DetailsContent from '../extensions/details_content';
import Division from '../extensions/division';
import Document from '../extensions/document';
import Dropcursor from '../extensions/dropcursor';
@@ -81,6 +83,8 @@ export const createContentEditor = ({
CodeBlockHighlight,
DescriptionItem,
DescriptionList,
+ Details,
+ DetailsContent,
Document,
Division,
Dropcursor,
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index 19b67f6fde8..8b6cff3f2e1 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -11,6 +11,8 @@ import Code from '../extensions/code';
import CodeBlockHighlight from '../extensions/code_block_highlight';
import DescriptionItem from '../extensions/description_item';
import DescriptionList from '../extensions/description_list';
+import Details from '../extensions/details';
+import DetailsContent from '../extensions/details_content';
import Division from '../extensions/division';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
@@ -53,6 +55,7 @@ import {
renderImage,
renderPlayable,
renderHTMLNode,
+ renderContent,
} from './serialization_helpers';
const defaultSerializerConfig = {
@@ -133,6 +136,15 @@ const defaultSerializerConfig = {
renderHTMLNode(node.attrs.isTerm ? 'dt' : 'dd')(state, node);
if (index === parent.childCount - 1) state.ensureNewLine();
},
+ [Details.name]: renderHTMLNode('details', true),
+ [DetailsContent.name]: (state, node, parent, index) => {
+ if (!index) renderHTMLNode('summary')(state, node);
+ else {
+ if (index === 1) state.ensureNewLine();
+ renderContent(state, node);
+ if (index === parent.childCount - 1) state.ensureNewLine();
+ }
+ },
[Emoji.name]: (state, node) => {
const { name } = node.attrs;
diff --git a/app/assets/javascripts/design_management/pages/design/index.vue b/app/assets/javascripts/design_management/pages/design/index.vue
index 38ea5406c02..837320b9423 100644
--- a/app/assets/javascripts/design_management/pages/design/index.vue
+++ b/app/assets/javascripts/design_management/pages/design/index.vue
@@ -273,7 +273,7 @@ export default {
this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
},
onDesignDeleteError(e) {
- this.onError(designDeletionError({ singular: true }), e);
+ this.onError(designDeletionError(), e);
},
onResolveDiscussionError(e) {
this.onError(UPDATE_IMAGE_DIFF_NOTE_ERROR, e);
diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue
index e66ae822a34..5092c30aa60 100644
--- a/app/assets/javascripts/design_management/pages/index.vue
+++ b/app/assets/javascripts/design_management/pages/index.vue
@@ -255,7 +255,7 @@ export default {
if (this.$route.query.version) this.$router.push({ name: DESIGNS_ROUTE_NAME });
},
onDesignDeleteError() {
- const errorMessage = designDeletionError({ singular: this.selectedDesigns.length === 1 });
+ const errorMessage = designDeletionError(this.selectedDesigns.length);
createFlash({ message: errorMessage });
},
onDesignDropzoneError() {
diff --git a/app/assets/javascripts/design_management/utils/cache_update.js b/app/assets/javascripts/design_management/utils/cache_update.js
index 33c4fd5a7d9..c8f445bfb88 100644
--- a/app/assets/javascripts/design_management/utils/cache_update.js
+++ b/app/assets/javascripts/design_management/utils/cache_update.js
@@ -250,7 +250,7 @@ export const hasErrors = ({ errors = [] }) => errors?.length;
*/
export const updateStoreAfterDesignsDelete = (store, data, query, designs) => {
if (hasErrors(data)) {
- onError(data, designDeletionError({ singular: designs.length === 1 }));
+ onError(data, designDeletionError(designs.length));
} else {
deleteDesignsFromStore(store, query, designs);
addNewVersionToStore(store, query, data.version);
diff --git a/app/assets/javascripts/design_management/utils/error_messages.js b/app/assets/javascripts/design_management/utils/error_messages.js
index afee7e81791..981b50329b2 100644
--- a/app/assets/javascripts/design_management/utils/error_messages.js
+++ b/app/assets/javascripts/design_management/utils/error_messages.js
@@ -1,4 +1,3 @@
-/* eslint-disable @gitlab/require-string-literal-i18n-helpers */
import { __, s__, n__, sprintf } from '~/locale';
export const ADD_DISCUSSION_COMMENT_ERROR = s__(
@@ -27,12 +26,6 @@ export const DESIGN_NOT_FOUND_ERROR = __('Could not find design.');
export const DESIGN_VERSION_NOT_EXIST_ERROR = __('Requested design version does not exist.');
-const DESIGN_UPLOAD_SKIPPED_MESSAGE = s__('DesignManagement|Upload skipped.');
-
-const ALL_DESIGNS_SKIPPED_MESSAGE = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'The designs you tried uploading did not change.',
-)}`;
-
export const EXISTING_DESIGN_DROP_MANY_FILES_MESSAGE = __(
'You can only upload one design when dropping onto an existing design.',
);
@@ -53,12 +46,9 @@ export const DELETE_DESIGN_TODO_ERROR = __('Failed to remove a to-do item for th
export const TOGGLE_TODO_ERROR = __('Failed to toggle the to-do status for the design.');
-const MAX_SKIPPED_FILES_LISTINGS = 5;
+const DESIGN_UPLOAD_SKIPPED_MESSAGE = s__('DesignManagement|Upload skipped. %{reason}');
-const oneDesignSkippedMessage = (filename) =>
- `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${sprintf(s__('DesignManagement|%{filename} did not change.'), {
- filename,
- })}`;
+const MAX_SKIPPED_FILES_LISTINGS = 5;
/**
* Return warning message indicating that some (but not all) uploaded
@@ -66,25 +56,40 @@ const oneDesignSkippedMessage = (filename) =>
* @param {Array<{ filename }>} skippedFiles
*/
const someDesignsSkippedMessage = (skippedFiles) => {
- const designsSkippedMessage = `${DESIGN_UPLOAD_SKIPPED_MESSAGE} ${s__(
- 'Some of the designs you tried uploading did not change:',
- )}`;
-
- const moreText = sprintf(s__(`DesignManagement|and %{moreCount} more.`), {
- moreCount: skippedFiles.length - MAX_SKIPPED_FILES_LISTINGS,
- });
-
- return `${designsSkippedMessage} ${skippedFiles
+ const skippedFilesList = skippedFiles
.slice(0, MAX_SKIPPED_FILES_LISTINGS)
.map(({ filename }) => filename)
- .join(', ')}${skippedFiles.length > MAX_SKIPPED_FILES_LISTINGS ? `, ${moreText}` : '.'}`;
+ .join(', ');
+
+ const uploadSkippedReason =
+ skippedFiles.length > MAX_SKIPPED_FILES_LISTINGS
+ ? sprintf(
+ s__(
+ 'DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more.',
+ ),
+ {
+ skippedFiles: skippedFilesList,
+ moreCount: skippedFiles.length - MAX_SKIPPED_FILES_LISTINGS,
+ },
+ )
+ : sprintf(
+ s__(
+ 'DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}.',
+ ),
+ { skippedFiles: skippedFilesList },
+ );
+
+ return sprintf(DESIGN_UPLOAD_SKIPPED_MESSAGE, {
+ reason: uploadSkippedReason,
+ });
};
-export const designDeletionError = ({ singular = true } = {}) => {
- const design = singular ? __('a design') : __('designs');
- return sprintf(s__('Could not archive %{design}. Please try again.'), {
- design,
- });
+export const designDeletionError = (designsCount = 1) => {
+ return n__(
+ 'Failed to archive a design. Please try again.',
+ 'Failed to archive designs. Please try again.',
+ designsCount,
+ );
};
/**
@@ -101,7 +106,18 @@ export const designUploadSkippedWarning = (uploadedDesigns, skippedFiles) => {
if (skippedFiles.length === uploadedDesigns.length) {
const { filename } = skippedFiles[0];
- return n__(oneDesignSkippedMessage(filename), ALL_DESIGNS_SKIPPED_MESSAGE, skippedFiles.length);
+ const uploadSkippedReason = sprintf(
+ n__(
+ 'DesignManagement|%{filename} did not change.',
+ 'DesignManagement|The designs you tried uploading did not change.',
+ skippedFiles.length,
+ ),
+ { filename },
+ );
+
+ return sprintf(DESIGN_UPLOAD_SKIPPED_MESSAGE, {
+ reason: uploadSkippedReason,
+ });
}
return someDesignsSkippedMessage(skippedFiles);
diff --git a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
index 8d2d5d41f6a..ee48543f0d2 100644
--- a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
+++ b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js
@@ -20,7 +20,7 @@ export default class OAuthRememberMe {
toggleRememberMe(event) {
const rememberMe = $(event.target).is(':checked');
- $('.oauth-login', this.container).each((i, element) => {
+ $('.js-oauth-login', this.container).each((i, element) => {
const $form = $(element).parent('form');
const href = $form.attr('action');
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
index 3470c963ade..b778fe28e59 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_multi_actions.vue
@@ -5,7 +5,6 @@ import {
GlDropdownItem,
GlDropdownSectionHeader,
GlLoadingIcon,
- GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
@@ -13,7 +12,6 @@ import { __, s__ } from '~/locale';
export const i18n = {
artifacts: __('Artifacts'),
- downloadArtifact: __('Download %{name} artifact'),
artifactSectionHeader: __('Download artifacts'),
artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
emptyArtifactsMessage: __('No artifacts found'),
@@ -30,7 +28,6 @@ export default {
GlDropdownItem,
GlDropdownSectionHeader,
GlLoadingIcon,
- GlSprintf,
},
inject: {
artifactsEndpoint: {
@@ -113,9 +110,7 @@ export default {
class="gl-word-break-word"
data-testid="artifact-item"
>
- <gl-sprintf :message="$options.i18n.downloadArtifact">
- <template #name>{{ artifact.name }}</template>
- </gl-sprintf>
+ {{ artifact.name }}
</gl-dropdown-item>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
index 36629d9f1f1..1c7c4d7c704 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_artifacts.vue
@@ -3,8 +3,8 @@ import {
GlAlert,
GlDropdown,
GlDropdownItem,
+ GlDropdownSectionHeader,
GlLoadingIcon,
- GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
import axios from '~/lib/utils/axios_utils';
@@ -12,7 +12,6 @@ import { __, s__ } from '~/locale';
export const i18n = {
artifacts: __('Artifacts'),
- downloadArtifact: __('Download %{name} artifact'),
artifactSectionHeader: __('Download artifacts'),
artifactsFetchErrorMessage: s__('Pipelines|Could not load artifacts.'),
noArtifacts: s__('Pipelines|No artifacts available'),
@@ -27,8 +26,8 @@ export default {
GlAlert,
GlDropdown,
GlDropdownItem,
+ GlDropdownSectionHeader,
GlLoadingIcon,
- GlSprintf,
},
inject: {
artifactsEndpoint: {
@@ -92,6 +91,10 @@ export default {
text-sr-only
@show.once="fetchArtifacts"
>
+ <gl-dropdown-section-header>{{
+ $options.i18n.artifactSectionHeader
+ }}</gl-dropdown-section-header>
+
<gl-alert v-if="hasError" variant="danger" :dismissible="false">
{{ $options.i18n.artifactsFetchErrorMessage }}
</gl-alert>
@@ -108,10 +111,9 @@ export default {
:href="artifact.path"
rel="nofollow"
download
+ class="gl-word-break-word"
>
- <gl-sprintf :message="$options.i18n.downloadArtifact">
- <template #name>{{ artifact.name }}</template>
- </gl-sprintf>
+ {{ artifact.name }}
</gl-dropdown-item>
</gl-dropdown>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
index eaa1d6f4cdd..38ee81be555 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
@@ -49,7 +49,7 @@ const MERGE_SUCCESS_STATUS = 'success';
const MERGE_HOOK_VALIDATION_ERROR_STATUS = 'hook_validation_error';
const { transitions } = STATE_MACHINE;
-const { MERGE, MERGED, MERGE_FAILURE } = transitions;
+const { MERGE, MERGED, MERGE_FAILURE, AUTO_MERGE } = transitions;
export default {
name: 'ReadyToMerge',
@@ -365,7 +365,11 @@ export default {
}
this.isMakingRequest = true;
- this.mr.transitionStateMachine({ transition: MERGE });
+
+ if (!useAutoMerge) {
+ this.mr.transitionStateMachine({ transition: MERGE });
+ }
+
this.service
.merge(options)
.then((res) => res.data)
@@ -376,6 +380,7 @@ export default {
if (AUTO_MERGE_STRATEGIES.includes(data.status)) {
eventHub.$emit('MRWidgetUpdateRequested');
+ this.mr.transitionStateMachine({ transition: AUTO_MERGE });
} else if (data.status === MERGE_SUCCESS_STATUS) {
this.initiateMergePolling();
} else if (hasError) {
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index 297e0cfa363..b88e83ccb0f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -58,9 +58,11 @@ const STATE_MACHINE = {
states: {
IDLE: 'IDLE',
MERGING: 'MERGING',
+ AUTO_MERGE: 'AUTO_MERGE',
},
transitions: {
MERGE: 'start-merge',
+ AUTO_MERGE: 'start-auto-merge',
MERGE_FAILURE: 'merge-failed',
MERGED: 'merge-done',
},
@@ -73,6 +75,7 @@ STATE_MACHINE.definition = {
[states.IDLE]: {
on: {
[transitions.MERGE]: states.MERGING,
+ [transitions.AUTO_MERGE]: states.AUTO_MERGE,
},
},
[states.MERGING]: {
@@ -81,15 +84,23 @@ STATE_MACHINE.definition = {
[transitions.MERGE_FAILURE]: states.IDLE,
},
},
+ [states.AUTO_MERGE]: {
+ on: {
+ [transitions.MERGED]: states.IDLE,
+ [transitions.MERGE_FAILURE]: states.IDLE,
+ },
+ },
},
};
export const stateToTransitionMap = {
[stateKey.merging]: transitions.MERGE,
[stateKey.merged]: transitions.MERGED,
+ [stateKey.autoMergeEnabled]: transitions.AUTO_MERGE,
};
export const stateToComponentMap = {
[states.MERGING]: classStateMap[stateKey.merging],
+ [states.AUTO_MERGE]: classStateMap[stateKey.autoMergeEnabled],
};
export const EXTENSION_ICONS = {
diff --git a/app/assets/stylesheets/components/content_editor.scss b/app/assets/stylesheets/components/content_editor.scss
index a013d971efb..673e935ed9d 100644
--- a/app/assets/stylesheets/components/content_editor.scss
+++ b/app/assets/stylesheets/components/content_editor.scss
@@ -3,7 +3,8 @@
th,
li,
dd,
- dt {
+ dt,
+ summary {
:first-child {
margin-bottom: 0 !important;
}
@@ -37,6 +38,7 @@
}
}
+
.dl-content {
width: 100%;
@@ -50,6 +52,38 @@
}
}
}
+
+ .details-toggle-icon {
+ cursor: pointer;
+ z-index: 1;
+
+ &::before {
+ content: '▶';
+ display: inline-block;
+ width: $gl-spacing-scale-4;
+ }
+
+ &.is-open::before {
+ content: '▼';
+ }
+ }
+
+ .details-content {
+ width: calc(100% - #{$gl-spacing-scale-4});
+
+ > li {
+ list-style-type: none;
+ margin-left: $gl-spacing-scale-2;
+ }
+
+ > :not(:first-child) {
+ display: none;
+ }
+
+ &.is-open > :not(:first-child) {
+ display: inherit;
+ }
+ }
}
.table-creator-grid-item {
diff --git a/app/assets/stylesheets/framework/forms.scss b/app/assets/stylesheets/framework/forms.scss
index c366bf80093..2a46e50f0da 100644
--- a/app/assets/stylesheets/framework/forms.scss
+++ b/app/assets/stylesheets/framework/forms.scss
@@ -196,14 +196,6 @@ label {
}
}
-@include media-breakpoint-down(xs) {
- .remember-me {
- .remember-me-checkbox {
- margin-top: 0;
- }
- }
-}
-
.input-icon-wrapper,
.select-wrapper {
position: relative;
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index c40433651ab..cb36c4e5767 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -75,6 +75,15 @@
details {
margin-bottom: $gl-padding;
+
+ > *:not(summary) {
+ margin-left: $gl-spacing-scale-5;
+ }
+ }
+
+ summary > * {
+ display: inline-block;
+ margin-bottom: 0;
}
// Single code lines should wrap
@@ -478,6 +487,7 @@
font-size: larger;
}
+ figcaption,
.small {
font-size: smaller;
}
diff --git a/app/assets/stylesheets/page_bundles/signup.scss b/app/assets/stylesheets/page_bundles/signup.scss
index 57e5d2411d1..4fc671dace8 100644
--- a/app/assets/stylesheets/page_bundles/signup.scss
+++ b/app/assets/stylesheets/page_bundles/signup.scss
@@ -26,14 +26,6 @@
}
}
- .omniauth-btn {
- width: 48%;
-
- @include media-breakpoint-down(md) {
- width: 100%;
- }
- }
-
.decline-page {
width: 350px;
}
diff --git a/app/assets/stylesheets/pages/login.scss b/app/assets/stylesheets/pages/login.scss
index 45cbef2d1c2..71ddbf175e9 100644
--- a/app/assets/stylesheets/pages/login.scss
+++ b/app/assets/stylesheets/pages/login.scss
@@ -99,11 +99,6 @@
padding: 0;
border: 0;
background: none;
- margin-bottom: $gl-padding;
- }
-
- .omniauth-btn {
- width: 100%;
}
}
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index 2f68694a2a5..d436c328921 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -5,13 +5,13 @@
body.gl-dark {
--gray-50: #303030;
--gray-100: #404040;
+ --gray-900: #fafafa;
--gray-950: #fff;
--green-100: #0d532a;
--green-400: #108548;
--green-700: #91d4a8;
--blue-400: #1f75cb;
--orange-400: #ab6100;
- --purple-100: #2f2a6b;
--gl-text-color: #fafafa;
--border-color: #4f4f4f;
--black: #fff;
@@ -1785,8 +1785,8 @@ body.gl-dark .nav-sidebar li.active > a {
body.gl-dark .nav-sidebar .fly-out-top-item a,
body.gl-dark .nav-sidebar .fly-out-top-item.active a,
body.gl-dark .nav-sidebar .fly-out-top-item .fly-out-top-item-container {
- background-color: var(--purple-100, #e1d8f9);
- color: var(--black, #333);
+ background-color: var(--gray-100, #303030);
+ color: var(--gray-900, #fafafa);
}
body.gl-dark .logo-text svg {
fill: var(--gl-text-color);
diff --git a/app/assets/stylesheets/startup/startup-signin.scss b/app/assets/stylesheets/startup/startup-signin.scss
index 013ad3fac87..8d7531d6c9c 100644
--- a/app/assets/stylesheets/startup/startup-signin.scss
+++ b/app/assets/stylesheets/startup/startup-signin.scss
@@ -258,21 +258,6 @@ fieldset:disabled a.btn {
align-items: center;
justify-content: space-between;
}
-.d-block {
- display: block !important;
-}
-.d-flex {
- display: flex !important;
-}
-.flex-wrap {
- flex-wrap: wrap !important;
-}
-.justify-content-between {
- justify-content: space-between !important;
-}
-.align-items-center {
- align-items: center !important;
-}
.fixed-top {
position: fixed;
top: 0;
@@ -280,9 +265,6 @@ fieldset:disabled a.btn {
left: 0;
z-index: 1030;
}
-.ml-2 {
- margin-left: 0.5rem !important;
-}
.mt-3 {
margin-top: 1rem !important;
}
@@ -349,6 +331,15 @@ fieldset:disabled a.btn {
font-size: 0.875rem;
border-radius: 0.25rem;
}
+.gl-button.gl-button .gl-button-text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ margin-top: -1px;
+ margin-bottom: -1px;
+}
.gl-button.gl-button .gl-button-icon {
height: 1rem;
width: 1rem;
@@ -637,10 +628,6 @@ svg {
padding: 0;
border: 0;
background: none;
- margin-bottom: 16px;
-}
-.login-page .omniauth-container .omniauth-btn {
- width: 100%;
}
.login-page .new-session-tabs {
display: flex;
@@ -771,21 +758,18 @@ svg {
.gl-align-items-center {
align-items: center;
}
+.gl-flex-wrap {
+ flex-wrap: wrap;
+}
.gl-w-full {
width: 100%;
}
-.gl-p-2 {
- padding: 0.25rem;
-}
.gl-p-4 {
padding: 0.75rem;
}
.gl-mt-2 {
margin-top: 0.25rem;
}
-.gl-mb-2 {
- margin-bottom: 0.25rem;
-}
.gl-mb-3 {
margin-bottom: 0.5rem;
}
@@ -797,8 +781,8 @@ svg {
margin-top: 0;
}
}
-.gl-text-left {
- text-align: left;
+.gl-font-weight-bold {
+ font-weight: 600;
}
@import "startup/cloaking";
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index a9e8b238d78..1332686a906 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -212,8 +212,8 @@
a:hover,
&.active a,
.fly-out-top-item-container {
- background-color: var(--purple-100, $purple-900);
- color: var(--black, $white);
+ background-color: var(--gray-100, $gray-50);
+ color: var(--gray-900, $gray-900);
}
}
}
diff --git a/app/helpers/startupjs_helper.rb b/app/helpers/startupjs_helper.rb
index b595590c7c9..2e8f0cb7dbe 100644
--- a/app/helpers/startupjs_helper.rb
+++ b/app/helpers/startupjs_helper.rb
@@ -5,6 +5,13 @@ module StartupjsHelper
@graphql_startup_calls
end
+ def page_startup_graphql_headers
+ {
+ 'X-CSRF-Token' => form_authenticity_token,
+ 'x-gitlab-feature-category' => ::Gitlab::ApplicationContext.current_context_attribute(:feature_category).presence || ''
+ }
+ end
+
def add_page_startup_graphql_call(query, variables = {})
@graphql_startup_calls ||= []
file_location = File.join(Rails.root, "app/graphql/queries/#{query}.query.graphql")
diff --git a/app/views/devise/sessions/_new_base.html.haml b/app/views/devise/sessions/_new_base.html.haml
index 82c0df354d4..9015474a868 100644
--- a/app/views/devise/sessions/_new_base.html.haml
+++ b/app/views/devise/sessions/_new_base.html.haml
@@ -6,10 +6,10 @@
= f.label :password, class: 'label-bold'
= f.password_field :password, class: 'form-control gl-form-input bottom', required: true, title: _('This field is required.'), data: { qa_selector: 'password_field' }
- if devise_mapping.rememberable?
- .remember-me
+ %div
%label{ for: 'user_remember_me' }
- = f.check_box :remember_me, class: 'remember-me-checkbox'
- %span Remember me
+ = f.check_box :remember_me
+ %span= _('Remember me')
.float-right
- if unconfirmed_email?
= link_to _('Resend confirmation email'), new_user_confirmation_path
diff --git a/app/views/devise/shared/_omniauth_box.html.haml b/app/views/devise/shared/_omniauth_box.html.haml
index 1752a43b032..bd7fe41ae8d 100644
--- a/app/views/devise/shared/_omniauth_box.html.haml
+++ b/app/views/devise/shared/_omniauth_box.html.haml
@@ -1,20 +1,20 @@
- hide_remember_me = local_assigns.fetch(:hide_remember_me, false)
.omniauth-container.gl-mt-5
- %label.label-bold.d-block
+ %label.gl-font-weight-bold
= _('Sign in with')
- providers = enabled_button_based_providers
- .d-flex.justify-content-between.flex-wrap
+ .gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- has_icon = provider_has_icon?(provider)
- = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default omniauth-btn oauth-login #{qa_class_for_provider(provider)}", form: { class: 'gl-w-full' } do
+ = button_to omniauth_authorize_path(:user, provider), id: "oauth-login-#{provider}", class: "btn gl-button btn-default gl-w-full js-oauth-login #{qa_class_for_provider(provider)}", form: { class: 'gl-w-full gl-mb-3' } do
- if has_icon
= provider_image_tag(provider)
%span.gl-button-text
= label_for_provider(provider)
- unless hide_remember_me
- %fieldset.remember-me
+ %fieldset
%label
- = check_box_tag :remember_me, nil, false, class: 'remember-me-checkbox'
+ = check_box_tag :remember_me, nil, false
%span
= _('Remember me')
diff --git a/app/views/devise/shared/_signup_omniauth_provider_list.haml b/app/views/devise/shared/_signup_omniauth_provider_list.haml
index 43e0802ee2a..c24e8770f05 100644
--- a/app/views/devise/shared/_signup_omniauth_provider_list.haml
+++ b/app/views/devise/shared/_signup_omniauth_provider_list.haml
@@ -1,9 +1,9 @@
-%label.label-bold.d-block
+%label.gl-font-weight-bold
= _("Create an account using:")
-.d-flex.justify-content-between.flex-wrap
+.gl-display-flex.gl-justify-content-between.gl-flex-wrap
- providers.each do |provider|
- = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-display-flex gl-align-items-center gl-text-left gl-mb-2 gl-p-2 omniauth-btn oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
+ = link_to omniauth_authorize_path(:user, provider), method: :post, class: "btn gl-button btn-default gl-w-full gl-mb-3 js-oauth-login #{qa_class_for_provider(provider)}", id: "oauth-login-#{provider}" do
- if provider_has_icon?(provider)
= provider_image_tag(provider)
- %span.ml-2
+ %span.gl-button-text
= label_for_provider(provider)
diff --git a/app/views/devise/shared/_signup_omniauth_providers.haml b/app/views/devise/shared/_signup_omniauth_providers.haml
index a653d44d694..30a54ab86a6 100644
--- a/app/views/devise/shared/_signup_omniauth_providers.haml
+++ b/app/views/devise/shared/_signup_omniauth_providers.haml
@@ -1,3 +1,3 @@
-.omniauth-divider.d-flex.align-items-center.text-center
+.omniauth-divider.gl-display-flex.gl-align-items-center
= _("or")
= render 'devise/shared/signup_omniauth_provider_list', providers: enabled_button_based_providers
diff --git a/app/views/devise/shared/_signup_omniauth_providers_top.haml b/app/views/devise/shared/_signup_omniauth_providers_top.haml
index 9a2629443ed..8eb22c0b023 100644
--- a/app/views/devise/shared/_signup_omniauth_providers_top.haml
+++ b/app/views/devise/shared/_signup_omniauth_providers_top.haml
@@ -1,3 +1,3 @@
= render 'devise/shared/signup_omniauth_provider_list', providers: popular_enabled_button_based_providers
-.omniauth-divider.d-flex.align-items-center.text-center
+.omniauth-divider.gl-display-flex.gl-align-items-center
= _("or")
diff --git a/app/views/layouts/_startup_js.html.haml b/app/views/layouts/_startup_js.html.haml
index 35cd191c600..b7dd3a9556c 100644
--- a/app/views/layouts/_startup_js.html.haml
+++ b/app/views/layouts/_startup_js.html.haml
@@ -17,11 +17,14 @@
});
}
if (gl.startup_graphql_calls && window.fetch) {
+ const headers = #{page_startup_graphql_headers.to_json};
const url = `#{api_graphql_url}`
const opts = {
method: "POST",
- headers: { "Content-Type": "application/json", 'X-CSRF-Token': "#{form_authenticity_token}" },
+ headers: {
+ "Content-Type": "application/json",
+ ...headers,
};
gl.startup_graphql_calls = gl.startup_graphql_calls.map(call => ({