attache_rails 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -2
- data/app/assets/javascripts/attache/bootstrap3.js +40 -98
- data/app/assets/javascripts/attache/bootstrap3.js.jsx +40 -98
- data/app/assets/javascripts/attache/cors_upload.js +9 -9
- data/app/assets/javascripts/attache/file_input.js +71 -0
- data/app/assets/javascripts/attache/file_input.js.jsx +71 -0
- data/app/assets/javascripts/attache.js +1 -0
- data/lib/attache_rails/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: edd291b58ed01055cda499254592cfd028ed2cde
|
4
|
+
data.tar.gz: e8c95574587c899c798cb3fe550523a86222ffa7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c6b5fa2be93e5a90b22bd39e58330eeaf663733af892a0c98ddd7c76fa2500ba8d3b6805b10a33dd1ffaddaf1f7c4b81654991845991b5e151f14e6f5b31a937
|
7
|
+
data.tar.gz: 9889e52f28712d7c5a10a50933ec7d637cb45a111b51fbcd92620989dfe883e88a71d1a464910b67a4068be658dcbe63b765ab8feabb6393035993ad02e6f942
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Ruby on Rails integration for [attache server](https://github.com/choonkeat/attache)
|
4
4
|
|
5
|
-
NOTE: You can learn how to use this gem by looking at the [changes made to our example app](https://github.com/choonkeat/attache-railsapp/
|
5
|
+
NOTE: You can learn how to use this gem by looking at the [changes made to our example app](https://github.com/choonkeat/attache-railsapp/compare/fc47c17...master) or follow the step by step instructions in this `README`
|
6
6
|
|
7
7
|
## Dependencies
|
8
8
|
|
@@ -32,10 +32,19 @@ Or you can include the various scripts yourself
|
|
32
32
|
|
33
33
|
``` javascript
|
34
34
|
//= require attache/cors_upload
|
35
|
+
//= require attache/file_input
|
35
36
|
//= require attache/bootstrap3
|
36
37
|
//= require attache/ujs
|
37
38
|
```
|
38
39
|
|
40
|
+
If you want to customize the file upload look and feel, define your own react `<AttacheFilePreview/>` renderer *before* including the attache js. For example,
|
41
|
+
|
42
|
+
``` javascript
|
43
|
+
//= require ./my_attache_file_preview.js
|
44
|
+
//= require attache
|
45
|
+
```
|
46
|
+
|
47
|
+
|
39
48
|
## Usage
|
40
49
|
|
41
50
|
### Database
|
@@ -138,7 +147,6 @@ Alternatively, you can get the list of urls and manipulate it however you want
|
|
138
147
|
* If this variable is not set, then upload requests will not be signed & `ATTACHE_UPLOAD_DURATION` will be ignored
|
139
148
|
* If this variable is set, it must be the same value as `SECRET_KEY` is set on the `attache` server
|
140
149
|
|
141
|
-
|
142
150
|
# License
|
143
151
|
|
144
152
|
MIT
|
@@ -1,106 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
new CORSUpload({
|
28
|
-
file_element: file_element, onComplete: this.setFileValue, onProgress: this.setFileValue,
|
29
|
-
onError: function(uid, status) { that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' }); }
|
30
|
-
});
|
31
|
-
// we don't want the file binary to be uploaded in the main form
|
32
|
-
file_element.value = '';
|
33
|
-
},
|
34
|
-
|
35
|
-
setFileValue: function(key, value) {
|
36
|
-
this.state.files[key] = value;
|
37
|
-
this.setState(this.state);
|
38
|
-
},
|
39
|
-
|
40
|
-
render: function() {
|
41
|
-
var that = this;
|
42
|
-
var previews = [];
|
43
|
-
$.each(that.state.files, function(key, result) {
|
44
|
-
var json = JSON.stringify(result);
|
45
|
-
if (result.path) {
|
46
|
-
var parts = result.path.split('/');
|
47
|
-
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
48
|
-
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
1
|
+
if (typeof AttacheFilePreview === 'undefined') {
|
2
|
+
|
3
|
+
var AttacheFilePreview = React.createClass({displayName: "AttacheFilePreview",
|
4
|
+
|
5
|
+
getInitialState: function() {
|
6
|
+
return { srcWas: '' };
|
7
|
+
},
|
8
|
+
|
9
|
+
onSrcLoaded: function() {
|
10
|
+
this.setState({ srcWas: this.props.src });
|
11
|
+
},
|
12
|
+
|
13
|
+
render: function() {
|
14
|
+
// progressbar
|
15
|
+
if (this.state.srcWas != this.props.src) {
|
16
|
+
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
17
|
+
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
18
|
+
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
19
|
+
var pctStyle = { width: pctString, minWidth: '3em' };
|
20
|
+
var progress = (
|
21
|
+
React.createElement("div", {className: "progress"},
|
22
|
+
React.createElement("div", {className: className, role: "progressbar", "aria-valuenow": this.props.percentLoaded, "aria-valuemin": "0", "aria-valuemax": "100", style: pctStyle},
|
23
|
+
pctDesc
|
24
|
+
)
|
25
|
+
)
|
26
|
+
);
|
49
27
|
}
|
50
|
-
previews.push(
|
51
|
-
React.createElement("div", {className: "thumbnail"},
|
52
|
-
React.createElement("input", {type: "hidden", name: that.props.name, value: result.path, readOnly: "true"}),
|
53
|
-
React.createElement(AttacheFilePreview, React.__spread({}, result, {key: key, onRemove: that.onRemove.bind(that, key)}))
|
54
|
-
)
|
55
|
-
);
|
56
|
-
});
|
57
|
-
return (
|
58
|
-
React.createElement("label", {htmlFor: this.props.id, className: "attache-file-selector"},
|
59
|
-
React.createElement("input", React.__spread({type: "file"}, this.props, {onChange: this.onChange})),
|
60
|
-
previews
|
61
|
-
)
|
62
|
-
);
|
63
|
-
}
|
64
|
-
});
|
65
|
-
|
66
|
-
var AttacheFilePreview = React.createClass({displayName: "AttacheFilePreview",
|
67
|
-
|
68
|
-
getInitialState: function() {
|
69
|
-
return { srcWas: '' };
|
70
|
-
},
|
71
28
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
render: function() {
|
77
|
-
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
78
|
-
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
79
|
-
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
80
|
-
var img = (this.props.src ? (React.createElement("img", {src: this.props.src, onLoad: this.removeProgressBar})) : '');
|
81
|
-
var pctStyle = { width: pctString, minWidth: '3em' };
|
82
|
-
var cptStyle = { textOverflow: "ellipsis" };
|
83
|
-
var caption = React.createElement("div", {className: "pull-left", style: cptStyle}, this.props.filename || this.props.path && this.props.path.split('/').pop());
|
29
|
+
// img tag
|
30
|
+
if (this.props.src) {
|
31
|
+
var img = React.createElement("img", {src: this.props.src, onLoad: this.onSrcLoaded});
|
32
|
+
}
|
84
33
|
|
85
|
-
|
86
|
-
|
87
|
-
React.createElement("div", {className: "
|
88
|
-
|
89
|
-
|
34
|
+
// combined
|
35
|
+
return (
|
36
|
+
React.createElement("div", {className: "attache-file-preview"},
|
37
|
+
progress,
|
38
|
+
img,
|
39
|
+
React.createElement("div", {className: "clearfix"},
|
40
|
+
React.createElement("div", {className: "pull-left", style: "textOverflow: 'ellipsis;'"}, this.props.filename),
|
41
|
+
React.createElement("a", {href: "#remove", className: "pull-right", onClick: this.props.onRemove, title: "Click to remove"}, "×")
|
90
42
|
)
|
91
43
|
)
|
92
44
|
);
|
93
45
|
}
|
46
|
+
});
|
94
47
|
|
95
|
-
|
96
|
-
React.createElement("div", {className: "attache-file-preview"},
|
97
|
-
progress,
|
98
|
-
img,
|
99
|
-
React.createElement("div", {className: "clearfix"},
|
100
|
-
caption,
|
101
|
-
React.createElement("a", {href: "#remove", className: "pull-right", onClick: this.props.onRemove, title: "Click to remove"}, "×")
|
102
|
-
)
|
103
|
-
)
|
104
|
-
);
|
105
|
-
}
|
106
|
-
});
|
48
|
+
}
|
@@ -1,106 +1,48 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
new CORSUpload({
|
28
|
-
file_element: file_element, onComplete: this.setFileValue, onProgress: this.setFileValue,
|
29
|
-
onError: function(uid, status) { that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' }); }
|
30
|
-
});
|
31
|
-
// we don't want the file binary to be uploaded in the main form
|
32
|
-
file_element.value = '';
|
33
|
-
},
|
34
|
-
|
35
|
-
setFileValue: function(key, value) {
|
36
|
-
this.state.files[key] = value;
|
37
|
-
this.setState(this.state);
|
38
|
-
},
|
39
|
-
|
40
|
-
render: function() {
|
41
|
-
var that = this;
|
42
|
-
var previews = [];
|
43
|
-
$.each(that.state.files, function(key, result) {
|
44
|
-
var json = JSON.stringify(result);
|
45
|
-
if (result.path) {
|
46
|
-
var parts = result.path.split('/');
|
47
|
-
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
48
|
-
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
1
|
+
if (typeof AttacheFilePreview === 'undefined') {
|
2
|
+
|
3
|
+
var AttacheFilePreview = React.createClass({
|
4
|
+
|
5
|
+
getInitialState: function() {
|
6
|
+
return { srcWas: '' };
|
7
|
+
},
|
8
|
+
|
9
|
+
onSrcLoaded: function() {
|
10
|
+
this.setState({ srcWas: this.props.src });
|
11
|
+
},
|
12
|
+
|
13
|
+
render: function() {
|
14
|
+
// progressbar
|
15
|
+
if (this.state.srcWas != this.props.src) {
|
16
|
+
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
17
|
+
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
18
|
+
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
19
|
+
var pctStyle = { width: pctString, minWidth: '3em' };
|
20
|
+
var progress = (
|
21
|
+
<div className="progress">
|
22
|
+
<div className={className} role="progressbar" aria-valuenow={this.props.percentLoaded} aria-valuemin="0" aria-valuemax="100" style={pctStyle}>
|
23
|
+
{pctDesc}
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
);
|
49
27
|
}
|
50
|
-
previews.push(
|
51
|
-
<div className="thumbnail">
|
52
|
-
<input type="hidden" name={that.props.name} value={result.path} readOnly="true" />
|
53
|
-
<AttacheFilePreview {...result} key={key} onRemove={that.onRemove.bind(that, key)}/>
|
54
|
-
</div>
|
55
|
-
);
|
56
|
-
});
|
57
|
-
return (
|
58
|
-
<label htmlFor={this.props.id} className="attache-file-selector">
|
59
|
-
<input type="file" {...this.props} onChange={this.onChange}/>
|
60
|
-
{previews}
|
61
|
-
</label>
|
62
|
-
);
|
63
|
-
}
|
64
|
-
});
|
65
|
-
|
66
|
-
var AttacheFilePreview = React.createClass({
|
67
|
-
|
68
|
-
getInitialState: function() {
|
69
|
-
return { srcWas: '' };
|
70
|
-
},
|
71
28
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
render: function() {
|
77
|
-
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
78
|
-
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
79
|
-
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
80
|
-
var img = (this.props.src ? (<img src={this.props.src} onLoad={this.removeProgressBar} />) : '');
|
81
|
-
var pctStyle = { width: pctString, minWidth: '3em' };
|
82
|
-
var cptStyle = { textOverflow: "ellipsis" };
|
83
|
-
var caption = <div className="pull-left" style={cptStyle}>{this.props.filename || this.props.path && this.props.path.split('/').pop()}</div>;
|
29
|
+
// img tag
|
30
|
+
if (this.props.src) {
|
31
|
+
var img = <img src={this.props.src} onLoad={this.onSrcLoaded} />;
|
32
|
+
}
|
84
33
|
|
85
|
-
|
86
|
-
|
87
|
-
<div className="
|
88
|
-
|
89
|
-
|
34
|
+
// combined
|
35
|
+
return (
|
36
|
+
<div className="attache-file-preview">
|
37
|
+
{progress}
|
38
|
+
{img}
|
39
|
+
<div className="clearfix">
|
40
|
+
<div className="pull-left" style="textOverflow: 'ellipsis;'">{this.props.filename}</div>
|
41
|
+
<a href="#remove" className="pull-right" onClick={this.props.onRemove} title="Click to remove">×</a>
|
90
42
|
</div>
|
91
43
|
</div>
|
92
44
|
);
|
93
45
|
}
|
46
|
+
});
|
94
47
|
|
95
|
-
|
96
|
-
<div className="attache-file-preview">
|
97
|
-
{progress}
|
98
|
-
{img}
|
99
|
-
<div className="clearfix">
|
100
|
-
{caption}
|
101
|
-
<a href="#remove" className="pull-right" onClick={this.props.onRemove} title="Click to remove">×</a>
|
102
|
-
</div>
|
103
|
-
</div>
|
104
|
-
);
|
105
|
-
}
|
106
|
-
});
|
48
|
+
}
|
@@ -1,11 +1,11 @@
|
|
1
|
-
var
|
1
|
+
var AttacheCORSUpload = (function() {
|
2
2
|
var counter = 0;
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
AttacheCORSUpload.prototype.onComplete = function(uid, json) { };
|
5
|
+
AttacheCORSUpload.prototype.onProgress = function(uid, json) { };
|
6
|
+
AttacheCORSUpload.prototype.onError = function(uid, status) { alert(status); };
|
7
7
|
|
8
|
-
function
|
8
|
+
function AttacheCORSUpload(options) {
|
9
9
|
if (options == null) options = {};
|
10
10
|
for (option in options) {
|
11
11
|
this[option] = options[option];
|
@@ -13,7 +13,7 @@ var CORSUpload = (function() {
|
|
13
13
|
this.handleFileSelect(options.file_element);
|
14
14
|
}
|
15
15
|
|
16
|
-
|
16
|
+
AttacheCORSUpload.prototype.handleFileSelect = function(file_element) {
|
17
17
|
var f, files, output, _i, _len, _results, url, $ele;
|
18
18
|
$ele = $(file_element);
|
19
19
|
url = $ele.data('uploadurl');
|
@@ -37,7 +37,7 @@ var CORSUpload = (function() {
|
|
37
37
|
return _results;
|
38
38
|
};
|
39
39
|
|
40
|
-
|
40
|
+
AttacheCORSUpload.prototype.createCORSRequest = function(method, url) {
|
41
41
|
var xhr;
|
42
42
|
xhr = new XMLHttpRequest();
|
43
43
|
if (xhr.withCredentials != null) {
|
@@ -51,7 +51,7 @@ var CORSUpload = (function() {
|
|
51
51
|
return xhr;
|
52
52
|
};
|
53
53
|
|
54
|
-
|
54
|
+
AttacheCORSUpload.prototype.performUpload = function(file, url) {
|
55
55
|
var this_s3upload, xhr;
|
56
56
|
this_s3upload = this;
|
57
57
|
url = url + (url.indexOf('?') == -1 ? '?' : '&') + 'file=' + encodeURIComponent(file.name);
|
@@ -80,6 +80,6 @@ var CORSUpload = (function() {
|
|
80
80
|
return xhr.send(file);
|
81
81
|
};
|
82
82
|
|
83
|
-
return
|
83
|
+
return AttacheCORSUpload;
|
84
84
|
|
85
85
|
})();
|
@@ -0,0 +1,71 @@
|
|
1
|
+
var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
2
|
+
|
3
|
+
getInitialState: function() {
|
4
|
+
var files = {};
|
5
|
+
var array = ([].concat(JSON.parse(this.props['data-value'])));
|
6
|
+
$.each(array, function(uid, json) {
|
7
|
+
if (json) files[uid] = { path: json };
|
8
|
+
});
|
9
|
+
return {files: files};
|
10
|
+
},
|
11
|
+
|
12
|
+
onRemove: function(uid, e) {
|
13
|
+
delete this.state.files[uid];
|
14
|
+
this.setState(this.state);
|
15
|
+
e.preventDefault();
|
16
|
+
e.stopPropagation();
|
17
|
+
},
|
18
|
+
|
19
|
+
onChange: function() {
|
20
|
+
var file_element = this.getDOMNode().firstChild;
|
21
|
+
// user cancelled file chooser dialog. ignore
|
22
|
+
if (file_element.files.length == 0) return;
|
23
|
+
this.state.files = {};
|
24
|
+
this.setState(this.state);
|
25
|
+
// upload the file via CORS
|
26
|
+
var that = this;
|
27
|
+
new AttacheCORSUpload({
|
28
|
+
file_element: file_element,
|
29
|
+
onComplete: this.setFileValue,
|
30
|
+
onProgress: this.setFileValue,
|
31
|
+
onError: function(uid, status) {
|
32
|
+
that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' });
|
33
|
+
}
|
34
|
+
});
|
35
|
+
|
36
|
+
// we don't want the file binary to be uploaded in the main form
|
37
|
+
// so the actual file input is neutered
|
38
|
+
file_element.value = '';
|
39
|
+
},
|
40
|
+
|
41
|
+
setFileValue: function(key, value) {
|
42
|
+
this.state.files[key] = value;
|
43
|
+
this.setState(this.state);
|
44
|
+
},
|
45
|
+
|
46
|
+
render: function() {
|
47
|
+
var that = this;
|
48
|
+
var previews = [];
|
49
|
+
$.each(that.state.files, function(key, result) {
|
50
|
+
var json = JSON.stringify(result);
|
51
|
+
if (result.path) {
|
52
|
+
var parts = result.path.split('/');
|
53
|
+
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
54
|
+
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
55
|
+
result.filename = result.src.split('/').pop().split(/[#?]/).shift();
|
56
|
+
}
|
57
|
+
previews.push(
|
58
|
+
React.createElement("div", {className: "attache-file-input"},
|
59
|
+
React.createElement("input", {type: "hidden", name: that.props.name, value: result.path, readOnly: "true"}),
|
60
|
+
React.createElement(AttacheFilePreview, React.__spread({}, result, {key: key, onRemove: that.onRemove.bind(that, key)}))
|
61
|
+
)
|
62
|
+
);
|
63
|
+
});
|
64
|
+
return (
|
65
|
+
React.createElement("label", {htmlFor: this.props.id, className: "attache-file-selector"},
|
66
|
+
React.createElement("input", React.__spread({type: "file"}, this.props, {onChange: this.onChange})),
|
67
|
+
previews
|
68
|
+
)
|
69
|
+
);
|
70
|
+
}
|
71
|
+
});
|
@@ -0,0 +1,71 @@
|
|
1
|
+
var AttacheFileInput = React.createClass({
|
2
|
+
|
3
|
+
getInitialState: function() {
|
4
|
+
var files = {};
|
5
|
+
var array = ([].concat(JSON.parse(this.props['data-value'])));
|
6
|
+
$.each(array, function(uid, json) {
|
7
|
+
if (json) files[uid] = { path: json };
|
8
|
+
});
|
9
|
+
return {files: files};
|
10
|
+
},
|
11
|
+
|
12
|
+
onRemove: function(uid, e) {
|
13
|
+
delete this.state.files[uid];
|
14
|
+
this.setState(this.state);
|
15
|
+
e.preventDefault();
|
16
|
+
e.stopPropagation();
|
17
|
+
},
|
18
|
+
|
19
|
+
onChange: function() {
|
20
|
+
var file_element = this.getDOMNode().firstChild;
|
21
|
+
// user cancelled file chooser dialog. ignore
|
22
|
+
if (file_element.files.length == 0) return;
|
23
|
+
this.state.files = {};
|
24
|
+
this.setState(this.state);
|
25
|
+
// upload the file via CORS
|
26
|
+
var that = this;
|
27
|
+
new AttacheCORSUpload({
|
28
|
+
file_element: file_element,
|
29
|
+
onComplete: this.setFileValue,
|
30
|
+
onProgress: this.setFileValue,
|
31
|
+
onError: function(uid, status) {
|
32
|
+
that.setFileValue(uid, { pctString: '90%', pctDesc: status, className: 'progress-bar progress-bar-danger' });
|
33
|
+
}
|
34
|
+
});
|
35
|
+
|
36
|
+
// we don't want the file binary to be uploaded in the main form
|
37
|
+
// so the actual file input is neutered
|
38
|
+
file_element.value = '';
|
39
|
+
},
|
40
|
+
|
41
|
+
setFileValue: function(key, value) {
|
42
|
+
this.state.files[key] = value;
|
43
|
+
this.setState(this.state);
|
44
|
+
},
|
45
|
+
|
46
|
+
render: function() {
|
47
|
+
var that = this;
|
48
|
+
var previews = [];
|
49
|
+
$.each(that.state.files, function(key, result) {
|
50
|
+
var json = JSON.stringify(result);
|
51
|
+
if (result.path) {
|
52
|
+
var parts = result.path.split('/');
|
53
|
+
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
54
|
+
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
55
|
+
result.filename = result.src.split('/').pop().split(/[#?]/).shift();
|
56
|
+
}
|
57
|
+
previews.push(
|
58
|
+
<div className="attache-file-input">
|
59
|
+
<input type="hidden" name={that.props.name} value={result.path} readOnly="true" />
|
60
|
+
<AttacheFilePreview {...result} key={key} onRemove={that.onRemove.bind(that, key)}/>
|
61
|
+
</div>
|
62
|
+
);
|
63
|
+
});
|
64
|
+
return (
|
65
|
+
<label htmlFor={this.props.id} className="attache-file-selector">
|
66
|
+
<input type="file" {...this.props} onChange={this.onChange}/>
|
67
|
+
{previews}
|
68
|
+
</label>
|
69
|
+
);
|
70
|
+
}
|
71
|
+
});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attache_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- choonkeat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -24,6 +24,8 @@ files:
|
|
24
24
|
- app/assets/javascripts/attache/bootstrap3.js
|
25
25
|
- app/assets/javascripts/attache/bootstrap3.js.jsx
|
26
26
|
- app/assets/javascripts/attache/cors_upload.js
|
27
|
+
- app/assets/javascripts/attache/file_input.js
|
28
|
+
- app/assets/javascripts/attache/file_input.js.jsx
|
27
29
|
- app/assets/javascripts/attache/ujs.js
|
28
30
|
- lib/attache_rails.rb
|
29
31
|
- lib/attache_rails/engine.rb
|