From 9d85972b1c3674012335512289376cd7f5c627b3 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 09:20:44 -0400 Subject: [PATCH 01/18] add bootstrap + server scripts, set up dev test pages --- .gitignore | 1 + pretty_file_input.gemspec | 1 + script/bootstrap | 6 ++++++ script/server | 3 +++ spec/dummy/config/database.yml | 4 ++++ 5 files changed, 15 insertions(+) create mode 100755 script/bootstrap create mode 100755 script/server diff --git a/.gitignore b/.gitignore index 4c4665e..b0b82ff 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ spec/dummy/tmp/* spec/dummy/log/* spec/dummy/public/uploads/* spec/dummy/db/test.sqlite +spec/dummy/db/development.sqlite diff --git a/pretty_file_input.gemspec b/pretty_file_input.gemspec index 17aee99..3c28faa 100644 --- a/pretty_file_input.gemspec +++ b/pretty_file_input.gemspec @@ -27,4 +27,5 @@ Gem::Specification.new do |s| s.add_development_dependency 'selenium-webdriver', '2.45.0' s.add_development_dependency 'simple_form', '3.1.0' s.add_development_dependency 'sqlite3', '1.3.9' + s.add_development_dependency 'thin', '1.6.3' end diff --git a/script/bootstrap b/script/bootstrap new file mode 100755 index 0000000..694d75e --- /dev/null +++ b/script/bootstrap @@ -0,0 +1,6 @@ +#! /bin/bash + +bundle install +cd spec/dummy +bundle exec rake db:create db:migrate +cd ../../ diff --git a/script/server b/script/server new file mode 100755 index 0000000..8becf9e --- /dev/null +++ b/script/server @@ -0,0 +1,3 @@ +#! /bin/bash + +bundle exec thin start --chdir spec/dummy --port 9393 diff --git a/spec/dummy/config/database.yml b/spec/dummy/config/database.yml index 1d1a221..b8ee8ec 100644 --- a/spec/dummy/config/database.yml +++ b/spec/dummy/config/database.yml @@ -1,3 +1,7 @@ +development: + adapter: sqlite3 + database: db/development.sqlite + test: adapter: sqlite3 database: db/test.sqlite From 0a5ce8f638cac86d1dd066ef654342ea4a0e5f52 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 09:39:25 -0400 Subject: [PATCH 02/18] refactor v1 --- .../javascripts/pretty_file_input.coffee | 20 +++++++---- app/assets/stylesheets/pretty_file_input.scss | 19 ----------- lib/pretty_file_input/component.rb | 10 +++--- .../dummy/app/controllers/users_controller.rb | 12 +++++++ spec/dummy/spec/features/users_spec.rb | 32 ++++++++++++++++++ spec/dummy/spec/fixtures/error.jpg | Bin 0 -> 7500 bytes spec/dummy/spec/fixtures/unknownerror.jpg | Bin 0 -> 7500 bytes 7 files changed, 63 insertions(+), 30 deletions(-) create mode 100644 spec/dummy/spec/fixtures/error.jpg create mode 100644 spec/dummy/spec/fixtures/unknownerror.jpg diff --git a/app/assets/javascripts/pretty_file_input.coffee b/app/assets/javascripts/pretty_file_input.coffee index 4988367..3cab612 100644 --- a/app/assets/javascripts/pretty_file_input.coffee +++ b/app/assets/javascripts/pretty_file_input.coffee @@ -14,8 +14,8 @@ @$form = @$el.closest('form') @$input = @$el.find('input') - @$filename = @$el.find('.pfi_existing_filename') - @$status = @$el.find('.pfi_status') + @$filename = @$el.find('.js_pfi_filename') + @$status = @$el.find('.js_pfi_status') # If we're not persisted, immediately add the correct input name if !@options.persisted @@ -41,7 +41,10 @@ else @$input.val('') - @$el.removeClass('is_uploaded') + @_toggleState() + + _toggleState: -> + $('.js_pfi_present, .js_pfi_blank').toggle() _baseParams: -> $.extend { pretty_file_input: true }, @options.additionalParams @@ -98,10 +101,15 @@ @options.additionalParams = data.additionalParams @$status.text('') - @$el.addClass('is_uploaded') + @_toggleState() + + _uploadError: (xhr) -> + msg = if (err = xhr.responseJSON?.error) + "Error: #{err}" + else + 'Whoops! An error occurred.' - _uploadError: -> - @$status.text 'Error' + @$status.text msg setTimeout ( => @$status.text('') ), 2000 _eventToFilename: (e) -> diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index fbdd279..e69de29 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,19 +0,0 @@ -// A more functional file input -.pfi { - input { - display: inline; - } -} - -.pfi_uploaded{ - display: none; -} - -.is_uploaded { - .pfi_uploaded { - display: block; - } - .pfi_not_uploaded { - display: none; - } -} diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index c8eba71..3e52677 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -10,7 +10,7 @@ class PrettyFileInput::Component < Erector::Widget def content div( - class: "pfi cf #{@filename ? 'is_uploaded' : ''}", + class: 'pfi cf', 'data-pfi' => { name: @name, persisted: @persisted, @@ -19,14 +19,14 @@ def content additionalParams: @additional_params }.to_json ) { - div.pfi_uploaded { - span.pfi_existing_filename @filename + div.js_pfi_present(style: @filename ? nil : 'display:none;') { + span.js_pfi_filename @filename text ' ' a.button.mini.info 'Remove', 'data-pfi-remove' => true } - div.pfi_not_uploaded { + div.js_pfi_blank(style: @filename ? 'display:none;' : nil) { input type: 'file' - span.pfi_status + span.js_pfi_status } } end diff --git a/spec/dummy/app/controllers/users_controller.rb b/spec/dummy/app/controllers/users_controller.rb index 7013b47..ac9906a 100644 --- a/spec/dummy/app/controllers/users_controller.rb +++ b/spec/dummy/app/controllers/users_controller.rb @@ -15,6 +15,18 @@ def edit end def update + # Hack for testing errors + if user_params[:avatar] + if user_params[:avatar].original_filename.match('unknownerror') + return head :bad_request + elsif user_params[:avatar].original_filename.match('error') + return render( + json: { error: 'This is a server-generated error message.' }, + status: :bad_request + ) + end + end + @user = User.find(params[:id]) @user.update(user_params) diff --git a/spec/dummy/spec/features/users_spec.rb b/spec/dummy/spec/features/users_spec.rb index 05b8e42..81aa14d 100644 --- a/spec/dummy/spec/features/users_spec.rb +++ b/spec/dummy/spec/features/users_spec.rb @@ -49,4 +49,36 @@ expect(user.avatar.file.filename).to eq 'avatar2.jpg' end end + + describe 'error messages' do + before do + user.update(remove_avatar: true) + end + + it 'displays server-generated errors' do + visit edit_user_path(user) + find('input[type=file]').set "#{Rails.root}/spec/fixtures/error.jpg" + sleep 1 + expect(page).to have_text 'server-generated error message' + + # Error clears after an interval + sleep 1.5 + expect(page).to_not have_text 'server-generated error message' + + expect(user.reload.avatar).to be_blank + end + + it 'falls back to a generic error' do + visit edit_user_path(user) + find('input[type=file]').set "#{Rails.root}/spec/fixtures/unknownerror.jpg" + sleep 1 + expect(page).to have_text 'Whoops!' + + # Error clears after an interval + sleep 1.5 + expect(page).to_not have_text 'Whoops!' + + expect(user.reload.avatar).to be_blank + end + end end diff --git a/spec/dummy/spec/fixtures/error.jpg b/spec/dummy/spec/fixtures/error.jpg new file mode 100644 index 0000000000000000000000000000000000000000..811d5f49448eced6f5ed5f1070f57d6f015e522d GIT binary patch literal 7500 zcmbW52UHYGx9_VbGUS{j3_0hVa}p3lf?yyFLr}?CkRS*O2m*>IAS#HU9uQC@DNzyR z5JW^oV2~ujkt9l*;Wm1Xp6|VN?|bX+S*!Zj)w`~3$rWU3Ef*@cH z|G@4fNH>Y}^#Z`!8b|^Fr~n#b21uA7_y-_vfd0V%?1%RKVmnCuZyy8zDZT*pw~q^a z+%vf6z1DvpkvE~=J>Eq8@>aZw{LOpKcK-tEwmt!&0U!!UODBkf@eBO_N^I~!9AD-&2C0JP>-zWxCSMgaW$Lxb(i z4DpAZUGUgmfB-mv0SW-P6G8&551HEU^=V;Zgb#t8e)RvV`1baP4lpQVZi~nNs{a22 zCPH9vC>#h|*j>q!7(#$K3FcD~p@Dn#%P_NgoZMr?o<`PScz`f-?y>hzmj2=MllAx5 z)6d@%_SqYApr@bb9(TZeK0J&FGtvs?7Csf`=L_=&%&dMy_YeS3w0rfT zM1l{@@-Wi|+uIqztPM{;t@pp!<6j&~jD*JtfKfnTRIsnNPbglTAc0rV&``&l6C+L$ zLqlb3-3ce%gFW#^0e*q*{!sw@)V$XUFz>|{4+mLQK|@tlMo|_H|1bL=FaGlSpJ8uq ze|oGP{4r+`d(ZE>-)(=_1>A<$)H)oSOTX(pt^x4m8~~i}f7c1$1b`t4fZD!)>0#en zFFv86ftqr15fKrxzC?oTUO<1@|I^`@=YJ3Xx}WUc{eHy`Z%p)Z4?7i#-wP@s;8Z|Z zFg_&Eoj}CP{GW^Xf8Fq3!}`}ar0s}a#9*R7d@DzImHGO6!_)2W=^N@B;E(t9|Lly}@5(;2-l?9A_tN{5}4?wZd0OZjd@D=FSyjkHK!QPYS#6S0Q-NOuD z|55%&fyjhU5h1?b_`PZ)J9|7KEI53R;b&s6Km%&P09XMR-~&QH9LNAgpa!&nJ}?3M zfeo++&fqv803YB7fhA7Qu?(MTjEg5b6j6geAfraSY*&2tu4jBq1^od5GJH z2Z&lkE8-Pm2th(DAl8upNrPlZ3Ls^W>PRD`4blbag$zcEk1~5~Ybu1Rkg_XkU zU~RDO*idXT_8Rs9wi){xJA>VzqM_oaQlv7aa-s64I!l#Hb&u*9)oZFbs%;!2P6Vfk zv%z`dqHvkG5?lkW4>yC`re>lRqt>Cer#?ZQK%GZjLH(Ti1N9mW4UHg;2F*blUz&KD zJer3zFKH%eHffn@C25UlkJ5(GX3*ZHZJ`~ZU8AF;6Q$FqbD;~R%b+W#Yo{Bh+n{Hm zm!-F$_oR=b&!?}Ye@*{|0mmT1V8C#k;WR@oLk&Y8!y+S&QIye$(Va1tF`u!XahP$P ziG@jl$%e^~DV^yaQy0@GW-PNPvk9{&a}skgb35}C3z9{M#fXK#lE_lR@|{}eX90nXjjtd+W z9IrXPbME8R=Ol8ba#nH6=NL|QF=(13o(6TVU zu(fcE@O|O;A~+Fs5g(DOBAp`NMa4v&L{mhch<*~|6tfUJEp}h*gE*bIo_LV>ZSgk} z7zuTWlM;mz{gMbt6-gh-e91m3gp{h3uT-JbfHYcKL)u^Zw)C(Jt&D+8xXgW-Nm+JT zE7`NMPh`Ky3Cp?2Wyy8QQRG$RPsx|ak18-L>{mFe(4erYD5*$L%vXG)M5kn`6sJ_D zw4yAfOjN$1{7!{M#abmrrA>vbs-_yOTA@0xCamVBR-iVl&Z=&!p055<1Fd1G5vS3l zv8k!58LC;WxuhkdbyDk|)+cQ-ZK8IG_LPpGj=Rn+9g;3y*G>1PE=f;7&t31f-bZ~Q zeNX*T{W${(gA)c1489o38wMLbHvDd+X>`V@#TaR9W}Ir=Yr<^eU~=7L+*Hui+w{Ka zvYComv{{Qe+T7AS%Y4{^*MeYCZn3;yZU3459hS6~hb*sKezcOb3btynMp*B+&awV* zK;(e`fhRV=#=<7YX3SR1HpsT|Am*U$!Tf`>b_#YecAbY<4!It>cj%kFp?#+PsDrpe zm_wT*gX2-ha>wsZ#!lHzq{DKD&m4Z`%U&=HoG0oK zvx#$FI$qgcpS*RvbG+w$^n7xC7JZF;uluf?Fh5ar;`>RPlXp+=||<~=2!2} z?0?d~BY-a;GGHK3Dlj>a6r>q+C1^R=GPpDZ3ON>17s?86rh3A}!_I|GhUDPIjZ2tI{+Hfn>1CB=Gi9I7p31S#slAN9oO=1| z71t|WxyrdkSE;XtT_xpN<<(sizIN%_&UK&bL-~gJl?6Nn7Ye=?dKSLEp?{;Ih_@)M zXzQl$&3CuVZq?ovy`5W(DGo25EpaUAyrX`nyp+2%t(1J%|1PP_uB@Y6t-Smm&%Mn1 zi2Gsp=N}w>(Eo?=A9WQn6}KwcE7Kl=hhYytSGiTat+uRgt5L71cqHqvW<6}1e)@nvOUdwM*S@5*>3ac=Jl4qmc>@@)~Pnv zw$b*(?Qc2`cJw~CeE#x<>5KMGgU;rcIxm~LG`s4%)w`d(Qhin1qtf&EPnAC(_p0{R z_Nn#N^=tGu3}_ELd#(4nbH?FzKD=yH6vhMpoX3zuz8> z|A79GI>tDbJI*tHdqQHOlB7y{I%z!F^YPHf(J8{z!gR>=&P>uQ-E8h0|6KVe#ZOK1 zrt|%uk9?k42wd1+O#X}MuYxb)Umh*#FZC=RUY=PAUfEquU*lT4`&IdC+q&)g_&2|A z+uu_+xHif*)i*o0oVMn+BX+Pmd1MK41I3c^Vb^bWcef2NQNamc5eYE?1QUd0f_6Iq zKfIGb!$}*qy&VEwt8A_NYV<(!b)w#La1bO@To`{Hy zI-Q(y{zB@d+^c!luHU>#* z8PK)dSG*isyTMS+7uGzqk-pFy^JV-<4a@EEwe<+u8pmRhVbs(*uGIV%peXuvuTg!i*RZkHX3akynl6AJ-Uf7wz+-a zK&>{paMo{Tyfan(Sn8FbY3cSjcwAKQDu>XB`jN`-{gv})(j%hp?1IM8@ljbeQMG8r zl5+xw|LPw(>ilIi)YjSWIBxU{OXG%|-+7aeXv;bdmCmo;A>rSh@&ym6^v>`ND}FTT za5{89W>oCbQGxKeuis|->x;v0i1e<$KiSxL=jf}Kxhqcjh|;Io3eEn?^$)Fph*b3P z1)pnjPxxO;)@4wAk?Xjc6=YNw`Y{bdB2SMoeSww?y7fA8$0!CMeULE zH~%jC$vYYRKLo&!tseAQ)9R_yxF>e|YPKFpuZVv@{dCnMo=W+e*QfCCcu`rG z_?z^|9dbbXRr>i4#f{g$-XcqpH+Dg|=T2fTbR=^_J=lEaxyRACgb_iFAi8s(g92^t zV#(gJI!WEFsEHiP3MFEFByODM^2^M|ZY8RVSr-|WC$^`^iP|?$4{scP$>O^`bt%ql zUFloWLO`b85})f*O!G%G^3+bxR%BE`%j9LkkreH%sLDTI3D8UJu=BpKBBo!Pq7235 zrQAE;1w<6}?%v%j8Zg@NXfMmOY5XwF(wX_aZ`+KcJENemIASK&h#|XR)xX>C&sENq z3=QekZo9G1Q=7QABfXuwzlj-|DXH8MQHr4so z+`NT*eWv{^uj&cL%KbGC$IUBcmuYg3B);y0?;1JNE|9aR%_!9}N3P@_pe(eK_1>C} zz0uY24^NSz#L*{nId73%4&L=3j7DnnVRDU95@_jHYID=Zf5lI{L zLgBr((kJ)m;?^_Iipj4iRk3p0uCu!!W`TjX=T~2GX}G&C)ggq#FfqF>3S00}3JqDL zOC}YW_!bu`lxo?Rsw9=lUi6)<5N%d1D%RHF);L&J=E&Ca2eoJV=7X|+i8TbmUihN= z+lHLV9)+-a$JH=~rBwBjD8QB56J2s)Na}o+smG0vLwrm6<)Ung!ztD#Hp`E@WU4Fe zMXj7^nUk(ii||wx?*g`@nBL~LS!0g-36`2|#wTvw9IW3!_q}+9uI`#fhf};yY zFh|epro{!p0-Z}-_F2-xL3v%f08cQBil#pFrS`r>p~IxnF{DG!iCH7fK}p*y4?N7u z238enp)7shZcN6Y@-Ei2Co74 z0ws;#z;{DzJ5wtEez0BEQO(n4MejNiv=@ax8+&E1cFwX5yu2VMTKxwVhq7Vr^`O|P z$7T7U^D3{;6rJbis6TQpZ{`YwVtHL+cad+UVgH@^uX^MCms1Zi>=5J93dY*%|0>D( z#9BaoS)wBKM7Hu;)1;zL9p%lZL75f1DIs*$%t}n1uXd|)s_?eN#=VOn-49B#99*7B z8=k&xgBnaM|DJk7ISU`xdVGwsaFs%v(H&fFdJk`3w3zWc16Px>cO=m{A7MRJSM@J_jtm}tl^ zn9_z{U6eW2@=4GF;cYvSUS)LDD~susMvra!XJW&HyzgTIi+V!5-hXMX1ltW)9n|6zD@Bt2!YCTDhCqWAgb^OCXDWu4}KrX5qeP---g(eSy&^^8a=2SSgjm1u|hgCk2kT4hxOHz<}Xg=vkEF%|u02D5YKaTTY^ zAL&!g=|Kk%r3{jt{rbe2h`pS_nG@cxP1AHjo|A5@e7&%AJt8waGACtqf{ALvhRJsA zme|LM%hrVcGD#zzV>-K_eJgIrMaDt0Q))f(%<(u$diqK@+`sn=jQ3_0zI)i<)ul76 zo3yO+I!dF9_9l^OZ{vmp5CRSFR^hMWI0!HaC@{jah!0xMO1M=u&^o#De@)_EvSc)8 zFO-jsIh&HJCm+mLtkaNL8uCn+I>w_h?OOrENHc%4o-d=9QO4TR^FlLDjn|Yo zn+Z=EQhZRK^V8<0K$8D{9+8sHAxE{7_@NbwXMyGPLGm`G zR-=|$W!su=Tx(`yPUek#_%x4V^1|%}tq{3w@-9%HUWmy{iyjpcgDg8?`9HRIaHV_j#p znzo)aA2;*;iXBQ+uW0pH>ih7pHx|x7P2}0IyzK>+CyO!7SjD|LSPo^L9kSU>J`s+}Ws4w`1h%x8|WJPV>u z4Fpg|P1w?v=C67)MGSb-ZEkP5i}Noly3Hy+#PST9W%T?x-JY28(c3v?Sg%>`ZC4G6 zKC^+6t3Q5VX@VTo`t59FTuRMqTrVZCw3O1Jmq;o?F7AS0V%v0c=AtVf@mCIJG*;Hw zr!>9U*=p9i&s&Sc7dw*1%>sE(uQ3kV~D%+7YHhW@iimz@JlV8k0 zq)DyLvCi3ouP*q6*)`sY?k}-vyMTuBK8eHt@f|6u@a@BUE1h{%AM?~*W1+Bjy}?au zeWJE`ko5W8(gCL@tGaPjjPw}qQ8JmbHX-yrl;W9_!hg|B_sjS73w=xEOV9j^=C+^o zHUD}sGRAHqIhi@-4GS*~v3~CARA-8}7BG3&I4N+JHL2>7-KjsGiWih?r%ONwMuKGp z_i;L|@KpHE^L7F4xtJ~3L?s8-tG z9bVJDOI+D2@kLULY*L$0t|phsJ`7zDZcf6Lq0RU+m2`gVMFB1_fx+Y3n5i2c_F3NT zzPmb9*=NV6Lv+h=68=g};*3r{dXsA3mpaIthc;70L%`Te9xEW`bW@};ZXZXzLh-jC zdDbvP=^=qTsB8}?WBn1k_Jts(mXng%O3GKBTf0%^XS2?)dzW!g#S@iULNM_aIc{tt zrNoD8vUX}K1>GKBSTOeY-Y=oiNyb&Qn?z!Ya9-peD<4?2lLS!a532MLP6u&Zp5}%u zNSv7bc#yAC4VRbynKoh<8fl7K2~L|d^EESc1ITz9&2$gXSw@@sdz?{9xiuHm*^ERU z1R~Vi^44gNO2_5(DmNw$c!IJOkLIrAo6d?UtQkd2w_x;ye;F%`ak literal 0 HcmV?d00001 diff --git a/spec/dummy/spec/fixtures/unknownerror.jpg b/spec/dummy/spec/fixtures/unknownerror.jpg new file mode 100644 index 0000000000000000000000000000000000000000..811d5f49448eced6f5ed5f1070f57d6f015e522d GIT binary patch literal 7500 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 literal 0 HcmV?d00001 From 0426ddf0ee356f29156bad9bad87cb0509934eda Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 10:15:33 -0400 Subject: [PATCH 03/18] mas --- Gemfile | 2 + .../javascripts/pretty_file_input.coffee | 2 +- app/assets/stylesheets/pretty_file_input.scss | 33 ++++++++++++++++ lib/pretty_file_input/component.rb | 16 +++++--- pretty_file_input.gemspec | 1 + .../app/assets/stylesheets/application.css | 13 ------- .../assets/stylesheets/application.css.scss | 12 ++++++ .../dummy/app/controllers/users_controller.rb | 36 ++++++++++++------ .../app/views/layouts/application.html.erb | 4 +- spec/dummy/config/initializers/simple_form.rb | 1 + spec/dummy/spec/fixtures/loading.jpg | Bin 0 -> 7500 bytes 11 files changed, 86 insertions(+), 34 deletions(-) delete mode 100644 spec/dummy/app/assets/stylesheets/application.css create mode 100644 spec/dummy/app/assets/stylesheets/application.css.scss create mode 100644 spec/dummy/config/initializers/simple_form.rb create mode 100644 spec/dummy/spec/fixtures/loading.jpg diff --git a/Gemfile b/Gemfile index 3be9c3c..49b3888 100644 --- a/Gemfile +++ b/Gemfile @@ -1,2 +1,4 @@ source "https://rubygems.org" gemspec + +gem 'dvl-core', github: 'dobtco/dvl-core' diff --git a/app/assets/javascripts/pretty_file_input.coffee b/app/assets/javascripts/pretty_file_input.coffee index 3cab612..1573e16 100644 --- a/app/assets/javascripts/pretty_file_input.coffee +++ b/app/assets/javascripts/pretty_file_input.coffee @@ -128,7 +128,7 @@ @_uploadSuccess() _bindEvents: -> - @$el.on 'click', '[data-pfi-remove]', $.proxy(@remove, @) + @$el.on 'click', '.js_pfi_remove', $.proxy(@remove, @) @_bindInputChange() # FF6 doesn't bubble the 'change' event, so we need to bind diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index e69de29..fad07b3 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -0,0 +1,33 @@ +.pfi_file_wrapper { + width: 300px; + position: relative; + display: inline-block; + height: $inputHeight; + + input, .input_group { + width: 100%; + position: absolute; + top: 0; + left: 0; + } + + input { + opacity: 0; + } + + .input_group :first-child { + display: table-cell; + width: 100%; + padding: 0 0.5rem; + border: 1px solid $lightGray; + border-right: 0; + color: $darkGray; + border-top-left-radius: $radius; + border-bottom-left-radius: $radius; + } +} + +// Override label weight +label.pfi_file_wrapper { + font-weight: $weightNormal; +} diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 3e52677..6e2655e 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -19,14 +19,18 @@ def content additionalParams: @additional_params }.to_json ) { - div.js_pfi_present(style: @filename ? nil : 'display:none;') { - span.js_pfi_filename @filename - text ' ' - a.button.mini.info 'Remove', 'data-pfi-remove' => true + div.js_pfi_present.pfi_file_wrapper(style: @filename ? nil : 'display:none;') { + div.input_group { + span.js_pfi_filename @filename + a.button.info.js_pfi_remove 'Remove' + } } - div.js_pfi_blank(style: @filename ? 'display:none;' : nil) { + label.js_pfi_blank.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { input type: 'file' - span.js_pfi_status + div.input_group { + span 'Choose a file...' + span.button.info 'Browse' + } } } end diff --git a/pretty_file_input.gemspec b/pretty_file_input.gemspec index 3c28faa..0643569 100644 --- a/pretty_file_input.gemspec +++ b/pretty_file_input.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |s| s.add_development_dependency 'capybara', '2.4.4' s.add_development_dependency 'carrierwave' + s.add_development_dependency 'dvl-core' s.add_development_dependency 'rails', '4.1.9' s.add_development_dependency 'rspec-rails', '3.1.0' s.add_development_dependency 'selenium-webdriver', '2.45.0' diff --git a/spec/dummy/app/assets/stylesheets/application.css b/spec/dummy/app/assets/stylesheets/application.css deleted file mode 100644 index 5e09656..0000000 --- a/spec/dummy/app/assets/stylesheets/application.css +++ /dev/null @@ -1,13 +0,0 @@ -/* - * This is a manifest file that'll be compiled into application.css, which will include all the files - * listed below. - * - * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, - * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. - * - * You're free to add application-wide styles to this file and they'll appear at the top of the - * compiled file, but it's generally better to create a new file per style scope. - * - *= require pretty_file_input - *= require_tree . - */ diff --git a/spec/dummy/app/assets/stylesheets/application.css.scss b/spec/dummy/app/assets/stylesheets/application.css.scss new file mode 100644 index 0000000..59c4af1 --- /dev/null +++ b/spec/dummy/app/assets/stylesheets/application.css.scss @@ -0,0 +1,12 @@ +@import 'dvl/app'; +@import 'pretty_file_input'; + +body { + background: #ccc; +} + +.container { + margin: 50px; + padding: 50px; + background: white; +} diff --git a/spec/dummy/app/controllers/users_controller.rb b/spec/dummy/app/controllers/users_controller.rb index ac9906a..8962ed3 100644 --- a/spec/dummy/app/controllers/users_controller.rb +++ b/spec/dummy/app/controllers/users_controller.rb @@ -1,6 +1,9 @@ class UsersController < ActionController::Base layout 'application' + before_action :error_hack, only: [:update] + before_action :loading_hack, only: [:update] + def new @user = User.new end @@ -15,18 +18,6 @@ def edit end def update - # Hack for testing errors - if user_params[:avatar] - if user_params[:avatar].original_filename.match('unknownerror') - return head :bad_request - elsif user_params[:avatar].original_filename.match('error') - return render( - json: { error: 'This is a server-generated error message.' }, - status: :bad_request - ) - end - end - @user = User.find(params[:id]) @user.update(user_params) @@ -41,4 +32,25 @@ def update def user_params params.require(:user).permit! end + + def error_hack + if user_params[:avatar] + if user_params[:avatar].original_filename.match('unknownerror') + head :bad_request + elsif user_params[:avatar].original_filename.match('error') + render( + json: { error: 'This is a server-generated error message.' }, + status: :bad_request + ) + end + end + end + + def loading_hack + if user_params[:avatar] + if user_params[:avatar].original_filename.match('loading') + sleep 3 + end + end + end end diff --git a/spec/dummy/app/views/layouts/application.html.erb b/spec/dummy/app/views/layouts/application.html.erb index ecbe539..d805c4a 100644 --- a/spec/dummy/app/views/layouts/application.html.erb +++ b/spec/dummy/app/views/layouts/application.html.erb @@ -8,8 +8,8 @@ <%= csrf_meta_tags %> - +
<%= yield %> - +
diff --git a/spec/dummy/config/initializers/simple_form.rb b/spec/dummy/config/initializers/simple_form.rb new file mode 100644 index 0000000..d50e51f --- /dev/null +++ b/spec/dummy/config/initializers/simple_form.rb @@ -0,0 +1 @@ +require 'dvl/simple_form_config' diff --git a/spec/dummy/spec/fixtures/loading.jpg b/spec/dummy/spec/fixtures/loading.jpg new file mode 100644 index 0000000000000000000000000000000000000000..811d5f49448eced6f5ed5f1070f57d6f015e522d GIT binary patch literal 7500 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 literal 0 HcmV?d00001 From 071b5ffcd7a44f21e42463422c0852282c33359a Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 10:37:35 -0400 Subject: [PATCH 04/18] more --- .../javascripts/pretty_file_input.coffee | 37 ++++++++++++++----- app/assets/stylesheets/pretty_file_input.scss | 37 ++++++++++++++----- lib/pretty_file_input/component.rb | 4 +- 3 files changed, 57 insertions(+), 21 deletions(-) diff --git a/app/assets/javascripts/pretty_file_input.coffee b/app/assets/javascripts/pretty_file_input.coffee index 1573e16..1f82c8e 100644 --- a/app/assets/javascripts/pretty_file_input.coffee +++ b/app/assets/javascripts/pretty_file_input.coffee @@ -16,6 +16,10 @@ @$input = @$el.find('input') @$filename = @$el.find('.js_pfi_filename') @$status = @$el.find('.js_pfi_status') + @$button = @$el.find('.js_pfi_browse') + + @buttonText = @$button.text() + @statusText = @$status.text() # If we're not persisted, immediately add the correct input name if !@options.persisted @@ -36,6 +40,8 @@ @_bindEvents() remove: -> + @$status.text @statusText + if @options.persisted @_ajaxRemove() else @@ -63,9 +69,9 @@ dataType: 'json' data: @_baseParams() uploadProgress: (_, __, ___, percentComplete) => - @$status.text( + @$button.text( if percentComplete == 100 - 'Finishing' + 'Finishing...' else "Uploading (#{percentComplete}%)" ) @@ -100,17 +106,29 @@ if data?.additionalParams? @options.additionalParams = data.additionalParams - @$status.text('') + @$button.removeClass('disabled') + @$button.text @buttonText @_toggleState() _uploadError: (xhr) -> - msg = if (err = xhr.responseJSON?.error) - "Error: #{err}" - else - 'Whoops! An error occurred.' + @$button.removeClass('disabled') + @$button.text @buttonText + @_flashError( + if (err = xhr.responseJSON?.error) + "Error: #{err}" + else + 'Whoops! An error occurred.' + ) + + _flashError: (msg) -> @$status.text msg - setTimeout ( => @$status.text('') ), 2000 + @$status.addClass 'is_error' + + setTimeout => + @$status.removeClass 'is_error' + @$status.text @statusText + , 2500 _eventToFilename: (e) -> if e.target.files? @@ -122,7 +140,8 @@ @$filename.text @_eventToFilename(e) if @options.persisted - @$status.text 'Uploading...' + @$button.addClass('disabled') + @$button.text 'Uploading...' @_ajaxUpload() else @_uploadSuccess() diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index fad07b3..6331a43 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,9 +1,11 @@ .pfi_file_wrapper { - width: 300px; + width: 100%; + max-width: 400px; position: relative; display: inline-block; height: $inputHeight; + // Position the items absolutely input, .input_group { width: 100%; position: absolute; @@ -11,19 +13,34 @@ left: 0; } + // Hide the input via opacity input { opacity: 0; } - .input_group :first-child { - display: table-cell; - width: 100%; - padding: 0 0.5rem; - border: 1px solid $lightGray; - border-right: 0; - color: $darkGray; - border-top-left-radius: $radius; - border-bottom-left-radius: $radius; + .input_group { + // Necessary for ellipsis to work + table-layout: fixed; + + span { + display: table-cell; + width: 65%; + padding: 0 0.5rem; + border: 1px solid $lightGray; + border-right: 0; + color: $darkGray; + border-top-left-radius: $radius; + border-bottom-left-radius: $radius; + @include ellipses; + + &.is_error { + border-color: $errorColor; + } + } + + a { + width: 35%; + } } } diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 6e2655e..4179dfb 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -28,8 +28,8 @@ def content label.js_pfi_blank.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { input type: 'file' div.input_group { - span 'Choose a file...' - span.button.info 'Browse' + span.js_pfi_filename.js_pfi_status 'Choose a file...' + a.button.info.js_pfi_browse 'Browse' } } } From 66e5122a0448e53bc946141af7b8fd5a99286c79 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 10:43:01 -0400 Subject: [PATCH 05/18] update, fix specs --- app/assets/stylesheets/pretty_file_input.scss | 5 ++--- spec/dummy/spec/features/users_spec.rb | 14 +++++++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index 6331a43..5517bac 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,13 +1,12 @@ .pfi_file_wrapper { - width: 100%; - max-width: 400px; + width: 400px; position: relative; display: inline-block; height: $inputHeight; // Position the items absolutely input, .input_group { - width: 100%; + width: 400px; position: absolute; top: 0; left: 0; diff --git a/spec/dummy/spec/features/users_spec.rb b/spec/dummy/spec/features/users_spec.rb index 81aa14d..5369920 100644 --- a/spec/dummy/spec/features/users_spec.rb +++ b/spec/dummy/spec/features/users_spec.rb @@ -7,10 +7,14 @@ let(:created_user) { User.last } + def file_input + find('input[type=file]', visible: false) + end + describe '#new + #create' do it 'functions properly' do visit new_user_path - attach_file 'user[avatar]', "#{Rails.root}/spec/fixtures/avatar2.jpg" + file_input.set "#{Rails.root}/spec/fixtures/avatar2.jpg" expect do click_button 'Submit' @@ -26,7 +30,7 @@ user.update(remove_avatar: true) expect(user.avatar).to be_blank visit edit_user_path(user) - find('input[type=file]').set "#{Rails.root}/spec/fixtures/avatar2.jpg" + file_input.set "#{Rails.root}/spec/fixtures/avatar2.jpg" sleep 1 expect(user.reload.avatar).to_not be_blank expect(user.avatar.file.filename).to eq 'avatar2.jpg' @@ -43,7 +47,7 @@ visit edit_user_path(user) find('a', text: 'Remove').click expect(user.reload.avatar).to be_blank - find('input[type=file]').set "#{Rails.root}/spec/fixtures/avatar2.jpg" + file_input.set "#{Rails.root}/spec/fixtures/avatar2.jpg" sleep 1 expect(user.reload.avatar).to_not be_blank expect(user.avatar.file.filename).to eq 'avatar2.jpg' @@ -57,7 +61,7 @@ it 'displays server-generated errors' do visit edit_user_path(user) - find('input[type=file]').set "#{Rails.root}/spec/fixtures/error.jpg" + file_input.set "#{Rails.root}/spec/fixtures/error.jpg" sleep 1 expect(page).to have_text 'server-generated error message' @@ -70,7 +74,7 @@ it 'falls back to a generic error' do visit edit_user_path(user) - find('input[type=file]').set "#{Rails.root}/spec/fixtures/unknownerror.jpg" + file_input.set "#{Rails.root}/spec/fixtures/unknownerror.jpg" sleep 1 expect(page).to have_text 'Whoops!' From 65efc52eab2aab7eed9c36b5abe5b51e55bd74f9 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 10:50:10 -0400 Subject: [PATCH 06/18] refactor, tests --- .../javascripts/pretty_file_input.coffee | 33 ++++++++++--------- lib/pretty_file_input/component.rb | 4 +-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/app/assets/javascripts/pretty_file_input.coffee b/app/assets/javascripts/pretty_file_input.coffee index 1f82c8e..f660c86 100644 --- a/app/assets/javascripts/pretty_file_input.coffee +++ b/app/assets/javascripts/pretty_file_input.coffee @@ -17,14 +17,18 @@ @$filename = @$el.find('.js_pfi_filename') @$status = @$el.find('.js_pfi_status') @$button = @$el.find('.js_pfi_browse') - @buttonText = @$button.text() @statusText = @$status.text() - # If we're not persisted, immediately add the correct input name - if !@options.persisted + if @options.persisted + @_calculateRemoveParams() + @_copyOptionsFromForm() + else @$input.attr('name', @options.name) + @_bindEvents() + + _calculateRemoveParams: -> removeKey = if @options.name.match(/\[/) i = @options.name.lastIndexOf('[') "#{@options.name.substring(0, i)}[remove_#{@options.name.substring(i + 1, @options.name.length)}" @@ -34,11 +38,10 @@ @removeParams = {} @removeParams[removeKey] = true + _copyOptionsFromForm: -> @options.action ||= @$form.attr('action') @options.method ||= @$form.find('[name=_method]').val() || @$form.attr('method') - @_bindEvents() - remove: -> @$status.text @statusText @@ -50,7 +53,7 @@ @_toggleState() _toggleState: -> - $('.js_pfi_present, .js_pfi_blank').toggle() + $('.js_pfi_toggle').toggle() _baseParams: -> $.extend { pretty_file_input: true }, @options.additionalParams @@ -76,44 +79,44 @@ "Uploading (#{percentComplete}%)" ) complete: => - @$input.show() $tmpForm.remove() success: $.proxy(@_uploadSuccess, @) error: $.proxy(@_uploadError, @) _createTemporaryForm: -> - form = $(""" + $form = $("""
""") $oldInput = @$input - @$input = $oldInput.clone().hide().val('').insertBefore($oldInput) + @$input = $oldInput.clone().val('').insertBefore($oldInput) @_bindInputChange() - $oldInput.appendTo(form) + $oldInput.appendTo($form) # We only add the name immediately before uploading because we # don't want to send the input value during submission of an # outer form. $oldInput.attr('name', @options.name) - form.insertBefore(@$input) + $form.insertBefore(@$input) - form + $form _uploadSuccess: (data) -> if data?.additionalParams? @options.additionalParams = data.additionalParams - @$button.removeClass('disabled') - @$button.text @buttonText + @_resetButton() @_toggleState() - _uploadError: (xhr) -> + _resetButton: -> @$button.removeClass('disabled') @$button.text @buttonText + _uploadError: (xhr) -> + @_resetButton() @_flashError( if (err = xhr.responseJSON?.error) "Error: #{err}" diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 4179dfb..7cf85ce 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -19,13 +19,13 @@ def content additionalParams: @additional_params }.to_json ) { - div.js_pfi_present.pfi_file_wrapper(style: @filename ? nil : 'display:none;') { + div.js_pfi_toggle.pfi_file_wrapper(style: @filename ? nil : 'display:none;') { div.input_group { span.js_pfi_filename @filename a.button.info.js_pfi_remove 'Remove' } } - label.js_pfi_blank.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { + label.js_pfi_toggle.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { input type: 'file' div.input_group { span.js_pfi_filename.js_pfi_status 'Choose a file...' From 71627c85d65aabd886bf6d165c69e198d40c2624 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 10:58:46 -0400 Subject: [PATCH 07/18] cross browsering.. --- app/assets/stylesheets/pretty_file_input.scss | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index 5517bac..6b3e277 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,15 +1,18 @@ .pfi_file_wrapper { - width: 400px; + width: 100%; + max-width: 400px; position: relative; display: inline-block; height: $inputHeight; // Position the items absolutely - input, .input_group { - width: 400px; + input { + width: 100%; position: absolute; top: 0; left: 0; + z-index: 2; + height: $inputHeight; } // Hide the input via opacity @@ -18,8 +21,8 @@ } .input_group { - // Necessary for ellipsis to work - table-layout: fixed; + width: 100%; + table-layout: fixed; // Necessary for ellipsis to work span { display: table-cell; From 37d0aba196f7a7e47c3f13f3e585ca2a167abcaf Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:01:23 -0400 Subject: [PATCH 08/18] more expectations --- spec/dummy/spec/features/users_spec.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/dummy/spec/features/users_spec.rb b/spec/dummy/spec/features/users_spec.rb index 5369920..ef5094d 100644 --- a/spec/dummy/spec/features/users_spec.rb +++ b/spec/dummy/spec/features/users_spec.rb @@ -30,6 +30,11 @@ def file_input user.update(remove_avatar: true) expect(user.avatar).to be_blank visit edit_user_path(user) + + # Initial visibility expectations + expect(page).to_not have_selector 'input[type=file]' + expect(page).to_not have_selector 'a', text: 'Remove' + file_input.set "#{Rails.root}/spec/fixtures/avatar2.jpg" sleep 1 expect(user.reload.avatar).to_not be_blank From 2e6e5fc4a9b670dc69d2a493b7e71d5fa385d9ff Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:20:14 -0400 Subject: [PATCH 09/18] take2 --- app/assets/stylesheets/pretty_file_input.scss | 24 +++++++++++-------- lib/pretty_file_input/component.rb | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index 6b3e277..2dc7b26 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,33 +1,34 @@ .pfi_file_wrapper { - width: 100%; + width: 400px; max-width: 400px; position: relative; display: inline-block; height: $inputHeight; // Position the items absolutely - input { + input, .pfi_input { width: 100%; position: absolute; top: 0; left: 0; - z-index: 2; - height: $inputHeight; } - // Hide the input via opacity input { opacity: 0; + z-index: 2; + height: $inputHeight; } - .input_group { - width: 100%; - table-layout: fixed; // Necessary for ellipsis to work + .pfi_input { + span, a { + display: inline-block; + vertical-align: top; + height: $inputHeight; + } span { - display: table-cell; width: 65%; - padding: 0 0.5rem; + padding: 0.4rem 0.5rem; border: 1px solid $lightGray; border-right: 0; color: $darkGray; @@ -42,6 +43,9 @@ a { width: 35%; + border-top-left-radius: 0; + border-bottom-left-radius: 0; + line-height: normal; } } } diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 7cf85ce..16976a1 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -20,14 +20,14 @@ def content }.to_json ) { div.js_pfi_toggle.pfi_file_wrapper(style: @filename ? nil : 'display:none;') { - div.input_group { + div.pfi_input { span.js_pfi_filename @filename a.button.info.js_pfi_remove 'Remove' } } label.js_pfi_toggle.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { input type: 'file' - div.input_group { + div.pfi_input { span.js_pfi_filename.js_pfi_status 'Choose a file...' a.button.info.js_pfi_browse 'Browse' } From 53b8de30b5c94aa7aff41b90d7e0ba9ed42e6467 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:22:00 -0400 Subject: [PATCH 10/18] tweak --- app/assets/stylesheets/pretty_file_input.scss | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index 2dc7b26..b51ed7d 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -1,5 +1,5 @@ .pfi_file_wrapper { - width: 400px; + width: 100%; max-width: 400px; position: relative; display: inline-block; @@ -27,8 +27,9 @@ } span { + font-size: 1rem; width: 65%; - padding: 0.4rem 0.5rem; + padding: 0.3rem 0.5rem; border: 1px solid $lightGray; border-right: 0; color: $darkGray; From 77f2d8df0dd2451327c93ccd369ea5210a0b3ceb Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:35:27 -0400 Subject: [PATCH 11/18] fix old browsers --- app/assets/stylesheets/pretty_file_input.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index b51ed7d..cb19c3b 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -15,11 +15,12 @@ // Hide the input via opacity input { opacity: 0; - z-index: 2; height: $inputHeight; } .pfi_input { + user-select: none; + span, a { display: inline-block; vertical-align: top; From 66a851df3354924d45c1647d33a51806f3fe2b32 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:40:08 -0400 Subject: [PATCH 12/18] can't pass clicks through `a` --- app/assets/stylesheets/pretty_file_input.scss | 4 ++-- lib/pretty_file_input/component.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index cb19c3b..f46158f 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -27,7 +27,7 @@ height: $inputHeight; } - span { + :first-child { font-size: 1rem; width: 65%; padding: 0.3rem 0.5rem; @@ -43,7 +43,7 @@ } } - a { + :last-child { width: 35%; border-top-left-radius: 0; border-bottom-left-radius: 0; diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 16976a1..1af746f 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -29,7 +29,7 @@ def content input type: 'file' div.pfi_input { span.js_pfi_filename.js_pfi_status 'Choose a file...' - a.button.info.js_pfi_browse 'Browse' + span.button.info.js_pfi_browse 'Browse' } } } From 64e1ef0cd242d4f85eed77175fe44a316d6053c2 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:52:08 -0400 Subject: [PATCH 13/18] always POSt, use _method --- app/assets/javascripts/pretty_file_input.coffee | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/pretty_file_input.coffee b/app/assets/javascripts/pretty_file_input.coffee index f660c86..9183e9d 100644 --- a/app/assets/javascripts/pretty_file_input.coffee +++ b/app/assets/javascripts/pretty_file_input.coffee @@ -56,12 +56,15 @@ $('.js_pfi_toggle').toggle() _baseParams: -> - $.extend { pretty_file_input: true }, @options.additionalParams + $.extend { + pretty_file_input: true + _method: @options.method + }, @options.additionalParams _ajaxRemove: -> $.ajax url: @options.action - type: @options.method + type: 'POST' dataType: 'json' data: $.extend @_baseParams(), @removeParams From 6e0892bb5836f43289f35ecae642bcd228b1182c Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:52:14 -0400 Subject: [PATCH 14/18] add autoprefixer --- pretty_file_input.gemspec | 1 + 1 file changed, 1 insertion(+) diff --git a/pretty_file_input.gemspec b/pretty_file_input.gemspec index 0643569..3333319 100644 --- a/pretty_file_input.gemspec +++ b/pretty_file_input.gemspec @@ -20,6 +20,7 @@ Gem::Specification.new do |s| s.add_dependency 'erector-rails4' s.add_dependency 'sass' + s.add_development_dependency 'autoprefixer-rails', '5.1.7.1' s.add_development_dependency 'capybara', '2.4.4' s.add_development_dependency 'carrierwave' s.add_development_dependency 'dvl-core' From 00a78afe47688865534869c7b15eee962bc0459b Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:52:32 -0400 Subject: [PATCH 15/18] hack request format with params[:pretty_file_input] --- spec/dummy/app/controllers/users_controller.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/dummy/app/controllers/users_controller.rb b/spec/dummy/app/controllers/users_controller.rb index 8962ed3..38e4b15 100644 --- a/spec/dummy/app/controllers/users_controller.rb +++ b/spec/dummy/app/controllers/users_controller.rb @@ -21,6 +21,10 @@ def update @user = User.find(params[:id]) @user.update(user_params) + if params[:pretty_file_input] + request.format = :json + end + respond_to do |format| format.json { render json: { ok: true } } format.html { redirect_to edit_user_path } From 2b2ac46fd9a452e57faf67156950f67cb8083bd0 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 11:52:46 -0400 Subject: [PATCH 16/18] fix spec --- spec/dummy/app/controllers/users_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/spec/dummy/app/controllers/users_controller.rb b/spec/dummy/app/controllers/users_controller.rb index 38e4b15..20ad1cf 100644 --- a/spec/dummy/app/controllers/users_controller.rb +++ b/spec/dummy/app/controllers/users_controller.rb @@ -34,7 +34,11 @@ def update private def user_params - params.require(:user).permit! + if params[:user] + params.require(:user).permit! + else + {} + end end def error_hack From 63b584e13acb2a908880341e0dbc7f3409b2c876 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 12:05:36 -0400 Subject: [PATCH 17/18] fix alignment --- app/assets/stylesheets/pretty_file_input.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index f46158f..71183df 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -45,6 +45,7 @@ :last-child { width: 35%; + border: 0; // Fix alignment border-top-left-radius: 0; border-bottom-left-radius: 0; line-height: normal; From 9cb20f936a380a7254fb644adcb989884541c362 Mon Sep 17 00:00:00 2001 From: ajb Date: Thu, 19 Mar 2015 12:06:05 -0400 Subject: [PATCH 18/18] div -> span --- app/assets/stylesheets/pretty_file_input.scss | 1 + lib/pretty_file_input/component.rb | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/stylesheets/pretty_file_input.scss b/app/assets/stylesheets/pretty_file_input.scss index 71183df..3c6541c 100644 --- a/app/assets/stylesheets/pretty_file_input.scss +++ b/app/assets/stylesheets/pretty_file_input.scss @@ -20,6 +20,7 @@ .pfi_input { user-select: none; + display: block; span, a { display: inline-block; diff --git a/lib/pretty_file_input/component.rb b/lib/pretty_file_input/component.rb index 1af746f..d4b59fe 100644 --- a/lib/pretty_file_input/component.rb +++ b/lib/pretty_file_input/component.rb @@ -20,14 +20,14 @@ def content }.to_json ) { div.js_pfi_toggle.pfi_file_wrapper(style: @filename ? nil : 'display:none;') { - div.pfi_input { + span.pfi_input { span.js_pfi_filename @filename a.button.info.js_pfi_remove 'Remove' } } label.js_pfi_toggle.pfi_file_wrapper(style: @filename ? 'display:none;' : nil) { input type: 'file' - div.pfi_input { + span.pfi_input { span.js_pfi_filename.js_pfi_status 'Choose a file...' span.button.info.js_pfi_browse 'Browse' }