!8J8%=j1DU8p1dp?uU&Ufvm25v^MAltMTj~yxc-k`Jc@7;Al$ntr6ImowNmM}!#)XnADeh0^rgITxaOE>r@tw7&L
z$%%Gcs)nDpQ{FOL{L${cLm&4xlr+(nCrPOMC=1SqoowIxVc+%TYJog(WX(yp~tB-R0(EJdM<761mIbF{Y6TNPBRKFeGX}L1~j{3tzE{cCv#|9db
z?fB#Tloa9ToFiQrl*QvxL$sQ97mmJ@Ui#c{wEt40Sw$MI*mdXNm#lYAl*sHY{=(-b
zAH)RK0zDng%R^)%TEx_KGV$H26#NU%Ap%f}C|rPRX~h35+%TU8Cl)K@6CybR{CZ||
zan!71D=jVUebLlAjrXUT{B(<|^76uZ@iNE@i;BEfMq53xA4!x-kJ`L_e1hJaKlnw-
zq0gDr)Fe52UV3nGX^9XYS3p3(kuV`nyj-7?F8apd_VlzxSWC~;lsY*M_L`iW9RIkK
z_a-6*mz6X8^zQvD(Fj{jPn;SGlo}Qi+
zVBOx<-X8hLCxTICX>~QX2bP_fD(0oDr&oCeCENb{;BfJ|6kUz1kB`{OIi|Z&QBk$V
zrQzXlAp)c_t!8aoTU%c_+9nq_J9cr=4ls8lNr*$K~54T;HG`knSgewHwu=djG!=VSNIHL{SrR3EaAR@vXN9NMj0ALP{NWv
zl$tcKv$N;s<&97vm|MSm`2r42^=eE)7a2U9vi2d5G+9(^tWk-se|{8MZ`IhU>uvr&
zukUkUvD6$ePEW?pUprnN9+2e>ha0?Hm@Z-e{OB|cxIys7b#!d3PJ#rfd_6Tab)^2K
z^EhFTZNfJ3n@cm)3A5X`5zNu}LGLFTyzVXc<>loS6%_&1U6C_GqKOs~00Y^V?a&p=
z@vW5a2w@jx_La~1OX27025L_?HZ~Ry&D2uT(a}BEKJTiz`Tr!e
zAN&;+Srx-v8M3mnNWy{)@(|1`o7>w+%E8a=*sGV6;$UhYe{6WTyT1XaHfr~n{;)U}
z%XI02prD}ZvHp`0wWXbd5p`Mk3+e6lEujErXM#mMeH?RF*KYf&n3xy{2RB?rQ$-z}
z?sNS1Vc-?%>+8E33zP^02gCpV>({S);6%S%
z4womoFQKrO)b{;7q50LNrKJh73);Y1nF7{&B@TatDX%ak)dS#(Jj+7^z;Jl
zqoFMp$sN`il;@NKuPen2J5~di17O4=o;`b}TQs2mj24Y>;*7@OB&4O)*3scxreH+}
z$c2&I`7SVSUsF?KMS#`G?6KvgK@YMavA8BCCg&s`5A^rXx{F%--Zcs~wzRcXrW3mP
z1tsfgYim1P<&Z3+*OZlo$05zlck9;NgS!3w{b7JCv0dLLzk_XBuftYC&xX`W*Eo7X
zAtC3n>gbgxWEG+PeQRs?<<A8yZSvf*nXWN=_ldX%%sOnVu{
zJb%`1_Nth*!<{i(y0mM)8!1!1a2ONib2WI1kW>B9{<7Qr!5CoGp2$&-3(E*b*X}PB
zS^p4CZu+3iqN%UH`@4m-?T~Ok^xvg8QzxK1T
zYkrcNHd^t7hQjZKtk_cHI)1%om10l=T3mLVYC5dw;O>|%Bj*6Mp*{jI-`~uWN*$Y8
zF!7pT)g3OkIv-6BLw)cy_S+f|p7M3;d|WVtS1x<+-pv*0_gBUbr$c}}ZFWt6HEwiL
za_I5`_Se~%YaUZK<(CDl06sDk@mZX@aL4nY(oB%8#sftsl6edV)So$V(0YI-))R;<
z&4v~OLS#^6f)eowC>uc~3F=f(NB;L;sY*Z{%S&aa{ox7>W}a^$@&8ok{$EJ)PkCk=Po{KJS*_>xG#9zbk8=)wp}T|_tU?lul<_XZo`>7GsB2wdVIXiXwL
z^9kAMA{@yCbnM0igkqUC*HLe}_#5
zJ_NQ+-&2&Fz5jnk%Yqs_E(`S%bWBY3lj@F6PF02_@6F>1aiBxc;&@$BQj(nwGLZ&9
z3^=Q$Cu>4-a&l5q1Py`~a$~+KvOoUKUu_~4v-&SW(0*IMwl^9kuvp
zkdm6Zrn*{_>F@TBc{I0#g|)8y{pvVUq2POoB#e#tuTX|YMi(z$d|`HbhOl#;a(+)WbD`tIJma;PGi);_q*gIeOW?(=4@rq9ZOtGOCsZ
zOJu3?$)33HLzNY&!dK3@G_N7*n-Ded*ckbVaC*3Uf43H^)X8l-Z`7yc|
zA`OmQT%`D}h@XA%*Qb9q_?95ls;mfil!IaiIPtJN9qTIlMN7QQQy#T9vbjllTQ8jQ
z_^>ju6qGYMS2p5(VxcOstK)g8n*PpFccBIwn8czhUv#Y0``n20$%Y!T89lyzO&)sU
zQwyI7sleRBD>;JIIZ;_w<6(nE@tPau^%Eg5i2k7=2jZZjQ$1%Dn90KRIjQK*ogA7e
zMP^U_SDT`Og4Y&M1pC;p0Fdo8P^bg`1d0Aqc!-&-sNlbhcN))fxd{WL-%Y!IwB$Rb
zqH031w7d*pm6DQTM*~TE2+=7o@3AZoZm~Gs)Ftep5f>k@n^9UCbK?Bn8+T18034l!
z#@Zye|B~tw_R&DFu^C{zJ$xfBpYY50ky3-eetYL!qm-rbAGC(wSjhSN`)g^DpY6gR
zo{|c=Oscj(vzUdw`Ob^v>#0M7gT1`aad|h@xw#@swz*d)J5EA&-HQ%9L*PdM7l5l!
zt9G~&J>qmwljgGIyT%8=xFS{mE>rr1pmNN-Ls@jXNKEtUD(^M!?0P5ze!I`6%WX=&r@|-<_a{i^OKvK1%
z{NQg`j2nMxxw(MqJ^T6!`!1W^voO_91xl(A8ycyyPK5fv8U#yd#>D!ZFWpi6GsSf%
z*aBD1Rms*e(R@v!&VvC7`2?-AKYwa5a^5ut;DZtjD)3R|J#7Q0rGj{E%D?(Vy`aAF
zmQ8U*f{pWxk7tBNwm{WcxW=1*8JDz|2at4zTe#Z~-RvCz+qbj7ImS
z(W@wdWOo9n+m9aTH}G|)^$4D^A^PV~sjBEzCxpIyq{{zp69=0;z
z&L?HTdrqw=wMGrPztw=-T!8-y#fOdWw1~fAF8D|E1Rd~0X%#|W&zepY+V^+PWYif;
zcVEh^J(q;gzw{{Jp@}@T+5f?gIbLn$(`~$GwA^PDId^`l9TifZ$zvZ8KaktxiQqUh
zMe1EX`^9$Mzgo%*YejJvpkCWjMgC3tBBK9pXy)rdcmNZw2?KvI@sy+##3XH>SoGQH
zWCpP*#*!>TX%I5xKP%8Fh@PD`dW&6gG3DQ_p{x}(xLYM=n|XQ)yazgfw=&TAFBWLl
z*%ft-2%XQ=Wv0%hkr2;lIpJ=u%lc&Rv<|^u5po{aH#T-0-->OuBniu^sOWWdXmT18
z0&Pd-$hG(j5)3fbg}|-lAs_Lp-%Fc|8z}~>tA(seJn!C(ZnZ2ZEVOrW%JIR=z{j9;
zb#LhMF0_}KG*rKNgYvA2zEylV+Mq<2Hod1D2Nl?aKp;T(%|G+9Bc_@{*Q&%9K|vN4
zPDaB3>f#CJ5WA5IYenM?WtM-^(|ITd5gg-#gYz4E^6xD9_XS|c?(17yTWWcIu0<2$
zfWZPiJasYCUaj8tafl|7Idv+<+(3
zodG~dw`tD?VlRfQ#>Vlv2d$QThh>FP@J^{?->{Z)>kg`YUcg7JV#mI?ud(F0QH(N8t%~auaG8D@_nF
zy^!)8fBUGAkWl+`#bdWUxz};6mTTS^RRIDp`pK-Qc(5{B6{5O;-l)H+YkZ?J}>5_J3oCS1{&7v
zZ27L6c7Bp(APDl(WM=``$XO=1b%4-pQ>l=p;a6(PLS|59PuVPkCk_9UTVG$_*l7HN
zqwfB9#mLsoF$blNH`3?M`!}cC<-!o}hifOCQ`1W*$tfr(7W&Rt)`)%+wuK>>spB3D
zg3fkqz`@Qg{#J2W+0b0a4VrJT&wiX5zM6
zM-rEUf&zDPBqSNL@aK+>zG>BCWfm}5alaLI^U?(@`x<1dxJv9~X@ba=(!>G#fv#az
z|02A+zB-R(-FimA&%oZnL9fiTq)4ZCjN&@qGyP{%88{ii7Nr{Ogj@7QWRhx08;qy9yS39{nM8Scf9U?TGoJy4AA%o$t+ImG(SJdKG
zSaDN6+L-_P;@Flp0hEmq(VLGjQb5-iilG<4$ZTYPbAH~YXrSJrCG^YV%}>$vb6FG4
z!g>%=5zGNUU*B6Ee_&*k(lU+xL!%(6Cn?Co!$U*#;07%yE`#x};f-i@4(4@S^|rIK
z3yoY);xb}zX%Wo8mexX<|YG_8Svfc()r2B(U3XwLF0hYH8xImWraZ&uoeSPwU~=q)a9-wBSr)
z;`R|C{4F~CEm~2AhKAx-Nl!42n5Mw)O50oCkm3Uipd#7W*ua>Uk^EvK2JN^RK5hV!
znHIuID{7`$rc$5t1gaUq1o6`sGi)3qG_0(wG&D5s+<~9q0b%i4zhp4#ibdBKARhz3
zYO9Nf^bW8dSW)&ct#&l9>Eya+6VU_oM!PcMU6wFj0JDL>csSQks-E7xa(#9V
zjym8s8Nss#fLDENT?c~2Pb=yp&fMHwNJxl5V}&qSG?qrkt)@7%Uy_&1tg92ba*;Hw
zMJT1DxH!rP%mk3iG8nbxx;YdgAw4}krsyV!dSyc#6`yB$*dafyAQQi;zOT0TDU4}x
zcf|FNuq}5o$K4=OAdroAV9T^}AM?YJ$eOX0#Kgn`6GtPXv3if?U1B=GxL0zS4SoZ-MU3d5@zk&JvG&pOaQaPWo2pi
zGBust+;lIbLPV}V6d$X0Qu*8)8X7w8>?J4H^6?|S85Iz1^IF5CrkhsnJ9A!rJw0Io
zflBu(`7DjFmiWRRa9N4GO|Y`E@*0KEQF(TaJMhJ;SH?3BLc_vTR8+tm6O4KHVt_X2
zr_xN_0|SZwD12UR9I(G~<%-G71GJx`(3n-M#HSiO5SX%*FDIL<=kVM!H-BeY&LHY;
z%Xaa_^XI?!d`-)|(CFZ@b3lDXkq5Kb3hRy}|8X;9-GuX0mBWxGRqxo?vg>V8QPHF(
zaAS&Ke!FDY6a&vbTA%Th0yK20CP3CaE#$YgS-wM{*bGKaN3uu`(cZFDVC@XY!bkNh&
zt9ZlLvW}Hv81Bqqf`Wq9>~c>JY8zY-l#i|4Vf;;d^=eYh&HJoGd-AkKzzfpSu6DBE
zf$T^C#+QzbFj0Y-~r$7GD(x4JMURz)yeBW#ra!tWox9TQV-@likgKCM?
z-jNXlJ-wRz8X{8CF~{l<>K$-b5Fg-6cp^qUxDDW5`bU0^O;OBi)fgN3y-yWLX=cW_
zLIj+5(xCt7C^MHPIwoe{w+Y;1fY1!?QDGGw&G{(~LV|+8H+j$z@loPv*Y2^g4iN1?
zZk0w>|J>sF-3o~2jnBnSElDe{?o&ZV7n9HGAvjXz@~6zwG7Zho%WGS7hw?mlD66m#
zX@AIOMwM_jBsoN4~)
z>CqV3Nk6`&Ib+RonJ{F&aBJOHNhz#j4mpF&2V7-%+`YW?^z^!pU%KArEPLUA?2W&!
z1TG3@Z;hV^E*V%JE`JTo^*0(bFqnz&YhUJqN=v!(`aXXHx8t(hOmqHe0-peeJRAJn
z-8VlzrekCTVJtwJDLirx2R55PMzH`h~GU@!*M1sxYOB?DVOi0>^sEKzsmn{5{~V-y#a;4n~={^?@&P{D}iq5Q^+N)dY7
zl>!ZQk_KWrJ5=AKRSwVavqv2X|p4Xt&b)UHQ9*u^eLUZ)Lhe}{X0jC
z$$m?P9SK{ibDo8HqU7qjdWH8^wde=gQ*;#MmV|i~rBv%4N$c&En@trfj03bCRk7R#IX0#PM;>2W
zN7sd+J8&2)OCoi1CfoGa_utcx58~Dn@?BBj>RQ6DroBr`%HP=M=)+FYM%O^Z5ouH5
zKwC$9|4#i|YGtmY4vuhYW8bDxpR#K7y>jo`EeaK}vy1MMrsJP>D|h(X{A%)rNo+~4
z)?F``yxFu)dR}LQVCj8+E~`P)vbe`L<`pUaZ3f8ZaoTCMDhBK7>x~JH7S)ZW8l}~P
ztjLX0{h2$Dtftgf0)BQ}Y~EL!A*c*`GUlwEzMgJrwHFidyBx?E~eN9wq`
z-l~$!06hS9ug?A=q2r$k+>d3S3mmdEYe1z_t6ky;fFw`QNk-5=J%$DAGI&6B=C
zg!^PUdm{(r>Qs$NnDwXI(u8YbiM$7aX`W6W-@MCtq~{QFw0Hik%sVCBn-5xa+7evH
zIbyW}^_5KBoa2S;Pk{5!XP4%(^(4lzwe+vkF1B;Ow*11I{WCTFY+5oCFA*1frKhTY
z`|$PS6^*UZzJaoXShMuHgiDVvb$uyXTJ0*>DMmfsXFfHA9n2+2g~qUj;|!
z`_sXd`s%L+1u<2rdZn?pjirjy1**?)k
zOrddxXe;FR9pr{Fa(C9yNn}u9z(bE=%tC6e*XH7(db%znd(Wi*dv>S!Uhy&tkMJ+(
zVkQz-3cDYeIj+h)2FP!MS*|zyI6mUqnmQlz*nfs#C7r72)x#C4uZ{P=u^iX`&bczt
zobg@i@uRt69`@PyW@g_v`Jo1CHnm~nk2fvsT|aX8IK#sKPZT8Vf9Ze!$yJ}L!s9$_
tt6&)yfrtLff0O}L<-h*VnJ4I7vy#F&?zC?ATtEYMM?p=#RMtH3-vG&vrl$Y^
literal 0
HcmV?d00001
diff --git a/library/Icinga/Util/Dimension.php b/library/Icinga/Util/Dimension.php
index f1371e46e..a08e68c32 100644
--- a/library/Icinga/Util/Dimension.php
+++ b/library/Icinga/Util/Dimension.php
@@ -48,7 +48,7 @@ class Dimension
private $unit = self::UNIT_PX;
/**
- * Creates a new Dimension object with the given size and unit
+ * Create a new Dimension object with the given size and unit
*
* @param int $value The new value
* @param string $unit The unit to use (default: px)
@@ -71,7 +71,7 @@ class Dimension
}
/**
- * Returns true when the value is > 0
+ * Return true when the value is > 0
*
* @return bool
*/
@@ -81,7 +81,7 @@ class Dimension
}
/**
- * Returns the underlying value without unit information
+ * Return the underlying value without unit information
*
* @return int
*/
@@ -91,7 +91,17 @@ class Dimension
}
/**
- * Returns this value with it's according unit as a string
+ * Return the unit used for the value
+ *
+ * @return string
+ */
+ public function getUnit()
+ {
+ return $this->unit;
+ }
+
+ /**
+ * Return this value with it's according unit as a string
*
* @return string
*/
@@ -103,12 +113,19 @@ class Dimension
return $this->value.$this->unit;
}
+ /**
+ * Create a new Dimension object from a string containing the numeric value and the dimension (e.g. 200px, 20%)
+ *
+ * @param $string The string to parse
+ *
+ * @return Dimension
+ */
public static function fromString($string)
{
$matches = array();
if (!preg_match_all('/^ *([0-9]+)(px|pt|em|\%) */i', $string, $matches)) {
- throw new InvalidArgumentException($string.' is not a valid dimension');
+ return new Dimension(0);
}
- return new Dimension(intval($matches[1]), $matches[2]);
+ return new Dimension(intval($matches[1][0]), $matches[2][0]);
}
}
\ No newline at end of file
diff --git a/library/Icinga/Web/Widget/Dashboard.php b/library/Icinga/Web/Widget/Dashboard.php
index 3217194fd..fee762c22 100644
--- a/library/Icinga/Web/Widget/Dashboard.php
+++ b/library/Icinga/Web/Widget/Dashboard.php
@@ -12,80 +12,121 @@ use Icinga\Web\Widget\Dashboard\Component as DashboardComponent;
use Icinga\Web\Url;
+/**
+ * Dashboards display multiple views on a single page
+ *
+ * The terminology is as follows:
+ * - Component: A single view showing a specific url
+ * - Pane: Aggregates one or more components on one page, displays it's title as a tab
+ * - Dashboard: Shows all panes
+ *
+ */
class Dashboard implements Widget
{
/**
+ * The configuration containing information about this dashboard
+ *
* @var IcingaConfig;
*/
private $config;
- private $configfile;
+
+ /**
+ * An array containing all panes of this dashboard
+ *
+ * @var array
+ */
private $panes = array();
+
+ /**
+ * The @see Icinga\Web\Widget\Tabs object for displaying displayable panes
+ *
+ * @var Tabs
+ */
private $tabs;
- private $url = null;
+ /**
+ * The parameter that will be added to identify panes
+ *
+ * @var string
+ */
private $tabParam = 'pane';
-
- public function __construct()
- {
- if ($this->url === null) {
- $this->url = Url::fromRequest()->getUrlWithout($this->tabParam);
- }
- }
-
+ /**
+ * Set the given tab name as active.
+ *
+ * @param string $name The tab name to activate
+ *
+ */
public function activate($name)
{
$this->getTabs()->activate($name);
}
-
+
+ /**
+ * Return the tab object used to navigate through this dashboard
+ *
+ * @return Tabs
+ */
public function getTabs()
{
+ $url = Url::fromRequest()->getUrlWithout($this->tabParam);
if ($this->tabs === null) {
$this->tabs = new Tabs();
foreach ($this->panes as $key => $pane) {
$this->tabs->add($key, array(
'title' => $pane->getTitle(),
- 'url' => clone($this->url),
+ 'url' => clone($url),
'urlParams' => array($this->tabParam => $key)
));
}
}
-
return $this->tabs;
}
- public function isWritable()
- {
- return is_writable($this->configfile);
- }
-
+ /**
+ * Store the current dashboard with all it's panes and components to the given file (or the default one if none is
+ * given)
+ *
+ *
+ * @param string $file The filename to store this dashboard as an ini
+ *
+ * @return $this
+ * @throws \Icinga\Exception\ConfigurationError If persisting fails, details are written to the log
+ *
+ */
public function store($file = null)
{
if ($file === null) {
$file = IcingaConfig::app('dashboard/dashboard')->getConfigFile();
}
- $this->configfile = $file;
- if (!$this->isWritable()) {
- Logger::error("Tried to persist dashboard to %s, but path is not writeable", $this->configfile);
+
+ if (!is_writable($file)) {
+ Logger::error('Tried to persist dashboard to %s, but path is not writeable', $file);
throw new ConfigurationError('Can\'t persist dashboard');
}
- if (! @file_put_contents($this->configfile, $this->toIni())) {
+ if (! @file_put_contents($file, $this->toIni())) {
$error = error_get_last();
if ($error == NULL) {
- $error = "Unknown error";
+ $error = 'Unknown error';
} else {
- $error = $error["message"];
+ $error = $error['message'];
}
- Logger::error("Tried to persist dashboard to %s, but got error: %s", $this->configfile, $error);
+ Logger::error('Tried to persist dashboard to %s, but got error: %s', $file, $error);
throw new ConfigurationError('Can\'t persist dashboard');
} else {
return $this;
}
-
}
+ /**
+ * Populate this dashboard via the given configuration file
+ *
+ * @param IcingaConfig $config The configuration file to populate this dashboard with
+ *
+ * @return $this
+ */
public function readConfig(IcingaConfig $config)
{
$this->config = $config;
@@ -94,6 +135,11 @@ class Dashboard implements Widget
return $this;
}
+ /**
+ * Creates a new empty pane with the given title
+ *
+ * @param $title
+ */
public function createPane($title)
{
$pane = new Pane($title);
@@ -102,12 +148,22 @@ class Dashboard implements Widget
}
+ /**
+ * Update or adds a new component with the given url to a pane
+ *
+ * @TODO: Should only allow component objects to be added directly as soon as we store more information
+ *
+ * @param string $pane The pane to add the component to
+ * @param Component|string $component The component to add or the title of the newly created component
+ * @param $url The url to use for the component
+ *
+ * @return $this
+ */
public function setComponentUrl($pane, $component, $url)
{
if ($component === null && strpos($pane, '.')) {
list($pane, $component) = preg_split('~\.~', $pane, 2);
}
-
if (!isset($this->panes[$pane])) {
$this->createPane($pane);
}
@@ -120,6 +176,13 @@ class Dashboard implements Widget
return $this;
}
+ /**
+ * Return true if a pane doesn't exist or doesn't have any components in it
+ *
+ * @param string $pane The name of the pane to check for emptyness
+ *
+ * @return bool
+ */
public function isEmptyPane($pane)
{
$paneObj = $this->getPane($pane);
@@ -130,6 +193,15 @@ class Dashboard implements Widget
return !empty($cmps);
}
+
+ /**
+ * Remove a component $component from the given pane
+ *
+ * @param string $pane The pane to remove the component from
+ * @param Component|string $component The component to remove or it's name
+ *
+ * @return $this
+ */
public function removeComponent($pane, $component)
{
if ($component === null && strpos($pane, '.')) {
@@ -143,6 +215,11 @@ class Dashboard implements Widget
return $this;
}
+ /**
+ * Return an array with pane name=>title format used for comboboxes
+ *
+ * @return array
+ */
public function getPaneKeyTitleArray()
{
$list = array();
@@ -152,40 +229,49 @@ class Dashboard implements Widget
return $list;
}
- public function getComponentEnum()
- {
- $list = array();
- foreach ($this->panes as $name => $pane) {
- foreach ($pane->getComponents() as $component) {
- $list[$name . '.' . $component->getTitle()] =
- $pane->getTitle() . ': ' . $component->getTitle();
- }
- }
- return $list;
- }
-
+ /**
+ * Add a pane object to this dashboard
+ *
+ * @param Pane $pane The pane to add
+ *
+ * @return $this
+ */
public function addPane(Pane $pane)
{
$this->panes[$pane->getName()] = $pane;
return $this;
}
+ /**
+ * Return the pane with the provided name or null if it doesn't exit
+ *
+ * @param string $name The name of the pane to return
+ *
+ * @return null|Pane The pane or null if no pane with the given name exists
+ */
public function getPane($name)
{
if (!isset($this->panes[$name]))
return null;
return $this->panes[$name];
}
-
+
+ /**
+ * @see Icinga\Web\Widget::render
+ */
public function render(\Zend_View_Abstract $view)
{
if (empty($this->panes)) {
return '';
}
-
- return $this->getActivePane()->render($view);
+ return $this->determineActivePane()->render($view);
}
+ /**
+ * Activates the default pane of this dashboard and returns it's name
+ *
+ * @return mixed
+ */
private function setDefaultPane()
{
reset($this->panes);
@@ -194,7 +280,12 @@ class Dashboard implements Widget
return $active;
}
- public function getActivePane()
+ /**
+ * Determine the active pane either by the selected tab or the current request
+ *
+ * @return Pane The currently active pane
+ */
+ public function determineActivePane()
{
$active = $this->getTabs()->getActiveName();
if (! $active) {
@@ -211,6 +302,11 @@ class Dashboard implements Widget
return $this->panes[$active];
}
+ /**
+ * Return the ini string describing this dashboard
+ *
+ * @return string
+ */
public function toIni()
{
$ini = '';
@@ -219,23 +315,24 @@ class Dashboard implements Widget
}
return $ini;
}
-
- protected function loadConfigPanes()
+
+ /**
+ * Load all config panes from @see Dashboard::$config
+ *
+ */
+ private function loadConfigPanes()
{
$items = $this->config;
- $app = Icinga::app();
foreach ($items->keys() as $key) {
$item = $this->config->get($key, false);
if (false === strstr($key, '.')) {
$this->addPane(Pane::fromIni($key, $item));
-
} else {
- list($paneName, $title) = explode('.', $key , 2);
+ list($paneName, $title) = explode('.', $key, 2);
$pane = $this->getPane($paneName);
$pane->addComponent(DashboardComponent::fromIni($title, $item, $pane));
}
}
-
-
}
}
+
diff --git a/library/Icinga/Web/Widget/Dashboard/Component.php b/library/Icinga/Web/Widget/Dashboard/Component.php
index 3690e29f7..22aa99d14 100644
--- a/library/Icinga/Web/Widget/Dashboard/Component.php
+++ b/library/Icinga/Web/Widget/Dashboard/Component.php
@@ -10,21 +10,49 @@ use Zend_Config;
/**
* A dashboard pane component
*
- * Needs a title and an URL
+ * This is the element displaying a specific view in icinga2web
*
*/
class Component implements Widget
{
+ /**
+ * The url of this Component
+ *
+ * @var \Icinga\Web\Url
+ */
private $url;
- private $title;
- private $width;
- private $height;
/**
+ * The title being displayed on top of the component
+ * @var
+ */
+ private $title;
+
+ /**
+ * The width of the component, if set
+ *
+ * @var Dimension|null
+ */
+ private $width = null;
+
+ /**
+ * The height of the component, if set
+ *
+ * @var Dimension|null
+ */
+ private $height = null;
+
+ /**
+ * The pane containing this component, needed for the 'remove button'
* @var Pane
*/
private $pane;
+ /**
+ * The template string used for rendering this widget
+ *
+ * @var string
+ */
private $template =<<<'EOD'
@@ -39,7 +67,13 @@ class Component implements Widget
EOD;
-
+ /**
+ * Create a new component displaying the given url in the provided pane
+ *
+ * @param string $title The title to use for this component
+ * @param Url|string $url The url this component uses for displaying information
+ * @param Pane $pane The pane this Component will be added to
+ */
public function __construct($title, $url, Pane $pane)
{
$this->title = $title;
@@ -51,18 +85,28 @@ EOD;
}
}
+ /**
+ * Set the with for this component or use the default width if null is provided
+ *
+ * @param Dimension|null $width The width to use or null to use the default width
+ */
public function setWidth(Dimension $width = null)
{
$this->width = $width;
}
+ /**
+ * Set the with for this component or use the default height if null is provided
+ *
+ * @param Dimension|null $height The height to use or null to use the default height
+ */
public function setHeight(Dimension $height = null)
{
$this->height = $height;
}
/**
- * Retrieve this components title
+ * Retrieve the components title
*
* @return string
*/
@@ -72,7 +116,7 @@ EOD;
}
/**
- * Retrieve my url
+ * Retrieve the components url
*
* @return Url
*/
@@ -82,10 +126,11 @@ EOD;
}
/**
- * Set this components URL
+ * Set the components URL
*
- * @param string|Url $url Component URL
- * @return self
+ * @param string|Url $url The url to use, either as an Url object or as a path
+ *
+ * @return $this
*/
public function setUrl($url)
{
@@ -97,35 +142,29 @@ EOD;
return $this;
}
- protected function iniPair($key, $val)
- {
- return sprintf(
- "%s = %s\n",
- $key,
- $this->quoteIni($val)
- );
- }
-
- protected function quoteIni($str)
- {
- return '"' . $str . '"';
- }
-
+ /**
+ * Return this component in a suitable format and encoding for ini files
+ *
+ * @return string
+ */
public function toIni()
{
- $ini = $this->iniPair('url', $this->url->getRelativeUrl());
+ $ini = 'url = "'.$this->url->getRelativeUrl().'"'.PHP_EOL;
foreach ($this->url->getParams() as $key => $val) {
- $ini .= $this->iniPair($key, $val);
+ $ini .= $key.' = "'.$val.'"'.PHP_EOL;
}
if ($this->height !== null) {
- $ini .= 'height: '.((string) $this->height).'\n';
+ $ini .= 'height = "'.((string) $this->height).'"'.PHP_EOL;
}
if ($this->width !== null) {
- $ini .= 'width: '.((string) $this->width).'\n';
+ $ini .= 'width = "'.((string) $this->width).'"'.PHP_EOL;
}
return $ini;
}
+ /**
+ * @see Widget::render()
+ */
public function render(\Zend_View_Abstract $view)
{
$url = clone($this->url);
@@ -141,14 +180,18 @@ EOD;
)
);
-
$html = str_replace("{URL}", $url->getAbsoluteUrl(), $this->template);
$html = str_replace("{REMOVE_URL}", $removeUrl, $html);
- $html = str_replace("{STYLE}", $this->getBoxSizeAsCSS(), $html);
+ $html = str_replace("{DIMENSION}", $this->getBoxSizeAsCSS(), $html);
$html = str_replace("{TITLE}", $view->escape($this->getTitle()), $html);
return $html;
}
+ /**
+ * Return the height and width deifnition (if given) in CSS format
+ *
+ * @return string
+ */
private function getBoxSizeAsCSS()
{
$style = "";
@@ -158,8 +201,18 @@ EOD;
if ($this->width) {
$style .= 'width:'.(string) $this->width.';';
}
+ return $style;
}
+ /**
+ * Create a @see Component instance from the given Zend config, using the provided title
+ *
+ * @param $title The title for this component
+ * @param Zend_Config $config The configuration defining url, parameters, height, width, etc.
+ * @param Pane $pane The pane this component belongs to
+ *
+ * @return Component A newly created Component for use in the Dashboard
+ */
public static function fromIni($title, Zend_Config $config, Pane $pane)
{
$height = null;
diff --git a/library/Icinga/Web/Widget/Dashboard/Pane.php b/library/Icinga/Web/Widget/Dashboard/Pane.php
index 6749da12a..43087cdc5 100644
--- a/library/Icinga/Web/Widget/Dashboard/Pane.php
+++ b/library/Icinga/Web/Widget/Dashboard/Pane.php
@@ -7,39 +7,97 @@ use Icinga\Exception\ConfigurationError;
use Icinga\Web\Widget\Widget;
use Zend_Config;
+/**
+ * A pane, displaying different Dashboard components
+ *
+ */
class Pane implements Widget
{
- protected $name;
- protected $title;
- protected $components = array();
+ /**
+ * The name of this pane, as defined in the ini file
+ *
+ * @var string
+ */
+ private $name;
+ /**
+ * The title of this pane, as displayed in the dashboard tabs
+ * @TODO: Currently the same as $name, evaluate if distinguishing is needed
+ *
+ * @var string
+ */
+ private $title;
+
+ /**
+ * An array of @see Components that are displayed in this pane
+ *
+ * @var array
+ */
+ private $components = array();
+
+ /**
+ * Create a new pane
+ *
+ * @param $name The pane to create
+ */
public function __construct($name)
{
$this->name = $name;
$this->title = $name;
}
+ /**
+ * Returns the name of this pane
+ *
+ * @return string
+ */
public function getName()
{
return $this->name;
}
+ /**
+ * Returns the title of this pane
+ *
+ * @return string
+ */
public function getTitle()
{
return $this->title;
}
+ /**
+ * Overwrite the title of this pane
+ *
+ * @param string $title The new title to use for this pane
+ * @return Pane $this
+ */
public function setTitle($title)
{
$this->title = $title;
return $this;
}
+ /**
+ * Return true if a component with the given title exists in this pane
+ *
+ * @param string $title The title of the component to check for existence
+ *
+ * @return bool
+ */
public function hasComponent($title)
{
return array_key_exists($title, $this->components);
}
+ /**
+ * Return a component with the given name if existing
+ *
+ * @param string $title The title of the component to return
+ *
+ * @return Component The component with the given title
+ * @throws ProgrammingError If the component doesn't exist
+ */
public function getComponent($title)
{
if ($this->hasComponent($title)) {
@@ -51,6 +109,12 @@ class Pane implements Widget
));
}
+ /**
+ * Removes the component with the given title if it exists in this pane
+ *
+ * @param string $title The pane
+ * @return Pane $this
+ */
public function removeComponent($title)
{
if ($this->hasComponent($title)) {
@@ -59,11 +123,19 @@ class Pane implements Widget
return $this;
}
+ /**
+ * Return all components added at this pane
+ *
+ * @return array
+ */
public function getComponents()
{
return $this->components;
}
+ /**
+ * @see Widget::render
+ */
public function render(\Zend_View_Abstract $view)
{
$html = PHP_EOL;
@@ -73,6 +145,15 @@ class Pane implements Widget
return $html;
}
+ /**
+ * Add a component to this pane, optionally creating it if $component is a string
+ *
+ * @param string|Component $component The component object or title (if a new component will be created)
+ * @param string|null $url An Url to be used when component is a string
+ *
+ * @return Pane $this
+ * @throws \Icinga\Exception\ConfigurationError
+ */
public function addComponent($component, $url = null)
{
if ($component instanceof Component) {
@@ -80,24 +161,24 @@ class Pane implements Widget
} elseif (is_string($component) && $url !== null) {
$this->components[$component] = new Component($component, $url, $this);
} else{
- throw new ConfigurationError('You messed up your dashboard');
+ throw new ConfigurationError('Invalid component added: '.$component);
}
return $this;
}
- protected function quoteIni($str)
- {
- return '"' . $str . '"';
- }
-
+ /**
+ * Return the ini representation of this pane as a string
+ *
+ * @return string
+ */
public function toIni()
{
if (empty($this->components))
{
- return "";
+ return '';
}
$ini = '['.$this->getName().']'.PHP_EOL.
- 'title = '.$this->quoteIni($this->getTitle()).PHP_EOL;
+ 'title = "'.$this->getTitle().'"'.PHP_EOL;
foreach ($this->components as $title => $component) {
// component header
@@ -108,6 +189,14 @@ class Pane implements Widget
return $ini;
}
+ /**
+ * Create a new pane with the title $title from the given configuration
+ *
+ * @param $title The title for this pane
+ * @param Zend_Config $config The configuration to use for setup
+ *
+ * @return Pane
+ */
public static function fromIni($title, Zend_Config $config)
{
$pane = new Pane($title);
diff --git a/modules/monitoring/application/controllers/ListController.php b/modules/monitoring/application/controllers/ListController.php
index 46d5cd6ac..38d53bf3f 100644
--- a/modules/monitoring/application/controllers/ListController.php
+++ b/modules/monitoring/application/controllers/ListController.php
@@ -60,6 +60,8 @@ class Monitoring_ListController extends ModuleActionController
$state_column = 'service_hard_state';
$state_change_column = 'service_last_hard_state_change';
}
+ $this->compactView = "services-compact";
+
$this->view->services = $this->query('status', array(
'host_name',