diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /app/assets/javascripts/behaviors | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) | |
download | gitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz |
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'app/assets/javascripts/behaviors')
33 files changed, 666 insertions, 141 deletions
diff --git a/app/assets/javascripts/behaviors/autosize.js b/app/assets/javascripts/behaviors/autosize.js index a5404539c17..181d841a068 100644 --- a/app/assets/javascripts/behaviors/autosize.js +++ b/app/assets/javascripts/behaviors/autosize.js @@ -1,13 +1,11 @@ import Autosize from 'autosize'; import { waitForCSSLoaded } from '~/helpers/startup_css_helper'; -document.addEventListener('DOMContentLoaded', () => { - waitForCSSLoaded(() => { - const autosizeEls = document.querySelectorAll('.js-autosize'); +waitForCSSLoaded(() => { + const autosizeEls = document.querySelectorAll('.js-autosize'); - Autosize(autosizeEls); - Autosize.update(autosizeEls); + Autosize(autosizeEls); + Autosize.update(autosizeEls); - autosizeEls.forEach((el) => el.classList.add('js-autosize-initialized')); - }); + autosizeEls.forEach((el) => el.classList.add('js-autosize-initialized')); }); diff --git a/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js b/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js index c4af34b848b..5e474e56196 100644 --- a/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js +++ b/app/assets/javascripts/behaviors/collapse_sidebar_on_window_resize.js @@ -1,5 +1,5 @@ -import $ from 'jquery'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; +import $ from 'jquery'; /** * This behavior collapses the right sidebar diff --git a/app/assets/javascripts/behaviors/copy_to_clipboard.js b/app/assets/javascripts/behaviors/copy_to_clipboard.js index 1176fa6628d..a31bcc2cb41 100644 --- a/app/assets/javascripts/behaviors/copy_to_clipboard.js +++ b/app/assets/javascripts/behaviors/copy_to_clipboard.js @@ -1,5 +1,5 @@ -import $ from 'jquery'; import Clipboard from 'clipboard'; +import $ from 'jquery'; import { sprintf, __ } from '~/locale'; import { fixTitle, show } from '~/tooltips'; diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js index 1fa37999d62..bf7a87144f9 100644 --- a/app/assets/javascripts/behaviors/gl_emoji.js +++ b/app/assets/javascripts/behaviors/gl_emoji.js @@ -1,6 +1,12 @@ import 'document-register-element'; +import { + initEmojiMap, + getEmojiInfo, + emojiFallbackImageSrc, + emojiImageTag, + FALLBACK_EMOJI_KEY, +} from '../emoji'; import isEmojiUnicodeSupported from '../emoji/support'; -import { initEmojiMap, getEmojiInfo, emojiFallbackImageSrc, emojiImageTag } from '../emoji'; class GlEmoji extends HTMLElement { connectedCallback() { @@ -17,6 +23,10 @@ class GlEmoji extends HTMLElement { if (emojiInfo) { if (name !== emojiInfo.name) { + if (emojiInfo.name === FALLBACK_EMOJI_KEY && this.innerHTML) { + return; // When fallback emoji is used, but there is a <img> provided, use the <img> instead + } + ({ name } = emojiInfo); this.dataset.name = emojiInfo.name; } diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js index 75659bbf685..bfd025e8dab 100644 --- a/app/assets/javascripts/behaviors/index.js +++ b/app/assets/javascripts/behaviors/index.js @@ -2,17 +2,17 @@ import $ from 'jquery'; import './autosize'; import './bind_in_out'; import './markdown/render_gfm'; -import initCopyAsGFM from './markdown/copy_as_gfm'; +import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize'; import initCopyToClipboard from './copy_to_clipboard'; import installGlEmojiElement from './gl_emoji'; +import { loadStartupCSS } from './load_startup_css'; +import initCopyAsGFM from './markdown/copy_as_gfm'; import './quick_submit'; import './requires_input'; +import initSelect2Dropdowns from './select2'; import initPageShortcuts from './shortcuts'; import './toggler_behavior'; import './preview_markdown'; -import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize'; -import initSelect2Dropdowns from './select2'; -import { loadStartupCSS } from './load_startup_css'; loadStartupCSS(); @@ -25,19 +25,17 @@ initPageShortcuts(); initCollapseSidebarOnWindowResize(); initSelect2Dropdowns(); -document.addEventListener('DOMContentLoaded', () => { - window.requestIdleCallback( - () => { - // Check if we have to Load GFM Input - const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)'); - if ($gfmInputs.length) { - import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete') - .then(({ default: initGFMInput }) => { - initGFMInput($gfmInputs); - }) - .catch(() => {}); - } - }, - { timeout: 500 }, - ); -}); +window.requestIdleCallback( + () => { + // Check if we have to Load GFM Input + const $gfmInputs = $('.js-gfm-input:not(.js-gfm-input-initialized)'); + if ($gfmInputs.length) { + import(/* webpackChunkName: 'initGFMInput' */ './markdown/gfm_auto_complete') + .then(({ default: initGFMInput }) => { + initGFMInput($gfmInputs); + }) + .catch(() => {}); + } + }, + { timeout: 500 }, +); diff --git a/app/assets/javascripts/behaviors/markdown/editor_extensions.js b/app/assets/javascripts/behaviors/markdown/editor_extensions.js index 308e31e7047..b512e4dbc8b 100644 --- a/app/assets/javascripts/behaviors/markdown/editor_extensions.js +++ b/app/assets/javascripts/behaviors/markdown/editor_extensions.js @@ -1,52 +1,45 @@ -import Doc from './nodes/doc'; -import Paragraph from './nodes/paragraph'; -import Text from './nodes/text'; - +import Bold from './marks/bold'; +import Code from './marks/code'; +import InlineDiff from './marks/inline_diff'; +import InlineHTML from './marks/inline_html'; +import Italic from './marks/italic'; +import Link from './marks/link'; +import MathMark from './marks/math'; +import Strike from './marks/strike'; +import Audio from './nodes/audio'; import Blockquote from './nodes/blockquote'; +import BulletList from './nodes/bullet_list'; import CodeBlock from './nodes/code_block'; +import DescriptionDetails from './nodes/description_details'; +import DescriptionList from './nodes/description_list'; +import DescriptionTerm from './nodes/description_term'; +import Details from './nodes/details'; +import Doc from './nodes/doc'; + +import Emoji from './nodes/emoji'; import HardBreak from './nodes/hard_break'; import Heading from './nodes/heading'; import HorizontalRule from './nodes/horizontal_rule'; import Image from './nodes/image'; +import ListItem from './nodes/list_item'; +import OrderedList from './nodes/ordered_list'; +import OrderedTaskList from './nodes/ordered_task_list'; +import Paragraph from './nodes/paragraph'; +import Reference from './nodes/reference'; +import Summary from './nodes/summary'; import Table from './nodes/table'; -import TableHead from './nodes/table_head'; import TableBody from './nodes/table_body'; -import TableHeaderRow from './nodes/table_header_row'; -import TableRow from './nodes/table_row'; import TableCell from './nodes/table_cell'; - -import Emoji from './nodes/emoji'; -import Reference from './nodes/reference'; - +import TableHead from './nodes/table_head'; +import TableHeaderRow from './nodes/table_header_row'; import TableOfContents from './nodes/table_of_contents'; -import Video from './nodes/video'; -import Audio from './nodes/audio'; - -import BulletList from './nodes/bullet_list'; -import OrderedList from './nodes/ordered_list'; -import ListItem from './nodes/list_item'; - -import DescriptionList from './nodes/description_list'; -import DescriptionTerm from './nodes/description_term'; -import DescriptionDetails from './nodes/description_details'; +import TableRow from './nodes/table_row'; import TaskList from './nodes/task_list'; -import OrderedTaskList from './nodes/ordered_task_list'; import TaskListItem from './nodes/task_list_item'; - -import Summary from './nodes/summary'; -import Details from './nodes/details'; - -import Bold from './marks/bold'; -import Italic from './marks/italic'; -import Strike from './marks/strike'; -import InlineDiff from './marks/inline_diff'; - -import Link from './marks/link'; -import Code from './marks/code'; -import MathMark from './marks/math'; -import InlineHTML from './marks/inline_html'; +import Text from './nodes/text'; +import Video from './nodes/video'; // The filters referenced in lib/banzai/pipeline/gfm_pipeline.rb transform // GitLab Flavored Markdown (GFM) to HTML. diff --git a/app/assets/javascripts/behaviors/markdown/marks/bold.js b/app/assets/javascripts/behaviors/markdown/marks/bold.js index b537954c1cb..d307edd9fd3 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/bold.js +++ b/app/assets/javascripts/behaviors/markdown/marks/bold.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Bold as BaseBold } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Bold as BaseBold } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Bold extends BaseBold { diff --git a/app/assets/javascripts/behaviors/markdown/marks/code.js b/app/assets/javascripts/behaviors/markdown/marks/code.js index a760ee80dd0..ccfe2cf5b8d 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/code.js +++ b/app/assets/javascripts/behaviors/markdown/marks/code.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Code as BaseCode } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Code as BaseCode } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Code extends BaseCode { diff --git a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js index 556e6f7df1c..e957f81b774 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/inline_html.js +++ b/app/assets/javascripts/behaviors/markdown/marks/inline_html.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Mark } from 'tiptap'; import { escape } from 'lodash'; +import { Mark } from 'tiptap'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class InlineHTML extends Mark { diff --git a/app/assets/javascripts/behaviors/markdown/marks/italic.js b/app/assets/javascripts/behaviors/markdown/marks/italic.js index 44b35c97739..dbef10536ab 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/italic.js +++ b/app/assets/javascripts/behaviors/markdown/marks/italic.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Italic as BaseItalic } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Italic as BaseItalic } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Italic extends BaseItalic { diff --git a/app/assets/javascripts/behaviors/markdown/marks/link.js b/app/assets/javascripts/behaviors/markdown/marks/link.js index 5c23d6a5ceb..1111c51805d 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/link.js +++ b/app/assets/javascripts/behaviors/markdown/marks/link.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Link as BaseLink } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Link as BaseLink } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Link extends BaseLink { diff --git a/app/assets/javascripts/behaviors/markdown/marks/math.js b/app/assets/javascripts/behaviors/markdown/marks/math.js index 04441d5d710..382bf5c9b5b 100644 --- a/app/assets/javascripts/behaviors/markdown/marks/math.js +++ b/app/assets/javascripts/behaviors/markdown/marks/math.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Mark } from 'tiptap'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Mark } from 'tiptap'; import { HIGHER_PARSE_RULE_PRIORITY } from '../constants'; // Transforms generated HTML back to GFM for Banzai::Filter::MathFilter diff --git a/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js index b0bc8f79643..bd5868e5524 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/blockquote.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Blockquote as BaseBlockquote } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Blockquote as BaseBlockquote } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Blockquote extends BaseBlockquote { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js index 3b0792e1af8..209e7239998 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/bullet_list.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { BulletList as BaseBulletList } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { BulletList as BaseBulletList } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class BulletList extends BaseBulletList { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/heading.js b/app/assets/javascripts/behaviors/markdown/nodes/heading.js index fec8608cf5d..708da053a2f 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/heading.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/heading.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Heading as BaseHeading } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Heading as BaseHeading } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Heading extends BaseHeading { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js index 695c7160bde..47a24eae1e8 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/horizontal_rule.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { HorizontalRule as BaseHorizontalRule } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class HorizontalRule extends BaseHorizontalRule { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/image.js b/app/assets/javascripts/behaviors/markdown/nodes/image.js index 76746528e72..ade5839d10b 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/image.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/image.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Image as BaseImage } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Image as BaseImage } from 'tiptap-extensions'; import { placeholderImage } from '~/lazy_loader'; import { HIGHER_PARSE_RULE_PRIORITY } from '../constants'; diff --git a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js index 4237637ed9a..0f56e89dca6 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/list_item.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/list_item.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { ListItem as BaseListItem } from 'tiptap-extensions'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { ListItem as BaseListItem } from 'tiptap-extensions'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class ListItem extends BaseListItem { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js index dec3207b1bb..93d00f27868 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/paragraph.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Node } from 'tiptap'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Node } from 'tiptap'; // Transforms generated HTML back to GFM for Banzai::Filter::MarkdownFilter export default class Paragraph extends Node { diff --git a/app/assets/javascripts/behaviors/markdown/nodes/playable.js b/app/assets/javascripts/behaviors/markdown/nodes/playable.js index 9cbd95a7bd8..33bb6e0c31c 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/playable.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/playable.js @@ -1,8 +1,8 @@ /* eslint-disable class-methods-use-this */ /* eslint-disable @gitlab/require-i18n-strings */ -import { Node } from 'tiptap'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Node } from 'tiptap'; import { HIGHER_PARSE_RULE_PRIORITY } from '../constants'; /** diff --git a/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js index 6e3c16f0a08..2cb2bb9e7fe 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/table_header_row.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import TableRow from './table_row'; import { HIGHER_PARSE_RULE_PRIORITY } from '../constants'; +import TableRow from './table_row'; const CENTER_ALIGN = 'center'; diff --git a/app/assets/javascripts/behaviors/markdown/nodes/text.js b/app/assets/javascripts/behaviors/markdown/nodes/text.js index 84838c14999..4eab10c9d98 100644 --- a/app/assets/javascripts/behaviors/markdown/nodes/text.js +++ b/app/assets/javascripts/behaviors/markdown/nodes/text.js @@ -1,7 +1,7 @@ /* eslint-disable class-methods-use-this */ -import { Node } from 'tiptap'; import { defaultMarkdownSerializer } from 'prosemirror-markdown'; +import { Node } from 'tiptap'; export default class Text extends Node { get name() { diff --git a/app/assets/javascripts/behaviors/markdown/render_gfm.js b/app/assets/javascripts/behaviors/markdown/render_gfm.js index 5e9d80e1529..7934eac2f7e 100644 --- a/app/assets/javascripts/behaviors/markdown/render_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/render_gfm.js @@ -1,10 +1,10 @@ import $ from 'jquery'; import syntaxHighlight from '~/syntax_highlight'; +import initUserPopovers from '../../user_popovers'; +import highlightCurrentUser from './highlight_current_user'; import renderMath from './render_math'; import renderMermaid from './render_mermaid'; import renderMetrics from './render_metrics'; -import highlightCurrentUser from './highlight_current_user'; -import initUserPopovers from '../../user_popovers'; // Render GitLab flavoured Markdown // diff --git a/app/assets/javascripts/behaviors/markdown/render_math.js b/app/assets/javascripts/behaviors/markdown/render_math.js index f34fec4d449..5479866c99a 100644 --- a/app/assets/javascripts/behaviors/markdown/render_math.js +++ b/app/assets/javascripts/behaviors/markdown/render_math.js @@ -1,6 +1,6 @@ import { deprecatedCreateFlash as flash } from '~/flash'; -import { s__, sprintf } from '~/locale'; import { differenceInMilliseconds } from '~/lib/utils/datetime_utility'; +import { s__, sprintf } from '~/locale'; // Renders math using KaTeX in any element with the // `js-render-math` class diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js index 479782a1f1f..0cb13815c7e 100644 --- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js @@ -140,7 +140,7 @@ function renderMermaids($els) { 'Warning: Displaying this diagram might cause performance issues on this page.', )}</div> <div class="gl-alert-actions"> - <button class="js-lazy-render-mermaid btn gl-alert-action btn-warning btn-md new-gl-button">Display</button> + <button class="js-lazy-render-mermaid btn gl-alert-action btn-warning btn-md gl-button">Display</button> </div> </div> <button type="button" class="close" data-dismiss="alert" aria-label="Close"> diff --git a/app/assets/javascripts/behaviors/preview_markdown.js b/app/assets/javascripts/behaviors/preview_markdown.js index def1c567cd5..5405819cfe0 100644 --- a/app/assets/javascripts/behaviors/preview_markdown.js +++ b/app/assets/javascripts/behaviors/preview_markdown.js @@ -1,8 +1,8 @@ /* eslint-disable func-names */ import $ from 'jquery'; -import axios from '~/lib/utils/axios_utils'; import { deprecatedCreateFlash as flash } from '~/flash'; +import axios from '~/lib/utils/axios_utils'; import { __ } from '~/locale'; // MarkdownPreview diff --git a/app/assets/javascripts/behaviors/quick_submit.js b/app/assets/javascripts/behaviors/quick_submit.js index 68e831252d6..12a2baed6e2 100644 --- a/app/assets/javascripts/behaviors/quick_submit.js +++ b/app/assets/javascripts/behaviors/quick_submit.js @@ -1,8 +1,8 @@ import $ from 'jquery'; import '../commons/bootstrap'; -import { isInIssuePage } from '../lib/utils/common_utils'; import { __ } from '~/locale'; import { add, show, hide } from '~/tooltips'; +import { isInIssuePage } from '../lib/utils/common_utils'; // Quick Submit behavior // diff --git a/app/assets/javascripts/behaviors/secret_values.js b/app/assets/javascripts/behaviors/secret_values.js index 2f1951c97f9..a34d5dcaef8 100644 --- a/app/assets/javascripts/behaviors/secret_values.js +++ b/app/assets/javascripts/behaviors/secret_values.js @@ -1,5 +1,5 @@ -import { n__ } from '../locale'; import { parseBoolean } from '../lib/utils/common_utils'; +import { n__ } from '../locale'; export default class SecretValues { constructor({ diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js index 10832583783..0513e807ed6 100644 --- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -1,6 +1,6 @@ import { flatten } from 'lodash'; -import { s__ } from '~/locale'; import AccessorUtilities from '~/lib/utils/accessor'; +import { s__ } from '~/locale'; import { shouldDisableShortcuts } from './shortcuts_toggle'; export const LOCAL_STORAGE_KEY = 'gl-keyboard-shortcuts-customizations'; @@ -29,6 +29,7 @@ export const customizations = parsedCustomizations; // All available commands export const TOGGLE_PERFORMANCE_BAR = 'globalShortcuts.togglePerformanceBar'; +export const TOGGLE_CANARY = 'globalShortcuts.toggleCanary'; /** All keybindings, grouped and ordered with descriptions */ export const keybindingGroups = [ @@ -42,6 +43,12 @@ export const keybindingGroups = [ // eslint-disable-next-line @gitlab/require-i18n-strings defaultKeys: ['p b'], }, + { + description: s__('KeyboardShortcuts|Toggle GitLab Next'), + command: TOGGLE_CANARY, + // eslint-disable-next-line @gitlab/require-i18n-strings + defaultKeys: ['g x'], + }, ], }, ] diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js index 50d2399b312..e4ec68601e0 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js @@ -1,15 +1,14 @@ import $ from 'jquery'; import Cookies from 'js-cookie'; +import { flatten } from 'lodash'; import Mousetrap from 'mousetrap'; import Vue from 'vue'; -import { flatten } from 'lodash'; +import { parseBoolean } from '~/lib/utils/common_utils'; +import findAndFollowLink from '~/lib/utils/navigation_utility'; +import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility'; + +import { keysFor, TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY } from './keybindings'; import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle'; -import ShortcutsToggle from './shortcuts_toggle.vue'; -import axios from '../../lib/utils/axios_utils'; -import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility'; -import findAndFollowLink from '../../lib/utils/navigation_utility'; -import { parseBoolean, getCspNonceValue } from '~/lib/utils/common_utils'; -import { keysFor, TOGGLE_PERFORMANCE_BAR } from './keybindings'; const defaultStopCallback = Mousetrap.prototype.stopCallback; Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) { @@ -20,15 +19,6 @@ Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo return defaultStopCallback.call(this, e, element, combo); }; -function initToggleButton() { - return new Vue({ - el: document.querySelector('.js-toggle-shortcuts'), - render(createElement) { - return createElement(ShortcutsToggle); - }, - }); -} - /** * The key used to save and fetch the local Mousetrap instance * attached to a `<textarea>` element using `jQuery.data` @@ -65,13 +55,15 @@ function getToolbarBtnToShortcutsMap($textarea) { export default class Shortcuts { constructor() { this.onToggleHelp = this.onToggleHelp.bind(this); - this.enabledHelp = []; + this.helpModalElement = null; + this.helpModalVueInstance = null; Mousetrap.bind('?', this.onToggleHelp); Mousetrap.bind('s', Shortcuts.focusSearch); Mousetrap.bind('/', Shortcuts.focusSearch); Mousetrap.bind('f', this.focusFilter.bind(this)); Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar); + Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary); const findFileURL = document.body.dataset.findFile; @@ -106,11 +98,33 @@ export default class Shortcuts { } onToggleHelp(e) { - if (e.preventDefault) { + if (e?.preventDefault) { e.preventDefault(); } - Shortcuts.toggleHelp(this.enabledHelp); + if (this.helpModalElement && this.helpModalVueInstance) { + this.helpModalVueInstance.$destroy(); + this.helpModalElement.remove(); + this.helpModalElement = null; + this.helpModalVueInstance = null; + } else { + this.helpModalElement = document.createElement('div'); + document.body.append(this.helpModalElement); + + this.helpModalVueInstance = new Vue({ + el: this.helpModalElement, + components: { + ShortcutsHelp: () => import('./shortcuts_help.vue'), + }, + render: (createElement) => { + return createElement('shortcuts-help', { + on: { + hidden: this.onToggleHelp, + }, + }); + }, + }); + } } static onTogglePerfBar(e) { @@ -124,6 +138,14 @@ export default class Shortcuts { refreshCurrentPage(); } + static onToggleCanary(e) { + e.preventDefault(); + const canaryCookieName = 'gitlab_canary'; + const currentValue = parseBoolean(Cookies.get(canaryCookieName)); + Cookies.set(canaryCookieName, (!currentValue).toString(), { expires: 365, path: '/' }); + refreshCurrentPage(); + } + static toggleMarkdownPreview(e) { // Check if short-cut was triggered while in Write Mode const $target = $(e.target); @@ -135,34 +157,6 @@ export default class Shortcuts { $(document).triggerHandler('markdown-preview:toggle', [e]); } - static toggleHelp(location) { - const $modal = $('#modal-shortcuts'); - - if ($modal.length) { - $modal.modal('toggle'); - return null; - } - - return axios - .get(gon.shortcuts_path, { - responseType: 'text', - }) - .then(({ data }) => { - $.globalEval(data, { nonce: getCspNonceValue() }); - - if (location && location.length > 0) { - const results = []; - for (let i = 0, len = location.length; i < len; i += 1) { - results.push($(location[i]).show()); - } - return results; - } - - return $('.js-more-help-button').remove(); - }) - .then(initToggleButton); - } - focusFilter(e) { if (!this.filterInput) { this.filterInput = $('input[type=search]', '.nav-controls'); diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue new file mode 100644 index 00000000000..1277dd0ed37 --- /dev/null +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue @@ -0,0 +1,525 @@ +<script> +/* eslint-disable @gitlab/vue-require-i18n-strings */ +import { GlIcon, GlModal } from '@gitlab/ui'; +import ShortcutsToggle from './shortcuts_toggle.vue'; + +export default { + components: { + GlIcon, + GlModal, + ShortcutsToggle, + }, + computed: { + ctrlCharacter() { + return window.gl.client.isMac ? '⌘' : 'ctrl'; + }, + onDotCom() { + return window.gon.dot_com; + }, + }, +}; +</script> +<template> + <gl-modal + modal-id="keyboard-shortcut-modal" + size="lg" + data-testid="modal-shortcuts" + :visible="true" + :hide-footer="true" + @hidden="$emit('hidden')" + > + <template #modal-title> + <shortcuts-toggle /> + </template> + <div class="row"> + <div class="col-lg-4"> + <table class="shortcut-mappings text-2"> + <tbody> + <tr> + <th></th> + <th>{{ __('Global Shortcuts') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>?</kbd> + </td> + <td>{{ __('Toggle this dialog') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift p</kbd> + </td> + <td>{{ __('Go to your projects') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift g</kbd> + </td> + <td>{{ __('Go to your groups') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift a</kbd> + </td> + <td>{{ __('Go to the activity feed') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift l</kbd> + </td> + <td>{{ __('Go to the milestone list') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift s</kbd> + </td> + <td>{{ __('Go to your snippets') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>s</kbd> + / + <kbd>/</kbd> + </td> + <td>{{ __('Start search') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift i</kbd> + </td> + <td>{{ __('Go to your issues') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift m</kbd> + </td> + <td>{{ __('Go to your merge requests') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>shift t</kbd> + </td> + <td>{{ __('Go to your To-Do list') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>p</kbd> + <kbd>b</kbd> + </td> + <td>{{ __('Toggle the Performance Bar') }}</td> + </tr> + <tr v-if="onDotCom"> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>x</kbd> + </td> + <td>{{ __('Toggle GitLab Next') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Editing') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>{{ ctrlCharacter }} shift p</kbd> + </td> + <td>{{ __('Toggle Markdown preview') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-up" /> + </kbd> + </td> + <td> + {{ __('Edit your most recent comment in a thread (from an empty textarea)') }} + </td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Wiki') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>e</kbd> + </td> + <td>{{ __('Edit wiki page') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Repository Graph') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-left" /> + </kbd> + / + <kbd>h</kbd> + </td> + <td>{{ __('Scroll left') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-right" /> + </kbd> + / + <kbd>l</kbd> + </td> + <td>{{ __('Scroll right') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-up" /> + </kbd> + / + <kbd>k</kbd> + </td> + <td>{{ __('Scroll up') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-down" /> + </kbd> + / + <kbd>j</kbd> + </td> + <td>{{ __('Scroll down') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + shift + <gl-icon name="arrow-up" /> + / k + </kbd> + </td> + <td>{{ __('Scroll to top') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + shift + <gl-icon name="arrow-down" /> + / j + </kbd> + </td> + <td>{{ __('Scroll to bottom') }}</td> + </tr> + </tbody> + </table> + </div> + <div class="col-lg-4"> + <table class="shortcut-mappings text-2"> + <tbody> + <tr> + <th></th> + <th>{{ __('Project') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>p</kbd> + </td> + <td>{{ __("Go to the project's overview page") }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>v</kbd> + </td> + <td>{{ __("Go to the project's activity feed") }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>r</kbd> + </td> + <td>{{ __('Go to releases') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>f</kbd> + </td> + <td>{{ __('Go to files') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>t</kbd> + </td> + <td>{{ __('Go to find file') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>c</kbd> + </td> + <td>{{ __('Go to commits') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>n</kbd> + </td> + <td>{{ __('Go to repository graph') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>d</kbd> + </td> + <td>{{ __('Go to repository charts') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>i</kbd> + </td> + <td>{{ __('Go to issues') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>i</kbd> + </td> + <td>{{ __('New issue') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>b</kbd> + </td> + <td>{{ __('Go to issue boards') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>m</kbd> + </td> + <td>{{ __('Go to merge requests') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>j</kbd> + </td> + <td>{{ __('Go to jobs') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>l</kbd> + </td> + <td>{{ __('Go to metrics') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>e</kbd> + </td> + <td>{{ __('Go to environments') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>k</kbd> + </td> + <td>{{ __('Go to kubernetes') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>s</kbd> + </td> + <td>{{ __('Go to snippets') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>g</kbd> + <kbd>w</kbd> + </td> + <td>{{ __('Go to wiki') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Project Files') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-up" /> + </kbd> + </td> + <td>{{ __('Move selection up') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd> + <gl-icon name="arrow-down" /> + </kbd> + </td> + <td>{{ __('Move selection down') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>enter</kbd> + </td> + <td>{{ __('Open Selection') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>esc</kbd> + </td> + <td>{{ __('Go back (while searching for files)') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>y</kbd> + </td> + <td>{{ __('Go to file permalink (while viewing a file)') }}</td> + </tr> + </tbody> + </table> + </div> + <div class="col-lg-4"> + <table class="shortcut-mappings text-2"> + <tbody> + <tr> + <th></th> + <th>{{ __('Epics, Issues, and Merge Requests') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>r</kbd> + </td> + <td>{{ __('Comment/Reply (quoting selected text)') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>e</kbd> + </td> + <td>{{ __('Edit description') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>l</kbd> + </td> + <td>{{ __('Change label') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Issues and Merge Requests') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>a</kbd> + </td> + <td>{{ __('Change assignee') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>m</kbd> + </td> + <td>{{ __('Change milestone') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Merge Requests') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>]</kbd> + / + <kbd>j</kbd> + </td> + <td>{{ __('Next file in diff') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>[</kbd> + / + <kbd>k</kbd> + </td> + <td>{{ __('Previous file in diff') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>{{ ctrlCharacter }} p</kbd> + </td> + <td>{{ __('Go to file') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>n</kbd> + </td> + <td>{{ __('Next unresolved discussion') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>p</kbd> + </td> + <td>{{ __('Previous unresolved discussion') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>b</kbd> + </td> + <td>{{ __('Copy source branch name') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Merge Request Commits') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>c</kbd> + </td> + <td>{{ __('Next commit') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>x</kbd> + </td> + <td>{{ __('Previous commit') }}</td> + </tr> + </tbody> + <tbody> + <tr> + <th></th> + <th>{{ __('Web IDE') }}</th> + </tr> + <tr> + <td class="shortcut"> + <kbd>{{ ctrlCharacter }} p</kbd> + </td> + <td>{{ __('Go to file') }}</td> + </tr> + <tr> + <td class="shortcut"> + <kbd>{{ ctrlCharacter }} enter</kbd> + </td> + <td>{{ __('Commit (when editing commit message)') }}</td> + </tr> + </tbody> + </table> + </div> + </div> + </gl-modal> +</template> diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js index 5e8ddeb6af7..476745beb19 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js @@ -1,11 +1,11 @@ import $ from 'jquery'; import Mousetrap from 'mousetrap'; -import Sidebar from '../../right_sidebar'; -import Shortcuts from './shortcuts'; -import { CopyAsGFM } from '../markdown/copy_as_gfm'; +import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard'; import { getSelectedFragment } from '~/lib/utils/common_utils'; import { isElementVisible } from '~/lib/utils/dom_utils'; -import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard'; +import Sidebar from '../../right_sidebar'; +import { CopyAsGFM } from '../markdown/copy_as_gfm'; +import Shortcuts from './shortcuts'; export default class ShortcutsIssuable extends Shortcuts { constructor() { diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js index 8b7e6a56d25..c609936a02a 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js @@ -1,6 +1,6 @@ import Mousetrap from 'mousetrap'; -import ShortcutsNavigation from './shortcuts_navigation'; import findAndFollowLink from '../../lib/utils/navigation_utility'; +import ShortcutsNavigation from './shortcuts_navigation'; export default class ShortcutsWiki extends ShortcutsNavigation { constructor() { |