From 62f61ac22bf495d745d261090ce4acabc305e403 Mon Sep 17 00:00:00 2001 From: Iceskysl Date: Sun, 8 Jul 2012 10:05:18 +0800 Subject: [PATCH] add photo upload and manager --- Gemfile | 7 + Gemfile.lock | 11 + README.md | 3 +- app/assets/images/sprites/icons.png | Bin 0 -> 557 bytes app/assets/images/sprites/icons/rss.png | Bin 0 -> 566 bytes app/assets/images/sprites/small.png | Bin 0 -> 3029 bytes app/assets/images/sprites/small/calenda.png | Bin 0 -> 3930 bytes app/assets/images/sprites/small/delete.png | Bin 0 -> 3884 bytes app/assets/images/sprites/small/edit.png | Bin 0 -> 3854 bytes app/assets/images/sprites/small/image.png | Bin 0 -> 3858 bytes app/assets/images/sprites/small/like.png | Bin 0 -> 3940 bytes app/assets/images/sprites/small/liked.png | Bin 0 -> 3749 bytes app/assets/images/sprites/small/lock.png | Bin 0 -> 3868 bytes app/assets/images/sprites/small/mail.png | Bin 0 -> 3843 bytes app/assets/images/sprites/small/mail_full.png | Bin 0 -> 3816 bytes app/assets/images/sprites/small/pin.png | Bin 0 -> 3886 bytes app/assets/images/sprites/small/reply.png | Bin 0 -> 3825 bytes app/assets/images/sprites/small/vote_down.png | Bin 0 -> 3803 bytes app/assets/images/sprites/small/vote_up.png | Bin 0 -> 3809 bytes app/assets/javascripts/app.coffee | 41 + .../javascripts/cpanel/photos.js.coffee | 3 + app/assets/javascripts/posts.js.coffee | 111 ++- app/assets/javascripts/will_paginate.js | 33 + app/assets/stylesheets/application.css | 1 + app/assets/stylesheets/cpanel.scss | 59 ++ app/assets/stylesheets/cpanel/photos.css.scss | 7 + app/assets/stylesheets/posts.css.scss | 254 +++++ app/assets/stylesheets/sprites/icons.scss | 16 + app/assets/stylesheets/sprites/small.scss | 40 + app/assets/stylesheets/window.scss | 8 + app/controllers/cpanel/home_controller.rb | 1 + app/controllers/cpanel/photos_controller.rb | 28 + app/controllers/cpanel/posts_controller.rb | 7 + app/helpers/cpanel/photos_helper.rb | 2 + app/helpers/cpanel/posts_helper.rb | 5 + app/models/photo.rb | 18 + app/uploaders/photo_uploader.rb | 51 + app/views/cpanel/categories/index.html.erb | 4 +- app/views/cpanel/pages/index.html.erb | 4 +- app/views/cpanel/photos/index.html.erb | 32 + .../cpanel/posts/_editor_toolbar.html.erb | 12 + app/views/cpanel/posts/_form.html.erb | 16 +- app/views/cpanel/posts/index.html.erb | 4 +- app/views/cpanel/posts/preview.json.erb | 1 + app/views/cpanel/site_configs/index.html.erb | 2 +- app/views/cpanel/sites/index.html.erb | 4 +- app/views/layouts/application.html.erb | 4 +- app/views/layouts/cpanel.html.erb | 5 + app/views/layouts/window.html.erb | 11 + config/environments/production.rb | 3 +- config/locales/carrierwave.zh-CN.yml | 9 + config/routes.rb | 16 +- test/fixtures/photos.yml | 11 + .../cpanel/photos_controller_test.rb | 7 + .../unit/helpers/cpanel/photos_helper_test.rb | 4 + test/unit/photo_test.rb | 7 + vendor/assets/images/jquery.chosen.png | Bin 0 -> 396 bytes vendor/assets/images/jquery.jdialog/close.gif | Bin 0 -> 199 bytes .../assets/images/jquery.jdialog/shadow.png | Bin 0 -> 217 bytes .../javascripts/gfdynamicfeedcontrol.js | 864 +++++++++++++++++ vendor/assets/javascripts/jquery-caret_pos.js | 70 ++ .../javascripts/jquery.autogrow-textarea.js | 46 + vendor/assets/javascripts/jquery.chosen.js | 898 ++++++++++++++++++ vendor/assets/javascripts/jquery.hotkeys.js | 99 ++ .../javascripts/jquery.html5-fileupload.js | 513 ++++++++++ vendor/assets/javascripts/jquery.jdialog.js | 188 ++++ vendor/assets/javascripts/jquery.timeago.js | 148 +++ .../jquery.timeago.settings.js.erb | 48 + .../stylesheets/gfdynamicfeedcontrol.scss | 191 ++++ .../assets/stylesheets/jquery.chosen.css.erb | 367 +++++++ vendor/assets/stylesheets/jquery.jdialog.scss | 20 + 71 files changed, 4296 insertions(+), 18 deletions(-) create mode 100644 app/assets/images/sprites/icons.png create mode 100644 app/assets/images/sprites/icons/rss.png create mode 100644 app/assets/images/sprites/small.png create mode 100644 app/assets/images/sprites/small/calenda.png create mode 100644 app/assets/images/sprites/small/delete.png create mode 100644 app/assets/images/sprites/small/edit.png create mode 100644 app/assets/images/sprites/small/image.png create mode 100644 app/assets/images/sprites/small/like.png create mode 100644 app/assets/images/sprites/small/liked.png create mode 100644 app/assets/images/sprites/small/lock.png create mode 100644 app/assets/images/sprites/small/mail.png create mode 100644 app/assets/images/sprites/small/mail_full.png create mode 100644 app/assets/images/sprites/small/pin.png create mode 100644 app/assets/images/sprites/small/reply.png create mode 100644 app/assets/images/sprites/small/vote_down.png create mode 100644 app/assets/images/sprites/small/vote_up.png create mode 100644 app/assets/javascripts/app.coffee create mode 100644 app/assets/javascripts/cpanel/photos.js.coffee create mode 100644 app/assets/javascripts/will_paginate.js create mode 100644 app/assets/stylesheets/cpanel/photos.css.scss create mode 100644 app/assets/stylesheets/sprites/icons.scss create mode 100644 app/assets/stylesheets/sprites/small.scss create mode 100644 app/assets/stylesheets/window.scss create mode 100644 app/controllers/cpanel/photos_controller.rb create mode 100644 app/helpers/cpanel/photos_helper.rb create mode 100644 app/models/photo.rb create mode 100644 app/uploaders/photo_uploader.rb create mode 100644 app/views/cpanel/photos/index.html.erb create mode 100644 app/views/cpanel/posts/_editor_toolbar.html.erb create mode 100644 app/views/cpanel/posts/preview.json.erb create mode 100644 app/views/layouts/window.html.erb create mode 100644 config/locales/carrierwave.zh-CN.yml create mode 100644 test/fixtures/photos.yml create mode 100644 test/functional/cpanel/photos_controller_test.rb create mode 100644 test/unit/helpers/cpanel/photos_helper_test.rb create mode 100644 test/unit/photo_test.rb create mode 100644 vendor/assets/images/jquery.chosen.png create mode 100644 vendor/assets/images/jquery.jdialog/close.gif create mode 100644 vendor/assets/images/jquery.jdialog/shadow.png create mode 100644 vendor/assets/javascripts/gfdynamicfeedcontrol.js create mode 100644 vendor/assets/javascripts/jquery-caret_pos.js create mode 100644 vendor/assets/javascripts/jquery.autogrow-textarea.js create mode 100644 vendor/assets/javascripts/jquery.chosen.js create mode 100644 vendor/assets/javascripts/jquery.hotkeys.js create mode 100644 vendor/assets/javascripts/jquery.html5-fileupload.js create mode 100644 vendor/assets/javascripts/jquery.jdialog.js create mode 100644 vendor/assets/javascripts/jquery.timeago.js create mode 100644 vendor/assets/javascripts/jquery.timeago.settings.js.erb create mode 100644 vendor/assets/stylesheets/gfdynamicfeedcontrol.scss create mode 100644 vendor/assets/stylesheets/jquery.chosen.css.erb create mode 100755 vendor/assets/stylesheets/jquery.jdialog.scss diff --git a/Gemfile b/Gemfile index e823256..0c18efa 100644 --- a/Gemfile +++ b/Gemfile @@ -28,6 +28,13 @@ gem "pygments.rb", '~> 0.2.4' # YAML 配置信息 gem "settingslogic", "~> 2.0.6" + +# 上传组件 +gem 'carrierwave', '0.5.7' +gem 'carrierwave-mongoid', '0.1.2', :require => 'carrierwave/mongoid' +gem 'mini_magick','3.3' +#gem 'carrierwave-upyun', '0.1.3' + # 禁用 assets 日志 gem 'quiet_assets', :git => 'git://github.com/AgilionApps/quiet_assets.git' diff --git a/Gemfile.lock b/Gemfile.lock index c8252c4..57fe384 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -56,6 +56,11 @@ GEM bson_ext (1.5.2) bson (= 1.5.2) builder (3.0.0) + carrierwave (0.5.7) + activesupport (~> 3.0) + carrierwave-mongoid (0.1.2) + carrierwave (>= 0.5.6) + mongoid (~> 2.1) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -82,6 +87,8 @@ GEM mime-types (~> 1.16) treetop (~> 1.4.8) mime-types (1.19) + mini_magick (3.3) + subexec (~> 0.1.0) mongo (1.5.2) bson (= 1.5.2) mongo-rails-instrumentation (0.2.4) @@ -142,6 +149,7 @@ GEM hike (~> 1.2) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + subexec (0.1.0) therubyracer (0.9.9) libv8 (~> 3.3.10) thor (0.14.6) @@ -169,10 +177,13 @@ PLATFORMS DEPENDENCIES bootstrap-rails! bson_ext (= 1.5.2) + carrierwave (= 0.5.7) + carrierwave-mongoid (= 0.1.2) coffee-rails (~> 3.2.1) execjs hpricot (~> 0.8.5) jquery-rails + mini_magick (= 3.3) mongo-rails-instrumentation (= 0.2.4) mongoid (= 2.4.3) mongoid_auto_increment_id (= 0.4.0) diff --git a/README.md b/README.md index ee6e04a..71c4995 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Iceylog is a semantic personal publishing platform with a focus on aesthetics, w - +###Mac OS X +brew install ImageMagick diff --git a/app/assets/images/sprites/icons.png b/app/assets/images/sprites/icons.png new file mode 100644 index 0000000000000000000000000000000000000000..ab05933314c25b1c31aa796a4c18163eb430392c GIT binary patch literal 557 zcmV+|0@D47P)@o+9#`CG?po^rbxYqC5G{ zEBWlZ`p+)>oFDw)zW-zb|G^ah!AbwaMgPSF|HUHz#|{6-9{a z;MS@CdFbrsB(^1`rA5JNhPMSt-ye5LJo)tnU; zg;HJ^CDWl%ErG(A)!X*R8)u$z1R}GL`>JaCMUR;gh1QFC9@c9aOh{{YVJ-BAv+VEX zG)Sy<7tG7&BgDC`AQ9}I66wR{9nu?FU&V9|*+cPpfP1PTx`fzI=>sDE2LBRv@I}9X vsNlK{%vJfyRF;a$CvIoC!_E4p=`j93ph$@$eX-sq00000NkvXXu0mjfC-y!K literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/icons/rss.png b/app/assets/images/sprites/icons/rss.png new file mode 100644 index 0000000000000000000000000000000000000000..3048c01f4ec3887393e1206daa8b19428ede62fd GIT binary patch literal 566 zcmV-60?GY}P)W{NR-t>Vh!g}xsGF+QQUuW!gwjAv znsjW^l*xp=(Rnjd6*uv67w6q~KF+&OxYd{S<*TjQ0-Y+J8nO=D6Qx(Z>0KEk9`6XW zT<3?qu6u6Pa4WcQbe-lm+*RypHfE6Ze-prSg)Te|>8U|1MPf*G`V6v0;SQzyc+TI9 zZx*FzX0}I0gKi%fWcPV?o>Irnc|M<`Rr(E-H)5jvG?_`YgM=iq5#3nFIQS4VN3+1f zC~h$vuhn!-$QW%+^+<&iWd^1&4`a_WH;g??*Iou6<0V3mZ`L%=2ZHuXx9AH9qCaC3XpmPI5ob{@@||@ z*OaOMGO1xIA1KbCC)hI{4Xz4#Ye3?`iOOKRZTMRzB3nR-`Rp~@uxPz!q_IJm&_`lke z30*U@(kb{U9o-UT7VVYS?wjjB9lIkS%=C_t+rI=D0OP5-9dGXlJpcdz07*qoM6N<$ Ef)P;sSO5S3 literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small.png b/app/assets/images/sprites/small.png new file mode 100644 index 0000000000000000000000000000000000000000..8e81741034b93fd2fe41e318cbb1c055daa89ea4 GIT binary patch literal 3029 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/delete.png b/app/assets/images/sprites/small/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..76800eb5c166e7ab83cf7682d941eed2672d88b2 GIT binary patch literal 3884 zcmeHKeQXnD7(a*zRwu(~zzOC!VoX2{nM4-DqMO8z4H1nK<1+b!Ecg)vMk#-QlQ;|}gE@mlqrP|jSQj^wCGcOH zwAc5Z=l6S__xC*Sle-sdYbtXzc^ZNsavW857rx%3d{^Cxe;dNhQ~2^ADsMt=sSQO~ z2nZW5c>(DNvOeGfEZ^BN0W26C6Fg0*$@wJ1NkJW}_~@d+5JnS(WotCVa_s<-Uf>f% zD>Z#`j3NczN;MWZ_0CWk@C#L45V*T)JX}{hSIkpeOEi`!g9(BFv1BwD5M?H6rBq%9 z|5t9)6sfwPb}N-gs>xYPmPrthW}Q)I)N=Yl6Io!=nF@@BMsq%C)a#3A{TAA!*BXi# zeF0-OkjW2Kq9HAiZ)05ciexyvvQmD8LJUnuA`xB0q?4eJHWU{Z(|RLqG-|PjR_+uL z8`X;PBML==!wzH)3Lzv&BB^k)UMY;M6ou_%lAPz#+@UZGsLVV^g8&Eu5y`YcXP`6v zu@Wx9=SOlHCdx^bvEFo)4Pl6$hN{mzWXLZeN%l*jg^_8qiq8z`2qDgl<0^utv3OUU znyid?I@3dit9435PbbVcS=bJ6tvxUdRQ@?rBk;Nri_|?Q^-1T$*uuy!LAh3v1w~10 zR|F<4JjW!qsV)R7FsD}KuE?^SE-;DdVWeuhMW>ff*C2gLC5?Q z=}fMaRprVAD`ZGO0gyqJ3Y=`WMRq%nKLt_w=lCphwWyczf%X6xly6m}MY%1Rjl-x# zkzkpG4-$tQVwkRu>*UY8NfSUdu^5?(@V6Sb!YC z#mGG%&?rGXgcih>2U+3&?Da5ZRSTAAw2TRYtC6^eClelubb2Z#%9Na6x9y^;b=%mJ z#MvNAQaCGDR<0!}uq5YfcV*>Tk^)O|&UV)=lS?!AUIj$_fE~eaO?4O1hXk?A=CIp5 z(fGkvs<)qNy?^iF%ANP!eg4^V1L9yw-uig#sA>H43HM57P5%R%(X#I*mmgm-&cM~N z!r)g=JhSEU+BF;26;1R^_k2Biz+YZ>?(g3Y&CFOv`i6cPW!Ig2s&B&z+qJ%_PUn~T zXLiRw?ymgo&^J?S2g&_EnJ(Uta;yG0_~^vFubr)U^V?E$^ZO0ML&6s?RmX;}wm3XH z9-922qn|r#UcIlyvAtmC&%teR(lGFA*QWT9xas=qa9p2r>exv2v1Z-dCq6iRy`}$- z(gt6yy$^n|PV_t@-y_hse%)lpt!A1-a}{TG{XbnO5D literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/edit.png b/app/assets/images/sprites/small/edit.png new file mode 100644 index 0000000000000000000000000000000000000000..cf0399064299d03ae191a0ada8bd137c204fcde3 GIT binary patch literal 3854 zcmeHKZ%i9y7%$tLTZPQv5*7F1yk%L4v{%ZX!KE$M7DtWkpp;QIojdMc+6#C0cJIBV z2g8}62%E|>6|$IU=7(t(g)CxFMs$&p=;Hja#6;x_7^j$QX4{92eK5xN?%Gl!n2>DW z+N8a{_dLJf^Sr<3d7s=JYYgo!vX)pa7E4i}!5=2qLjAjGBl+E%d|`oH9>?`j+zdN# zibKHS6<|A{0x}l^VZaI9hb{pZ0Us43Q5+3E&+<^VbGnaRlM@7OvAF8A1jly*OtpiU zsJQ7HQx|AT6x?)cRnQSk_&{82=s}>lCluj(I{8|GuJc%38cPUdfH_K&B}HX5H*N5; z9eokHiEPp+f1LTsur+H%${el_nSXEO#P_B!gMt86W`}C|G66?d43a zKT#qq#^PAb!W1>FGSQpSxCDVX7-aY?Lnh)7Lp2T)DSC6sq-V(Mks!)Ru^Aj%o+6XW zm9ZLJxnP|Pi&z3VRGGl(c3Wk)%lI=8gMW$7wN#51l^o~@K(czTBCX2p%55ChC<;VA zNDdN@14;)p&dG8g(JP>O4RZp@oTLBReIo8&-5MsN$LOL}*c*8$kUlq0zzXCTtwtUJ zQY%Dc2(5^%mpSqO>@6r`H40`nTFwL^)iCdo$wY=ClbwoYnbPy?zFiEp?i+iWI3Hw9 z3g_j@%e5v2*5sV;uDo1pQeaKa`R=-Ba#@$&tAIituv6r%sc8<6TPy|J1AcEro5d%; zdT!?Ft^GSMU2T1%pBjAY{e7Fi?u%aU8~*Zi*{6dH$H`BPoK20E^*(g0|J-O-Tm2{R z?!P(*r^hw~?Y);T|1h~TR&3j}?#kYlmd$gEUld+EbyjWK`fAP4OSkQ}O3sM0FSd<5 zVZF2X`2-mFIkhcz{M?>v4|wK(ocQbGSJr>9aJ%gL_a6T6f>e5I$Mxx>5<4|EHFURN z!F%zy4P6IMMAgaSN50t=RA&164={)QT;5BbNQ HIoS6vuRCJg literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/image.png b/app/assets/images/sprites/small/image.png new file mode 100644 index 0000000000000000000000000000000000000000..89d7c524d66467243bd63aa789ded7f47fa4b893 GIT binary patch literal 3858 zcmeHKZ)_7~81G~wO9Qy*76tuqIf#pi?cKU|>u&8vX~(G2W`DZ>7`@%SZO>irE$_Xh z-5juyh|CWf794)y0}1~5puR4h)=CX=f%73YNkfT?~E zkrX%m`{^%eN)p|4mm|Oi;$9Gyb_^lVJ`@ZILjyvcNH;c^T`7(b!~o{0R7_S>F6E|m zUXJ|NZZkBcyWjygZ6wtlXra6i0m^Q*S#1`9t*NFQ)z)f_ z!F-hYT{x}xwB(5fC4oh|= z=*g;BWb!?9xLzkCdM;ruz@q^`Y8^repz|-9x3_sG~-8B1BxWaeaEiMZ*MMFe3!A!EA1ivW+MJ%BVxECv;o@?eal z{)AqsAXF^ceSidsm#HA6d;m#%bb#t&v_i^KCZ@j126Zt@Q_?aNv`7%;rPvO3FHMoj z=gL}ju6(dYh9xY6JgRKqOuMbH+a>&2h|a&r=US{qhe{4~2%wmHzap*3?aFT)PA>{X zUPum-fc;7s>gQyskK_?iQwsAU%ATYD+PxAUT-n-2MvvY_E3mf+P$YeBoPcG>F)icD@Q8fD7NuLpL~)p}s;8R9~a zRViGMt032^6j+sWp}PultxADaITyO?zR6`?e6IoudB9GRx2D!K{@7$Hs`UFjq12Tl zho_&N+gf(8_Hy9$xnt9vH*dal#x*iobN$R^>BgGU-n&oLTuHU#+kQ zZg-ZSb(S93{K$Mq$KJ`0UOD#eFR!L&CLdCT3tRl-^`AbxueIEKse%PXGjG|~*5hw% zr<&oHB~RR~{9&Q&+`_4ExnlF!xocB>hbm5vZYf#wccf?H==cY>dYfAD$c5%Z>7DK$ zpJ$Y9wKJZB(I;CU-+IK6E_?1o;QGdUhvP5%9Vb4VWrxqEz0Mo^zP9+L-k9sF^ly+K z+m(Q)k6(TIuh};(f$t;7`-Y3}OpMPu1`@YwdM3WQ*!WxXNRjEicRq0*{k42bdrS2< L1$`&Cy?EeXhn8X5 literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/like.png b/app/assets/images/sprites/small/like.png new file mode 100644 index 0000000000000000000000000000000000000000..08ac4855a64064e29c3ba513178bbb0d1f5562a6 GIT binary patch literal 3940 zcmeHKeMlQ;7*Ab4GO4XA!qzd_?c4{nOD-Sk^hlJ{j~d&E#%NT;dAWO&+`QbKcW+D- z*Et!kZggwG3iAVDZVWam?K;=mm94dOGWJnAOIORpN;e$Rt)0TH1!8cS|ir050!F%R&u zycNIs)i*fCGFIH3;V?MFJm6=GS|m{3QsSap8t7~W&&^4+gh@mY0Fc7M0gji+uoYK% zN%UX2P2ia70voJ&B&jM#DV8Tl087`K^d=o`$TVXaX1zJXlxa$T88aCSS%l#g!fenP zvq(b*nQp|QA3P@!vq+4WbmkXE!=aTG_d_U>1Q7~_^dYlekbHzOJ3E^&mzOkZFk(AuI5h!by3AAhhB*vSU$lhK_NIL5WkD8JYkb2ml_+gi&uK z;{A~lPS)p#aty}HQI(P2M3@p0#6U=@&l05Q7oZ^f1#x*~%&g+$L)t}1r=z%vpfN1k z6|E*KLxza=P~mEwBGF?BlMYI10I1e3DF{^lMUxwN${_{SJxBG4^i`s7V3=ftN8G zgc9oss+B4cc%5<|NHj}vSc!n;1Bq=?0kVZq3dyn2nCfaFsD)UXl9C~g6%SU(APYGVN3{?*+HNcCb_xFiMCD)Pvn#{Y$`^|6rEp>?4qjm z$k?OAYe80}@S0p}a;-{%RXMM9*P2|bQeaiiYu)wG; zd&g@x5)JQN|8r1lwTeK-$~bTz&Jz&X*3>^p9C@9jfm?^7*G#cU?V>0kZ7! z*;7g9szxjR30-^9*f-j`d&`ZBeYZoE&pF>Xubn>=Y9!{qPP+F;oA*#Fkvyi|R@_y0 zG@*CiSa)sT;m2-Yyr5w_ESdf0^aJ6x2MK)F`t6y0uaA}QJDd8^4?TIUyGB}jwZ4=6 uQ~O`5+mE+Df6jer)BU%0bkFQ*Tc;Vh_xl&-4MeB%-fJ%?$sgKP-~KN!ACIvB literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/liked.png b/app/assets/images/sprites/small/liked.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd2df2c44555d304b54af20f15b53312311a5ad GIT binary patch literal 3749 zcmeHKU5Fc16b>#dl6HNP`t#y+iddE=cQV=CHsfU1nCx}~P1t7B-LzD6GIKW>cV_PF zotw>Ud|I^+6{P5j6rrF9wy;o2EB>?(eX7z`p@kx}V68~qf?^e=FA93+PLfSM?i~m|84Lsh1L?_Bjy|_~e-HQ5@0rTsb^3UMj2Fl>nj=*O z!$3kqMaZR1r37`Iitghb(7)36-Ljq{9GqW^oZ z0nafPG9TytqzaiSE{QPYhQeZ445`9MlpBtQqr>8eIJAos1z`^mc7v!8itLeuVQDDB z)j#}bkdv`CC*@KT^>B0*=gWlH5&+d|HC&B`5iWs9EEWTT2t+YNJwncsMHDw=IXgTG zpCbhw73((9k;QqON)c5^oad>XtCMSLliRLfgE4C=fCe<7MH~2qO(6on%%=@$mk~iu8QGg7n`VY@4VkuyIz;1of;O>qS1L=^AsT4)U~pC^ zKYBA^DWl+dNNb(P70CEEOtY{!O%%fRT-T?WkCdp8GQ!Rja&%8gYWD=@WKEU)ZL+1W zc)}q5%3m6~C$nTIRw>TAAq~zc6@&1jNemUDFGAWRrim#3M9%5Bj z3@(ef6vX->12{793Tf!|m~7PuDuecvybM(@62dJhPQ!)v6hSLj!^*f?!5$gWi2+-v z8iDKW)?v48{0#`>-{6xsYH`4!2RaY2>D;eK9l7P!#*tW25Kba`kW`Yk<`6q4?LK-! z!{aVdG~75x|FtJ|veem{qoap)Q3v)Z6=}53{S&YWIl-OC^U#<@m=2*$vE!zq|DXK; zZdh5t{6=e;Aha6(J35)@Pz24X=$ENJzaH3wsrA6v>%_evT`Am?t0z}i3UuY%>#m+$ zT`AC&bFaJZn_R(-dlj_k59}(vHSPbNoTE3c^XXI~@7{Rl%Ec|q`yc({_n*J{=)QGwC)c;GPt2Tn zmw)=tTk5gF#pB#-&-9lkmhj{J>CtrYjc0SUZOOjf2k#t$E3e->asJDdnIC?9Wi4{{ z%)*@)wGZx|5mt^we%iiP`WSA1Zs6qD?Z*Z`d+)BU%UhiJ$h4$X^-dkGG z>0}>?m`u0$$0BA<5}hO2n9~>*j6en&qh^0N$=nw)nPG8eeoW1D#`)g$gA&1nWc#m8 z+UtAI^ZPx|`+J`E$=%CMz9$Ow>-0LEuE5*iX(88q^}A{%`F$$7eU4n#;<|R+3OjI& zM?mKiVE|CxFy9GU05A4-e-1bTeo6AT!x4hk>A0GBgcrI1rUIZ- zlAZKVW8*X>iB7uB(P(arxIs{A=tH2j&*vBVx`Zl`uBp~@ah4E-0p_WAI3z1<+(~P^ zEcvhAW@t)t!Cg)|kyLwQ6Xk{oPsvYO46jCnI-GaD_H ztl7cZEmZPDSL-Pbi5+Zy55OpP(loJCNpew0b4Q{mq%n&E141ASWUMe2lZDCj zCrY$Pok6UmVX~4`ndr^L`3QlS8Kn6vKt_TPLnR0!izCx!4WAj(8^MB|#8m}NW67=r zEm;MNOs0nh*Xopro=%u;&~Z6MH!d93X@sZTl|))mD;h?FL%NUD;= zt_nCEPPW?;yIsJaf@u8neB693wkhO5`vD3ocPrA8++1ekuv$?d zazk>E1niYNpmt6c`baJj)x|L{qSQJ1uiY)--leTAWb|lVv;=#T07cU0i4(90IYvv7 z`$4D;A~J*)#ny#+>HqB8P|B(mEYWBg6NFSFagR(UG8CEgR7{j9Ilu1NMN{jZu_uYM zL6)U(R<5jE%Ti!j&e`tD%C#&7mgSu7uDd3ee*V1*$m9V#M&6p5XYmI*U5>@;arxsH zUOzbgmGQe-gtPH+uU`K{vWU4?l? zLxWR)k3qco$8RrBoE)>=yxsAbC;v?C#nJVLX5KhuD61%+?&f~q`QrYodB%G1UAMJR%Ve*;R*jo8Y^m3_Z_&dXBs|`0nYE;o*_%e--?&Wh!2LI_JWve$;;MRox?ZUSKQEUTR)DvHxiPs*5?3 z%*x}!hbsaj+rNZwPTzTyduUh9nVL)IM|V3OzWRP-);+i5hFpIoZ|i|CX3x(~u9(Tq a*9|=QXT#2u%?9;-)m!KDoOt}%{(k{B>Sd+? literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/mail.png b/app/assets/images/sprites/small/mail.png new file mode 100644 index 0000000000000000000000000000000000000000..de012734ab4b38614950259dda660713d7d9c853 GIT binary patch literal 3843 zcmeHKYitx%6y7G-VlAdpOejCfWO!JNyEEP0K6cz~yL1=2eXO0q!B>wQu?4#S*nlyob zyUFhCopZkLoco<~PiFRYgtx9JUQ=wd*;a&_1D)hrVt$twlHX?%J8qFnIS%&VF4&Kg zJOVbq2>SpPQur9?1iUyj_&x9v@XJ!92luqMaRO8vyy@dG6pf&5HgAKW@xlPWR3C^* zs*j#I^#x5yqL1#bZfD!ICJ>jJhY{!+4o8IH0l_2E4fVxdgChhAz&vFrvZ`~2kG6O@ z^54A8(3ItZ2YhrYsh;)@stF=MxgAc2(=Mq9E$ z4ZEtZGbvIW0iX*=(y#H{(3>2VZovCtEF}eOk ziB2gN$9fi~>S>jU-i*O(1i~`N@|lO!;t)eU4z-1mS+j-D4H?p~;3jcRL9%u&?_MFxyn-Awt;5bBj2h=4~Nn$qz zro5uSrM77;Q;Pd#oLZ%pvSiB4$-El#(S}_F{d_{kbbS*7JeGC=(j=Kv-F468DxQ0<0xEgHPLj8#r?21>He12!P{1ECetv80 zRQQ|5(%^}|Mt|D)d*!D1`9B`Q=VlL{?>P4*JUH@EeQor! zw#yHAjDqMP@K|ZdWYLT_MI934Lb_D@W+C1(R0ZYp;_&`y7l!CpYw# z&3rZV{@|aNDXnPBR2h2s&B3#Ue;+=5r}g;P`q=*Mdsl6`^x%$5zidqwZfrT;GX34! xB)jt18#jy=_Sc!~wPlaiKL2Cyjn+K{wj=J7M&rrX51Fr}p3_?%_DDCE1@CrqA1)zgu_H@5c+{ztBe;=^Y~@Xo3`F z47r$!(hwwbat01VS)D%l84Oc!NlT59v4KY=1?9Z5q z-+3+afVq=68}HZTO@2tyF^2D|}5@f{6<&Y(Bg88{jU9RUHK@0jR&Pz?G6|1rte zDTVx?{NcMjAdJ-sX*lt4IUHR@_$(oLNfe94qPH0IBAgNZU0q$GFCYd20`(BgX@kg? zV3>y-3YQ}RO$BRtq9Fq~oN^i!NQCF99hAvcrOKTzV4X3miU@U>g9b50zt=C;`cox_ zwM>?nRhVIxRi=82mYk;$pNN^yCS*Q~2r{!MzcsRIX878W$vja)G_E6P6-#%euw+f5 zinSgL&g$ewuO=)F$aoUcTBmRUGX4$IC`^wKnXo;V^{M6~#R?>gusMWG%~6ut9f3hu zRU~(tZ0RZ<(}}xsm%8T2Ea|e5iSU-7!U?&c6TUl+p-i+XNSh>=Lxu@rgkUXQV3is~ zhTy!1SkYu13?h(#Ses%1Gb}oV)U|RvSQ%F> z*dZet(P0f$C2+ajw%P3_{tATgZ}5dTYH{482Ra3D&b(2Pw&f1jHjc!Kf^ZzsgQSq8 zF@e}Q+3cgmRNQM3S;due^j~{iBh%Ykhw12HU9=7Rkb+d&=k5vEf}G&($Wu@sMVJnu zEwQ~hS^Gcxaa^&og1L=WGeKxI+;?;`(V-|-r=nY?^8C7K52n^lV=oiegX~D*x?FX+ zcBH_Loa^0Hmup7~?8v#^T{lcF&&It98uSNtk=~jfTP7dU8`nR{L@Z@}mtI?6?`gWv z{`v1~D_=(6KJfYa^L@gd{ios5o5EiE<>R?*0XCcAi@$;MLvfUH4r2)V}`x7nd);#i=hXhHSf~bx+gb40re^TNl6&4Oic3 z{C!X9qtTi!m@922VbM8vRKB4)8Z|q;g;3@9lBhRj1f8qV*#?>dlRMU@Rpu6E> z_t5#%&1rLvzjv-By0&ZfeB<5ao&fPQFJD9le I(9_TT3sdq!#sB~S literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/pin.png b/app/assets/images/sprites/small/pin.png new file mode 100644 index 0000000000000000000000000000000000000000..fd78a3fe5e3d8ca09b5dc198df5370241bfeaf93 GIT binary patch literal 3886 zcmeHKZ%i9y81LrhpIRm&ncHO9aV%j$+AA&0^=ui1cCJVpXv^pfCSLE}wkOxS^4?oo z(8Y}fY zwAc5Z=l6S__xC*Sle?E%Jx>&AcW5;lO_A%M!;7yv<$Lel`1eq}a{*trBWD2lq!3Cl z5NPb26a<7T%7lRzFkEl<*T9Ow$9R7L1>7w(D@6^A;$uigV;HT`SobGm4BG_|5d>jg zw2?PIJ5LfkXCpi6+(vh-2}JmVeGvHiJbt#Xi?wj%{(7x7Nn?U2Kn#(L3ZhIWZKTRe zDQ)MX>nNd?@kM3V#oQEM<6OnTP1*G$xz4dy!2UQ=x~VKN%`QO3t8vr%8O zk2coPwKYWML)L2vE9647*Kr^d4zFxv1fdvBQHeytkT4r07^Z4077JxGQ6`ffd+6m} z5iv=gd{m4#a2h=%ql)Vq$`HlS{zpqG>65z zV%212#8LSkDqO8oI(jZ)+ReZ&fNSlCaiH=qn>s+yhZv;pIipW5AKD&A5edqzlFTbg zV!I+RVdYply-jtQR@^S2^eVj+ctvJfV8pPEOzJrhV&VcK>zg285Z?oElSHGEC=+&s zARmmYmGVfUUbzn-%QFJukq8HXe2)r{t&~zofzQNLSJ|LeYGq1FhO81vf_W+WK=;ZN zseG=iRprVDD`bdA0?4Dv2F|qG8oOP=pM|LW%Y4@5TC~gfK>GoV%C{@hn%vg>#-Y`s zNU%x52Z=>4F(j$yWTg*p=b$r*7!GF7(SPktJnCKB>cyi+?V>f;!&mYMVpnG@1=fE{ENp zywcJ(?nyP2E)Gwe$(0-F+Jy7q$HtOLm8jH=LQ-dW@Vs zJNU8tt&vOL2%(|bQOm&NiKonN-|_M5bcOEAr{{jZd4dU4ginPIwO{TYU7)(l9&rtA z+v?CBD0MDPT)+D3k@L+boh>JK*gCiDB0eem>P?OI4PErig-^xV-!_d>H|DA*M;A^9 zch7uO92i?Fs@i;Oc;x89^VXTk>W5P=(j|XP?s@sqV0o(Ym-{VOf7sUGosW*U5!2_! zQ@g$guk1XH-R#AGjSZh#(z&O>yrZY`*3P@iHm4r?aY}b%e&|E^dF%AyffPIY4ljOp z?eNk_`IC$9U5+35LU(k}?3AsafB)MLo^37~4Q?NNp>NAi#TQ$yTPsdn==`(nZ>s#Y oYo6!cy{Gr*4ON$H|7_H09vocq4OC9NuDrpzoF2zS<1_vL0?0>ctN;K2 literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/reply.png b/app/assets/images/sprites/small/reply.png new file mode 100644 index 0000000000000000000000000000000000000000..227b569c0c700e831d75ffc04e373ebe035c9d41 GIT binary patch literal 3825 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 BJ(~ak literal 0 HcmV?d00001 diff --git a/app/assets/images/sprites/small/vote_up.png b/app/assets/images/sprites/small/vote_up.png new file mode 100644 index 0000000000000000000000000000000000000000..7a2041ac9902c443a1731b4bbf1886e89908b989 GIT binary patch literal 3809 zcmeHKUuauZ7{9f%?Yh;9IIson?e)P;o7^N#XL7k|8=KArnh?`$O<@ji?mbN|x%ZyC zb5EMI3TtZ>1!0pS4w+DV@DCGT#25dt!dj$I_98gk%T^EuKIp?llvV4w=O$@_tx(wB zav?c6_xpao?>oQmJBOUN6Y&>2+Pm8shUti&j3mi;*#5M&knhulGk3_)g-6qP98Te) zga8v(Up&#nc{P>B>DZVcL)|UeKJJok5;VhzLnTv^^8m9MkX4Nk z_uDsDIaXCd+{8f46EjCZPCYq`!1!!DCC}#Npu!Cewu>c!5a<9)Y)RJ)ODKgn$}5oH z_G_MFsSD1BI47xeEWwUI1X#b@=k~c|&+&eCpx@m;;5+W~_pv^YC%}82=leY_Z$R)2 z2!1bHez?JQRz%8_kc^xtha-O@s{zQqS zn$2OW3Nx&-%0zFzB$))_;Su$zLz+2=p_PN??#QZ{;%h@jO)UFKTwBm8maIyq$y!+9 zYdt8O*2#%pO<0IYC=W=jQ>Xwa|Bh(_WX7?C>6**>RPzzS1)PJ(NNW5!(zi2BQ;Z?m5M{d zWxoeVRwa#%LpB1CI!ytV$lHa~)N)KZs{|GK`jqSpWjhi?H7SmRbM-0mwOkb|<*EhS zWLU)-sG+I^F1OnrtF7a&Kq&tXpSV+tQx@6KDS&kAenr}oTdZvyfffa#5lA+YjHAXB zr2C}aM-3}zw1g!ERrb+;?IS9l+1r{VM-T0yJ=ha6R7jsYJ75=bjP@c=0c`>zatQ5; z9n~fE|Lmtw#Yzk2G+NCGLaO1sBPSC%6#43@=#;5^em$^(s`bFw%fyW!`%<_eS3|CS zDX=f+Mt3#j+Lr?Ra&C0jeUqzw=UxR2@&~&}ZcQ)U!e5db*B{YHI90lt+1lP7x_0xc zeAn6UX4h6WHa6xCFD@>o(&@Bue(O)~=JywR4t0^|(i0|gF+BYFBOlG*?iss$@cqp4 zx;QLs-@1DK=r5Pdqf@sxH$P+0%iI6_edw`!2bQwo8!M};t1D}3?=>l>7sgt@zSozy zHvQ=jZ1?i74?oxPfzhGdXpX)4)AgpuFDSD7YNyiEoM+IPKp^nW*AypL}RN zsW1259lm~GVW}^X#mtfJ*R{Xy-sx<9YPs`A#{ce0 zZf?>4?R-!TJ$j{S;H?Gm;Oc7u?)PVh=bD&fA5K5B?CLmSUpk|s@yHi1yt42wxFJ0H literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/app.coffee b/app/assets/javascripts/app.coffee new file mode 100644 index 0000000..388f346 --- /dev/null +++ b/app/assets/javascripts/app.coffee @@ -0,0 +1,41 @@ +#= require jquery +#= require jquery_ujs +#= require bootstrap +#= require will_paginate +#= require jquery.timeago +#= require jquery.timeago.settings +#= require jquery.hotkeys +#= require jquery.chosen +#= require jquery.autogrow-textarea +#= require jquery.html5-fileupload +#= require jquery-caret_pos +#= require_self + +window.App = + loading : () -> + console.log "loading..." + + # 警告信息显示, to 显示在那个dom前(可以用 css selector) + alert : (msg,to) -> + $(to).before("
X#{msg}
") + + # 成功信息显示, to 显示在那个dom前(可以用 css selector) + notice : (msg,to) -> + $(to).before("
X#{msg}
") + + openUrl : (url) -> + window.open(url) + + + + + + +$(document).ready -> + $("abbr.timeago").timeago() + $(".alert").alert() + $('.dropdown-toggle').dropdown() + + + + diff --git a/app/assets/javascripts/cpanel/photos.js.coffee b/app/assets/javascripts/cpanel/photos.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/cpanel/photos.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/javascripts/posts.js.coffee b/app/assets/javascripts/posts.js.coffee index 7615679..76ebda4 100644 --- a/app/assets/javascripts/posts.js.coffee +++ b/app/assets/javascripts/posts.js.coffee @@ -1,3 +1,108 @@ -# Place all the behaviors and hooks related to the matching controller here. -# All this logic will automatically be available in application.js. -# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ + +# PostsController 下所有页面的 JS 功能 +window.Posts = + # 往话题编辑器里面插入图片代码 + appendImageFromUpload : (srcs) -> + txtBox = $(".post_editor") + caret_pos = txtBox.caretPos(); + src_merged = "" + for src in srcs + src_merged = "![](#{src})\n" + source = txtBox.val() + before_text = source.slice(0, caret_pos) + txtBox.val(before_text + src_merged + source.slice(caret_pos+1, source.count)) + txtBox.caretPos(caret_pos+src_merged.length) + txtBox.focus() + + # 上传图片 + initUploader : () -> + $("#post_add_image").bind "click", () -> + $("#post_upload_images").click() + return false + + opts = + url : "/cpanel/photos" + type : "POST" + beforeSend : () -> + $("#post_add_image").hide() + $("#post_add_image").before("上传中...") + success : (result, status, xhr) -> + $("#post_add_image").parent().find("span").remove() + $("#post_add_image").show() + + Posts.appendImageFromUpload([result]) + + $("#post_upload_images").fileUpload opts + return false + + + + preview: (body) -> + $("#preview").text "Loading..." + $.post "/cpanel/posts/preview", + "body": body, + (data) -> + $("#preview").html data.body + "json" + + hookPreview: (switcher, textarea) -> + # put div#preview after textarea + preview_box = $(document.createElement("div")).attr "id", "preview" + preview_box.addClass("body") + $(textarea).after preview_box + preview_box.hide() + + $(".edit a",switcher).click -> + $(".preview",switcher).removeClass("active") + $(this).parent().addClass("active") + $(preview_box).hide() + $(textarea).show() + false + $(".preview a",switcher).click -> + $(".edit",switcher).removeClass("active") + $(this).parent().addClass("active") + $(preview_box).show() + $(textarea).hide() + Posts.preview($(textarea).val()) + false + + initCloseWarning: (el, msg) -> + return false if el.length == 0 + msg = "离开本页面将丢失未保存页面!" if !msg + $("input[type=submit]").click -> + $(window).unbind("beforeunload") + el.change -> + if el.val().length > 0 + $(window).bind "beforeunload", (e) -> + if $.browser.msie + e.returnValue = msg + else + return msg + else + $(window).unbind("beforeunload") + + + + + +# pages ready +$(document).ready -> + $("textarea").bind "keydown","ctrl+return",(el) -> + if $(el.target).val().trim().length > 0 + $("#reply > form").submit() + return false + + Posts.initCloseWarning($("textarea.closewarning")) + $("textarea").autogrow() + Posts.initUploader() + + Posts.hookPreview($(".editor_toolbar"), $(".post_editor")) + + $("body").bind "keydown", "m", (el) -> + $('#markdown_help_tip_modal').modal + keyboard : true + backdrop : true + show : true + + # Focus title field in new-post page + $("body.posts-controller.new-action #post_title").focus() \ No newline at end of file diff --git a/app/assets/javascripts/will_paginate.js b/app/assets/javascripts/will_paginate.js new file mode 100644 index 0000000..0c19526 --- /dev/null +++ b/app/assets/javascripts/will_paginate.js @@ -0,0 +1,33 @@ +// Keyboard shortcuts for browsing pages of lists +(function($) { + $(document).keydown(handleKey); + function handleKey(e) { + var left_arrow = 37; + var right_arrow = 39; + if (e.target.nodeName == 'BODY' || e.target.nodeName == 'HTML') { + if (!e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) { + var code = e.which; + if (code == left_arrow) { + prevPage(); + } + else if (code == right_arrow) { + nextPage(); + } + } + } + } + + function prevPage() { + var href = $('.pagination .previous_page a').attr('href'); + if (href && href != document.location) { + document.location = href; + } + } + + function nextPage() { + var href = $('.pagination .next_page a').attr('href'); + if (href && href != document.location) { + document.location = href; + } + } +})(jQuery); diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 7261d5d..5492163 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -10,6 +10,7 @@ * *= require bootstrap.min *= require style +*= require_tree ./sprites/ *= require_self */ diff --git a/app/assets/stylesheets/cpanel.scss b/app/assets/stylesheets/cpanel.scss index a5f76ce..b5ebf46 100644 --- a/app/assets/stylesheets/cpanel.scss +++ b/app/assets/stylesheets/cpanel.scss @@ -1,5 +1,6 @@ /* *= require bootstrap +*= require_tree ./sprites/ *= require_self */ body { color: #333; } @@ -193,3 +194,61 @@ div.field .hint { font-size:12px; color:#999;} p { font-size:16px; } } +#preview { + /* copied from twitter bootstrap */ + margin-top:0px; + border: 1px solid #ccc; + padding:4px; + min-height:400px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + #reply & { + width:578px; + margin-bottom:10px; + min-height:72px; + } +} + +.help-block ul { margin-bottom:0; } +.editor_toolbar { + position:relative; + margin-bottom:5px; + .icons { position:absolute; top:3px; right:0; } + .pills { + margin: 0; + list-style: none; + li { display:inline;} + a { + -moz-border-radius: 8px; + -webkit-border-radius: 8px; + border-radius: 8px; + padding:0 5px; + line-height:18px; + font-size:12px; + margin-right:6px; + text-shadow:0; + color:#444; + border:1px solid #fff; + } + a:hover { + background:#fff; + color:#00438A; + text-decoration: underline; + text-shadow:0; + } + .active { + a { + background:#fff; + border:1px solid #ddd; + color:#666; + text-shadow:0; + } + a:hover { text-decoration: none;} + } + } +} + + + +#post_upload_images { position:absolute;bottom:0;right:0;width:0;height:0;overflow:hidden; } \ No newline at end of file diff --git a/app/assets/stylesheets/cpanel/photos.css.scss b/app/assets/stylesheets/cpanel/photos.css.scss new file mode 100644 index 0000000..e778984 --- /dev/null +++ b/app/assets/stylesheets/cpanel/photos.css.scss @@ -0,0 +1,7 @@ +// Place all the styles related to the cpanel::photos controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ + + + + diff --git a/app/assets/stylesheets/posts.css.scss b/app/assets/stylesheets/posts.css.scss index 1a7e153..effd45c 100644 --- a/app/assets/stylesheets/posts.css.scss +++ b/app/assets/stylesheets/posts.css.scss @@ -1,3 +1,257 @@ // Place all the styles related to the posts controller here. // They will automatically be included in application.css. // You can use Sass (SCSS) here: http://sass-lang.com/ + +//= require gfdynamicfeedcontrol +//= require gadget +.topics .topic .title a:link, +.topics .topic .title a:visited, +.node_topics .title a:link, +.node_topics .title a:visited {color:#2c64d7; text-decoration: none;} +.topics .topic .title a:hover, +.node_topics .title a:hover { text-decoration: underline; } + +.sidebar p { margin-bottom:8px;} + +.topics { + .topic { + .avatar_large { width:64px; } + .avatar { width:56px; margin-left:10px; } + .infos { padding-right:74px; } + .right_info { padding-left:66px;} + .title { font-size:14px; } + .info { color:#999; margin-bottom:2px; } + a:link, a:visited { color:#999; text-decoration: underline; } + .replies { + width:70px; margin-right:10px; text-align:right; vertical-align:middle; + a.count,a.count:visited { line-height: 12px; font-weight: bold; color: white; + background-color: #1c7fdb; display: inline-block; + padding: 2px 10px 2px 10px; + -moz-border-radius: 12px; -webkit-border-radius: 12px; + margin: 18px 12px 0px 0px; text-decoration: none; + } + a.count:hover { color:write; background-color:#1F8AEE; } + a.state_true:link,a.state_true:visited { background:#DDD; } + a.state_true:hover { background:#1dc115;} + } + } + .body { + margin-bottom:10px; margin-top:8px; + img { max-width:690px;} + } + .tools { + text-align:right; height:16px; overflow:hidden; + a.likeable { + i { position:relative; margin-bottom:-1px; } + text-decoration: none; + } + } + .topic_line {border-bottom:1px solid #DDD; padding:10px 0; margin:0 -10px; vertical-align:top; } + tr.topic td.replies { text-align:right; width:50px; font-size:14px; color:green;font-weight:bold; } +} + + +#topic_show { + h1 { font-size:20px; color:#333; margin-top:6px; text-align: left; line-height:100%;margin-bottom:8px;} + .infos { + border-bottom:1px solid #ddd; + padding-bottom:6px; margin-bottom:8px; + } +} + +.more { padding:8px; padding-bottom:0; font-size:14px; text-align:right; } + +/* topics list in node page */ + +.node_topics { + margin-bottom: 16px; + tr td { + padding: 8px; } + tr.head td { + padding-top: 14px; + color: #CCC; + font-weight: bold; + font-size: 12px; } + tr.topic td.title { + font-size: 14px; + font-weight: bold; } + tr.topic td.author { + width: 80px; } + tr.topic td.author a { + color: #666; + font-weight: bold; } +} + +.no_result { margin-bottom:20px; text-align:center; } + +#node_info { + margin:0 -10px; padding:0 10px; border-bottom:1px solid #ddd; + h1 { text-align:right; font-size:15px; } + h2 { line-height:100%; display:inline; font-size:16px; margin-right:10px;} + .desc { color:#999; } + .feed { + float: right; + .icon { margin-bottom: -3px; } + a { + width: auto; + padding-left: 18px; + color: #B94E22; + &:hover { + text-decoration: none; + color: #333; + } + } + } +} + +#replies { + .total { padding-bottom:6px; color:#999; } + .reply { + border-top:1px solid #DDD; padding:8px 10px; margin:0 -10px; + .face { padding-right:8px; width:48px; margin-left:0; } + .infos { padding-left:58px; } + .info { + margin-top:4px; color:#999;height:20px; + a:link, + a:visited { color:#999; text-decoration: underline;} + .name { float:left; } + .time { float:right; text-align:right; } + a.reply_link img { vertical-align:middle;} + } + .body { + img { max-width:622px;} + } + } + .reply.light { background:#F7F2FC;} +} + +#reply.form { + .pills::after { clear:left;} + textarea { width:578px; margin-bottom:10px;} + position:relative; + .submit_buttons { + position:absolute; right:10px; top:42px; + } +} + + +/* Topic & Reply body format */ +.topics .topic .body, +#replies .reply .body { + line-height:180%; font-size:14px; text-overflow: ellipsis; word-wrap: break-word; + a:link, a:visited { color:#0069D6; text-decoration: none; } + a:hover { text-decoration: underline; color:#00438A; } + a.at_floor { color:#376B43; } + a.at_user { + color:#333; font-weight:bold; + i { color:#777; } + } + h4 { font-weight:bold; font-size:15px; line-height:100%; margin:0; color:#222; margin-top:20px; border-left:15px solid #eee; padding-left:5px; margin-bottom:8px; } + p { margin-bottom:10px; } + strong { color:#000; } + ul, + ol { + list-style-position: inside; + margin:0; + padding:5px 14px; + p { margin:0; } + li { line-height:160%; color:#333; font-size:13px; } + } +} + +.edit_tools { text-align:left; margin-bottom:2px } + +.totals ul li { line-height:150%;} + +#topic_new_tip li { margin-bottom:6px;} + +#topics_recent { + h2 { + margin:0 -10px; padding:0 10px; + font-size:14px; color:#999; line-height:100%; + border-bottom:1px solid #ddd; padding-bottom:8px; + } + .node { + margin-right:6px; + a { color:#333; background:#eee; -webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px; padding:3px;font-size:11px; } + } + .info { font-size:12px; color:#999; + margin-left:6px; + a { color:#999; text-decoration: underline;} + } + ul { + margin:0; padding:0; + li { + margin:0 -10px; padding:6px 10px; + list-style:none; border-bottom:1px dashed #ddd; + } + } + .more { } +} + +#reply { + form { + } + .editor_toolbar { + width:588px; + } +} + +.sidebar { + .hot_nodes { + ul { + margin: 0; + list-style: none; + li { + display: inline; + margin: 0; + padding: 0; + a { + display: inline-block; + margin-right: 3px; + margin-bottom: 6px; + padding: 2px 10px; + color: #778087; + text-decoration: none; + background-color: #f5f5f5; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; + &:hover { + color: white; + background-color: #99a; + } + } + } + } + } + .suggest_topics { + ul { + li { + line-height:130%; + a { + color:#AA2D19; + font-size:12px; + } + } + } + } +} + +#preview { + /* copied from twitter bootstrap */ + margin-top:0px; + border: 1px solid #ccc; + padding:4px; + min-height:400px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + #reply & { + width:578px; + margin-bottom:10px; + min-height:72px; + } +} + + diff --git a/app/assets/stylesheets/sprites/icons.scss b/app/assets/stylesheets/sprites/icons.scss new file mode 100644 index 0000000..51c4221 --- /dev/null +++ b/app/assets/stylesheets/sprites/icons.scss @@ -0,0 +1,16 @@ +/* + + Creating a sprite from following images: + + app/assets/images/sprites/icons/rss.png (16x16) + + Output files: + app/assets/images/sprites/icons.png + app/assets/stylesheets/sprites/icons.scss + + Output size: + 16x16 + + +*/ +.icons_rss { width: 16px; height: 16px; background: url(image-path('sprites/icons.png')) 0px 0px no-repeat; } diff --git a/app/assets/stylesheets/sprites/small.scss b/app/assets/stylesheets/sprites/small.scss new file mode 100644 index 0000000..2c57808 --- /dev/null +++ b/app/assets/stylesheets/sprites/small.scss @@ -0,0 +1,40 @@ +/* + + Creating a sprite from following images: + + app/assets/images/sprites/small/calenda.png (12x12) + app/assets/images/sprites/small/delete.png (12x12) + app/assets/images/sprites/small/edit.png (12x12) + app/assets/images/sprites/small/image.png (12x12) + app/assets/images/sprites/small/like.png (12x12) + app/assets/images/sprites/small/liked.png (12x12) + app/assets/images/sprites/small/lock.png (12x12) + app/assets/images/sprites/small/mail.png (12x12) + app/assets/images/sprites/small/mail_full.png (12x12) + app/assets/images/sprites/small/pin.png (12x12) + app/assets/images/sprites/small/reply.png (12x12) + app/assets/images/sprites/small/vote_down.png (12x12) + app/assets/images/sprites/small/vote_up.png (12x12) + + Output files: + app/assets/images/sprites/small.png + app/assets/stylesheets/sprites/small.scss + + Output size: + 156x12 + + +*/ +.small_calenda { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) 0px 0px no-repeat; } +.small_delete { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -12px 0px no-repeat; } +.small_edit { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -24px 0px no-repeat; } +.small_image { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -36px 0px no-repeat; } +.small_like { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -48px 0px no-repeat; } +.small_liked { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -60px 0px no-repeat; } +.small_lock { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -72px 0px no-repeat; } +.small_mail { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -84px 0px no-repeat; } +.small_mail_full { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -96px 0px no-repeat; } +.small_pin { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -108px 0px no-repeat; } +.small_reply { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -120px 0px no-repeat; } +.small_vote_down { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -132px 0px no-repeat; } +.small_vote_up { width: 12px; height: 12px; background: url(image-path('sprites/small.png')) -144px 0px no-repeat; } diff --git a/app/assets/stylesheets/window.scss b/app/assets/stylesheets/window.scss new file mode 100644 index 0000000..07e3c68 --- /dev/null +++ b/app/assets/stylesheets/window.scss @@ -0,0 +1,8 @@ +/* + *= require bootstrap + *= require_self + */ +* { margin:0;} +html { background:#FFF; } +body { text-align: left; padding:0;} +form .row { margin-bottom:6px; } \ No newline at end of file diff --git a/app/controllers/cpanel/home_controller.rb b/app/controllers/cpanel/home_controller.rb index 97ce8a0..6ee19af 100644 --- a/app/controllers/cpanel/home_controller.rb +++ b/app/controllers/cpanel/home_controller.rb @@ -1,3 +1,4 @@ +# coding: utf-8 class Cpanel::HomeController < Cpanel::ApplicationController def index diff --git a/app/controllers/cpanel/photos_controller.rb b/app/controllers/cpanel/photos_controller.rb new file mode 100644 index 0000000..e2a74b4 --- /dev/null +++ b/app/controllers/cpanel/photos_controller.rb @@ -0,0 +1,28 @@ +# coding: utf-8 +class Cpanel::PhotosController < Cpanel::ApplicationController + + + def index + @photos = Photo.unscoped.desc(:_id).paginate :page => params[:page], :per_page => 30 + end + + def create + # 浮动窗口上传 + @photo = Photo.new + @photo.image = params[:Filedata] + @photo.filename = params[:Filedata].original_filename + @photo.content_type = params[:Filedata].content_type + @photo.save! + render :text => @photo.image.normal.url + end + + + def destroy + @photo = Photo.unscoped.find(params[:id]) + @photo.destroy + + redirect_to(cpanel_photos_path) + end + + +end diff --git a/app/controllers/cpanel/posts_controller.rb b/app/controllers/cpanel/posts_controller.rb index e061e3d..d44cfb0 100644 --- a/app/controllers/cpanel/posts_controller.rb +++ b/app/controllers/cpanel/posts_controller.rb @@ -21,6 +21,13 @@ def edit @post.tag_list = @post.tags.join(", ") end + + def preview + @body = params[:body] + respond_to do |format| + format.json + end + end def create @post = Post.new(params[:post]) diff --git a/app/helpers/cpanel/photos_helper.rb b/app/helpers/cpanel/photos_helper.rb new file mode 100644 index 0000000..71dc653 --- /dev/null +++ b/app/helpers/cpanel/photos_helper.rb @@ -0,0 +1,2 @@ +module Cpanel::PhotosHelper +end diff --git a/app/helpers/cpanel/posts_helper.rb b/app/helpers/cpanel/posts_helper.rb index 3b51dbb..22b1939 100644 --- a/app/helpers/cpanel/posts_helper.rb +++ b/app/helpers/cpanel/posts_helper.rb @@ -1,2 +1,7 @@ module Cpanel::PostsHelper + + def format_topic_body(text) + MarkdownTopicConverter.format(text) + end + end diff --git a/app/models/photo.rb b/app/models/photo.rb new file mode 100644 index 0000000..62ed358 --- /dev/null +++ b/app/models/photo.rb @@ -0,0 +1,18 @@ +# coding: utf-8 +class Photo + include Mongoid::Document + include Mongoid::Timestamps + include Mongoid::BaseModel + + field :image + field :filename + field :content_type + + + + attr_accessible :image + + # 封面图 + mount_uploader :image, PhotoUploader + +end \ No newline at end of file diff --git a/app/uploaders/photo_uploader.rb b/app/uploaders/photo_uploader.rb new file mode 100644 index 0000000..ed93ee2 --- /dev/null +++ b/app/uploaders/photo_uploader.rb @@ -0,0 +1,51 @@ +# coding: utf-8 +require 'carrierwave/processing/mini_magick' +class PhotoUploader < CarrierWave::Uploader::Base + include CarrierWave::MiniMagick + + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + # "#{model.class.to_s.underscore}" + end + + # Provide a default URL as a default if there hasn't been a file uploaded: + def default_url + "photo/#{version_name}.jpg" + end + + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w(jpg jpeg gif png) + end + + + + # Override the filename of the uploaded files: + def filename + # current_path 是 Carrierwave 上传过程临时创建的一个文件,有时间标记,所以它将是唯一的 + @name ||= Digest::MD5.hexdigest(File.dirname(current_path)) + "#{@name}.#{file.extension.downcase}" + end + + + version :original + + version :normal do + process :resize_to_limit => [480, nil] + end + + version :thumb do + process :resize_to_limit => [240, nil] + end + + version :small do + process :resize_to_fit => [120, nil] + end + + +end \ No newline at end of file diff --git a/app/views/cpanel/categories/index.html.erb b/app/views/cpanel/categories/index.html.erb index 8b06124..0f99631 100644 --- a/app/views/cpanel/categories/index.html.erb +++ b/app/views/cpanel/categories/index.html.erb @@ -17,8 +17,8 @@ <%= categorie.id %> <%= categorie.name %> <%= categorie.sort %> - <%= link_to '编辑', edit_cpanel_category_path(categorie) , :class => "icon small_edit" %> - <%= link_to '删除', cpanel_category_path(categorie), :confirm => 'Are you sure?', :method => :delete, :class => "icon small_delete" %> + <%= link_to '', edit_cpanel_category_path(categorie) , :class => "icon small_edit" %> + <%= link_to '', cpanel_category_path(categorie), :confirm => 'Are you sure?', :method => :delete, :class => "icon small_delete" %> <% end %> diff --git a/app/views/cpanel/pages/index.html.erb b/app/views/cpanel/pages/index.html.erb index fac2f37..41a9fa1 100644 --- a/app/views/cpanel/pages/index.html.erb +++ b/app/views/cpanel/pages/index.html.erb @@ -19,8 +19,8 @@ <%= truncate(page.title,:length => 30) %> <%= page.created_at %> - <%= link_to '编辑', edit_cpanel_page_path(page), :class => "icon small_edit" %> - <%= link_to '删除', cpanel_page_path(page), :confirm => 'Are you sure?', :method => :delete, :class => "icon small_delete" %> + <%= link_to '', edit_cpanel_page_path(page), :class => "icon small_edit" %> + <%= link_to '', cpanel_page_path(page), :confirm => 'Are you sure?', :method => :delete, :class => "icon small_delete" %> <% end %> diff --git a/app/views/cpanel/photos/index.html.erb b/app/views/cpanel/photos/index.html.erb new file mode 100644 index 0000000..2a7f236 --- /dev/null +++ b/app/views/cpanel/photos/index.html.erb @@ -0,0 +1,32 @@ +<% content_for :sitemap do %> + <%= t("cpanel.menu.photos") %> +<% end %> +

Listing photos

+ + + + + + + + + +<% @photos.each do |photo| %> + + + + + + + +<% end %> +
Idimagetime
<%= photo.id %> + <%= photo.filename %>( <%= photo.content_type %>)
+ <%= image_tag(photo.image.thumb.url ) %> +
<%= photo.created_at %> + <%= link_to '', cpanel_photo_path(photo), :confirm => 'Are you sure?', :method => :delete, :class => "icon small_delete" %>
+ +
+ + + diff --git a/app/views/cpanel/posts/_editor_toolbar.html.erb b/app/views/cpanel/posts/_editor_toolbar.html.erb new file mode 100644 index 0000000..f4a148c --- /dev/null +++ b/app/views/cpanel/posts/_editor_toolbar.html.erb @@ -0,0 +1,12 @@ +
+
+ <%= link_to("", "#", :id => "post_add_image", :rel => "twipsy", :title => "添加图片", :class => "icon small_image")%> +
+ +
+
+
    +
  • <%= link_to(t("common.editor_toolbar_edit"), "#") %>
  • +
  • <%= link_to(t("common.editor_toolbar_preview"), "#") %>
  • +
+
\ No newline at end of file diff --git a/app/views/cpanel/posts/_form.html.erb b/app/views/cpanel/posts/_form.html.erb index 61ce100..9cd435d 100644 --- a/app/views/cpanel/posts/_form.html.erb +++ b/app/views/cpanel/posts/_form.html.erb @@ -1,3 +1,5 @@ +<%= javascript_include_tag "posts" %> + <%= form_for([:cpanel,@post]) do |f| %>
@@ -15,12 +17,24 @@ <%= f.select :category_id, Category.all.collect { |s| [s.name,s.id] } %> + + +
+ +
+ <%= render "editor_toolbar" %> +
+
+ + +
<%= f.label :body %>
- <%= f.text_area :body, :class => "span13", :style => "height:400px" %> + <%= f.text_area :body, :class => "post_editor closewarning ", :style => "height:400px;width:99%" %>
+
<%= f.label :tag_list %>
diff --git a/app/views/cpanel/posts/index.html.erb b/app/views/cpanel/posts/index.html.erb index d30a995..7c98e6b 100644 --- a/app/views/cpanel/posts/index.html.erb +++ b/app/views/cpanel/posts/index.html.erb @@ -18,8 +18,8 @@ <%= truncate(post.title,:length => 30) %> <%= post.created_at %> <%= render_post_state_s(post) %> - <%= link_to '编辑', edit_cpanel_post_path(post), :class => "icon small_edit" %> - <%= link_to '删除', cpanel_post_path(post), :confirm => "Are you sure?", :method => :delete , :class => "icon small_delete"%> + <%= link_to '', edit_cpanel_post_path(post), :class => "icon small_edit" %> + <%= link_to '', cpanel_post_path(post), :confirm => "Are you sure?", :method => :delete , :class => "icon small_delete"%> <% end %> diff --git a/app/views/cpanel/posts/preview.json.erb b/app/views/cpanel/posts/preview.json.erb new file mode 100644 index 0000000..6873f70 --- /dev/null +++ b/app/views/cpanel/posts/preview.json.erb @@ -0,0 +1 @@ +<%= {:body => format_topic_body(@body)}.to_json.html_safe %> \ No newline at end of file diff --git a/app/views/cpanel/site_configs/index.html.erb b/app/views/cpanel/site_configs/index.html.erb index 501463b..675d36a 100644 --- a/app/views/cpanel/site_configs/index.html.erb +++ b/app/views/cpanel/site_configs/index.html.erb @@ -13,7 +13,7 @@ <% @site_configs.each do |site_config| %> <%= site_config.key %> - <%= link_to 'edit', edit_cpanel_site_config_path(site_config), :class => "icon small_edit" %> + <%= link_to '', edit_cpanel_site_config_path(site_config), :class => "icon small_edit" %> <% end %> diff --git a/app/views/cpanel/sites/index.html.erb b/app/views/cpanel/sites/index.html.erb index c5b9d8c..45fcce4 100644 --- a/app/views/cpanel/sites/index.html.erb +++ b/app/views/cpanel/sites/index.html.erb @@ -21,8 +21,8 @@ <%= item.desc %> <%= item.created_at %> - <%= link_to "编辑", edit_cpanel_site_path(item.id), :class => "icon small_edit" %> - <%= link_to "删除", cpanel_site_path(item.id), :method => :delete, :confirm => '确定要删除吗?', :class => "icon small_delete" %> + <%= link_to "", edit_cpanel_site_path(item.id), :class => "icon small_edit" %> + <%= link_to "", cpanel_site_path(item.id), :method => :delete, :confirm => '确定要删除吗?', :class => "icon small_delete" %> <% end %> diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 252f247..7dc4df2 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -3,7 +3,7 @@ <%= raw SiteConfig.site_title %> - Powered by Icelog(<%= APP_VERSION %>) <%= stylesheet_link_tag "application", :media => "all" %> - <%= javascript_include_tag "application" %> + <%= csrf_meta_tags %> @@ -35,7 +35,7 @@
- +<%= javascript_include_tag "app" %> <%= render :partial => "shared/google_analytics"%> diff --git a/app/views/layouts/cpanel.html.erb b/app/views/layouts/cpanel.html.erb index 9d01e25..b877fa9 100644 --- a/app/views/layouts/cpanel.html.erb +++ b/app/views/layouts/cpanel.html.erb @@ -3,6 +3,7 @@ <%= raw SiteConfig.site_title %> - Control Panel <%= stylesheet_link_tag "cpanel" %> + <%= javascript_include_tag "app" %> <%= csrf_meta_tag %> @@ -15,6 +16,7 @@ li << link_to(t("cpanel.menu.sections"), cpanel_categories_path ) li << link_to(t("cpanel.menu.posts"),cpanel_posts_path ) li << link_to(t("cpanel.menu.pages"),cpanel_pages_path ) + li << link_to(t("cpanel.menu.photos"),cpanel_photos_path ) li << link_to(t("cpanel.menu.sites"),cpanel_sites_path ) li << link_to(t("cpanel.menu.site_configs"), cpanel_site_configs_path ) end %> @@ -40,6 +42,9 @@ <%= yield %> + + +