attache_rails 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/attache/bootstrap3.js +4 -1
- data/app/assets/javascripts/attache/bootstrap3.js.jsx +4 -1
- data/app/assets/javascripts/attache/cors_upload.js +7 -6
- data/app/assets/javascripts/attache/file_input.js +40 -7
- data/app/assets/javascripts/attache/file_input.js.jsx +40 -7
- data/lib/attache_rails/model.rb +7 -2
- data/lib/attache_rails/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da5e22bb598e1b06cbb35fc8492b02f3e004978
|
4
|
+
data.tar.gz: 7b1d38f4fb5193ca9490ab1d4463d74938c5300d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b254f432f52a43161cf4c19aed219623e795315984d2fbafa66c09169b39075300776b2a20f8c21bac0465ad130939ec6e7ab2c211e5aa9b772bc1468072b8c3
|
7
|
+
data.tar.gz: ed680e0629577892f63c29e103743ba1383e61e6d33427420352f07605e4b8a0425b871c85f36a9210e5cb763dac8925ab1f7e5ff544724fbc318fd39443b12f
|
@@ -11,8 +11,11 @@ if (typeof AttacheFilePreview === 'undefined') {
|
|
11
11
|
},
|
12
12
|
|
13
13
|
render: function() {
|
14
|
+
var previewClassName = "attache-file-preview";
|
15
|
+
|
14
16
|
// progressbar
|
15
17
|
if (this.state.srcWas != this.props.src) {
|
18
|
+
previewClassName = previewClassName + " attache-loading";
|
16
19
|
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
17
20
|
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
18
21
|
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
@@ -33,7 +36,7 @@ if (typeof AttacheFilePreview === 'undefined') {
|
|
33
36
|
|
34
37
|
// combined
|
35
38
|
return (
|
36
|
-
React.createElement("div", {className:
|
39
|
+
React.createElement("div", {className: previewClassName},
|
37
40
|
progress,
|
38
41
|
img,
|
39
42
|
React.createElement("div", {className: "clearfix"},
|
@@ -11,8 +11,11 @@ if (typeof AttacheFilePreview === 'undefined') {
|
|
11
11
|
},
|
12
12
|
|
13
13
|
render: function() {
|
14
|
+
var previewClassName = "attache-file-preview";
|
15
|
+
|
14
16
|
// progressbar
|
15
17
|
if (this.state.srcWas != this.props.src) {
|
18
|
+
previewClassName = previewClassName + " attache-loading";
|
16
19
|
var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
|
17
20
|
var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
|
18
21
|
var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
|
@@ -33,7 +36,7 @@ if (typeof AttacheFilePreview === 'undefined') {
|
|
33
36
|
|
34
37
|
// combined
|
35
38
|
return (
|
36
|
-
<div className=
|
39
|
+
<div className={previewClassName}>
|
37
40
|
{progress}
|
38
41
|
{img}
|
39
42
|
<div className="clearfix">
|
@@ -4,17 +4,18 @@ var AttacheCORSUpload = (function() {
|
|
4
4
|
AttacheCORSUpload.prototype.onComplete = function(uid, json) { };
|
5
5
|
AttacheCORSUpload.prototype.onProgress = function(uid, json) { };
|
6
6
|
AttacheCORSUpload.prototype.onError = function(uid, status) { alert(status); };
|
7
|
+
AttacheCORSUpload.prototype.createLocalThumbnail = function() { }; // for overwriting
|
7
8
|
|
8
9
|
function AttacheCORSUpload(options) {
|
9
10
|
if (options == null) options = {};
|
10
11
|
for (option in options) {
|
11
12
|
this[option] = options[option];
|
12
13
|
}
|
13
|
-
this.handleFileSelect(options.file_element);
|
14
|
+
this.handleFileSelect(options.file_element, options.files);
|
14
15
|
}
|
15
16
|
|
16
|
-
AttacheCORSUpload.prototype.handleFileSelect = function(file_element) {
|
17
|
-
var f,
|
17
|
+
AttacheCORSUpload.prototype.handleFileSelect = function(file_element, files) {
|
18
|
+
var f, output, _i, _len, _results, url, $ele, prefix;
|
18
19
|
$ele = $(file_element);
|
19
20
|
url = $ele.data('uploadurl');
|
20
21
|
if ($ele.data('hmac')) {
|
@@ -26,13 +27,13 @@ var AttacheCORSUpload = (function() {
|
|
26
27
|
}
|
27
28
|
|
28
29
|
prefix = Date.now() + "_";
|
29
|
-
files = file_element.files;
|
30
30
|
output = [];
|
31
31
|
_results = [];
|
32
32
|
for (_i = 0, _len = files.length; _i < _len; _i++) {
|
33
33
|
f = files[_i];
|
34
|
+
this.createLocalThumbnail(f); // if any
|
34
35
|
f.uid = prefix + (counter++);
|
35
|
-
this.onProgress(f.uid, { filename: f.name, percentLoaded: 0, bytesLoaded: 0, bytesTotal: f.size });
|
36
|
+
this.onProgress(f.uid, { src: f.src, filename: f.name, percentLoaded: 0, bytesLoaded: 0, bytesTotal: f.size });
|
36
37
|
_results.push(this.performUpload(f, url));
|
37
38
|
}
|
38
39
|
return _results;
|
@@ -74,7 +75,7 @@ var AttacheCORSUpload = (function() {
|
|
74
75
|
var percentLoaded;
|
75
76
|
if (e.lengthComputable) {
|
76
77
|
percentLoaded = Math.round((e.loaded / e.total) * 100);
|
77
|
-
return this_s3upload.onProgress(file.uid, { filename: file.name, percentLoaded: percentLoaded, bytesLoaded: e.loaded, bytesTotal: e.total });
|
78
|
+
return this_s3upload.onProgress(file.uid, { src: file.src, filename: file.name, percentLoaded: percentLoaded, bytesLoaded: e.loaded, bytesTotal: e.total });
|
78
79
|
}
|
79
80
|
};
|
80
81
|
}
|
@@ -21,17 +21,20 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
|
21
21
|
this.setState(this.state);
|
22
22
|
},
|
23
23
|
|
24
|
-
|
25
|
-
var file_element = this.getDOMNode().firstChild;
|
24
|
+
performUpload: function(file_element, files) {
|
26
25
|
// user cancelled file chooser dialog. ignore
|
27
|
-
if (!
|
28
|
-
if (! this.props.multiple)
|
26
|
+
if (! files || files.length == 0) return;
|
27
|
+
if (! this.props.multiple) {
|
28
|
+
this.state.files = {};
|
29
|
+
files = Array.prototype.splice.apply(files, [0, 1]); // array of 1 element
|
30
|
+
}
|
29
31
|
|
30
32
|
this.setState(this.state);
|
31
33
|
// upload the file via CORS
|
32
34
|
var that = this;
|
33
35
|
new AttacheCORSUpload({
|
34
36
|
file_element: file_element,
|
37
|
+
files: files,
|
35
38
|
onComplete: this.setFileValue,
|
36
39
|
onProgress: this.setFileValue,
|
37
40
|
onError: function(uid, status) {
|
@@ -44,6 +47,31 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
|
44
47
|
file_element.value = '';
|
45
48
|
},
|
46
49
|
|
50
|
+
onChange: function() {
|
51
|
+
var file_element = this.getDOMNode().firstChild;
|
52
|
+
this.performUpload(file_element, file_element && file_element.files);
|
53
|
+
},
|
54
|
+
|
55
|
+
onDragOver: function(e) {
|
56
|
+
e.stopPropagation();
|
57
|
+
e.preventDefault();
|
58
|
+
$(this.getDOMNode()).addClass('attache-dragover');
|
59
|
+
},
|
60
|
+
|
61
|
+
onDragLeave: function(e) {
|
62
|
+
e.stopPropagation();
|
63
|
+
e.preventDefault();
|
64
|
+
$(this.getDOMNode()).removeClass('attache-dragover');
|
65
|
+
},
|
66
|
+
|
67
|
+
onDrop: function(e) {
|
68
|
+
e.stopPropagation();
|
69
|
+
e.preventDefault();
|
70
|
+
var file_element = this.getDOMNode().firstChild;
|
71
|
+
this.performUpload(file_element, e.target.files || e.dataTransfer.files);
|
72
|
+
$(this.getDOMNode()).removeClass('attache-dragover');
|
73
|
+
},
|
74
|
+
|
47
75
|
setFileValue: function(key, value) {
|
48
76
|
this.state.files[key] = value;
|
49
77
|
this.setState(this.state);
|
@@ -58,14 +86,19 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
|
58
86
|
|
59
87
|
var previews = [];
|
60
88
|
$.each(that.state.files, function(key, result) {
|
89
|
+
// json is input[value], drop non essential values
|
90
|
+
var copy = JSON.parse(JSON.stringify(result));
|
91
|
+
delete copy.src;
|
92
|
+
delete copy.filename;
|
93
|
+
var json = JSON.stringify(copy);
|
94
|
+
//
|
95
|
+
result.multiple = that.props.multiple;
|
61
96
|
if (result.path) {
|
62
97
|
var parts = result.path.split('/');
|
63
98
|
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
64
99
|
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
65
100
|
result.filename = result.src.split('/').pop().split(/[#?]/).shift();
|
66
|
-
result.multiple = that.props.multiple;
|
67
101
|
}
|
68
|
-
var json = JSON.stringify(result);
|
69
102
|
previews.push(
|
70
103
|
React.createElement("div", {className: "attache-file-input"},
|
71
104
|
React.createElement("input", {type: "hidden", name: that.props.name, value: json, readOnly: "true"}),
|
@@ -90,7 +123,7 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
|
|
90
123
|
|
91
124
|
var className = ["attache-file-selector", "attache-placeholders-count-" + placeholders.length, "attache-previews-count-" + previews.length, this.props['data-classname']].join(' ').trim();
|
92
125
|
return (
|
93
|
-
React.createElement("label", {htmlFor: that.props.id, className: className},
|
126
|
+
React.createElement("label", {htmlFor: that.props.id, className: className, onDragOver: this.onDragOver, onDragLeave: this.onDragLeave, onDrop: this.onDrop},
|
94
127
|
React.createElement("input", React.__spread({type: "file"}, that.props, {onChange: this.onChange})),
|
95
128
|
React.createElement("input", {type: "hidden", name: that.props.name, value: ""}),
|
96
129
|
React.createElement(Header, React.__spread({}, that.props)),
|
@@ -21,17 +21,20 @@ var AttacheFileInput = React.createClass({
|
|
21
21
|
this.setState(this.state);
|
22
22
|
},
|
23
23
|
|
24
|
-
|
25
|
-
var file_element = this.getDOMNode().firstChild;
|
24
|
+
performUpload: function(file_element, files) {
|
26
25
|
// user cancelled file chooser dialog. ignore
|
27
|
-
if (!
|
28
|
-
if (! this.props.multiple)
|
26
|
+
if (! files || files.length == 0) return;
|
27
|
+
if (! this.props.multiple) {
|
28
|
+
this.state.files = {};
|
29
|
+
files = Array.prototype.splice.apply(files, [0, 1]); // array of 1 element
|
30
|
+
}
|
29
31
|
|
30
32
|
this.setState(this.state);
|
31
33
|
// upload the file via CORS
|
32
34
|
var that = this;
|
33
35
|
new AttacheCORSUpload({
|
34
36
|
file_element: file_element,
|
37
|
+
files: files,
|
35
38
|
onComplete: this.setFileValue,
|
36
39
|
onProgress: this.setFileValue,
|
37
40
|
onError: function(uid, status) {
|
@@ -44,6 +47,31 @@ var AttacheFileInput = React.createClass({
|
|
44
47
|
file_element.value = '';
|
45
48
|
},
|
46
49
|
|
50
|
+
onChange: function() {
|
51
|
+
var file_element = this.getDOMNode().firstChild;
|
52
|
+
this.performUpload(file_element, file_element && file_element.files);
|
53
|
+
},
|
54
|
+
|
55
|
+
onDragOver: function(e) {
|
56
|
+
e.stopPropagation();
|
57
|
+
e.preventDefault();
|
58
|
+
$(this.getDOMNode()).addClass('attache-dragover');
|
59
|
+
},
|
60
|
+
|
61
|
+
onDragLeave: function(e) {
|
62
|
+
e.stopPropagation();
|
63
|
+
e.preventDefault();
|
64
|
+
$(this.getDOMNode()).removeClass('attache-dragover');
|
65
|
+
},
|
66
|
+
|
67
|
+
onDrop: function(e) {
|
68
|
+
e.stopPropagation();
|
69
|
+
e.preventDefault();
|
70
|
+
var file_element = this.getDOMNode().firstChild;
|
71
|
+
this.performUpload(file_element, e.target.files || e.dataTransfer.files);
|
72
|
+
$(this.getDOMNode()).removeClass('attache-dragover');
|
73
|
+
},
|
74
|
+
|
47
75
|
setFileValue: function(key, value) {
|
48
76
|
this.state.files[key] = value;
|
49
77
|
this.setState(this.state);
|
@@ -58,14 +86,19 @@ var AttacheFileInput = React.createClass({
|
|
58
86
|
|
59
87
|
var previews = [];
|
60
88
|
$.each(that.state.files, function(key, result) {
|
89
|
+
// json is input[value], drop non essential values
|
90
|
+
var copy = JSON.parse(JSON.stringify(result));
|
91
|
+
delete copy.src;
|
92
|
+
delete copy.filename;
|
93
|
+
var json = JSON.stringify(copy);
|
94
|
+
//
|
95
|
+
result.multiple = that.props.multiple;
|
61
96
|
if (result.path) {
|
62
97
|
var parts = result.path.split('/');
|
63
98
|
parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
|
64
99
|
result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
|
65
100
|
result.filename = result.src.split('/').pop().split(/[#?]/).shift();
|
66
|
-
result.multiple = that.props.multiple;
|
67
101
|
}
|
68
|
-
var json = JSON.stringify(result);
|
69
102
|
previews.push(
|
70
103
|
<div className="attache-file-input">
|
71
104
|
<input type="hidden" name={that.props.name} value={json} readOnly="true" />
|
@@ -90,7 +123,7 @@ var AttacheFileInput = React.createClass({
|
|
90
123
|
|
91
124
|
var className = ["attache-file-selector", "attache-placeholders-count-" + placeholders.length, "attache-previews-count-" + previews.length, this.props['data-classname']].join(' ').trim();
|
92
125
|
return (
|
93
|
-
<label htmlFor={that.props.id} className={className}>
|
126
|
+
<label htmlFor={that.props.id} className={className} onDragOver={this.onDragOver} onDragLeave={this.onDragLeave} onDrop={this.onDrop}>
|
94
127
|
<input type="file" {...that.props} onChange={this.onChange}/>
|
95
128
|
<input type="hidden" name={that.props.name} value="" />
|
96
129
|
<Header {...that.props} />
|
data/lib/attache_rails/model.rb
CHANGED
@@ -92,7 +92,8 @@ module AttacheRails
|
|
92
92
|
define_method "#{name}_attributes", -> (geometry) { str = self.send(name); Utils.attache_url_for(str, geometry) if str; }
|
93
93
|
define_method "#{name}=", -> (value) {
|
94
94
|
new_value = (value.respond_to?(:read) ? Utils.attache_upload_and_get_json(value) : value)
|
95
|
-
|
95
|
+
okay = JSON.parse(new_value)['path'] rescue nil
|
96
|
+
super(Utils.array(okay ? new_value : nil).first)
|
96
97
|
}
|
97
98
|
define_method "#{name}_discard_was",-> do
|
98
99
|
new_value = self.send("#{name}")
|
@@ -121,7 +122,11 @@ module AttacheRails
|
|
121
122
|
end
|
122
123
|
}
|
123
124
|
define_method "#{name}=", -> (array) {
|
124
|
-
new_value = Utils.array(array).
|
125
|
+
new_value = Utils.array(array).inject([]) {|sum,value|
|
126
|
+
hash = value.respond_to?(:read) ? Utils.attache_upload_and_get_json(value) : value
|
127
|
+
okay = JSON.parse(hash)['path'] rescue nil
|
128
|
+
okay ? sum + [hash] : sum
|
129
|
+
}
|
125
130
|
super(Utils.array new_value)
|
126
131
|
}
|
127
132
|
define_method "#{name}_discard_was",-> do
|
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.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- choonkeat
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-04-
|
11
|
+
date: 2015-04-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|