mirror of
https://github.com/dolthub/dolt.git
synced 2026-02-05 10:31:30 -06:00
tagshow: factor out a preview view
This commit is contained in:
45
clients/tagshow/photo.js
Normal file
45
clients/tagshow/photo.js
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var ImmutableRenderMixin = require('react-immutable-render-mixin');
|
||||
var noms = require('noms')
|
||||
var React = require('react');
|
||||
|
||||
var Photo = React.createClass({
|
||||
mixins: [ImmutableRenderMixin],
|
||||
|
||||
propTypes: {
|
||||
onTimeout: React.PropTypes.func.isRequired,
|
||||
photoRef: React.PropTypes.instanceOf(noms.Ref),
|
||||
style: React.PropTypes.object,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
blob: null,
|
||||
};
|
||||
},
|
||||
|
||||
handleLoad: function(e) {
|
||||
URL.revokeObjectURL(e.target.src);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.props.photoRef.deref().then(
|
||||
p => p.get('image').deref()).then(
|
||||
b => this.setState({blob: b}));
|
||||
|
||||
if (this.state.blob == null) {
|
||||
return <span style={this.props.style}>loading...</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<img
|
||||
style={this.props.style}
|
||||
src={URL.createObjectURL(this.state.blob)}
|
||||
onLoad={this.handleLoad}/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = React.createFactory(Photo);
|
||||
33
clients/tagshow/preview.js
Normal file
33
clients/tagshow/preview.js
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var ImmutableRenderMixin = require('react-immutable-render-mixin');
|
||||
var noms = require('noms')
|
||||
var Photo = require('./photo.js');
|
||||
var React = require('react');
|
||||
|
||||
var photoStyle = {
|
||||
display: 'inline-block',
|
||||
marginRight: '1em',
|
||||
maxHeight: 300,
|
||||
};
|
||||
|
||||
var Preview = React.createClass({
|
||||
mixins: [ImmutableRenderMixin],
|
||||
|
||||
propTypes: {
|
||||
photos: React.PropTypes.instanceOf(Immutable.List),
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<div>
|
||||
{
|
||||
this.props.photos.map(p => <Photo photoRef={p} style={photoStyle}/>).toArray()
|
||||
}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = React.createFactory(Preview);
|
||||
@@ -20,7 +20,7 @@ var Root = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selected: Immutable.Set(),
|
||||
selectedPhotos: Immutable.Set(),
|
||||
selectedPhotos: Immutable.List(),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -38,8 +38,36 @@ var Root = React.createClass({
|
||||
return Immutable.Set(tags);
|
||||
},
|
||||
|
||||
handleTagChoose: function(tags) {
|
||||
this.props.updateQuery(this.props.qs.set('tags', tags.toArray().join(',')).set('show', 1));
|
||||
setSelectedPhotos: function(ds, selectedTags) {
|
||||
ds
|
||||
.then(head => head.get('value').deref())
|
||||
.then(tags => {
|
||||
return Promise.all(
|
||||
tags.filter((v, t) => selectedTags.has(t))
|
||||
.valueSeq()
|
||||
.map(ref => ref.deref()))
|
||||
}).then(sets => {
|
||||
this.setState({
|
||||
selectedPhotos:
|
||||
Immutable.List(
|
||||
Immutable.Set(sets[0])
|
||||
.intersect(...sets)
|
||||
// This sorts the photos deterministically, by the ref of their image
|
||||
// blob.
|
||||
// TODO: Sort by create date if it ends up that the common image type
|
||||
// has a create date.
|
||||
.sort((a, b) => a.ref < b.ref)
|
||||
)
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
handleTagsChange: function(tags) {
|
||||
this.props.updateQuery(this.props.qs.set('tags', tags.toArray().join(',')));
|
||||
},
|
||||
|
||||
handleTagsChoose: function() {
|
||||
this.props.updateQuery(this.props.qs.set('show', 1));
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -49,19 +77,23 @@ var Root = React.createClass({
|
||||
|
||||
var dataset = noms.getDataset(this.props.pRoot, this.props.qs.get('ds'))
|
||||
.then(ref => ref.deref());
|
||||
|
||||
var selectedTags = this.getSelectedTags();
|
||||
if (!this.props.qs.get('show')) {
|
||||
|
||||
this.setSelectedPhotos(dataset, selectedTags);
|
||||
|
||||
if (!this.props.qs.get('show') || selectedTags.isEmpty()) {
|
||||
return (
|
||||
<TagChooser
|
||||
ds={dataset}
|
||||
selected={this.getSelectedTags()}
|
||||
onChoose={this.handleTagChoose}/>
|
||||
selectedPhotos={this.state.selectedPhotos}
|
||||
selectedTags={this.getSelectedTags()}
|
||||
onChange={this.handleTagsChange}
|
||||
onChoose={this.handleTagsChoose}/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SlideShow ds={dataset} tags={selectedTags}/>
|
||||
<SlideShow ds={dataset} photos={this.state.selectedPhotos}/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var ImmutableRenderMixin = require('react-immutable-render-mixin');
|
||||
var noms = require('noms')
|
||||
var noms = require('noms');
|
||||
var Photo = require('./photo.js');
|
||||
var React = require('react');
|
||||
|
||||
var containerStyle = {
|
||||
@@ -29,49 +30,25 @@ var SlideShow = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
ds: React.PropTypes.instanceOf(Immutable.Map),
|
||||
tags: React.PropTypes.instanceOf(Immutable.Set),
|
||||
photos: React.PropTypes.instanceOf(Immutable.Set),
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
photos: Immutable.Set(),
|
||||
index: 0,
|
||||
nextSlideTime: 0,
|
||||
}
|
||||
},
|
||||
|
||||
handleTimeout: function() {
|
||||
var newIndex = this.state.index + 1;
|
||||
if (newIndex >= this.state.photos.size) {
|
||||
if (newIndex >= this.props.photos.size) {
|
||||
newIndex = 0;
|
||||
}
|
||||
this.setState({index: newIndex});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.props.ds
|
||||
.then(head => head.get('value').deref())
|
||||
.then(tags => {
|
||||
return Promise.all(
|
||||
tags.filter((v, t) => this.props.tags.has(t))
|
||||
.valueSeq()
|
||||
.map(ref => ref.deref()))
|
||||
}).then(sets => {
|
||||
this.setState({
|
||||
photos:
|
||||
Immutable.List(
|
||||
Immutable.Set(sets[0])
|
||||
.intersect(...sets)
|
||||
// This sorts the photos deterministically, by the ref of their image
|
||||
// blob.
|
||||
// TODO: Sort by create date if it ends up that the common image type
|
||||
// has a create date.
|
||||
.sort((a, b) => a.ref < b.ref)
|
||||
)
|
||||
});
|
||||
});
|
||||
|
||||
var photoRef = this.state.photos.get(this.state.index);
|
||||
var photoRef = this.props.photos.get(this.state.index);
|
||||
if (!photoRef) {
|
||||
return null;
|
||||
}
|
||||
@@ -97,8 +74,7 @@ var Item = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
blob: null,
|
||||
tags: Immutable.Set(),
|
||||
timerId: 0,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -112,28 +88,11 @@ var Item = React.createClass({
|
||||
window.clearTimeout(this.state.timerId);
|
||||
},
|
||||
|
||||
handleLoad: function(e) {
|
||||
URL.revokeObjectURL(e.target.src);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.props.photoRef.deref().then(
|
||||
p => p.get('image').deref()).then(
|
||||
b => this.setState({blob: b}));
|
||||
|
||||
this.props.photoRef.deref().then(
|
||||
p => p.get('tags').deref()).then(
|
||||
tags => this.setState({tags: tags}));
|
||||
|
||||
if (this.state.blob == null) {
|
||||
return <span>loading...</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<img
|
||||
style={imageStyle}
|
||||
src={URL.createObjectURL(this.state.blob)}
|
||||
onLoad={this.handleLoad}/>
|
||||
<Photo
|
||||
photoRef={this.props.photoRef}
|
||||
style={imageStyle}/>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
var Immutable = require('immutable');
|
||||
var ImmutableRenderMixin = require('react-immutable-render-mixin');
|
||||
var Preview = require('./preview.js');
|
||||
var React = require('react');
|
||||
var TagList = require('./taglist.js');
|
||||
|
||||
@@ -10,36 +11,36 @@ var TagChooser = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
ds: React.PropTypes.instanceOf(Immutable.Map),
|
||||
selected: React.PropTypes.instanceOf(Immutable.Set),
|
||||
selectedPhotos: React.PropTypes.instanceOf(Immutable.Set),
|
||||
selectedTags: React.PropTypes.instanceOf(Immutable.Set),
|
||||
onChange: React.PropTypes.func.isRequired,
|
||||
onChoose: React.PropTypes.func.isRequired,
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
selected: this.props.selected,
|
||||
tags: Immutable.Map(),
|
||||
};
|
||||
},
|
||||
|
||||
handleOnChange: function(selected) {
|
||||
this.setState({selected: selected});
|
||||
},
|
||||
|
||||
handleSubmit: function(e) {
|
||||
this.props.onChoose(this.state.selected);
|
||||
this.props.onChoose();
|
||||
e.preventDefault();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input type="submit" value="OK!"/>
|
||||
<br/>
|
||||
<TagList
|
||||
ds={this.props.ds}
|
||||
selected={this.state.selected}
|
||||
onChange={this.handleOnChange}/>
|
||||
</form>
|
||||
<table width="100%">
|
||||
<tr>
|
||||
<td style={{verticalAlign: 'top'}}>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input type="submit" value="OK!"/>
|
||||
<br/>
|
||||
<TagList
|
||||
ds={this.props.ds}
|
||||
selected={this.props.selectedTags}
|
||||
onChange={this.props.onChange}/>
|
||||
</form>
|
||||
</td>
|
||||
<td style={{verticalAlign: 'top'}} width="100%">
|
||||
<Preview photos={this.props.selectedPhotos}/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ var React = require('react');
|
||||
|
||||
var tagStyle = {
|
||||
display: 'block',
|
||||
whiteSpace: 'nowrap',
|
||||
};
|
||||
|
||||
var TagCloud = React.createClass({
|
||||
|
||||
Reference in New Issue
Block a user