From d9aa828dd00260a70392169e62a0953caa642752 Mon Sep 17 00:00:00 2001 From: Allen Servedio Date: Sun, 15 Mar 2015 00:48:47 -0400 Subject: [PATCH 01/34] Altering the repo name to be a link that takes you to the Docker Hub page for it. Tried to follow styling for other link on card. --- src/ImageCard.react.js | 14 ++++++++++++-- styles/new-container.less | 6 ++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index b132aec25f..7739d11963 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -5,6 +5,7 @@ var ContainerStore = require('./ContainerStore'); var metrics = require('./Metrics'); var OverlayTrigger = require('react-bootstrap').OverlayTrigger; var Tooltip = require('react-bootstrap').Tooltip; +var util = require('./Util'); var ImageCard = React.createClass({ getInitialState: function () { @@ -40,6 +41,15 @@ var ImageCard = React.createClass({ var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); $tagOverlay.fadeOut(300); }, + handleRepoClick: function () { + var $repoUri = 'https://registry.hub.docker.com/' + if (this.props.image.is_official) { + $repoUri = $repoUri + "_/" + } else { + $repoUri = $repoUri + "u/" + } + util.exec(['open', $repoUri + this.props.image.name]); + }, render: function () { var self = this; var name; @@ -58,7 +68,7 @@ var ImageCard = React.createClass({
{namespace}
{this.props.image.name}}> - {repo} + {repo}
); @@ -67,7 +77,7 @@ var ImageCard = React.createClass({
{namespace}
{this.props.image.name}}> - {repo} + {repo}
); diff --git a/styles/new-container.less b/styles/new-container.less index 0a201ae8f3..1956f38295 100644 --- a/styles/new-container.less +++ b/styles/new-container.less @@ -186,6 +186,12 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + text-decoration: underline; + &:hover { + background-color: @brand-action; + color: white; + border-radius: 20px; + } } } .description { From f589d2c65d35aae82bfbb8407312440ce043360a Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 24 Mar 2015 11:25:51 -0700 Subject: [PATCH 02/34] Cleaner icons. --- images/button-restart.png | Bin 1618 -> 1395 bytes images/button-restart@2x.png | Bin 3670 -> 3144 bytes images/button-terminal.png | Bin 1467 -> 1289 bytes images/button-terminal@2x.png | Bin 3237 -> 2704 bytes images/button-view.png | Bin 1753 -> 1511 bytes images/button-view@2x.png | Bin 4026 -> 3382 bytes styles/right-panel.less | 7 +++---- 7 files changed, 3 insertions(+), 4 deletions(-) diff --git a/images/button-restart.png b/images/button-restart.png index 69f030d3ec36b28c818e1d656827d39bdf7d7465..a43a41994ceb3ad812f64b35f57ee67c89d17478 100644 GIT binary patch literal 1395 zcmV-(1&sQMP)Px)ElET{R9Fe^Sba=fMG&9ed&gb*>IZlnaC{thCT(n@CZ$aiYd|r2Txn}HSd(Hy zs@7nljfp14k6>#2$B#cvnwZp7P1Tr2a&UJhRSapHLR%ASHE7`u4hnYfUnT!33CG1c-wYKFkt43fIR@glb*a z7J@?-Vx*d0)D$U5v#ffBaQ+Mj=pqCe*L=dRaK28T1vaG+(uAuk1Jo??lu zJ=OLz((ppP0GzHU-*X^i2=X zVL+V$bw6(T?rx9GD~;zib!M%xKI#!zczB0Bc1)b4BBKmmh~%q zsR_xvot{JDoscL0tXOMJ@Eo8-)#_oK4^l$%wKO>{hD=x5mWCfOlfI$c)Z*l;p9llA zP4hWZ8PHtCnw{pwxY@uMc|k6`ot{jPUb$|Jja*&>>t?r5(CH)zK^jzugc{ztepJee zK2n|kn>#pINkO^DfPWPB=FNZ|jU#mZ9jB*0oD53b(fFI;S3Zw>1Fp2Y@B@J_<&cf*_ocBwb z>;+gH?{NAC%c+?@YlXD)7{3`F%+mf5Z%!g=@006NPL}!0q;#W*^x@2mC-Pl4QOfkJ-Ldav}&*{I$SoOi=xtDt^n0> z%92Pc9$k|AbQZ68RL3bxA|>}ICvndHb3+~HgwHuR;P1q-1W^+6(2US@Jg}vr8Fjf! zh7C{fcDw*algUYba*s;MW$ssirg{TbJo>-&sKObH5(<0q|5K`+u&6$)!)Ck?<}E6u zVNU;XcKKtw5Nt}W3>w`@hisCZ3DwvxB^5-0e*oYr-hyxF{jC51002ovPDHLkV1lLd BoH_si literal 1618 zcmV-Y2CeytP)Px*3`s;mR9FecS9@$zRT%%yx%c+5wtJPW+Zfy04gzdU5r%|C2*waMUXs9!LJUC! z1;xL_1SJ_p0wE9u&4Lkv7$CX;4)-b>q6xlX&n*^5U+jf` zNz;42=kI*ye&6{nGF!T;DMc6HeC=d#?yQwgF zr?IL%6J!2EK;V`LIeND!<-D=N`V>NtMnrFKG?2KlDCqz*d`4E{Fg1EbvYPd5k8?JWillM8Zd#7iIRy>qx{$5{xOoqy!U+bQohj#h@mLYN4!*8)}TG@4`@> zMA9?YSeL1JTsU>k#y*|ERi>-(0h1b+YcRKWa@_m@t-x;u4lRR{AEPEKsxVUU$MKET z)&&|Kt(g!btSe4e#TFTqXq?iY4@JP%Ard&<>77yD;hCf@n6}ALV}1Wlq2WkCKKOsk zGpQc0eNV6APkfxC)mP3*h-YWS78b2eUNhG?+yn1P&f+P)!P zz;mxWp9qPH;k#9^Ht@}?IJKL=jA?cDePa%i0@4c@cAcCZr_iy7krHc7aQy{6dlg`{ z$zod=@G~Zbqv7atZx~~g{}e~S_rw1mx;#*8^};XRK2WheWW{i>DnkwPk{;I4LtQ0@ z;DgCp?UsiA-HchyeynSak}@i-CX8^#dZRk*hWFhbfE|AhKwcaV$MWN#bb2hTUDTw}-T6e)b(=nOXVuNS8&wJM%lDlbM2GM1+=FHKWCxC#e_8(;u--gLr# zmbv&ag`{G~dN@B8%33{eqc3zyd(oian2H}{*drPg>+z2Wr6xaU)PCJA4}q!<5AZCp z3sV%(zyJ(L6!H^7_Tlf9vl0cUXF5}2ABAFIK0Smc%1%d}NsmO6(^UUn!!qC=)+`VG z<${|I2`={d!U7EJel`PniRlEB+$9(|H15Tv`%aEFS2JTluJmB4=x{rGCHPwA^K5#a4_{mkExll?2<;T)6KD zd9lJU4&QasGgddXxmjsMpsn=|S6-dHbi{zd8K#%DsPpPcaIq6!F6_{wo@@H#qoxSH+v&%bNq_tKL zkvD0q=$I8P#+bq)yJJIfT-SZIQljyeYK6=1boZKHS)RO@j zh{V3Fjk;bOhgS}}I5Jp3ju6`Fl;|xVA>Z9@Zn+HWXNF$h0UzxDZ(d`PsZ?OS Qe*gdg07*qoM6N<$f-&>~(*OVf diff --git a/images/button-restart@2x.png b/images/button-restart@2x.png index c710010d3589d4b3f2870502a3edbec352861ca4..30c4f26e01bafd3c216bd8f25c56d5db6c5b5a60 100644 GIT binary patch literal 3144 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 diff --git a/images/button-terminal.png b/images/button-terminal.png index e64a22aa5eadaaeed7c0a31c56f6609f1b0236d9..b317d67bffc0c77e11c2d9252875510b7eb7b5bc 100644 GIT binary patch literal 1289 zcmV+k1@`)hP)Px(!%0LzR9Fe^SZhpNMHD_W_rh*@w9>-v0t>Pa6RIZq18RKKq*|lPhSnN`{wQrs zRE$5=nCKt1S)=~)5&zbhR57t>e>4(ccbl|gjF^h3F&eFrU0w_9UhoA=S%iC!XWCq{ zyY36Rw*WA_tD1V}SexyF z?l>D2fXih0JOYao*ax!76_xJ{DEGJnisI^v-nuTsz5&@CoJCh)_U(1)ZAkd|a0xm4 z)g6dExDkC3S$AMI;_RPp5&HC2jA@R>#v_Or9`RVuZp6cMd)*~X!`C>M-xB(U0VTtS z0N5uwNS8l$w<{R?z}`Dquk-TJgtmGL7~JJN9ok_GP+DUIVxJm~f2M;8wOI#I#V<^< zY52yz>D@X%7Zp*ZO?3{+EA|@#)V8O&it^;r*b|OKGLW#>_Nj(=v_z8oE~l*I$t-Y6TNjkGBT#aa?=AndK_yVAY-|G9(B3p;|!V!c0NpK7y5 zgvGKN)gHoy`@wV5+M7d^stEX=6puGsK29DZLbC*Fw+=LUu1J0CF@fn(GWNbOIO?hY zE#2^Vo8<@MJ(bSa$09?}8g-9+bNov~Hj{9qt!N)|4lgyG7&YsT*Go;3`Bh}B8+<;^ zFrcIDVq@X=vaS5x^#T;~P5sL4!10lPmzUlXW5a-wZCqVi>;%T1b^2#t5Y7s1qBf8v z_zF}wI(e{hTId-G6vhrY{!Yv%c5#l+5!hpeECW$(F=0n0hY)CNAFB4 zFX2y`q4Ya zSXsfh*C!ivuQw^T5qYAWx22lYBPc6jCO{}O^av-EICGS|_oFZ7WOmfMPGu>-sn(PBqbMhzAihr^VjifucmJ<7u+bRe|m6iS+; zs~rHk4Stxw7Ujs0WIJzHTVWT%?Uvv33X;Hosfnk`S+#^%00000NkvXXu0mjfCaP$F literal 1467 zcmV;s1w{IZP)Px)bxA})R9FecS9@$zRT%%yx##v_Tgp~gSsB~f4gw7D0RvME>9pKw^k8l*b0ny}Fjc)~(Nb&+(kiChgjl zwj25-?LFsv{?2#K{myrh)7{;`7`g=i6Cp$=H($KI32K%oBSI*1d$x}#{0{`q2G2{5 zx{l&>p)k*)EuF$6mm#oHf^fPx1Q@#PIO$#9vTR~~>B;UVh=evU#$=|z&XyGgx10^# zI{+aW0S(-CS!>GNo#l*?Ey8J(DSKM03a>jGyVn7rnE))W*?;~msIFF>ZtpH&KpC)} z7FWS%_LChY7?TeHK}eRU*CVK;q`Ai3hmhQ$k6?%pOtbE(+`` zgw!IzV~FXRT@$zR;W#m;Oe#^8=;w+W{X%Ba&^947OXx5J*GdN}WT7Vj3LfT}8k{0r zs4{v`RbdCgXsX~zGApGjKHR#zZw1fH3#BBWvg;QOTxwW0)X~xRgTl|fl_wKl?hhp;h z=a^?wKiT-MMMsW(Qf{==FUm8&UaXG+jE@T@f?;)$4h~hAO?#g-*-8y$@0_#V{lJe# zf+C+JF@`H-GdDb<1qs{pgb3qK05 z&f)ehi}}gjW6T488YK42n|8hS-vUgo`)Y z^HEZ)@pbIq{Ss)47^_arPJlZmJj92}bP!=EPXXz;wsyW`)5 zA#YsTG!l9r1A0RN)+KmC(b4GH%@~dj>L{$8$Yd*#$lF}Mor4MVDXF*ghF^j2+d{B1 zi^48q2vQm2tso-4@NWU&O~8>Mc5eR_=k8s-crVOb&_wD8C~V$OK33ZvOc0#)gxEKK z1rmNY{m}#+G3g2_j2HC>0u|v+=dIk}4OxX1cD2b*XD`T4JUVUs>iBMf861Yh%GAmE zxBJzEkTZGp9!^btD)3Hw5F6p!xY+6Th^96t>Q||9ye$}6U!v2+I}k5UDtfJ0pNgHt ztLqE}dR6#Z2ng?T^k44iiYGqr9MUQoag1lRzQI&1)>0<}H)dl^j z!aW+0u}J*e+HQKbT*i16|L`j37e_G`>^B?W` V30gJcPQ?HK002ovPDHLkV1h^}&{hBd diff --git a/images/button-terminal@2x.png b/images/button-terminal@2x.png index be2c92fa245660f65be17d99abc8a2248a7e7d41..58fb047de0126bc8d63dde28068965eb4c8f7f17 100644 GIT binary patch literal 2704 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 KMNUMnLSTY{P&Tpv literal 3237 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 XCzl6m+ diff --git a/images/button-view.png b/images/button-view.png index 4d67f928f4b5be36b7333fd19e4eb44eefd8b31a..35368ba068ba13d3d8de28b6251f670ec097b521 100644 GIT binary patch literal 1511 zcmVPx)p-DtRR9Fe^Sbc0$RTMw>zSp&Etnx9sc8tOL`Uf}@HS!@w2vZQd4-h1iLj@82?cc6Ak=9wisj?YioimF+%uKqXt>Bwu7yV_7wrQj&)n#y`Ecq z%iGemu(j}qyGeWRJ@=e*fA75WaqlB=r<=z^T`P93)<9ASka9}+6{hhB48)Iy8kBz~ zfBL@;kufLN)?~FN225}3VbsLn1d5= zP$2adljRS^8~X&Bn$UA?S>NQ zk3EYisS9(dtVITP^s8D0A$*t1TAiHZ?X(IxVO0#Oqfj(+ZC-%dmoJ`;d2;Z=bCrn{ zP_&Zk;VLg$uLmQ!y1Q=SHN|S{#N4wN)6R0qUi4*jyL}+wwplob1GCAj7V%(07S}IR ziP+`x=AJp`VoMXItf7?BN&a!r-V3=MXN0&#<8y%$RafP*uCBu^*J+pIGg7qXa|MLM ztR#b#z>*2sWI7Mc=XOFv)iCexdxcu9*Ole>)&&6$17|7&S|VGl1+|z~moP?N)D=&r zCqv|-E*EEgmuA773Vj}U(%yn;>SMIrF|^d`6d-SGw=9w0I5laEgGbQjd&A|FntM27 zyMr~QH{FJi3Jl8Q#O04R0;f*|-18cB#kuGezZy-j;fF5Ol!yP*M=+4SBZO>b0Cl0h zcKD<+AAQsnIJNJml*1a7PY ze!u9OuCGRe3bhAoY#0yFl&b9jC8C%Q4{EV+!vYa_qqQB!V3sUt6~VrXZeYmZ9n)t0`FpSM84FX+ETSOm~VxeZei76RUmY3oqe#f$r4=Tf12Ov?&%4ENL~90Tk$ zst~^yN?JOKXHx6@ghc+1obI>=p6X;K^?3#A@0OeM$FO+UfG%2ARU*rBy8%na;avlo5mlPS zX`pG0G9}WqMWyV9*lc9QBXI4gJ_!pT>7vdL_Px*lSxEDR9FecS7}UCR}?JoN=gv4&L_i#{ zy?@@jXMg9M``z; zbH!m6O}z=cbRL03MIc;negvT8n&q5*-h;XEMd|07Cki}SLn#%h1bZILPpHZ$Zr%li zhy)b({hY-7Ol#vsKwBQ< zB|Uylu%7|PW&c(9nAI$<Y<>3@2ihq zd!esJdXmd1u`SdJT+W!R^-hDx7Y);Jhb>y}td8UNkBXVqp%;a1z>|fL|4XmQ>Xq4( z^XJjc#kM&*fvg%nNL-UQOfxt)QB8)bgZWT}bzPDIrA_`xXB&MZ_1WV$x=L)DYjP5g zhWVYJ1D;83ivDw>MmY85SiP|*D=y~4RBbrG&VIolaIkoo298dSF&uc+U`p2s2PXV% zKLpqsPYL4Y8A4Zq7uoB0ZeBov9i`c^`uWM~KC5OMRbb7IGmOv)E5>E5zlMsWv+{ri zIl9!bE>`4b+Y3{kzfSrx*-4^v{aUIiwNzu@?0z=Nbfj3NhnPEU(b8So|Ah0p|d z-Z5e;z)FkNJ~wP9dW&HT_|)QF^^WBzsXiSoVIO?$jci zg(F<*TC=uWTMDIcyG?@PCLh?amI`_{X*kG9Qp3a;0WY(s+AsK3xyajJNpi38+RH3WzNtAf^!|p#j;DhUJup~tTCDY^J&7mr&b<0rGA;U*$+8}LFiW-(* zYlA~I?ylbl?!*I)w1DQD9nn5J@?$OvD}Gs0gc#5L^+>AhcH6FGwG9Qf=Ls)hMAM~x14aa)(a=6 z#so{uoSdlh!aBHA$`V>G1velg2VTl8*m6X z9+8gXW%9*G*g9*|ShVxbVrzoFcP!SOIBK@G`>kE}6HVOdLUK7=0`KEu|Si?Gxc!U`L` z?lu{|XEsBfaqz}d5E6FQm*>!=G)dL|D>vZq6qT*~y=Nsm1LI1jf|NHT~U}IG!sr((2f->}snk(op?;*;e85Ot|1U z5O&;e2x5lZPS24FXTW~2#v_LfNBg{tSwB(%(3qtIslu{q#r9*9>3E`l&!iSJb-bG0$82bC z#F4GeO9Q7Gyq-rsMG44sdyA7Ew&x|Zcjxit1R3^(|JG*1%&{WJEyN$Mv3PN$qC*}p vn>x2ls{)F0=6>zN8?g5E&_y2B>+<{uUk`{E-$v=!00000NkvXXu0mjfmd|7; diff --git a/images/button-view@2x.png b/images/button-view@2x.png index a4455455586c643fe88a1c9ac18ca7e34e86e7b8..fb9acb39faa234c3a10ced714058b42720358f2e 100644 GIT binary patch literal 3382 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 diff --git a/styles/right-panel.less b/styles/right-panel.less index 2d5af45524..a212649e4e 100644 --- a/styles/right-panel.less +++ b/styles/right-panel.less @@ -25,7 +25,6 @@ .action { display: inline-block; position: relative; - top: 10px; &.disabled { opacity: 0.3; } @@ -36,11 +35,11 @@ .btn-label { position: absolute; color: @brand-action; - font-size: 10px; + font-size: 9px; width: 200px; - top: 30px; + top: 43px; &.view { - left: 6px; + left: 7px; //left: 0px; } &.restart { From 379f0280ecef125a2480934ed125cb7ce7f4556c Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 24 Mar 2015 11:27:41 -0700 Subject: [PATCH 03/34] Icon label padding tweak. --- styles/right-panel.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/right-panel.less b/styles/right-panel.less index a212649e4e..384b3e8934 100644 --- a/styles/right-panel.less +++ b/styles/right-panel.less @@ -37,7 +37,7 @@ color: @brand-action; font-size: 9px; width: 200px; - top: 43px; + top: 45px; &.view { left: 7px; //left: 0px; From 835e0d55caf47605acad905833a56547db3a9a4e Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 27 Mar 2015 11:55:56 -0400 Subject: [PATCH 04/34] Volumes off by default unless edit files folder is Clicked. Ability to disable volumes --- src/ContainerHomeFolders.react.js | 63 ++++++++++++++++----------- src/ContainerSettingsVolumes.react.js | 17 ++++++++ src/ContainerStore.js | 51 +++++++--------------- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/src/ContainerHomeFolders.react.js b/src/ContainerHomeFolders.react.js index 513cc974b5..135134a88b 100644 --- a/src/ContainerHomeFolders.react.js +++ b/src/ContainerHomeFolders.react.js @@ -2,19 +2,37 @@ var _ = require('underscore'); var React = require('react/addons'); var RetinaImage = require('react-retina-image'); var path = require('path'); -var exec = require('exec'); +var shell = require('shell'); +var util = require('./Util'); var metrics = require('./Metrics'); var Router = require('react-router'); +var ContainerStore = require('./ContainerStore'); var ContainerHomeFolder = React.createClass({ mixins: [Router.State, Router.Navigation], - handleClickFolder: function (path) { + handleClickFolder: function (hostVolume, containerVolume) { metrics.track('Opened Volume Directory', { from: 'home' }); - exec(['open', path], function (err) { - if (err) { throw err; } - }); + + if (hostVolume.indexOf(process.env.HOME) === -1) { + var volumes = _.clone(this.props.container.Volumes); + volumes[containerVolume] = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume); + var binds = _.pairs(volumes).map(function (pair) { + return pair[1] + ':' + pair[0]; + }); + ContainerStore.updateContainer(this.props.container.Name, { + Binds: binds + }, function (err) { + if (err) { + console.log(err); + return; + } + shell.showItemInFolder(hostVolume); + }); + } else { + shell.showItemInFolder(hostVolume); + } }, handleClickChangeFolders: function () { metrics.track('Viewed Volume Settings', { @@ -23,24 +41,21 @@ var ContainerHomeFolder = React.createClass({ this.transitionTo('containerSettingsVolumes', {name: this.getParams().name}); }, render: function () { - var folders; - if (this.props.container) { - var self = this; - folders = _.map(self.props.container.Volumes, function (val, key) { - var firstFolder = key.split(path.sep)[1]; - if (!val || val.indexOf(process.env.HOME) === -1) { - return; - } else { - return ( -
- -
{firstFolder}
-
- ); - } - }); + if (!this.props.container) { + return false; } - if (this.props.container && this.props.container.Volumes && _.keys(this.props.container.Volumes).length > 0 && this.props.container.State.Running) { + + var folders = _.map(this.props.container.Volumes, (val, key) => { + var firstFolder = key.split(path.sep)[1]; + return ( +
+ +
{firstFolder}
+
+ ); + }); + + if (this.props.container.Volumes && _.keys(this.props.container.Volumes).length > 0 && this.props.container.State.Running) { return (

Edit Files

@@ -51,9 +66,7 @@ var ContainerHomeFolder = React.createClass({
); } else { - return ( -
- ); + return false; } } }); diff --git a/src/ContainerSettingsVolumes.react.js b/src/ContainerSettingsVolumes.react.js index 32e699449e..cb470e75aa 100644 --- a/src/ContainerSettingsVolumes.react.js +++ b/src/ContainerSettingsVolumes.react.js @@ -31,6 +31,21 @@ var ContainerSettingsVolumes = React.createClass({ } }); }, + handleRemoveVolumeClick: function (dockerVol) { + metrics.track('Removed Volume Directory', { + from: 'settings' + }); + var volumes = _.clone(this.props.container.Volumes); + delete volumes[dockerVol]; + var binds = _.pairs(volumes).map(function (pair) { + return pair[1] + ':' + pair[0]; + }); + ContainerStore.updateContainer(this.props.container.Name, { + Binds: binds + }, function (err) { + if (err) { console.log(err); } + }); + }, handleOpenVolumeClick: function (path) { metrics.track('Opened Volume Directory', { from: 'settings' @@ -50,6 +65,7 @@ var ContainerSettingsVolumes = React.createClass({
No Folder Change + Remove ); } else { @@ -57,6 +73,7 @@ var ContainerSettingsVolumes = React.createClass({ {val.replace(process.env.HOME, '~')} Change + Remove ); } diff --git a/src/ContainerStore.js b/src/ContainerStore.js index 121033316f..6f141172a0 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -1,14 +1,12 @@ var _ = require('underscore'); var EventEmitter = require('events').EventEmitter; var async = require('async'); -var path = require('path'); var assign = require('object-assign'); var docker = require('./Docker'); var metrics = require('./Metrics'); var registry = require('./Registry'); var logstore = require('./LogStore'); var bugsnag = require('bugsnag-js'); -var util = require('./Util'); var _placeholders = {}; var _containers = {}; @@ -92,38 +90,22 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { }, _startContainer: function (name, containerData, callback) { var self = this; - docker.client().getImage(containerData.Image).inspect(function (err, data) { + var binds = containerData.Binds || []; + var startopts = { + Binds: binds + }; + if (containerData.NetworkSettings && containerData.NetworkSettings.Ports) { + startopts.PortBindings = containerData.NetworkSettings.Ports; + } else{ + startopts.PublishAllPorts = true; + } + var container = docker.client().getContainer(name); + container.start(startopts, function (err) { if (err) { callback(err); return; } - var binds = containerData.Binds || []; - if (data.Config.Volumes) { - _.each(data.Config.Volumes, function (value, key) { - var existingBind = _.find(binds, b => { - return b.indexOf(':' + key) !== -1; - }); - if (!existingBind) { - binds.push(path.join(util.home(), 'Kitematic', name, key)+ ':' + key); - } - }); - } - var startopts = { - Binds: binds - }; - if (containerData.NetworkSettings && containerData.NetworkSettings.Ports) { - startopts.PortBindings = containerData.NetworkSettings.Ports; - } else{ - startopts.PublishAllPorts = true; - } - var container = docker.client().getContainer(name); - container.start(startopts, function (err) { - if (err) { - callback(err); - return; - } - self.fetchContainer(name, callback); - }); + self.fetchContainer(name, callback); }); }, _createContainer: function (name, containerData, callback) { @@ -137,6 +119,9 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { if (containerData.Config && containerData.Config.Image) { containerData.Image = containerData.Config.Image; } + if (!containerData.Env) { + containerData.Env = containerData.Config.Env; + } existing.kill(function () { existing.remove(function () { docker.client().createContainer(containerData, function (err) { @@ -144,11 +129,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { callback(err, null); return; } - if (containerData.State && !containerData.State.Running) { - self.fetchContainer(containerData.name, callback); - } else { - self._startContainer(name, containerData, callback); - } + self._startContainer(name, containerData, callback); }); }); }); From bada95e9e04af719b8904216f0d1cb9b47a64f37 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 27 Mar 2015 12:12:36 -0400 Subject: [PATCH 05/34] Fix bug related to Env vars --- src/ContainerStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ContainerStore.js b/src/ContainerStore.js index 6f141172a0..cb394f1593 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -119,7 +119,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { if (containerData.Config && containerData.Config.Image) { containerData.Image = containerData.Config.Image; } - if (!containerData.Env) { + if (containerData.Config && containerData.Config.Env) { containerData.Env = containerData.Config.Env; } existing.kill(function () { From 4780087ad444737fbe78687712749fba16e97a41 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 27 Mar 2015 12:30:22 -0400 Subject: [PATCH 06/34] Fix opening directory on first launch --- src/ContainerHomeFolders.react.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ContainerHomeFolders.react.js b/src/ContainerHomeFolders.react.js index 135134a88b..1ace6d4e90 100644 --- a/src/ContainerHomeFolders.react.js +++ b/src/ContainerHomeFolders.react.js @@ -17,7 +17,8 @@ var ContainerHomeFolder = React.createClass({ if (hostVolume.indexOf(process.env.HOME) === -1) { var volumes = _.clone(this.props.container.Volumes); - volumes[containerVolume] = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume); + var newHostVolume = path.join(util.home(), 'Kitematic', this.props.container.Name, containerVolume); + volumes[containerVolume] = newHostVolume; var binds = _.pairs(volumes).map(function (pair) { return pair[1] + ':' + pair[0]; }); @@ -28,7 +29,7 @@ var ContainerHomeFolder = React.createClass({ console.log(err); return; } - shell.showItemInFolder(hostVolume); + shell.showItemInFolder(newHostVolume); }); } else { shell.showItemInFolder(hostVolume); From 898213d515f820defca61b2433b7e62ff491cbbf Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 27 Mar 2015 10:05:17 -0700 Subject: [PATCH 07/34] Rounded containers in icons. --- images/button-restart.png | Bin 1395 -> 1468 bytes images/button-restart@2x.png | Bin 3144 -> 3354 bytes images/button-terminal.png | Bin 1289 -> 1358 bytes images/button-terminal@2x.png | Bin 2704 -> 2882 bytes images/button-view.png | Bin 1511 -> 1583 bytes images/button-view@2x.png | Bin 3382 -> 3550 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/images/button-restart.png b/images/button-restart.png index a43a41994ceb3ad812f64b35f57ee67c89d17478..0cf9ae43ce1524f3e54028a870c5026d0c84b5ce 100644 GIT binary patch delta 1437 zcmV;O1!DU13cL%DF@JVRL_t(o3GG>ZY*a-MpV@oul~TTJZLg)YT<=UUlBfxV5XFE( z@LCFjreY!zf=Ysk5)(~~AF09kj~{;;NlYN9!5BkquI-%(iXlL3`A9@GsJ#~2(%!uy zNGauN`*xgd-R63E?OoG*5R-0l*?lv!Gru=GGjDef;dZyWI)C9`vFi~FTs{OW6-Za4 zMNzoff26I}cYPu_I1wY$^hNa@CE4y-uOiWN1kj2I7l5b(P!#fWF#@dxf|F7Xzu8t@ zayr@mZ2{_QiarWL90G}l2d(&fT{Vj?Cj%)7cIV~@<7pvqF9Sam3EcfU%kXftIS#ZU z+*>UG8iu8{@_%BL=O=A=qFw>cHH_~Gu%E%Mn@BFB^oo%Aus>v)zJ}=1DJiZyYWTyw z=1<;dp44)q zp3VA0%AqGz%sK|t8!~tDl5dFw3ahp8g8B<{=DYLzIDhiGB+4B)K<6+QRuYNr05~_& zeExB$TQjWXD;mumLcrG6K;e4Ffcipa0~`N>|MnosT7m97> zT6b2_GTD4#Gq$j)t29w3C(M5S9ZOu=M84ga3>O>+3$}M|D(hAv zP6CCCo4tR>`{MaR(8~<=opE7c15lCFZVL_9FOr}(Qe7CkY>4Pav@Y^OfW*SNyKpMOWi}gUc9frBR$0QQl3KQ!l_frLCM`jST2RuDPq)0)K@~ ziTYE9biMu8{GmZlFhoT!>JGw%49)D6_rz^ncrZij17)?`;tr&spK_IkwCx5*-CP zDHh%emN#_YJE=?p^Ns;sTzOxCVHigfuuM9p7E%S zQ>H~q?NP!wNg7PDGC)YCCT-PT;8x{qWQzIZT?X2=b6wo6@MMPgZJld~%l00000NkvXXu0mjfWU$3M delta 1363 zcmV-Z1+4nK3-bz)F@G&dL_t(o3GG;YOk70}pWS=MUHR$nynBfe)@N_sSo#$;XVL+V$bw6(T?rx9GD~;zib!M%xd832K+<6==X4(c z$?k5y_!u-+PD%N)7PX#I*wf{)J!%+GS3qq>&p87RSRF4qAmMEF&H?P(zJaG7tQSgskU zDHzA3I)4EfnN@}WwQpX(7VG4Vo_c3o8l_aJARLYAHUA~cm5wjQa0h9SbcVMu>kQkjY$eS!+c~WZ}Yvq2N|L&%%+Y!Ja z%zx@!Er0&l;p;2J7fkMyY&cEU#@f=F|O9=Mu zIbom!P>{rFizudF7>C+!uPrFWk^*)4RnPQ!Qm(+>8Hnw5`eOHLNN7NPd484)et&Jz zmH5cSCInlqx!Xb>n_sIxX^e6L+bE&<)qo%5LVpUR z223!C^PeRRbED3}=_#D|OPcHjSRC(g`UcCXnLcZUwDTCh8CWDE7$G*!VHNhRSn!XB zdwY+m9O6tMUs5=nd(G}?r z=y^zdorVGLO*h$+#^_Dz(G}xh`hV21HZMz;d5c6tfi8*#kAfx50~;2V(J+?{XleO9 zxr(B+YOpLiTsEMKqS9fm0M&8Il1M8aU6T8B7O!|z$0vEu%)6Ib-7E14NvfPyZ}a%$w_{4k4nj9?pJ`OdIMHG`b@v|sKObH z5(<0q|5K`+u&6$)!)Ck?<}E6uVNU;XcKKtw5Nt}W3>w`@hisCZ3DwvxB^5-0e*oYr V-hyxF{jC51002ovPDHLkV1kDSnn3^n diff --git a/images/button-restart@2x.png b/images/button-restart@2x.png index 30c4f26e01bafd3c216bd8f25c56d5db6c5b5a60..bb62729cb3db73ff5b8349a8cf819c18564066cf 100644 GIT binary patch literal 3354 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 Q0000007*qoM6N<$f=|jcBLDyZ diff --git a/images/button-terminal.png b/images/button-terminal.png index b317d67bffc0c77e11c2d9252875510b7eb7b5bc..cfcedd974f6fd0ca313c31f1906b38f2cbd8ed6d 100644 GIT binary patch delta 1327 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 TS+#^%00000NkvXXu0mjf0)J)6 diff --git a/images/button-terminal@2x.png b/images/button-terminal@2x.png index 58fb047de0126bc8d63dde28068965eb4c8f7f17..658786d3f65ca291b6e44a6b5b175e7c02d48df1 100644 GIT binary patch delta 2862 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 KMNUMnLSTZMkis+o delta 3367 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 From b10f2996e7dc4dc29345321e856fe0dcbcb7441a Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 27 Mar 2015 10:10:04 -0700 Subject: [PATCH 08/34] Bumped up running status animation speed slightly. --- styles/left-panel.less | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/left-panel.less b/styles/left-panel.less index ecba94e97c..2aa98270fc 100644 --- a/styles/left-panel.less +++ b/styles/left-panel.less @@ -201,7 +201,7 @@ left: -20px; .at2x('runningwave.png', 20px, 20px); -webkit-animation-name: translatewave; - -webkit-animation-duration: 8.0s; + -webkit-animation-duration: 7.0s; -webkit-animation-iteration-count: infinite; -webkit-animation-timing-function: linear; } From 0cb0a7c5882f7a0bb7ae7674946925e0f90e9a86 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Fri, 27 Mar 2015 11:00:14 -0700 Subject: [PATCH 09/34] Display no logs message when there is no logs. --- src/ContainerHomeLogs.react.js | 3 +++ src/ContainerLogs.react.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/ContainerHomeLogs.react.js b/src/ContainerHomeLogs.react.js index a13f310c3c..d400a48d72 100644 --- a/src/ContainerHomeLogs.react.js +++ b/src/ContainerHomeLogs.react.js @@ -52,6 +52,9 @@ var ContainerHomeLogs = React.createClass({ var logs = this.state.logs.map(function (l, i) { return

; }); + if (logs.length === 0) { + logs = "No logs for this container."; + } return (

Logs

diff --git a/src/ContainerLogs.react.js b/src/ContainerLogs.react.js index cdde86f4d2..e20910cc49 100644 --- a/src/ContainerLogs.react.js +++ b/src/ContainerLogs.react.js @@ -45,6 +45,9 @@ var ContainerLogs = React.createClass({ var logs = this.state.logs.map(function (l, i) { return

; }); + if (logs.length === 0) { + logs = "No logs for this container."; + } return (
{logs} From 149f31750e3d7ee2015e3b2143a5823c026a391b Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 27 Mar 2015 14:45:27 -0400 Subject: [PATCH 10/34] Fix bug where environment variables wouldn't be saved --- src/ContainerStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ContainerStore.js b/src/ContainerStore.js index cb394f1593..b0cc3940df 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -119,7 +119,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { if (containerData.Config && containerData.Config.Image) { containerData.Image = containerData.Config.Image; } - if (containerData.Config && containerData.Config.Env) { + if (!containerData.Env && containerData.Config && containerData.Config.Env) { containerData.Env = containerData.Config.Env; } existing.kill(function () { From 70208ed19e3edfc6699e62a07f90d95682794b4c Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 27 Mar 2015 14:49:01 -0400 Subject: [PATCH 11/34] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7f5153e58..c64f3fcb1c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Kitematic", - "version": "0.5.11", + "version": "0.5.12", "author": "Kitematic", "description": "Simple Docker Container management for Mac OS X.", "homepage": "https://kitematic.com/", From 1b8e25501cb6f5a46f2d1c8b55b32f55fe08eeec Mon Sep 17 00:00:00 2001 From: Allen Servedio Date: Sat, 28 Mar 2015 21:34:22 -0400 Subject: [PATCH 12/34] Changes made in response to code review. --- src/ImageCard.react.js | 8 ++++---- styles/new-container.less | 5 ----- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index 7739d11963..29a09efebf 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -42,11 +42,11 @@ var ImageCard = React.createClass({ $tagOverlay.fadeOut(300); }, handleRepoClick: function () { - var $repoUri = 'https://registry.hub.docker.com/' + var $repoUri = 'https://registry.hub.docker.com/'; if (this.props.image.is_official) { - $repoUri = $repoUri + "_/" + $repoUri = $repoUri + "_/"; } else { - $repoUri = $repoUri + "u/" + $repoUri = $repoUri + "u/"; } util.exec(['open', $repoUri + this.props.image.name]); }, @@ -67,7 +67,7 @@ var ImageCard = React.createClass({ name = (
{namespace}
- {this.props.image.name}}> + View on DockerHub}> {repo}
diff --git a/styles/new-container.less b/styles/new-container.less index 1956f38295..a00f9c3eb3 100644 --- a/styles/new-container.less +++ b/styles/new-container.less @@ -187,11 +187,6 @@ text-overflow: ellipsis; white-space: nowrap; text-decoration: underline; - &:hover { - background-color: @brand-action; - color: white; - border-radius: 20px; - } } } .description { From c51a2bdce69566806d3b0c7eb41b0f10fe040c54 Mon Sep 17 00:00:00 2001 From: Allen Servedio Date: Sat, 28 Mar 2015 21:48:18 -0400 Subject: [PATCH 13/34] Missed updating one tool tip. --- src/ImageCard.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index 29a09efebf..db895f6e32 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -76,7 +76,7 @@ var ImageCard = React.createClass({ name = (
{namespace}
- {this.props.image.name}}> + View on DockerHub}> {repo}
From ffdc9d3019f5a045285673e43ff6b72d8bbf344a Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Sun, 29 Mar 2015 14:19:08 -0400 Subject: [PATCH 14/34] Update CONTRIBUTING.md --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5c885f559f..3fe22bdc17 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,6 +53,10 @@ We're thrilled to receive pull requests of any kind. Anything from bug fix, test That said, please let us know what you're planning to do! For large changes always create a proposal. Maintainers will love to give you advice on building it and it keeps the app's design coherent. +### Pull Request Requirements: +- Tests +- [Signed Off](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work) + ## Code Guidelines ### Javascript From 39d999b635fdce20a436f6407170bb84e4e39426 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Sun, 29 Mar 2015 16:24:47 -0400 Subject: [PATCH 15/34] Bump Virtualbox Version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c64f3fcb1c..fcbed0a115 100644 --- a/package.json +++ b/package.json @@ -44,8 +44,8 @@ "docker-machine-version": "0.1.0-kitematic-0.5.10", "atom-shell-version": "0.21.3", "virtualbox-version": "4.3.24", - "virtualbox-filename": "VirtualBox-4.3.24.pkg", - "virtualbox-checksum": "100eee21df3808fc1b1e461e86f10b6d2a748935c5f31bc665f4ff0777e44a0b", + "virtualbox-filename": "VirtualBox-4.3.26.pkg", + "virtualbox-checksum": "668f61c95efe37f8fc65cafe95b866fba64e37f2492dfc1e2b44a7ac3dcafa3b", "dependencies": { "ansi-to-html": "0.3.0", "async": "^0.9.0", From 2565493975520793706e4a2a072f7db344b59784 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Sun, 29 Mar 2015 16:38:30 -0400 Subject: [PATCH 16/34] Bumping version in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fcbed0a115..d0014723fe 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,7 @@ "docker-version": "1.5.0", "docker-machine-version": "0.1.0-kitematic-0.5.10", "atom-shell-version": "0.21.3", - "virtualbox-version": "4.3.24", + "virtualbox-version": "4.3.26", "virtualbox-filename": "VirtualBox-4.3.26.pkg", "virtualbox-checksum": "668f61c95efe37f8fc65cafe95b866fba64e37f2492dfc1e2b44a7ac3dcafa3b", "dependencies": { From 246affabd42f8f379c22aad8b768e97bda61ed07 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Tue, 31 Mar 2015 13:29:26 -0400 Subject: [PATCH 17/34] bumping version to 0.5.13 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d0014723fe..bbb611d8c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "Kitematic", - "version": "0.5.12", + "version": "0.5.13", "author": "Kitematic", "description": "Simple Docker Container management for Mac OS X.", "homepage": "https://kitematic.com/", From 97272b971feaea56a22937f1f6ff6d7e1aaea5fe Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Tue, 31 Mar 2015 18:31:35 -0400 Subject: [PATCH 18/34] Fix any mac errors due to windows changes --- src/SetupStore.js | 2 ++ src/SetupUtil.js | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/SetupStore.js b/src/SetupStore.js index 3615fff789..f1c93cdf30 100644 --- a/src/SetupStore.js +++ b/src/SetupStore.js @@ -270,6 +270,8 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), { step: _currentStep, message: err.message }); + console.log(err); + console.log(err.stack); bugsnag.notify('SetupError', err.message, { error: err, step: _currentStep diff --git a/src/SetupUtil.js b/src/SetupUtil.js index 9dfed3c7dc..bd3cf5a9f8 100644 --- a/src/SetupUtil.js +++ b/src/SetupUtil.js @@ -33,9 +33,9 @@ var SetupUtil = { return; } - yield fs.chown(util.binsPath(), process.getuid(), '80'); - yield fs.chown(util.dockerBinPath(), process.getuid(), '80'); - yield fs.chown(util.dockerMachineBinPath(), process.getuid(), '80'); + yield fs.chown(util.binsPath(), process.getuid(), 80); + yield fs.chown(util.dockerBinPath(), process.getuid(), 80); + yield fs.chown(util.dockerMachineBinPath(), process.getuid(), 80); return Promise.resolve(); }), installVirtualBoxCmd: Promise.coroutine(function* () { From d92a102a8388ca7e6ff8911290cbc59ef7efc297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Wed, 1 Apr 2015 21:05:42 +0000 Subject: [PATCH 19/34] Remove `componentDidMount` function with reload. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removing the reload (and the whole `componentDidMount` function since the reload was the only thing in there) makes sure that the container view isn't reloaded when the DOM changes and so does not make a request to the container. Because of this change kitematic will not make a request to the container when hovering over the preference button. (I wasn't sure if this was used somewhere for real. If it is, I couldn't find it). Fixes #333. Signed-off-by: Kristján Oddsson --- src/ContainerHomePreview.react.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/ContainerHomePreview.react.js b/src/ContainerHomePreview.react.js index 9e0d21a108..e03c448411 100644 --- a/src/ContainerHomePreview.react.js +++ b/src/ContainerHomePreview.react.js @@ -37,9 +37,6 @@ var ContainerHomePreview = React.createClass({ }); } }, - componentDidUpdate: function () { - this.reload(); - }, componentWillUnmount: function() { clearInterval(this.timer); }, From b5acaafd9e7eabc3cadf13e06729fd6fc334f3ca Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Fri, 3 Apr 2015 10:58:14 -0400 Subject: [PATCH 20/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 795d88e9c1..ce35ee50c7 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![Kitematic Logo](https://cloud.githubusercontent.com/assets/251292/5269258/1b229c3c-7a2f-11e4-96f1-e7baf3c86d73.png) -Kitematic is a simple application for managing Docker containers on Mac OS X. +Kitematic is a simple application for managing Docker containers on Mac OS X and Windows (coming soon!). ## Installing Kitematic From 584c7955125c408333caf4033770604ddf38d57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 3 Apr 2015 20:07:11 +0000 Subject: [PATCH 21/34] Replace hard-coded error message with props. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure that errors that happen when pulling image layers bubble up to the UI. We do this by catching errors coming from the docker client, calling the callback with that error and setting the global variable `_error` as the error we just caught. This is to make sure that when the stream ends we call the callback with the error as well as to not to over-ride it. Finally we remove the hard-coded message in the UI and display the error that gets passed in to it through the props attribute. This is the only part I'm not super sure on if we really want since it must have been set there for a reason. If I can get a re-producible test case I can make sure that it's still passing with this patch. Fixes #355. Signed-off-by: Kristján Oddsson --- src/ContainerHome.react.js | 4 +++- src/ContainerStore.js | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/ContainerHome.react.js b/src/ContainerHome.react.js index bb3c4655f1..de13f769c0 100644 --- a/src/ContainerHome.react.js +++ b/src/ContainerHome.react.js @@ -74,7 +74,9 @@ var ContainerHome = React.createClass({ if (this.props.error) { body = (
); diff --git a/src/ContainerStore.js b/src/ContainerStore.js index b0cc3940df..109a022d19 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -56,6 +56,12 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { var data = JSON.parse(str); console.log(data); + if (data.error) { + _error = data.error; + callback(data.error); + return; + } + if (data.status && (data.status === 'Pulling dependent layers' || data.status.indexOf('already being pulled by another client') !== -1)) { blockedCallback(); return; @@ -82,7 +88,8 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { progressCallback(totalProgress); }); stream.on('end', function () { - callback(); + callback(_error); + _error = null; }); }); }); From b67c1a912e11cea06d80fb693d7c0190a870168c Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Sat, 4 Apr 2015 17:24:18 -0400 Subject: [PATCH 22/34] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ce35ee50c7..9d8d3fe3b2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![CircleCI](https://img.shields.io/circleci/project/kitematic/kitematic.svg)](https://circleci.com/gh/kitematic/kitematic/tree/master) +[![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg)](https://coveralls.io/r/kitematic/kitematic) [![bitHound Score](https://app.bithound.io/kitematic/kitematic/badges/score.svg)](http://app.bithound.io/kitematic/kitematic) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From dfe80af6e4c7ae1eea77b3403778dff55cf36b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Sun, 5 Apr 2015 17:01:18 +0000 Subject: [PATCH 23/34] Fall-back to image name as key when there is no id MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a container is first started and the image is downloading there is no id set. With this patch we'll check if the container has a id and and is downloading, if so we'll substitute it with the image name and render such. This will fix the react key props warning in the developer console as well as maybe give us some sort of performance boost(?) Signed-off-by: Kristján Oddsson --- src/ContainerList.react.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/ContainerList.react.js b/src/ContainerList.react.js index 1d6d25a034..9b1dcf9cb4 100644 --- a/src/ContainerList.react.js +++ b/src/ContainerList.react.js @@ -9,8 +9,14 @@ var ContainerList = React.createClass({ render: function () { var self = this; var containers = this.props.containers.map(function (container) { + var container_id = container.Id; + if (!container_id && container.State.Downloading) { + // Fall back to the container image name when there is no id. (when the + // image is downloading). + container_id = container.Image; + } return ( - + ); }); var newItem; From 9eab0501fde1b8c5c9ee5d02240eed1dc53a4319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Sun, 5 Apr 2015 15:41:01 +0000 Subject: [PATCH 24/34] Format the error message a little bit better. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error message is actually a object and not a string so we format it a bit better with this patch. Signed-off-by: Kristján Oddsson --- src/ContainerHome.react.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ContainerHome.react.js b/src/ContainerHome.react.js index de13f769c0..530e1b2668 100644 --- a/src/ContainerHome.react.js +++ b/src/ContainerHome.react.js @@ -75,7 +75,7 @@ var ContainerHome = React.createClass({ body = (

An error occurred:

-

{this.props.error}

+

{this.props.error.statusCode} {this.props.error.reason} - {this.props.error.json}

If you feel that this error is invalid, please file a ticket on our GitHub repo.

From 603b9c5952b3b0a88d07af8e3cb0d2380825c38b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Sun, 5 Apr 2015 15:42:11 +0000 Subject: [PATCH 25/34] Fetch tags when a Image card has been mounted. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For images that don't have a "latest" tag (such as `google/debian`) we fetch all the tags when the `ImageCard` component mounts and set the chosen tag to the first one in the list (so far it seems to be the latest tag where such a tag exists but we can add some logic here to choose a appropriate tag if we want). Signed-off-by: Kristján Oddsson --- src/ImageCard.react.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index db895f6e32..88f12d60fd 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -50,6 +50,14 @@ var ImageCard = React.createClass({ } util.exec(['open', $repoUri + this.props.image.name]); }, + componentDidMount: function() { + $.get('https://registry.hub.docker.com/v1/repositories/' + this.props.image.name + '/tags', function (result) { + this.setState({ + tags: result, + chosenTag: result[0].name + }); + }.bind(this)); + }, render: function () { var self = this; var name; From 6e56c4f66500d92e0671de37b46700795b557ab7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Sun, 5 Apr 2015 21:08:15 +0000 Subject: [PATCH 26/34] Change normal function in to a ES6 arrow function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need for `.bind(this)` with ECMAScript6 syntax! Signed-off-by: Kristján Oddsson --- src/ImageCard.react.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index 88f12d60fd..659d1407e6 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -31,11 +31,11 @@ var ImageCard = React.createClass({ handleTagOverlayClick: function (name) { var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); $tagOverlay.fadeIn(300); - $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) { + $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', result => { this.setState({ tags: result }); - }.bind(this)); + }); }, handleCloseTagOverlay: function () { var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); @@ -51,12 +51,12 @@ var ImageCard = React.createClass({ util.exec(['open', $repoUri + this.props.image.name]); }, componentDidMount: function() { - $.get('https://registry.hub.docker.com/v1/repositories/' + this.props.image.name + '/tags', function (result) { + $.get('https://registry.hub.docker.com/v1/repositories/' + this.props.image.name + '/tags', result => { this.setState({ tags: result, chosenTag: result[0].name }); - }.bind(this)); + }); }, render: function () { var self = this; From 748207797551fed3da91330c490598ac19bda32b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Sun, 5 Apr 2015 21:14:34 +0000 Subject: [PATCH 27/34] Change variable from snake_case to camelCase. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristján Oddsson --- src/ContainerList.react.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ContainerList.react.js b/src/ContainerList.react.js index 9b1dcf9cb4..d2954dc603 100644 --- a/src/ContainerList.react.js +++ b/src/ContainerList.react.js @@ -9,14 +9,14 @@ var ContainerList = React.createClass({ render: function () { var self = this; var containers = this.props.containers.map(function (container) { - var container_id = container.Id; - if (!container_id && container.State.Downloading) { + var containerId = container.Id; + if (!containerId && container.State.Downloading) { // Fall back to the container image name when there is no id. (when the // image is downloading). - container_id = container.Image; + containerId = container.Image; } return ( - + ); }); var newItem; From be368f7a77c1be37f0f9f8db4f3f28b4a5699b80 Mon Sep 17 00:00:00 2001 From: Jeffrey Dean Morgan Date: Sun, 5 Apr 2015 19:51:45 -0400 Subject: [PATCH 28/34] Adding code coverage to unit tests Signed-off-by: Jeffrey Morgan --- .gitignore | 1 + .jshintrc | 2 +- README.md | 1 + package.json | 21 ++++++++++++++------- src/ContainerHome.react.js | 4 +++- src/ContainerStore.js | 9 ++++++++- src/ImageCard.react.js | 12 ++++++++++-- {__tests__ => src}/SetupStore-test.js | 13 ++++++------- {__tests__ => src}/Virtualbox-test.js | 7 +++---- 9 files changed, 47 insertions(+), 23 deletions(-) rename {__tests__ => src}/SetupStore-test.js (92%) rename {__tests__ => src}/Virtualbox-test.js (76%) diff --git a/.gitignore b/.gitignore index 7b9e66caf1..ca23db9e8a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ build dist node_modules +coverage npm-debug.log # Signing Identity diff --git a/.jshintrc b/.jshintrc index 9240a3ae9f..daeaf45072 100644 --- a/.jshintrc +++ b/.jshintrc @@ -27,5 +27,5 @@ "jest": true, "pit": true }, - "predef": [ "-Promise" ] + "predef": [ "Promise" ] } diff --git a/README.md b/README.md index ce35ee50c7..9d8d3fe3b2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![CircleCI](https://img.shields.io/circleci/project/kitematic/kitematic.svg)](https://circleci.com/gh/kitematic/kitematic/tree/master) +[![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg)](https://coveralls.io/r/kitematic/kitematic) [![bitHound Score](https://app.bithound.io/kitematic/kitematic/badges/score.svg)](http://app.bithound.io/kitematic/kitematic) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) diff --git a/package.json b/package.json index bbb611d8c7..057aac3a84 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "bugs": "https://github.com/kitematic/kitematic/issues", "scripts": { "start": "gulp", - "test": "jest", + "test": "jest --coverage", "release": "gulp release", "release:beta": "gulp release --beta", "preinstall": "./util/deps", @@ -28,16 +28,21 @@ "jest": { "scriptPreprocessor": "/util/preprocessor.js", "setupEnvScriptFile": "/util/testenv.js", + "collectCoverage": true, + "testDirectoryName": "src", + "testPathIgnorePatterns": [ + "/node_modules/", + "^((?!-test).)*$" + ], "unmockedModulePathPatterns": [ + "stream", "tty", "net", "crypto", - "stream", + "/node_modules/.*JSONStream", "/node_modules/object-assign", "/node_modules/underscore", - "/node_modules/react", - "/node_modules/bluebird", - "/node_modules/babel" + "/node_modules/bluebird" ] }, "docker-version": "1.5.0", @@ -51,7 +56,8 @@ "async": "^0.9.0", "bluebird": "^2.9.12", "bugsnag-js": "^2.4.7", - "dockerode": "^2.0.7", + "coveralls": "^2.11.2", + "dockerode": "^2.1.1", "exec": "0.2.0", "jquery": "^2.1.3", "minimist": "^1.1.0", @@ -76,6 +82,7 @@ "gulp-cssmin": "^0.1.6", "gulp-download-atom-shell": "0.0.4", "gulp-if": "^1.2.5", + "gulp-insert": "^0.4.0", "gulp-less": "^3.0.1", "gulp-livereload": "^3.8.0", "gulp-plumber": "^0.6.6", @@ -83,7 +90,7 @@ "gulp-shell": "^0.3.0", "gulp-sourcemaps": "^1.5.0", "gulp-util": "^3.0.4", - "jest-cli": "^0.4.0", + "jest-cli": "kitematic/jest", "jsxhint": "^0.12.1", "react-tools": "^0.12.2", "run-sequence": "^1.0.2" diff --git a/src/ContainerHome.react.js b/src/ContainerHome.react.js index bb3c4655f1..530e1b2668 100644 --- a/src/ContainerHome.react.js +++ b/src/ContainerHome.react.js @@ -74,7 +74,9 @@ var ContainerHome = React.createClass({ if (this.props.error) { body = (
-

There was a problem connecting to the Docker Engine in the VirtualBox VM.
This could be caused because this Mac is currently connected to a VPN, blocking access to the VM. If the issue persists, please file a ticket on our GitHub repo.

+

An error occurred:

+

{this.props.error.statusCode} {this.props.error.reason} - {this.props.error.json}

+

If you feel that this error is invalid, please file a ticket on our GitHub repo.

); diff --git a/src/ContainerStore.js b/src/ContainerStore.js index b0cc3940df..109a022d19 100644 --- a/src/ContainerStore.js +++ b/src/ContainerStore.js @@ -56,6 +56,12 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { var data = JSON.parse(str); console.log(data); + if (data.error) { + _error = data.error; + callback(data.error); + return; + } + if (data.status && (data.status === 'Pulling dependent layers' || data.status.indexOf('already being pulled by another client') !== -1)) { blockedCallback(); return; @@ -82,7 +88,8 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), { progressCallback(totalProgress); }); stream.on('end', function () { - callback(); + callback(_error); + _error = null; }); }); }); diff --git a/src/ImageCard.react.js b/src/ImageCard.react.js index db895f6e32..659d1407e6 100644 --- a/src/ImageCard.react.js +++ b/src/ImageCard.react.js @@ -31,11 +31,11 @@ var ImageCard = React.createClass({ handleTagOverlayClick: function (name) { var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); $tagOverlay.fadeIn(300); - $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', function (result) { + $.get('https://registry.hub.docker.com/v1/repositories/' + name + '/tags', result => { this.setState({ tags: result }); - }.bind(this)); + }); }, handleCloseTagOverlay: function () { var $tagOverlay = $(this.getDOMNode()).find('.tag-overlay'); @@ -50,6 +50,14 @@ var ImageCard = React.createClass({ } util.exec(['open', $repoUri + this.props.image.name]); }, + componentDidMount: function() { + $.get('https://registry.hub.docker.com/v1/repositories/' + this.props.image.name + '/tags', result => { + this.setState({ + tags: result, + chosenTag: result[0].name + }); + }); + }, render: function () { var self = this; var name; diff --git a/__tests__/SetupStore-test.js b/src/SetupStore-test.js similarity index 92% rename from __tests__/SetupStore-test.js rename to src/SetupStore-test.js index 1410a883b0..42add6fd37 100644 --- a/__tests__/SetupStore-test.js +++ b/src/SetupStore-test.js @@ -1,10 +1,9 @@ -jest.dontMock('../src/SetupStore'); -var setupStore = require('../src/SetupStore'); -var virtualBox = require('../src/VirtualBox'); -var util = require('../src/Util'); -var machine = require('../src/DockerMachine'); -var setupUtil = require('../src/SetupUtil'); -var Promise = require('bluebird'); +jest.dontMock('./SetupStore'); +var setupStore = require('./SetupStore'); +var virtualBox = require('./VirtualBox'); +var util = require('./Util'); +var machine = require('./DockerMachine'); +var setupUtil = require('./SetupUtil'); describe('SetupStore', function () { describe('download step', function () { diff --git a/__tests__/Virtualbox-test.js b/src/Virtualbox-test.js similarity index 76% rename from __tests__/Virtualbox-test.js rename to src/Virtualbox-test.js index 1a8efa7aab..567210a08a 100644 --- a/__tests__/Virtualbox-test.js +++ b/src/Virtualbox-test.js @@ -1,7 +1,6 @@ -jest.dontMock('../src/VirtualBox'); -var virtualBox = require('../src/VirtualBox'); -var util = require('../src/Util'); -var Promise = require('bluebird'); +jest.dontMock('./VirtualBox'); +var virtualBox = require('./VirtualBox'); +var util = require('./Util'); describe('VirtualBox', function () { it('returns the right command', function () { From 832ba18c027a15e5d5d27ed274bb8d0289b4d211 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 12:20:02 -0400 Subject: [PATCH 29/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9d8d3fe3b2..84d453e802 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ [![CircleCI](https://img.shields.io/circleci/project/kitematic/kitematic.svg)](https://circleci.com/gh/kitematic/kitematic/tree/master) -[![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg)](https://coveralls.io/r/kitematic/kitematic) +[![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg?branch=master)](https://coveralls.io/r/kitematic/kitematic?branch=master) [![bitHound Score](https://app.bithound.io/kitematic/kitematic/badges/score.svg)](http://app.bithound.io/kitematic/kitematic) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) From 4b96ac9bc92d17e2e8117afbf50851f47948c552 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 13:38:08 -0400 Subject: [PATCH 30/34] Update circle.yml --- circle.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/circle.yml b/circle.yml index 0ddf9ac841..9933147169 100644 --- a/circle.yml +++ b/circle.yml @@ -5,3 +5,6 @@ dependencies: cache_directories: - "resources" - "node_modules" +notify: + webhooks: + - url: https://coveralls.io/webhook From f730b5ebf2945a0d9becd7f96fd6d9e18964a783 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 13:46:46 -0400 Subject: [PATCH 31/34] adding travis ci --- .travis.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000000..8d530885bf --- /dev/null +++ b/.travis.yml @@ -0,0 +1,12 @@ +language: node_js +node_js: + - "0.10" + +sudo: false + +cache: + - resources + - node_modules + +after_success: + which ./node_modules/coveralls/bin/coveralls.js && cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js From ec43f48537dea19ed11768d4215826b7bb706415 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 13:49:31 -0400 Subject: [PATCH 32/34] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8d530885bf..2fd698f0cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,4 +9,4 @@ cache: - node_modules after_success: - which ./node_modules/coveralls/bin/coveralls.js && cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js + - which ./node_modules/coveralls/bin/coveralls.js && cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js From 063e923065c59b7e35f9bd40e2c2b96ad7fc84d8 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 13:58:11 -0400 Subject: [PATCH 33/34] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 2fd698f0cb..dabf931807 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ node_js: sudo: false cache: + directories: - resources - node_modules From b6039efc768c29e3c876a2e77ac712ceef9925c4 Mon Sep 17 00:00:00 2001 From: Jeffrey Morgan Date: Mon, 6 Apr 2015 13:58:47 -0400 Subject: [PATCH 34/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 84d453e802..bb6f6b105e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![CircleCI](https://img.shields.io/circleci/project/kitematic/kitematic.svg)](https://circleci.com/gh/kitematic/kitematic/tree/master) +[![Build Status](https://travis-ci.org/kitematic/kitematic.svg?branch=master)](https://travis-ci.org/kitematic/kitematic) [![Coverage Status](https://coveralls.io/repos/kitematic/kitematic/badge.svg?branch=master)](https://coveralls.io/r/kitematic/kitematic?branch=master) [![bitHound Score](https://app.bithound.io/kitematic/kitematic/badges/score.svg)](http://app.bithound.io/kitematic/kitematic) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)