From 82d5d1b003823cda4064ae91a488425bac44e3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Feb 2016 09:53:56 +0100 Subject: [PATCH 1/5] feat(plugins): working on plugin examples --- examples/nginx-app/css/dark.css | 0 examples/nginx-app/css/light.css | 0 examples/nginx-app/img/logo_large.png | Bin 0 -> 14460 bytes examples/nginx-app/img/logo_small.png | Bin 0 -> 6430 bytes examples/nginx-app/module.js | 28 +++++++++++ examples/nginx-app/panel/module.js | 21 +++++++++ examples/nginx-app/panel/plugin.json | 6 +++ examples/nginx-app/partials/config.html | 1 + examples/nginx-app/partials/stream.html | 12 +++++ examples/nginx-app/plugin.json | 44 ++++++++++++++++++ .../module.js | 0 .../panel.html | 0 .../plugin.json | 0 public/app/{grafana.ts => app.ts} | 0 public/app/boot.js | 4 +- tasks/systemjs_task.js | 2 +- 16 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 examples/nginx-app/css/dark.css create mode 100644 examples/nginx-app/css/light.css create mode 100644 examples/nginx-app/img/logo_large.png create mode 100644 examples/nginx-app/img/logo_small.png create mode 100644 examples/nginx-app/module.js create mode 100644 examples/nginx-app/panel/module.js create mode 100644 examples/nginx-app/panel/plugin.json create mode 100644 examples/nginx-app/partials/config.html create mode 100644 examples/nginx-app/partials/stream.html create mode 100644 examples/nginx-app/plugin.json rename examples/{panel-plugin-boilerplate-es5 => panel-boilerplate-es5}/module.js (100%) rename examples/{panel-plugin-boilerplate-es5 => panel-boilerplate-es5}/panel.html (100%) rename examples/{panel-plugin-boilerplate-es5 => panel-boilerplate-es5}/plugin.json (100%) rename public/app/{grafana.ts => app.ts} (100%) diff --git a/examples/nginx-app/css/dark.css b/examples/nginx-app/css/dark.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/nginx-app/css/light.css b/examples/nginx-app/css/light.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/examples/nginx-app/img/logo_large.png b/examples/nginx-app/img/logo_large.png new file mode 100644 index 0000000000000000000000000000000000000000..c28955960e4d842f8d47496e9382e7ceadae2100 GIT binary patch literal 14460 zcmcJ01zS|#7w!Nf3{oR8got!WNlKRpNP|dAgCgBMG}0x^k48kKQ@XnZ6hXSAyQGKV zp27dU-{3y#gPgt3+N<~8YrQ8zT~(goKGl5?2t=T$@LUrF!UX<{34&k)KmK}-UjaX` z&6MPygKp7(a$3G70Z(up74%#{AUqQEKMYV>1_kgC$5l~94rd7y7s8F-zx+WE1fm5g zK9_#wIkPwK@!zYp>As_b)Ktr@*Uu}@WnOVq@VQrbXlRU2U4PFd{(Mx^_m)FLW16z^ zVT^``MoH!80=_3^6++!Xxk0*8GbzFckMRl=mDQ&$twzq149UZGc$-H3M!uhjo(qq< zNF_2V{{Q%EBOsgjTPpHH2va<}p&)K5reV!HDX~g^jBx3S#}%+24=zYOgLs-TgU$nl z@n?x+AKLBZ-G}L77Iv0z;*guX&9?b-6dq6-P;`6jpv<`XocGda0|!TujLix+?`89L z`Mb+%_FV<8Q=C6X)9tml=Epd?2>}mQHREI|0z*IUf)vH?p!~`JC6+{y{cT~D2wL*8J!(~RrJz`E z&OX2b1Pp^a7FIP6pkO#=(d-`<%!kBLekxq2tXv?E z9G^x=2%JaAvSc%pKXE%0f+TnrrHqmlB2L5yCHj|nmHyqimhOr^rF{)*{P+_xLYFC7 z&Qx!Ulgc8NkEQ_^;KvQV&%@tEnGg&=<1YU~yk)njrpVTrnt5^QnWPF_c4< z%T45HDT+4>iSe2qV$X=6!sl0#($#}EwU!yOa5L0I;LCBn+yfw5xtB&oBv0+ZXHnzzvaNxRK5r?M z*4GZ@iytx8;AUgQ&y2;dp5JCD5z_Up_N$;c5j0UGU~@=OU&2l`ad4mXZ)+?@QIICn z(3dmJDk-9y!tKlZW1>aRH4ZGxbsmn^rnsD=BrpNqPvoeQ69>BC zc%k^8Y(F9Yckh&r6-NfT0m6W9j`%k}wc#me9sDe}iJB_ye6Ktxl*+7RvB^xPQeMje zyxz#1&>V_-1P9n>x-%|uZs`Hb zt#d;Ot}5dP6=nny3pCkeq0S3ZxE&HO7;cHQpmZ*rjp&hRN1T0pPh9`OaGPKq?4ySV z_{dE++3g%lf4Ws2OL_?t%{3;)ThqY>Z}6NF*Qwa_cqHJ2F(HhAv((e!%EM?8yF?wQ z^?Bu*!x;O_nYX21;sI%S(%%5tL7Jy?pe+$7X;V8}THmPy6P#b^{5rO7E)s8em2!53ZNk6;zaiSg4Fb~IDY#=j;2|!+ zMRMq6=`4@5V8fG$ZhTrh)4zPDflIpaxYq`ml0b;1LKGwC+| z&1*S8j@s0Vq!vi9DR^8LpVLhK=bSHI@EcoK20BVm-fvArB*}_~i9ysS;$s3+r-!_! z_ z7Acj!h*k>l;|QZ)eGegGGV%mnplT+7j7#=jfqS$08MXNRszQ!Hhi$DqKk3S;^qH#& z3D$zzbxu%CX~#;A(+I6|p`t2^cpeA}W<+CV#Z*MKPcyZ!=G%HbR@y_xaShP ziEtFduu#0NuSmmcWk_W#X#7h_q<(T8X#A>dsy@wqLJgBm_Um6sl~4Vs@%8Mp+JIe9 z!S}MOjk1k4*Di{NRlRS;S@&%BFPS;x?YliA4YxIda=wJ7xEYvIf?f@-*Ko{+I#msD zZcSBE2Ax#=V!R<11>G_tiWp$8^$39}X;q2^!(Bhdslb($;ErmToIWdWNF{fF{s?Gk zJrjh)&jpLzZIW~FZh!p#cFWS)g=&O+13i&^;YR#Uq_{!3y;7Z>MZa=74CU&5;b2H zE`jLjMW%HeXCQg$pASkl5KB8^Rb=+W!y2$V9YHZ-{feRVvWYxXv4Hq*O)0K|nG~kS z9fM4QlGQn1Bu;xw2tFt>lCC9Z z#msS+FJ6UH4f+Ps(E)oAnK6nx9j=TDeQX3p`wl|oCL&-FYmYOGRFCcu7SqEiT#0(J zt;xxKs>yf(HDP4FURb9_LDDfANtu*;X_ zi+0ms2v$)f`ZuybX+U!-`9D@s81A4~u>dvrn+m5O!)=TYe%q_uTX16-b{z@$KnpPw zri@WG-I+!KdIejr+0PGu>Rf29m+OsP@vya2Z7j$jf0BBPdDu(M?#gph?6F(HFHL#lA;BWAs1Q~W*H5WFB(|OVkS3WMRan+_f=wV2Ny+}%tpmJ% zP{AEE9#&Ooj!SX>l^(vLT^^-pnybH$k|{`iRt-5z;z(B!(G&me11at$Nw)8`JeMz@ z>$Hj25ll)?`Al-A-};?%VK}bm_W|QE`fORu5!0R?t9T{5ms&q~zt$%Jxs%hP!2%Z4 z6%Y%P)x`Ar(vnDk#$mVQ0gb-kbPR0)&g&YU#K9j&zQUFi)^T;j*r1#90l588N!e&(_a7ll zAAM3qOM5Xn)h~kZ@-IA~O=F`;@>qYW?ZihPoS@)IJyOMFCf^V7N&Td@I2539=ZWkf zW&ee$*6Tx>w!HhQ80~v`Cpdcdu>!UeA42iMfYU-)-iQD24W&fj$pF3Qo00H+Ka{Pr z6Xr-bt+@uHoFF9R?^@JUdd9h!J);Gvz_(#suboYbJc^F(Ph>kDzkuBkt~nJ&Vn|0= zK<$zQ$j-~g_=V56 zP-zp2j1rjpn8dIbiT=qe5l6Vwt9qQ|`tDfxASRay$#V<*pyYus`*a^-aJ+RX6!ky2 zXhSpPxdgIkDc%ah2p?l2YqmA_a68Q*K~Fft7;8cgptmb7+?&8nfnVD3Nkz!Lggik6$ejt1CMS4$6I&$ft(ST) zbC9EBR2{Lcz|o8w1lWWz`6DHi88=v{e^qunQGF*i$Q=X=Gu)Oj^Ic!%R%9w90hd2G z-Y`zy{!U6Kib0Xd?){(20Sm1SVlZdjTO*N+$6k0# zU&l}PUveA)2j`ynyej^59gZ&UK7c6Fdu8Ut#20LkO@dqQo{n- z2X;XvsI9e7JLu4S(P33fMNlB%EJC>bXBJiBtEYm@5E>RlV=%4mm@@?^r!0T%i}l(K`Y}t;Pu(K$?|%EmZ)UOS~ijWjVJ^=LCJ4$ z!WiGe5hKhFHX!r-fUbRaPUm!8(+9+G!=a%0F?2MM%XYY*ahI~x4=Z;9gJSIc!YaH3 za17j_(takqUA+L?K|-le4^RpNgxPBh@xhEFM2K*tmL5^U8enLOLroW@W@?K zMB7?$*vjgctrh?9`p)#P3+J=C?-_ihYy5;}&?p17n&nXQ2a&^2r5~SNgc?0`6MJUd za^E+NNL>W;37P1xDCY}(H#y#QxcJ+|#xFD+q?^0etQ|qERz{a3IRa82a4wASY-?j| z6%(!7`R*is{^!um-LkX?xM^WxVg}``DV<2dU&!jCW{0R`nC4EApZoQtw`5E$n zKgL=?CcpL@XiUpI6Io1bprWmnIE<|BqHolgqxG^GkRv`f3N>lAvEtJyZ+JARc@>z*y6;j=6g&m z`=%lDC&`Y%h&JaScMW_$Vb2aVYW!aF%>)>0C->us z{5l@J83wHYY-)UKud=|=EYexoQh>aR}fG=I8Ie(c7k2KjOCM~@}>QE~;z zPwxn2YbBChM_b;Jm)qRLDeJBtMQ~T0$hK9VMZJ7F7eCWktU+NjZZE;PHa#y$a!VCe z+OBmI?$mb%*I!MNlLb@;0b!Z@ehym+xBMLrFV9FeQ*fB9vr8C zTs^3Bi;MB{oE*Bm_#m&_K$az|emR@xqb6~+*JAtauYT0(M)?mf%B%x8K~s6HK#0Gc zFt><$GBO#Cb-w5N06tqLMpLa@c~YhPY}0;!aV;?=ob)DF+XV~IU*CUz4y+Nz8>md~ z<=qAOk-gW7*r4RRcpQ(mNO7I{qGkz@bo9K=LQwvSvB|l1T}Zw#&0v34=kRW&w`ACX zBT9`+)`%1}b>#vb%Qi^J_1xQ`-ZN|XiqY>+_FTV>uEbo5PjGV+-=(REO@w8>g)6&Ly zGjraXhs zJiMn^6oD+is@ofJvJAin>Hkf-bJ(0rF}FA@Hy@LaLT>ZG5mB_?N+;v zD{9g0hDqnE{f-s^1~2ICPu2Jp>^aS!<|UC#o~^e6yOl*smF(x+Z3!pdkBwfp9Y5XK z8{oBT{+y2w8k>u{rN^3_%d!;Vco4B1J9la3%~jKw8Sqlec6}TOiJp<6k48K)3Ih@If{^#rfD}3)>$R2rkz!gsRVoi!We-_s0s2SVp$|Ec8(OEOtEc`$j3Jw1c1= z!4~AkN0qo7^X>)x-&`q6Kj+JG{Bmcsa%9F`4-~_BC9>LPmq0|h0A0}|T6E091}e+v zEcJSKT^Mi|$6uq;toYvEU@+AzkB-(14YFmcBw$F{eKpTbt06aLt6Di|SS^~X7~ZlU z)<0YH#XV!MHhOY9;gDh&vmN44^AVW)X{x)m_?!uLlzB|3=VPt9@E7vFuNHwPFaI^2sUte8{f883QDu| z)(>yUnlooD=B%Y}wQOt#SMoc`J7<#ubJaBe&-L4On$$%ZQ5R_MC15ETJD z85tELb1&7dII3xc?0srSu|5vxQNH>i0mGPZ(!m4{!>?ak7GJYGY8|n+`2E-f!upvj zAX|wN#K=kNW{~wA{KJ(LcLWSuFLD1GzsJF& zL)XBDjYKm>|4d{aW!{kw=?;GO_~z_QqnmC}yYn6WpEX7-`}137GEE@#``>I^cdx`6 zXOm$vz=bk0?a}MqF1>UbLX~RZBmh+0m^Mx&(gJsO_i643jwAi9Pu5%c+M%@Q^&v4W_|&rDQC{{AyF_{v?z%)i@QTK#ddrD<2-t9%S=$;O8kF{((=K- z*GzUN#o(U_qyHR#KtvdefTI;!=wkQ14gxYDqM?Reye-dSY5z|F(D zefuV-q2r%WyuRTlil1b-itQ;SseaxY{hycQJx~U2e8mtIy@e;9TD3yS1$^>sNbc2-F)BPz!4=i$B!y zZ_>um@kbAOfqlI9W42>>ic17a>scWCOA(-gfzNSl#0f;{|a$4dlUs65V@2Ou&n#5ogq*+r$f~ z_0I|f*F~Jz)u^%eSIX$>dv39?tyQon(fTh+Er50M^M=6WMy@C|Fq&i)Rg{YDZF>YM z!#7jaYfsTPn{dvFBlj#2+SFxrt!eEqx`<-N|3e&%$5>w*?}^^AX(}D9)8-qOWK2O- zXnMY1%O!LwN|LtjdB6Sj|ivpq_bQ;6IeDK}=w-A&;a*J$)6+ddcLTjjObXfGw(m&N- zl8|h4A{>~{dp`hb`cdPt{KL)T6i7Az56&#Ks_WBAlsD7$z}R}Lb=3jYtTz&^T|0xg z?}q~(Nelw(23MKG_cNQOanS{H*HF`b>@K3%@&7~_i@eU;mpNX~PmoBV^Wf>}uEX?p ztLrxzsphnB_ZHH$hhi9Li8Q36e`ZI2a{p_YKy|i0WZ&LD9|kJJN0WQiQ{3O`PA=4X zW0Duv(#LMV>)939`s^<6?SrW=FNDST*z})ZaV_pXcQO_=g=K(ditHFu+$QtKB;`6k?8UIMNyMyMze0rAI4{i0ao(7f&$p8TR+`O zssf5a*e)gms+ZYB-Pyj1h2?kkq$CPj_>`sTHmu2`@kcP)qgg#L|3qgTa!j@e^J;c2 zSl8G+^IMUfXFv}t(f*L622E&u1)rV~a}r^}1-`=8oz+%NHV zI4bY|6WU_fCSy3VZg=2Y7-a(0`H7FQEO1u+=YR#YOS8aJA6CbK?Xu?9TRU~zGwM6V zi{Chj}uKs@YfPOh2L(>mw+!hLJG{Tuho`n3J>IM zrVtMP^lf@JZjf|woPVi9YJ0)_zX|HhT2HYLM>GC#^J&!~&wsk)qq45rG72YoQNoGx zy*2&utm`fjCD>sdu8$uj7*JN|Pp)}cEw&LuJ@2Dae^K@(*dq=edGe<5DGw0q$&lQCo~6;lV{s!&XrbRt6YukG@uA+kN}7MsP(j;k#Sj}a9={@;@%6mF(WnAV zY%hj;(J~xIEqeSvot>HB&Q>AsLv+qvQ}YVyV~LHJ8w^OBCmiwufyi&rSOCl4D`Bm- zI1jw-s?hd!81XV?6>7Or&+GN=7HM+%9)<-RMgI9*`_Io@7M>rm!0eUJfQ+uBlB9%`31oJ0lT&}!gZjKaV{DKTur20_%Zs^5thC*9>jQKYe{O@jH@!BbeI-tw zya!rEjB<*yE)3~0&t_!M!x|?Y-_)khP|`3Nz|$f>()MaS-Vko_|E~r}jEVG23$b{8 zsAPi$um494Ono)(6^*jZ_%|aN12VN7m~`R0{wnH@yd31az5SAq2kN)k-2!}WzlChi z+j0Nz0!ssNZdbhe8+Wc&U$&5rZs3kBKApS=Ab+Cn!Khl^MN`-kn(y?QWNv;@(#y&HUAs}@(R z?|PhUHZ&+l{_DH#Kd-`Z`$xUSiWRKj(opp80;4KaLl4x9P3X}3-&?+8 z2Xj~Zk|lTJY)3YPUdLiD8txKWWL73XJp7krH54uRM?g(EqvG<%nFr|YIx*LB@Oyb- z!v-tfof=<457%{8gs)Pg{?RIhLN~5-4$S(W)ES_gw``ik6UhD0PtAvy@BeX|HhdtQ zi2I9K4}u=nUlhcxZ9MSYxpSD|ufHU%yOwdZ@PYdPT1_KDsu?<8TSpZ~jZHbx+!s(@ z4L-_v1CI&4W9D=?X(<=sU^@Pl``>aeWn``vT)+qZd_V8(ngDD8oCl&KBL9r+wf^dN zgCFhi-42pS&-meJMCh^8cUIuskM=pvdyXqR9xfeI>74&G6LFT2I;wfwlm3tQkDg=( za~>QHem8WVChi#cTsWoNc8&A2#VM@k?!oFws#amcH7jt${3k+UT^lOEk4Aj{&XE&{ zyFE=hS-E^KVgKBG=OKH?)~IpEXA(U08gDf&%ig{2iMD+Gi<X>ktGdSyd%Px2_Lk=wLK30uz{v}Ez*NFY=q4n`x9()D^kim}5WU$2H zKmL`WDw>{q+>7{?>_paja2KX$_TxRx*Ta1YoE-&f#%IDXV10M0w1)$TqX`$S%G8Go z-k?9&0acRZQ7R=j=NP^M*7}Tn@Zod@C#ERi-mk?X;UPDT+9zqd4pJLx4*v8Q^5^d( zy@w5^aGo1J8mik6bP}p5RcpHmX=^*z1&S`gSxp&cmD9nx(rvZQh&5bGHe< za*A4T(32~l3y`<^Doy(>$D(%0XwrBFuk*>yIbkffm&HKDAAEk`2~-%9xfgrR+JL$f zMn zg4m6_$!&aR)jHz#$sBKbT2`{nx|YLvnhHPBhkH(G!PBm3fRM_OLxwgvP&Sv}l$J}b z5?xX=7KvMt-NwK+CJGNKXY8&I2ciea1imF@wFUY39;yKay2z*5EuC~~Svpm1i**Ei zQ&tvX>lK?Fk_!3Zb5|o><1PMb z12;Cnr9`mh+L3wmYG#F08rbmKKU-I9FnmopeHPa2jUzAalqHG+_|t4&ihTNZJp1z3 zRQk(5leoC4Kc7Wqc~JLXI7l2{JfFKEc~LnYBZ|(a$@2$UG&kh_=W}HChQR*!vVlZ> zczV=$0C&_#wf+M+L^bPFpk-g=qeojNB#`^%kpWkSj!VANuGU8N@}aD!+xA7`ZE{=2 z4X3DtC$UbOdz=mmC?Mg#aLnhx0?%){wESb91z}a(nU26j?_iPIHBbpNZA^ z8fy)lY0T$E30bGlA#*n<*4M2yl5r{}9>)j_skOEFa!Ip+haP{@gl5XtM1YERxR@7> z!MxkloTX-2(r@@{{3xIR9bV%19$s62{>(b4JaUDRt$@KHgp={Ln?mc` zlGkOw>$LsHzw+ffqNdWl4nJ>Pt~L!o!}j-e*wd`tOn%f)V+XuUQrUaaj+M0>rSQvE z;oC;LfQJbpS;)MF>9y%;+0d^Vqp!D@<^IR>7QJfMAwV8k&cglN56=jHj>F<#qe%hz z!C&=Sx%}wzGlElf&FAk!==Myq4F^~QwCcwIN4-?rcrXDq7LGu0;cF_%dKJ`5( z2qWiM1f*ENDaCaPsYu#rV#Ix$KlP2e#ytP|yB|OGv2_gscCMsF+W0~oyhfA~1NI6Y z@rBx|GB#x83 zXB#b)&ct@VHR#XJydC-H4G>k&6ALYI+)f-i-5xUq%^s0d9_knQJV~|$7TW}%1i|u$ zpm?QBeB|SbkD&>9kxoRWPgU~$tG>KlZUQY`55N_;6*jmTGL6%CnrT?|sTJAZYq7#6 z=`t4)JnO3tI3^gDTJK4Cz*9h3Q&TUMkotv)WTz(3=DXMFp|IgWXF+5VbQ+(RD1=iV z=-T>Z3kj)Gd}4;PL{3%9L@h+MU3>q705xF;0ZcCO<#DbZsY-`^Mtrs@=Pn58-4~Pf zFnK*B4^K#w;|x?*%aizucY)qQek`;VnA4$NenkMn`_=q~KBmJu@8n%4&@A==`mV54 z2VCI@SAX%P%1ijegcc+L$j;6Yqe`)V94>>k0}Z*@QQA@^foK97YbQMN&Ll`;RojZgVwII?x2yFR+rX z=iCZHTww=j5`qh3AoW=(=XeT<{xR_@Z@Ey(B-_@bZA*z5Io-kSieNy&(Lg^m`wOLK zyyJ)zFZXCI&^A8)sPqQEqYx;{!usVymQzT(BJhjCZ5{ffE7`FFcwL5Jj=L`E2>o=5 z4XkURF@F^&aSuCbWYLmMKYIvdFk3k~9HYN1nsEaBG z1h**n6XxMzy+t@4*I_{?Mx+kPz!Baic5xAT_l1Ial#|%z{v=9>f;6&`bbMA+TgXPJ zJ)SSn$k#5YW~<6gYI_8_`DnQ9ON+%}|CCWXfaM(*&G($E(E=su()7z|j303XTNB6D zB5>xO3LH8H0CmAD7+f)xlpi}=ql{8yfs2ClO{Q0w!5xf0bk=$6co?1=rU zIp_yBj|0Oe+if09u6rp}tcfpQF&sj-eBl7#;z#F4r5Xl&oCjb8P!nZhTD63n(`)?) z`8GF3EjH5lktZ92wU|hEN-E!xvgc1xfPv*p_In3d*GU5oyzpZj7C2S_tmsn7%ItCC z$btM+GZ&|iwUVa6d*)T&u}cAkR|MI&(CWc302iWNi_Lq=^UWhj*USSm3=0>Jp^yL{ z3joSy+p+;zso^G!QLkQ_ss?g2ASQGsmjw2=KBDZ#;e2;mhzqpD-jwm?zO_0B z;g?$fE2KdjdgEHv{EGE;skSo_W(W~elI`Nk;CE-1P2%Z)f_k~a2TJBh4{=3}whx9F z+DS8V25{qc)x5LcA5t{8*3?-6B3NqeF+}qr)R7X6efrDYO22B$d&#l%LINA4Z75Hx z70|dk(jC+U#DrXAGqcIFEu?fxCn!fDBrxp^icF!cA2CzVAd|rEILbRADUthofiLAc z%&b+PwZ8r(@Ii`fSHPQcSg)4FTN@<+gc@EuJM2Z#W-*FHfjq3%cVA0A zy^awmE&nDGA|Cv5hEdjM8Lat51&NUMe7beTHkTF>>{qo2Ks&$2N(m-2E%ErOtFwEQ zYjW(X+1iqBBQa$16GjdIS8tc(jC}=*Y@g<@dY0O$6hex@0tcM5Tpb}2OMzIn!zd&bz)}O| zg6b3E&`2;96o6hMV!+o4I2?sNXJ>PGP}PAPkeuurFb1$dFRKKKiMz|NYHKLQ=udFz z$N~IdHE9)APVHdqhpO8_S{NUFd8^!GX*Kffz>Y`&$M zlVYjp2@wnaByG}TWuq}?pzkDSvLN33T$^tTdCEWbpgub#Jb{tZkR+#GV5<}5`sUOR zWHbL=zAa-E1SIap{D(bLpTV{kPxC^ZevV?OH>WH6{X*7x1E|thn$CVp7guZ+#}7$( zp%>k`3T;zlA+AhGZNX*cOyh)jyg)seyng$RpJzJ#Q2YoH zGyYdB$JLeBFYwTa!AAQTYC<@T^MEBJSPAlMJXb;T9dAfeJXdrLTIgf!#%!vNQMOAG|DjYKDn`U%W%??$Qw!3NsQl^Y zDH6Ci-m)V^XzD?_on{3xb21cJ()owDZUT!Q9eHy70M3+inlbN0C&^NAiN?1rU~u*; z>6W4hoOMs6);4l&l^Xyr2Z4iL5d|H-hFt04CnxjFW#%6~P%UxDf)^{Hf!YCdiklRw z^hQ&#PK@?zm>g3XMuGW^&Qsn{97QlEcds-040%O~O}=#4*<4)Mq_{Cji?4=F#TonZ z#}NO|7*~I&Q3?d(@v)ZT2`pf+ulZ~Kj!g=~hfGzeQaKG=PegoI|LRGK41lNoeRwl5 zZf$WK4C!*iI9Hy`JthdTP8=y8jx=3}@dcoQHbeGOf@D~U;Ap`gMZ+Pcv6d;{d6rDy z(*a`8Z(#!mt5hT&|432T54+Hb85$ORp9D6G|B%TOXe_UVVM>;>97+OcGuOPvK zPsFU{*?C8p9r%jF(fLz?tN(i$L9j#x>(zuzY;M1e#eKDS6_Lv!!hlyW=R$r*>>pib zo7Ptkd-Cyt6Ho&>uoTvQKiDK)SJ*&=A5!7v-up`__nI+N@;_P$0>@(nux^QEQZX@@ z91Dvh45iZVx+KMWiL-&DVEpq5R=_I&AxIqih@fGW3u<_;#9jmZ9c)jZ>0!;HOi3=y(?W^sR||1|J#)a&PHm&pNugb<;iL#8N=7czujrkXKRJD*hnJ0t*E{af6K zA&h{zYRGu66-ZWLL&xbD0hq>a zC*R-kLQ5SHO;Uj+eF%cq@s#d6kO~LRASY8~09I>Sy0X*AKc^3n(tK+0a$0(c_sb^h zYd;J?0wy&K51`BSQMy+9T~;cU2MQZ%xpbS5=zB6z)#~4a9BH?ZFtFGnapUW1_OWsR zhyBj9NJ)Bc?i|?K6ivVt8KIXw*jlUDHYdLt-0_~R3qPR;jLMs!k|hnr$4;rDz}tOH z8YQn`aLYEmdTs<$#EYo|<-Jb7@To&yPEV3cO+C73lDo`q&FL@7I}sJV)56P5%x}sT z)8k?7mSEfW8vYi9j?`Po;r2L(FX%QB83SVOVGu_}35jHv;s()CUi?f7K(zKXBE;1c zZ0e-Fln2qt&5GAvS3}7rWjzG+&W2gGh#gCH&#iF3yB_>uQ2Wpz1R1D|!cfBm%tb0L zACq>jW*k5A_+@21jHfV2eh$1$nRl{NDeZA*(7a0`+^o~|0Lvy@wRT93*1edDSRN!p zYA1rm79f!4wa)3bv%tid1dn!YgKFz8ccv3{_sLRIi`0~Fc%+`s84#I{fA zGOixC|2Ocxi8(V+5#yZWYM;XuOgBW(Uf@;i&|j(K6FXC-B2T4;IHRQBoC2)^#nPQt zPSbMqXD=8XT~Y|as{w-c)4UT(qM%o;z7TbG9iJF`uSN+Y&sgTh2VwHHC?W!R;wspd zZ`jUN&0JbM5IAG>ya%6}ioNSt66z@_D&nzF??aXk0RO9=Lf0VKC;_-=XbKM$hG2q? zVij|Q6r;Kn$Wd3HbI{%K!jLu1CakUi8cF!VhFPRxcMeiW6{)#)LuYfk0vZkvrj zgIv)Pjo7cEpgvU|x*hrQ8!Lq=Ph9$fsb|T^=7dw{y7rps|I0^oiGP)ll3%rPpS}D` TE(&}n2vU?&eO@MG67+un{$ko6 literal 0 HcmV?d00001 diff --git a/examples/nginx-app/img/logo_small.png b/examples/nginx-app/img/logo_small.png new file mode 100644 index 0000000000000000000000000000000000000000..a6040f66f3da060c679acd661cf8b1f53eb6720d GIT binary patch literal 6430 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 literal 0 HcmV?d00001 diff --git a/examples/nginx-app/module.js b/examples/nginx-app/module.js new file mode 100644 index 00000000000..9e061df04cc --- /dev/null +++ b/examples/nginx-app/module.js @@ -0,0 +1,28 @@ +define([ + 'angular', + 'app/app' +], function(angular, app) { + + var module = angular.module('nginx-app', []); + app.default.useModule(module); + + module.config(function($routeProvider) { + $routeProvider + .when('/nginx/stream', { + templateUrl: 'public/plugins/nginx-app/partials/stream.html', + }); + }); + + function NginxConfigCtrl() { + this.appEditCtrl.beforeUpdate = function() { + alert('before!'); + }; + } + NginxConfigCtrl.templateUrl = 'public/plugins/nginx-app/partials/config.html'; + + + return { + ConfigCtrl: NginxConfigCtrl + }; + +}); diff --git a/examples/nginx-app/panel/module.js b/examples/nginx-app/panel/module.js new file mode 100644 index 00000000000..9ccc5b6c962 --- /dev/null +++ b/examples/nginx-app/panel/module.js @@ -0,0 +1,21 @@ +define([ + 'app/plugins/sdk' +], function(sdk) { + 'use strict'; + + var NginxPanel = (function(_super) { + function NginxPanel($scope, $injector) { + _super.call(this, $scope, $injector); + } + + NginxPanel.template = '

nginx!

'; + NginxPanel.prototype = Object.create(_super.prototype); + NginxPanel.prototype.constructor = NginxPanel; + + return NginxPanel; + })(sdk.PanelCtrl); + + return { + PanelCtrl: NginxPanel + }; +}); diff --git a/examples/nginx-app/panel/plugin.json b/examples/nginx-app/panel/plugin.json new file mode 100644 index 00000000000..4160f9ae6f3 --- /dev/null +++ b/examples/nginx-app/panel/plugin.json @@ -0,0 +1,6 @@ +{ + "type": "panel", + "name": "Nginx Panel", + "id": "nginx-panel", + "staticRoot": "." +} diff --git a/examples/nginx-app/partials/config.html b/examples/nginx-app/partials/config.html new file mode 100644 index 00000000000..cdd6b8d9b60 --- /dev/null +++ b/examples/nginx-app/partials/config.html @@ -0,0 +1 @@ +

nginx config

diff --git a/examples/nginx-app/partials/stream.html b/examples/nginx-app/partials/stream.html new file mode 100644 index 00000000000..a89afaced57 --- /dev/null +++ b/examples/nginx-app/partials/stream.html @@ -0,0 +1,12 @@ + + + + +
+
+

NGINX app

+
+
+ diff --git a/examples/nginx-app/plugin.json b/examples/nginx-app/plugin.json new file mode 100644 index 00000000000..6941fe87f17 --- /dev/null +++ b/examples/nginx-app/plugin.json @@ -0,0 +1,44 @@ +{ + "type": "app", + "name": "Nginx", + "id": "nginx-app", + + "staticRoot": ".", + + "pages": [ + {"name": "Live stream", "url": "nginx/stream", "reqRole": "Editor"}, + {"name": "Log view", "url": "nginx/log", "reqRole": "Editor"} + ], + + "css": { + "dark": "css/dark.css", + "light": "css/light.css" + }, + + "info": { + "description": "Official Grafana Nginx App & Dashboard bundle", + "author": { + "name": "Nginx Inc.", + "url": "http://nginx.com" + }, + "keywords": ["nginx"], + "logos": { + "small": "img/logo_small.png", + "large": "img/logo_large.png" + }, + "links": [ + {"name": "Project site", "url": "http://project.com"}, + {"name": "License & Terms", "url": "http://license.com"} + ], + "version": "1.0.0", + "updated": "2015-02-10" + }, + + "dependencies": { + "grafanaVersion": "2.6.x", + "plugins": [ + {"type": "datasource", "id": "graphite", "name": "Graphite", "version": "1.0.0"}, + {"type": "panel", "id": "graph", "name": "Graph", "version": "1.0.0"} + ] + } +} diff --git a/examples/panel-plugin-boilerplate-es5/module.js b/examples/panel-boilerplate-es5/module.js similarity index 100% rename from examples/panel-plugin-boilerplate-es5/module.js rename to examples/panel-boilerplate-es5/module.js diff --git a/examples/panel-plugin-boilerplate-es5/panel.html b/examples/panel-boilerplate-es5/panel.html similarity index 100% rename from examples/panel-plugin-boilerplate-es5/panel.html rename to examples/panel-boilerplate-es5/panel.html diff --git a/examples/panel-plugin-boilerplate-es5/plugin.json b/examples/panel-boilerplate-es5/plugin.json similarity index 100% rename from examples/panel-plugin-boilerplate-es5/plugin.json rename to examples/panel-boilerplate-es5/plugin.json diff --git a/public/app/grafana.ts b/public/app/app.ts similarity index 100% rename from public/app/grafana.ts rename to public/app/app.ts diff --git a/public/app/boot.js b/public/app/boot.js index 7ba0fb12bf2..d9924ca9dad 100644 --- a/public/app/boot.js +++ b/public/app/boot.js @@ -1,8 +1,8 @@ (function bootGrafana() { 'use strict'; - System.import('app/grafana').then(function(grafana) { - grafana.default.init(); + System.import('app/app').then(function(app) { + app.default.init(); }).catch(function(err) { console.log('Loading app module failed: ', err); }); diff --git a/tasks/systemjs_task.js b/tasks/systemjs_task.js index a2a4b6433d7..0f1a63883e0 100644 --- a/tasks/systemjs_task.js +++ b/tasks/systemjs_task.js @@ -11,7 +11,7 @@ module.exports = function(grunt) { console.log('Starting systemjs-builder'); var modules = [ - 'app/grafana', + 'app/app', 'app/features/all', 'app/plugins/panel/**/module', 'app/plugins/datasource/graphite/datasource', From 18eb9d60768129a062b3e3840ccf08110f7b40f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Feb 2016 11:17:49 +0100 Subject: [PATCH 2/5] feat(apps): began work on app pages --- examples/nginx-app/module.js | 28 +-- examples/nginx-app/partials/logs.html | 4 + examples/nginx-app/partials/stream.html | 12 +- examples/nginx-app/plugin.json | 4 +- pkg/api/dtos/apps.go | 18 +- pkg/api/index.go | 4 - pkg/plugins/app_plugin.go | 20 +- public/app/app.ts | 6 - public/app/core/core.ts | 2 +- .../app/core/directives/plugin_component.ts | 17 +- public/app/core/routes/all.js | 166 ----------------- public/app/core/routes/routes.ts | 171 ++++++++++++++++++ public/app/features/apps/all.ts | 1 + public/app/features/apps/page_ctrl.ts | 23 +++ public/app/features/apps/partials/list.html | 2 +- public/app/features/apps/partials/page.html | 14 ++ public/views/index.html | 1 - 17 files changed, 267 insertions(+), 226 deletions(-) create mode 100644 examples/nginx-app/partials/logs.html delete mode 100644 public/app/core/routes/all.js create mode 100644 public/app/core/routes/routes.ts create mode 100644 public/app/features/apps/page_ctrl.ts create mode 100644 public/app/features/apps/partials/page.html diff --git a/examples/nginx-app/module.js b/examples/nginx-app/module.js index 9e061df04cc..1805d1a0fad 100644 --- a/examples/nginx-app/module.js +++ b/examples/nginx-app/module.js @@ -1,28 +1,20 @@ define([ - 'angular', - 'app/app' -], function(angular, app) { +], function() { + 'use strict'; - var module = angular.module('nginx-app', []); - app.default.useModule(module); + function StreamPageCtrl() {} + StreamPageCtrl.templateUrl = 'public/plugins/nginx-app/partials/stream.html'; - module.config(function($routeProvider) { - $routeProvider - .when('/nginx/stream', { - templateUrl: 'public/plugins/nginx-app/partials/stream.html', - }); - }); + function LogsPageCtrl() {} + LogsPageCtrl.templateUrl = 'public/plugins/nginx-app/partials/logs.html'; - function NginxConfigCtrl() { - this.appEditCtrl.beforeUpdate = function() { - alert('before!'); - }; - } + function NginxConfigCtrl() {} NginxConfigCtrl.templateUrl = 'public/plugins/nginx-app/partials/config.html'; - return { - ConfigCtrl: NginxConfigCtrl + ConfigCtrl: NginxConfigCtrl, + StreamPageCtrl: StreamPageCtrl, + LogsPageCtrl: LogsPageCtrl, }; }); diff --git a/examples/nginx-app/partials/logs.html b/examples/nginx-app/partials/logs.html new file mode 100644 index 00000000000..38ad06f4384 --- /dev/null +++ b/examples/nginx-app/partials/logs.html @@ -0,0 +1,4 @@ + +

Nginx logs view

+ +Logs! diff --git a/examples/nginx-app/partials/stream.html b/examples/nginx-app/partials/stream.html index a89afaced57..fc0f367046f 100644 --- a/examples/nginx-app/partials/stream.html +++ b/examples/nginx-app/partials/stream.html @@ -1,12 +1,4 @@ - - - -
-
-

NGINX app

-
-
+

Nginx stream view

+testing! diff --git a/examples/nginx-app/plugin.json b/examples/nginx-app/plugin.json index 6941fe87f17..7e3cdd7ad08 100644 --- a/examples/nginx-app/plugin.json +++ b/examples/nginx-app/plugin.json @@ -6,8 +6,8 @@ "staticRoot": ".", "pages": [ - {"name": "Live stream", "url": "nginx/stream", "reqRole": "Editor"}, - {"name": "Log view", "url": "nginx/log", "reqRole": "Editor"} + { "name": "Live stream", "component": "StreamPageCtrl", "role": "Editor"}, + { "name": "Log view", "component": "LogsPageCtrl", "role": "Viewer"} ], "css": { diff --git a/pkg/api/dtos/apps.go b/pkg/api/dtos/apps.go index d10883a26d7..7a1e18148e2 100644 --- a/pkg/api/dtos/apps.go +++ b/pkg/api/dtos/apps.go @@ -6,15 +6,15 @@ import ( ) type AppSettings struct { - Name string `json:"name"` - AppId string `json:"appId"` - Enabled bool `json:"enabled"` - Pinned bool `json:"pinned"` - Module string `json:"module"` - Info *plugins.PluginInfo `json:"info"` - Pages []plugins.AppPluginPage `json:"pages"` - Includes []plugins.AppIncludeInfo `json:"includes"` - JsonData map[string]interface{} `json:"jsonData"` + Name string `json:"name"` + AppId string `json:"appId"` + Enabled bool `json:"enabled"` + Pinned bool `json:"pinned"` + Module string `json:"module"` + Info *plugins.PluginInfo `json:"info"` + Pages []*plugins.AppPluginPage `json:"pages"` + Includes []*plugins.AppIncludeInfo `json:"includes"` + JsonData map[string]interface{} `json:"jsonData"` } func NewAppSettingsDto(def *plugins.AppPlugin, data *models.AppSettings) *AppSettings { diff --git a/pkg/api/index.go b/pkg/api/index.go index 522b53b9026..9eea59fa4d2 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -86,10 +86,6 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { } for _, plugin := range enabledPlugins.Apps { - if plugin.Module != "" { - data.PluginModules = append(data.PluginModules, plugin.Module) - } - if plugin.Css != nil { data.PluginCss = append(data.PluginCss, &dtos.PluginCss{Light: plugin.Css.Light, Dark: plugin.Css.Dark}) } diff --git a/pkg/plugins/app_plugin.go b/pkg/plugins/app_plugin.go index 547cd91283c..cb1349047da 100644 --- a/pkg/plugins/app_plugin.go +++ b/pkg/plugins/app_plugin.go @@ -4,13 +4,15 @@ import ( "encoding/json" "strings" + "github.com/gosimple/slug" "github.com/grafana/grafana/pkg/models" ) type AppPluginPage struct { - Name string `json:"name"` - Url string `json:"url"` - ReqRole models.RoleType `json:"reqRole"` + Name string `json:"name"` + Slug string `json:"slug"` + Component string `json:"component"` + Role models.RoleType `json:"role"` } type AppPluginCss struct { @@ -27,9 +29,9 @@ type AppIncludeInfo struct { type AppPlugin struct { FrontendPluginBase Css *AppPluginCss `json:"css"` - Pages []AppPluginPage `json:"pages"` + Pages []*AppPluginPage `json:"pages"` Routes []*AppPluginRoute `json:"routes"` - Includes []AppIncludeInfo `json:"-"` + Includes []*AppIncludeInfo `json:"-"` Pinned bool `json:"-"` Enabled bool `json:"-"` @@ -67,7 +69,7 @@ func (app *AppPlugin) Load(decoder *json.Decoder, pluginDir string) error { for _, panel := range Panels { if strings.HasPrefix(panel.PluginDir, app.PluginDir) { panel.IncludedInAppId = app.Id - app.Includes = append(app.Includes, AppIncludeInfo{ + app.Includes = append(app.Includes, &AppIncludeInfo{ Name: panel.Name, Id: panel.Id, Type: panel.Type, @@ -75,6 +77,12 @@ func (app *AppPlugin) Load(decoder *json.Decoder, pluginDir string) error { } } + for _, page := range app.Pages { + if page.Slug == "" { + page.Slug = slug.Make(page.Name) + } + } + Apps[app.Id] = app return nil } diff --git a/public/app/app.ts b/public/app/app.ts index d9ad3a449d3..a4e1bebca6e 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -72,12 +72,6 @@ export class GrafanaApp { this.useModule(coreModule); var preBootRequires = [System.import('app/features/all')]; - var pluginModules = config.bootData.pluginModules || []; - - // add plugin modules - for (var i = 0; i < pluginModules.length; i++) { - preBootRequires.push(System.import(pluginModules[i])); - } Promise.all(preBootRequires).then(() => { // disable tool tip animation diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 55c0f4ec049..361dea334ef 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -28,7 +28,7 @@ import {navbarDirective} from './components/navbar/navbar'; import {arrayJoin} from './directives/array_join'; import 'app/core/controllers/all'; import 'app/core/services/all'; -import 'app/core/routes/all'; +import 'app/core/routes/routes'; import './filters/filters'; import coreModule from './core_module'; diff --git a/public/app/core/directives/plugin_component.ts b/public/app/core/directives/plugin_component.ts index 8dd05a83ab0..518d5a8af56 100644 --- a/public/app/core/directives/plugin_component.ts +++ b/public/app/core/directives/plugin_component.ts @@ -143,15 +143,28 @@ function pluginDirectiveLoader($compile, datasourceSrv, $rootScope, $q, $http, $ } // AppConfigCtrl case 'app-config-ctrl': { - return System.import(scope.ctrl.appModel.module).then(function(appModule) { + let appModel = scope.ctrl.appModel; + return System.import(appModel.module).then(function(appModule) { return { - name: 'app-config-' + scope.ctrl.appModel.appId, + name: 'app-config-' + appModel.appId, bindings: {appModel: "=", appEditCtrl: "="}, attrs: {"app-model": "ctrl.appModel", "app-edit-ctrl": "ctrl"}, Component: appModule.ConfigCtrl, }; }); } + // App Page + case 'app-page': { + let appModel = scope.ctrl.appModel; + return System.import(appModel.module).then(function(appModule) { + return { + name: 'app-page-' + appModel.appId + '-' + scope.ctrl.page.slug, + bindings: {appModel: "="}, + attrs: {"app-model": "ctrl.appModel"}, + Component: appModule[scope.ctrl.page.component], + }; + }); + } // Panel case 'panel': { return loadPanelComponentInfo(scope, attrs); diff --git a/public/app/core/routes/all.js b/public/app/core/routes/all.js deleted file mode 100644 index 2d313d7322f..00000000000 --- a/public/app/core/routes/all.js +++ /dev/null @@ -1,166 +0,0 @@ -define([ - 'angular', - '../core_module', - './bundle_loader', - './dashboard_loaders', -], function(angular, coreModule, BundleLoader) { - "use strict"; - - coreModule.default.config(function($routeProvider, $locationProvider) { - $locationProvider.html5Mode(true); - - var loadOrgBundle = new BundleLoader.BundleLoader('app/features/org/all'); - var loadAppsBundle = new BundleLoader.BundleLoader('app/features/apps/all'); - - $routeProvider - .when('/', { - templateUrl: 'public/app/partials/dashboard.html', - controller : 'LoadDashboardCtrl', - reloadOnSearch: false, - }) - .when('/dashboard/:type/:slug', { - templateUrl: 'public/app/partials/dashboard.html', - controller : 'LoadDashboardCtrl', - reloadOnSearch: false, - }) - .when('/dashboard-solo/:type/:slug', { - templateUrl: 'public/app/features/panel/partials/soloPanel.html', - controller : 'SoloPanelCtrl', - }) - .when('/dashboard-import/:file', { - templateUrl: 'public/app/partials/dashboard.html', - controller : 'DashFromImportCtrl', - reloadOnSearch: false, - }) - .when('/dashboard/new', { - templateUrl: 'public/app/partials/dashboard.html', - controller : 'NewDashboardCtrl', - reloadOnSearch: false, - }) - .when('/import/dashboard', { - templateUrl: 'public/app/features/dashboard/partials/import.html', - controller : 'DashboardImportCtrl', - }) - .when('/datasources', { - templateUrl: 'public/app/features/datasources/partials/list.html', - controller : 'DataSourcesCtrl', - resolve: loadOrgBundle, - }) - .when('/datasources/edit/:id', { - templateUrl: 'public/app/features/datasources/partials/edit.html', - controller : 'DataSourceEditCtrl', - resolve: loadOrgBundle, - }) - .when('/datasources/new', { - templateUrl: 'public/app/features/datasources/partials/edit.html', - controller : 'DataSourceEditCtrl', - resolve: loadOrgBundle, - }) - .when('/org', { - templateUrl: 'public/app/features/org/partials/orgDetails.html', - controller : 'OrgDetailsCtrl', - resolve: loadOrgBundle, - }) - .when('/org/new', { - templateUrl: 'public/app/features/org/partials/newOrg.html', - controller : 'NewOrgCtrl', - resolve: loadOrgBundle, - }) - .when('/org/users', { - templateUrl: 'public/app/features/org/partials/orgUsers.html', - controller : 'OrgUsersCtrl', - resolve: loadOrgBundle, - }) - .when('/org/apikeys', { - templateUrl: 'public/app/features/org/partials/orgApiKeys.html', - controller : 'OrgApiKeysCtrl', - resolve: loadOrgBundle, - }) - .when('/profile', { - templateUrl: 'public/app/features/profile/partials/profile.html', - controller : 'ProfileCtrl', - }) - .when('/profile/password', { - templateUrl: 'public/app/features/profile/partials/password.html', - controller : 'ChangePasswordCtrl', - }) - .when('/profile/select-org', { - templateUrl: 'public/app/features/profile/partials/select_org.html', - controller : 'SelectOrgCtrl', - }) - .when('/admin/settings', { - templateUrl: 'public/app/features/admin/partials/settings.html', - controller : 'AdminSettingsCtrl', - }) - .when('/admin/users', { - templateUrl: 'public/app/features/admin/partials/users.html', - controller : 'AdminListUsersCtrl', - }) - .when('/admin/users/create', { - templateUrl: 'public/app/features/admin/partials/new_user.html', - controller : 'AdminEditUserCtrl', - }) - .when('/admin/users/edit/:id', { - templateUrl: 'public/app/features/admin/partials/edit_user.html', - controller : 'AdminEditUserCtrl', - }) - .when('/admin/orgs', { - templateUrl: 'public/app/features/admin/partials/orgs.html', - controller : 'AdminListOrgsCtrl', - }) - .when('/admin/orgs/edit/:id', { - templateUrl: 'public/app/features/admin/partials/edit_org.html', - controller : 'AdminEditOrgCtrl', - }) - .when('/admin/stats', { - templateUrl: 'public/app/features/admin/partials/stats.html', - controller : 'AdminStatsCtrl', - controllerAs: 'ctrl', - }) - .when('/login', { - templateUrl: 'public/app/partials/login.html', - controller : 'LoginCtrl', - }) - .when('/invite/:code', { - templateUrl: 'public/app/partials/signup_invited.html', - controller : 'InvitedCtrl', - }) - .when('/signup', { - templateUrl: 'public/app/partials/signup_step2.html', - controller : 'SignUpCtrl', - }) - .when('/user/password/send-reset-email', { - templateUrl: 'public/app/partials/reset_password.html', - controller : 'ResetPasswordCtrl', - }) - .when('/user/password/reset', { - templateUrl: 'public/app/partials/reset_password.html', - controller : 'ResetPasswordCtrl', - }) - .when('/dashboard/snapshots', { - templateUrl: 'public/app/features/snapshot/partials/snapshots.html', - controller : 'SnapshotsCtrl', - controllerAs: 'ctrl', - }) - .when('/apps', { - templateUrl: 'public/app/features/apps/partials/list.html', - controller: 'AppListCtrl', - controllerAs: 'ctrl', - resolve: loadAppsBundle, - }) - .when('/apps/edit/:appId', { - templateUrl: 'public/app/features/apps/partials/edit.html', - controller: 'AppEditCtrl', - controllerAs: 'ctrl', - resolve: loadAppsBundle, - }) - .when('/global-alerts', { - templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html', - }) - .otherwise({ - templateUrl: 'public/app/partials/error.html', - controller: 'ErrorCtrl' - }); - }); - -}); diff --git a/public/app/core/routes/routes.ts b/public/app/core/routes/routes.ts new file mode 100644 index 00000000000..95fecce664d --- /dev/null +++ b/public/app/core/routes/routes.ts @@ -0,0 +1,171 @@ +/// + +import angular from 'angular'; +import coreModule from 'app/core/core_module'; +import {BundleLoader} from './bundle_loader'; + +/** @ngInject **/ +function setupAngularRoutes($routeProvider, $locationProvider) { + $locationProvider.html5Mode(true); + + var loadOrgBundle = new BundleLoader('app/features/org/all'); + var loadAppsBundle = new BundleLoader('app/features/apps/all'); + + $routeProvider + .when('/', { + templateUrl: 'public/app/partials/dashboard.html', + controller : 'LoadDashboardCtrl', + reloadOnSearch: false, + }) + .when('/dashboard/:type/:slug', { + templateUrl: 'public/app/partials/dashboard.html', + controller : 'LoadDashboardCtrl', + reloadOnSearch: false, + }) + .when('/dashboard-solo/:type/:slug', { + templateUrl: 'public/app/features/panel/partials/soloPanel.html', + controller : 'SoloPanelCtrl', + }) + .when('/dashboard-import/:file', { + templateUrl: 'public/app/partials/dashboard.html', + controller : 'DashFromImportCtrl', + reloadOnSearch: false, + }) + .when('/dashboard/new', { + templateUrl: 'public/app/partials/dashboard.html', + controller : 'NewDashboardCtrl', + reloadOnSearch: false, + }) + .when('/import/dashboard', { + templateUrl: 'public/app/features/dashboard/partials/import.html', + controller : 'DashboardImportCtrl', + }) + .when('/datasources', { + templateUrl: 'public/app/features/datasources/partials/list.html', + controller : 'DataSourcesCtrl', + resolve: loadOrgBundle, + }) + .when('/datasources/edit/:id', { + templateUrl: 'public/app/features/datasources/partials/edit.html', + controller : 'DataSourceEditCtrl', + resolve: loadOrgBundle, + }) + .when('/datasources/new', { + templateUrl: 'public/app/features/datasources/partials/edit.html', + controller : 'DataSourceEditCtrl', + resolve: loadOrgBundle, + }) + .when('/org', { + templateUrl: 'public/app/features/org/partials/orgDetails.html', + controller : 'OrgDetailsCtrl', + resolve: loadOrgBundle, + }) + .when('/org/new', { + templateUrl: 'public/app/features/org/partials/newOrg.html', + controller : 'NewOrgCtrl', + resolve: loadOrgBundle, + }) + .when('/org/users', { + templateUrl: 'public/app/features/org/partials/orgUsers.html', + controller : 'OrgUsersCtrl', + resolve: loadOrgBundle, + }) + .when('/org/apikeys', { + templateUrl: 'public/app/features/org/partials/orgApiKeys.html', + controller : 'OrgApiKeysCtrl', + resolve: loadOrgBundle, + }) + .when('/profile', { + templateUrl: 'public/app/features/profile/partials/profile.html', + controller : 'ProfileCtrl', + }) + .when('/profile/password', { + templateUrl: 'public/app/features/profile/partials/password.html', + controller : 'ChangePasswordCtrl', + }) + .when('/profile/select-org', { + templateUrl: 'public/app/features/profile/partials/select_org.html', + controller : 'SelectOrgCtrl', + }) + .when('/admin/settings', { + templateUrl: 'public/app/features/admin/partials/settings.html', + controller : 'AdminSettingsCtrl', + }) + .when('/admin/users', { + templateUrl: 'public/app/features/admin/partials/users.html', + controller : 'AdminListUsersCtrl', + }) + .when('/admin/users/create', { + templateUrl: 'public/app/features/admin/partials/new_user.html', + controller : 'AdminEditUserCtrl', + }) + .when('/admin/users/edit/:id', { + templateUrl: 'public/app/features/admin/partials/edit_user.html', + controller : 'AdminEditUserCtrl', + }) + .when('/admin/orgs', { + templateUrl: 'public/app/features/admin/partials/orgs.html', + controller : 'AdminListOrgsCtrl', + }) + .when('/admin/orgs/edit/:id', { + templateUrl: 'public/app/features/admin/partials/edit_org.html', + controller : 'AdminEditOrgCtrl', + }) + .when('/admin/stats', { + templateUrl: 'public/app/features/admin/partials/stats.html', + controller : 'AdminStatsCtrl', + controllerAs: 'ctrl', + }) + .when('/login', { + templateUrl: 'public/app/partials/login.html', + controller : 'LoginCtrl', + }) + .when('/invite/:code', { + templateUrl: 'public/app/partials/signup_invited.html', + controller : 'InvitedCtrl', + }) + .when('/signup', { + templateUrl: 'public/app/partials/signup_step2.html', + controller : 'SignUpCtrl', + }) + .when('/user/password/send-reset-email', { + templateUrl: 'public/app/partials/reset_password.html', + controller : 'ResetPasswordCtrl', + }) + .when('/user/password/reset', { + templateUrl: 'public/app/partials/reset_password.html', + controller : 'ResetPasswordCtrl', + }) + .when('/dashboard/snapshots', { + templateUrl: 'public/app/features/snapshot/partials/snapshots.html', + controller : 'SnapshotsCtrl', + controllerAs: 'ctrl', + }) + .when('/apps', { + templateUrl: 'public/app/features/apps/partials/list.html', + controller: 'AppListCtrl', + controllerAs: 'ctrl', + resolve: loadAppsBundle, + }) + .when('/apps/:appId/edit', { + templateUrl: 'public/app/features/apps/partials/edit.html', + controller: 'AppEditCtrl', + controllerAs: 'ctrl', + resolve: loadAppsBundle, + }) + .when('/apps/:appId/page/:slug', { + templateUrl: 'public/app/features/apps/partials/page.html', + controller: 'AppPageCtrl', + controllerAs: 'ctrl', + resolve: loadAppsBundle, + }) + .when('/global-alerts', { + templateUrl: 'public/app/features/dashboard/partials/globalAlerts.html', + }) + .otherwise({ + templateUrl: 'public/app/partials/error.html', + controller: 'ErrorCtrl' + }); +} + +coreModule.config(setupAngularRoutes); diff --git a/public/app/features/apps/all.ts b/public/app/features/apps/all.ts index fcdd27dff4d..9d54165e56b 100644 --- a/public/app/features/apps/all.ts +++ b/public/app/features/apps/all.ts @@ -1,2 +1,3 @@ import './edit_ctrl'; +import './page_ctrl'; import './list_ctrl'; diff --git a/public/app/features/apps/page_ctrl.ts b/public/app/features/apps/page_ctrl.ts new file mode 100644 index 00000000000..ac04a59f43f --- /dev/null +++ b/public/app/features/apps/page_ctrl.ts @@ -0,0 +1,23 @@ +/// + +import angular from 'angular'; +import _ from 'lodash'; + +export class AppPageCtrl { + page: any; + appModel: any; + + /** @ngInject */ + constructor(private backendSrv, private $routeParams: any, private $rootScope) { + this.backendSrv.get(`/api/org/apps/${this.$routeParams.appId}/settings`).then(app => { + this.appModel = app; + this.page = _.findWhere(app.pages, {slug: this.$routeParams.slug}); + if (!this.page) { + $rootScope.appEvent('alert-error', ['App Page Not Found', '']); + } + }); + } +} + +angular.module('grafana.controllers').controller('AppPageCtrl', AppPageCtrl); + diff --git a/public/app/features/apps/partials/list.html b/public/app/features/apps/partials/list.html index 6d2d8cc24df..59c1054816f 100644 --- a/public/app/features/apps/partials/list.html +++ b/public/app/features/apps/partials/list.html @@ -24,7 +24,7 @@ - + {{app.name}}     diff --git a/public/app/features/apps/partials/page.html b/public/app/features/apps/partials/page.html new file mode 100644 index 00000000000..0f111ce9398 --- /dev/null +++ b/public/app/features/apps/partials/page.html @@ -0,0 +1,14 @@ + + + + +

+ App page +

+ +
+ + +
diff --git a/public/views/index.html b/public/views/index.html index 40be796b306..724afd33f33 100644 --- a/public/views/index.html +++ b/public/views/index.html @@ -50,7 +50,6 @@ window.grafanaBootData = { user:[[.User]], settings: [[.Settings]], - pluginModules: [[.PluginModules]], mainNavLinks: [[.MainNavLinks]] }; From 0def04ad343646de9ac723ac8e69ded5de50952b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Feb 2016 12:10:59 +0100 Subject: [PATCH 3/5] feat(apps): more progress on app pages --- examples/nginx-app/partials/logs.html | 2 -- examples/nginx-app/partials/stream.html | 4 +--- public/app/core/routes/routes.ts | 2 ++ public/app/features/apps/edit_ctrl.ts | 14 ++++++++------ public/app/features/apps/list_ctrl.ts | 3 +-- public/app/features/apps/page_ctrl.ts | 5 ++++- public/app/features/apps/partials/edit.html | 2 +- public/app/features/apps/partials/list.html | 4 ++-- public/app/features/apps/partials/page.html | 19 +++++++++++-------- 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/examples/nginx-app/partials/logs.html b/examples/nginx-app/partials/logs.html index 38ad06f4384..f6bef036395 100644 --- a/examples/nginx-app/partials/logs.html +++ b/examples/nginx-app/partials/logs.html @@ -1,4 +1,2 @@ -

Nginx logs view

- Logs! diff --git a/examples/nginx-app/partials/stream.html b/examples/nginx-app/partials/stream.html index fc0f367046f..ffa1c7f1836 100644 --- a/examples/nginx-app/partials/stream.html +++ b/examples/nginx-app/partials/stream.html @@ -1,4 +1,2 @@ -

Nginx stream view

- -testing! +streams! diff --git a/public/app/core/routes/routes.ts b/public/app/core/routes/routes.ts index 95fecce664d..8963228210b 100644 --- a/public/app/core/routes/routes.ts +++ b/public/app/core/routes/routes.ts @@ -1,5 +1,7 @@ /// +import './dashboard_loaders'; + import angular from 'angular'; import coreModule from 'app/core/core_module'; import {BundleLoader} from './bundle_loader'; diff --git a/public/app/features/apps/edit_ctrl.ts b/public/app/features/apps/edit_ctrl.ts index ccdaf529b5e..fc87c53f7fd 100644 --- a/public/app/features/apps/edit_ctrl.ts +++ b/public/app/features/apps/edit_ctrl.ts @@ -5,19 +5,21 @@ import _ from 'lodash'; export class AppEditCtrl { appModel: any; + appId: any; includedPanels: any; /** @ngInject */ constructor(private backendSrv: any, private $routeParams: any) { this.appModel = {}; + this.appId = $routeParams.appId; - this.backendSrv.get(`/api/org/apps/${this.$routeParams.appId}/settings`).then(result => { + this.backendSrv.get(`/api/org/apps/${this.appId}/settings`).then(result => { this.appModel = result; this.includedPanels = _.where(result.includes, {type: 'panel'}); }); } - update(options) { + update() { var updateCmd = _.extend({ appId: this.appModel.appId, orgId: this.appModel.orgId, @@ -25,19 +27,19 @@ export class AppEditCtrl { pinned: this.appModel.pinned, jsonData: this.appModel.jsonData, secureJsonData: this.appModel.secureJsonData, - }, options); + }, {}); - this.backendSrv.post(`/api/org/apps/${this.$routeParams.appId}/settings`, updateCmd).then(function() { + this.backendSrv.post(`/api/org/apps/${this.appId}/settings`, updateCmd).then(function() { window.location.href = window.location.href; }); } toggleEnabled() { - this.update({enabled: this.appModel.enabled}); + this.update(); } togglePinned() { - this.update({pinned: this.appModel.pinned}); + this.update(); } } diff --git a/public/app/features/apps/list_ctrl.ts b/public/app/features/apps/list_ctrl.ts index 142f0e12b0a..8777f206d88 100644 --- a/public/app/features/apps/list_ctrl.ts +++ b/public/app/features/apps/list_ctrl.ts @@ -6,9 +6,8 @@ export class AppListCtrl { apps: any[]; /** @ngInject */ - constructor(private backendSrv: any) {} + constructor(private backendSrv: any) { - init() { this.backendSrv.get('api/org/apps').then(apps => { this.apps = apps; }); diff --git a/public/app/features/apps/page_ctrl.ts b/public/app/features/apps/page_ctrl.ts index ac04a59f43f..15b08ca1cfe 100644 --- a/public/app/features/apps/page_ctrl.ts +++ b/public/app/features/apps/page_ctrl.ts @@ -5,11 +5,14 @@ import _ from 'lodash'; export class AppPageCtrl { page: any; + appId: any; appModel: any; /** @ngInject */ constructor(private backendSrv, private $routeParams: any, private $rootScope) { - this.backendSrv.get(`/api/org/apps/${this.$routeParams.appId}/settings`).then(app => { + this.appId = $routeParams.appId; + + this.backendSrv.get(`/api/org/apps/${this.appId}/settings`).then(app => { this.appModel = app; this.page = _.findWhere(app.pages, {slug: this.$routeParams.slug}); if (!this.page) { diff --git a/public/app/features/apps/partials/edit.html b/public/app/features/apps/partials/edit.html index efc5f93c738..5211ac27cf3 100644 --- a/public/app/features/apps/partials/edit.html +++ b/public/app/features/apps/partials/edit.html @@ -78,7 +78,7 @@ diff --git a/public/app/features/apps/partials/list.html b/public/app/features/apps/partials/list.html index 59c1054816f..98f2cfea5c8 100644 --- a/public/app/features/apps/partials/list.html +++ b/public/app/features/apps/partials/list.html @@ -2,7 +2,7 @@
-
+

Apps

@@ -18,7 +18,7 @@
  • diff --git a/public/app/features/apps/partials/page.html b/public/app/features/apps/partials/page.html index 0f111ce9398..506708fa654 100644 --- a/public/app/features/apps/partials/page.html +++ b/public/app/features/apps/partials/page.html @@ -1,14 +1,17 @@ - + -

    - App page -

    +
    +
    +

    {{ctrl.page.name}}

    -
    - - +
    + + +
    + +
    From 9dcfe6dc39d09218d2c7e905cbb14cf44bf8442e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Feb 2016 14:06:23 +0100 Subject: [PATCH 4/5] feat(apps): more work on app pages and sidemenu subnav --- pkg/api/dtos/index.go | 9 +++-- pkg/api/index.go | 37 ++++++++++--------- .../core/components/sidemenu/sidemenu.html | 12 +++++- .../app/core/components/sidemenu/sidemenu.ts | 8 ++-- public/less/login.less | 1 - public/less/sidemenu.less | 17 ++++++--- 6 files changed, 50 insertions(+), 34 deletions(-) diff --git a/pkg/api/dtos/index.go b/pkg/api/dtos/index.go index c5b81ee0e98..180ec767281 100644 --- a/pkg/api/dtos/index.go +++ b/pkg/api/dtos/index.go @@ -19,8 +19,9 @@ type PluginCss struct { } type NavLink struct { - Text string `json:"text"` - Icon string `json:"icon"` - Img string `json:"img"` - Url string `json:"url"` + Text string `json:"text"` + Icon string `json:"icon"` + Img string `json:"img"` + Url string `json:"url"` + Children []*NavLink `json:"children"` } diff --git a/pkg/api/index.go b/pkg/api/index.go index 9eea59fa4d2..74b168e53e9 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -51,32 +51,24 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Dashboards", Icon: "fa fa-fw fa-th-large", - Url: "/", - }) - - data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ - Text: "Playlists", - Icon: "fa fa-fw fa-list", - Url: "/playlists", - }) - - data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ - Text: "Snapshots", - Icon: "fa-fw icon-gf icon-gf-snapshot", - Url: "/dashboard/snapshots", + Url: setting.AppSubUrl + "/", + Children: []*dtos.NavLink{ + {Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}, + {Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}, + }, }) if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", Icon: "fa fa-fw fa-database", - Url: "/datasources", + Url: setting.AppSubUrl + "/datasources", }) data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Apps", Icon: "fa fa-fw fa-cubes", - Url: "/apps", + Url: setting.AppSubUrl + "/apps", }) } @@ -91,11 +83,20 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { } if plugin.Pinned { - data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ + pageLink := &dtos.NavLink{ Text: plugin.Name, - Url: "/apps/edit/" + plugin.Id, + Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/edit", Img: plugin.Info.Logos.Small, - }) + } + + for _, page := range plugin.Pages { + pageLink.Children = append(pageLink.Children, &dtos.NavLink{ + Url: setting.AppSubUrl + "/apps/" + plugin.Id + "/page/" + page.Slug, + Text: page.Name, + }) + } + + data.MainNavLinks = append(data.MainNavLinks, pageLink) } } diff --git a/public/app/core/components/sidemenu/sidemenu.html b/public/app/core/components/sidemenu/sidemenu.html index a651c87aa7c..dd3b71e54b4 100644 --- a/public/app/core/components/sidemenu/sidemenu.html +++ b/public/app/core/components/sidemenu/sidemenu.html @@ -1,7 +1,7 @@
      -
    • +
      @@ -43,7 +43,15 @@ {{item.text}} + +
      • diff --git a/public/app/core/components/sidemenu/sidemenu.ts b/public/app/core/components/sidemenu/sidemenu.ts index 833bba1913f..275b0e782a4 100644 --- a/public/app/core/components/sidemenu/sidemenu.ts +++ b/public/app/core/components/sidemenu/sidemenu.ts @@ -16,7 +16,7 @@ export class SideMenuCtrl { appSubUrl: string; /** @ngInject */ - constructor(private $scope, private $location, private contextSrv, private backendSrv) { + constructor(private $scope, private $location, private contextSrv, private backendSrv, private $element) { this.isSignedIn = contextSrv.isSignedIn; this.user = contextSrv.user; this.appSubUrl = config.appSubUrl; @@ -29,6 +29,7 @@ export class SideMenuCtrl { this.contextSrv.sidemenu = false; } }); + } getUrl(url) { @@ -36,9 +37,8 @@ export class SideMenuCtrl { } setupMainNav() { - this.mainLinks = config.bootData.mainNavLinks.map(item => { - return {text: item.text, icon: item.icon, img: item.img, url: this.getUrl(item.url)}; - }); + this.mainLinks = config.bootData.mainNavLinks; + this.openUserDropdown(); } openUserDropdown() { diff --git a/public/less/login.less b/public/less/login.less index afebfde9271..070100b63b2 100644 --- a/public/less/login.less +++ b/public/less/login.less @@ -84,7 +84,6 @@ min-width: 150px; display: inline-block; border: 1px solid lighten(@btnInverseBackground, 10%); - color: @grayLight; } } diff --git a/public/less/sidemenu.less b/public/less/sidemenu.less index 79d79e9750c..4349bd4a0c6 100644 --- a/public/less/sidemenu.less +++ b/public/less/sidemenu.less @@ -41,8 +41,8 @@ .top-nav-menu-btn { a { background-color: @sideMenuBackground; - padding-right: 46px; - padding-left: 24px; + padding-right: 54px; + padding-left: 16px; } .icon-gf-grafana_wordmark { display: inline-block; @@ -76,6 +76,13 @@ color: @linkColor; } } + + li:hover { + position: relative; + .dropdown-menu { + display: block; + } + } } .sidemenu-main-link { @@ -88,6 +95,7 @@ vertical-align: middle; overflow: hidden; text-overflow: ellipsis; + white-space: nowrap; } .icon-circle { @@ -111,9 +119,8 @@ .sidemenu-item { color: @linkColor; line-height: 47px; - padding: 0px 10px 0px 20px; + padding: 0px 10px 0px 10px; display: block; - white-space: nowrap; &:hover { background-color: @sideMenuBackgroundHighlight; @@ -193,7 +200,7 @@ .sidemenu-org { border-bottom: @sideMenuBorder; border-top: @sideMenuBorder; - padding: 17px 10px 15px 21px; + padding: 17px 10px 15px 14px; box-sizing: border-box; cursor: pointer; &:hover { From f0ecbd3878c8e1b0139e3b567e0c3506cf1cbc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 9 Feb 2016 14:20:41 +0100 Subject: [PATCH 5/5] feat(apps): removed some on hover stuff from sidemenu to make it ready to merge to master --- pkg/api/index.go | 11 +++++++---- public/app/core/components/sidemenu/sidemenu.html | 3 +-- public/app/core/components/sidemenu/sidemenu.ts | 1 - public/less/sidemenu.less | 7 ------- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/pkg/api/index.go b/pkg/api/index.go index 74b168e53e9..094511df1ea 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -52,12 +52,15 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) { Text: "Dashboards", Icon: "fa fa-fw fa-th-large", Url: setting.AppSubUrl + "/", - Children: []*dtos.NavLink{ - {Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}, - {Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}, - }, + // Children: []*dtos.NavLink{ + // {Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}, + // {Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}, + // }, }) + data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{Text: "Playlists", Icon: "fa fa-fw fa-list", Url: setting.AppSubUrl + "/playlists"}) + data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{Text: "Snapshots", Icon: "fa-fw icon-gf icon-gf-snapshot", Url: setting.AppSubUrl + "/dashboard/snapshots"}) + if c.OrgRole == m.ROLE_ADMIN { data.MainNavLinks = append(data.MainNavLinks, &dtos.NavLink{ Text: "Data Sources", diff --git a/public/app/core/components/sidemenu/sidemenu.html b/public/app/core/components/sidemenu/sidemenu.html index dd3b71e54b4..7fcd41a2824 100644 --- a/public/app/core/components/sidemenu/sidemenu.html +++ b/public/app/core/components/sidemenu/sidemenu.html @@ -1,7 +1,7 @@
        • -
          +
          @@ -43,7 +43,6 @@ {{item.text}} -