From fdac822036e4588b5d80aa3620af67b9c0f1ad4a Mon Sep 17 00:00:00 2001 From: chiu Date: Wed, 1 Apr 2020 11:44:59 +0800 Subject: [PATCH] add some feature --- .../ui-bg_flat_0_888888_40x100.png | Bin 0 -> 179 bytes .../ui-bg_flat_0_aaaaaa_40x100.png | Bin 0 -> 180 bytes .../ui-bg_flat_75_ffffff_40x100.png | Bin 0 -> 178 bytes .../ui-bg_glass_25_e1f0f5_1x400.png | Bin 0 -> 114 bytes .../ui-bg_glass_55_444444_1x400.png | Bin 0 -> 121 bytes .../ui-bg_glass_65_ffffff_1x400.png | Bin 0 -> 105 bytes .../ui-bg_glass_75_dadada_1x400.png | Bin 0 -> 111 bytes .../ui-bg_highlight-soft_75_cccccc_1x100.png | Bin 0 -> 101 bytes .../ui-bg_inset-soft_95_fef1ec_1x100.png | Bin 0 -> 123 bytes .../ui-icons_222222_256x240.png | Bin 0 -> 4369 bytes .../ui-icons_309bbf_256x240.png | Bin 0 -> 5355 bytes .../ui-icons_454545_256x240.png | Bin 0 -> 4369 bytes .../ui-icons_bf3030_256x240.png | Bin 0 -> 4369 bytes .../ui-icons_ffffff_256x240.png | Bin 0 -> 4369 bytes .../javascripts/registered_site_progress.js | 20 +- .../admin/register_api_controller.rb | 25 +- .../admin/registered_sites_controller.rb | 463 +++++++++++++++++- .../registered_sites_controller.rb | 10 + app/models/bundle_update_log.rb | 13 + app/models/bundle_update_temp.rb | 8 + app/models/check_site_temp.rb | 7 + app/models/registered_site.rb | 84 +++- app/models/site_annc.rb | 17 + app/models/site_status.rb | 8 + app/models/update_flags.rb | 6 + .../_bundle_update_remote_show.html.erb | 79 +++ .../admin/registered_sites/_form.html.erb | 9 +- .../_site_selection_box.html.erb | 99 ++++ .../admin/registered_sites/announcement.erb | 100 ++++ .../bundle_update_remote_show.erb | 343 +++++++++++++ .../admin/registered_sites/edit_annc.erb | 76 +++ .../registered_sites/get_select_box.html.erb | 87 ++++ config/locales/en.yml | 36 +- config/locales/zh_tw.yml | 20 + config/routes.rb | 25 +- lib/registered_sites/engine.rb | 14 +- 36 files changed, 1514 insertions(+), 35 deletions(-) create mode 100644 app/assets/images/registered_sites/ui-bg_flat_0_888888_40x100.png create mode 100644 app/assets/images/registered_sites/ui-bg_flat_0_aaaaaa_40x100.png create mode 100644 app/assets/images/registered_sites/ui-bg_flat_75_ffffff_40x100.png create mode 100644 app/assets/images/registered_sites/ui-bg_glass_25_e1f0f5_1x400.png create mode 100644 app/assets/images/registered_sites/ui-bg_glass_55_444444_1x400.png create mode 100644 app/assets/images/registered_sites/ui-bg_glass_65_ffffff_1x400.png create mode 100644 app/assets/images/registered_sites/ui-bg_glass_75_dadada_1x400.png create mode 100644 app/assets/images/registered_sites/ui-bg_highlight-soft_75_cccccc_1x100.png create mode 100644 app/assets/images/registered_sites/ui-bg_inset-soft_95_fef1ec_1x100.png create mode 100644 app/assets/images/registered_sites/ui-icons_222222_256x240.png create mode 100644 app/assets/images/registered_sites/ui-icons_309bbf_256x240.png create mode 100644 app/assets/images/registered_sites/ui-icons_454545_256x240.png create mode 100644 app/assets/images/registered_sites/ui-icons_bf3030_256x240.png create mode 100644 app/assets/images/registered_sites/ui-icons_ffffff_256x240.png create mode 100644 app/models/bundle_update_log.rb create mode 100644 app/models/bundle_update_temp.rb create mode 100644 app/models/check_site_temp.rb create mode 100644 app/models/site_annc.rb create mode 100644 app/models/site_status.rb create mode 100644 app/models/update_flags.rb create mode 100644 app/views/admin/registered_sites/_bundle_update_remote_show.html.erb create mode 100644 app/views/admin/registered_sites/_site_selection_box.html.erb create mode 100644 app/views/admin/registered_sites/announcement.erb create mode 100644 app/views/admin/registered_sites/bundle_update_remote_show.erb create mode 100644 app/views/admin/registered_sites/edit_annc.erb create mode 100644 app/views/admin/registered_sites/get_select_box.html.erb diff --git a/app/assets/images/registered_sites/ui-bg_flat_0_888888_40x100.png b/app/assets/images/registered_sites/ui-bg_flat_0_888888_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..7cd111a0da8e1753ebafc6476c31fbf576f89ac0 GIT binary patch literal 179 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsVYww$B>N1x91EQ4=4yQ7&`pj zttVualF{DX^k!z|wf?#5ne(|;HLY5pwSvkN_ZCa$__&+5Vu7w;@O1TaS?83{1OTMo BM2G+Y literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-bg_flat_0_aaaaaa_40x100.png b/app/assets/images/registered_sites/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..5b5dab2ab7b1c50dea9cfe73dc5a269a92d2d4b4 GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FscKIb$B>N1x91EQ4=4yQ7#`R^ z$vje}bP0l+XkK DSH>_4 literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-bg_flat_75_ffffff_40x100.png b/app/assets/images/registered_sites/ui-bg_flat_75_ffffff_40x100.png new file mode 100644 index 0000000000000000000000000000000000000000..ac8b229af950c29356abf64a6c4aa894575445f0 GIT binary patch literal 178 zcmeAS@N?(olHy`uVBq!ia0vp^8bF-F!3HG1q!d*FsY*{5$B>N1x91EQ4=4yQYz+E8 zPo9&<{J;c_6SHRil>2s{Zw^OT)6@jj2u|u!(plXsM>LJD`vD!n;OXk;vd$@?2>^GI BH@yG= literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-bg_glass_25_e1f0f5_1x400.png b/app/assets/images/registered_sites/ui-bg_glass_25_e1f0f5_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42f8788cc629a8cd5fc735dbe877c1df0c7eec1e GIT binary patch literal 114 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq%1vM978O6-=5pZ$)F&@e9`;c z{Y#uWIe+;Sn&v8G#uaNiyt9jgP6p@Y(h^dJ=*OX-%Q5Ub|N9mM?V{^7zDUd~AlfUkMM# V!i8#5oj|h~JYD@<);T3K0RRE2CJF!m literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-bg_glass_65_ffffff_1x400.png b/app/assets/images/registered_sites/ui-bg_glass_65_ffffff_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..42ccba269b6e91bef12ad0fa18be651b5ef0ee68 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouqzpV=978O6-=0?FV^9z|eBtf= z|7WztIJ;WT>{+tN>ySr~=F{k$>;_x^_y?afmf9pRKH0)6?eSP?3s5hEr>mdKI;Vst E0O;M1& literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-bg_glass_75_dadada_1x400.png b/app/assets/images/registered_sites/ui-bg_glass_75_dadada_1x400.png new file mode 100644 index 0000000000000000000000000000000000000000..5a46b47cb16631068aee9e0bd61269fc4e95e5cd GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^j6gJjgAK^akKnouq|7{B978O6lPf+wIa#m9#>Unb zm^4K~wN3Zq+uPS{Ou}E*`%9 zKPdOkfrN+ZlHSt7(uY{3{#;wiJb&Ugx1>W4qtrSDm(4hFaaY-$3p3x|sIU3`%J?Qj YcLn#R=pC)AfTl5cy85}Sb4q9e0MP_2(*OVf literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-icons_222222_256x240.png b/app/assets/images/registered_sites/ui-icons_222222_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b273ff111d219c9b9a8b96d57683d0075fb7871a GIT binary patch literal 4369 zcmd^?`8O2)_s3^phOrG}UnfiUEn8(9QW1?MNkxXVDEpFin2{xWrLx5kBC;k~GmPmYTG^FX}c% zlGE{DS1Q;~I7-6ze&TN@+F-xsI6sd%SwK#*O5K|pDRZqEy< zJg0Nd8F@!OxqElm`~U#piM22@u@8B<moyKE%ct`B(jysxK+1m?G)UyIFs1t0}L zemGR&?jGaM1YQblj?v&@0iXS#fi-VbR9zLEnHLP?xQ|=%Ihrc7^yPWR!tW$yH!zrw z#I2}_!JnT^(qk)VgJr`NGdPtT^dmQIZc%=6nTAyJDXk+^3}wUOilJuwq>s=T_!9V) zr1)DT6VQ2~rgd@!Jlrte3}}m~j}juCS`J4(d-5+e-3@EzzTJNCE2z)w(kJ90z*QE) zBtnV@4mM>jTrZZ*$01SnGov0&=A-JrX5Ge%Pce1Vj}=5YQqBD^W@n4KmFxxpFK`uH zP;(xKV+6VJ2|g+?_Lct7`uElL<&jzGS8Gfva2+=8A@#V+xsAj9|Dkg)vL5yhX@~B= zN2KZSAUD%QH`x>H+@Ou(D1~Pyv#0nc&$!1kI?IO01yw3jD0@80qvc?T*Nr8?-%rC8 z@5$|WY?Hqp`ixmEkzeJTz_`_wsSRi1%Zivd`#+T{Aib6-rf$}M8sz6v zb6ERbr-SniO2wbOv!M4)nb}6UVzoVZEh5kQWh_5x4rYy3c!871NeaM(_p=4(kbS6U#x<*k8Wg^KHs2ttCz<+pBxQ$Z zQMv;kVm5_fF_vH`Mzrq$Y&6u?j6~ftIV0Yg)Nw7JysIN_ z-_n*K_v1c&D}-1{NbBwS2h#m1y0a5RiEcYil+58$8IDh49bPnzE7R8In6P%V{2IZU z7#clr=V4yyrRe@oXNqbqo^^LvlLE?%8XaI&N(Np90-psU}7kqmbWk zZ;YBwJNnNs$~d!mx9oMGyT( znaBoj0d}gpQ^aRr?6nW)$4god*`@Uh2e+YpS@0(Mw{|z|6ko3NbTvDiCu3YO+)egL z>uW(^ahKFj>iJ-JF!^KhKQyPTznJa;xyHYwxJgr16&Wid_9)-%*mEwo{B_|M9t@S1 zf@T@q?b2Qgl!~_(Roe;fdK)y|XG0;ls;ZbT)w-aOVttk#daQcY7$cpY496H*`m@+L zeP#$&yRbBjFWv}B)|5-1v=(66M_;V1SWv6MHnO}}1=vby&9l+gaP?|pXwp0AFDe#L z&MRJ^*qX6wgxhA_`*o=LGZ>G_NTX%AKHPz4bO^R72ZYK}ale3lffDgM8H!Wrw{B7A z{?c_|dh2J*y8b04c37OmqUw;#;G<* z@nz@dV`;7&^$)e!B}cd5tl0{g(Q>5_7H^@bEJi7;fQ4B$NGZerH#Ae1#8WDTH`iB&) zC6Et3BYY#mcJxh&)b2C^{aLq~psFN)Q1SucCaBaBUr%5PYX{~-q{KGEh)*;n;?75k z=hq%i^I}rd;z-#YyI`8-OfMpWz5kgJE3I!3ean6=UZi!BxG7i(YBk? z02HM7wS0)Wni{dWbQMRtd-A)_Az!t>F;IwWf~!*)-Az4}yryNkz&9)w>ElA80Oc`6 zHo#9H!Y3*Qx9n@Jn)!w6G^hb;e_n8zpIyXCN`JFkPc)^Q?2MsLNFhMgrcZI-<#1ne zjH;KFf?4eAT9mQZ}ZfHLGA#d%s;SZK4p0FwZT2S^{ zQ2BG1xJsbK6?yrHTjJi|5C0u=!|r!?*4FL%y%3q#(d+e>b_2I9!*iI!30}42Ia0bq zUf`Z?LGSEvtz8s``Tg5o_CP(FbR0X$FlE0yCnB7suDPmI2=yOg^*2#cY9o`X z;NY-3VBHZjnVcGS){GZ98{e+lq~O$u6pEcgd0CrnIsWffN1MbCZDH<7c^hv+Z0Ucf0{w zSzi^qKuUHD9Dgp0EAGg@@$zr32dQx>N=ws`MESEsmzgT2&L;?MSTo&ky&!-JR3g~1 zPGTt515X)wr+Bx(G9lWd;@Y3^Vl}50Wb&6-Tiy;HPS0drF`rC}qYq22K4)G#AoD0X zYw$E+Bz@Zr^50MAwu@$?%f9$r4WHH?*2|67&FXFhXBrVFGmg)6?h3^-1?t;UzH0*I zNVf9wQLNLnG2@q>6CGm>&y|lC`iCFfYd}9i%+xkl^5oBJ?<;aneCfcHqJh7Yl5uLS z9Fx-(kMdcNyZejXh22N{mCw_rX1O!cOE&3>e(ZH81PR95wQC37En4O{w;{3q9n1t&;p)D%&Z%Nw$gSPa!nz8Slh7=ko2am)XARwOWw zpsz0~K!s{(dM$NB=(A=kkp>T(*yU6<_dwIx>cH4+LWl282hXa6-EUq>R3t?G2623< z*RwTN%-fgBmD{fu*ejNn)1@KG?Sg*8z3hYtkQJQjB6 zQ|x>wA=o$=O)+nLmgTXW3_6diA;b4EY{*i*R%6dO2EMg z@6g?M3rpbnfB@hOdUeb96=~I?OIA3@BWAGmTwiQ{x5Cqq<8c10L!P zd@Qk^BseTX%$Q7^s}5n%HB|)gKx}H$d8Sb$bBnq9-AglT2dGR2(+I;_fL|R4p$odJ zllfb0NqI)7=^z~qAm1V{(PkpxXsQ#4*NH9yYZ`Vf@)?#ueGgtCmGGY|9U#v|hRdg- zQ%0#cGIfXCd{Y)JB~qykO;KPvHu|5Ck&(Hn%DF~cct@}j+87xhs2ew;fLm5#2+mb| z8{9e*YI(u|gt|{x1G+U=DA3y)9s2w7@cvQ($ZJIA)x$e~5_3LKFV~ASci8W}jF&VeJoPDUy(BB>ExJpck;%;!`0AAo zAcHgcnT8%OX&UW_n|%{2B|<6Wp2MMGvd5`T2KKv;ltt_~H+w00x6+SlAD`{K4!9zx z*1?EpQ%Lwiik){3n{-+YNrT;fH_niD_Ng9|58@m8RsKFVF!6pk@qxa{BH-&8tsim0 zdAQ(GyC^9ane7_KW*#^vMIoeQdpJqmPp%%px3GIftbwESu#+vPyI*YTuJ6+4`z{s? zpkv~0x4c_PFH`-tqafw5)>4AuQ78SkZ!$8}INLK;Egr;2tS18hEO5=t;QDmZ-qu?I zG+=DN`nR72Xto{{bJp||`k}-2G;5#xg8E~xgz22)^_Z;=K|4@(E&5J)SY2of=olcw z5)@L)_Ntcm!*5nEy0M9v0`S33;pO4TN;>4(Z+19p_0>u#e-vE zXCU(6gAvu~I7Cw(xd%0e59MNLw^U37ZDbsBrj%eDCexw8a3G`nTcXVNL6{B7Hj@i& zbVB{;ApEtHk76q08DJ48dSxd$C(;$K6=FpU<~l9pVoT9arW^Vu{%Bcn4`eIpkOVC| z$)AKYG_`ypM{0@BUb3^9lqi_c?ONH|4UJMJWDowMVjacycX7}9g={O7swOB+{;+?; zjBo!9?+nd)ie#x5IbFW-zBOo0c4q@9wGVt5;pNt`=-~Zgcw#*`m($6ibxtZ`H=e=} zF#GZ~5$%AUn};8U#tRem0J(JTR}d4vR(dgK2ML~lZsPhayJ2h1%sD4FVst| zKF)+@`iNzLRjg4=K8@**0=5cE>%?FDc({I^+g9USk<8$&^qD~@%W0i4b|yMG*p4`N zh}I!ltTRI8Ex$+@V{02Br%xq#O?UlhO{r8WsaZnZCZq0MK9%AXU%MDLT;3=0A9(BV z9VxxxJd7jo$hw3q;3o?yBLmA=azBUrd9>-<_ANs0n3?-Ic*6&ytb@H~?0E(*d>T5n z-HiH2jsDf6uWhID%#n>SzOqrFCPDfUcu5QPd?<(=w6pv1BE#nsxS{n!UnC9qAha1< z;3cpZ9A-e$+Y)%b;w@!!YRA9p%Kf9IHGGg^{+p`mh;q8i7}&e@V3EQaMsItEMS&=X plT@$;k0WcB_jb;cn%_Idz4HO$QU*abf4}+wi?e96N>fbq{{i|W0@(ln literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-icons_309bbf_256x240.png b/app/assets/images/registered_sites/ui-icons_309bbf_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..d6f62ed384de852c57f4f1427d22f0306a78b0dd GIT binary patch literal 5355 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 literal 0 HcmV?d00001 diff --git a/app/assets/images/registered_sites/ui-icons_ffffff_256x240.png b/app/assets/images/registered_sites/ui-icons_ffffff_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..42f8f992c727ddaa617da224a522e463df690387 GIT binary patch literal 4369 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 literal 0 HcmV?d00001 diff --git a/app/assets/javascripts/registered_site_progress.js b/app/assets/javascripts/registered_site_progress.js index 6d772dd..c59a437 100644 --- a/app/assets/javascripts/registered_site_progress.js +++ b/app/assets/javascripts/registered_site_progress.js @@ -1 +1,19 @@ -// site progress javascript is here \ No newline at end of file +// site progress javascript is here +$(document).ready(function() { + var config = {} + config.autoGrow_minHeight = 50; + config.toolbar = [ + { name: 'clipboard', items: [ 'Cut', 'Copy', 'Paste', 'PasteText', 'PasteFromWord', '-', 'Undo', 'Redo' ] }, + { name: 'editing', items: [ 'Find', 'Replace', '-', 'SelectAll', '-', 'Scayt' ] }, + + { name: 'basicstyles', items: [ 'Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'CopyFormatting', 'RemoveFormat' ] }, + '/', + { name: 'insert', items: [ 'SpecialChar'] }, + { name: 'styles', items: [ 'Font' ] }, + { name: 'colors', items: [ 'TextColor', 'BGColor' ] } + ]; + var ckeditor_reduce = $('.ckeditor_reduce') + ckeditor_reduce.each(function(i,v){ + CKEDITOR.replace(v,config); + }) +}); \ No newline at end of file diff --git a/app/controllers/admin/register_api_controller.rb b/app/controllers/admin/register_api_controller.rb index 818c2ec..4ae52df 100644 --- a/app/controllers/admin/register_api_controller.rb +++ b/app/controllers/admin/register_api_controller.rb @@ -37,11 +37,9 @@ class Admin::RegisterApiController < ApplicationController end def send_store_token site = RegisteredSite.where(:site_domain => params[:site_domain]).first - if !site.nil? - render :json => {'store_token'=>site.uid} - else - render :json => {'store_token'=>nil} - end + uid = site.uid if !site.nil? + + render :json => {'store_token'=>uid,} end def send_confirmation_email(email, confirmation_token, site_token) url = "#{request.protocol}#{request.host_with_port}/register/confirm_email?confirmation=#{confirmation_token}&site=#{site_token}" @@ -64,7 +62,22 @@ class Admin::RegisterApiController < ApplicationController if !site.nil? site.site_domain = params[:site_domain] site.save - render :json => {"success" => true}.to_json + watch_list_save_flag = (params['user']!= 'rulingcom' && params['user'].to_s != '') + user_name = params['user'] + puts ['user_name',user_name] + site_anncs = SiteAnnc + .where(visible: true) + .select{|v| v.send_all || v.recieve_sites.include?(site)}.collect do |v| + if watch_list_save_flag + watch_list = v.watch_list + if watch_list.select{|v| v[0]==site.id && v[1]==user_name}.count == 0 + watch_list << [site.id,user_name] + end + v.update_attributes(watch_list: watch_list) + end + {title: v.title,content: v.content,see_more_link: v.see_more_link} + end + render :json => {"success" => true,'site_anncs'=>site_anncs}.to_json else render :json => {"success" => false}.to_json end diff --git a/app/controllers/admin/registered_sites_controller.rb b/app/controllers/admin/registered_sites_controller.rb index 73a6b9b..dabf8b0 100644 --- a/app/controllers/admin/registered_sites_controller.rb +++ b/app/controllers/admin/registered_sites_controller.rb @@ -7,15 +7,458 @@ class Admin::RegisteredSitesController < OrbitAdminController .with_tags(filters("tag")).desc(:created_at) @table_fields = table_fields @tags = @module_app.tags - @categories = @module_app.categories.enabled - @filter_fields = filter_fields_without_status(@categories, @tags) - @registeredsites = search_data(@registeredsites,[:title,:site_domain]).page(params[:page]).per(10) - - if request.xhr? - render :partial => "index" - end + @categories = @module_app.categories.enabled + @filter_fields = filter_fields_without_status(@categories, @tags) + @registeredsites = search_data(@registeredsites,[:title,:site_domain]).page(params[:page]).per(10) + + if request.xhr? + render :partial => "index" + end + end + def get_watch_list + site_annc = SiteAnnc.find(params['data']) + lists = site_annc.watch_list.group_by{|v| v[0]}.map{|k,v| [k,v.collect{|v1| v1[1]}]} + res = lists.collect do |v| + site = RegisteredSite.find(v[0]) rescue nil + par1 = site.nil? ? ['not found',''] : [site.show_name,site.site_domain] + par2 = v[1].join(', ') + [par1,par2] + end + render :json => res + end + def show + end + def announcement + @site_anncs = SiteAnnc.all.desc(:craete_at).page(params[:page]).per(10) + end + def edit_annc + @site_annc = SiteAnnc.find(params['site_annc_id']) rescue SiteAnnc.new + end + def update_annc + site_annc = SiteAnnc.find(params['site_annc_id']) rescue SiteAnnc.create + site_annc.update_attributes(title: params['title'], + see_more_link: params['see_more_link'], + content: params['content'], + recieve_sites: params['recieve_sites'], + visible: params['visible']=='true', + send_all: params['send_all']=='true') + redirect_to '/admin/registered_sites/announcement' + end + def get_select_box + tags = @module_app.tags.map{|v| v} + categories = @module_app.categories.enabled.map{|v| v} + sites = RegisteredSite.all.collect{|v1| [v1,v1.tags,v1.category]} + @sites_order_by_tags = tags.map{|v| {v=>sites.select{|v1| v1[1].include? v}.map{|v2| v2[0]}}} + @sites_order_by_tags << {'no_tag'=>sites.select{|v1| v1[1]== []}.map{|v2| v2[0]}} + @sites_order_by_cats = categories.map{|v| {v=>sites.select{|v1| v1[2]== v}.map{|v2| v2[0]}}} + @sites_order_by_cats << {'no_category'=>sites.select{|v1| v1[2].nil?}.map{|v2| v2[0]}} + end + def delete_annc + site_annc = SiteAnnc.find(params['site_annc_id']) rescue nil + if !site_annc.nil? + site_annc.destroy + end + redirect_to '/admin/registered_sites/announcement' + end + def update_status(site) + tp1 = site.site_statuses.first + tp1 = site.site_statuses.create if tp1.nil? + if site.site_domain.to_s.blank? + urls = nil + else + urls = site.self_test + end + if urls.nil? + tp1.status = 'domain is blank' + elsif urls == [nil,nil] + tp1.status = 'domain not found' + tp1.href = 'http://'+site.site_domain + elsif !urls[0].to_s.empty? || !urls[1].to_s.empty? + tp1.status = 'ok' + if !urls[0].empty? + root_url = urls[0] + else + root_url = urls[1] + end + tp1.href = root_url + uri = URI(root_url) + Net::HTTP.start(uri.host, uri.port,:use_ssl => uri.scheme == 'https',open_timeout: 30,read_timeout: 30) do |http| + r3 = login_reomote(http,root_url) + if r3.code != '200' + tp1.can_login = true + else + tp1.can_login = false + end + r4 = get_website(uri,http,r3) + uri2 = URI ("#{root_url}/admin/playground") + r5 = get_website(uri2,http,r4) + if r5.code.to_s == '200' + uri3 = URI ("#{root_url}/admin/playground/command") + doc = Nokogiri::HTML(r5.body) rescue nil + csrf_data = doc.search("meta[name='csrf-token']")[0].attributes['content'].value rescue nil + r6 = post_website(uri3,http,r5,{'command' => "ip addr | grep \"inet \" | grep -v 127.0.0.1 | awk '{print $2}'| xargs | awk '{print $1}'"},csrf_data) + res = JSON.parse(r6.body) rescue '' + if (res == {"success"=>true} || r6.code.to_s != '200') + uri4 = URI ("#{root_url}/admin/playground/console_output") + count = 0 + while count < 5 + r7 = get_website(uri4,http,r6,{'count' => '0'},csrf_data) + if (r7.code.to_s == '200' rescue false) + r6 = r7 + response = JSON.parse(r6.body)['response'] rescue nil + end + if Array(response).count != 0 + real_ip = Array(response)[0].to_s.split(/\//)[0].scan(/\d+.\d+.\d+.\d+/)[0] + tp1.status = tp1.status + " ,ip: #{real_ip}" + if !real_ip.to_s.empty? + site.real_ip = real_ip + site.save + end + break + end + count = count + 1 + sleep 1 + end + end + end + end + else + tp1.href = 'http://'+site.site_domain + tp1.status = 'bad gateway' + end + tp1.save! + end + def get_check_log + tp = CheckSiteTemp.first + tp_all_ids = tp.all_ids + count = tp_all_ids.index(params['data']) + count = count.nil? ? 0 : (count+1) + all_ids = tp_all_ids[count..-1] + item = RegisteredSite.find(all_ids).collect do |v| + site_status = v.site_statuses.first + site_name = v.title.nil? ? v.site_domain : v.title + { id: v.id.to_s, + can_login: site_status.can_login, + href: site_status.href, + site_name: site_name, + status: site_status.status} + end + render :json =>{status: tp.status,item:item,now_id:params['data']}.to_json + end + def check_site + site = RegisteredSite.find(params['item_id']) + update_status(site) + render :text => "ip: #{site.real_ip}" + end + def check_all_site + tp = CheckSiteTemp.first + tp = CheckSiteTemp.create() if tp.nil? + tp.all_ids = [] + tp.status = 'running' + tp.save + Thread.new do + count = RegisteredSite.where(:is_hidden.ne=>true).count + batch_l = (count/50.0).ceil + (1..batch_l).each do |v| + sites = RegisteredSite.where(:is_hidden.ne=>true).sort_by{|v| v.id}[(v-1)*50..(v*50)] + sites.each do |site| + begin + update_status(site) + system('sleep 0.5') + tp.all_ids << site.id.to_s + tp.save + rescue => e + puts e.inspect + end + end + end + tp.status = 'finish' + tp.save + end + render :text => '' + end + def request_website(type,uri,http,pre_req,data,csrf_data) + req = (type =='get' ? Net::HTTP::Get.new(uri) : Net::HTTP::Post.new(uri)) + req.set_form_data(data) + req['Cookie'] = pre_req['set-cookie'].to_s.gsub(' path=/; HttpOnly','') rescue '' + req['X-CSRF-Token'] = csrf_data + req['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' + http.request req + end + def get_website(uri,http,pre_req=nil,data={},csrf_data=nil) + request_website('get',uri,http,pre_req,data,csrf_data) + end + def post_website(uri,http,pre_req=nil,data={},csrf_data=nil) + request_website('post',uri,http,pre_req,data,csrf_data) + end + def login_reomote(http,root_url) + uri = URI(root_url) + r1 = get_website(uri,http) + r2 = get_website(uri,http,r1) + doc = Nokogiri::HTML(r2.body) + checkvalue = doc.css('.login-body').css('input[name=authenticity_token]')[0].attr('value') rescue nil + if checkvalue.nil? + puts [root_url,r2,doc.css('.login-body').css('input[name=authenticity_token]')] + end + uri1 = URI("#{root_url}/sessions") + data = {'authenticity_token' => checkvalue,'user_name' => 'rulingcom', 'password' =>'orbit_is_great_1','referer_url'=>root_url} + r3 = post_website(uri1,http,r2,data) + end + def bundle_update_remote(site) + root_url,log = site.fetch_web_url_and_log + tp = BundleUpdateTemp.first + tp.now_id = site.id.to_s + tp.save + timeout_flag = false + sel_flag = false + not_login_flag = false + not_accept_flag = false + timeout_count = 0 + if !root_url.nil? + uri = URI(root_url) + puts 'starting' + begin + Net::HTTP.start(uri.host, uri.port,:use_ssl => uri.scheme == 'https',open_timeout: 30,read_timeout: 30) do |http| + r3 = login_reomote(http,root_url) + r4 = get_website(uri,http,r3) + uri2 = URI ("#{root_url}/admin/playground") + r5 = get_website(uri2,http,r4) + if r5.code.to_s != '200' + not_login_flag = true + end + puts '1' + if !not_login_flag + not_accept_flag = true + puts '2' + uri3 = URI ("#{root_url}/admin/playground/command") + doc = Nokogiri::HTML(r5.body) rescue nil + csrf_data = doc.search("meta[name='csrf-token']")[0].attributes['content'].value rescue nil + r6 = post_website(uri3,http,r5,{'command' => 'bundle'},csrf_data) + count = 0 + flag = false + res = JSON.parse(r6.body) rescue '' + puts ['3',res.inspect] + if (res == {"success"=>true} || r6.code.to_s != '200') + not_accept_flag = false + last_length = 0 + while 1 + uri4 = URI ("#{root_url}/admin/playground/console_output") + r7 = get_website(uri4,http,r6,{'count' => '0'},csrf_data) + message = log.message + timeout_count = timeout_count + 1 + if timeout_count > 30 + timeout_flag = true + end + if (r7.code.to_s == '200' rescue false) + r6 = r7 + response = JSON.parse(r6.body)['response'] rescue nil + last_message = nil + else + response = '' + message << "code:#{r7.code.to_s}" + last_message = "code:#{r7.code.to_s}" + if flag + count = count + 1 + end + end + array_res = Array(response).clone + res = array_res[-1] + if !res.blank? + flag = true + end + if array_res.length > last_length + message << array_res[last_length..-1] + elsif array_res.length < last_length + message << array_res + end + message = message.flatten 1 + if res.blank? && flag + message << res.inspect + count = count + 1 + elsif res.blank? + count = count + 0.3 + else + count = 0 + last_message = last_message || res + if last_message != log.last_message + timeout_count = 0 + end + end + last_length = array_res.length + log.message = message + log.last_message = last_message + log.save! + if message.length >= 5 + message[-5..-1].each do |v| + if v.to_s.downcase.scan(/bundle.*update|run `bundle clean --force`|bundle.*complete!/).length>0 || v.to_s=='finish' + sel_flag = true + end + end + end + if count>30 + timeout_flag = true + end + if sel_flag || timeout_flag + break + end + system('sleep 1') + end + else + log.status = 'failed' + log.message << r6.body rescue 'no response' + log.last_message = r6.body rescue 'no response' + log.save + end + end + #r6 = post_website(uri3,http,r6,{'command' => 'restart_server'},csrf_data) + #if (JSON.parse(r6.body) == {"success"=>true} rescue false) + # log.last_message += "
restart success" + #else + # log.last_message += "
restart failed" + #end + #log.message[-1] = log.last_message + #log.save! + end + rescue => e + not_accept_flag = true + puts e + end + puts 'out' + if not_accept_flag || not_login_flag + log.status = 'failed' + log.last_message = "can't login to admin" + elsif !timeout_flag + if sel_flag || site.is_alive? + puts 'finish2' + log.status = 'finish' + else + log.status = 'failed' + end + else + puts 'timeout_flag' + system('sleep 10') + puts 'sleep finish' + if site.is_alive? + puts 'finish' + log.status = 'finish' + else + puts 'failed' + log.status = 'failed' + #update_flags = UpdateFlags.first + #update_flags.bundle_update_flag = false + #update_flags.save! + end + end + log.last_time = Time.now + log.save! + end + end + def stop_bundle_update + update_flags = UpdateFlags.first + update_flags.bundle_update_flag = false + update_flags.save + render :text => '' + end + def get_detail + site = RegisteredSite.find(params['item_id']) rescue nil + message = '' + if !site.nil? + message = site.bundle_update_logs.first.message.join('
') rescue '' + end + render :text => message + end + def destroy_bundle_temp + render :text => (BundleUpdateTemp.first.destroy.inspect rescue '') + end + def bundle_update + update_flags = UpdateFlags.first.nil? ? UpdateFlags.new() : UpdateFlags.first + update_flags.bundle_update_flag = true + update_flags.save + if BundleUpdateTemp.first.nil? + if params['item_ids'][0] == 'all' + item_ids = RegisteredSite.all.collect(&:id).map{|v| v.to_s}.reverse + else + item_ids = params['item_ids'] + end + BundleUpdateTemp.create(all_ids: item_ids,now_id: nil) + Thread.new do + clone_item_ids = item_ids.clone + clone_item_ids.each do |site_id| + if !UpdateFlags.first.bundle_update_flag + tp = BundleUpdateTemp.first + tp.now_id = 'terminated' + tp.save + Thread.current.terminate! + end + site = RegisteredSite.find(site_id) rescue nil + if !site.nil? && (site.site_statuses.first.can_login rescue true) + bundle_update_remote(site) + elsif !site.nil? + if site.bundle_update_logs.first.nil? + log = site.bundle_update_logs.create() + else + log = site.bundle_update_logs.first + end + log.status = 'failed' + log.last_message = "can't login" + log.save + end + end + tp = BundleUpdateTemp.first + tp.now_id = 'finish' + tp.save + end + render :json => {status: 'success'} + elsif BundleUpdateTemp.first.all_ids == params['item_ids'] + render :json => {status: 'success'} + else + render :json => {status: 'failed'} + end + end + def get_message + tp = BundleUpdateTemp.first.now_id + if tp.nil? + render :json => {status: 'initializing'} + elsif tp=='terminated' + BundleUpdateTemp.first.destroy + render :json => {status: tp} + else + site_id = (tp=='finish' ? BundleUpdateTemp.first.all_ids.last : tp) + if tp=='finish' + BundleUpdateTemp.first.destroy + end + site = RegisteredSite.find(site_id) rescue nil + if !site.nil? + status = tp=='finish' ? 'finish' : 'running' + log = site.bundle_update_logs.first + render :json => {status: status, + item: {item_id: site_id, + status: log.status, + last_time: log.last_time, + last_message: log.last_message}} + else + render :json => {status: 'not found', + item: {item_id: site_id, + status: 'not found', + last_time: 'not found', + last_message: 'not found'}} + end + end + end + def bundle_update_remote_show + @registeredsites = RegisteredSite.all.order_by(sort) + .with_categories(filters("category")) + .with_tags(filters("tag")).desc(:created_at) + @table_fields = table_fields_for_bundle_update + @tags = @module_app.tags + @categories = @module_app.categories.enabled + @filter_fields = filter_fields_without_status(@categories, @tags) + @registeredsites = search_data(@registeredsites,[:title,:site_domain]).page(params[:page]).per(RegisteredSite.all.count)#.per(10) + + if request.xhr? + render :partial => "bundle_update_remote_show" + end end - def edit @registered_site = RegisteredSite.find(params[:id]) if can_edit_or_delete?(@registered_site) @@ -75,7 +518,9 @@ class Admin::RegisteredSitesController < OrbitAdminController def table_fields [:domain, :admin_email, :status, :category, :tags, :permission] end - + def table_fields_for_bundle_update + [:domain, 'registered_sites.bundle_update', 'registered_sites.bundle_update_status', :category, 'registered_sites.last_message'] + end def registered_site_params params.require(:registered_site).permit! end diff --git a/app/controllers/registered_sites_controller.rb b/app/controllers/registered_sites_controller.rb index b75553a..0a83879 100644 --- a/app/controllers/registered_sites_controller.rb +++ b/app/controllers/registered_sites_controller.rb @@ -8,4 +8,14 @@ class RegisteredSitesController < ApplicationController } } end + def git_auth + user_ip = params['user_ip'] + all_ips = RegisteredSite.all.collect{|v| [v.ip,v.real_ip]}.flatten.compact + puts user_ip + if all_ips.include?(user_ip) || user_ip == '118.163.60.152' || user_ip == '163.19.249.14' || user_ip == '203.72.2.177' + render :text=>'hello',:status=> 200 + else + render :text=>'forbidden',:status=> 500 + end + end end \ No newline at end of file diff --git a/app/models/bundle_update_log.rb b/app/models/bundle_update_log.rb new file mode 100644 index 0000000..4c33828 --- /dev/null +++ b/app/models/bundle_update_log.rb @@ -0,0 +1,13 @@ +class BundleUpdateLog + include Mongoid::Document + include Mongoid::Timestamps + + field :last_time, default: Time.now + field :status, type: String, default: 'running' + field :last_message, type: String, default: '' + field :message, type: Array, default: [] + belongs_to :registered_site + def last_time + self['last_time'].in_time_zone.strftime('%Y/%m/%d %H:%M') + end +end \ No newline at end of file diff --git a/app/models/bundle_update_temp.rb b/app/models/bundle_update_temp.rb new file mode 100644 index 0000000..c7aea85 --- /dev/null +++ b/app/models/bundle_update_temp.rb @@ -0,0 +1,8 @@ +class BundleUpdateTemp + include Mongoid::Document + include Mongoid::Timestamps + + field :all_ids + field :now_id + +end \ No newline at end of file diff --git a/app/models/check_site_temp.rb b/app/models/check_site_temp.rb new file mode 100644 index 0000000..2fa204a --- /dev/null +++ b/app/models/check_site_temp.rb @@ -0,0 +1,7 @@ +class CheckSiteTemp + include Mongoid::Document + include Mongoid::Timestamps + + field :all_ids + field :status +end \ No newline at end of file diff --git a/app/models/registered_site.rb b/app/models/registered_site.rb index c90f3d4..fef862c 100644 --- a/app/models/registered_site.rb +++ b/app/models/registered_site.rb @@ -4,7 +4,8 @@ class RegisteredSite include OrbitTag::Taggable include OrbitCategory::Categorizable include Slug - + field :ip + field :real_ip field :site_domain field :title, as: :slug_title, localize: true field :description, localize: true @@ -12,18 +13,31 @@ class RegisteredSite field :admin_email field :site_confirmed, type: Boolean, :default => false field :confirmation_token - + field :is_hidden,type: Boolean,:default => false + has_many :bundle_update_logs has_many :site_logs has_many :installed_modules has_many :tickets - + has_many :site_statuses + + before_save :generate_ip + after_create do + self.bundle_update_logs.create + end index({ confirmation_token: 1}, { unique: true }) scope :active, ->{where(:access_granted => true,:site_confirmed => true)} - + def generate_ip + self[:ip] = %x[dig +short '#{self[:site_domain]}'].split("\n") + if self[:ip].count==0 + self[:ip] = self[:site_domain] + end + end def site_token self.uid end - + def show_name + self.title.nil? ? self.site_domain : self.title + end def generate_confirmation_token self.confirmation_token = SecureRandom.hex(5) self.save @@ -32,4 +46,64 @@ class RegisteredSite def active? return self.access_granted && self.site_confirmed end + def is_alive? + urls = self.self_test + if !urls[0].to_s.empty? || !urls[1].to_s.empty? + true + else + false + end + end + def self_test + domain = self.site_domain + types = ['http','https'] + urls = types.collect do |type| + root_url = "#{type}://#{domain}" + uri0 = URI(root_url) + r = Net::HTTP.start(uri0.host, uri0.port,:use_ssl => uri0.scheme == 'https',open_timeout: 20,read_timeout: 20) do |http| + req = Net::HTTP::Get.new(uri0) + req['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' + http.request req + end rescue nil + code = r.code.to_s rescue nil + if code == '200' + root_url + elsif code.nil? + nil + else + '' + end + end + end + def fetch_web_url_and_log + if self.bundle_update_logs.first.nil? + log = self.bundle_update_logs.create() + else + log = self.bundle_update_logs.first + end + urls = self.self_test + log.last_time = Time.now + if urls == [nil,nil] + log.message = ['domain not found'] + log.last_message = 'domain not found' + log.status = 'failed' + root_url = nil + elsif !urls[0].to_s.empty? || !urls[1].to_s.empty? + if !urls[0].empty? + root_url = urls[0] + else + root_url = urls[1] + end + log.message = ["open the web by #{root_url}"] + log.status = 'running' + log.last_message = "open the web by #{root_url}" + else + log.message = ['Maybe the web need to restart'] + log.last_message = 'Maybe the web need to restart' + log.status = 'failed' + root_url = nil + end + log.save! + [root_url,log] + end end \ No newline at end of file diff --git a/app/models/site_annc.rb b/app/models/site_annc.rb new file mode 100644 index 0000000..cfc5b70 --- /dev/null +++ b/app/models/site_annc.rb @@ -0,0 +1,17 @@ +class SiteAnnc + include Mongoid::Document + include Mongoid::Timestamps + field :title,type: Hash, default: {en:'',zh_tw:''} + field :visible, type: Boolean, default: true + field :content,type: Hash, default: {en:'',zh_tw:''} + field :see_more_link + field :recieve_sites,type: Array, default: [] + field :watch_list,type: Array, default: [] + field :send_all,type: Boolean,default: false + def recieve_sites + RegisteredSite.find(self[:recieve_sites]) rescue [] + end + def recieve_sites=(value) + self[:recieve_sites] = Array(value).uniq + end +end \ No newline at end of file diff --git a/app/models/site_status.rb b/app/models/site_status.rb new file mode 100644 index 0000000..9d3e60f --- /dev/null +++ b/app/models/site_status.rb @@ -0,0 +1,8 @@ +class SiteStatus + include Mongoid::Document + include Mongoid::Timestamps + field :status + field :can_login,default: false + field :href, type: String ,default: '' + belongs_to :registered_site +end \ No newline at end of file diff --git a/app/models/update_flags.rb b/app/models/update_flags.rb new file mode 100644 index 0000000..dc8698e --- /dev/null +++ b/app/models/update_flags.rb @@ -0,0 +1,6 @@ +class UpdateFlags + include Mongoid::Document + + field :bundle_update_flag, type: Boolean, default: true + +end \ No newline at end of file diff --git a/app/views/admin/registered_sites/_bundle_update_remote_show.html.erb b/app/views/admin/registered_sites/_bundle_update_remote_show.html.erb new file mode 100644 index 0000000..eb24188 --- /dev/null +++ b/app/views/admin/registered_sites/_bundle_update_remote_show.html.erb @@ -0,0 +1,79 @@ + + + + + + <% @table_fields.zip(['20%','10%','15%','15%']).each do |f| %> + + <% end %> + + + + <% @registeredsites.each_with_index do |site,index1| %> + <% status = site.is_hidden == true ? 'is_hidden' : site.bundle_update_logs.first.status + if status == 'failed' + status = 'error' + elsif status == 'finish' + status = 'success' + end + %> + + + + + + + + + <% end %> + +
+ + <%= t(f[0]) %>
+ <% if site.is_hidden != true %> + + <% end %> + + <%= site.title.nil? ? site.site_domain : site.title %> +
+ +
+
+ + + + + <% if !site.site_confirmed %> + <%= t("registered_sites.site_inactive") %>
+ <%= t("registered_sites.email_not_confirmed") %> + <% elsif !site.access_granted %> + <%= t("registered_sites.site_inactive") %>
+ <%= t("registered_sites.site_permission_revoked") %> + <% else %> + <%= t("registered_sites.site_active") %>
+ <% end %> + <% ['last_time','status'].each do |log_t| %> + + <%= site.bundle_update_logs.first.send(log_t) rescue '' %> + +
+ <% end %> +
<%= site.category.nil? ? "Category not assigned." : "#{site.category.title}".html_safe %> + <%=site.bundle_update_logs.first.last_message.html_safe rescue '' %> +
+ + <%= + content_tag :div, class: "bottomnav clearfix" do + content_tag :div, paginate(@registeredsites), class: "pagination pagination-centered" + end +%> \ No newline at end of file diff --git a/app/views/admin/registered_sites/_form.html.erb b/app/views/admin/registered_sites/_form.html.erb index d0b6219..cec2819 100644 --- a/app/views/admin/registered_sites/_form.html.erb +++ b/app/views/admin/registered_sites/_form.html.erb @@ -45,13 +45,18 @@ -
+
<%= f.text_field :admin_email %>
- +
+ +
+ <%= f.check_box :is_hidden,{},'true','false' %> +
+
diff --git a/app/views/admin/registered_sites/_site_selection_box.html.erb b/app/views/admin/registered_sites/_site_selection_box.html.erb new file mode 100644 index 0000000..96c14c8 --- /dev/null +++ b/app/views/admin/registered_sites/_site_selection_box.html.erb @@ -0,0 +1,99 @@ +<% content_for :page_specific_javascript do -%> + <%= javascript_include_tag "select2/select2.min" %> + <%= javascript_include_tag "lib/jquery.nanoscroller" %> +<% end -%> +<% content_for :page_specific_css do -%> + <%= stylesheet_link_tag "member_select" %> +<% end %> + +
+ <% recieve_sites.each do |recieve_site| %> + + x + <%= recieve_site.title.nil? ? recieve_site.site_domain : recieve_site.title %> + <%= hidden_field_tag field, recieve_site.id %> + + <% end %> +
+
delete all +<%= t(:add) %> + \ No newline at end of file diff --git a/app/views/admin/registered_sites/announcement.erb b/app/views/admin/registered_sites/announcement.erb new file mode 100644 index 0000000..0d0dd3b --- /dev/null +++ b/app/views/admin/registered_sites/announcement.erb @@ -0,0 +1,100 @@ + + + +
+
+ +
+ + + + + + + + + + + <% @site_anncs.each do |site_annc| %> + + + + + + <% end %> + +
+ <%= t('site_annc.title') %>(中文/英文) + + <%= t('site_annc.watch_list_count') %> + + <%= t('site_annc.see_more_link') %> +
+ <%= site_annc[:title][:zh_tw].to_s.html_safe %> + / + <%= site_annc[:title][:en].to_s.html_safe %> + + + + <%= site_annc.watch_list.count %> + + + <%= link_to site_annc.see_more_link.to_s,site_annc.see_more_link.to_s %> +
+ <%= + content_tag :div, class: "bottomnav clearfix" do + content_tag :div, paginate(@site_anncs), class: "pagination pagination-centered" + end + %> +
\ No newline at end of file diff --git a/app/views/admin/registered_sites/bundle_update_remote_show.erb b/app/views/admin/registered_sites/bundle_update_remote_show.erb new file mode 100644 index 0000000..e96cde1 --- /dev/null +++ b/app/views/admin/registered_sites/bundle_update_remote_show.erb @@ -0,0 +1,343 @@ + + +<% if !BundleUpdateTemp.first.nil? %> + <% tp = BundleUpdateTemp.first %> + 全部: + <%= tp.all_ids.count %> + 目前: + <% now_index = tp.all_ids.index(tp.now_id) %> + <% if tp.now_id=='finish' + now_index = tp.all_ids.count - 1 + end + %> + <%= now_index.nil? ? "unprocess" : now_index+1 %> +
+ 失敗(僅確認可登入): + <%= now_index.nil? ? 0 : RegisteredSite.where(:id.in => Array(tp.all_ids[0..now_index])).select{|v| (v.site_statuses.first.can_login rescue true) && v.bundle_update_logs.first.status=='failed'}.collect{|v| "#{v.show_name} :#{v.bundle_update_logs.first.last_message}"}.join('
').html_safe %> +<% end %> +<%= render_filter @filter_fields, "index_table" %> + + + + select all behind + + + + + +show_all + +ok only + +fail only +
+
+
+ + +
+ <%= render 'bundle_update_remote_show'%> +
\ No newline at end of file diff --git a/app/views/admin/registered_sites/edit_annc.erb b/app/views/admin/registered_sites/edit_annc.erb new file mode 100644 index 0000000..e77dc1d --- /dev/null +++ b/app/views/admin/registered_sites/edit_annc.erb @@ -0,0 +1,76 @@ +<% content_for :page_specific_css do %> + <%= stylesheet_link_tag "lib/main-forms" %> + <%= stylesheet_link_tag "lib/main-list" %> + <%= stylesheet_link_tag "member_select" %> +<% end %> +<% content_for :page_specific_javascript do %> + <%= javascript_include_tag "lib/module-area" %> + <%= javascript_include_tag "registered_site_progress" %> +<% end %> + +
+ <%= hidden_field_tag :authenticity_token, form_authenticity_token %> + +
+
+ +
+ <%= render partial: 'admin/registered_sites/site_selection_box', locals: {field: 'recieve_sites[]', recieve_sites:(@site_annc.recieve_sites || [])} %> +
+
+
+ + <%= check_box_tag 'visible', 'true', @site_annc.visible %> +
+
+ + <%= check_box_tag 'send_all', 'true', @site_annc.send_all %> +
+ + + + +
+ <% I18n.available_locales.each_with_index do |locale, i| %> +
"> + +
+ +
+ <%= text_area_tag "title[#{locale}]",(@site_annc.title[locale] rescue nil), class: "ckeditor_reduce input-block-level", placeholder: t(:title) %> +
+
+
+ +
+ <%= text_area_tag "content[#{locale}]",(@site_annc.content[locale] rescue nil), class: "ckeditor input-block-level", placeholder: t('site_annc.content') %> +
+
+
+ <% end %> + +
+ <%= url_field_tag "see_more_link",(@site_annc.see_more_link rescue nil),class: "input-block-level", placeholder: t('site_annc.see_more_link') %> +
+
+
+ +
+ <%= submit_tag t('submit'), class: 'btn btn-primary' %> + + <%= link_to t('cancel'), '/admin/registered_sites/announcement', :class=>"btn" %> +
+
\ No newline at end of file diff --git a/app/views/admin/registered_sites/get_select_box.html.erb b/app/views/admin/registered_sites/get_select_box.html.erb new file mode 100644 index 0000000..acec738 --- /dev/null +++ b/app/views/admin/registered_sites/get_select_box.html.erb @@ -0,0 +1,87 @@ +<% tags = @sites_order_by_tags + .collect{|v| v.keys[0]} + .map{|tag| tag.class == String ? [tag.to_s,'無標籤'] : [tag.id.to_s,tag.name] } + cats = @sites_order_by_cats + .collect{|v| v.keys[0]} + .map{|cat| cat.class == String ? [cat.to_s,'無類別'] : [cat.id.to_s,cat.title] } + @sites_by_cats_and_tags = @sites_order_by_cats + @sites_order_by_tags +%> + \ No newline at end of file diff --git a/config/locales/en.yml b/config/locales/en.yml index a486c93..65b2f5a 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -4,13 +4,33 @@ en: status: Status permission: Access resend_email: Resend email + site_annc: + watch_list_count: Watch count + recieve_sites: Recieve Sites + new: New announcement + title: Title + content: Content + visible: Visible + see_more_link: See more link registered_sites: - customization_log: Customization Log - registered_sites: Registered Sites - all: All - email_not_confirmed: Email not confirmed. - site_permission_revoked: Site permission revoked. - site_active: Active - site_inactive: Inactive - progress: Progress + announcement: All site announcement + destroy_bundle_temp: Destroy bundle temp + stop_bundle_update: Stop Bundle update + update_select: Update selected + get_detail: Detail + update: Update + last_time: Last Update Time + status: Status + last_message: Last Message + bundle_update_status: bundle update status + bundle_update: bundle update + bundle_update_remote_show: Bundle update remote + customization_log: Customization Log + registered_sites: Registered Sites + all: All + email_not_confirmed: Email not confirmed. + site_permission_revoked: Site permission revoked. + site_active: Active + site_inactive: Inactive + progress: Progress diff --git a/config/locales/zh_tw.yml b/config/locales/zh_tw.yml index 358c1cc..46e5903 100644 --- a/config/locales/zh_tw.yml +++ b/config/locales/zh_tw.yml @@ -4,7 +4,27 @@ zh_tw: status: Status permission: Access resend_email: Resend email + site_annc: + watch_list_count: 查看人數 + recieve_sites: 接收網站 + new: 新增公告 + title: 標題 + content: 內容 + visible: 顯示 + see_more_link: 更多連結 registered_sites: + announcement: 全站公告 + destroy_bundle_temp: 刪除程序暫存 + stop_bundle_update: 中止套件更新 + update_select: 更新所選 + get_detail: 詳細資訊 + update: 更新 + last_time: 最後更新時間 + status: 狀態 + last_message: 最新訊息 + bundle_update_status: 套件更新狀態 + bundle_update: 外掛更新 + bundle_update_remote_show: 遠端網站外掛更新 customization_log: Customization Log registered_sites: Registered Sites all: All diff --git a/config/routes.rb b/config/routes.rb index 8358216..8bb031c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,13 +3,32 @@ Rails.application.routes.draw do locales = Site.first.in_use_locales rescue I18n.available_locales scope "(:locale)", locale: Regexp.new(locales.join("|")) do - post "/xhr/site/re_register_url", to: 'admin/register_api#re_register_url' - namespace :admin do + post "/xhr/site/re_register_url", to: 'admin/register_api#re_register_url' + get 'git-auth' => 'registered_sites#git_auth' + post 'git-auth' => 'registered_sites#git_auth' + namespace :admin do get "/registered_site/change_access/:uid" => "registered_sites#change_access_status" - resources :registered_sites do + resources :registered_sites,:except => ['show'] do member do get "progress" end + end + resource :registered_sites,:only => [] do + post 'get_watch_list' => 'registered_sites#get_watch_list' + get 'get_select_box' => 'registered_sites#get_select_box' + get 'announcement' => 'registered_sites#announcement' + get ':site_annc_id/edit_annc' => 'registered_sites#edit_annc' + get ':site_annc_id/delete_annc' => 'registered_sites#delete_annc' + post ':site_annc_id/update_annc' => 'registered_sites#update_annc' + post 'get_check_log' => 'registered_sites#get_check_log' + post 'check_all_site' => 'registered_sites#check_all_site' + post 'destroy_bundle_temp' => 'registered_sites#destroy_bundle_temp' + get 'bundle_update_remote_show' => 'registered_sites#bundle_update_remote_show' + post "bundle_update" => 'registered_sites#bundle_update' + post 'stop_bundle_update' => 'registered_sites#stop_bundle_update' + post 'get_message' => 'registered_sites#get_message' + post 'get_detail' => 'registered_sites#get_detail' + post 'check_site' => 'registered_sites#check_site' end resources :customization_logs do member do diff --git a/lib/registered_sites/engine.rb b/lib/registered_sites/engine.rb index 13cbb06..6c74881 100644 --- a/lib/registered_sites/engine.rb +++ b/lib/registered_sites/engine.rb @@ -9,7 +9,7 @@ module RegisteredSites authorizable taggable "RegisteredSite" categorizable - + set_keyword_contstraints ['/git-auth'] side_bar do head_label_i18n 'registered_sites.registered_sites', icon_class: "icons-earth" available_for "users" @@ -35,6 +35,18 @@ module RegisteredSites :active_for_action=>{'admin/registered_sites'=>'categories'}, :active_for_category => 'RegisteredSite', :available_for => 'managers' + + context_link 'registered_sites.bundle_update_remote_show', + :link_path=>"bundle_update_remote_show_admin_registered_sites_path", + :priority=>4, + :active_for_action=>{'admin/registered_sites'=>'bundle_update_remote_show'}, + :available_for => 'managers' + + context_link 'registered_sites.announcement', + :link_path=>"announcement_admin_registered_sites_path", + :priority=>5, + :active_for_action=>{'admin/registered_sites'=>'announcement'}, + :available_for => 'managers' end end end