attache_rails 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|