Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-06-29 00:23:49 +00:00
parent 9fb28832b8
commit 87ea12cef8
190 changed files with 1553 additions and 1715 deletions

View File

@ -38,12 +38,8 @@ export default function initAddContextCommitsTriggers() {
el: addContextCommitsModalWrapperEl,
store,
data() {
const {
contextCommitsPath,
targetBranch,
mergeRequestIid,
projectId,
} = this.$options.el.dataset;
const { contextCommitsPath, targetBranch, mergeRequestIid, projectId } =
this.$options.el.dataset;
return {
contextCommitsPath,
targetBranch,

View File

@ -3,14 +3,8 @@ import BroadcastMessagesBase from './components/base.vue';
export default () => {
const el = document.querySelector('#js-broadcast-messages');
const {
page,
targetAccessLevelOptions,
messagesPath,
previewPath,
messagesCount,
messages,
} = el.dataset;
const { page, targetAccessLevelOptions, messagesPath, previewPath, messagesCount, messages } =
el.dataset;
return new Vue({
el,

View File

@ -38,7 +38,8 @@ export default {
i18n: {
title: s__('AdminUsers|Delete User %{username}?'),
primaryButtonLabel: s__('AdminUsers|Delete user'),
messageBody: s__(`AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests,
messageBody:
s__(`AdminUsers|You are about to permanently delete the user %{username}. Issues, merge requests,
and groups linked to them will be transferred to a system-wide "Ghost-user". To avoid data loss,
consider using the %{strongStart}block user%{strongEnd} feature instead. Once you %{strongStart}Delete user%{strongEnd},
it cannot be undone or recovered.`),

View File

@ -59,7 +59,8 @@ export default {
i18n: {
title: s__('AdminUsers|Delete User %{username} and contributions?'),
primaryButtonLabel: s__('AdminUsers|Delete user and contributions'),
messageBody: s__(`AdminUsers|You are about to permanently delete the user %{username}. This will delete all issues,
messageBody:
s__(`AdminUsers|You are about to permanently delete the user %{username}. This will delete all issues,
merge requests, groups, and projects linked to them. To avoid data loss,
consider using the %{strongStart}Block user%{strongEnd} feature instead. After you %{strongStart}Delete user%{strongEnd},
you cannot undo this action or recover the data.`),

View File

@ -186,8 +186,13 @@ export default {
);
},
isFormDirty() {
const { type, active, name, payloadAlertFields = [], payloadAttributeMappings = [] } =
this.currentIntegration || {};
const {
type,
active,
name,
payloadAlertFields = [],
payloadAttributeMappings = [],
} = this.currentIntegration || {};
const { name: formName, active: formActive, type: formType } = this.integrationForm;
const isDirty =

View File

@ -15,9 +15,8 @@ const deleteIntegrationFromStore = (store, query, { httpIntegrationDestroy }, va
});
const data = produce(sourceData, (draftData) => {
draftData.project.alertManagementIntegrations.nodes = draftData.project.alertManagementIntegrations.nodes.filter(
({ id }) => id !== integration.id,
);
draftData.project.alertManagementIntegrations.nodes =
draftData.project.alertManagementIntegrations.nodes.filter(({ id }) => id !== integration.id);
});
store.writeQuery({

View File

@ -18,12 +18,8 @@ export default () => {
const initialData = buildCycleAnalyticsInitialData({ ...el.dataset, gon });
const pagination = extractPaginationQueryParameters(window.location.search);
const {
selectedAuthor,
selectedMilestone,
selectedAssigneeList,
selectedLabelList,
} = extractFilterQueryParameters(window.location.search);
const { selectedAuthor, selectedMilestone, selectedAssigneeList, selectedLabelList } =
extractFilterQueryParameters(window.location.search);
store.dispatch('initializeVsa', {
...initialData,

View File

@ -10,15 +10,8 @@ export const initPasswordInput = () => {
const { form } = el;
const {
title,
id,
minimumPasswordLength,
testid,
trackActionForErrors,
autocomplete,
name,
} = el.dataset;
const { title, id, minimumPasswordLength, testid, trackActionForErrors, autocomplete, name } =
el.dataset;
// eslint-disable-next-line no-new
new Vue({

View File

@ -65,16 +65,18 @@ export const shouldRenderDraftRowInDiscussion = (state, getters) => (discussionI
export const draftForDiscussion = (state, getters) => (discussionId) =>
getters.draftsPerDiscussionId[discussionId] || {};
export const draftsForLine = (state, getters) => (diffFileSha, line, side = null) => {
const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha];
const key = side !== null ? parallelLineKey(line, side) : line.line_code;
const showDraftsForThisSide = showDraftOnSide(line, side);
export const draftsForLine =
(state, getters) =>
(diffFileSha, line, side = null) => {
const draftsForFile = getters.draftsPerFileHashAndLine[diffFileSha];
const key = side !== null ? parallelLineKey(line, side) : line.line_code;
const showDraftsForThisSide = showDraftOnSide(line, side);
if (showDraftsForThisSide && draftsForFile?.[key]) {
return draftsForFile[key].filter((d) => d.position.position_type === 'text');
}
return [];
};
if (showDraftsForThisSide && draftsForFile?.[key]) {
return draftsForFile[key].filter((d) => d.position.position_type === 'text');
}
return [];
};
export const draftsForFile = (state) => (diffFileSha) =>
state.drafts.filter((draft) => draft.file_hash === diffFileSha);

View File

@ -4,8 +4,8 @@ import { __ } from '~/locale';
import { createAlert } from '~/alert';
// Async import component since we might not need it...
const JSONTable = memoize(() =>
import(/* webpackChunkName: 'gfm_json_table' */ '../components/json_table.vue'),
const JSONTable = memoize(
() => import(/* webpackChunkName: 'gfm_json_table' */ '../components/json_table.vue'),
);
const mountParseError = (element) => {

View File

@ -648,7 +648,8 @@ export default {
:data-board="list.id"
:data-board-type="list.listType"
:class="{
'gl-bg-red-50 gl-rounded-bottom-left-base gl-rounded-bottom-right-base': boardItemsSizeExceedsMax,
'gl-bg-red-50 gl-rounded-bottom-left-base gl-rounded-bottom-right-base':
boardItemsSizeExceedsMax,
'gl-overflow-hidden': disableScrollingWhenMutationInProgress,
'gl-overflow-y-auto': !disableScrollingWhenMutationInProgress,
}"

View File

@ -330,7 +330,8 @@ export default {
:class="{
'gl-h-full': list.collapsed,
'gl-bg-gray-50': isSwimlanesHeader,
'gl-border-t-solid gl-border-4 gl-rounded-top-left-base gl-rounded-top-right-base': isLabelList,
'gl-border-t-solid gl-border-4 gl-rounded-top-left-base gl-rounded-top-right-base':
isLabelList,
'gl-bg-red-50 gl-rounded-top-left-base gl-rounded-top-right-base': boardItemsSizeExceedsMax,
}"
:style="headerStyle"

View File

@ -25,13 +25,8 @@ export default (containerId = 'js-jobs-table') => {
return false;
}
const {
fullPath,
jobStatuses,
pipelineEditorPath,
emptyStateSvgPath,
admin,
} = containerEl.dataset;
const { fullPath, jobStatuses, pipelineEditorPath, emptyStateSvgPath, admin } =
containerEl.dataset;
return new Vue({
el: containerEl,

View File

@ -216,14 +216,8 @@ export default {
},
drawGraph({ maxNodesPerLayer, linksAndNodes }) {
const {
baseWidth,
baseHeight,
minNodeHeight,
nodeWidth,
nodePadding,
paddingForLabels,
} = this.$options.viewOptions;
const { baseWidth, baseHeight, minNodeHeight, nodeWidth, nodePadding, paddingForLabels } =
this.$options.viewOptions;
this.width = baseWidth;
this.height = baseHeight + maxNodesPerLayer * minNodeHeight;

View File

@ -180,7 +180,8 @@ export default {
ref="mainPipelineContainer"
class="pipeline-graph gl-display-flex gl-position-relative gl-whitespace-nowrap gl-rounded-lg"
:class="{
'pipeline-graph-container gl-bg-gray-10 gl-pipeline-min-h gl-align-items-flex-start gl-pt-3 gl-pb-8 gl-mt-3 gl-overflow-auto': !isLinkedPipeline,
'pipeline-graph-container gl-bg-gray-10 gl-pipeline-min-h gl-align-items-flex-start gl-pt-3 gl-pb-8 gl-mt-3 gl-overflow-auto':
!isLinkedPipeline,
'gl-bg-gray-50 gl-sm-ml-5': isLinkedPipeline,
}"
data-testid="pipeline-container"

View File

@ -65,8 +65,14 @@ export default {
};
},
update(data) {
const { id, iid, commit = {}, detailedStatus = {}, stages, status } =
data.project?.pipeline || {};
const {
id,
iid,
commit = {},
detailedStatus = {},
stages,
status,
} = data.project?.pipeline || {};
return {
id,

View File

@ -172,7 +172,8 @@ export default {
:class="[
cssClassJobName,
{
'gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none': hasDetails,
'gl-text-gray-900 gl-active-text-decoration-none gl-focus-text-decoration-none gl-hover-text-decoration-none':
hasDetails,
'js-job-component-tooltip non-details-job-component': !hasDetails,
},
]"

View File

@ -3,11 +3,13 @@ import ReportItem from '~/ci/reports/components/report_item.vue';
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/ci/reports/constants';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
const wrapIssueWithState = (status, isNew = false) => (issue) => ({
status: issue.status || status,
isNew,
issue,
});
const wrapIssueWithState =
(status, isNew = false) =>
(issue) => ({
status: issue.status || status,
isNew,
issue,
});
/**
* Renders block of issues

View File

@ -33,12 +33,8 @@ export const initAdminRunners = (selector = '#js-admin-runners') => {
return null;
}
const {
newRunnerPath,
allowRegistrationToken,
registrationToken,
tagSuggestionsPath,
} = el.dataset;
const { newRunnerPath, allowRegistrationToken, registrationToken, tagSuggestionsPath } =
el.dataset;
const { cacheConfig, typeDefs, localMutations } = createLocalState();
const apolloProvider = new VueApollo({

View File

@ -109,8 +109,9 @@ export const platformArchitectures = ({ platform }) => {
};
export const installScript = ({ platform, architecture }) => {
const downloadLocation = DOWNLOAD_LOCATIONS[platform].find(({ arch }) => arch === architecture)
.url;
const downloadLocation = DOWNLOAD_LOCATIONS[platform].find(
({ arch }) => arch === architecture,
).url;
return importInstallScript({ platform })
.replace(

View File

@ -19,13 +19,8 @@ export const initGroupRunners = (selector = '#js-group-runners') => {
return null;
}
const {
allowRegistrationToken,
registrationToken,
newRunnerPath,
groupId,
groupFullPath,
} = el.dataset;
const { allowRegistrationToken, registrationToken, newRunnerPath, groupId, groupFullPath } =
el.dataset;
const { cacheConfig, typeDefs, localMutations } = createLocalState();

View File

@ -31,9 +31,8 @@ export function removeTokenFromStore(store, revokeToken, query, variables) {
});
const data = produce(sourceData, (draftData) => {
draftData.project.clusterAgent.tokens.nodes = draftData.project.clusterAgent.tokens.nodes.filter(
({ id }) => id !== revokeToken.id,
);
draftData.project.clusterAgent.tokens.nodes =
draftData.project.clusterAgent.tokens.nodes.filter(({ id }) => id !== revokeToken.id);
draftData.project.clusterAgent.tokens.count -= 1;
});

View File

@ -44,12 +44,14 @@ export function removeAgentFromStore(store, deleteClusterAgent, query, variables
draftData.project.clusterAgents.nodes = draftData.project.clusterAgents.nodes.filter(
({ id }) => id !== deleteClusterAgent.id,
);
draftData.project.ciAccessAuthorizedAgents.nodes = draftData.project.ciAccessAuthorizedAgents.nodes.filter(
({ agent }) => agent.id !== deleteClusterAgent.id,
);
draftData.project.userAccessAuthorizedAgents.nodes = draftData.project.userAccessAuthorizedAgents.nodes.filter(
({ agent }) => agent.id !== deleteClusterAgent.id,
);
draftData.project.ciAccessAuthorizedAgents.nodes =
draftData.project.ciAccessAuthorizedAgents.nodes.filter(
({ agent }) => agent.id !== deleteClusterAgent.id,
);
draftData.project.userAccessAuthorizedAgents.nodes =
draftData.project.userAccessAuthorizedAgents.nodes.filter(
({ agent }) => agent.id !== deleteClusterAgent.id,
);
});
store.writeQuery({

View File

@ -13,7 +13,11 @@ function required(name) {
}
async function observeMergeRequestFinishingPreparation({ apollo, signaler }) {
const { namespace, project, id: iid } = getDerivedMergeRequestInformation({
const {
namespace,
project,
id: iid,
} = getDerivedMergeRequestInformation({
endpoint: document.location.pathname,
});
const projectPath = `${namespace}/${project}`;

View File

@ -29,17 +29,19 @@ export default Extension.create({
addCommands() {
return {
uploadAttachment: ({ file }) => () => {
const { uploadsPath, renderMarkdown, eventHub } = this.options;
uploadAttachment:
({ file }) =>
() => {
const { uploadsPath, renderMarkdown, eventHub } = this.options;
return handleFileEvent({
file,
uploadsPath,
renderMarkdown,
editor: this.editor,
eventHub,
});
},
return handleFileEvent({
file,
uploadsPath,
renderMarkdown,
editor: this.editor,
eventHub,
});
},
};
},
addProseMirrorPlugins() {

View File

@ -34,32 +34,34 @@ export default CodeBlockHighlight.extend({
const ext = this;
return {
insertCodeSuggestion: (attributes) => async ({ editor }) => {
// do not insert a new suggestion if already inside a suggestion
if (editor.isActive('codeSuggestion')) return false;
insertCodeSuggestion:
(attributes) =>
async ({ editor }) => {
// do not insert a new suggestion if already inside a suggestion
if (editor.isActive('codeSuggestion')) return false;
const rawPath = ext.options.codeSuggestionsConfig.diffFile.view_path.replace(
'/blob/',
'/raw/',
);
const allLines = (await memoizedGet(rawPath)).split('\n');
const { line } = ext.options.codeSuggestionsConfig;
let { lines } = ext.options.codeSuggestionsConfig;
const rawPath = ext.options.codeSuggestionsConfig.diffFile.view_path.replace(
'/blob/',
'/raw/',
);
const allLines = (await memoizedGet(rawPath)).split('\n');
const { line } = ext.options.codeSuggestionsConfig;
let { lines } = ext.options.codeSuggestionsConfig;
if (!lines.length) lines = [line];
if (!lines.length) lines = [line];
const content = lines.map((l) => allLines[l.new_line - 1]).join('\n');
const lineNumbers = `-${lines.length - 1}+0`;
const content = lines.map((l) => allLines[l.new_line - 1]).join('\n');
const lineNumbers = `-${lines.length - 1}+0`;
editor.commands.insertContent({
type: 'codeSuggestion',
attrs: { langParams: lineNumbers, ...attributes },
// empty strings are not allowed in text nodes
content: [{ type: 'text', text: content || ' ' }],
});
editor.commands.insertContent({
type: 'codeSuggestion',
attrs: { langParams: lineNumbers, ...attributes },
// empty strings are not allowed in text nodes
content: [{ type: 'text', text: content || ' ' }],
});
return true;
},
return true;
},
};
},

View File

@ -43,62 +43,68 @@ export default Extension.create({
},
addCommands() {
return {
pasteContent: (content = '', processMarkdown = true) => () => {
const { editor, options } = this;
const { renderMarkdown, eventHub } = options;
const deserializer = createMarkdownDeserializer({ render: renderMarkdown });
pasteContent:
(content = '', processMarkdown = true) =>
() => {
const { editor, options } = this;
const { renderMarkdown, eventHub } = options;
const deserializer = createMarkdownDeserializer({ render: renderMarkdown });
const pasteSchemaSpec = { ...editor.schema.spec };
pasteSchemaSpec.marks = OrderedMap.from(pasteSchemaSpec.marks).remove('span');
pasteSchemaSpec.nodes = OrderedMap.from(pasteSchemaSpec.nodes).remove('div').remove('pre');
const pasteSchema = new Schema(pasteSchemaSpec);
const pasteSchemaSpec = { ...editor.schema.spec };
pasteSchemaSpec.marks = OrderedMap.from(pasteSchemaSpec.marks).remove('span');
pasteSchemaSpec.nodes = OrderedMap.from(pasteSchemaSpec.nodes)
.remove('div')
.remove('pre');
const pasteSchema = new Schema(pasteSchemaSpec);
const promise = processMarkdown
? deserializer.deserialize({ schema: pasteSchema, markdown: content })
: Promise.resolve(parseHTML(pasteSchema, content));
const loaderId = uniqueId('loading');
const promise = processMarkdown
? deserializer.deserialize({ schema: pasteSchema, markdown: content })
: Promise.resolve(parseHTML(pasteSchema, content));
const loaderId = uniqueId('loading');
Promise.resolve()
.then(() => {
editor
.chain()
.deleteSelection()
.setMeta(loadingPlugin, {
add: { loaderId, pos: editor.state.selection.from },
})
.run();
Promise.resolve()
.then(() => {
editor
.chain()
.deleteSelection()
.setMeta(loadingPlugin, {
add: { loaderId, pos: editor.state.selection.from },
})
.run();
return promise;
})
.then(async ({ document }) => {
if (!document) return;
return promise;
})
.then(async ({ document }) => {
if (!document) return;
const pos = findLoader(editor.state, loaderId);
if (!pos) return;
const pos = findLoader(editor.state, loaderId);
if (!pos) return;
const { firstChild, childCount } = document.content;
const toPaste =
childCount === 1 && firstChild.type.name === 'paragraph'
? firstChild.content
: document.content;
const { firstChild, childCount } = document.content;
const toPaste =
childCount === 1 && firstChild.type.name === 'paragraph'
? firstChild.content
: document.content;
editor
.chain()
.setMeta(loadingPlugin, { remove: { loaderId } })
.insertContentAt(pos, toPaste.toJSON(), {
updateSelection: false,
})
.run();
})
.catch(() => {
eventHub.$emit(ALERT_EVENT, {
message: __('An error occurred while pasting text in the editor. Please try again.'),
variant: VARIANT_DANGER,
editor
.chain()
.setMeta(loadingPlugin, { remove: { loaderId } })
.insertContentAt(pos, toPaste.toJSON(), {
updateSelection: false,
})
.run();
})
.catch(() => {
eventHub.$emit(ALERT_EVENT, {
message: __(
'An error occurred while pasting text in the editor. Please try again.',
),
variant: VARIANT_DANGER,
});
});
});
return true;
},
return true;
},
};
},
addProseMirrorPlugins() {

View File

@ -28,8 +28,14 @@ export default Node.create({
addCommands() {
return {
setDetails: () => ({ commands }) => commands.wrapInList('details'),
toggleDetails: () => ({ commands }) => commands.toggleList('details', 'detailsContent'),
setDetails:
() =>
({ commands }) =>
commands.wrapInList('details'),
toggleDetails:
() =>
({ commands }) =>
commands.toggleList('details', 'detailsContent'),
};
},
});

View File

@ -31,12 +31,16 @@ export default CodeBlockHighlight.extend({
},
addCommands() {
return {
setFrontmatter: (attributes) => ({ commands }) => {
return commands.setNode(this.name, attributes);
},
toggleFrontmatter: (attributes) => ({ commands }) => {
return commands.toggleNode(this.name, 'paragraph', attributes);
},
setFrontmatter:
(attributes) =>
({ commands }) => {
return commands.setNode(this.name, attributes);
},
toggleFrontmatter:
(attributes) =>
({ commands }) => {
return commands.toggleNode(this.name, 'paragraph', attributes);
},
};
},

View File

@ -77,9 +77,11 @@ export default Link.extend({
addCommands() {
return {
...this.parent?.(),
editLink: (attrs) => ({ chain }) => {
chain().setMeta('creatingLink', true).setLink(attrs).run();
},
editLink:
(attrs) =>
({ chain }) => {
chain().setMeta('creatingLink', true).setLink(attrs).run();
},
};
},

View File

@ -65,14 +65,18 @@ export default Node.create({
addCommands() {
return {
insertQuickAction: () => ({ commands }) => commands.insertContent('<p>/</p>'),
insertQuickAction:
() =>
({ commands }) =>
commands.insertContent('<p>/</p>'),
};
},
addInputRules() {
const { editor } = this;
const { assetResolver } = this.options;
const referenceInputRegex = /(?:^|\s)([\w/]*([#!&%$@~]|\[vulnerability:)[\w.]+(\+?s?\]?))(?:\s|\n)/m;
const referenceInputRegex =
/(?:^|\s)([\w/]*([#!&%$@~]|\[vulnerability:)[\w.]+(\+?s?\]?))(?:\s|\n)/m;
const referenceTypes = {
'#': 'issue',
'!': 'merge_request',
@ -95,13 +99,8 @@ export default Node.create({
const [, referenceId, referenceSymbol, expansionType] = match;
const referenceType = referenceTypes[referenceSymbol];
const {
href,
text,
expandedText,
fullyExpandedText,
backgroundColor,
} = await assetResolver.resolveReference(referenceId);
const { href, text, expandedText, fullyExpandedText, backgroundColor } =
await assetResolver.resolveReference(referenceId);
if (!text) return;

View File

@ -20,23 +20,36 @@ export default TableHeader.extend({
addCommands() {
return {
...this.parent?.(),
alignColumn: (pos, align) => ({ commands }) => {
commands.selectColumn(pos);
commands.updateAttributes('tableHeader', { align });
commands.updateAttributes('tableCell', { align });
},
alignColumnLeft: (pos) => ({ commands }) => commands.alignColumn(pos, 'left'),
alignColumnCenter: (pos) => ({ commands }) => commands.alignColumn(pos, 'center'),
alignColumnRight: (pos) => ({ commands }) => commands.alignColumn(pos, 'right'),
selectColumn: (pos) => ({ tr, dispatch }) => {
if (dispatch) {
const position = tr.doc.resolve(pos);
const colSelection = CellSelection.colSelection(position);
tr.setSelection(colSelection);
}
alignColumn:
(pos, align) =>
({ commands }) => {
commands.selectColumn(pos);
commands.updateAttributes('tableHeader', { align });
commands.updateAttributes('tableCell', { align });
},
alignColumnLeft:
(pos) =>
({ commands }) =>
commands.alignColumn(pos, 'left'),
alignColumnCenter:
(pos) =>
({ commands }) =>
commands.alignColumn(pos, 'center'),
alignColumnRight:
(pos) =>
({ commands }) =>
commands.alignColumn(pos, 'right'),
selectColumn:
(pos) =>
({ tr, dispatch }) => {
if (dispatch) {
const position = tr.doc.resolve(pos);
const colSelection = CellSelection.colSelection(position);
tr.setSelection(colSelection);
}
return true;
},
return true;
},
};
},

View File

@ -36,7 +36,10 @@ export default Node.create({
addCommands() {
return {
insertTableOfContents: () => ({ commands }) => commands.insertContent({ type: this.name }),
insertTableOfContents:
() =>
({ commands }) =>
commands.insertContent({ type: this.name }),
};
},

View File

@ -426,9 +426,8 @@ const expandPreserveUnchangedConfig = (configOrRender) =>
export function preserveUnchanged(configOrRender) {
return (state, node, parent, index) => {
const { render, overwriteSourcePreservationStrategy, inline } = expandPreserveUnchangedConfig(
configOrRender,
);
const { render, overwriteSourcePreservationStrategy, inline } =
expandPreserveUnchangedConfig(configOrRender);
const { sourceMarkdown } = node.attrs;
const same = state.options.changeTracker.get(node);

View File

@ -8,13 +8,15 @@ import {
INPUT_RULE_TRACKING_ACTION,
} from '../constants';
const trackKeyboardShortcut = (contentType, commandFn, shortcut) => (...args) => {
Tracking.event(undefined, KEYBOARD_SHORTCUT_TRACKING_ACTION, {
label: CONTENT_EDITOR_TRACKING_LABEL,
property: `${contentType}.${shortcut}`,
});
return commandFn(...args);
};
const trackKeyboardShortcut =
(contentType, commandFn, shortcut) =>
(...args) => {
Tracking.event(undefined, KEYBOARD_SHORTCUT_TRACKING_ACTION, {
label: CONTENT_EDITOR_TRACKING_LABEL,
property: `${contentType}.${shortcut}`,
});
return commandFn(...args);
};
const trackInputRule = (contentType, inputRule) => {
return new InputRule({

View File

@ -248,11 +248,10 @@ export default {
const sourceData = cache.readQuery(query);
const newData = produce(sourceData, (draftState) => {
const {
awardEmoji,
} = draftState.project.issue.designCollection.designs.nodes[0].discussions.nodes
.find((d) => d.id === this.note.discussion.id)
.notes.nodes.find((n) => n.id === this.note.id);
const { awardEmoji } =
draftState.project.issue.designCollection.designs.nodes[0].discussions.nodes
.find((d) => d.id === this.note.discussion.id)
.notes.nodes.find((n) => n.id === this.note.id);
awardEmoji.nodes = this.getAwardEmojiNodes(name, toggledOn);
});

View File

@ -8,14 +8,8 @@ import createRouter from './router';
export default () => {
const el = document.querySelector('.js-design-management');
const {
issueIid,
projectPath,
issuePath,
registerPath,
signInPath,
newCommentTemplatePaths,
} = el.dataset;
const { issueIid, projectPath, issuePath, registerPath, signInPath, newCommentTemplatePaths } =
el.dataset;
const router = createRouter(issuePath);
apolloProvider.clients.defaultClient.cache.writeQuery({

View File

@ -191,30 +191,29 @@ export default {
'saveDiffDiscussion',
'setSuggestPopoverDismissed',
]),
handleCancelCommentForm: ignoreWhilePending(async function handleCancelCommentForm(
shouldConfirm,
isDirty,
) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
handleCancelCommentForm: ignoreWhilePending(
async function handleCancelCommentForm(shouldConfirm, isDirty) {
if (shouldConfirm && isDirty) {
const msg = s__('Notes|Are you sure you want to cancel creating this comment?');
const confirmed = await confirmAction(msg, {
primaryBtnText: __('Discard changes'),
cancelBtnText: __('Continue editing'),
});
const confirmed = await confirmAction(msg, {
primaryBtnText: __('Discard changes'),
cancelBtnText: __('Continue editing'),
});
if (!confirmed) {
return;
if (!confirmed) {
return;
}
}
}
this.cancelCommentForm({
lineCode: this.line.line_code,
fileHash: this.diffFileHash,
});
nextTick(() => {
clearDraft(this.autosaveKey);
});
}),
this.cancelCommentForm({
lineCode: this.line.line_code,
fileHash: this.diffFileHash,
});
nextTick(() => {
clearDraft(this.autosaveKey);
});
},
),
handleSaveNote(note, parentElement, errorCallback) {
return this.saveDiffDiscussion({ note, formData: this.formData })
.then(() => this.handleCancelCommentForm())

View File

@ -153,67 +153,68 @@ export const shouldShowCommentButton = (hover, context, meta, discussions) => {
return hover && !context && !meta && !discussions;
};
export const mapParallel = ({
diffFile,
hasParallelDraftLeft,
hasParallelDraftRight,
draftsForLine,
}) => (line) => {
let { left, right } = line;
export const mapParallel =
({ diffFile, hasParallelDraftLeft, hasParallelDraftRight, draftsForLine }) =>
(line) => {
let { left, right } = line;
// Dicussions/Comments
const hasExpandedDiscussionOnLeft =
left?.discussions?.length > 0 ? left?.discussionsExpanded : false;
const hasExpandedDiscussionOnRight =
right?.discussions?.length > 0 ? right?.discussionsExpanded : false;
// Dicussions/Comments
const hasExpandedDiscussionOnLeft =
left?.discussions?.length > 0 ? left?.discussionsExpanded : false;
const hasExpandedDiscussionOnRight =
right?.discussions?.length > 0 ? right?.discussionsExpanded : false;
const renderCommentRow =
hasExpandedDiscussionOnLeft || hasExpandedDiscussionOnRight || left?.hasForm || right?.hasForm;
const renderCommentRow =
hasExpandedDiscussionOnLeft ||
hasExpandedDiscussionOnRight ||
left?.hasForm ||
right?.hasForm;
if (left) {
left = {
...left,
renderDiscussion: hasExpandedDiscussionOnLeft,
hasDraft: hasParallelDraftLeft(diffFile.file_hash, line),
lineDrafts: draftsForLine(diffFile.file_hash, line, 'left'),
hasCommentForm: left.hasForm,
isConflictMarker:
line.left.type === CONFLICT_MARKER_OUR || line.left.type === CONFLICT_MARKER_THEIR,
emptyCellClassMap: { conflict_our: line.right?.type === CONFLICT_THEIR },
addCommentTooltip: addCommentTooltip(line.left),
if (left) {
left = {
...left,
renderDiscussion: hasExpandedDiscussionOnLeft,
hasDraft: hasParallelDraftLeft(diffFile.file_hash, line),
lineDrafts: draftsForLine(diffFile.file_hash, line, 'left'),
hasCommentForm: left.hasForm,
isConflictMarker:
line.left.type === CONFLICT_MARKER_OUR || line.left.type === CONFLICT_MARKER_THEIR,
emptyCellClassMap: { conflict_our: line.right?.type === CONFLICT_THEIR },
addCommentTooltip: addCommentTooltip(line.left),
};
}
if (right) {
right = {
...right,
renderDiscussion: Boolean(
hasExpandedDiscussionOnRight && right.type && right.type !== EXPANDED_LINE_TYPE,
),
hasDraft: hasParallelDraftRight(diffFile.file_hash, line),
lineDrafts: draftsForLine(diffFile.file_hash, line, 'right'),
hasCommentForm: Boolean(right.hasForm && right.type && right.type !== EXPANDED_LINE_TYPE),
emptyCellClassMap: { conflict_their: line.left?.type === CONFLICT_OUR },
addCommentTooltip: addCommentTooltip(line.right),
};
}
return {
...line,
left,
right,
isMatchLineLeft: isMatchLine(left?.type),
isMatchLineRight: isMatchLine(right?.type),
isContextLineLeft: isContextLine(left?.type),
isContextLineRight: isContextLine(right?.type),
hasDiscussionsLeft: hasDiscussions(left),
hasDiscussionsRight: hasDiscussions(right),
lineHrefOld: lineHref(left, diffFile),
lineHrefNew: lineHref(right, diffFile),
lineCode: lineCode(line),
isMetaLineLeft: isMetaLine(left?.type),
isMetaLineRight: isMetaLine(right?.type),
draftRowClasses: left?.hasDraft || right?.hasDraft ? '' : 'js-temp-notes-holder',
renderCommentRow,
commentRowClasses:
hasDiscussions(left) || hasDiscussions(right) ? '' : 'js-temp-notes-holder',
};
}
if (right) {
right = {
...right,
renderDiscussion: Boolean(
hasExpandedDiscussionOnRight && right.type && right.type !== EXPANDED_LINE_TYPE,
),
hasDraft: hasParallelDraftRight(diffFile.file_hash, line),
lineDrafts: draftsForLine(diffFile.file_hash, line, 'right'),
hasCommentForm: Boolean(right.hasForm && right.type && right.type !== EXPANDED_LINE_TYPE),
emptyCellClassMap: { conflict_their: line.left?.type === CONFLICT_OUR },
addCommentTooltip: addCommentTooltip(line.right),
};
}
return {
...line,
left,
right,
isMatchLineLeft: isMatchLine(left?.type),
isMatchLineRight: isMatchLine(right?.type),
isContextLineLeft: isContextLine(left?.type),
isContextLineRight: isContextLine(right?.type),
hasDiscussionsLeft: hasDiscussions(left),
hasDiscussionsRight: hasDiscussions(right),
lineHrefOld: lineHref(left, diffFile),
lineHrefNew: lineHref(right, diffFile),
lineCode: lineCode(line),
isMetaLineLeft: isMetaLine(left?.type),
isMetaLineRight: isMetaLine(right?.type),
draftRowClasses: left?.hasDraft || right?.hasDraft ? '' : 'js-temp-notes-holder',
renderCommentRow,
commentRowClasses: hasDiscussions(left) || hasDiscussions(right) ? '' : 'js-temp-notes-holder',
};
};

View File

@ -83,8 +83,12 @@ export class EditorMarkdownExtension {
instance.setPosition(pos);
},
insertMarkdown: (instance, e) => {
const { mdTag: tag, mdBlock: blockTag, mdPrepend, mdSelect: select } =
e.currentTarget?.dataset || e;
const {
mdTag: tag,
mdBlock: blockTag,
mdPrepend,
mdSelect: select,
} = e.currentTarget?.dataset || e;
insertMarkdownText({
tag,

View File

@ -76,8 +76,10 @@ const chromeVersion = chromeMatches && chromeMatches[1] && parseInt(chromeMatche
const fontSize = 16;
function generateUnicodeSupportMap(testMap) {
const testMapKeys = Object.keys(testMap);
const numTestEntries = testMapKeys.reduce((list, testKey) => list.concat(testMap[testKey]), [])
.length;
const numTestEntries = testMapKeys.reduce(
(list, testKey) => list.concat(testMap[testKey]),
[],
).length;
const canvas = document.createElement('canvas');
(window.gl || window).testEmojiUnicodeSupportMapCanvas = canvas;
@ -106,8 +108,12 @@ function generateUnicodeSupportMap(testMap) {
// keep the `readIndex` in sync from the writes by running all entries
const isTestSatisfied = [].concat(testEntry).reduce((isSatisfied) => {
// Sample along the vertical-middle for a couple of characters
const imageData = ctx.getImageData(0, readIndex * fontSize + fontSize / 2, 2 * fontSize, 1)
.data;
const imageData = ctx.getImageData(
0,
readIndex * fontSize + fontSize / 2,
2 * fontSize,
1,
).data;
let isValidEmoji = false;
for (let currentPixel = 0; currentPixel < 64; currentPixel += 1) {

View File

@ -22,13 +22,8 @@ export default {
document.querySelectorAll(this.selector).forEach((button) => {
button.addEventListener('click', (e) => {
e.preventDefault();
const {
environmentName,
commitShortSha,
commitUrl,
isLastDeployment,
retryPath,
} = button.dataset;
const { environmentName, commitShortSha, commitUrl, isLastDeployment, retryPath } =
button.dataset;
this.environment = {
name: environmentName,

View File

@ -104,12 +104,8 @@ export default {
try {
// TLDR: when we load a page, if there's next and/or previous pages existing, we'll load their data as well to improve percepted performance.
const {
endCursor,
hasPreviousPage,
hasNextPage,
startCursor,
} = newProject.environment.deployments.pageInfo;
const { endCursor, hasPreviousPage, hasNextPage, startCursor } =
newProject.environment.deployments.pageInfo;
// At the moment we have a limit of deployments being requested only from a signle environment entity per query,
// and apparently two batched queries count as one on server-side

View File

@ -94,12 +94,10 @@ const getDeploymentApprovalFromDeploymentNode = (deploymentNode, environment) =>
const hasRequiredApprovals = protectedEnvironmentInfo.requiredApprovalCount > 0;
const isApprovalActionAvailable = hasRequiredApprovals || hasApprovalRules;
const requiredMultipleApprovalRulesApprovals = protectedEnvironmentInfo.approvalRules.nodes.reduce(
(requiredApprovals, rule) => {
const requiredMultipleApprovalRulesApprovals =
protectedEnvironmentInfo.approvalRules.nodes.reduce((requiredApprovals, rule) => {
return requiredApprovals + rule.requiredApprovals;
},
0,
);
}, 0);
const requiredApprovalCount = hasRequiredApprovals
? protectedEnvironmentInfo.requiredApprovalCount

View File

@ -12,13 +12,8 @@ export default () => {
const selector = '#js-error_details';
const domEl = document.querySelector(selector);
const {
issueId,
projectPath,
issueUpdatePath,
issueStackTracePath,
projectIssuesPath,
} = domEl.dataset;
const { issueId, projectPath, issueUpdatePath, issueStackTracePath, projectIssuesPath } =
domEl.dataset;
let { integratedErrorTrackingEnabled } = domEl.dataset;
integratedErrorTrackingEnabled = parseBoolean(integratedErrorTrackingEnabled);

View File

@ -7,13 +7,8 @@ export default () => {
const selector = '#js-error_tracking';
const domEl = document.querySelector(selector);
const {
indexPath,
enableErrorTrackingLink,
illustrationPath,
projectPath,
listPath,
} = domEl.dataset;
const { indexPath, enableErrorTrackingLink, illustrationPath, projectPath, listPath } =
domEl.dataset;
let {
errorTrackingEnabled,
userCanEnableErrorTracking,

View File

@ -163,9 +163,8 @@ export default class DropdownUtils {
values.push(name.innerText);
}
} else if (token.classList.contains('input-token')) {
const {
isLastVisualTokenValid,
} = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { isLastVisualTokenValid } =
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const input = FilteredSearchContainer.container.querySelector('.filtered-search');
const inputValue = input && input.value;

View File

@ -35,9 +35,8 @@ export default class FilteredSearchDropdown {
itemClicked(e, getValueFunction) {
const { selected } = e.detail;
if (selected.tagName === 'LI' && selected.innerHTML) {
const {
lastVisualToken: visualToken,
} = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { lastVisualToken: visualToken } =
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { tokenOperator } = DropdownUtils.getVisualTokenValues(visualToken);
const dataValueSet = DropdownUtils.setDataValueIfSelected(

View File

@ -62,11 +62,8 @@ export default class FilteredSearchManager {
this.placeholder = placeholder;
this.anchor = anchor;
const {
multipleAssignees,
epicsEndpoint,
iterationsEndpoint,
} = this.filteredSearchInput.dataset;
const { multipleAssignees, epicsEndpoint, iterationsEndpoint } =
this.filteredSearchInput.dataset;
if (multipleAssignees && this.filteredSearchTokenKeys.enableMultipleAssignees) {
this.filteredSearchTokenKeys.enableMultipleAssignees();
@ -546,7 +543,8 @@ export default class FilteredSearchManager {
}
} else {
// Keep listening to token until we determine that the user is done typing the token value
const valueCompletedRegex = /([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g;
const valueCompletedRegex =
/([~%@]{0,1}".+")|([~%@]{0,1}'.+')|^((?![~%@]')(?![~%@]")(?!')(?!")).*/g;
if (searchToken.match(valueCompletedRegex) && input.value[input.value.length - 1] === ' ') {
const tokenKey = FilteredSearchVisualTokens.getLastTokenPartial();

View File

@ -156,10 +156,8 @@ export default class FilteredSearchVisualTokens {
}
static addValueToPreviousVisualTokenElement(value) {
const {
lastVisualToken,
isLastVisualTokenValid,
} = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { lastVisualToken, isLastVisualTokenValid } =
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
if (!isLastVisualTokenValid && lastVisualToken.classList.contains('filtered-search-token')) {
const name = FilteredSearchVisualTokens.getLastTokenPartial();
@ -181,10 +179,8 @@ export default class FilteredSearchVisualTokens {
tokenValue,
{ canEdit, uppercaseTokenName = false, capitalizeTokenValue = false } = {},
) {
const {
lastVisualToken,
isLastVisualTokenValid,
} = FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { lastVisualToken, isLastVisualTokenValid } =
FilteredSearchVisualTokens.getLastVisualTokenBeforeInput();
const { addVisualTokenElement } = FilteredSearchVisualTokens;
if (isLastVisualTokenValid) {

View File

@ -35,11 +35,8 @@ const mountSecurityPatchUpgradeAlertModal = (el) => {
const { currentVersion, version } = el.dataset;
try {
const {
details,
latestStableVersions,
latestStableVersionOfMinor,
} = convertObjectPropsToCamelCase(JSON.parse(version));
const { details, latestStableVersions, latestStableVersionOfMinor } =
convertObjectPropsToCamelCase(JSON.parse(version));
return new Vue({
el,

View File

@ -30,12 +30,8 @@ export const initGroupsExplore = () => {
const {
dataset: { appData },
} = el;
const {
groupsEmptyStateIllustration,
emptySearchIllustration,
endpoint,
initialSort,
} = convertObjectPropsToCamelCase(JSON.parse(appData));
const { groupsEmptyStateIllustration, emptySearchIllustration, endpoint, initialSort } =
convertObjectPropsToCamelCase(JSON.parse(appData));
Vue.use(VueRouter);
const router = createRouter();

View File

@ -8,14 +8,8 @@ export default function initInviteMembersBanner() {
return false;
}
const {
svgPath,
inviteMembersPath,
trackLabel,
calloutsPath,
calloutsFeatureId,
groupId,
} = el.dataset;
const { svgPath, inviteMembersPath, trackLabel, calloutsPath, calloutsFeatureId, groupId } =
el.dataset;
return new Vue({
el,

View File

@ -144,13 +144,11 @@ export default {
},
async getGroupTransferLocations() {
try {
const {
data: groupTransferLocations,
headers,
} = await this.groupTransferLocationsApiMethod(this.resourceId, {
page: this.page,
search: this.searchTerm,
});
const { data: groupTransferLocations, headers } =
await this.groupTransferLocationsApiMethod(this.resourceId, {
page: this.page,
search: this.searchTerm,
});
const { totalPages } = parseIntPagination(normalizeHeaders(headers));
this.totalPages = totalPages;

View File

@ -12,9 +12,8 @@ import {
import NewMergeRequestOption from './new_merge_request_option.vue';
import RadioGroup from './radio_group.vue';
const { mapState: mapCommitState, mapActions: mapCommitActions } = createNamespacedHelpers(
'commit',
);
const { mapState: mapCommitState, mapActions: mapCommitActions } =
createNamespacedHelpers('commit');
export default {
components: {

View File

@ -4,9 +4,8 @@ import { GlTooltipDirective, GlFormCheckbox } from '@gitlab/ui';
import { createNamespacedHelpers } from 'vuex';
import { s__ } from '~/locale';
const { mapActions: mapCommitActions, mapGetters: mapCommitGetters } = createNamespacedHelpers(
'commit',
);
const { mapActions: mapCommitActions, mapGetters: mapCommitGetters } =
createNamespacedHelpers('commit');
export default {
components: { GlFormCheckbox },

View File

@ -77,7 +77,8 @@ const language = {
symbols: /[=><!~?:&|+\-*\/\^%]+/,
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
terraformFunctions: /(abs|ceil|floor|log|max|min|pow|signum|chomp|format|formatlist|indent|join|lower|regex|regexall|replace|split|strrev|substr|title|trimspace|upper|chunklist|coalesce|coalescelist|compact|concat|contains|distinct|element|flatten|index|keys|length|list|lookup|map|matchkeys|merge|range|reverse|setintersection|setproduct|setunion|slice|sort|transpose|values|zipmap|base64decode|base64encode|base64gzip|csvdecode|jsondecode|jsonencode|urlencode|yamldecode|yamlencode|abspath|dirname|pathexpand|basename|file|fileexists|fileset|filebase64|templatefile|formatdate|timeadd|timestamp|base64sha256|base64sha512|bcrypt|filebase64sha256|filebase64sha512|filemd5|filemd1|filesha256|filesha512|md5|rsadecrypt|sha1|sha256|sha512|uuid|uuidv5|cidrhost|cidrnetmask|cidrsubnet|tobool|tolist|tomap|tonumber|toset|tostring)/,
terraformFunctions:
/(abs|ceil|floor|log|max|min|pow|signum|chomp|format|formatlist|indent|join|lower|regex|regexall|replace|split|strrev|substr|title|trimspace|upper|chunklist|coalesce|coalescelist|compact|concat|contains|distinct|element|flatten|index|keys|length|list|lookup|map|matchkeys|merge|range|reverse|setintersection|setproduct|setunion|slice|sort|transpose|values|zipmap|base64decode|base64encode|base64gzip|csvdecode|jsondecode|jsonencode|urlencode|yamldecode|yamlencode|abspath|dirname|pathexpand|basename|file|fileexists|fileset|filebase64|templatefile|formatdate|timeadd|timestamp|base64sha256|base64sha512|bcrypt|filebase64sha256|filebase64sha512|filemd5|filemd1|filesha256|filesha512|md5|rsadecrypt|sha1|sha256|sha512|uuid|uuidv5|cidrhost|cidrnetmask|cidrsubnet|tobool|tolist|tomap|tonumber|toset|tostring)/,
terraformMainBlocks: /(module|data|terraform|resource|provider|variable|output|locals)/,
tokenizer: {
root: [

View File

@ -7,9 +7,8 @@ export class OAuthCallbackDomainMismatchErrorApp {
constructor(el, callbackUrls) {
this.#el = el;
this.#callbackUrlOrigins = OAuthCallbackDomainMismatchErrorApp.#getCallbackUrlOrigins(
callbackUrls,
);
this.#callbackUrlOrigins =
OAuthCallbackDomainMismatchErrorApp.#getCallbackUrlOrigins(callbackUrls);
}
isVisitingFromNonRegisteredOrigin() {

View File

@ -84,163 +84,174 @@ const importAll = ({ state, dispatch }, config = {}) => {
);
};
const fetchReposFactory = ({ reposPath = isRequired() }) => ({ state, commit }) => {
commit(types.REQUEST_REPOS);
const fetchReposFactory =
({ reposPath = isRequired() }) =>
({ state, commit }) => {
commit(types.REQUEST_REPOS);
const { provider, filter } = state;
const { provider, filter } = state;
return axios
.get(
pathWithParams({
path: reposPath,
...filter,
...paginationParams({ state }),
}),
)
.then(({ data }) => {
const camelData = convertObjectPropsToCamelCase(data, { deep: true });
commitPaginationData({ state, commit, data: camelData });
commit(types.RECEIVE_REPOS_SUCCESS, camelData);
})
.catch((e) => {
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else if (tooManyRequests(e)) {
createAlert({
message: sprintf(
s__('ImportProjects|%{provider} rate limit exceeded. Try again later'),
{
provider: capitalizeFirstCharacter(provider),
},
),
});
commit(types.RECEIVE_REPOS_ERROR);
} else {
createAlert({
message: sprintf(
s__('ImportProjects|Requesting your %{provider} repositories failed'),
{
provider,
},
),
});
commit(types.RECEIVE_REPOS_ERROR);
}
});
};
const fetchImportFactory =
(importPath = isRequired()) =>
({ state, commit, getters }, { repoId, optionalStages }) => {
const { ciCdOnly } = state;
const importTarget = getters.getImportTarget(repoId);
commit(types.REQUEST_IMPORT, { repoId, importTarget });
const { newName, targetNamespace } = importTarget;
return axios
.post(importPath, {
repo_id: repoId,
ci_cd_only: ciCdOnly,
new_name: newName,
target_namespace: targetNamespace,
...(Object.keys(optionalStages).length ? { optional_stages: optionalStages } : {}),
})
.then(({ data }) => {
commit(types.RECEIVE_IMPORT_SUCCESS, {
importedProject: convertObjectPropsToCamelCase(data, { deep: true }),
repoId,
});
})
.catch((e) => {
const serverErrorMessage = e?.response?.data?.errors;
const alertMessage = serverErrorMessage
? sprintf(
s__('ImportProjects|Importing the project failed: %{reason}'),
{
reason: serverErrorMessage,
},
false,
)
: s__('ImportProjects|Importing the project failed');
return axios
.get(
pathWithParams({
path: reposPath,
...filter,
...paginationParams({ state }),
}),
)
.then(({ data }) => {
const camelData = convertObjectPropsToCamelCase(data, { deep: true });
commitPaginationData({ state, commit, data: camelData });
commit(types.RECEIVE_REPOS_SUCCESS, camelData);
})
.catch((e) => {
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else if (tooManyRequests(e)) {
createAlert({
message: sprintf(s__('ImportProjects|%{provider} rate limit exceeded. Try again later'), {
provider: capitalizeFirstCharacter(provider),
}),
message: alertMessage,
});
commit(types.RECEIVE_REPOS_ERROR);
} else {
createAlert({
message: sprintf(s__('ImportProjects|Requesting your %{provider} repositories failed'), {
provider,
}),
});
commit(types.RECEIVE_REPOS_ERROR);
}
});
};
const fetchImportFactory = (importPath = isRequired()) => (
{ state, commit, getters },
{ repoId, optionalStages },
) => {
const { ciCdOnly } = state;
const importTarget = getters.getImportTarget(repoId);
commit(types.REQUEST_IMPORT, { repoId, importTarget });
const { newName, targetNamespace } = importTarget;
return axios
.post(importPath, {
repo_id: repoId,
ci_cd_only: ciCdOnly,
new_name: newName,
target_namespace: targetNamespace,
...(Object.keys(optionalStages).length ? { optional_stages: optionalStages } : {}),
})
.then(({ data }) => {
commit(types.RECEIVE_IMPORT_SUCCESS, {
importedProject: convertObjectPropsToCamelCase(data, { deep: true }),
repoId,
commit(types.RECEIVE_IMPORT_ERROR, repoId);
});
})
.catch((e) => {
const serverErrorMessage = e?.response?.data?.errors;
const alertMessage = serverErrorMessage
? sprintf(
s__('ImportProjects|Importing the project failed: %{reason}'),
{
reason: serverErrorMessage,
},
false,
)
: s__('ImportProjects|Importing the project failed');
};
createAlert({
message: alertMessage,
});
export const cancelImportFactory =
(cancelImportPath) =>
({ state, commit }, { repoId }) => {
const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
commit(types.RECEIVE_IMPORT_ERROR, repoId);
});
};
export const cancelImportFactory = (cancelImportPath) => ({ state, commit }, { repoId }) => {
const existingRepo = state.repositories.find((r) => r.importSource.id === repoId);
if (!existingRepo?.importedProject) {
throw new Error(`Attempting to cancel project which is not started: ${repoId}`);
}
const { id } = existingRepo.importedProject;
return axios
.post(cancelImportPath, {
project_id: id,
})
.then(() => {
commit(types.CANCEL_IMPORT_SUCCESS, {
repoId,
});
})
.catch((e) => {
const serverErrorMessage = e?.response?.data?.errors;
const alertMessage = serverErrorMessage
? sprintf(
s__('ImportProjects|Cancelling project import failed: %{reason}'),
{
reason: serverErrorMessage,
},
false,
)
: s__('ImportProjects|Cancelling project import failed');
createAlert({
message: alertMessage,
});
});
};
export const fetchJobsFactory = (jobsPath = isRequired()) => ({ state, commit, dispatch }) => {
if (eTagPoll) {
stopJobsPolling();
clearJobsEtagPoll();
}
eTagPoll = new Poll({
resource: {
fetchJobs: () => axios.get(pathWithParams({ path: jobsPath, ...state.filter })),
},
method: 'fetchJobs',
successCallback: ({ data }) =>
commit(types.RECEIVE_JOBS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })),
errorCallback: (e) => {
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
createAlert({
message: s__('ImportProjects|Update of imported projects with realtime changes failed'),
});
}
},
});
if (!Visibility.hidden()) {
eTagPoll.makeRequest();
}
Visibility.change(() => {
if (!Visibility.hidden()) {
dispatch('restartJobsPolling');
} else {
dispatch('stopJobsPolling');
if (!existingRepo?.importedProject) {
throw new Error(`Attempting to cancel project which is not started: ${repoId}`);
}
});
};
const { id } = existingRepo.importedProject;
return axios
.post(cancelImportPath, {
project_id: id,
})
.then(() => {
commit(types.CANCEL_IMPORT_SUCCESS, {
repoId,
});
})
.catch((e) => {
const serverErrorMessage = e?.response?.data?.errors;
const alertMessage = serverErrorMessage
? sprintf(
s__('ImportProjects|Cancelling project import failed: %{reason}'),
{
reason: serverErrorMessage,
},
false,
)
: s__('ImportProjects|Cancelling project import failed');
createAlert({
message: alertMessage,
});
});
};
export const fetchJobsFactory =
(jobsPath = isRequired()) =>
({ state, commit, dispatch }) => {
if (eTagPoll) {
stopJobsPolling();
clearJobsEtagPoll();
}
eTagPoll = new Poll({
resource: {
fetchJobs: () => axios.get(pathWithParams({ path: jobsPath, ...state.filter })),
},
method: 'fetchJobs',
successCallback: ({ data }) =>
commit(types.RECEIVE_JOBS_SUCCESS, convertObjectPropsToCamelCase(data, { deep: true })),
errorCallback: (e) => {
if (hasRedirectInError(e)) {
redirectToUrlInError(e);
} else {
createAlert({
message: s__('ImportProjects|Update of imported projects with realtime changes failed'),
});
}
},
});
if (!Visibility.hidden()) {
eTagPoll.makeRequest();
}
Visibility.change(() => {
if (!Visibility.hidden()) {
dispatch('restartJobsPolling');
} else {
dispatch('stopJobsPolling');
}
});
};
const setFilter = ({ commit, dispatch }, filter) => {
commit(types.SET_FILTER, filter);

View File

@ -7,14 +7,8 @@ export default () => {
if (!el) return null;
const {
projects,
isSignedIn,
signInPath,
slackLinkPath,
gitlabLogoPath,
slackLogoPath,
} = el.dataset;
const { projects, isSignedIn, signInPath, slackLinkPath, gitlabLogoPath, slackLogoPath } =
el.dataset;
return new Vue({
el,

View File

@ -9,13 +9,8 @@ export default function initImportProjectMembersModal() {
return false;
}
const {
projectId,
projectName,
reloadPageOnSubmit,
usersLimitDataset,
addSeatsHref,
} = el.dataset;
const { projectId, projectName, reloadPageOnSubmit, usersLimitDataset, addSeatsHref } =
el.dataset;
return new Vue({
el,

View File

@ -36,9 +36,8 @@ export default {
const prevMergeRequests = previousResult.project.issue.relatedMergeRequests.nodes;
return produce(fetchMoreResult, (draftData) => {
draftData.project.issue.relatedMergeRequests.nodes = prevMergeRequests.concat(
newMergeRequests,
);
draftData.project.issue.relatedMergeRequests.nodes =
prevMergeRequests.concat(newMergeRequests);
});
},
});

View File

@ -168,10 +168,8 @@ export default {
this.$emit('error');
},
async getOAuthToken(code) {
const {
oauth_token_payload: oauthTokenPayload,
oauth_token_path: oauthTokenPath,
} = this.oauthMetadata;
const { oauth_token_payload: oauthTokenPayload, oauth_token_path: oauthTokenPath } =
this.oauthMetadata;
const { data } = await fetchOAuthToken(oauthTokenPath, {
...oauthTokenPayload,
code,

View File

@ -47,7 +47,8 @@ export default {
<li class="gl-leading-20 gl-py-3 gl-border-b-solid gl-border-b-2 gl-border-b-gray-100">
<div
:class="{
'gl-display-flex gl-flex-wrap gl-justify-content-space-between gl-align-items-center': collapsible,
'gl-display-flex gl-flex-wrap gl-justify-content-space-between gl-align-items-center':
collapsible,
}"
>
<slot name="label">

View File

@ -579,7 +579,11 @@ export const approximateDuration = (seconds = 0) => {
const HOURS_LIMIT = 86370; // 23 hours 59 minutes 30s
const ONE_DAY_LIMIT = 151170; // 41 hours 59 minutes 30s
const { days = 0, hours = 0, minutes = 0 } = parseSeconds(seconds, {
const {
days = 0,
hours = 0,
minutes = 0,
} = parseSeconds(seconds, {
daysPerWeek: 7,
hoursPerDay: 24,
limitToDays: true,

View File

@ -7,4 +7,5 @@
export const unicodeLetters =
'\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0527\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0620-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0800-\\u0815\\u081A\\u0824\\u0828\\u0840-\\u0858\\u08A0\\u08A2-\\u08AC\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971-\\u0977\\u0979-\\u097F\\u0985-\\u098C\\u098F\\u0990\\u0993-\\u09A8\\u09AA-\\u09B0\\u09B2\\u09B6-\\u09B9\\u09BD\\u09CE\\u09DC\\u09DD\\u09DF-\\u09E1\\u09F0\\u09F1\\u0A05-\\u0A0A\\u0A0F\\u0A10\\u0A13-\\u0A28\\u0A2A-\\u0A30\\u0A32\\u0A33\\u0A35\\u0A36\\u0A38\\u0A39\\u0A59-\\u0A5C\\u0A5E\\u0A72-\\u0A74\\u0A85-\\u0A8D\\u0A8F-\\u0A91\\u0A93-\\u0AA8\\u0AAA-\\u0AB0\\u0AB2\\u0AB3\\u0AB5-\\u0AB9\\u0ABD\\u0AD0\\u0AE0\\u0AE1\\u0B05-\\u0B0C\\u0B0F\\u0B10\\u0B13-\\u0B28\\u0B2A-\\u0B30\\u0B32\\u0B33\\u0B35-\\u0B39\\u0B3D\\u0B5C\\u0B5D\\u0B5F-\\u0B61\\u0B71\\u0B83\\u0B85-\\u0B8A\\u0B8E-\\u0B90\\u0B92-\\u0B95\\u0B99\\u0B9A\\u0B9C\\u0B9E\\u0B9F\\u0BA3\\u0BA4\\u0BA8-\\u0BAA\\u0BAE-\\u0BB9\\u0BD0\\u0C05-\\u0C0C\\u0C0E-\\u0C10\\u0C12-\\u0C28\\u0C2A-\\u0C33\\u0C35-\\u0C39\\u0C3D\\u0C58\\u0C59\\u0C60\\u0C61\\u0C85-\\u0C8C\\u0C8E-\\u0C90\\u0C92-\\u0CA8\\u0CAA-\\u0CB3\\u0CB5-\\u0CB9\\u0CBD\\u0CDE\\u0CE0\\u0CE1\\u0CF1\\u0CF2\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D3A\\u0D3D\\u0D4E\\u0D60\\u0D61\\u0D7A-\\u0D7F\\u0D85-\\u0D96\\u0D9A-\\u0DB1\\u0DB3-\\u0DBB\\u0DBD\\u0DC0-\\u0DC6\\u0E01-\\u0E30\\u0E32\\u0E33\\u0E40-\\u0E46\\u0E81\\u0E82\\u0E84\\u0E87\\u0E88\\u0E8A\\u0E8D\\u0E94-\\u0E97\\u0E99-\\u0E9F\\u0EA1-\\u0EA3\\u0EA5\\u0EA7\\u0EAA\\u0EAB\\u0EAD-\\u0EB0\\u0EB2\\u0EB3\\u0EBD\\u0EC0-\\u0EC4\\u0EC6\\u0EDC-\\u0EDF\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8C\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10C7\\u10CD\\u10D0-\\u10FA\\u10FC-\\u1248\\u124A-\\u124D\\u1250-\\u1256\\u1258\\u125A-\\u125D\\u1260-\\u1288\\u128A-\\u128D\\u1290-\\u12B0\\u12B2-\\u12B5\\u12B8-\\u12BE\\u12C0\\u12C2-\\u12C5\\u12C8-\\u12D6\\u12D8-\\u1310\\u1312-\\u1315\\u1318-\\u135A\\u1380-\\u138F\\u13A0-\\u13F4\\u1401-\\u166C\\u166F-\\u167F\\u1681-\\u169A\\u16A0-\\u16EA\\u16EE-\\u16F0\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u18B0-\\u18F5\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19AB\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1A20-\\u1A54\\u1AA7\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1BBA-\\u1BE5\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\u1CE9-\\u1CEC\\u1CEE-\\u1CF1\\u1CF5\\u1CF6\\u1D00-\\u1DBF\\u1E00-\\u1F15\\u1F18-\\u1F1D\\u1F20-\\u1F45\\u1F48-\\u1F4D\\u1F50-\\u1F57\\u1F59\\u1F5B\\u1F5D\\u1F5F-\\u1F7D\\u1F80-\\u1FB4\\u1FB6-\\u1FBC\\u1FBE\\u1FC2-\\u1FC4\\u1FC6-\\u1FCC\\u1FD0-\\u1FD3\\u1FD6-\\u1FDB\\u1FE0-\\u1FEC\\u1FF2-\\u1FF4\\u1FF6-\\u1FFC\\u2071\\u207F\\u2090-\\u209C\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2160-\\u2188\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2CE4\\u2CEB-\\u2CEE\\u2CF2\\u2CF3\\u2D00-\\u2D25\\u2D27\\u2D2D\\u2D30-\\u2D67\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005-\\u3007\\u3021-\\u3029\\u3031-\\u3035\\u3038-\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31BA\\u31F0-\\u31FF\\u3400-\\u4DB5\\u4E00-\\u9FCC\\uA000-\\uA48C\\uA4D0-\\uA4FD\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA66E\\uA67F-\\uA697\\uA6A0-\\uA6EF\\uA717-\\uA71F\\uA722-\\uA788\\uA78B-\\uA78E\\uA790-\\uA793\\uA7A0-\\uA7AA\\uA7F8-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA8F2-\\uA8F7\\uA8FB\\uA90A-\\uA925\\uA930-\\uA946\\uA960-\\uA97C\\uA984-\\uA9B2\\uA9CF\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAA60-\\uAA76\\uAA7A\\uAA80-\\uAAAF\\uAAB1\\uAAB5\\uAAB6\\uAAB9-\\uAABD\\uAAC0\\uAAC2\\uAADB-\\uAADD\\uAAE0-\\uAAEA\\uAAF2-\\uAAF4\\uAB01-\\uAB06\\uAB09-\\uAB0E\\uAB11-\\uAB16\\uAB20-\\uAB26\\uAB28-\\uAB2E\\uABC0-\\uABE2\\uAC00-\\uD7A3\\uD7B0-\\uD7C6\\uD7CB-\\uD7FB\\uF900-\\uFA6D\\uFA70-\\uFAD9\\uFB00-\\uFB06\\uFB13-\\uFB17\\uFB1D\\uFB1F-\\uFB28\\uFB2A-\\uFB36\\uFB38-\\uFB3C\\uFB3E\\uFB40\\uFB41\\uFB43\\uFB44\\uFB46-\\uFBB1\\uFBD3-\\uFD3D\\uFD50-\\uFD8F\\uFD92-\\uFDC7\\uFDF0-\\uFDFB\\uFE70-\\uFE74\\uFE76-\\uFEFC\\uFF21-\\uFF3A\\uFF41-\\uFF5A\\uFF66-\\uFFBE\\uFFC2-\\uFFC7\\uFFCA-\\uFFCF\\uFFD2-\\uFFD7\\uFFDA-\\uFFDC';
export const semverRegex = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
export const semverRegex =
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;

View File

@ -12,7 +12,8 @@ const INDENT_LENGTH = 2;
// 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>((?<isUl>[*+-])|(?<isOl>\d+\.))( \[([xX~\s])\])?\s)(?<content>.)?/;
const LIST_LINE_HEAD_PATTERN =
/^(?<indent>\s*)(?<leader>((?<isUl>[*+-])|(?<isOl>\d+\.))( \[([xX~\s])\])?\s)(?<content>.)?/;
// detect a horizontal rule that might be mistaken for a list item (not full pattern for an <hr>)
const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/;

View File

@ -140,10 +140,8 @@ const getAverageCharWidth = memoize(function getAverageCharWidth(options = {}) {
* @return {String} either the original string or a truncated version
*/
export const truncateWidth = (string, options = {}) => {
const {
maxWidth = TRUNCATE_WIDTH_DEFAULT_WIDTH,
fontSize = TRUNCATE_WIDTH_DEFAULT_FONT_SIZE,
} = options;
const { maxWidth = TRUNCATE_WIDTH_DEFAULT_WIDTH, fontSize = TRUNCATE_WIDTH_DEFAULT_FONT_SIZE } =
options;
const { truncateIndex } = string.split('').reduce(
(memo, char, index) => {
let newIndex = index;

View File

@ -161,23 +161,21 @@ export const parseDataAttributes = (el) => {
});
};
export const baseRequestFormatter = (basePropertyName, accessLevelPropertyName) => ({
accessLevel,
memberRoleId,
...otherProperties
}) => {
const accessLevelProperty = !isUndefined(accessLevel)
? { [accessLevelPropertyName]: accessLevel }
: {};
export const baseRequestFormatter =
(basePropertyName, accessLevelPropertyName) =>
({ accessLevel, memberRoleId, ...otherProperties }) => {
const accessLevelProperty = !isUndefined(accessLevel)
? { [accessLevelPropertyName]: accessLevel }
: {};
return {
[basePropertyName]: {
...accessLevelProperty,
member_role_id: memberRoleId ?? null,
...otherProperties,
},
return {
[basePropertyName]: {
...accessLevelProperty,
member_role_id: memberRoleId ?? null,
...otherProperties,
},
};
};
};
export const groupLinkRequestFormatter = baseRequestFormatter(
GROUP_LINK_BASE_PROPERTY_NAME,

View File

@ -6,12 +6,8 @@ import { createStore } from './store';
export default function initMergeConflicts() {
const conflictsEl = document.querySelector('#conflicts');
const {
sourceBranchPath,
mergeRequestPath,
conflictsPath,
resolveConflictsPath,
} = conflictsEl.dataset;
const { sourceBranchPath, mergeRequestPath, conflictsPath, resolveConflictsPath } =
conflictsEl.dataset;
initIssuableSidebar();

View File

@ -112,6 +112,8 @@ export const fileTextTypePresent = (state) => {
return state.conflictsData?.files.some((f) => f.type === CONFLICT_TYPES.TEXT);
};
export const getFileIndex = (state) => ({ blobPath }) => {
return state.conflictsData.files.findIndex((f) => f.blobPath === blobPath);
};
export const getFileIndex =
(state) =>
({ blobPath }) => {
return state.conflictsData.files.findIndex((f) => f.blobPath === blobPath);
};

View File

@ -297,12 +297,8 @@ export default {
return getSortOptions({ hasManualSort: false });
},
tabCounts() {
const {
openedMergeRequests,
closedMergeRequests,
mergedMergeRequests,
allMergeRequests,
} = this.mergeRequestCounts;
const { openedMergeRequests, closedMergeRequests, mergedMergeRequests, allMergeRequests } =
this.mergeRequestCounts;
return {
[STATUS_OPEN]: openedMergeRequests?.count,
[STATUS_MERGED]: mergedMergeRequests?.count,

View File

@ -31,11 +31,8 @@ export default {
dataset: { popoverData },
} = el;
const {
lockedByAncestor,
lockedByApplicationSetting,
ancestorNamespace,
} = convertObjectPropsToCamelCase(JSON.parse(popoverData || '{}'), { deep: true });
const { lockedByAncestor, lockedByApplicationSetting, ancestorNamespace } =
convertObjectPropsToCamelCase(JSON.parse(popoverData || '{}'), { deep: true });
return {
el,

View File

@ -38,9 +38,8 @@ function getNextDiscussion() {
if (hasReachedPageEnd()) {
return firstDiscussion;
}
const [nextClosestDiscussion, index, isActive] = findNextClosestVisibleDiscussion(
discussionElements,
);
const [nextClosestDiscussion, index, isActive] =
findNextClosestVisibleDiscussion(discussionElements);
if (nextClosestDiscussion && !isActive) {
return nextClosestDiscussion;
}

View File

@ -179,14 +179,16 @@ export const getDiscussionLastNote = (state) => (discussion) =>
export const unresolvedDiscussionsCount = (state) => state.unresolvedDiscussionsCount;
export const resolvableDiscussionsCount = (state) => state.resolvableDiscussionsCount;
export const showJumpToNextDiscussion = (state, getters) => (mode = 'discussion') => {
const orderedDiffs =
mode !== 'discussion'
? getters.unresolvedDiscussionsIdsByDiff
: getters.unresolvedDiscussionsIdsByDate;
export const showJumpToNextDiscussion =
(state, getters) =>
(mode = 'discussion') => {
const orderedDiffs =
mode !== 'discussion'
? getters.unresolvedDiscussionsIdsByDiff
: getters.unresolvedDiscussionsIdsByDate;
return orderedDiffs.length > 1;
};
return orderedDiffs.length > 1;
};
export const isDiscussionResolved = (state, getters) => (discussionId) =>
getters.resolvedDiscussionsById[discussionId] !== undefined;
@ -302,26 +304,24 @@ export const isLastUnresolvedDiscussion = (state, getters) => (discussionId, dif
return lastDiscussionId === discussionId;
};
export const findUnresolvedDiscussionIdNeighbor = (state, getters) => ({
discussionId,
diffOrder,
step,
}) => {
const diffIds = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
const dateIds = getters.unresolvedDiscussionsIdsOrdered(false);
const ids = diffIds.length ? diffIds : dateIds;
const index = ids.indexOf(discussionId) + step;
export const findUnresolvedDiscussionIdNeighbor =
(state, getters) =>
({ discussionId, diffOrder, step }) => {
const diffIds = getters.unresolvedDiscussionsIdsOrdered(diffOrder);
const dateIds = getters.unresolvedDiscussionsIdsOrdered(false);
const ids = diffIds.length ? diffIds : dateIds;
const index = ids.indexOf(discussionId) + step;
if (index < 0 && step < 0) {
return ids[ids.length - 1];
}
if (index < 0 && step < 0) {
return ids[ids.length - 1];
}
if (index === ids.length && step > 0) {
return ids[0];
}
if (index === ids.length && step > 0) {
return ids[0];
}
return ids[index];
};
return ids[index];
};
// Gets the ID of the discussion following the one provided, respecting order (diff or date)
// @param {Boolean} discussionId - id of the current discussion

View File

@ -8,11 +8,8 @@ export const initOrganizationsActivity = () => {
const {
dataset: { appData },
} = el;
const {
organizationActivityPath,
organizationActivityEventTypes,
organizationActivityAllEvent,
} = convertObjectPropsToCamelCase(JSON.parse(appData));
const { organizationActivityPath, organizationActivityEventTypes, organizationActivityAllEvent } =
convertObjectPropsToCamelCase(JSON.parse(appData));
return new Vue({
el,

View File

@ -32,6 +32,7 @@ export const initOrganizationsGroupsAndProjects = () => {
projectsEmptyStateSvgPath,
groupsEmptyStateSvgPath,
newGroupPath,
groupsPath,
newProjectPath,
canCreateGroup,
canCreateProject,
@ -56,6 +57,7 @@ export const initOrganizationsGroupsAndProjects = () => {
projectsEmptyStateSvgPath,
groupsEmptyStateSvgPath,
newGroupPath,
groupsPath,
newProjectPath,
canCreateGroup,
canCreateProject,

View File

@ -11,11 +11,10 @@ export const initOrganizationsProjectsEdit = () => {
const {
dataset: { appData },
} = el;
const {
projectsOrganizationPath,
previewMarkdownPath,
project,
} = convertObjectPropsToCamelCase(JSON.parse(appData), { deep: true });
const { projectsOrganizationPath, previewMarkdownPath, project } = convertObjectPropsToCamelCase(
JSON.parse(appData),
{ deep: true },
);
return new Vue({
el,

View File

@ -13,12 +13,8 @@ export const initOrganizationsSettingsGeneral = () => {
const {
dataset: { appData },
} = el;
const {
organization,
organizationsPath,
rootUrl,
previewMarkdownPath,
} = convertObjectPropsToCamelCase(JSON.parse(appData));
const { organization, organizationsPath, rootUrl, previewMarkdownPath } =
convertObjectPropsToCamelCase(JSON.parse(appData));
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),

View File

@ -5,7 +5,7 @@ import { s__, __ } from '~/locale';
import GroupsList from '~/vue_shared/components/groups_list/groups_list.vue';
import { ACTION_DELETE } from '~/vue_shared/components/list_actions/constants';
import { DEFAULT_PER_PAGE } from '~/api';
import { deleteGroup } from 'ee_else_ce/rest_api';
import axios from '~/lib/utils/axios_utils';
import {
renderDeleteSuccessToast,
deleteParams,
@ -43,6 +43,7 @@ export default {
inject: {
organizationGid: {},
groupsEmptyStateSvgPath: {},
groupsPath: {},
},
props: {
shouldShowEmptyStateButtons: {
@ -172,7 +173,9 @@ export default {
try {
this.setGroupIsDeleting(nodeIndex, true);
await deleteGroup(group.id, deleteParams(group));
await axios.delete(this.groupsPath, {
params: { id: group.fullPath, ...deleteParams(group) },
});
this.$apollo.queries.groups.refetch();
renderDeleteSuccessToast(group, this.$options.i18n.group);
} catch (error) {

View File

@ -34,6 +34,7 @@ export const initOrganizationsShow = () => {
projectsEmptyStateSvgPath,
groupsEmptyStateSvgPath,
newGroupPath,
groupsPath,
newProjectPath,
associationCounts,
canCreateProject,
@ -57,6 +58,7 @@ export const initOrganizationsShow = () => {
projectsEmptyStateSvgPath,
groupsEmptyStateSvgPath,
newGroupPath,
groupsPath,
newProjectPath,
canCreateProject,
canCreateGroup,

View File

@ -11,14 +11,8 @@ export const initDependencyProxyApp = () => {
if (!el) {
return null;
}
const {
endpoint,
groupPath,
groupId,
noManifestsIllustration,
canClearCache,
settingsPath,
} = el.dataset;
const { endpoint, groupPath, groupId, noManifestsIllustration, canClearCache, settingsPath } =
el.dataset;
return new Vue({
el,
apolloProvider,

View File

@ -1,33 +1,35 @@
import { produce } from 'immer';
import getGroupPackagesSettingsQuery from '../queries/get_group_packages_settings.query.graphql';
export const updateGroupPackageSettings = (fullPath) => (client, { data: updatedData }) => {
const queryAndParams = {
query: getGroupPackagesSettingsQuery,
variables: { fullPath },
export const updateGroupPackageSettings =
(fullPath) =>
(client, { data: updatedData }) => {
const queryAndParams = {
query: getGroupPackagesSettingsQuery,
variables: { fullPath },
};
const sourceData = client.readQuery(queryAndParams);
const data = produce(sourceData, (draftState) => {
if (updatedData.updateNamespacePackageSettings) {
draftState.group.packageSettings = {
...updatedData.updateNamespacePackageSettings.packageSettings,
};
}
if (updatedData.updateDependencyProxySettings) {
draftState.group.dependencyProxySetting = {
...updatedData.updateDependencyProxySettings.dependencyProxySetting,
};
}
if (updatedData.updateDependencyProxyImageTtlGroupPolicy) {
draftState.group.dependencyProxyImageTtlPolicy = {
...updatedData.updateDependencyProxyImageTtlGroupPolicy.dependencyProxyImageTtlPolicy,
};
}
});
client.writeQuery({
...queryAndParams,
data,
});
};
const sourceData = client.readQuery(queryAndParams);
const data = produce(sourceData, (draftState) => {
if (updatedData.updateNamespacePackageSettings) {
draftState.group.packageSettings = {
...updatedData.updateNamespacePackageSettings.packageSettings,
};
}
if (updatedData.updateDependencyProxySettings) {
draftState.group.dependencyProxySetting = {
...updatedData.updateDependencyProxySettings.dependencyProxySetting,
};
}
if (updatedData.updateDependencyProxyImageTtlGroupPolicy) {
draftState.group.dependencyProxyImageTtlPolicy = {
...updatedData.updateDependencyProxyImageTtlGroupPolicy.dependencyProxyImageTtlPolicy,
};
}
});
client.writeQuery({
...queryAndParams,
data,
});
};

View File

@ -1,22 +1,24 @@
import { produce } from 'immer';
import expirationPolicyQuery from '../queries/get_expiration_policy.query.graphql';
export const updateContainerExpirationPolicy = (projectPath) => (client, { data: updatedData }) => {
const queryAndParams = {
query: expirationPolicyQuery,
variables: { projectPath },
};
const sourceData = client.readQuery(queryAndParams);
const data = produce(sourceData, (draftState) => {
draftState.project.containerExpirationPolicy = {
...draftState.project.containerExpirationPolicy,
...updatedData.updateContainerExpirationPolicy.containerExpirationPolicy,
export const updateContainerExpirationPolicy =
(projectPath) =>
(client, { data: updatedData }) => {
const queryAndParams = {
query: expirationPolicyQuery,
variables: { projectPath },
};
});
const sourceData = client.readQuery(queryAndParams);
client.writeQuery({
...queryAndParams,
data,
});
};
const data = produce(sourceData, (draftState) => {
draftState.project.containerExpirationPolicy = {
...draftState.project.containerExpirationPolicy,
...updatedData.updateContainerExpirationPolicy.containerExpirationPolicy,
};
});
client.writeQuery({
...queryAndParams,
data,
});
};

View File

@ -6,9 +6,8 @@ import initDeleteMergedBranches from '~/branches/init_delete_merged_branches';
import initBranchMoreActions from '~/branches/init_branch_more_actions';
import initSourceCodeDropdowns from '~/vue_shared/components/download_dropdown/init_download_dropdowns';
const { divergingCountsEndpoint, defaultBranch } = document.querySelector(
'.js-branch-list',
).dataset;
const { divergingCountsEndpoint, defaultBranch } =
document.querySelector('.js-branch-list').dataset;
initDiverganceGraph(divergingCountsEndpoint, defaultBranch);
BranchSortDropdown();

View File

@ -64,13 +64,8 @@ new Vue({
});
if (codeCoverageContainer?.dataset) {
const {
graphEndpoint,
graphEndDate,
graphStartDate,
graphRef,
graphCsvPath,
} = codeCoverageContainer.dataset;
const { graphEndpoint, graphEndDate, graphStartDate, graphRef, graphCsvPath } =
codeCoverageContainer.dataset;
// eslint-disable-next-line no-new
new Vue({
el: codeCoverageContainer,

View File

@ -10,14 +10,8 @@ export default class PerformanceBarService {
static registerInterceptor(peekUrl, callback) {
PerformanceBarService.interceptor = (response) => {
const [
fireCallback,
requestId,
requestUrl,
requestParams,
operationName,
methodVerb,
] = PerformanceBarService.callbackParams(response, peekUrl);
const [fireCallback, requestId, requestUrl, requestParams, operationName, methodVerb] =
PerformanceBarService.callbackParams(response, peekUrl);
if (fireCallback) {
callback(requestId, requestUrl, operationName, requestParams, methodVerb);

View File

@ -11,12 +11,8 @@ export const initProjectsExploreFilteredSearchAndSort = () => {
dataset: { appData },
} = el;
const {
initialSort,
programmingLanguages,
starredExploreProjectsPath,
exploreRootPath,
} = convertObjectPropsToCamelCase(JSON.parse(appData));
const { initialSort, programmingLanguages, starredExploreProjectsPath, exploreRootPath } =
convertObjectPropsToCamelCase(JSON.parse(appData));
return new Vue({
el,

View File

@ -13,13 +13,8 @@ const apolloProvider = new VueApollo({
export default function mountBranchRules(el) {
if (!el) return null;
const {
projectPath,
branchRulesPath,
showCodeOwners,
showStatusChecks,
showApprovers,
} = el.dataset;
const { projectPath, branchRulesPath, showCodeOwners, showStatusChecks, showApprovers } =
el.dataset;
return new Vue({
el,

View File

@ -8,13 +8,8 @@ export const initUploadFileTrigger = () => {
if (!uploadFileTriggerEl) return false;
const {
targetBranch,
originalBranch,
canPushCode,
path,
projectPath,
} = uploadFileTriggerEl.dataset;
const { targetBranch, originalBranch, canPushCode, path, projectPath } =
uploadFileTriggerEl.dataset;
return new Vue({
el: uploadFileTriggerEl,

View File

@ -27,9 +27,8 @@ export default class CustomMetrics extends PrometheusMetrics {
this.$monitoredCustomMetricsEmpty = this.$monitoredCustomMetricsPanel.find(
'.js-empty-custom-metrics',
);
this.$monitoredCustomMetricsList = this.$monitoredCustomMetricsPanel.find(
'.js-custom-metrics-list',
);
this.$monitoredCustomMetricsList =
this.$monitoredCustomMetricsPanel.find('.js-custom-metrics-list');
this.$monitoredCustomMetricsNoIntegrationText = this.$monitoredCustomMetricsPanel.find(
'.js-no-active-integration-text',
);
@ -46,9 +45,8 @@ export default class CustomMetrics extends PrometheusMetrics {
this.$monitoredCustomMetricsEmpty,
];
this.activeCustomMetricsEndpoint = this.$monitoredCustomMetricsPanel.data(
'active-custom-metrics',
);
this.activeCustomMetricsEndpoint =
this.$monitoredCustomMetricsPanel.data('active-custom-metrics');
this.environmentsDataEndpoint = this.$monitoredCustomMetricsPanel.data(
'environments-data-endpoint',
);

View File

@ -48,7 +48,8 @@ export default {
<template>
<div
:class="{
'issue-token gl-inline-flex gl-align-items-stretch gl-max-w-full gl-leading-24 gl-whitespace-nowrap': isCondensed,
'issue-token gl-inline-flex gl-align-items-stretch gl-max-w-full gl-leading-24 gl-whitespace-nowrap':
isCondensed,
'flex-row issuable-info-container': !isCondensed,
}"
>
@ -69,7 +70,8 @@ export default {
v-if="hasTitle"
ref="title"
:class="{
'issue-token-title issue-token-end gl-overflow-hidden gl-display-flex gl-align-items-baseline gl-text-gray-500 gl-pl-3': isCondensed,
'issue-token-title issue-token-end gl-overflow-hidden gl-display-flex gl-align-items-baseline gl-text-gray-500 gl-pl-3':
isCondensed,
'issue-title block-truncated': !isCondensed,
'gl-rounded-top-right-small gl-rounded-bottom-right-small gl-pr-3': !canRemove,
}"
@ -81,7 +83,8 @@ export default {
:is="innerComponentType"
ref="reference"
:class="{
'issue-token-reference gl-display-flex gl-align-items-center gl-rounded-top-left-small gl-rounded-bottom-left-small gl-px-3': isCondensed,
'issue-token-reference gl-display-flex gl-align-items-center gl-rounded-top-left-small gl-rounded-bottom-left-small gl-px-3':
isCondensed,
'issuable-info': !isCondensed,
}"
>
@ -103,7 +106,8 @@ export default {
ref="removeButton"
v-gl-tooltip
:class="{
'issue-token-remove-button gl-display-flex gl-align-items-center gl-px-3 gl-border-0 gl-rounded-top-right-small gl-rounded-bottom-right-small gl-text-gray-500': isCondensed,
'issue-token-remove-button gl-display-flex gl-align-items-center gl-px-3 gl-border-0 gl-rounded-top-right-small gl-rounded-bottom-right-small gl-text-gray-500':
isCondensed,
'btn btn-default': !isCondensed,
}"
:title="removeButtonLabel"

View File

@ -18,14 +18,16 @@ import * as types from './mutation_types';
class GraphQLError extends Error {}
const updateDraft = (action) => (store, ...args) => {
action(store, ...args);
const updateDraft =
(action) =>
(store, ...args) => {
action(store, ...args);
if (!store.state.isExistingRelease) {
store.dispatch('saveDraftRelease');
store.dispatch('saveDraftCreateFrom');
}
};
if (!store.state.isExistingRelease) {
store.dispatch('saveDraftRelease');
store.dispatch('saveDraftCreateFrom');
}
};
export const initializeRelease = ({ dispatch, state }) => {
if (state.isExistingRelease) {

View File

@ -175,13 +175,8 @@ export default function setupVueRepositoryList() {
if (!codeDropdownEl) return false;
const {
sshUrl,
httpUrl,
kerberosUrl,
xcodeUrl,
directoryDownloadLinks,
} = codeDropdownEl.dataset;
const { sshUrl, httpUrl, kerberosUrl, xcodeUrl, directoryDownloadLinks } =
codeDropdownEl.dataset;
return new Vue({
el: codeDropdownEl,

View File

@ -11,13 +11,8 @@ const sidebarInitState = () => {
const el = document.getElementById('js-search-sidebar');
if (!el) return {};
const {
navigationJson,
searchType,
searchLevel,
groupInitialJson,
projectInitialJson,
} = el.dataset;
const { navigationJson, searchType, searchLevel, groupInitialJson, projectInitialJson } =
el.dataset;
const navigationJsonParsed = JSON.parse(navigationJson);
const groupInitialJsonParsed = JSON.parse(groupInitialJson);

View File

@ -14,27 +14,29 @@ export const updateSecurityTrainingOptimisticResponse = (changes) => ({
},
});
export const updateSecurityTrainingCache = ({ query, variables }) => (cache, { data }) => {
const {
securityTrainingUpdate: { training: updatedProvider },
} = data;
const { project } = cache.readQuery({ query, variables });
if (!updatedProvider.isPrimary) {
return;
}
export const updateSecurityTrainingCache =
({ query, variables }) =>
(cache, { data }) => {
const {
securityTrainingUpdate: { training: updatedProvider },
} = data;
const { project } = cache.readQuery({ query, variables });
if (!updatedProvider.isPrimary) {
return;
}
// when we set a new primary provider, we need to unset the previous one(s)
const updatedProject = produce(project, (draft) => {
draft.securityTrainingProviders.forEach((provider) => {
// eslint-disable-next-line no-param-reassign
provider.isPrimary = provider.id === updatedProvider.id;
// when we set a new primary provider, we need to unset the previous one(s)
const updatedProject = produce(project, (draft) => {
draft.securityTrainingProviders.forEach((provider) => {
// eslint-disable-next-line no-param-reassign
provider.isPrimary = provider.id === updatedProvider.id;
});
});
});
// write to the cache
cache.writeQuery({
query,
variables,
data: { project: updatedProject },
});
};
// write to the cache
cache.writeQuery({
query,
variables,
data: { project: updatedProject },
});
};

View File

@ -8,14 +8,8 @@ export default class SidebarMilestone {
if (!el) return;
const {
timeEstimate,
timeSpent,
humanTimeEstimate,
humanTimeSpent,
limitToHours,
iid,
} = el.dataset;
const { timeEstimate, timeSpent, humanTimeEstimate, humanTimeSpent, limitToHours, iid } =
el.dataset;
// eslint-disable-next-line no-new
new Vue({

View File

@ -547,15 +547,8 @@ function mountSidebarSubscriptionsWidget() {
function mountSidebarTimeTracking() {
const el = document.querySelector('.js-sidebar-time-tracking-root');
const {
id,
iid,
fullPath,
issuableType,
timeTrackingLimitToHours,
canCreateTimelogs,
editable,
} = getSidebarOptions();
const { id, iid, fullPath, issuableType, timeTrackingLimitToHours, canCreateTimelogs, editable } =
getSidebarOptions();
if (!el) {
return null;

View File

@ -54,13 +54,8 @@ const getTrialStatusWidgetData = (sidebarData) => {
sidebarData.duo_pro_trial_status_widget_data_attrs &&
sidebarData.duo_pro_trial_status_popover_data_attrs
) {
const {
containerId,
trialDaysUsed,
trialDuration,
percentageComplete,
widgetUrl,
} = convertObjectPropsToCamelCase(sidebarData.duo_pro_trial_status_widget_data_attrs);
const { containerId, trialDaysUsed, trialDuration, percentageComplete, widgetUrl } =
convertObjectPropsToCamelCase(sidebarData.duo_pro_trial_status_widget_data_attrs);
const { daysRemaining, trialEndDate, purchaseNowUrl } = convertObjectPropsToCamelCase(
sidebarData.duo_pro_trial_status_popover_data_attrs,
@ -108,14 +103,8 @@ export const initSuperSidebar = () => {
const commandPaletteLinks = convertObjectPropsToCamelCase(sidebarData.current_menu_items || []);
const contextSwitcherLinks = sidebarData.context_switcher_links;
const {
searchPath,
issuesPath,
mrPath,
autocompletePath,
settingsPath,
searchContext,
} = searchData;
const { searchPath, issuesPath, mrPath, autocompletePath, settingsPath, searchContext } =
searchData;
const isImpersonating = parseBoolean(sidebarData.is_impersonating);
const isGroup = Boolean(sidebarData.current_context?.namespace === CONTEXT_NAMESPACE_GROUPS);

View File

@ -7,13 +7,8 @@ export const initUserActionsApp = () => {
if (!mountingEl) return false;
const {
userId,
rssSubscriptionPath,
reportAbusePath,
reportedUserId,
reportedFromUrl,
} = mountingEl.dataset;
const { userId, rssSubscriptionPath, reportAbusePath, reportedUserId, reportedFromUrl } =
mountingEl.dataset;
Vue.use(GlToast);

Some files were not shown because too many files have changed in this diff Show More