Skip to content

Commit

Permalink
#38: rework conflict calculation and conflict details modal
Browse files Browse the repository at this point in the history
  • Loading branch information
m4nv3ru committed Jan 8, 2023
1 parent 48d27a5 commit eca9ae5
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,19 @@ export default class ConflictDetailsModal extends React.Component {
content = <FileDetails fileDetails={fileDetails} isFileDetailsProcessing={isFileDetailsProcessing} />;
}

function navigateToFiles() {
displayConflictDetails(Object.assign(selectedConflict, { overviewType: 'files' }));
}

return (
<div className={this.styles.darkBG} onClick={e => closeModal(e)}>
<div className={this.styles.modal}>
<div className={this.styles.header}>
{overviewType === 'fileDetails' &&
<i className={this.styles.backIcon + ' fas fa-caret-left'} title="Go back to file list" onClick={() => navigateToFiles()} />}
{overviewType === 'files' && <i />}
<b>Conflict Details</b>
<i className={this.styles.closeIcon + ' fas fa-times'} onClick={() => close()} title="Close Details Modal" />
</div>
{content}
<div className={this.styles.footer}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,6 @@
border-radius: 5px;
box-shadow: 0 5px 20px 0 rgba(0, 0, 0, 0.04);

.header {
margin-top: 15px;
font-size: 2rem;
display: flex;
align-items: center;
flex-direction: row;
justify-content: center;
}
.footer {
display: flex;
justify-content: end;
Expand All @@ -51,17 +43,28 @@
}
}
}
.header {
margin-top: 15px;
font-size: 2rem;
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
}

.backIcon {
margin-left: 17px;
cursor: pointer;
}
.closeIcon {
margin-right: 17px;
cursor: pointer;
}
.modalBody {}

.item{
margin-left: 15px;
}
.header {
display: flex;
align-items: center;
flex-direction: row;
}
.fileBody {
margin-left: 35px;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,40 @@ export default class FileDetails extends React.Component {
this.styles = Object.assign({}, styles);
}

renderError(error) {
return (
<div>
<span>Could not load conflict details. Reason: </span>
<span>
{error}
</span>
</div>
);
}

renderLoadingIndicator() {
return (
<div className={this.styles.loadingWrapper}>
<div className={this.styles.loadingIcon}>
{LOADING_ICON}
</div>
<div>Loading file conflict details</div>
</div>
);
}

render() {
const { isFileDetailsProcessing, fileDetails: { selectedConflict, repositoryUrl } } = this.props;
const { isFileDetailsProcessing, fileDetails: { selectedConflict, repositoryUrl, fetchError } } = this.props;
const { conflictBranch, selectedBranch, selectedFile } = selectedConflict;
console.log(selectedConflict);
console.log(selectedConflict, this.props.fileDetails);

if (isFileDetailsProcessing) {
return (
<div className={this.styles.loadingWrapper}>
<div className={this.styles.loadingIcon}>
{LOADING_ICON}
</div>
<div>Loading file conflict details</div>
</div>
);
return this.renderLoadingIndicator();
}
if (fetchError) {
return this.renderError(fetchError);
}

return (
<div>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export default class ConflictOverview extends React.Component {
render() {
const { conflicts } = this.props;
const participantsTag = conflicts.length > 1 ? 'participants' : 'participant';

const handleContentMouseOver = () => {
clearTimeout(this.state.contentCloseTimeout);
this.setState({ showContent: true });
Expand Down
62 changes: 45 additions & 17 deletions ui/src/visualizations/team-awareness/sagas/conflictCalculations.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const analyseConflictsFromAppState = async appState => {

if (config.selectedConflictBranch === 'not_set' || config.selectedConflictBranch === config.selectedBranch) {
console.debug('nothing to do');
return { conflicts: null };
return { conflicts: [] };
}

const changedFiles = extractChangedFiles(data.data.files, config);
Expand All @@ -35,7 +35,7 @@ const analyseConflictsFromAppState = async appState => {
if (conflictingStakeholders.length === 0) continue;

for (const s of conflictingStakeholders) {
const { conflictStakeholder, otherStakeholder } = s;
const { conflictStakeholder, otherStakeholder, hunks, changes } = s;

const combined = `${conflictStakeholder.stakeholder.id}${otherStakeholder.stakeholder.id}`;
if (!stakeholders.has(combined)) {
Expand All @@ -48,9 +48,18 @@ const analyseConflictsFromAppState = async appState => {
}

if (!stakeholders.get(combined).files.has(file.path)) {
stakeholders.get(combined).files.set(file.path, { file: { path: file.path, url: file.webUrl }, branches: [] });
stakeholders.get(combined).files.set(file.path, {
file: { path: file.path, url: file.webUrl },
branches: [],
changes: new Map()
});
}
stakeholders.get(combined).files.get(file.path).branches.push(branch);
stakeholders.get(combined).files.get(file.path).changes.set(branch, {
branch: branch,
conflicting: changes.conflicting,
other: changes.other
});
}
}
}
Expand Down Expand Up @@ -116,41 +125,60 @@ const checkBranchConflicts = (conflictBranchContributors, otherContributors) =>
const detectedBranchConflicts = [];
for (const conflictContributor of conflictBranchContributors) {
for (const otherContributor of otherContributors) {
if (checkContributorConflict(conflictContributor, otherContributor)) {
detectedBranchConflicts.push({ conflictStakeholder: conflictContributor, otherStakeholder: otherContributor });
const conflictingChanges = checkContributorConflict(conflictContributor, otherContributor);
if (conflictingChanges.conflicting.length > 0) {
detectedBranchConflicts.push({
conflictStakeholder: conflictContributor,
otherStakeholder: otherContributor,
changes: conflictingChanges
});
}
}
}
return detectedBranchConflicts;
};

const checkContributorConflict = (conflictContributor, otherContributor) => {
const conflictChanges = [];
const otherChanges = [];

for (const conflictHunk of conflictContributor.hunks) {
for (const otherHunk of otherContributor.hunks) {
if (checkHunkConflict(conflictHunk, otherHunk)) {
return true;
const changes = checkHunkConflict(conflictHunk, otherHunk);
if (changes.conflictingChanges.length > 0 || changes.otherChanges.length > 0) {
conflictChanges.push(...changes.conflictingChanges);
otherChanges.push(...changes.otherChanges);
}
}
}
return false;

return {
conflicting: conflictChanges,
other: otherChanges
};
};

const checkHunkConflict = (conflictHunk, otherHunk) => {
const conflictingHunks = new Set();
const otherHunks = new Set();

for (const conflictChanges of conflictHunk) {
for (const otherChanges of otherHunk) {
if (conflictChanges.newStart >= otherChanges.oldStart && conflictChanges.newStart <= otherChanges.oldStart + otherChanges.oldLines) {
return true;
if (conflictChanges.newStart < otherChanges.oldStart || conflictChanges.newStart > otherChanges.oldStart + otherChanges.oldLines) {
continue;
}

if (
otherChanges.newStart >= conflictChanges.oldStart &&
otherChanges.newStart <= conflictChanges.oldStart + conflictChanges.oldLines
) {
return true;
if (otherChanges.newStart < conflictChanges.oldStart && otherChanges.newStart > conflictChanges.oldStart + conflictChanges.oldLines) {
continue;
}

conflictingHunks.add(conflictChanges);
otherHunks.add(otherChanges);
}
}
return false;
return {
conflictingChanges: Array.from(conflictingHunks),
otherChanges: Array.from(otherHunks)
};
};

export { processConflictBranchSelection };
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const analyseFileConflictDetails = async appState => {
const { data: { data: { fileDetails } } } = getState(appState);

const { selectedConflict: { files, selectedBranch, conflictBranch, selectedFile } } = fileDetails;
const { file: file } = files.get(selectedFile);
const { file, changes } = files.get(selectedFile);

const blobIndex = file.url.indexOf('blob/');
if (!githubExpression.test(file.url) || blobIndex === -1) {
Expand All @@ -33,34 +33,65 @@ const analyseFileConflictDetails = async appState => {
const githubContentUrl = repositoryUrl.replace('github.com', 'raw.githubusercontent.com');

const results = await Promise.all([
fetch(`${githubContentUrl}${conflictBranch}/${file.path}`, { mode: 'cors' }),
fetch(`${githubContentUrl}${selectedBranch}/${file.path}`, { mode: 'cors' })
fetch(`${githubContentUrl}${conflictBranch}/${file.path}`, { mode: 'cors' })
]);
if (results.filter(response => response.status >= 400).length >= 1) {
return {
fileDetails: {
selectedConflict: fileDetails.selectedConflict,
fetchError: 'Could not fetch file details from Github'
fetchError: 'Could not fetch files from Github'
}
};
}
const resultData = await Promise.all(results.map(r => r.text()));
try {
const trees = resultData.map(d => MyParser.parse(d, { ecmaVersion: 2020, sourceType: 'module', locations: true }));
const changedNodes = getChangedAstNodes(trees[0], changes, conflictBranch);

fileDetails.trees = trees;


fileDetails.changes = changedNodes;
} catch (e) {
fileDetails.parsingError = e;
console.error(e);
}

// TODO: Process file details conflict
// Compare them
// Give feedback according to the AST data

fileDetails.repositoryUrl = repositoryUrl + 'blob/';
fileDetails.testData = resultData;
return { fileDetails };
};

const splitPascalCase = text => {
const result = [];
for (let i = 0; i < text.length; i++) {
if (text[i] === text[i].toUpperCase()) {
result.push(text[i]);
} else {
if (result.length > 0) {
result[result.length - 1] += text[i];
} else {
result.push(text[i]);
}
}
}
return result;
};

function getChangedAstNodes(ast, changes, selectedBranch) {
const changedNodes = [];

for (const node of ast.body) {
for (const change of changes.get(selectedBranch).other) {
if (node.loc.end.line < change.newStart && node.loc.end.line < change.oldStart) {
continue;
}
if (node.loc.start.line > change.newStart + change.newLines && node.loc.start.line > change.oldStart + change.oldLines) {
continue;
}
changedNodes.push(node);
break;
}
}

return changedNodes;
}

export { processFileConflictDetails };

0 comments on commit eca9ae5

Please sign in to comment.