Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ui: collapse and expand files #12

Merged
merged 1 commit into from
Nov 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
ui: collapse and expand files
  • Loading branch information
yunshi authored and Ivan Yelizariev committed Nov 29, 2019
commit 1d32469f947371fb00d242387f3b4a4d4a88ed2b
29 changes: 29 additions & 0 deletions ui/assets/css/hound.css
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,16 @@ button:focus {
margin-right: 10px;
}

#result > .actions {
padding: 5px 0 30px 0;
}

#result > .actions > button {
margin: 2px;
float: right;
background-color: #f5f5f5;
color: #666;
}
.repo {
margin-bottom: 100px;
}
Expand All @@ -224,6 +234,7 @@ button:focus {
color: #666;
font-size: 24px;
padding-bottom: 5px;
cursor: pointer;
}

.repo > .title > .name {
Expand All @@ -235,6 +246,11 @@ button:focus {
margin-right: 10px;
}

.repo > .title > .indicator {
vertical-align: text-top;
padding-left: 10px;
}

.files > .moar {
height: 55px;
vertical-align: top;
Expand All @@ -247,11 +263,16 @@ button:focus {
border: 1px solid #d8d8d8;
}

.file.closed {
margin: 10px 0 0 0;
}

.file > .title {
padding: 10px 10px 10px 20px;
display: block;
line-height: 30px;
background-color: #f5f5f5;
cursor: pointer;
}

.title a {
Expand All @@ -263,6 +284,14 @@ button:focus {
overflow: auto;
}

.file.closed > .file-body {
display: none;
}

.file.open > .file-boby {
display: block;
}

.match {
border-bottom: 2px solid #f0f0f0;
}
Expand Down
163 changes: 130 additions & 33 deletions ui/assets/js/hound.js
Original file line number Diff line number Diff line change
Expand Up @@ -672,61 +672,134 @@ var ContentFor = function(line, regexp) {
return buffer.join('');
};

var FilesView = createReactClass({
onLoadMore: function(event) {
Model.LoadMore(this.props.repo);
var FileContentView = createReactClass({
getInitialState: function() {
return { open: true };
},

render: function() {
var rev = this.props.rev,
repo = this.props.repo,
regexp = this.props.regexp,
matches = this.props.matches,
totalMatches = this.props.totalMatches;
var files = matches.map(function(match, index) {
var filename = match.Filename,
blocks = CoalesceMatches(match.Matches);
toggleContent: function() {
this.state.open ? this.closeContent(): this.openContent();
},
openContent: function() {
this.setState({open: true});
},
closeContent: function() {
this.setState({open: false});
},
render: function () {
var repo = this.props.repo,
rev = this.props.rev,
regexp = this.props.regexp,
fileName = this.props.fileName,
index = this.props.index,
blocks = this.props.blocks;
var matches = blocks.map(function(block, mindex) {
var lines = block.map(function(line, lindex) {
var content = ContentFor(line, regexp);
return (
<div className="line" key={repo + "-" + lindex + "-" + mindex + "-" + index}>
<a href={Model.UrlToRepo(repo, filename, line.Number, rev)}
<a href={Model.UrlToRepo(repo, fileName, line.Number, rev)}
className="lnum"
target="_blank">{line.Number}</a>
<span className="lval" dangerouslySetInnerHTML={{__html:content}} />
</div>
);
});

return (
<div className="match" key={repo + "-lines-" + mindex + "-" + index}>{lines}</div>
);
});

return (
<div className="file" key={repo + "-file-" + index}>
<div className="title">
<a href={Model.UrlToRepo(repo, match.Filename, null, rev)}>
{match.Filename}
<div className={"file " + (this.state.open ? 'open' : 'closed')} key={repo + "-file-" + index}>
<div className="title" onClick={this.toggleContent}>
<a href={Model.UrlToRepo(repo, fileName, null, rev)}>
{fileName}
</a>
</div>
<div className="file-body">
{matches}
</div>
</div>
);
}
});

var FilesView = createReactClass({
onLoadMore: function(event) {
Model.LoadMore(this.props.repo);
},

render: function() {
var rev = this.props.rev,
repo = this.props.repo,
regexp = this.props.regexp,
matches = this.props.matches,
totalMatches = this.props.totalMatches;

var files = matches.map(function (match, index) {
return <FileContentView ref={"file-"+index}
repo={repo}
rev={rev}
index={index}
fileName={match.Filename}
blocks={CoalesceMatches(match.Matches)}
regexp={regexp}/>
});


var more = '';
if (matches.length < totalMatches) {
more = (<button className="moar" onClick={this.onLoadMore}>Load all {totalMatches} matches in {Model.NameForRepo(repo)}</button>);
}

return (
<div className="files">
{files}
{more}
{files}
{more}
</div>
);
}
});

var RepoView = createReactClass({
getInitialState: function() {
return { open: true };
},
toggleRepo: function() {
this.state.open ? this.closeRepo(): this.openRepo();
},
openOrCloseRepo: function (to_open) {
for (var ref in this.refs.filesView.refs) {
if (ref.startsWith("file-")) {
if (to_open) {
this.refs.filesView.refs[ref].openContent();
} else {
this.refs.filesView.refs[ref].closeContent();
}
}
}
this.setState({open: to_open});
},
openRepo: function() {
this.openOrCloseRepo(true);
},
closeRepo: function() {
this.openOrCloseRepo(false);
},
render: function() {
return (
<div className={"repo " + (this.state.open? "open":"closed")}>
<div className="title" onClick={this.toggleRepo}>
<span className="mega-octicon octicon-repo"></span>
<span className="name">{Model.NameForRepo(this.props.repo)}</span>
<span className={"indicator octicon octicon-chevron-"+ (this.state.open? "up":"down")} onClick={this.toggleRepo}></span>
</div>
<FilesView ref="filesView"
matches={this.props.matches}
rev={this.props.rev}
repo={this.props.repo}
regexp={this.props.regexp}
totalMatches={this.props.files} />
</div>
);
}
Expand All @@ -742,6 +815,23 @@ var ResultView = createReactClass({
});
});
},
openOrCloseAll: function (to_open) {
for (var ref in this.refs) {
if (ref.startsWith("repo-")) {
if (to_open) {
this.refs[ref].openRepo();
} else {
this.refs[ref].closeRepo();
}
}
}
},
openAll: function () {
this.openOrCloseAll(true);
},
closeAll: function () {
this.openOrCloseAll(false);
},
getInitialState: function() {
return { results: null };
},
Expand Down Expand Up @@ -771,21 +861,28 @@ var ResultView = createReactClass({
results = this.state.results || [];
var repos = results.map(function(result, index) {
return (
<div className="repo" key={"results-view-" + index}>
<div className="title">
<span className="mega-octicon octicon-repo"></span>
<span className="name">{Model.NameForRepo(result.Repo)}</span>
</div>
<FilesView matches={result.Matches}
rev={result.Rev}
repo={result.Repo}
regexp={regexp}
totalMatches={result.FilesWithMatch} />
</div>
<RepoView ref={"repo-"+index}
matches={result.Matches}
rev={result.Rev}
repo={result.Repo}
regexp={regexp}
files={result.FilesWithMatch}/>
);
});
var actions = '';
if (results.length > 0) {
actions = (
<div className="actions">
<button onClick={this.openAll}><span className="octicon octicon-chevron-down"></span> Expand all</button>
<button onClick={this.closeAll}><span className="octicon octicon-chevron-up"></span> Collapse all</button>
</div>
)
}
return (
<div id="result">{repos}</div>
<div id="result">
{actions}
{repos}
</div>
);
}
});
Expand Down