Skip to content

Commit

Permalink
#38 fix conflict detection and add ast parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
m4nv3ru committed Nov 30, 2022
1 parent cf72719 commit 48d27a5
Show file tree
Hide file tree
Showing 9 changed files with 262 additions and 139 deletions.
123 changes: 106 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^5.10.2",
"@grpc/proto-loader": "^0.5.4",
"abstract-syntax-tree": "^2.20.6",
"acorn": "^8.8.1",
"acorn-jsx": "^5.3.2",
"acorn-walk": "^8.2.0",
"adm-zip": "^0.4.13",
"apollo-client": "^1.9.3",
"apollo-client-preset": "0.1.0-1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,17 @@ export default class ConflictFile extends React.Component {
}

render() {
const { filePath, conflicts, displayConflictDetails, startFileConflictDetails } = this.props;

const { filePath, conflict, displayConflictDetails, startFileConflictDetails } = this.props;
const fileIcon = filePath.endsWith('.js') ? TEXT_DOCUMENT_ICON : EMPTY_DOCUMENT_ICON;
const showInfoIcon = filePath.endsWith('.js');

const showFileDetails = conflict => {
startFileConflictDetails(conflict);
displayConflictDetails(Object.assign({ overviewType: 'fileDetails' }, conflict));
const showFileDetails = branch => {
startFileConflictDetails(Object.assign(conflict, { selectedBranch: branch }));
displayConflictDetails(Object.assign(conflict, { overviewType: 'fileDetails', selectedBranch: branch }));
};

const { branches } = conflict.files.get(conflict.selectedFile);

return (
<div>
<div className={this.styles.item}>
Expand All @@ -32,20 +33,20 @@ export default class ConflictFile extends React.Component {
</div>
<div className={this.styles.fileBody}>
<small>
Conflicts on {conflicts.length} branch{conflicts.length === 1 ? '' : 'es'}
Conflicts on {branches.length} branch{branches.length === 1 ? '' : 'es'}
</small>
<div>
{conflicts.map(c =>
<div key={`file_branch_${c.otherStakeholder.branch}`} className={this.styles.branch}>
{branches.map(branch =>
<div key={`file_branch_${branch}`} className={this.styles.branch}>
<div className={this.styles.branchIcon}>
{GIT_BRANCH_ICON}
</div>
<div className={this.styles.branchTextContainer}>
<div className={this.styles.branchText}>
{c.otherStakeholder.branch}
{branch}
</div>
{showInfoIcon &&
<button className={this.styles.branchInfoIcon} onClick={() => showFileDetails(c)} title="View conflicts">
<button className={this.styles.branchInfoIcon} onClick={() => showFileDetails(branch)} title="View conflicts">
{MAGNIFY_DOCUMENT_ICON}
</button>}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@ export default class FileDetails extends React.Component {
}

render() {
const { isFileDetailsProcessing, fileDetails: { selectedConflict } } = this.props;
const { conflictStakeholder, otherStakeholder } = selectedConflict;

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

if (isFileDetailsProcessing) {
return (
Expand All @@ -27,7 +26,14 @@ export default class FileDetails extends React.Component {
return (
<div>
<div>
Conflict between branches <a>{conflictStakeholder.branch}</a> and <a>{otherStakeholder.branch}</a>
{'Conflict between branches '}
<a href={`${repositoryUrl}${conflictBranch}/${selectedFile}`}>
{conflictBranch}
</a>
{'and '}
<a href={`${repositoryUrl}${selectedBranch}/${selectedFile}`}>
{selectedBranch}
</a>
</div>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,18 @@ export default class FileOverview extends React.Component {
this.styles = Object.assign({}, styles);
}

getUniqueFiles(selectedConflict) {
const files = new Map();

selectedConflict.conflicts.forEach(c => {
if (!files.has(c.file.path)) {
files.set(c.file.path, []);
}

files.get(c.file.path).push(c);
});

return files;
}

render() {
const { selectedConflict, displayConflictDetails, startFileConflictDetails } = this.props;

const fileEntries = [];
for (const [filePath, conflicts] of this.getUniqueFiles(selectedConflict)) {
for (const [filePath, file] of selectedConflict.files) {
fileEntries.push(
<ConflictFile
startFileConflictDetails={startFileConflictDetails}
displayConflictDetails={displayConflictDetails}
filePath={filePath}
key={`conflicted_file_${filePath}`}
conflicts={conflicts}
conflict={Object.assign(selectedConflict, { selectedFile: file.file.path })}
/>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,33 +15,8 @@ export default class ConflictOverview extends React.Component {
};
}

reduceConflictsToStakeholders() {
const conflictedFiles = this.props.conflicts ? this.props.conflicts : [];
const conflicts = new Map();

for (const conflictedFile of conflictedFiles) {
for (const branch of conflictedFile.data) {
for (const conflict of branch.conflicts) {
const participants = `${conflict.conflictStakeholder.id}${conflict.otherStakeholder.id}`;
if (conflict.conflictStakeholder.id === conflict.otherStakeholder.id) continue;
if (!conflicts.has(participants)) {
conflicts.set(participants, {
conflictStakeholder: conflict.conflictStakeholder,
otherStakeholder: conflict.otherStakeholder,
conflicts: [conflict],
file: conflictedFile
});
} else {
conflicts.get(participants).conflicts.push(conflict);
}
}
}
}
return Array.from(conflicts.values());
}

render() {
const conflicts = this.reduceConflictsToStakeholders();
const { conflicts } = this.props;
const participantsTag = conflicts.length > 1 ? 'participants' : 'participant';

const handleContentMouseOver = () => {
Expand Down Expand Up @@ -72,7 +47,6 @@ export default class ConflictOverview extends React.Component {
</div>
);
}

if (conflicts.length === 0) {
return (
<div className={[this.styles.conflictOverview, this.styles.conflictOverviewHeader].join(' ')}>
Expand Down
12 changes: 8 additions & 4 deletions ui/src/visualizations/team-awareness/reducers/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ export default handleActions(
PROCESS_TEAM_AWARENESS_DATA: (state, action) => _.assign({}, state, { data: _.assign({}, state.data, action.payload) }),
PROCESS_TEAM_AWARENESS_FILE_BROWSER: (state, action) => _.assign({}, state, { data: _.assign({}, state.data, action.payload) }),
START_TEAM_AWARENESS_CONFLICT_PROCESSING: state => Object.assign({}, state, { isConflictsProcessing: true }),
RECEIVE_TEAM_AWARENESS_CONFLICTS: (state, action) =>
Object.assign({}, state, { isConflictsProcessing: false, data: Object.assign(state.data, action.payload) }),
RECEIVE_TEAM_AWARENESS_CONFLICTS: (state, action) => {
return Object.assign({}, state, { isConflictsProcessing: false, data: Object.assign(state.data, action.payload) });
},
START_TEAM_AWARENESS_FILE_CONFLICT_DETAILS_PROCESSING: (state, action) =>
Object.assign({}, state, { isFileDetailsProcessing: true, data: { fileDetails: { selectedConflict: action.payload } } }),
Object.assign({}, state, {
isFileDetailsProcessing: true,
data: Object.assign({}, state.data, { fileDetails: { selectedConflict: action.payload } })
}),
RECEIVE_TEAM_AWARENESS_FILE_CONFLICT_DETAILS: (state, action) =>
Object.assign({}, state, { isFileDetailsProcessing: false, data: Object.assign(state.data, action.payload) })
Object.assign({}, state, { isFileDetailsProcessing: false, data: Object.assign({}, state.data, action.payload) })
},
{
data: {
Expand Down
Loading

0 comments on commit 48d27a5

Please sign in to comment.