Skip to content

Commit

Permalink
ui: collapse and expand files
Browse files Browse the repository at this point in the history
  • Loading branch information
yunshi authored and Ivan Yelizariev committed Nov 24, 2019
1 parent 781c064 commit d590407
Show file tree
Hide file tree
Showing 2 changed files with 159 additions and 35 deletions.
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
165 changes: 130 additions & 35 deletions ui/assets/js/hound.js
Original file line number Diff line number Diff line change
Expand Up @@ -672,61 +672,132 @@ 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);
var matches = blocks.map(function(block, mindex) {
var lines = block.map(function(line, lindex) {
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,
blocks = this.props.blocks;
var matches = blocks.map(function(block) {
var lines = block.map(function(line) {
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 = React.createClass({
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}
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 = React.createClass({
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 +813,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 +859,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

0 comments on commit d590407

Please sign in to comment.