From 13f91ced451465ff7a31de290ce7bd7168c70217 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 23 Jan 2015 14:55:03 -0800 Subject: [PATCH 01/10] New status images. --- app/images/paused.png | Bin 726 -> 705 bytes app/images/paused@2x.png | Bin 1594 -> 1611 bytes app/images/running-white.png | Bin 0 -> 359 bytes app/images/running-white@2x.png | Bin 0 -> 731 bytes app/images/runningwave-white.png | Bin 0 -> 252 bytes app/images/runningwave-white@2x.png | Bin 0 -> 461 bytes app/images/runningwave.png | Bin 340 -> 0 bytes app/images/runningwave@2x.png | Bin 626 -> 638 bytes app/images/still-white.png | Bin 0 -> 349 bytes app/images/still-white@2x.png | Bin 0 -> 729 bytes app/images/stopped.png | Bin 571 -> 535 bytes app/images/stopped@2x.png | Bin 1177 -> 1194 bytes app/images/wavy-white.png | Bin 0 -> 466 bytes app/images/wavy-white@2x.png | Bin 0 -> 1049 bytes app/styles/containers.less | 47 ++++++++++++++++++++-------- app/styles/main.less | 4 +-- 16 files changed, 36 insertions(+), 15 deletions(-) create mode 100644 app/images/running-white.png create mode 100644 app/images/running-white@2x.png create mode 100644 app/images/runningwave-white.png create mode 100644 app/images/runningwave-white@2x.png delete mode 100644 app/images/runningwave.png create mode 100644 app/images/still-white.png create mode 100644 app/images/still-white@2x.png create mode 100644 app/images/wavy-white.png create mode 100644 app/images/wavy-white@2x.png diff --git a/app/images/paused.png b/app/images/paused.png index 221adf9f1b0d315459f8b6a4ae2041ac23352f13..225cd93ec43bb2817012e0acd8d17a7586272dd5 100644 GIT binary patch delta 668 zcmV;N0%QHw1;GW7F@JkWL_t(I5v^5CXcIvcp4qff+5}4>3WCXk4Qg`|1A+$y4}##K zdhVrAP*9;gR6OP=_Er=xLRv5gf|{F9(32N2-i)>;mEEO?q!&wq(6yQI`^Mdxq)l3A z2WH>Azi-}q^JZ3x9Y(2C>OYc5j0q{nq!3vx#BrKo{R8Wg(0{tPzP47(X0v}f-C@%{ zmL2E1CFQJ?@?^WFozq&cD6MBs+4k#JjTJJvT+XVx?!$;>y&@PK%9zubnT>iq&dGHk zE7OLy^r3Hvvqh<>dY-Ph?ncFNZtrLmSW`zE+R}%vF0?l-l*dfK+%g$BLo zlH**CNcjfQMt_@1-C+7MIDoGvO{MOnZToRAkWL*Vm6r7g!K~n*&R9Inux5q%`6rzY zyYch^n5n7hjEd(Kg4#{(=G;w>T22`ZVD+)jj3L5=@FjZe9QyAlWKs0oI{1=OD*t?8 z;ROyubpc(ZoLG`4#iDjG{4dt}6PTMLsT673D3{BzLx1sj9RW1Z!?HineiTaG6~3RY zt*#FIs@0;1Y!uCV3sJg=nvs9_=DKs$YV|}b;^D!;OCc}OLqB17428|4Q>ibZqLrc( z28I%eoR)GLY4t&;5Y2aNw1o9Af@0a2rDwtDEfySC{*mop+}Ynq^&T$nS!`SYkPqMy z0A0hpfPWdG7dClsL0JqSCVSlu+KeWXpOMA5_Whye=H_`eGw4N>X4zl>>%bcukqdE< zSI@i><_Xf8Pgaz7bFYs>c#l!G+3*=N5i&~FZ+v3n0Zx2|Jg*bTQ_Mxb(eNmX#$rhj z9^NE2&rn9NXZig7u<5q|jS`>zKCs&W3A~?Qz!hJY$%stZ>}|UM0000@pfD#C(q4uAWRV#X9)Dk0$&V)zvn9Vf`xWb% z)OivaW#%rwtzH(9uf#kQ=}5n>*Beh59wxKCn7pGqymDkBbJof=vZdbq`dSNqcy~Ir z0Rt?2;Op_!Rv2=bl;oC@o7tt*l`TP4G;F{C3m^D;L@s5diQP2SV#Ugt*2B~9JivDA z@9+Hs0mBoTdVhluT|oMb12}r1aULmHp{vn&dTcuqzYUQZrU$6$m*ql_!D)ImyZpRp)yFLjO-(UR zMubZ$bd*Y^V{J!1e)0_dHM`hzJdschoGwjOpV$U1fbeFY-s@mWb}H}b)J<>7YJ@Q2+3f}U7a>S@^9lF^ XpNMLmWwJGZ00000NkvXXu0mjf&c9ON diff --git a/app/images/paused@2x.png b/app/images/paused@2x.png index dea41b188163933d2df021fa901fe3dddda7dc2c..567492f7473a82d700aeda859ef8537d92047e89 100644 GIT binary patch delta 1582 zcmV+}2GRMt49g6VFnK#tp@|{g4M`KbG!})J z4V&F&@A!R_y?5u{-EKFVUG2c+&YU?v-=3K{GiRb}WtQm7%zrM3cBAe?ZPZZ(D%GJK zM>~!t>m}5S;pXN^d{(5eUO9D7H zHWo5Np<|k^ABRAwRON;E;Ms&G#QW();)C|~_Cz5bm3CWzSEi?5G<5xAfZM7HuDLD5 zoGrxR-L0)(7Jt)K44@vpdiA8P>!+X~k534Z2I%iK+x{9J`F+{8DU#`i;ySpW#sh~98ZOCQGI-29Sfm@Gp>Lv>r4nm&Wlm-0k}xGr?PPfMjf z4~N757vdy9Z}YPNgzUcd<(iypaxYLf`lhu2F>HiJb(aq3c?Xp7*ljz*!F?&&YeGc z=w)`IQ&W%XhB4sxCO}32vR75>0Vp?wVO#)%O1~^psb?{rf2e|MZDZQE>%rhR(9@yl zf*VL*@fiRQ=L!lUcRc^P^bLsR$l?LYkk|0gD=27mcwoGUk!sCr6m)0T{_UICu>n$BAZ z5XYP`xI3+-(_64UN(#b`+*-dfn49JeggE!aK|r)P#k?}*3XZS;8XS#Fn>;$brF$Lv zywBwd&Q|=IplzCu1N~F@MSC!~3%h13eo-CTb?|rw?Z45U!{!>&Gnwzi^76MZlG}|r zjen)Lc&;19Gm5}I0+g3bhlmLOv@tx-1(2X$SI-T{E59P0yGP0bM~j>o2_KU$oh zKU?= zJ2@Gc&1C8_$>jEoZ9fMkXTZ1M*8q=p*VNXIAxgXvi9}?)_4D}qI6;~{G$`iPDy431 zF#G~g{l5(lU+n4W$#?{A(ZM->Hl z1>gHrIq(j07ypXt0t8bV`h%#eF1X8a7e0aAd<2HyDX`fXqMn2eR;hpGFPhoD&uH8L zO1d>ym_w|s2&=XAw4F@u!PK6EDt~(o>Mm9NsEfs7mN3oNF@*==rIy=(g}-v)79C4^ z80+vd2KG9_7&wfVfU{1&QeS}GAp(I%pzlG{&8Q8iOIVLHxGZc&dixssP8qeDn>)A$ zSq4yDfXu#-;G8S_M35@;|5%na3o7dcb(G0e{iaRsg(W*iOe@zdK1aZ7xqmDlsUfp3 zRY^75(w35r5(_c80OeZ=o+DHch-W95eW|o+v}J||TOQrO;=JFu5uR@)SPOFwBLD`O z8ZxnQXqEoTqzN`?%he4G5=)lg0%R7&w-V6d;cS81nHp9Dqy)#bQ<+-YCI%;?BMKKF zJIqHByL#DHN{5cru#(d)r+<~{rZ*?X1d3iYCng3rkSl=hsHYE)2eTjrA9C<(&MTlX z6ME1vj6Q|~-cT?_8`SY)ZSqovvee;Oa}cC0+GNwOr;rC7o;&yX%|XcT|NVejXo^*Q za^vu=1k(^<0QC%((V-6NqE7#YD5S2~6zB10AJLCufH{YIH0CiDCMS%7T%AYsLiU*O ggU+0~s{e-g7iz7~_z|gjj{pDw07*qoM6N<$g4Kr$)&Kwi delta 1565 zcmV+&2IBe447v=EFnGUVrEN`u%ImY`YG3ldk8Ud(Sz)o_o)^_uL68vQ0(XHh*bEdj*M|B&bf2sDmp0 za2pq-#!1n*A~hn3&IcQZZW=>{{S}2wpBQUfSLqXP0aynKv8@nUQtCQ@4$LLgsoJKY zJNe4y1@O*jsJb#x^R6Q82n4G0Ri0~}BAO8-Kbo7q-?uI_I+JUTllPwhN^j zQBhTw(tLGZkK9V6y-cKbL4_|Hh=M~^x4&Vi2V8$Y_jC(hl1HN+4YXEx;UaQS9<=hmdUVm?B_;D_CEEhm{uKf#4bc0j0 zfFIdA`%nC2?T%k&GZp32pZNLds;V{qci{P>09u|QbI#uoc?CR|C$j)zS&!qFcDaP% zHJMT!H5&(ia`B7o-2WroqItwXwl`%Lmb=@j)&)=x2%@iCdrr}{#KPi>Sk6D4g3G0` z?Df9#vVZRYa=WdI_aq%~295<#PbL1~m@8W0Ie>en)Zk1&X^_J%Pa?YK;!{m#3PR2` z8t1tTa0|SwD+P|NvTnA4U5EXhZb)Z3mULGK$R`9RVRMf0t$Itf=iGYTJ;R3Tb#fUC zV`82Tu+m3|vDWqpfu-eWbqcK{t=rPmmtlpm@PCoYJsqG%VxJp;>?t;txb@`MGi=Eo z=WGD$;J)BniAQK-)*w!Z#6t2h?2o*XuqC%l!bs-cyUr6QrDT%^q5u-#B!|lq}?%FCAX5Lju^e^i9~}YC^oPgR?jV5Q5-w?J~~tFYn&kxuF0_ zeJbCGoHC3}6G}blWR{3NSguw47LT@dLVsU|?;mWzyskNB)FHzdsm8%flZsn}lzdN8 z>IJo^wxlGj#kJ^>zB3U|GC8w`Qpv5j%6DQvUe1&kLImK={^@A=^1a*PQ0929zVHMy zehhXumLrDA^|pY*olJZp6N{&6HeJ18^OvTkZ?}X=^Y+0)bB>uw6i=U%6dwnkh<`+K zjO(oFTdhZg$Mc~%j+?{p02oGSi)SsSlKTRUL+8zYA>UnHq`mz{dnY3Mgzmwd!YWEi z48r(`qSUw$o_V3<2JE-z5o~*a1=+=H@`{K@!)FnqubM0@>6?hceyd*u!MBvMin7!2 z=1WD0+agL{L=>wLo5K{>5X)7au!rUU5C% zDkslGwopnQK)`*2Yt?)qni!iNHCX0rSmte(u#$(c%%`n>iHOnBkgwifvjeu8kv=v9 zbP!pj8nHTwe77F^Z@*;n(*}s@3kA++rM}UGLZc{EX@5BVv9K7$ zQ~1F}ct0=scpl*hT z(+zIt(r_g}vd(nb>3C^?ZGT`eD>_DD0pyNRkE(8_t%kZ4iiS(M+^mar0*s?3W{dnz z<9yQWV#X;iBs8IS06STFRQXZHgo90M!)i0&|Bkq_(N5ElOeC2p4Cq>cM! P00000NkvXXu0mjfXIl!~ diff --git a/app/images/running-white.png b/app/images/running-white.png new file mode 100644 index 0000000000000000000000000000000000000000..682d7b46856426f8f4a526aaf59c9af59bb97da8 GIT binary patch literal 359 zcmV-t0hs=YP)Px$AxT6*R5%f>m9Y)NFc3v!q;yO`!2qe5fP$J7nIa8yFatv{NJ<(c>MW27Arbx~ zXOV~mLhzT)XW!lb*p6*n)PuUNV}-Y7EBS?$mGXt`h&ktO79VyJOJx_?H&BxfDk(XW z?OQ4*^>?yFHaDYBjGPCY*_*I}UhJxV-dkiWa#lkv*mndKV3~k|btm~@K&^4)Z29WM zGQVf}2Yzo#Tvh|nh$A%_BY}N+--}+ER}hYI8EGLI zFVn4r`&5t?f|U*C-Lml`@i|tY`gza3{S1O!C$MbXq}Fpw1i71F)3`~k=N7?_4T510 zHVc$!xU1)POrqf)2b*Qs=c_f-zaCiUh1#AErSYV{fCnDq0|!pEsxtrp002ovPDHLk FV1gsMmZ1Ou literal 0 HcmV?d00001 diff --git a/app/images/running-white@2x.png b/app/images/running-white@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a83f28aee8140e250a7ddc8bbe53c9f32614ec42 GIT binary patch literal 731 zcmV<10wn#3P)Px%l}SWFR9FeknY~UNF%*S&(xIS~NUYMWl!BIqGEV>!Z$aJxSt4(fE~)5v0vc9I zN6S(}Lz+y!vv?OY&N zxz~j^1)>h%6`aCtp)neJkX6-eeZwm4qV6&A_2JFEfFohY$3;1bMr|KKWXlx3KwYQN!Ix2H1 zaWB{};m3^}B|2$r^dVm!in%_MbP9eXZT<3-M9e`Z`HDU%dI&2W(p3|}KXZ53KCc`& z;G%p&`LB-#9eB+pE--_QA7t+aID>F(yTatIiLmX=i?|Tyz%;RS2uK z)nYmijb&o3)V1nwya?ygub445MTf};0%*%*al_W=$r?)3W6T>D>r4W*pR@R78-?pW z_OS$NvuW|$HVW5$>~Tt0{3%aQVKMl+=&qC+tH?;8A}}(Uy-r7pU)6i&NVuT=%hWHH)i$)y)%x z$a*&mQiwo(@mo~4-Ku-T8nYN|3aQt#<&OgE{%DFK>;3GMK!IE9Z?*2cCQY_4Jo$<~ zDSGIC&Am$M|D}7~M;|eZ^&TEA@)XW#ABjYbI~BVfU^Px#wn;=mR5%gs(7g)6Fc84;1gV{cA~=bI@8BYci=%Ji;0w5kllTq}K8Kr2$BNwx zqTu49lktCo5CSp9IS0RzkGo4brDDVh{67I>%m5o4aK#f3oUlf>R(BF7$Po&8V1ee( z##WaL>lMamBSnT0ws=9J#1sv?G5a2tiq8#mq;`V4=6;9*-?+0lVh{P5Pe{X-TkPAD zn_vcMPx$heko7ljG@QlX{+(CZGvu z0-As(pb2OK|2Y9;8{YT*cJ?MPi75=C8=Yvy8=mlhbDZMD7*pohxMHvw9H4~XR*@Ul zARo?M(Xa{2xQ2_mrOCXL32C%|8y8d6>2btbBFdmfnuavUvv-CxGAQC1@;z%t9HU5K z5giED3k&Pm<@;F;ZibyR+MFi?2CB^YA(CM?2lu$X3tN!;>(v#DE0BlGTI|QMgf#rx z1mC%951V|_J8Oq;Ht0FbB|Dh5Tv}rN5?S0s-Ue;xhuk}k7(Pp;q>eH4wHEbAuNYSG ziby5@;@PMJ+3u%zFZNNvU#ep3?R1^V2C$9752mbg%>_2lXZPx$4oO5oR5%f1U>F6XAwY5nFoJb7Ffb)0Ft{@@Fa!blW(yz~GPsNdOhT0}@YwmVE-!x}(7O z=|ls1ImE;&igk)$I=evd;|K&R1w~L1gj5z5et{o|ayd~0T1bK)$>p*;{#6n-IXB!M zDhM;|vO90yd-I>)ycuxK5pV(lfEA`eotd}$G>s=$`+>La#mw66WEbwFCNF0tW9E4Ns>zVs05!Yjx#W{ zjju^!<9vS#+&7HBp`LbiPD|A0IOj_368bg_IGJnUMx`-ve&$$#Hf>{{9Gc>ssMN&3}`)tBU=tIFZPQFla+MOVhLj6RaJ3&(g8`_@$5~#YyTy%K_D2zjAyj z(_lDQlj3=1L?zRs!b#XNd0I{OjjATvRQ%R(O%o5~)-xO(TIfIXjFqH0<5{|Ocoxm~ z)g(_%NPke|vWR}3KR(lMf5EES6s=lLr);~T0;grTWPhjVz1YONnSi9<%xjvB&w17I zo|xDP5r3$9eo@Uji*RgOF1y>X$J|lbN-h*`stR=&as! zvf#PiCOg9Z3-#QYYyLC6j#t!av-?EmkTT9vNsv7(y9W~lSL~{7Z^Y+>Ci`)>u3IQj zTdju&s!`WlItzpUL||0V;R0)P`)`-ft*XJa4%On&!+Ifwz>?SP@OY?^kI@+S?+7>o mj({WJ2si?cfFtnN2z&Aix3j`vb? z$sqX7a5-nbzw@5weuoRl5CTF#2nYcoAOwWK|4cwRiSPZ2Dt}K2nzcd`H10F5S}FLr zz77R1=adHaX;1K(GqZ?7BNGUq%xj>+<3S4#_lV@%ZOVWm zKWh^M6Mn4P`JHUtF_aVm&n^qp*yY6tQ}+0~TEv_R? zc!)K&)fc*xl$xO!AJ=}ao0(U0KF#XEV;Wv14>3Yvsq;>^>&Kh8Ra}ZOZWeG`<19}F zw@}0WNSqn|=G+@cs{y>G&<0m^HIk%#^&=QVn=;VD&8&-5_M07#_^RjG0@Ei4`0!5z z<^(;5(M8vdJM7U$3aH~{xJCiR>_O|Rv}I~Uw=-Ce)Z<4kM;1ar2nYcoAOwVf5D)@a aN#GaSexM9A_t44!0000Px$7fD1xR5%f>mAwtZFc5{~ND&PaFhXi3prD2#Q>0;z%#a}%Bqa?JH8X&a2;U=T zkqGk_eA4;OclTb-j^nr_AZ^=bgjc3>?99rJ*aqE7opTq9zc!Gq(F6KPRI`4`L^4II z9?K4YgXZYeRK8-$c@ZXkA|~j`&iG}p$WY2zjcO&;fRKQeDN(^e4GsR zdse=|2UB3R8i_cvgrU$3(Y`$IMUdtZ6vnWawh)1ihot5hTs!ys(J-|kR_bssY9#-j zW>_igodGU~b0R$%mW-aAf8Mi?kD|kj2b<*iGFNE824anfsn@g^!$!N v8t-zjF5_Nby-xqSV4WxGTfHdeqkaK5$v_4B;ZwT{00000NkvXXu0mjfQm>Zn literal 0 HcmV?d00001 diff --git a/app/images/still-white@2x.png b/app/images/still-white@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..64110715fe778e796e4c6a26167cab37396be257 GIT binary patch literal 729 zcmV;~0w(>5P)Px%lSxEDR9FeknLSPxa_v8-q>xoZL(2AnzLu z=s~YQ)Hb|;Q@ASBMs2q{7m3qN7~m6Z3;76evlF2>I)Q&-*O1SX#v*B)!2sW26<#U4 zg=g>(?m_jmC|hNEraG!y1^EszTS+Jl*5MVb!i>UGxK-Dw>c%!|TLr~hujP-5>bWX$ zFO;9djarT>DyePsAzvPfxx6Q-6nsna`sF_=Vm2z0ujrGcgz&9Hs%k>`ckU-;yWci! z@K8RXd|N1X^~B+UUT!~I)pMPTTl^mRhW@>jhObKyg#lXVJ?U&%7ovQs7|_3y<)Nm6 zz7T#9KKIW0$`f0Y&q7*0zc^$r?Ne-Zd*j)<>JL$@7?Y&HMd62{X;J)PoE8rUG6<`+ z)nYmiP084nVr$i}y$E-uUom5Bk^~hdqnIFETnF@-xByl?XN3$T^Ie+BSO1yi-~$rM?{N#n;F>lu^%K*=T?g&n;F>lvF|j*Nq_3*9fZhq zHw#jTK%Mw4lG|>jyyLym%t^P-Pw8X?e6T(9A`5= z!!TAi;_)=&Jk1%?C1aa_(fE_b29vV-)#+4qUH_S+6K4Etn1AMp;JnB=-yZjjTT;rl zBV~S9)1Lo(gl7~A1<|ssn}`rk5FOV~LFv9r@?KV1eoKqa1yBF}T zj_EiTNlm*85`UTWVW(V(TiQ&UE^1%kHocft%H{h>!aN%s5>qi%FQaMO6*qRdd1OC7 z#WJTfNK4?IxxktqA;i4mLW`5~HxbrCkitOv)9)t?EdaAZK8xB81vZsTB;EqBzAlR4 z0bOhzT0-UKAN0tVG2fxM&=N>=7oQEv4nIwolU07wT50;jUV7@OTUI4VN|dZ9ax-jk z@bZ|#R`kl4+9A%5Se#`t*Hl#Vu#ryGJy5F+dOaI+(O7JYI$S`O7EfUgVvnWL74aRI mBS9GW7A>$-f)HKg7w`*COf1xeLCWRObC$bY_L#OICM36k$m~}>X#045sl$ymZ14dCEI8mgo#GDRAm({> zQd)R#;i!CC1#&E*D} zy#vK1e4%lK&wn_8cJ}UV&O~PPOY4<{!hVfxT6emJoZg7vVsM%+X9zP4j5 zr2(P{ZT*(BC}D8GwHVbhg*v0)Qx2nuQ9j3o7N1^Rz3a);L=ocpgy^GKKXFNwa8(L; z)Vmo)JJ8d8SBX&0e|&z?T9q)j&@#3+b!DnKT@D<_=6|@*GH7&=m}vqX5Jw=40S8=b zQ!Rt3fudyMHrq~Nbc{7P;6ejh|K55wL_31C!F59k^d{OVDt!2Waea*8;KrEUAtD1v zx4%@FID~dW2cT&Ex7R0NyxRIk8~}2LFkyq3w%?-i?PMwnTBrW}b-?}*gz#Vf0=@xl XP7RTPVGhtk00000NkvXXu0mjf3>x@J diff --git a/app/images/stopped@2x.png b/app/images/stopped@2x.png index 776f0c8aeae5ab5ccf84a46e6a16d81f3e170670..0c19121c59766f8efbca12a57a09373706e07159 100644 GIT binary patch delta 1161 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 JPDHLkV1j73CjbBd diff --git a/app/images/wavy-white.png b/app/images/wavy-white.png new file mode 100644 index 0000000000000000000000000000000000000000..066b750d3545a4af66785373cfce0ba2fd0ca25e GIT binary patch literal 466 zcmV;@0WJQCP)200001b5ch_0Itp) z=>Px$j7da6R5%f>l{-rVK@^3ZKoG@3ECo9o#m-=7V`-HX3;qL(Smbx4Or6q{f?%b+ zjil5{3vI;4DxgR->vwkN%Eau%NA|$CGjr$8$-H*s<|0bdv`SaqQ=?qI2F#h zp^r~5Fl@jb{3PWxrn-?(fp*|@O}z!1u;fu)G4+`=rc!85hZ(+6Z$=Xttv;WlT&X=_ zN>EFdl(aXI5D6&PkD&;*f<_f=51Wzk(J*7RDoGwX;A|;L7RvXjcyFSXUt3{&oS1>G zj@0FfjPmO5pMFf&kEole?xEzE@d@0+3%tWKoWlWFex5!4yztGMPH`FR1gTC{pWf|p zue?QES56wpbOlCgp({9obyxr$;07FmW-n>>9asy^Y43wH$l_FrW>9c=O{A|nr^aV4X=_BpT=zGcX|NVFJ2`LiUoE?GYzyJUM07*qo IM6N<$g8N?8zyJUM literal 0 HcmV?d00001 diff --git a/app/images/wavy-white@2x.png b/app/images/wavy-white@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d9a4287c4aaf72b6899c3a54eaf2d8253ca3798 GIT binary patch literal 1049 zcmV+!1m^pRP)?00001b5ch_0Itp) z=>Px&(@8`@R9FesnLB6{Q51%=KG0wkd=TF@D?vmN6jab6!NNi?l2Usii=}NCh=q-1 zM9@wU#7fhcLP#n_Ax$0RX_cu?ZPYf&r0qeerGV+!2`?bY zzEU^{yV8oQZO})3lT5xk)9U%{=%A5I3UYz+A=r^g&@@)xKto!t$!GeJrLpHKkk?3D zG(K}Br4?v$h?$p4m@Zm4?wp*W>_{qs42`4-(zYhw%@-IAvE z42^GHRC-`d^Qf@P9R}wf+<*s3(qlGaqtA+m*++7O6GGvhoQ=;XT`mv@S=> zt2^rn$yeZ$LuA7%bf~IE)%C>SibicNz^(4h)~Yd=)Rb*4X+1?!-^^oTIWqDY_~sB< zd6Uu9R?XTtTe4raU@g*t&vD0B{}xlA{iL-~&Sx71m*EPW0PQ{ZgC29@AN+*x@D|>{ zYn&}|%wwZ;zG?)PViuq>8D+nwHd!NC4KPM))bi5l{uU`N*dB$Pe*I>;bPiO{pJQ@dhdAxx8OV+fSs@v zG*9(ty#^0q9$eER{fJlHc0zw{8#jN-!(1RO1YB=*q$KKy|s zo2Ibo9+vvOFza-liS~U|Xdd(!?|rP^36oEqMC&AtAH$^voqkjP9^Qf8N`HW^(iyl3 z2f^AzltKKta~74TvV{a%x=MGTl{<$MO6{4QGasCIt~>cmS*}J6M(Cvb?^9UHBoJ?` zZvu7W6x#X-MgKTFfKRZRxtsQKG)EOKy|n>2RS(_&tuQK&OumpLevTq^0nWlc*bNIX z7vyhq3~ibiPKO!)h=9IeSX;N-yp6GO*03_1o*h!s>+e-02y|n-+y%kviR7-lDas0e z6O|@N+uG`{%L-IRFVFT2(pp@Fy^%@_r0H7n+h;wr_%A&-#wVR%R67Yc>HCvLKqJv~ zgAqS<|0)&#kt}pVFdA78+&N2;Z`yT@K?QnY?LRw)!3LwN1?GP0p(wXWv-x)>8%UZo zg1U8iP{fW%8q#X~eJM>)&DtQYCz!sfR3WRWPv$=xVw;j?!8NMGsa~Pm{`bv)7&Q+z T;Cx{K00000NkvXXu0mjfr`qdc literal 0 HcmV?d00001 diff --git a/app/styles/containers.less b/app/styles/containers.less index 2159209d65..94155a28c3 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -75,21 +75,42 @@ margin: 0px 5px 0px 20px; &.active { - background: @brand-primary; - li { - .name { - color: white; - } - .image { - color: white; - opacity: 0.9; - } + background: @brand-primary; + li { + .name { + color: white; } - color: white; - border-bottom: none; - border-radius: 40px; + .image { + color: white; + opacity: 0.9; + } + } + color: white; + border-bottom: none; + border-radius: 40px; + .state-running { + .at2x('running-white.png', 20px, 20px); + overflow: hidden; + // -webkit-mask-image: -webkit-radial-gradient(circle, white, black); - &:hover { + .runningwave { + position: absolute; + width: 40px; + height: 20px; + left: -20px; + .at2x('runningwave-white.png', 20px, 20px); + // background-repeat: repeat; + -webkit-animation-name: translatewave; + -webkit-animation-duration: 8.0s; + -webkit-animation-iteration-count: infinite; + -webkit-animation-timing-function: linear; + } + } + .state-paused { + .at2x('wavy-white.png', 20px, 20px); + } + .state-stopped { + .at2x('still-white.png', 20px, 20px); } } diff --git a/app/styles/main.less b/app/styles/main.less index 780e59028f..e8bcec4aa9 100644 --- a/app/styles/main.less +++ b/app/styles/main.less @@ -18,7 +18,7 @@ html, body { } ::-webkit-scrollbar { - width: 13px; + width: 10px; } ::-webkit-scrollbar-track { @@ -33,7 +33,7 @@ html, body { background-clip: padding-box; width: 7px; border-radius: 8px; - background-color: rgba(0,0,0,0.2); + background-color: rgba(0,0,0,0.07); } .create-modal { From 155cbd3e232de4c63e49474e753e488399a5a822 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 23 Jan 2015 14:56:38 -0800 Subject: [PATCH 02/10] Added missing image. --- app/images/runningwave.png | Bin 0 -> 347 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 app/images/runningwave.png diff --git a/app/images/runningwave.png b/app/images/runningwave.png new file mode 100644 index 0000000000000000000000000000000000000000..d65fc18e1397cda8516853e1a3786f1d84c0537a GIT binary patch literal 347 zcmV-h0i^zkP)Px$6-h)vR5%gskiAL+K@^3*t3(S?v{0}T0}K8&YLmv=H;|xq?t;F6Z=k6y1PjH^ zCaow~*=uQ|g~>t+@dsJ7*{D074J?STh^hB7mos?1?KMyTvu#B;*T*xDJ&K)36QYnv|Mz+=;s#U2$4p;VWzGH<>geFhAr)O?Fxz?4NtY8R0kj z_bkbh12vvW@6`BB&{F-R_fx{L^xRfMMouPpO^d%`@tV^7C|gpvDK*nS`5N$`A6zQC ti}fbs{Rtkul&sC|p(nLP6b^Lfz&9mUPy}DOF6RIM002ovPDHLkV1mN2kzW7+ literal 0 HcmV?d00001 From 5530cc53c62235d60d22d18b0a4f99a675621e36 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 23 Jan 2015 17:19:08 -0800 Subject: [PATCH 03/10] Added tooltips. --- app/ContainerModal.react.js | 6 +++++- app/styles/main.less | 3 +++ app/styles/theme.less | 5 +++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/app/ContainerModal.react.js b/app/ContainerModal.react.js index e454baa9ea..c8778663d0 100644 --- a/app/ContainerModal.react.js +++ b/app/ContainerModal.react.js @@ -5,6 +5,8 @@ var Router = require('react-router'); var Modal = require('react-bootstrap/Modal'); var RetinaImage = require('react-retina-image'); var ContainerStore = require('./ContainerStore'); +var OverlayTrigger = require('react-bootstrap/OverlayTrigger'); +var Popover = require('react-bootstrap/Popover'); var Navigation = Router.Navigation; @@ -109,7 +111,9 @@ var ContainerModal = React.createClass({
- What's an image? + An image is a template which a container can be created from.}> + What's an image? +
{title} diff --git a/app/styles/main.less b/app/styles/main.less index e8bcec4aa9..c1c9e3037a 100644 --- a/app/styles/main.less +++ b/app/styles/main.less @@ -77,9 +77,12 @@ html, body { .question { a { + transition: all 0.3s ease 0s; + cursor: default; color: @gray-lightest; &:hover { color: darken(@gray-lightest, 10%); + text-decoration: none; } } font-size: 10px; diff --git a/app/styles/theme.less b/app/styles/theme.less index 5093a8532c..012ae7c8db 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -12,6 +12,11 @@ h4 { font-weight: 400; } +.popover-content { + color: @gray-normal; + font-size: 13px; +} + // // Buttons // -------------------------------------------------- From ef5a201a9a62ddaad2019246133c340b88608605 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 23 Jan 2015 17:38:27 -0800 Subject: [PATCH 04/10] Added Kitematic to title. --- app/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/app/index.html b/app/index.html index 5b3d4ba12d..a97ba8b788 100644 --- a/app/index.html +++ b/app/index.html @@ -3,6 +3,7 @@ + Kitematic From db1facdd806eaa46905b44af34410fd7b4443d65 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 25 Jan 2015 10:57:51 -0800 Subject: [PATCH 05/10] Added missing modules and fixed merge conflict. --- app/styles/containers.less | 39 -------------------------------------- package.json | 1 + 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/app/styles/containers.less b/app/styles/containers.less index 37b7000149..a2719b89aa 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -84,44 +84,6 @@ padding: 4px 5px; &.active { -<<<<<<< HEAD - background: @brand-primary; - li { - .name { - color: white; - } - .image { - color: white; - opacity: 0.9; - } - } - color: white; - border-bottom: none; - border-radius: 40px; - .state-running { - .at2x('running-white.png', 20px, 20px); - overflow: hidden; - // -webkit-mask-image: -webkit-radial-gradient(circle, white, black); - - .runningwave { - position: absolute; - width: 40px; - height: 20px; - left: -20px; - .at2x('runningwave-white.png', 20px, 20px); - // background-repeat: repeat; - -webkit-animation-name: translatewave; - -webkit-animation-duration: 8.0s; - -webkit-animation-iteration-count: infinite; - -webkit-animation-timing-function: linear; - } - } - .state-paused { - .at2x('wavy-white.png', 20px, 20px); - } - .state-stopped { - .at2x('still-white.png', 20px, 20px); -======= li { border-bottom: none; border-radius: 40px; @@ -152,7 +114,6 @@ .at2x('downloading-arrow-white.png', 20px, 20px); } } ->>>>>>> master } } diff --git a/package.json b/package.json index 52e6f7c3f8..757d5c0888 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "minimist": "^1.1.0", "moment": "2.8.1", "node-uuid": "1.4.1", + "object-assign": "^2.0.0", "open": "0.0.5", "react": "^0.12.2", "react-bootstrap": "^0.13.2", From e9943328ead6ec5c2260a4d8ecdc467987439ea2 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 25 Jan 2015 16:57:27 -0800 Subject: [PATCH 06/10] Fixed button styles. --- app/ContainerDetails.react.js | 8 ++++---- app/ContainerModal.react.js | 2 +- app/styles/containers.less | 4 ++-- app/styles/theme.less | 16 +++++++++++++++- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/app/ContainerDetails.react.js b/app/ContainerDetails.react.js index a126de1f9c..f185a214e8 100644 --- a/app/ContainerDetails.react.js +++ b/app/ContainerDetails.react.js @@ -186,16 +186,16 @@ var ContainerDetails = React.createClass({
- View + View
diff --git a/app/ContainerModal.react.js b/app/ContainerModal.react.js index 8e8c348132..5cda684458 100644 --- a/app/ContainerModal.react.js +++ b/app/ContainerModal.react.js @@ -103,7 +103,7 @@ var ContainerModal = React.createClass({
Create - +
diff --git a/app/styles/containers.less b/app/styles/containers.less index a2719b89aa..9d9e18d59c 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -41,7 +41,7 @@ .create { flex: 1 auto; text-align: right; - .btn { + /*.btn { margin-top: 4px; padding: 4px 7px; font-size: 16px; @@ -51,7 +51,7 @@ top: 3px; left: 1px; } - } + }*/ } } diff --git a/app/styles/theme.less b/app/styles/theme.less index da284b8a67..0c16fbaffb 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -70,7 +70,9 @@ h4 { .btn { .icon-dropdown { &.icon:before { - top: 7px; + position: relative; + font-size: 10px; + top: -2px; margin-left: 0px; margin-right: 4px; } @@ -99,6 +101,14 @@ h4 { margin-right: 5px; } + .icon-dropdown { + &.icon:before { + font-size: 10px; + position: relative; + top: -2px; + } + } + .icon { position: relative; font-size: 16px; @@ -116,6 +126,10 @@ h4 { box-shadow: none; outline: none !important; } + + &.only-icon { + padding: 6px 7px 6px 7px; + } } // Apply the mixin to the buttons From cbc0518f2aca55f543a6634174fbb13cb1f46033 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 25 Jan 2015 17:03:09 -0800 Subject: [PATCH 07/10] Fixed tab style. --- app/styles/theme.less | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/styles/theme.less b/app/styles/theme.less index 0c16fbaffb..a9c54373eb 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -67,6 +67,11 @@ h4 { } .btn-group { + &.tabs { + .btn { + padding: 6px 14px 6px 14px; + } + } .btn { .icon-dropdown { &.icon:before { @@ -98,7 +103,7 @@ h4 { position: relative; top: -4px; margin-left: 5px; - margin-right: 5px; + margin-right: 2px; } .icon-dropdown { From 0a6b77673902191557220df1232a6d53c8de31cc Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 25 Jan 2015 17:04:02 -0800 Subject: [PATCH 08/10] Button content spacing. --- app/styles/theme.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/styles/theme.less b/app/styles/theme.less index a9c54373eb..f860fcd4da 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -103,7 +103,7 @@ h4 { position: relative; top: -4px; margin-left: 5px; - margin-right: 2px; + margin-right: 5px; } .icon-dropdown { From cb5f10a05678db8f5235015c18d527b92dffaf80 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 25 Jan 2015 22:28:49 -0800 Subject: [PATCH 09/10] Added delete container functionality. --- app/ContainerDetails.react.js | 39 ++++++++++++++++++++++++++++----- app/ContainerStore.js | 41 +++++++++++++++++++++++++++++++++++ app/styles/containers.less | 12 +++++----- app/styles/theme.less | 16 ++++++++++++++ 4 files changed, 96 insertions(+), 12 deletions(-) diff --git a/app/ContainerDetails.react.js b/app/ContainerDetails.react.js index f185a214e8..e7d568f6c2 100644 --- a/app/ContainerDetails.react.js +++ b/app/ContainerDetails.react.js @@ -102,6 +102,14 @@ var ContainerDetails = React.createClass({ }); }); }, + saveEnvVar: function () { + console.log('Saved Vars!'); + }, + deleteContainer: function () { + var container = this.props.container; + var name = container.Name.replace('/', ''); + ContainerStore.remove(name); + }, render: function () { var self = this; @@ -135,6 +143,21 @@ var ContainerDetails = React.createClass({ button = View; } + var name = this.props.container.Name; + var image = this.props.container.Config.Image; + + var envVars = this.props.container.Config.Env.map(function (keyval) { + var keyvalTokens = keyval.split('='); + var key = keyvalTokens[0]; + var val = keyvalTokens[1]; + return ( +
+ + +
+ ); + }); + var body; if (this.props.container.State.Downloading) { body = ( @@ -145,7 +168,7 @@ var ContainerDetails = React.createClass({ } else { if (this.state.page === this.PAGE_LOGS) { body = ( -
+
{logs}
@@ -153,8 +176,17 @@ var ContainerDetails = React.createClass({ ); } else { body = ( -
+
+

Container Detail

+ +

Environment Variables

+
+ {envVars} +
+ Save +

Delete Container

+ Delete Container
); @@ -175,9 +207,6 @@ var ContainerDetails = React.createClass({ 'active': this.state.page === this.PAGE_SETTINGS }); - var name = this.props.container.Name; - var image = this.props.container.Config.Image; - return (
diff --git a/app/ContainerStore.js b/app/ContainerStore.js index 05a9c84998..de5055cc82 100644 --- a/app/ContainerStore.js +++ b/app/ContainerStore.js @@ -130,6 +130,47 @@ var ContainerStore = assign(EventEmitter.prototype, { }); }); }, + rename: function (name, newName, callback) { + var existing = docker.client().getContainer(name); + var existingImage = existing.Image; + var self = this; + existing.remove(function (err, data) { + docker.client().createContainer({ + Image: existingImage, + Tty: false, + name: newName, + User: 'root' + }, function (err, container) { + if (err) { + callback(err, null); + return; + } + container.start({ + PublishAllPorts: true + }, function (err) { + if (err) { + callback(err); + return; + } + self.fetchContainer(newName, callback); + }); + }); + }); + }, + remove: function (name, callback) { + var existing = docker.client().getContainer(name); + existing.kill(function (err) { + if (err) { + console.log(err); + } else { + existing.remove(function (err) { + if (err) { + console.log(err); + } + }); + } + }); + }, _createPlaceholderContainer: function (imageName, name, callback) { var self = this; this._pullScratchImage(function (err) { diff --git a/app/styles/containers.less b/app/styles/containers.less index 9d9e18d59c..54a17ebbbb 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -329,25 +329,23 @@ width: 300px; } - .details-logs { + .details-panel { flex: 1; overflow: auto; - h4 { - font-size: 14px; - margin-top: 16px; - margin-left: 40px; - } .logs { -webkit-user-select: text; font-family: Menlo; font-size: 12px; - padding: 18px 45px; + padding: 18px 35px; color: lighten(@gray-normal, 6%); white-space: pre-wrap; p { margin: 0 6px; } } + .settings { + padding: 18px 35px; + } } } } diff --git a/app/styles/theme.less b/app/styles/theme.less index f860fcd4da..79dfb38d89 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -17,6 +17,22 @@ h4 { font-size: 13px; } +input[type="text"] { + &.line { + border: 0; + border-bottom: 1px solid @gray-normal; + color: @gray-normal; + font-weight: 300; + &:focus { + outline: 0; + } + &::-webkit-input-placeholder { + color: #ddd; + font-weight: 300; + } + } +} + // // Buttons // -------------------------------------------------- From 04cfc3c261152e9684c563e84c337a220781b032 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 26 Jan 2015 16:58:28 -0800 Subject: [PATCH 10/10] Styled environment variables settings section. --- app/ContainerDetails.react.js | 119 ++++++++++++++++++++------ app/ContainerDetailsSettings.react.js | 0 app/ContainerStore.js | 62 +++++++++----- app/ContainerUtil.js | 13 +++ app/styles/containers.less | 32 +++++++ app/styles/theme.less | 22 ++++- 6 files changed, 198 insertions(+), 50 deletions(-) create mode 100644 app/ContainerDetailsSettings.react.js create mode 100644 app/ContainerUtil.js diff --git a/app/ContainerDetails.react.js b/app/ContainerDetails.react.js index e7d568f6c2..388b16efe6 100644 --- a/app/ContainerDetails.react.js +++ b/app/ContainerDetails.react.js @@ -3,6 +3,7 @@ var $ = require('jquery'); var React = require('react/addons'); var Router = require('react-router'); var ContainerStore = require('./ContainerStore'); +var ContainerUtil = require('./ContainerUtil'); var docker = require('./docker'); var exec = require('exec'); var boot2docker = require('./boot2docker'); @@ -22,22 +23,28 @@ var ContainerDetails = React.createClass({ getInitialState: function () { return { logs: [], - page: this.PAGE_LOGS + page: this.PAGE_LOGS, + env: {}, + pendingEnv: {} }; }, componentWillReceiveProps: function () { - this.setState({ - page: this.PAGE_LOGS - }); - ContainerStore.fetchLogs(this.getParams().name, function () { - this.updateLogs(); - }.bind(this)); + // active container changes + if (this.state.page === this.PAGE_SETTINGS) { + + } + console.log(this.props.container); + this.init(); + }, + componentWillMount: function () { + this.init(); }, componentDidMount: function () { ContainerStore.on(ContainerStore.SERVER_PROGRESS_EVENT, this.updateProgress); ContainerStore.on(ContainerStore.SERVER_LOGS_EVENT, this.updateLogs); }, componentWillUnmount: function () { + // app close ContainerStore.removeListener(ContainerStore.SERVER_PROGRESS_EVENT, this.updateProgress); ContainerStore.removeListener(ContainerStore.SERVER_LOGS_EVENT, this.updateLogs); }, @@ -52,6 +59,15 @@ var ContainerDetails = React.createClass({ } this._oldHeight = parent[0].scrollHeight - parent.height(); }, + init: function () { + this.setState({ + page: this.PAGE_LOGS, + env: ContainerUtil.env(ContainerStore.container(this.getParams().name)) + }); + ContainerStore.fetchLogs(this.getParams().name, function () { + this.updateLogs(); + }.bind(this)); + }, updateLogs: function (name) { if (name && name !== this.getParams().name) { return; @@ -78,7 +94,7 @@ var ContainerDetails = React.createClass({ page: this.PAGE_SETTINGS }); }, - handleClick: function (name) { + handleView: function () { var container = this.props.container; boot2docker.ip(function (err, ip) { var ports = _.map(container.NetworkSettings.Ports, function (value, key) { @@ -102,13 +118,45 @@ var ContainerDetails = React.createClass({ }); }); }, - saveEnvVar: function () { - console.log('Saved Vars!'); + handleSaveEnvVar: function () { + var $rows = $('.env-vars .keyval-row'); + var envVarList = []; + $rows.each(function () { + var key = $(this).find('.key').val(); + var val = $(this).find('.val').val(); + envVarList.push(key + '=' + val); + }); + console.log(envVarList); }, - deleteContainer: function () { + handleAddPendingEnvVar: function () { + var newKey = $('#new-env-key').val(); + var newVal = $('#new-env-val').val(); + var newEnv = {}; + newEnv[newKey] = newVal; + this.setState({ + pendingEnv: _.extend(this.state.pendingEnv, newEnv) + }); + $('#new-env-key').val(''); + $('#new-env-val').val(''); + }, + handleRemoveEnvVar: function (key) { + var newEnv = _.omit(this.state.env, key); + this.setState({ + env: newEnv + }); + }, + handleRemovePendingEnvVar: function (key) { + var newEnv = _.omit(this.state.pendingEnv, key); + this.setState({ + pendingEnv: newEnv + }); + }, + handleDeleteContainer: function () { var container = this.props.container; var name = container.Name.replace('/', ''); - ContainerStore.remove(name); + ContainerStore.remove(name, function (err) { + console.error(err); + }); }, render: function () { var self = this; @@ -145,15 +193,21 @@ var ContainerDetails = React.createClass({ var name = this.props.container.Name; var image = this.props.container.Config.Image; - - var envVars = this.props.container.Config.Env.map(function (keyval) { - var keyvalTokens = keyval.split('='); - var key = keyvalTokens[0]; - var val = keyvalTokens[1]; + var envVars = _.map(this.state.env, function (val, key) { return ( -
+
+ +
+ ); + }); + var pendingEnvVars = _.map(this.state.pendingEnv, function (val, key) { + return ( +
+ + +
); }); @@ -175,18 +229,29 @@ var ContainerDetails = React.createClass({
); } else { + body = (
-

Container Detail

+

Container Detail

-

Environment Variables

+

Environment Variables

+
+
KEY
+
VALUE
+
{envVars} + {pendingEnvVars} +
+ + + +
- Save -

Delete Container

- Delete Container + Save +

Delete Container

+ Delete Container
); @@ -215,16 +280,16 @@ var ContainerDetails = React.createClass({
- View + View
diff --git a/app/ContainerDetailsSettings.react.js b/app/ContainerDetailsSettings.react.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/ContainerStore.js b/app/ContainerStore.js index de5055cc82..1a3720dd6f 100644 --- a/app/ContainerStore.js +++ b/app/ContainerStore.js @@ -6,6 +6,7 @@ var Convert = require('ansi-to-html'); var convert = new Convert(); var docker = require('./docker'); var registry = require('./registry'); +var ContainerUtil = require('./ContainerUtil'); var $ = require('jquery'); var _ = require('underscore'); @@ -158,18 +159,44 @@ var ContainerStore = assign(EventEmitter.prototype, { }); }, remove: function (name, callback) { + var self = this; var existing = docker.client().getContainer(name); - existing.kill(function (err) { - if (err) { - console.log(err); - } else { - existing.remove(function (err) { - if (err) { - console.log(err); - } - }); - } - }); + if (_containers[name].State.Paused) { + existing.unpause(function (err) { + if (err) { + callback(err); + return; + } else { + existing.kill(function (err) { + if (err) { + callback(err); + return; + } else { + existing.remove(function (err) { + if (err) { + callback(err); + return; + } + }); + } + }); + } + }); + } else { + existing.kill(function (err) { + if (err) { + callback(err); + return; + } else { + existing.remove(function (err) { + if (err) { + callback(err); + return; + } + }); + } + }); + } }, _createPlaceholderContainer: function (imageName, name, callback) { var self = this; @@ -272,7 +299,7 @@ var ContainerStore = assign(EventEmitter.prototype, { container.Name = container.Name.replace('/', ''); // Add Downloading State (stored in environment variables) to containers for Kitematic - var env = _.object(container.Config.Env.map(function (e) { return e.split('='); })); + var env = ContainerUtil.env(container); container.State.Downloading = !!env.KITEMATIC_DOWNLOADING; container.KitematicDownloadingImage = env.KITEMATIC_DOWNLOADING_IMAGE; @@ -413,16 +440,7 @@ var ContainerStore = assign(EventEmitter.prototype, { }, sorted: function () { return _.values(_containers).sort(function (a, b) { - var active = function (container) { - return container.State.Running || container.State.Restarting || container.State.Downloading; - }; - if (active(a) && !active(b)) { - return -1; - } else if (!active(a) && active(b)) { - return 1; - } else { - return a.Name.localeCompare(b.Name); - } + return a.Name.localeCompare(b.Name); }); }, recommended: function () { diff --git a/app/ContainerUtil.js b/app/ContainerUtil.js new file mode 100644 index 0000000000..479ea1077b --- /dev/null +++ b/app/ContainerUtil.js @@ -0,0 +1,13 @@ +var _ = require('underscore'); + +var ContainerUtil = { + env: function (container) { + return _.object(container.Config.Env.map(function (env) { + var i = env.indexOf('='); + var splits = [env.slice(0, i), env.slice(i + 1)]; + return splits; + })); + } +}; + +module.exports = ContainerUtil; diff --git a/app/styles/containers.less b/app/styles/containers.less index 54a17ebbbb..ef62d65a91 100644 --- a/app/styles/containers.less +++ b/app/styles/containers.less @@ -347,6 +347,38 @@ padding: 18px 35px; } } + + .env-vars-labels { + width: 100%; + font-size: 12px; + color: @gray-lightest; + margin-left: 5px; + margin-bottom: 5px; + .label-key { + display: inline-block; + margin-right: 30px; + width: 20%; + } + .label-val { + display: inline-block; + width: 40%; + } + } + .env-vars { + margin-bottom: 20px; + .keyval-row { + margin-bottom: 5px; + } + input { + margin-right: 30px; + &.key { + width: 20%; + } + &.val { + width: 40%; + } + } + } } } } diff --git a/app/styles/theme.less b/app/styles/theme.less index 79dfb38d89..91ef1f4278 100644 --- a/app/styles/theme.less +++ b/app/styles/theme.less @@ -5,6 +5,10 @@ @import "bootstrap/variables.less"; @import "bootstrap/mixins.less"; +h3 { + font-size: 14px; + color: @gray-darkest; +} h4 { font-size: 13px; @@ -20,11 +24,14 @@ h4 { input[type="text"] { &.line { border: 0; - border-bottom: 1px solid @gray-normal; + border-bottom: 1px solid @gray-lightest; color: @gray-normal; font-weight: 300; + padding: 5px; + transition: all 0.1s; &:focus { outline: 0; + border-bottom: 1px solid @brand-action; } &::-webkit-input-placeholder { color: #ddd; @@ -115,6 +122,13 @@ input[type="text"] { height: 32px; cursor: default; + &.small { + height: 22px; + .icon { + font-size: 10px; + } + } + .content { position: relative; top: -4px; @@ -150,6 +164,9 @@ input[type="text"] { &.only-icon { padding: 6px 7px 6px 7px; + &.small { + padding: 2px 5px 3px 5px; + } } } @@ -157,6 +174,9 @@ input[type="text"] { .btn-action { .btn-styles(@brand-action); } +.btn-positive { + .btn-styles(@brand-positive); +} .btn-default { .btn-styles(@btn-default-bg); } .btn-primary { .btn-styles(@btn-primary-bg); } .btn-success { .btn-styles(@btn-success-bg); }