debian-mirror-gitlab/app/assets/javascripts/merge_conflicts/merge_conflict_store.js

434 lines
12 KiB
JavaScript
Raw Normal View History

2020-03-13 15:44:24 +05:30
/* eslint-disable no-param-reassign, babel/camelcase, no-nested-ternary, no-continue */
2017-08-17 22:00:37 +05:30
2018-05-09 12:01:36 +05:30
import $ from 'jquery';
2017-08-17 22:00:37 +05:30
import Vue from 'vue';
import Cookies from 'js-cookie';
2019-07-31 22:56:46 +05:30
import { s__ } from '~/locale';
2017-08-17 22:00:37 +05:30
2018-12-13 13:39:08 +05:30
(global => {
2016-11-03 12:29:30 +05:30
global.mergeConflicts = global.mergeConflicts || {};
2017-08-17 22:00:37 +05:30
const diffViewType = Cookies.get('diff_view');
2019-07-31 22:56:46 +05:30
const HEAD_HEADER_TEXT = s__('MergeConflict|HEAD//our changes');
const ORIGIN_HEADER_TEXT = s__('MergeConflict|origin//their changes');
const HEAD_BUTTON_TITLE = s__('MergeConflict|Use ours');
const ORIGIN_BUTTON_TITLE = s__('MergeConflict|Use theirs');
2016-11-03 12:29:30 +05:30
const INTERACTIVE_RESOLVE_MODE = 'interactive';
const EDIT_RESOLVE_MODE = 'edit';
const DEFAULT_RESOLVE_MODE = INTERACTIVE_RESOLVE_MODE;
const VIEW_TYPES = {
INLINE: 'inline',
2018-12-13 13:39:08 +05:30
PARALLEL: 'parallel',
2016-11-03 12:29:30 +05:30
};
const CONFLICT_TYPES = {
TEXT: 'text',
2018-12-13 13:39:08 +05:30
TEXT_EDITOR: 'text-editor',
2016-11-03 12:29:30 +05:30
};
global.mergeConflicts.mergeConflictsStore = {
state: {
isLoading: true,
hasError: false,
isSubmitting: false,
isParallel: diffViewType === VIEW_TYPES.PARALLEL,
2019-12-04 20:38:33 +05:30
diffViewType,
2018-12-13 13:39:08 +05:30
conflictsData: {},
2016-11-03 12:29:30 +05:30
},
setConflictsData(data) {
this.decorateFiles(data.files);
this.state.conflictsData = {
files: data.files,
commitMessage: data.commit_message,
sourceBranch: data.source_branch,
targetBranch: data.target_branch,
shortCommitSha: data.commit_sha.slice(0, 7),
};
},
decorateFiles(files) {
2018-12-13 13:39:08 +05:30
files.forEach(file => {
2016-11-03 12:29:30 +05:30
file.content = '';
file.resolutionData = {};
file.promptDiscardConfirmation = false;
file.resolveMode = DEFAULT_RESOLVE_MODE;
file.filePath = this.getFilePath(file);
file.iconClass = `fa-${file.blob_icon}`;
file.blobPath = file.blob_path;
if (file.type === CONFLICT_TYPES.TEXT) {
file.showEditor = false;
file.loadEditor = false;
this.setInlineLine(file);
this.setParallelLine(file);
} else if (file.type === CONFLICT_TYPES.TEXT_EDITOR) {
file.showEditor = true;
file.loadEditor = true;
}
});
},
setInlineLine(file) {
file.inlineLines = [];
2018-12-13 13:39:08 +05:30
file.sections.forEach(section => {
2016-11-03 12:29:30 +05:30
let currentLineType = 'new';
const { conflict, lines, id } = section;
if (conflict) {
file.inlineLines.push(this.getHeadHeaderLine(id));
}
2018-12-13 13:39:08 +05:30
lines.forEach(line => {
2016-11-03 12:29:30 +05:30
const { type } = line;
if ((type === 'new' || type === 'old') && currentLineType !== type) {
currentLineType = type;
file.inlineLines.push({ lineType: 'emptyLine', richText: '' });
}
this.decorateLineForInlineView(line, id, conflict);
file.inlineLines.push(line);
2017-08-17 22:00:37 +05:30
});
2016-11-03 12:29:30 +05:30
if (conflict) {
file.inlineLines.push(this.getOriginHeaderLine(id));
}
});
},
setParallelLine(file) {
file.parallelLines = [];
const linesObj = { left: [], right: [] };
2018-12-13 13:39:08 +05:30
file.sections.forEach(section => {
2016-11-03 12:29:30 +05:30
const { conflict, lines, id } = section;
if (conflict) {
linesObj.left.push(this.getOriginHeaderLine(id));
linesObj.right.push(this.getHeadHeaderLine(id));
}
2018-12-13 13:39:08 +05:30
lines.forEach(line => {
2016-11-03 12:29:30 +05:30
const { type } = line;
if (conflict) {
if (type === 'old') {
linesObj.left.push(this.getLineForParallelView(line, id, 'conflict'));
} else if (type === 'new') {
linesObj.right.push(this.getLineForParallelView(line, id, 'conflict', true));
}
} else {
const lineType = type || 'context';
2017-08-17 22:00:37 +05:30
linesObj.left.push(this.getLineForParallelView(line, id, lineType));
2016-11-03 12:29:30 +05:30
linesObj.right.push(this.getLineForParallelView(line, id, lineType, true));
}
});
this.checkLineLengths(linesObj);
});
2017-08-17 22:00:37 +05:30
for (let i = 0, len = linesObj.left.length; i < len; i += 1) {
2018-12-13 13:39:08 +05:30
file.parallelLines.push([linesObj.right[i], linesObj.left[i]]);
2016-11-03 12:29:30 +05:30
}
},
setLoadingState(state) {
this.state.isLoading = state;
},
setErrorState(state) {
this.state.hasError = state;
},
setFailedRequest(message) {
this.state.hasError = true;
this.state.conflictsData.errorMessage = message;
},
getConflictsCount() {
if (!this.state.conflictsData.files.length) {
return 0;
}
2018-11-08 19:23:39 +05:30
const { files } = this.state.conflictsData;
2016-11-03 12:29:30 +05:30
let count = 0;
2018-12-13 13:39:08 +05:30
files.forEach(file => {
2016-11-03 12:29:30 +05:30
if (file.type === CONFLICT_TYPES.TEXT) {
2018-12-13 13:39:08 +05:30
file.sections.forEach(section => {
2016-11-03 12:29:30 +05:30
if (section.conflict) {
2017-08-17 22:00:37 +05:30
count += 1;
2016-11-03 12:29:30 +05:30
}
});
} else {
2017-08-17 22:00:37 +05:30
count += 1;
2016-11-03 12:29:30 +05:30
}
});
return count;
},
getConflictsCountText() {
const count = this.getConflictsCount();
2019-07-31 22:56:46 +05:30
const text = count > 1 ? s__('MergeConflict|conflicts') : s__('MergeConflict|conflict');
2016-11-03 12:29:30 +05:30
return `${count} ${text}`;
},
setViewType(viewType) {
this.state.diffView = viewType;
this.state.isParallel = viewType === VIEW_TYPES.PARALLEL;
2017-08-17 22:00:37 +05:30
Cookies.set('diff_view', viewType);
2016-11-03 12:29:30 +05:30
},
getHeadHeaderLine(id) {
return {
2019-12-04 20:38:33 +05:30
id,
2016-11-03 12:29:30 +05:30
richText: HEAD_HEADER_TEXT,
buttonTitle: HEAD_BUTTON_TITLE,
type: 'new',
section: 'head',
isHeader: true,
isHead: true,
isSelected: false,
2018-12-13 13:39:08 +05:30
isUnselected: false,
2016-11-03 12:29:30 +05:30
};
},
decorateLineForInlineView(line, id, conflict) {
const { type } = line;
line.id = id;
line.hasConflict = conflict;
line.isHead = type === 'new';
line.isOrigin = type === 'old';
line.hasMatch = type === 'match';
line.richText = line.rich_text;
line.isSelected = false;
line.isUnselected = false;
},
getLineForParallelView(line, id, lineType, isHead) {
const { old_line, new_line, rich_text } = line;
const hasConflict = lineType === 'conflict';
return {
id,
lineType,
hasConflict,
isHead: hasConflict && isHead,
isOrigin: hasConflict && !isHead,
hasMatch: lineType === 'match',
lineNumber: isHead ? new_line : old_line,
section: isHead ? 'head' : 'origin',
richText: rich_text,
isSelected: false,
2018-12-13 13:39:08 +05:30
isUnselected: false,
2016-11-03 12:29:30 +05:30
};
},
getOriginHeaderLine(id) {
return {
2019-12-04 20:38:33 +05:30
id,
2016-11-03 12:29:30 +05:30
richText: ORIGIN_HEADER_TEXT,
buttonTitle: ORIGIN_BUTTON_TITLE,
type: 'old',
section: 'origin',
isHeader: true,
isOrigin: true,
isSelected: false,
2018-12-13 13:39:08 +05:30
isUnselected: false,
2016-11-03 12:29:30 +05:30
};
},
getFilePath(file) {
const { old_path, new_path } = file;
return old_path === new_path ? new_path : `${old_path}${new_path}`;
},
checkLineLengths(linesObj) {
2017-08-17 22:00:37 +05:30
const { left, right } = linesObj;
2016-11-03 12:29:30 +05:30
if (left.length !== right.length) {
if (left.length > right.length) {
const diff = left.length - right.length;
2017-08-17 22:00:37 +05:30
for (let i = 0; i < diff; i += 1) {
2016-11-03 12:29:30 +05:30
right.push({ lineType: 'emptyLine', richText: '' });
}
} else {
const diff = right.length - left.length;
2017-08-17 22:00:37 +05:30
for (let i = 0; i < diff; i += 1) {
2016-11-03 12:29:30 +05:30
left.push({ lineType: 'emptyLine', richText: '' });
}
}
}
},
setPromptConfirmationState(file, state) {
file.promptDiscardConfirmation = state;
},
setFileResolveMode(file, mode) {
if (mode === INTERACTIVE_RESOLVE_MODE) {
file.showEditor = false;
} else if (mode === EDIT_RESOLVE_MODE) {
// Restore Interactive mode when switching to Edit mode
file.showEditor = true;
file.loadEditor = true;
file.resolutionData = {};
this.restoreFileLinesState(file);
}
file.resolveMode = mode;
},
restoreFileLinesState(file) {
2018-12-13 13:39:08 +05:30
file.inlineLines.forEach(line => {
2016-11-03 12:29:30 +05:30
if (line.hasConflict || line.isHeader) {
line.isSelected = false;
line.isUnselected = false;
}
});
2018-12-13 13:39:08 +05:30
file.parallelLines.forEach(lines => {
2016-11-03 12:29:30 +05:30
const left = lines[0];
const right = lines[1];
const isLeftMatch = left.hasConflict || left.isHeader;
const isRightMatch = right.hasConflict || right.isHeader;
if (isLeftMatch || isRightMatch) {
left.isSelected = false;
left.isUnselected = false;
right.isSelected = false;
right.isUnselected = false;
}
});
},
isReadyToCommit() {
2018-11-08 19:23:39 +05:30
const { files } = this.state.conflictsData;
2016-11-03 12:29:30 +05:30
const hasCommitMessage = $.trim(this.state.conflictsData.commitMessage).length;
let unresolved = 0;
2017-08-17 22:00:37 +05:30
for (let i = 0, l = files.length; i < l; i += 1) {
const file = files[i];
2016-11-03 12:29:30 +05:30
if (file.resolveMode === INTERACTIVE_RESOLVE_MODE) {
let numberConflicts = 0;
2017-08-17 22:00:37 +05:30
const resolvedConflicts = Object.keys(file.resolutionData).length;
2016-11-03 12:29:30 +05:30
// We only check for conflicts type 'text'
// since conflicts `text_editor` can´t be resolved in interactive mode
if (file.type === CONFLICT_TYPES.TEXT) {
2017-08-17 22:00:37 +05:30
for (let j = 0, k = file.sections.length; j < k; j += 1) {
2016-11-03 12:29:30 +05:30
if (file.sections[j].conflict) {
2017-08-17 22:00:37 +05:30
numberConflicts += 1;
2016-11-03 12:29:30 +05:30
}
}
if (resolvedConflicts !== numberConflicts) {
2017-08-17 22:00:37 +05:30
unresolved += 1;
2016-11-03 12:29:30 +05:30
}
}
} else if (file.resolveMode === EDIT_RESOLVE_MODE) {
// Unlikely to happen since switching to Edit mode saves content automatically.
// Checking anyway in case the save strategy changes in the future
if (!file.content) {
2017-08-17 22:00:37 +05:30
unresolved += 1;
2016-11-03 12:29:30 +05:30
continue;
}
}
}
return !this.state.isSubmitting && hasCommitMessage && !unresolved;
},
getCommitButtonText() {
2019-07-31 22:56:46 +05:30
const initial = s__('MergeConflict|Commit to source branch');
const inProgress = s__('MergeConflict|Committing...');
2016-11-03 12:29:30 +05:30
2018-12-13 13:39:08 +05:30
return this.state ? (this.state.isSubmitting ? inProgress : initial) : initial;
2016-11-03 12:29:30 +05:30
},
getCommitData() {
let commitData = {};
commitData = {
commit_message: this.state.conflictsData.commitMessage,
2018-12-13 13:39:08 +05:30
files: [],
2016-11-03 12:29:30 +05:30
};
2018-12-13 13:39:08 +05:30
this.state.conflictsData.files.forEach(file => {
2017-08-17 22:00:37 +05:30
const addFile = {
2016-11-03 12:29:30 +05:30
old_path: file.old_path,
2018-12-13 13:39:08 +05:30
new_path: file.new_path,
2016-11-03 12:29:30 +05:30
};
if (file.type === CONFLICT_TYPES.TEXT) {
// Submit only one data for type of editing
if (file.resolveMode === INTERACTIVE_RESOLVE_MODE) {
addFile.sections = file.resolutionData;
} else if (file.resolveMode === EDIT_RESOLVE_MODE) {
addFile.content = file.content;
}
} else if (file.type === CONFLICT_TYPES.TEXT_EDITOR) {
addFile.content = file.content;
}
commitData.files.push(addFile);
});
return commitData;
},
handleSelected(file, sectionId, selection) {
Vue.set(file.resolutionData, sectionId, selection);
2018-12-13 13:39:08 +05:30
file.inlineLines.forEach(line => {
2016-11-03 12:29:30 +05:30
if (line.id === sectionId && (line.hasConflict || line.isHeader)) {
this.markLine(line, selection);
}
});
2018-12-13 13:39:08 +05:30
file.parallelLines.forEach(lines => {
2016-11-03 12:29:30 +05:30
const left = lines[0];
const right = lines[1];
const hasSameId = right.id === sectionId || left.id === sectionId;
const isLeftMatch = left.hasConflict || left.isHeader;
const isRightMatch = right.hasConflict || right.isHeader;
if (hasSameId && (isLeftMatch || isRightMatch)) {
this.markLine(left, selection);
this.markLine(right, selection);
}
});
},
markLine(line, selection) {
if (selection === 'head' && line.isHead) {
line.isSelected = true;
line.isUnselected = false;
} else if (selection === 'origin' && line.isOrigin) {
line.isSelected = true;
line.isUnselected = false;
} else {
line.isSelected = false;
line.isUnselected = true;
}
},
setSubmitState(state) {
this.state.isSubmitting = state;
},
fileTextTypePresent() {
return this.state.conflictsData.files.some(f => f.type === CONFLICT_TYPES.TEXT);
2018-12-13 13:39:08 +05:30
},
2016-11-03 12:29:30 +05:30
};
})(window.gl || (window.gl = {}));