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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-16 09:12:24 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-16 09:12:24 +0300
commit885897989971931fcb139969b49d8b06f907d7d0 (patch)
tree7c2873a6690b73d0036b56bf379634c235dfb438 /app/assets/javascripts/lib
parentf5c9eb81b000010cf8abc91cbcfd1d6537f66c64 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/lib')
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue34
-rw-r--r--app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js8
-rw-r--r--app/assets/javascripts/lib/utils/text_markdown.js65
3 files changed, 97 insertions, 10 deletions
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
index 733d0f69f5d..f3380b7b4ba 100644
--- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_modal.vue
@@ -1,13 +1,21 @@
<script>
-import { GlModal } from '@gitlab/ui';
+import { GlModal, GlSafeHtmlDirective } from '@gitlab/ui';
import { __ } from '~/locale';
export default {
cancelAction: { text: __('Cancel') },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
components: {
GlModal,
},
props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
primaryText: {
type: String,
required: false,
@@ -18,11 +26,27 @@ export default {
required: false,
default: 'confirm',
},
+ modalHtmlMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ hideCancel: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
primaryAction() {
return { text: this.primaryText, attributes: { variant: this.primaryVariant } };
},
+ cancelAction() {
+ return this.hideCancel ? null : this.$options.cancelAction;
+ },
+ shouldShowHeader() {
+ return Boolean(this.title?.length);
+ },
},
mounted() {
this.$refs.modal.show();
@@ -36,12 +60,14 @@ export default {
size="sm"
modal-id="confirmationModal"
body-class="gl-display-flex"
+ :title="title"
:action-primary="primaryAction"
- :action-cancel="$options.cancelAction"
- hide-header
+ :action-cancel="cancelAction"
+ :hide-header="!shouldShowHeader"
@primary="$emit('confirmed')"
@hidden="$emit('closed')"
>
- <div class="gl-align-self-center"><slot></slot></div>
+ <div v-if="!modalHtmlMessage" class="gl-align-self-center"><slot></slot></div>
+ <div v-else v-safe-html="modalHtmlMessage" class="gl-align-self-center"></div>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
index fdd0e045d07..a8a89d0644a 100644
--- a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
+++ b/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js
@@ -1,6 +1,9 @@
import Vue from 'vue';
-export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {}) {
+export function confirmAction(
+ message,
+ { primaryBtnVariant, primaryBtnText, modalHtmlMessage, title, hideCancel } = {},
+) {
return new Promise((resolve) => {
let confirmed = false;
@@ -15,6 +18,9 @@ export function confirmAction(message, { primaryBtnVariant, primaryBtnText } = {
props: {
primaryVariant: primaryBtnVariant,
primaryText: primaryBtnText,
+ title,
+ modalHtmlMessage,
+ hideCancel,
},
on: {
confirmed() {
diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js
index 40dd29bea76..ec6789d81ec 100644
--- a/app/assets/javascripts/lib/utils/text_markdown.js
+++ b/app/assets/javascripts/lib/utils/text_markdown.js
@@ -5,6 +5,12 @@ import { insertText } from '~/lib/utils/common_utils';
const LINK_TAG_PATTERN = '[{text}](url)';
+// at the start of a line, find any amount of whitespace followed by
+// a bullet point character (*+-) and an optional checkbox ([ ] [x])
+// OR a number with a . after it and an optional checkbox ([ ] [x])
+// followed by one or more whitespace characters
+const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isOl>[*+-])|(?<isUl>\d+\.))( \[([x ])\])?\s)(?<content>.)?/;
+
function selectedText(text, textarea) {
return text.substring(textarea.selectionStart, textarea.selectionEnd);
}
@@ -13,8 +19,15 @@ function addBlockTags(blockTag, selected) {
return `${blockTag}\n${selected}\n${blockTag}`;
}
-function lineBefore(text, textarea) {
- const split = text.substring(0, textarea.selectionStart).trim().split('\n');
+function lineBefore(text, textarea, trimNewlines = true) {
+ let split = text.substring(0, textarea.selectionStart);
+
+ if (trimNewlines) {
+ split = split.trim();
+ }
+
+ split = split.split('\n');
+
return split[split.length - 1];
}
@@ -284,9 +297,9 @@ function updateText({ textArea, tag, cursorOffset, blockTag, wrap, select, tagCo
}
/* eslint-disable @gitlab/require-i18n-strings */
-export function keypressNoteText(e) {
+function handleSurroundSelectedText(e, textArea) {
if (!gon.markdown_surround_selection) return;
- if (this.selectionStart === this.selectionEnd) return;
+ if (textArea.selectionStart === textArea.selectionEnd) return;
const keys = {
'*': '**{text}**', // wraps with bold character
@@ -306,7 +319,7 @@ export function keypressNoteText(e) {
updateText({
tag,
- textArea: this,
+ textArea,
blockTag: '',
wrap: true,
select: '',
@@ -316,6 +329,48 @@ export function keypressNoteText(e) {
}
/* eslint-enable @gitlab/require-i18n-strings */
+function handleContinueList(e, textArea) {
+ if (!gon.features?.markdownContinueLists) return;
+ if (!(e.key === 'Enter')) return;
+ if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
+ if (textArea.selectionStart !== textArea.selectionEnd) return;
+
+ const currentLine = lineBefore(textArea.value, textArea, false);
+ const result = currentLine.match(LIST_LINE_HEAD_PATTERN);
+
+ if (result) {
+ const { indent, content, leader } = result.groups;
+ const prevLineEmpty = !content;
+
+ if (prevLineEmpty) {
+ // erase previous empty list item - select the text and allow the
+ // natural line feed erase the text
+ textArea.selectionStart = textArea.selectionStart - result[0].length;
+ return;
+ }
+
+ const itemInsert = `${indent}${leader}`;
+
+ e.preventDefault();
+
+ updateText({
+ tag: itemInsert,
+ textArea,
+ blockTag: '',
+ wrap: false,
+ select: '',
+ tagContent: '',
+ });
+ }
+}
+
+export function keypressNoteText(e) {
+ const textArea = this;
+
+ handleContinueList(e, textArea);
+ handleSurroundSelectedText(e, textArea);
+}
+
export function updateTextForToolbarBtn($toolbarBtn) {
return updateText({
textArea: $toolbarBtn.closest('.md-area').find('textarea'),