From 5444f24c0c85af8c38b6730d5c078bbb877ec4c3 Mon Sep 17 00:00:00 2001 From: Albert Wang Date: Tue, 31 Jul 2018 15:20:13 -0700 Subject: [PATCH] Brave Rewards Integration Closes #1092 --- .babelrc | 28 +- .gitignore | 3 + Gemfile | 3 + Gemfile.lock | 17 + app/assets/images/camera.png | Bin 0 -> 1358 bytes app/assets/images/camera@2x.png | Bin 0 -> 2976 bytes app/assets/images/camera@3x.png | Bin 0 -> 4551 bytes app/assets/images/icn-donation-jar@1x.png | Bin 0 -> 5677 bytes app/assets/images/icn-donation-jar@2x.png | Bin 0 -> 12711 bytes app/assets/images/icn-donation-jar@3x.png | Bin 0 -> 20410 bytes app/assets/images/icn-editPhoto.svg | 18 + app/assets/stylesheets/pages/home.scss | 52 ++ app/controllers/banners_controller.rb | 5 + .../publishers/site_banners_controller.rb | 56 ++ app/javascript/locale/en.js | 86 ++++ .../packs/brave_rewards_banner_display.jsx | 480 ++++++++++++++++++ app/javascript/publishers/home.js | 16 + .../json_builders/channels_json_builder.rb | 13 +- app/models/publisher.rb | 6 + app/models/site_banner.rb | 38 ++ app/views/application/_nav.html.slim | 10 +- .../_instant_donation_button.html.slim | 1 + .../_instant_donation_modal.html.slim | 24 + app/views/publishers/home.html.slim | 11 +- .../publishers/site_banners/new.html.slim | 2 + config/environments/development.rb | 3 + config/environments/production.rb | 3 + config/environments/staging.rb | 3 + config/locales/en.yml | 2 + config/routes.rb | 7 + config/secrets.yml | 1 + config/storage.yml | 14 + config/webpack/environment.js | 2 + config/webpack/loaders/typescript.js | 6 + config/webpacker.yml | 1 + package.json | 12 +- tsconfig.json | 20 + yarn.lock | 273 +++++++++- 38 files changed, 1176 insertions(+), 40 deletions(-) create mode 100644 app/assets/images/camera.png create mode 100644 app/assets/images/camera@2x.png create mode 100644 app/assets/images/camera@3x.png create mode 100644 app/assets/images/icn-donation-jar@1x.png create mode 100644 app/assets/images/icn-donation-jar@2x.png create mode 100644 app/assets/images/icn-donation-jar@3x.png create mode 100644 app/assets/images/icn-editPhoto.svg create mode 100644 app/controllers/banners_controller.rb create mode 100644 app/controllers/publishers/site_banners_controller.rb create mode 100644 app/javascript/locale/en.js create mode 100644 app/javascript/packs/brave_rewards_banner_display.jsx create mode 100644 app/models/site_banner.rb create mode 100644 app/views/publishers/_instant_donation_button.html.slim create mode 100644 app/views/publishers/_instant_donation_modal.html.slim create mode 100644 app/views/publishers/site_banners/new.html.slim create mode 100644 config/storage.yml create mode 100644 config/webpack/loaders/typescript.js create mode 100644 tsconfig.json diff --git a/.babelrc b/.babelrc index ded31c0d80..75e4c04e4a 100644 --- a/.babelrc +++ b/.babelrc @@ -1,18 +1,26 @@ { "presets": [ - ["env", { - "modules": false, - "targets": { - "browsers": "> 1%", - "uglify": true - }, - "useBuiltIns": true - }] + [ + "env", + { + "modules": false, + "targets": { + "browsers": "> 1%", + "uglify": true + }, + "useBuiltIns": true + } + ], + "react" ], - "plugins": [ "syntax-dynamic-import", "transform-object-rest-spread", - ["transform-class-properties", { "spec": true }] + [ + "transform-class-properties", + { + "spec": true + } + ] ] } diff --git a/.gitignore b/.gitignore index bcc7cb5fd3..dbb56137e9 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,9 @@ dump.rdb yarn-error.log .DS_Store +# Ignore assets stored in /storage +/storage + # Ignore Byebug command history file. .byebug_history /ssl/ diff --git a/Gemfile b/Gemfile index 25b0df6111..4559180b8e 100644 --- a/Gemfile +++ b/Gemfile @@ -19,6 +19,9 @@ gem "attr_encrypted", "~> 3.1.0" # Integration with Matomo Piwik gem 'autometal-piwik', :require => 'piwik', git: "https://github.com/matomo-org/piwik-ruby-api.git", branch: "master" +# Use AWS gem for s3 uploads +gem 'aws-sdk-s3', require: false + gem "bootstrap", "~> 4.1.1" # browser details diff --git a/Gemfile.lock b/Gemfile.lock index bae4158ab7..d1619d8b89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -78,6 +78,21 @@ GEM encryptor (~> 3.0.0) autoprefixer-rails (9.0.0) execjs + aws-eventstream (1.0.1) + aws-partitions (1.104.0) + aws-sdk-core (3.27.0) + aws-eventstream (~> 1.0) + aws-partitions (~> 1.0) + aws-sigv4 (~> 1.0) + jmespath (~> 1.0) + aws-sdk-kms (1.9.0) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sigv4 (~> 1.0) + aws-sdk-s3 (1.19.0) + aws-sdk-core (~> 3, >= 3.26.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.0) + aws-sigv4 (1.0.3) bcrypt (3.1.12) bindex (0.5.0) bootstrap (4.1.3) @@ -170,6 +185,7 @@ GEM jbuilder (2.7.0) activesupport (>= 4.2.0) multi_json (>= 1.2) + jmespath (1.4.0) json (2.1.0) jsonapi-renderer (0.2.0) jwt (1.5.6) @@ -457,6 +473,7 @@ DEPENDENCIES api-pagination attr_encrypted (~> 3.1.0) autometal-piwik! + aws-sdk-s3 bootstrap (~> 4.1.1) brakeman browser diff --git a/app/assets/images/camera.png b/app/assets/images/camera.png new file mode 100644 index 0000000000000000000000000000000000000000..746c40375b52320ae25d746a51f94fe692d2b4e0 GIT binary patch literal 1358 zcmV-U1+n^xP)Px)2uVaiRA>d=nqP<&RUF6fwT%o3!7wdNHYiiF)F`6}lGPq8#fS>_!4&MFw-r%* zao?g|dWaMsdMPX^qXGs0Kp7YrH?VrhKN;n!_=h&?Mb=DnZ=dhn^V=P#yLac_^PAke zU-;fLXU;j_`F-cioH=vmmP$^jR;w%FckplM1!*0I&pL(aBSSzd;2IysTB%t-J21Pr0nr2}nJ^Z_)e4%>ww=v;dl5_sMPj}yaZ1q ziN_8Z?okeC6kOc)E;9z?DR?8P_Q-HWTj1kN-EotZx5Ob{C*W#Ma8`dbYZKcTng|y{ zO;)lnZ*ydLawt8Mt<^4hOx{VX$Km&|kNkp6?B;E9N2;Kj+Ad_1KqewQ6W#@NybJIw zqvvJP7_6mnXAroZbRAq1^4BG4!`BsfWiWX&TC3m-unXP-)6gvHOLlw$-^cvbbYafz z-!k>G`Qc&?W^kV+A^ajdX$MH9|FC@}mAB1b+0cn;3bfIqbsIbdcS5^O6CLu;!2}wm z4Q_@JQ~+<8FzHqJ0el`#hZA5KPKD3Fci<&xP+PaF53Rxt@36>8_rrTf>oV%hfFD7_ zj?voWEl038!-)4<#H4RRJqdDy`WsX2H|K8Hpdxzqidl8Nq!FGCb@>YKHi)5N5p7>j z6l(Xm&4(MdX;g?-VTL~qfu1JSBd8_NR`D6 zy~VX8OZy?iP2FFk98JqR8d?8>(Y=Dk7f=%uX}T>Pc^bCq+#x0pT5*U18k&h|r9+rs zOX7b$4Qsk6oT())zos?AMGX;8!?u7I-McAsre)fxqSiJ&4eNdr^ycCPTb4cVCFp7R zWC+UbenZd3g}$+9cy9>mJ{|+}Vgp2DDjHfc7WUMV_+PgkW>nQ@mY+gMo8m(&Z9wBD zX`+3^L9ZsknKVSdEg_^;LO~0HPqi8(Z6AP_p%A@_ipJ2y!*wn#gNPqglt4?qqrN3& zPYP}HLBQUj4`$0-$)i`OVFi2&3jJ_#-XN*F09sq6T2PM$I>i}QbR1wV)ar$xZ@b&! zh;KcV-3_-wTLn>DTTOK}ta++C7-WtU@S_NChx#z5HLX?bJ4Sj4>Y05F>Y2R=J`4>S zkzYnbpGUlqd{Rop2*MCOXw{1j@g?vpsDW%Gs7!U1)YFLFhwjiNT}Th71Ei-8kUzjd z^#yMk)IeslG4=E>a3A$XUTLI)7Ya9Qfd)hGS^h?)ZWE6iWuV#P%J5)lqy_Ww3iCE7 z!}bw7dj30x&z5=Xm*GkXbU6ddxVyxIr{%$8MU#XsXpfBEG2BZng@(6YD9B@1BErTN z?FrDw;|HPMRN4}XJ$SGW;bg0C%Z&Z0MN23j!t~@rtB-%cc7#5erk90wk?-cwC{M%S zEOf*3IvwK#=kU=z>@f6jdIuFWa4m$LFwY;;s5a&>Ktx&=`hi~6a_V!Z literal 0 HcmV?d00001 diff --git a/app/assets/images/camera@2x.png b/app/assets/images/camera@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb0e904c4ec36ce144fe677f93c50d7c1f293f92 GIT binary patch literal 2976 zcmV;R3t#k!P)Px=T1iAfRCodHoqMbuRTaj25n54fDM+-f*p?C?^^X!GZ7_f(6@?A)n1HZn5uUTCcXp9J&42Z2X>5mJwVKZ2hP z3=ACbNYWK2#Jv>k1ZA`B5MJUcnUERqM2G}k2%o#a6i>W5;PN_kFXBr6dk5!aTGfrf zi2H7Ox*fbf(;jEv_%I>nBJx|=hiV<+*w$5Yt8pcfthlbDW|>5oH}HD&+bM;?l}C5Oj#kW7lD@rdcPr1=C$a~0I^E~ zWk+8TA7zulKJyXxMAxf+oNd6tL~X#MvV9Lr~`9o=Y6KFKN!CZu4c2o znjkupoLz(ea-yu8U46&i8RIFwh8^stvC(rOH~?0F-+YKsC*pwIVWh!@a#q> zW>~(FkDo&swx3DUaNbA5n=@&=d85+kE@>w1Y}J&&RM5Tf9`FrYF-N~lqi36z&}iD$ z$;y{z_rx03W7I#tIUun$xVf}`G`*t<^xMG}pqssJ`dQd;PX-WKFl*5!IXs>!r?jXx z(Zd?lYJmGOupBg+<2BZmSG)7vN;z-3aL1=)W zk(!?JROT=P(gsK)Ytm9*X~zs_$kxE$2ue4at@Y_>*-E2WD>f+`o9d-#7O+o4^i}1= zqa{gY?YZu)wo>8~_hF$tCLNXpLs zA@BiHxpJLnK$^wcv8me~x`O8z?ho@9@scU4T;~~xHG9O+oTCQ_T4Iv4?MbKF&p!iP ze{+ed`FKq{Z9%;I+hp-y>YbgaJ5wLg)&>(5s@a@GN+edz`j~8eBE+FuMf_-Cv(`XpPrp zpjE=CGD+i*=h^5fmL9fjLh!fQ=52ckxDPa2jk%*^QgqH*)NvyPpFjun9q?wb*LG$C zzS>Y*xz7aw&K})poNhs;7V2#L|@G zYgy8%U=dgav=TyZBQ!HT zFL(W|1AdY1K&b?V{E0y8j~bb-w(o&iH8I=Wa?UjHW$+AWWQwiPu1kYkWQmtXV2JB} z`-ts8?CXB{BQUMo%+toP;Ok%*giIXlI__@6_T+qcMV4?W1ctO8YTs$e$NqzC+xj}x zNfv4I1aNB{!*0aI-C_thMV4q;1pcWd9{ay#tA%cv7;S6e|8*cVDEmn!LAz)ao)Jiy zdx2s5l@#M6&P`q9qN7s@sS$ffu23lEk#{`3lx^(J7{* z`mwRCrYtv?*l!YSwFxMW*O@Xuu2mer@GBS&nrYf?xV?g3_#^`yG_wAe;kFBZ+>2j% zs|<(8@N#hxE z9^!1Or^Z`n|m6+8<3p+JZA1E1b3#3{tRP~IK|4n2x{ zq0lS^f^#3%&m-x3aneHElgD%4_b6~^Vc9FWXQsV?mRE>-do5*D%cHRwB{Xy2p2p}FRc*I4C{*w7zch3xD3)ic_p=7Oek+CrnpJrpf^V&a37j#_;%tzfrWM`Yn&^Nhq^a^O9 z1_!MLyVj7{2Iqg9G8e8(f#b{!nhZ_H_pox}^YA#wa2qtfAD6#KYlW}qP<9}th379C za&O|#D=K@$){9}=45yv=wHM2aqBa^A9+BbZc16b|KJql9rFB_Jn~ZY{ov6P^mOPll z{x66z+r(KDb2Y_IT&p;~iz`^^fs0;Qc{ITBHp+A_%*}{*ZGeZkxp{>JE|KNvdf~g& zgYdb)E}vCDew>%O#QGwzZ#Ib2xp{GDCk}ifkTUlIt79-$f#9ScfRx!)mBBXhE`(QP z`IbpwT}{8T9f|1 zFXDzwi{-BYcBET7z2TN~P6A&8TS3Sab9KW892|gOWQmtfVC9icECu>Om1g!Z2lcVO z1e^uxzm~)P@n9Y}4}2Hg3l4%trdUfIXxNkj93$I-QVJZ4dj`>EXO55u;n z7-uxitdoQAj4XN2Q`&i!DCVklOd=eVm@T7hes zB>8^<3-R@|N&j1$UFle>+Rj$zs*RPjxkzodbCTyeee+wDh@r=In&HyCu&(T7Kv#FG zwaWVa$3Fx8PUYRS6I%4gp>kT^2wY2lEYPUfDvJd_on3u}sy!5th`YdZ{U#`VN?G3t zoa!A;ETGG0wU%oZe(CSQStO;O+N=cbCp80osRRxrrJsr_f%{3#Kwl*A0aKpYPXn4b zmD~FaSnb}B!1mS5&?_0er&6_;MFy;P!xDJdL|VXi$H}Iwa-C-&)@*^HIV$jGQ#ci0 zGeMP=D+5}LFYS`HSu;Hgfwc!HaQRR>$-dej%Yd{3(#+a95?BYHwny;4T_vy_89=M= z1oV4~vaySlot1$KdI0X}eV}q=J7<=$cA>=zm#3&u@xFk_T1|L8s0LlBY!&ZFlUSS3 ziqCt;F{JV=umgl_D}`E!*4F>uGp_Nfpl2D724EG~20|tc>tB~r11S!C6egR1eKj&k z@P9Zv!5hiKYCrP~Xc9xhozf)Is~lU*6SN0wby5PW5RvDz83KBST3LBA@C;O!BW~&! z_{Pme#})K?}G)>O;lF;47>yC Wnq*Pk1ZE2W0000Px`fk{L`RCodHoej_xRT;-$Onn7W6s#0915L8TG80A70sIzC(>^fsV{}r}Da0n5 zrkb*`MlBnsoNBUZGPNu;of<_21;rT^b;^)390g4g&{q-sKvC%ThkM_-@4b7T-Fvwo zyXQX7%%8n`&e?OG=YRh1vU~RI*+D&BU>i1U*qbm<1CzlXU?=cC5VO5Ua4&g2QY@FTbup)R?1w3GX?n3@m5AyL&Dr^b(7y~=f2ePg{}fmY zVzzAvZZ9y{2=ZO>M#grQHsUQ-7J@z>Sat=OLy8quE=@qprUjdC_Na)3<>j?=%8E&dBqub~C`4 zXA7{>I0GHqZlChj9^6bb_<1sK{&uxLbkxB{XXzSILs(sHa4;OaYw$EC27+R_`5+}OvQL$UX#!@(=;Jlvm9`y-0~#kQ=CYx7b#1B{@CcApU~L3j1_b5(E7V*lW( zwDRtW^xbXcoi=UP@`u*f%(fbSQb_PS;D~M}1kEwl<7Q!NkQdXG$z33AWnLWWq#yLz z{ojA(|9_1~?rY3Yva~r_N^DLl85enH3hf zF8WXXE%9iIK%PyHS^@rT_MMVXJ`WdCI{UCiYR8q z>z5m1p~?`$t0X;Cm0XlvY4MJdHWPhLybk7oizt0%;t}D*6=dm#L&(Fp?~P$syFTaF zFp!6l9}Vx8N5`_>sOltqB^q7FALrGnJxRf-;60GV?xD~HV7JtYy?`@dFdz+q3xPD1 z#iY@xMwLB16c`6qXQ*vHWezbb^Gs);K?cy)L?Df&nY5}GqHB!|O)=D+q-B~5aB=O? zp5hENp8>S?4PebbkyfSI+QAJHt=U*Qa1DrN-fZ*f_ZnNlfHYUq9-E*|8_+hzdcl%l z@lDs%)_mgu_4$r7&`bu<CUY$wMXRQHEEVZ0+U@iR0hzNp5UDXjsaTccnx?A z+<>k$iLGv<&aF7;ZBYAku&1X_H-#ZvRd;KCfHP2H08#11koyDTT1EQVjgrN&IzG`X zL2KTun=?>111N1Y$TG?8(z+|>0P21rnHJx=*(QLLrpvyAFM2p z!7)KW>!#4n8E7U0$5WYB1ju4~0{x>b1+$iML1$&k%VlNY@T>((U+=HPFb0R@BsJheka#`ms5e z5UTe=`sX^fxixsyaNL)GZk{!lLp(eNevj`<*fwO;tNXhhk`8u3SFi$65}Z~QQYX}F z>Y#bx0q`HNm`>|sTVu2{n8ZE7SfD3mlfb7yz2mVra?Dq0N5g?#W0s)(rm!RfNZJ+D zd#${fW4;eQvbk!ajvc@`U@lk>vYM`~b@uBTBi`U8hYK1RK+rzmd63n#X7P!wQV@0T z4eGgm{~zV|X_Y^DtCv_^(4kI&oc%y>IwE0L{GCG0BNRqz4cDEscfpL zzwt$LjW17gnta6;?K~Y~b3s=s3qq~}Y4%GBXaZ9148OFnrXEgM_S4)s-Xw`U079lY8o7BA*o?mv;<3)s$2X&m zPS-(wxLuqNyOg~{=G_(X6sDbkxZA+xv$9aF6I(5Xv*1;vV_)>~rG8#yl- zF;1#Is@N&Sx;1z?5VK|$ZqBP;xgduay7mnH33_0sKrcK``h9`C!Y1=S&O10iGZ4W0 zNgo%;iy}GpOODA#FU_IzLoWy$hZQ30Zo|tdMqc5wVi)wjMi0#~@`|1{mjJZHR+3qq zB$Y2zTI_=UsL>k_8hM4z;(s1}ec{PK5EdtaLyD8!t%BA!I+hlvn;P=e1>F#BIX#Fw zVJ#AqxEKlPS~FvPPF-)7TOmQ~%fVU~Bub0<3~fyVT@ht(4h(Afz}*3R+Yi`_Xs25R zt>w95H)}N|>yN$Ayu>VMYh606u@<{og0{FRG%qm=`Yoepwl?x&$+BX!xG8k}F$>x{ zLq+>vZiO1H>*Q!JxndTy)oG#8j|x2${^u|w0_%_6I4u8J(F&SjIbA1*u9f%5f7fib zhgz;T$=1M))|Zabq7`(hxAe)hB-@#>*x1j~p(lc&@#!R<3YQkUpsmh}cGekxtePSk zT3*-Uq;LYRb~tuHKT#cU#r~9v-?9DFwAtZ-pcVzvqezZj(DRI5I^4)BdX^QN#YxfQ z-ng0&|3f8O3~#Jx5ti2yquaFTOcZZ>SF4bCLo2IlVfR8Tb5xbuMpf|V0}a7#NzheK+lPDm=UWu*k<4n#oQx~?!4qscky4W<}Fxf zrtcNATNAyWPU^74oSvSW;9_kcFP>!79UDm#$TVi!VL&CnmI!hOJ z1ybVrA_$pcj_Ro>@wlK%XX)RDdcBnXox+@^N{-_90YGc?h3wj*#gyhRfx4hY5=0CK z)`vEAHv3!}p?S&2*WG}%(79p_Jp#{57Q$1+qS^^u8P9Dp)%%}eiNGuy0SwdM1uG?uxvG% zCsiJohu`=#2K>u%oV-OK+81Go%>`X8Mo8HkyaFuKHT4fbE*_8L#}S|pSf-dlll!Y_ zDC9ozxuBDJ4q_$%ePbofZli$p(rHrlO-rL~t#f@bNc(cEVmYX34d=8XVst@=`UZ0J ziQ%_FnrXyfI_M46)rxf5lYftbG*b*mw!(+J)k&N#Xsc5oXbK2DHYRI;EoJXa(9)TT z)IT2F1G1QWpJK%rQy#Ippwl`OlJq3;1(4OApx`+mG#MzZ$(nrX(hCVXBi{M1p0!^;3%Q$8PI2l|6tcN6I*O+`ARab)%6ei}N zpmnnm`YgjLrW+P|!cHT72OWAv>AOJFN*j4yNnh2{o7GxE;W?lMZ?v$B-kuo>v})7N zV6PJPU|a7fit73yxQsrEeOX|_9B2|WDap%FNYDX`YPQ`#O49e>MAxtj0^D>mSw0<* z9znb%h(CCSZt0CpktyZOw*db&1a>ZXDF?CW%>NZ|5WYQ<1Ap@Af^n+p>N9j@Z^6+J z@OAL4!B?xY)aKW~kV>Dr`8Qky&(J+aFSwwqR0CIAfob4&unx4!RJYntTU%AR(e=A< z5)`!G6gDUiNYyvOHPuuPGY$irJ5BQy>bM`w1~a*=$irn0uH?@oXuL|iDReVk{T~^tfE38iGut9l~p13D8K$V(<^}I3f;>IFapEX21nqX2Q2oFklJV zM>(SCVh^IsfD5|Jgm0r@zy%#eH+m3d23*i(CVU$O11{(&y3vCuGvIp5+X5f`Ktcqs!6+J=Hkavz&oWFmRmF=*Bbj ze51f;jXckC20FpO$ws5|HNk&4uqLY?V^rW-&OqB3K&QumkV(Uv=A`puPN)>=3qd1q zKesJVZzz5Sq`{IF*(BN=v7l>c+0C0aiT~;&=ra;?Jkc3w9|O{$v>39P{Tb-J7c5QG z{iZ}M5@=nF_t)h=oPlODfcB;WeaS0iOUM|w<{$~DhDw*xSF@ecY-hbbXTV}Wngi0F zWz%ZvptRmEOj}q*7v9rr4)z3Rpal$|wTnR762cEtCiy`N8CtM#4M;Pssis9(+?;`? zGk~_VZnrd+W;%0^GaaD7@xZ!XschtKcFqGM%}PDf8AxG38Y*c?n#y9*Xw8Ga#8Wi| zbw~NL6dx+H_4@sbK=VSD1ASlH%^65zU@!$VH$x}HT|lB9Nl&sFEcI3jSQ@!ty2;6ouM|( zvo8nE;=u9X(NG1R?hLevfk$X(yd`G&VG3FWsNg9!67?5=maTGg2HMGhmP`9QIIyHe zvu*Q|qxwiLLAE6AOrTHhP6XO_a|W8tz`IoV0Jt7phmiHff=pJIpet)c+&i+b$Kk@B zKzFISWA)dzAi*s&1M4WMkui;sJq_*<5OG7xIX5h58m%!zuKGrRZE7+-!5OG!U@b{~ lh}TzLt>wm3oPnO6{{tG|Y9NQh6U+br002ovPDHLkV1jD>n%@8b literal 0 HcmV?d00001 diff --git a/app/assets/images/icn-donation-jar@1x.png b/app/assets/images/icn-donation-jar@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..c1f26a67e3263e5790dfd741c8f4d5b6fa802441 GIT binary patch literal 5677 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 TAhls{00000NkvXXu0mjfwnx~k literal 0 HcmV?d00001 diff --git a/app/assets/images/icn-donation-jar@2x.png b/app/assets/images/icn-donation-jar@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9e1598b517d101b0e4f3e0a72af743bcfcc4bce5 GIT binary patch literal 12711 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%0AFlq*YlMXNpd4B7A|;$glg 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 JPDHLkV1n}wjg9~S literal 0 HcmV?d00001 diff --git a/app/assets/images/icn-editPhoto.svg b/app/assets/images/icn-editPhoto.svg new file mode 100644 index 0000000000..97f52cd53b --- /dev/null +++ b/app/assets/images/icn-editPhoto.svg @@ -0,0 +1,18 @@ + + + + camera2 + Created with Sketch. + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/assets/stylesheets/pages/home.scss b/app/assets/stylesheets/pages/home.scss index 3369b34058..e2a414d308 100644 --- a/app/assets/stylesheets/pages/home.scss +++ b/app/assets/stylesheets/pages/home.scss @@ -1,3 +1,55 @@ +.camera-background { + background-size: 60px 47px; + width: 60px; + height: 47px; + background-image: url(asset-path("camera@2x.png")); + background-color: transparent; + border-style: none; +} + +#icn-donation-jar { + margin-bottom: 30px; +} + +.brave-rewards-banner { + &--background { + &-label { + display: block; + margin-left: -4px; + margin-top: 5px; + font-size: 16px; + } + + &-camera { + margin-left: 46%; + margin-top: -60px; + } + } + &--logo { + &-parent { + position: relative; + } + + &-label { + display: block; + margin-left: -4px; + margin-top: 5px; + font-size: 16px; + } + + &-no-attachment { + margin-left: 30%; + position: absolute; + } + + &-camera { + margin-left: 30%; + margin-top: 30%; + position: absolute; + } + } +} + .nav { display: block; diff --git a/app/controllers/banners_controller.rb b/app/controllers/banners_controller.rb new file mode 100644 index 0000000000..c55add06d2 --- /dev/null +++ b/app/controllers/banners_controller.rb @@ -0,0 +1,5 @@ +class BannersController < ApplicationController + def new + @publisher_id = current_publisher.id + end +end diff --git a/app/controllers/publishers/site_banners_controller.rb b/app/controllers/publishers/site_banners_controller.rb new file mode 100644 index 0000000000..55db323522 --- /dev/null +++ b/app/controllers/publishers/site_banners_controller.rb @@ -0,0 +1,56 @@ +class Publishers::SiteBannersController < ApplicationController + def new + @site_banner = current_publisher.site_banner || SiteBanner.new + end + + def create + site_banner = current_publisher.site_banner || SiteBanner.new + donation_amounts = JSON.parse(params[:donation_amounts]) + site_banner.update( + publisher_id: current_publisher.id, + title: params[:title], + donation_amounts: donation_amounts, + default_donation: donation_amounts[1], + social_links: params[:social_links], + description: params[:description] + ) + head :ok + end + + def update_logo + site_banner = current_publisher.site_banner + update_image(site_banner.logo) + head :ok + end + + def update_background_image + site_banner = current_publisher.site_banner + update_image(site_banner.background_image) + head :ok + end + + private + + def update_image(attachment) + data_url = params[:image].split(',')[0] + if data_url.starts_with?("data:image/jpeg") + content_type = "image/jpeg" + extension = ".jpg" + elsif data_url.starts_with?("data:image/png") + content_type = "image/png" + extension = ".png" + else + # TODO: Throw an exception here + end + filename = Time.now.to_s.gsub!(" ", "_").gsub!(":", "_") + current_publisher.id + "_logo" + + file = Tempfile.new([filename, extension]) + File.open(file.path, 'wb') do |f| + f.write(Base64.decode64(params[:image].split(',')[1])) + end + attachment.attach(io: open(file.path), + filename: filename, + content_type: content_type + ) + end +end diff --git a/app/javascript/locale/en.js b/app/javascript/locale/en.js new file mode 100644 index 0000000000..4f5e6d77cc --- /dev/null +++ b/app/javascript/locale/en.js @@ -0,0 +1,86 @@ +const locale = { + about: 'about', + addFunds: 'add funds', + allowTip: 'Allow tips on', + braveRewards: 'Brave Rewards', + cancel: 'Cancel', + claim: 'Claim', + copy: 'Copy', + currentDonation: 'You’re currently donating {{currentDonation}} BAT to this site every month.', + detail: 'Detail', + donationAmount: 'Donation amount', + done: 'Done', + earningsAds: 'Earnings from Brave Ads', + expiresOn: 'expires on', + import: 'import', + makeMonthly: 'Make this monthly', + monthApr: 'Apr', + monthAug: 'August', + monthDec: 'December', + monthFeb: 'February', + monthJan: 'January', + monthJul: 'July', + monthJun: 'June', + monthMar: 'March', + monthMay: 'May', + monthNov: 'November', + monthOct: 'October', + monthSep: 'September', + noGrants: 'Currently no token grant is available.', + notEnoughTokens: 'Not enough tokens. Please', + on: 'on', + oneTime: 'One time', + oneTimeDonation: 'One-time Donations/Tips', + print: 'Print', + recoveryKeys: 'Recovery Key', + recurring: 'Recurring', + recurringDonations: 'Recurring Donations', + remove: 'remove', + restore: 'Restore', + rewardsBackupText1: 'Backup your Wallet', + rewardsBackupText2: 'Keep this anonymized recovery key for your Brave wallet in the safe place in case you lose access to this browser. Your funds are safe as long as you keep this recovery key either on a paper or in a device with preferably no internet connection.', + rewardsBannerText1: 'Thanks for stopping by. We joined Brave’s vision of protecting your privacy because we believe that fans like you would support us in our effort to keep the web a clean and safe place to be.', + rewardsBannerText2: 'Your donation is much appreciated and it encourages us to continue to improve our content.', + rewardsContribute: 'Brave Contribute', + rewardsContributeAttention: 'Your attention metric', + rewardsContributeText1: 'You’re currently supporting', + rewardsContributeVisited: 'Site visited', + rewardsOffText1: 'Do you know that you’ve been paying for the web content with your data for the digital ads? You didn’t have a voice in it and worse, you’re exposed to privacy and security risks.', + rewardsOffText2: 'Brave Rewards allows you to take control back.', + rewardsOffText3: 'How does it work?', + rewardsOffText4: 'Your attention is valuable. Get paid for the ads. And pay directly the favorite content creators at your will. That way, they can grow and continue delivering the content that delights you.', + rewardsPanelEmptyText1: 'Sadly, no tokens yet.', + rewardsPanelEmptyText2: '3 ways to fill your wallet:', + rewardsPanelEmptyText3: 'You can add funds.', + rewardsPanelEmptyText4: 'You can earn tokens from Brave Ads.', + rewardsPanelEmptyText5: 'Occasionally, you will also received token grants from Brave. So keep an eye out for the alert!', + rewardsPanelOffText1: 'Get Rewarded for Browsing!', + rewardsPanelOffText2: 'Earn tokens for your attention to ads and pay it forward to support content creators you value!', + rewardsPanelText1: 'Add, withdraw and manage funds at', + rewardsPanelText2: 'Brave wallet is managed by', + rewardsRestoreText1: 'Restore your Wallet', + rewardsRestoreText2: 'Enter the recovery key to restore your Brave wallet. Make sure that the current wallet doesn’t have any balance or is backed up safely. Restoring a wallet replaces the current wallet and you will loose any balance if you don’t back up its recovery key.', + rewardsRestoreText3: 'Enter your recovery key or', + rewardsSummary: 'Rewards Summary', + rewardsWhy: 'Why Brave Rewards…', + saveAsFile: 'Save as File', + seeAllItems: 'See all {{numItems}} items', + seeAllSites: 'See all {{numSites}} sites', + sendDonation: 'Send my donation', + sendTip: 'Send my Tip', + settings: 'Settings', + siteVisited: 'Site visited', + sites: 'sites', + tipOnLike: 'Tip on like', + tokenBalance: 'Token balance', + tokenGrant: 'Token Grant', + tokens: 'tokens', + type: 'Type', + verifiedPublisher: 'Brave Verified Publisher', + walletActivity: 'Wallet Activity/ Monthly Statement', + walletBalance: 'wallet balance', + welcome: 'Welcome!', + yourWallet: 'Your wallet' +}; + +export default locale; diff --git a/app/javascript/packs/brave_rewards_banner_display.jsx b/app/javascript/packs/brave_rewards_banner_display.jsx new file mode 100644 index 0000000000..4a096af3d3 --- /dev/null +++ b/app/javascript/packs/brave_rewards_banner_display.jsx @@ -0,0 +1,480 @@ +// Run this example by adding <%= javascript_pack_tag 'hello_react' %> to the head of your layout file, +// like app/views/layouts/application.html.erb. All it does is render
ButtonPrimary
at the bottom +// of the page. + +import React from 'react' +import ReactDOM from 'react-dom' +import PropTypes from 'prop-types' +import SiteBanner from 'brave-ui/features/rewards/siteBanner' +import { initLocale } from 'brave-ui' +import locale from 'locale/en' + +class BraveRewardsPageForm extends React.Component { + constructor(props) { + super(props); + + this.state = { + title: props.details.title || 'YOUR TITLE', + description: props.details.description || 'A brief description', + backgroundImage: props.details.backgroundUrl, + logo: props.details.logoUrl, + donationAmounts: props.details.donationAmounts || [1, 5, 10], + socialLinks: props.details.socialLinks || {'twitter': '@', 'youtube': '@', 'twitch': '@'}, + }; + + this.updateDescription = this.updateDescription.bind(this); + this.updateTwitch = this.updateTwitch.bind(this); + this.updateYoutube = this.updateYoutube.bind(this); + this.updateTwitter = this.updateTwitter.bind(this); + this.handleLogoImageChange = this.handleLogoImageChange.bind(this); + this.handleBackgroundImageChange = this.handleBackgroundImageChange.bind(this); + this.handleDonationAmountsChange = this.handleDonationAmountsChange.bind(this); + this.handleSubmit = this.handleSubmit.bind(this); + } + + isNormalInteger(str) { + return /^\+?(0|[1-9]\d*)$/.test(str); + } + + convertDonationAmounts(donationAmounts) { + if (donationAmounts == null) return null; + + return donationAmounts.map( + amount => ({ + 'tokens': amount, + 'converted': this.props.conversionRate * amount, + 'selected': false + }) + ); + } + + handleDonationAmountsChange(event) { + this.setState({ + donationAmounts: + document.getElementById("donation-amounts-input").value.split(',').map(Number) + }); + } + + handleLogoImageChange(event) { + this.setState({logo: URL.createObjectURL(event.target.files[0])}); + var logoImageDiv = document.getElementsByClassName("brave-rewards-banner--logo-no-attachment")[0]; + var logoDiv = document.getElementsByClassName("sc-dnqmqq")[0]; + + if (this.state.logo != null) { + logoImageDiv.classList.remove("brave-rewards-banner--logo-no-attachment"); + logoImageDiv.classList.add("brave-rewards-banner--logo-camera"); + logoDiv.classList.add("brave-rewards-banner--logo-parent"); + } + } + + applyFade() { + if(this.props.editMode){ + let bgClass = document.getElementsByClassName('sc-EHOje')[0].classList[1]; + let bgElement = document.getElementsByClassName('sc-EHOje ' + bgClass)[0]; + let bgStyle = getComputedStyle(bgElement); + let bgUrl = bgStyle.background.match(/url\(([^)]+)\)/i)[1]; + let bgFaded = 'linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url(' + bgUrl + ')'; + + //Check for default image + if(!bgUrl.includes('/rewards/siteBanner/assets/')){ + bgElement.style.backgroundImage = bgFaded + } + } + } + + handleBackgroundImageChange(event) { + this.setState({backgroundImage: URL.createObjectURL(event.target.files[0])}); + this.applyFade(); + } + + setupBackgroundLabel() { + // Allow uploads + var backgroundButton = document.createElement("button"); + backgroundButton.id = "background-image-select-button"; + backgroundButton.classList.add("camera-background"); + + var backgroundInput = document.createElement("input"); + backgroundInput.id="background-image-select-input"; + backgroundInput.type="file"; + backgroundInput.style.display = "none"; + backgroundInput.onchange = this.handleBackgroundImageChange; + + backgroundButton.addEventListener("click", function (e) { + if (backgroundInput) { + backgroundInput.click(); + } + }, false); + + var label = document.createElement("label"); + label.innerHTML="900 x 176"; + label.classList.add("brave-rewards-banner--background-label"); + + var backgroundDiv = document.getElementsByClassName("sc-EHOje")[0]; + var callToActionDiv = document.createElement("div"); + callToActionDiv.classList.add("brave-rewards-banner--background-camera"); + backgroundDiv.append(callToActionDiv); + callToActionDiv.appendChild(backgroundInput); + callToActionDiv.appendChild(backgroundButton); + callToActionDiv.appendChild(label); + } + + setupLogoLabel() { + // Allow uploads + var logoButton = document.createElement("button"); + logoButton.id = "logo-image-select-button"; + logoButton.classList.add("camera-background"); + + var logoInput = document.createElement("input"); + logoInput.id="logo-image-select-input"; + logoInput.type="file"; + logoInput.style.display = "none"; + logoInput.onchange = this.handleLogoImageChange; + + logoButton.addEventListener("click", function (e) { + if (logoInput) { + logoInput.click(); + } + }, false); + + var label = document.createElement("label"); + label.innerHTML="148 x 148"; + label.classList.add("brave-rewards-banner--logo-label"); + + var logoDiv = document.getElementsByClassName("sc-dnqmqq")[0]; + logoDiv.classList.add("brave-rewards-banner--logo-parent"); + var callToActionDiv = document.createElement("div"); + if (this.state.logo == null) { + callToActionDiv.classList.add("brave-rewards-banner--logo-no-attachment"); + } else { + callToActionDiv.classList.add("brave-rewards-banner--logo-camera"); + } + logoDiv.prepend(callToActionDiv); + callToActionDiv.appendChild(logoInput); + callToActionDiv.appendChild(logoButton); + callToActionDiv.appendChild(label); + } + + componentDidMount() { + + this.applyFade(); + + if (this.props.editMode) { + this.setupBackgroundLabel(); + this.setupLogoLabel(); + + // Set h3 editable + document.getElementsByClassName("sc-gZMcBi")[0].setAttribute("contenteditable", true) + + // Set p editable + // document.getElementsByClassName("sc-gqjmRU")[0].setAttribute("contenteditable", true) + + var hiddenDonationAmounts = document.createElement('input'); + hiddenDonationAmounts.id = 'donation-amounts-input'; + hiddenDonationAmounts.type = "hidden" + hiddenDonationAmounts.style.display = 'none'; + hiddenDonationAmounts.onchange = this.handleDonationAmountsChange; + document.body.appendChild(hiddenDonationAmounts); + + // Editable for tokens + for (let element of document.getElementsByClassName("sc-brqgnP")) { + element.setAttribute("contenteditable", true); + var observer = new MutationObserver(function(mutations) { + mutations.forEach(function(mutation) { + if (mutation.type == "contentList") { + return; + } + // TODO: (Albert Wang) Make sure the input are valid numbers + var donationAmounts = []; + for (let amountSpan of document.getElementsByClassName("sc-brqgnP")) { + donationAmounts.push(parseInt(amountSpan.textContent)); + } + document.getElementById("donation-amounts-input").value = donationAmounts; + document.getElementById("donation-amounts-input").onchange(); + }); + }); + // configuration of the observer: + var config = { characterData: true, attributes: false, childList: true, subtree: true }; + // pass in the target node, as well as the observer options + observer.observe(element, config); + }; + + // Hide X-mark + document.getElementsByClassName("sc-bZQynM")[0].style = "display: none"; + } + } + + submitById(id, suffix) { + const url = '/publishers/' + this.props.publisher_id + "/site_banners/update_" + suffix; + var file = document.getElementById(id); + var reader = new FileReader(); + + // Don't upload if user didn't upload a new image + if (file.value == "" || file.value == null) { + return; + } + reader.readAsDataURL(file.files[0]); + reader.onloadend = function () { + const body = new FormData(); + body.append('image', reader.result); + fetch(url, { + method: 'POST', + headers: { + 'Accept': 'text/html', + 'X-Requested-With': 'XMLHttpRequest', + 'X-CSRF-Token': document.head.querySelector("[name=csrf-token]").content + }, + credentials: "same-origin", + body: body + }); + }; + } + + updateDescription(event) { + this.setState({description: event.target.value}) + } + + updateTwitch(event) { + let temp = this.state.socialLinks + temp.twitch = event.target.value + this.setState({socialLink : temp}); + } + + updateYoutube(event) { + let temp = this.state.socialLinks + temp.youtube = event.target.value + this.setState({socialLink : temp}); + } + + updateTwitter(event) { + let temp = this.state.socialLinks + temp.twitter = event.target.value + this.setState({socialLink : temp}); + } + + /* + setTextsFromDiv() { + this.setState({ + title: document.getElementsByClassName("sc-gZMcBi")[0].innerText, + description: document.getElementsByClassName("sc-gqjmRU")[0].innerText + }); + } + */ + + handleSubmit(event) { + const url = '/publishers/' + this.props.publisher_id + "/site_banners"; + var request = new XMLHttpRequest(); + const body = new FormData(); + + body.append('title', document.getElementsByClassName("sc-gZMcBi")[0].innerText); + body.append('description', this.state.description); + body.append('donation_amounts', JSON.stringify(this.state.donationAmounts)); + body.append('social_links', JSON.stringify(this.state.socialLinks)); + + fetch(url, { + method: 'POST', + headers: { + 'Accept': 'text/html', + 'X-Requested-With': 'XMLHttpRequest', + 'X-CSRF-Token': document.head.querySelector("[name=csrf-token]").content + }, + credentials: "same-origin", + body: body + }).then ( + function(response) { + function submitById(id, suffix) { + const url = '/publishers/' + document.getElementById("publisher_id").value + "/site_banners/update_" + suffix; + var file = document.getElementById(id); + var reader = new FileReader(); + + // Don't upload if user didn't upload a new image + if (file.value == "" || file.value == null) { + return; + } + reader.readAsDataURL(file.files[0]); + reader.onloadend = function () { + const body = new FormData(); + body.append('image', reader.result); + fetch(url, { + method: 'POST', + headers: { + 'Accept': 'text/html', + 'X-Requested-With': 'XMLHttpRequest', + 'X-CSRF-Token': document.head.querySelector("[name=csrf-token]").content + }, + credentials: "same-origin", + body: body + }); + }; + } + if (response.status === 200) { + submitById("background-image-select-input", "background_image"); + submitById("logo-image-select-input", "logo"); + } + // TODO: (Albert Wang): Make sure the above code doesn't reach here until a response is received + }).then( + function(response) { + ReactDOM.unmountComponentAtNode(document.getElementsByClassName("modal-panel--content")[0]); + document.getElementsByClassName("modal-panel--close")[0].click(); + }); + } + + render() { + initLocale(locale); + + let topController; + + if (this.props.editMode) { + topController = + + Don't Change + Preview Banner + Save Change + + } else { + topController = Close + } + + return ( +
+
+
+
+
+

All Channels

+
+
+ {topController} +
+
+
+
+ + + +
+ { + // this.state.socialLinks.twitter !== undefined && +
+ + +
+ } + { + // this.state.socialLinks.youtube !== undefined && +
+ + +
+ } + { + // this.state.socialLinks.twitch !== undefined && +
+ + +
+ } +
+
+
+ + +
+
+ ); + } +} + +/* +
+
+

PREVIEW

+
+ +
+ Description: +