From 6c59aff866ff412b46f1d171fc99f2e303a509f0 Mon Sep 17 00:00:00 2001 From: Marcin Haba Date: Mon, 27 Nov 2017 21:08:47 +0100 Subject: [PATCH] baculum: New reworked restore wizard --- gui/baculum/protected/Web/Lang/en/messages.mo | Bin 33961 -> 36033 bytes gui/baculum/protected/Web/Lang/en/messages.po | 65 ++ gui/baculum/protected/Web/Lang/ja/messages.mo | Bin 31067 -> 33075 bytes gui/baculum/protected/Web/Lang/ja/messages.po | 65 ++ gui/baculum/protected/Web/Lang/pl/messages.mo | Bin 36368 -> 38638 bytes gui/baculum/protected/Web/Lang/pl/messages.po | 65 ++ gui/baculum/protected/Web/Lang/pt/messages.mo | Bin 36821 -> 38893 bytes gui/baculum/protected/Web/Lang/pt/messages.po | 65 ++ .../protected/Web/Pages/RestoreWizard.page | 434 ++++++++-- .../protected/Web/Pages/RestoreWizard.php | 789 +++++++++++++----- .../themes/Baculum-v1/restore-wizard.css | 70 ++ 11 files changed, 1248 insertions(+), 305 deletions(-) create mode 100644 gui/baculum/themes/Baculum-v1/restore-wizard.css diff --git a/gui/baculum/protected/Web/Lang/en/messages.mo b/gui/baculum/protected/Web/Lang/en/messages.mo index 523418c02ef99a531ac27da154c1ed2774a0984d..946847662181ac818b996c17453b58a0f08a6b5b 100644 GIT binary patch literal 36033 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
  • *vDZG!Tztt#r_$K+e?@u5Wj_~#;%{n&C!^9kgsrV znmdofEJMB&^P+Rd$=hFl_+5_MU6=zgms%%tMw0a1a-(Y{*$y>wcF$-{CgV`AS z&hSd-pM`f|cEq$hx7+bQ29v_Pis_G;h~G|_b1}n_lP;`qALanu^xMk9taIOBpN#t~ zcp>H(%yJiQ3m72(%*j7@)cSodM!#)wYsEZ;{UprG*q_EUV}6S~0dqFyHH?1y;C=^2 zzgh4)%r;gue@}FNO|T8K8rNpbOw2UrcOGoP?1tGC^E~Di%-1Fb+7JHB+5ZWK`2Ehw zr(i!B(}sK})bA0@jo6RHoR4`FIl}x4M!$nFzjk5&gncdMX5=HGeivaj!`zBns~q_4 zi~SGQ>g|C2ChYfMPQ$)EW-m+w<~Nvmm~Ub9`!0L|&VZL07yIW%FbTIsE}UHN!UV{3 zD%^e{4}QxrY3Du_`vsT+W&&t`6=#I@Mg?njDGK7=Hq@KJOMs}c~Bnw zwzu$(#H}CZ-;lS(^ud0c^LrEiv$J0Z2jQpRQ}8v+XzXueKE&*a`3`PrsNcodPk}#z z_ha#762(lh!(W^Z)cebY!?TS;%n=ISNosyPwsqtnc5=E+!qH4D4)IL|tx0M`XkH|xdGQN~( z)nWzXQ+COwI{gu-o8l%?M-{qqDLuIBPT;m4n<`I%>E|=-@ zW>~HJQ4vd_Jt$ax2HApCm``=6FN}!F)!ThUwEJ{#M!}yux300#n?Vct&D4qHu~Ox9 z!nBqV%WYR~59xNpo^*)~d**^{DkJZ(DPPRmEW<>5kZqF|R|e@!(1Owe)5?)YH(OE6 zIrzz-5csY6u)|Me(v-6<_E2A?^$KC06m6XKhKm@yw*Pdb=$4Eq(~ko+m>SNCbnAv} zx{wYs{!%(_K3Q^JoGKLPwx(RB`)5pdVBAXEar3H&qe{Os)#B4XR;Kbbr9^W1 zkScbRWQ9p*3#oi-kWeQ)rkJKKN-d!0(wv!85EbZ@DL)={>f7mTR0y)f=uFdoQ9FY# z>CZw#j38H{8ox<#H51tJ5XYe~uEs88g=~7VdS_(^Mp1EumUK4Aca{5gg%?4(Pfevr zi6V_dv#pctEL9=nS@_Gt7Ob`kQ8AYb^965~=^P9rI|;_J(QZ1M3_JZOeQe5`MNRYk zRljiXHF7KMbxw#GA%~HI@YlANNzt1X5B@p^&KQ4@n|m8tqHdb;Q>#*mVuA6)%pZ@jcx7`*7PDsJ2uwOrdsxgQ zwN%j_pYtc@vN?7YB%}5CIU1V9Y5>2Nql3Ga6 zYIz!1XZ+VQBNu2!12g{Xna7!8%$B9HFS%?yJMzLjy(7-quCcA@6m3Ec-4vRvStkT~ z*OE>3;@OSeR((2BN1^kFo!LwnB+X1v+6>shUVWayP6L~XS^5c3NHX1)F8C{hOfhBG znLRF4hv6SW#shT-X@5JJ3T}coa;IP9iS3nibg2fy^B) zM?Ys*RW>1s75*qTo1+-H*%c~gk|~;z*(yDnok}YkUd@@T;;qa%dFvXO4Z8Kyjy#zU zb3R?EJ(W+HjJ2`wlc`pUMALS#u_+B$Z8#%4pSWe!?LSCdCCsNaLe(A2UetM3l?LIA zS@WaOCMOLRJ3Ufb>ZiFS&qkIFtX;2L;zVrUikB-}yHL}L(P}DS6R%>?KolZMX%aJm z*!Vv=7eTpCnZz?)HO8Zkzs0=y z!yFqFj4kpwvuJ@*d98ZVB&p2_4Z}uLhqtyo`YnV!)AZ?jw0KmjoV3}glOs9G(XXN@ zbO4eE-u7a_XC`Vs0`qJH<@KPQyB%bp%P)P4pMAL@^J< z`!U(O@0Q2JjqQ#e%!y{xY4XV#_Kyhm@ z`Y*C%*l~dmg-Nq-H~Ut%oXAu(mx zEvdz+1QU0USy4M# zGeMb+j|R5Z@0Jw(!CW3B{VEsDEqHz|l~0FBCW;(;i{xl;UZ4Xj`(Z|Z#kwe|IpmxY z84q*LkeeNYvaNT~T-U>`ncY2%X4c&@{H;J6UNIHRZTn?qmOq#}wszH-l9v}XBbz@B z%sg=@*DO7jZ=WfMTMhO#G)~qZTcflpqnUJ!ZrH+_JqNRW#kPaswgugJtt2zdl~$w$ z^Wc!l!Dya&*Ucd&CpQgO%}LLsh0L^U&Na-k9UYuay?Mosoa(Tg3Rh)xc;>E-DR6$k zG+_U#TWI;J(6#!!cJv*&0&}zp>q5Dhrg`oBOycpF)PhSFv%= zL7STG9@f6n)UGNTjbFB{$d0^ZQFbcxc&6_n$0#FBsub)BXxyXpDm2T2=)x7+wLEll z=?u*}=>nJ~(?sperwep^mtB|6&-2-xX4x0cPpy=u^cO*EP=fNMJJPI&^VuR(}WaoOVzO!IzF&A}nQ1v4=Z(4MK@9Do0QZVA3tJHIA{Fz0m%uq8onA$ILCB{A~$Hk_0 zj&^HQL$Fl^e`Ma=;alOMwcdh||IEJLtpKcHW|1Ylb9XyXTW&csBV_D-?gHilcbmi3 zV1Yfv(LZbw=%wsrx=Nk5P(S zb+xr_Yt&Xu*G(Nebz&`dgtaV4CJGao%d9eylH=k;sOuCLB$C8l(5~W9N+)V|xk}?e zZy`51Os%>TMbUQK>MdjqwA()R0Ssu){7m;zgonSR?(#2Qy=#0OC^~~e!d#^&8-l9&?Y7SxlhiG^ z-~{Rx3e#xsI4bVEv+5&Of9BGT+1s3srfE|=#vc}~NON_Ql#Mbbd24U48%xV@hD)4y z!JA;VL(C6xsJfDk`xST8S6L#q-h|?6m%gQIMBPw(?oyU1hXi$%>vrsfw5O!950y=4 z*W(`VzSrl)U0V<5((ZEo?zU_8@T)jT&;s!}qDP=^ovepnW#{bS)#F%MUL!UbZvEHC z8w#%FriWkLq0Ab-A-}&BPgj^d;;pZ7HqbC^2la(%9bY^6IO4j^szQ}=ah@5sKPb5u zvvf|5EjsO+&sXuaw7pxPR&-#`;Vmp}9tCVuiyVasZ^0(t%}-BU#b@ zjquVjSbvLcMQw(g*d()e=vx1BweIdP4o@QX+eduLG?%fA+sfm3{LLcKp5k^z9k0?` zJ9JK=x>TSlTt|k9kSz+fm1!Nc?GWcS(%uQWIY~Pma~aHM8GUYvKgpPHP+pThBzgxG zb(^Ev!`_&9i&BZM1X~hK@O7~yiy5R)%aTKRYKa|m9fCcV(do%8z)S#4iPV>iouHU; zyH7&(XhuqH&a=$EnnhZ}42M@um2vy90Id_rp0;~lH4x0qIgat?hgh_VkH1vJu2O>i z<{c>?C14bjbM0<&k6p`x8q$52i({#-@hxq)fEsFLhj{a}sC3oHoT-DDZXDeisq9A= zi2ck4nZ;}!&x(D0w9<3(~Dr9}&K2$FdOs}?q%m)QKb{8jD zvAKe?J#{e~`2@;kS`V{Hk~9mvN#EHk#z~sZfjOZmyxR!aO=Zc|eezt~&IL-h(&vNt zD&3Q3Z95~-+%c8vS6Xl>1^t&=>Q=98E#2!mCv$9x{mnsTvA*ps&V&W?$KTL(xeA~5vfz$^-b1$ zD{{B@0(4IEx`U82%g;k_)hGW_92bbqv2Z-xNWzOEk$yj=wZ%H`}dx6J7Pn?;qBwoy|Z2-DGL@#NASv)Fb!Fm9qVu zYmcl_dpB9_Y#lVly9x9W=M@jMk_#65O_wd~VrB>?1r1pi4}BvojhBSx(oP%2ntScaN|qiNw3#dPoO?gTg%f>Km(@29!+^L57OIMj4TuW$EL#auvoS(a+cRkH4 z&E?O&B%u?RUIR_{%!i8Rbj}}NXS6OA+g;+ZVc1c+sYlbe>yvb+X>Zo0HhuM=n(3U4 z*=BFx{BH5MZCjyNUxDuH;utLXO!CbJr3oIS;UYvYYrGgo4Sh`eTY1KyGjbLX(c zPT(!9o*`3%A8D!ZoU0N1i0|>;UFf_>8 z?EZ{r5zkUxuzyIbVC4GR&mlRz}ZVT6HfX_v5-B zOL=CuD-G+&z=u=2MKK=$;)$7=QSVJS2yWOv%p~QnyCCiF&5Xxos(H{=MN4v|;PX7piz9Y-;17X*D~)~ab9*R3=|PPco^-`;VI;rt2yid2_g zG}|xG^jxQ7`|8*{C*X2L?|>DYu3RuTzr@h^k(;KT8t9XFwR+_-9n&-n3m6ZWp#dqO`h3YK%-S>2GVW_nWKI=^4j!shB(TBOTy`{@fw zbu&-PB0hri+Q@HYU0_Vj4O#+!U+Rfa(~ht|Ybu{JYI2$Vh-5$IR5z!B4ib*#Ixao? zH8wQPE@wKfW^BJ%3?*j#YOO+beBxhKsAV*yv-{Zl#Z+NhItr_&Oqn>fdR#fM%G8?5 zSI^F}PN9!Fe@aWb(C?6H`wqeswkhPYm`_MG6Kf{)<2ifp`}WG-MhEJB-yT14?S0?w z{%rztOg#JczHfKu_ulvIT%^r(tGxD8-QQQ2eb)bhf`{h4@7vkTmA{;F?CO2ruI-8c z5Awc!S$0|Wf9Vr<75#tymAlEc+a*iyLwBycH*_;!`3%1Ip?i(%Ehwg5&>3!&K-_G|wbZ6n{edyl% z&|P=`+`0b!hwk0}tz+*ycRhFSedpf$&fR{{_(yo>UV8K%mL9e1z)*fX(fio_f74_4 ze*F%h_5S-`yZ7rC-(dDWcQ5$8&)wZ)bA47XJu0{V<{ zD!Yi+4(<_rS>Su2eQD9nsrR|N9zgd#cjsY7?{jzkFFN#3Ui81j>3!~Q-U;ym)Gfc| zugSdU=DoBY)VqgSz0cj5ZuLK@vM)?~pS$Zp{r|D&?)r|}?fw4$=Zp7szsEM~onr5! zcOGu{K6>Zz$p)T+FX?^s?q0xe=+V1I*57>ht^iH;Uu^szdivgTLg{_|Uiv4@UhnI7 Q^KUQzFmTJy%98ZJ7kucrBog( zo6Kgj+L}$4p6b-K+vusInUz=Tbek-*EGs>q?|v5L>z-csk8|(+?>?`7yw_UKwAOE} z^&lNN6&73>9{8|T#LX7Rone;M0TY^AR$91a#k5zeW$o)?S+TeuIc2?r&G2K4!7okw zPo^H7?3_<9+NkS#V`ChKO)wMRvaEnL!89bLI4|ms(OfXpI2s#K&p|zC0;&U-8{L>l zeF3(`HK>l>g^~Cu4#r)k{R`|!{U>b7`>nQJod+gk94Go<6pleXFbCt&Wvnsn*I^6V z@4?piI4V=G;s891EwOnw$0W3=r=gOYkL`HB<)P3SS78)x$ENrQ>H&LDFL(tb@k5Nl z6R1plfy&GoROTYOJI0`{Pe667J@&y~n1EMcKrgPMAUB~d++}Yr-t+8X7dB7CoH{5>X?zQ5OzDy?8Wg zuJf=j&ch_!h??`AI1u-uGI9!a|9NBMUe18xP?>4hi~Ofk=tP6eN8Pv-HAibvQ?MPC zf!){!U&40yf$;}qx~tRzrjBiu_4ll)*SpfMMPx_i-ppZf{3Kgbd z5$Zu#<4C*%Sy$FkT#XU^oRO?Wb+{h&pu0``BdDp`joLjg7!M&k&iWPyVe9^(``G^! zTF@{ZmFg0Vz=f!Ndlkmw6R45CXwDx%z2HsMeV<_r{)l>BBzsUMpw1_w7Uuv|=Eh;9 z_WxW8nmadYMC))AZb4<{FzNxHpyu#<)CkX^u5ZkW(~Dc9GLekBJ{{w5B&s75QTNS7 z-RDtV`@fb#G_F7`j_Xh(y}`8KV(NFGUa;NNA2aSjeY&4V?V2Na5uQSIqy_nw9Z?-g zM-6xc26UpxH26^UEvUJA5Ou>F$miWUikb?|i#igAs&_zjJk2-&wPuE)GBXdAxe5%& zg{Uc5G?@Iirm&F)rTPJEg}YD>eg$njgu3x3Ou%1Ib00Uv$y`r7LA^g}WNn5zsUCsK z#5hz3i%ASi5H-yCW>3b8sjtC&dLyN!YSDd@r-*ax3Nt^WV~1QW3>Dii6Zo{3saGf->9 zZQAQl9ovAq|4!5#KZ;8A^QerykD7`z*a4F!G=EcYf%BgYxM)Da}NseCB1&3q7a-)SzB? z6)F=eO?|C7ztOnav~R`60WQ3kf;zARkKrEF+;5raqDG1!jw_NG1%)xk{EFST3@{r+E0K@YwWHS)VqtN&4q!vm-rKftbd9QA2#!b0hV zNvK7ei^@z1YM0cYp0^%nU_Gj%+pr7%8I`F|P*W2gnC6VE12(3iJ6^>i>x=5p zBh#H12C+N!7g5)Jfm$=CF%i#UUrd?hO%TVBDR*w_O%;StQn%302RLF_^O9n@6(f?8WGS$SzV5PM=F zzKz%8EZ%R;oudN3r%{Wn-CSoorJ(A4Q5_hLBXKHr!<%q5K8u=)G4q@bk4I(5g&Nob z)Kn}(WpF*V#od?^pzsETLHHf&MLk^3Hp)Uhr~viFD#XE9idvL+pfa`7_$2BDdr|j& zit4}*sBPJ(&}nal>OdC^XpV+c=!7oR8d!m9UxOWR2WsR8P#>BmMb3i~Q61=tT0^~2 zBOQo(aV9E*m!Uc|6XS3`szXbP$iGszjt1R$GpfD~^}rpd4(&!|=2_H(-bG#i3F-yk zp)zvLoNrm|OhqTuJ|Bd-eiG{bxkhg>`BzT@G-$*dFd285`XS>vOrbr+?d;=RV>zm0 zH=sK5AZmNONiFdEg<>84(a8o@HOaXsq3 z9jJZ(7-~+Bq3%12pJLNeXJFr=GSsHb$w(?jQV(QP(00kg^*9?R;O961hj^U7h_1wZ z>JOk6;ThEV^!d&QrVw?0GtR?LaVUeGfKb65fx>$jhijdJsF~H<*pBDxAeR9h*>}gSx&9mFa~T`u~3$DCmMMs1$7r zonQ{J5A_#J{Uj=7XN^{+ljZk}yWmE1ewV55H=aPPq39}Sk#$5(aT;n0Mq_uJg#i_=rl1Et zf>HRU@jYxw{V3`IUm2|h&I{sE9qWm@Z!{_s<1iYhn)cbKj1*&6tU`TnZdt(m>&7Q( z&=l-NrT7($z}Hc8`wnUioJ5VFQML0y>V&b>=in&xVjS+oR=6KEfWI0~pgMdSwRoHQ z$bWkZBYjS4FGrnNhJEn~OvB@-#TDmwt{Y&SfqKDGJ z&R;|;FqBzrO8e`m4h0TTXiVWtR0qCC_4q6%V)MmLN|Q14DMgK761G4uYOyUteK~JN z&GFOb{70x=@HJ{cKcg}hc~$5=0V|P$8d6aY9BS(0P$`;@S_5UM#kv}`opzws&U>g1 zA4QGm8`R>8SmG?g6x8#3V^=bHF=~+(E>(w^|0)XV;bPQYA zyHFi?8uh@G75v4EM+q&q+X)?=)yUD$cn#(Lgx}Oz{Gnqa@3&m0@+mgug7@$eVmdLE z`aSrg%ET(-!sAbzpGm{tO=BzS_fihSu~=x@rx>GYf0J?|wjlI=>n?bn$R)Kjs#C{@@ zw!jDqeJJR-jo1|`@vm0Ys@36k2<>mS?{CLQN;hzCxVirg>g@x2oWT7Tu=1m z{3$$1j5615!RADc=3gHf9SJn-#{VQfCdLsBM>&NXiN;)0+R%u9Bi7M20q?|xgpRGm z)1i{Hbyd9F)Q6zHxH`H9xZzr2ley7p=6@!d!Y8P|2fGl-#1di>ZTcWJ95u9+P$?qX zQN9@4<3MwPhjJNlBf+na&~ccb&k|aHRuv}}5nCwh)2icF;sEgzk`j0 zrs)jFO~g!2yo7_)z>!G&2XS5%js%C$&pxJ{aY5T~$~O~Jc+LP^jkzil@zgW0;mB0} zzoT|5jbkwLf|JcCmlIuRpN+Gyg5Z|WZ$Ge(=?BNp4%R@fYdES*VG?Z{h_|U=eg_ja(lzXU7=vYOYj-C$ITvJzdH04(K z4iT*ej$)!KafY~B^M5UcD+nDA6EB2H&cF3c(VD=6o@l6G1ksd;qg@$%N^SThK1ke2 z={VUF%xpv;AJ%N2iMXcA=~2%9<)Qm@K8+msOT8GN;Lqxq#bvq<5jG*zL2+ zJwCtfEwSf&3w?G;wYS2qE%OwWnFM=$c9oYN7MAnIh8G2FZ>3u|q}#bA_9AbMUFqiO zOo?62r13oGMdo>G&nox0EB&^s-0!Zgboo6C-SkU$7P%@ld-k|$FI}(ja&xu2NY^$z zL%nsn6q;?un)Ul&c?GG~g9=?fO+6EBMoItdN>_zj^Wm%`x1R0u)>Id{)9aUb->uKc zynjj=L#*{Ic2yVK?n)Qq^o1VBV2i!Br_yG&c|UzJss6X zd*zSz&5#MFqZ0l%_f2s1!jXMTgF^M{1h zZ@$tU+FteJM%AllyHMm)y$AtCi(;Yc#u`@AE&;>*ed-^XkX@obzAK`Tx%O|55WS z^}BG};kpzN@RCJY--IAOD~3jJxnjvBBABk>*798aMpb{(B~ zA3Nbg)8Da`Wi_XrgLSYJ^#D^aobj#sR08Q(gSz2*tdD;&9y0xBFqHlq*bsj~Wu{)7 zWp%_@48x(uaTr5;E;hl9*cjhLp4mEvfsAi`Pen7ki@L#Yr~$%S+fNjanqXVh%sZko zk&Vh!zHtaTX_ufTHU`^aIX1voQ3LNYo=2BXd`Lxx#M?J)j(XB~)LLbr)-D@$gMQ}t zWK^aqO#6A`R^uC}2iuRj{zF{lu&k39NPAc!`PT^}6YVFSh&s`Q8hACf#|_vF|BhPg ztEddz!XSKTbhfb{AQYYSH^fwIY8-&Nt`fB*tJ;u%rF;h+dg8ZGYjnhT0ZEQ^54EYH zlk8Lu!f@IXP!p&?4Y<_wuSPxLpHLHi1$F=3xBw610nBtITUH+`cTl@DtF2`{!6XrIM_xQl}Y_%mvcJ?YO_5+WhgAoPI&@qiBeDxG8nV543&vjQ1|~U>cI}79_%9w(ffaz ziUz)fdXk%{3+`h$26nI~6otAl0X0yXX=kHe!~Uo}P=s2#;ii9-X^%(Uf0}78kb3`J zRP^axiF)r}#c14*n#kwIZ%~=Jk9uM!UmYD!Mzy<|b{T4kW}(jChX{gUi%RdYcSL$xlaSi{CdXmfRET!7X&QT`9(EFsgmUdUn$D_zxt;kHv>W2NX09PW1tj|!# zgR?A)TU$L*$LC@xevn1}savf(+bJ7`8gLmV;C4*Kf0+LJ#)vNVd8x)ctj~Glu_0EX zK3FfJ_R4P55+A}wcpm%UZ5I`7mdvj9>(T?YHoZ}6SAbfYk;bvcNvQK?U^}ctWo(x@ z{x{=()Ka{Mn#dW{QeH-7-gTXd*6v5tfDcirs!Kk#2YRAToPat$1NG~7G3tr`VA`*v z-lD^(J#ftQUqVgbE@}y#-R;apVpF~UX;hTz0&IcvP#=zs=#N`a6WES=f}N-dzirw_ zP!l?Zy6$V!e*<;heD8H|Qt)cJ`Rr1!rE6coH2}4=BQOffFb*rR32w(&7nS`~Qt%6m!8$!Hi$7af$*9Z}Vj|8* zO{@x)%0tEz#*3(leUF;>BUHxf=GYT!j9U9-)P2*@rA<>pWgCvi3=HVS#{#>cGIIsl z7S`9uN70JyZEwoKsDX-&<52^Yqpn+o%D@s-%2%T@^fD@=dwP@qW>k*Tp_JV~y*|HS zE3DVY-V^Dli4HN2GEPLj9kWrJZUHJYzen9~3kKjW)Z4NfmBIa}asSoFWvBKY9oi(# zpRk`O33Y=^)F$eSO&x4fR7$7xwa>3WWncw5aRX|io6#S4;2^BV2KWnVoX}kR!J4?J zXwAByE*O9TSctW72PGLN27DK5;YX%@(j5QHc)|2v#UReRjA-E4m;zy_f;|lB#NIJ&RE=2XuLG6X*sNZ^9 zP5)`EL;DKqHN1(<(NW0zuT;lS(d!eBI-xUa0)^=Pt!9o_qRxLF^@MJ0hr3Zvcp3Gj z`v!IVH`L~ie$uurhSBbhI&a{U`*1yn}1qMq;oM&kRZ8=l2C@iuP2*M`}D(8wHaU$+R`(7y#E(Dfk|ZKAW7g1=%C zCO>8W1!EYN&`vD2U4i;8e2E(H2jmx^6*R*B^Fl7JpgkS+8s0@s@DVB#4W70iBo4_m zzyGNyRoSRbF%dPPC76NLsDZw~P`r=2k&{{J!xM?hTobH^MX1b-LEU!}>ii9;4DLYP zXScVX^*>BS1D`}K#kbf3LwM)3#wn=&j@T57QBOP%m5H}e0~|pOd9R)cJv<*vNYS8&c7X5>YA3L|vF;+J&ea7NaIqhRVnU)Qy&)&VLa#z;;w7cA4V` zP)l$Oqwy;0{9n*7ZM24a^ zZz(DR^HC479OH3qDeJERJ#@(T(GSmHBm5L~gYQri^)IvA^-)idgfW@YI+vi9 z^m){E)%XqWMLpQIF?NRjKE`FI2LZ+U_095O#3Bt z(ylUAqf%Uhn#e)a=KL77=GV;epD>ZOW0IYzB#hVlKbne8TxoQpp0Em)vc1?6FPP(x zOuO!6yFV4RM~YBOI1!b>g_wYwjPIiE^DQbPb*4zxKb(r5APRMZL}ORfjSEl{8i%@Y zA?it&Vl7;cb#XJc#@Da~evCT*2G+)(FaRH*mdcvSk}|&4jEZKQhCOf~Y6;e2Hf}@h zjf2@%ETTI|udT<+u%>#SDy|$>$u4W|DuUBz2Z$@iDSGBH6Jv zpf=eftb+lw?SaBDh;}Q~b!{;M(@+`cgW)&=mC>oFiLJ&^tVS*A+t><^&nEv`vmea~ z4a@D#*cvtS4j6{rFaq;Udo=2XGfaCiYRT52)^8%kGaQ8HP)pf%p1m0hPy>uWO{fxe{w7rB zwxBkrtBQ)&ekUq*$FVbB!cG`9-~Lb(qAr|(TAHb-iOxn1^c?bLSyiUL?gIOGW7NbG zP)nI<+P!RD)*vcM+gTP)%$-+f771H$$y|e9(`r6uY#lK_anZdUi4Uh zzB#`kecIeA9~0UiV>tEztBH+z{^?YD(>aLH4)>LTR6ZnT)BhLKIfr^}B8pf}Umnqd zdNHwrP)WD3hSHv4`m})qsdq7L{ab>!`11cVt(S-&iJ{&j_7ClNUTtd<7c9dz#5H0Q z@p$>K#~Y?zAKxRMFoSi&>$FRV%S1YDS4V#M(fFL`PCW^Spgx-_{I2o-{(q9bZ@fMH zfs^_z>PLu1L|fV_zYyirbBPzJSKuT36VZ$Cm7l15N#tt(1(}O=&`G@*OVyz6mXxoF z&E6Wnzwyte9?LmvssGWmedya?NOb1-@9-7kpM7@~x}XR#$-zyZV+;tQh6xBeA0p5law zL^DF=3F0&2KC#&JQT3K#wC9_?DARWr<4oUV+(UZ{@g(sokxbvea6WN~c$&7Wj2}}8 zl>&U-u3Cd}zp1yPej-~Br3roG2>tG$ zxV-;6Y#ALN(c0$i`~N@mJwH#JCgyUkN^@c$^?zeuti%geAx?U0mh~UT5!jXE9=u9q5Cud4eKEv5>b|mow#u6})^OAAX;gP1 z_1#!b%uclDhDfD<8mjCf zdYEh9rQVi!p7@oRqVK=TSR#V>y&9B5#2w-W5zNKsuodAe{pd^aHH`TZc+d?j6NZo}0yKPVe1A9iE)h=?>4{vUP!;yoq<6!Cx)g<^AvAS4-dV zR8L>v@TAP_&%7Fk`>h3MJpZf+@pE5XnCoe~sFw48 E0o9h~nE(I) diff --git a/gui/baculum/protected/Web/Lang/ja/messages.po b/gui/baculum/protected/Web/Lang/ja/messages.po index 1d460895ec..6ed67fd1b9 100644 --- a/gui/baculum/protected/Web/Lang/ja/messages.po +++ b/gui/baculum/protected/Web/Lang/ja/messages.po @@ -1187,3 +1187,68 @@ msgstr "Resource %s \"%s\" removed successfully." msgid "Please unassign resource %s \"%s\" from these resources and try again." msgstr "Please unassign resource %s \"%s\" from these resources and try again." +msgid "Size:" +msgstr "Size:" + +msgid "JobId:" +msgstr "JobId:" + +msgid "Volume:" +msgstr "Volume:" + +msgid "InChanger:" +msgstr "InChanger:" + +msgid "Sum:" +msgstr "Sum:" + +msgid "Select" +msgstr "Select" + +msgid "Path:" +msgstr "Path:" + +msgid "Restore wizard" +msgstr "Restore wizard" + +msgid "This wizard enables you to do in easy way restore files to destination Bacula Client." +msgstr "This wizard enables you to do in easy way restore files to destination Bacula Client." + +msgid "To start, please select backup Client which data you want to restore." +msgstr "To start, please select backup Client which data you want to restore." + +msgid "There are two ways to select backup to restore. Only selected backup way provides list of jobs from which there is possible to select one job. If you need the latest backups from the Client alternatively you can use Group most recent backups way which will select backups for you basing on backup job name and fileset resource." +msgstr "There are two ways to select backup to restore. Only selected backup way provides list of jobs from which there is possible to select one job. If you need the latest backups from the Client alternatively you can use Group most recent backups way which will select backups for you basing on backup job name and fileset resource." + +msgid "Do not relocate files" +msgstr "Do not relocate files" + +msgid "Relocate files with prefix and/or suffix" +msgstr "Relocate files with prefix and/or suffix" + +msgid "Relocate files with regular expression" +msgstr "Relocate files with regular expression" + +msgid "Strip prefix:" +msgstr "Strip prefix:" + +msgid "Add prefix:" +msgstr "Add prefix:" + +msgid "Add suffix:" +msgstr "Add suffix:" + +msgid "RegexWhere:" +msgstr "RegexWhere:" + +msgid "File relocation option:" +msgstr "File relocation option:" + +msgid "In Changer" +msgstr "In Changer" + +msgid "Volume" +msgstr "Volume" + +msgid "During restore there will be used following volumes:" +msgstr "During restore there will be used following volumes:" diff --git a/gui/baculum/protected/Web/Lang/pl/messages.mo b/gui/baculum/protected/Web/Lang/pl/messages.mo index 054235dd35a0f55c5893b8e6a042a2b09d113089..e37cc42c5999332de62465c088c219cbdb496bcc 100644 GIT binary patch delta 12676 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 diff --git a/gui/baculum/protected/Web/Lang/pl/messages.po b/gui/baculum/protected/Web/Lang/pl/messages.po index 9c5eae621f..8dcc96ca93 100644 --- a/gui/baculum/protected/Web/Lang/pl/messages.po +++ b/gui/baculum/protected/Web/Lang/pl/messages.po @@ -1443,3 +1443,68 @@ msgstr "Zasób %s \"%s\" został usunięty pomyślnie." msgid "Please unassign resource %s \"%s\" from these resources and try again." msgstr "Proszę wypisać zasób %s \"%s\" z tych zasobów i spróbować ponownie." +msgid "Size:" +msgstr "Rozmiar:" + +msgid "JobId:" +msgstr "JobId:" + +msgid "Volume:" +msgstr "Wolumen:" + +msgid "InChanger:" +msgstr "InChanger:" + +msgid "Sum:" +msgstr "Suma:" + +msgid "Select" +msgstr "Wybierz" + +msgid "Path:" +msgstr "Lokalizacja:" + +msgid "Restore wizard" +msgstr "Konfigurator przywracania danych" + +msgid "This wizard enables you to do in easy way restore files to destination Bacula Client." +msgstr "Ten konfigurator umożliwia wykonanie w łatwy sposób przywracania plików do docelowego Klienta Bacula." + +msgid "To start, please select backup Client which data you want to restore." +msgstr "Aby zacząć, proszę wybrać Klienta kopii zapasowych, którego dane chcesz przywrócić." + +msgid "There are two ways to select backup to restore. Only selected backup way provides list of jobs from which there is possible to select one job. If you need the latest backups from the Client alternatively you can use Group most recent backups way which will select backups for you basing on backup job name and fileset resource." +msgstr "Są dwa sposoby na wybranie kopii zapasowych do przywrócenia. Sposób 'Tylko wybrany backup' dostarcza listę zadań, z których możliwe jest wybranie jednej kopii zapasowej. Jeśli potrzebujesz przywrócić dane z najnowszych backupów alternatywnie możesz użyć opcję 'Grupa najaktualniejszych backupów', która będzie wybierać backupy za ciebie bazując na zadaniu kopii zapasowych i zasobie fileset." + +msgid "Do not relocate files" +msgstr "Nie relokuj plików" + +msgid "Relocate files with prefix and/or suffix" +msgstr "Relokuj pliki z prefiksem i/lub sufiksem." + +msgid "Relocate files with regular expression" +msgstr "Relokuj pliki z użyciem wyrażenia regularnego" + +msgid "Strip prefix:" +msgstr "Obetnij prefiks:" + +msgid "Add prefix:" +msgstr "Dodaj prefiks:" + +msgid "Add suffix:" +msgstr "Dodaj sufiks:" + +msgid "RegexWhere:" +msgstr "RegexWhere:" + +msgid "File relocation option:" +msgstr "Opcja relokacji plików:" + +msgid "In Changer" +msgstr "In Changer" + +msgid "Volume" +msgstr "Wolumen" + +msgid "During restore there will be used following volumes:" +msgstr "Podczas zadania przywracania danych potrzebne będą następujące wolumeny:" diff --git a/gui/baculum/protected/Web/Lang/pt/messages.mo b/gui/baculum/protected/Web/Lang/pt/messages.mo index a4e3dcdf01408070ce66cf6afe20c57b274406c1..efb09de1e6095fd02efb56e327a3e6b09312ed36 100644 GIT binary patch delta 12485 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 @@ -42,7 +44,7 @@
    - +
    @@ -54,106 +56,235 @@ +

    <%[ Restore wizard ]%>

    +

    + <%[ This wizard enables you to do in easy way restore files to destination Bacula Client. ]%> + <%[ To start, please select backup Client which data you want to restore. ]%> +

    - - +
    - +

    + <%[ There are two ways to select backup to restore. Only selected backup way provides list of jobs from which there is possible to select one job. If you need the latest backups from the Client alternatively you can use Group most recent backups way which will select backups for you basing on backup job name and fileset resource. ]%> +

    - -
    + + + +
    - -
    -
    -
    - -
    +
    +
    +

    <%[ Backup for restore: ]%>

    + + + + +
    <%=$this->getParent()->Data['name']%>
    +
    +
    + + + T + + + <%=$this->getParent()->Data['type']%> + + + + + L + + + <%=$this->getParent()->Data['level']%> + + + + +
    <%=$this->getPage()->getModule('misc')->jobStates[$this->getParent()->Data['jobstatus']]['value']%>
    +
    +
    + + +
    <%=$this->getParent()->Data['jobbytes']%>
    +
    +
    + + + + <%=$this->getParent()->Data['endtime']%> + + + + +
    +
    +
    +
    +
    - - +
    +
    - +
    - +
    - +
    + + + <%[ Path: ]%> + + + document.getElementById('restore-browser-files-loading').style.display = 'block'; + + + document.getElementById('restore-browser-files-loading').style.display = 'none'; + +
    - - -
    - <%[ It seems that there is no files for choosing or file records in database for this job has been purged (file retention period expired) ]%> + + +
    + <%[ It seems that there is no files for choosing or file records in database for this job has been purged (file retention period expired) ]%> +
    +
    + + + + <%=$this->getParent()->Data['type'] == 'dir' ? 'directory' : 'file' %> <%=($this->getParent()->Data['name'] != '/') ? preg_replace('/\/$/', '', $this->getParent()->Data['name']) : '/'%> +
    + + <%=isset($this->getParent()->Data['lstat']['size']) ? $this->getParent()->Data['lstat']['size'] : '0'%>
    - - - - - <%=$this->getParent()->Data['type'] == 'dir' ? 'directory' : 'file' %> <%=($this->getParent()->Data['name'] != '/') ? preg_replace('/\/$/', '', $this->getParent()->Data['name']) : '/'%> - - - - - document.getElementById('restore-browser-files-loading').style.display = 'block'; - - - document.getElementById('restore-browser-files-loading').style.display = 'none'; - - - - - -
    + + + + document.getElementById('restore-browser-files-loading').style.display = 'block'; + + + document.getElementById('restore-browser-files-loading').style.display = 'none'; + + + + + +
    @@ -176,10 +307,27 @@ <%=$this->getParent()->Data['type'] == 'dir' ? 'directory' : 'file'%> - <%=is_array($this->getParent()->Data['lstat']) && array_key_exists('mtime', $this->getParent()->Data['lstat']) ? date("Y-m-d H:i:s", $this->getParent()->Data['lstat']['mtime']) : ''%> + <%=$this->getParent()->Data['name']%> » MTIME:<%=date("Y-m-d H:i:s", $this->getParent()->Data['lstat']['mtime'])%> » <%[ Size: ]%><%=$this->getParent()->Data['lstat']['size']%> - + + + @@ -241,19 +392,39 @@
    - +
    +
    +

    <%[ During restore there will be used following volumes: ]%>

    + + + + + + + + + + + + + + + +
    <%[ In Changer ]%><%[ Volume ]%>
    + +
    - +
    @@ -273,6 +444,68 @@
    +
    +
    <%[ File relocation option: ]%>
    +
    +
    +
    + +
    +
    + + +
    @@ -291,7 +524,6 @@
    <%[ Backup for restore: ]%>
    -
    @@ -343,6 +575,34 @@
    <%[ Restore job priority: ]%>
    <%=$this->RestoreJobPriority->Text%>
    +
    +
    <%[ File relocation option: ]%>
    +
    + + + +
    +
    +
    +
    +
    <%[ Strip prefix: ]%>
    +
    <%=$this->RestoreStripPrefix->Text%>
    +
    +
    +
    <%[ Add prefix: ]%>
    +
    <%=$this->RestoreAddPrefix->Text%>
    +
    +
    +
    <%[ Add suffix: ]%>
    +
    <%=$this->RestoreAddSuffix->Text%>
    +
    +
    +
    +
    +
    <%[ RegexWhere: ]%>
    +
    <%=$this->RestoreRegexWhere->Text%>
    +
    +
    diff --git a/gui/baculum/protected/Web/Pages/RestoreWizard.php b/gui/baculum/protected/Web/Pages/RestoreWizard.php index f395a7812b..aeffaec46a 100644 --- a/gui/baculum/protected/Web/Pages/RestoreWizard.php +++ b/gui/baculum/protected/Web/Pages/RestoreWizard.php @@ -23,261 +23,300 @@ Prado::using('Application.Web.Class.BaculumWebPage'); Prado::using('System.Exceptions.TException'); Prado::using('System.Web.UI.WebControls.TWizard'); -Prado::using('System.Web.UI.ActiveControls.TActiveDropDownList'); -Prado::using('System.Web.UI.ActiveControls.TActivePanel'); +Prado::using('System.Web.UI.WebControls.TDataGrid'); Prado::using('System.Web.UI.ActiveControls.TActiveLinkButton'); Prado::using('System.Web.UI.ActiveControls.TActiveImageButton'); Prado::using('System.Web.UI.ActiveControls.TDropContainer'); Prado::using('System.Web.UI.ActiveControls.TDraggable'); -Prado::using('System.Web.UI.ActiveControls.TActiveRadioButton'); Prado::using('System.Web.UI.ActiveControls.TActiveDataGrid'); Prado::using('System.Web.UI.ActiveControls.TCallback'); +Prado::using('System.Web.UI.ActiveControls.TActiveTextBox'); class RestoreWizard extends BaculumWebPage { - private $job_levels_to_restore = array('F' => 'Full', 'I' => 'Incremental', 'D'=> 'Differential'); - private $jobs = null; - private $filesets = null; - private $storages = null; - private $clients = null; - private $browser_root_dir = array('name' => '.', 'type' => 'dir'); + /** + * Job levels allowed to restore. + */ + + private $joblevel = array('F', 'I', 'D'); + /** + * Job statuses allowed to restore. + */ + private $jobstatus = array('T', 'W', 'A', 'E', 'e', 'f'); + + /** + * File browser special directories. + */ + private $browser_root_dir = array('name' => '.', 'type' => 'dir', 'fileid' => null); private $browser_up_dir = array('name' => '..', 'type' => 'dir'); + /** + * Used to provide in template selected by user single jobid to restore. + */ + public $restore_single_jobid; + + /** + * Stores file relocation option. Used in template. + */ + public $file_relocation_opt; + + /** + * FIle browser elements for which 'Add' button is unavailable. + */ public $excluded_elements_from_add = array('.', '..'); + /** + * Prefix for Bvfs path. + */ const BVFS_PATH_PREFIX = 'b2'; public function onInit($param) { parent::onInit($param); if(!$this->IsPostBack && !$this->IsCallBack) { - $this->setBrowserFiles(array()); - $this->setFileVersions(array()); - $this->setFilesToRestore(array()); - $this->markFileToRestore(null, null); - $this->setRestoreJobs(); - $_SESSION['restore_path'] = array(); + $this->resetWizard(); + $this->loadBackupClients(); } } - public function onLoad($param) { - parent::onLoad($param); - if($this->RestoreWizard->ActiveStepIndex == 0) { - $this->jobs = $this->getModule('api')->get(array('jobs'))->output; - $this->filesets = $this->getModule('api')->get(array('filesets', 'info'))->output; + /** + * Wizard next button callback actions. + * + * @param TWizard $sender sender object + * @param TWizardNavigationEventParameter $param sender parameters + * @return none + */ + public function wizardNext($sender, $param) { + if ($param->CurrentStepIndex === 0) { + $this->loadBackupsForClient(); + $this->loadGroupBackupToRestore(); + $this->loadGroupFileSetToRestore(); + $this->loadRestoreClients(); + if (isset($_SESSION['restore_single_jobid'])) { + $this->restore_single_jobid = $_SESSION['restore_single_jobid']; } - $this->clients = $this->getModule('api')->get(array('clients'))->output; - - if(!$this->IsCallBack && (($this->RestoreWizard->ActiveStepIndex == 1 && $this->getPage()->BackupToRestore->ItemCount > 0) || $this->RestoreWizard->ActiveStepIndex == 3)) { - $this->setFileVersions(array()); - $this->setBrowserPath(''); - $this->prepareFilesToRestore(); - $this->prepareVersionsToRestore(); + } elseif ($param->CurrentStepIndex === 1) { + if ($this->Request->contains('backup_to_restore')) { + $_SESSION['restore_single_jobid'] = $this->Request['backup_to_restore']; } - } - - public function addFileToRestore($sender, $param) { - $fileid = null; - if (isset($param->callbackParameter)) { - list(, , , $sourceElementID, , ) = explode('_', $sender->ClientID, 6); - $fileid = $param->callbackParameter; - } else { - $control = $param->getDroppedControl(); - $item = $control->getNamingContainer(); - list(, , , $sourceElementID, , ) = explode('_', $param->getDragElementID(), 6); // I know that it is ugly. - } - if($sourceElementID == $this->VersionsDataGrid->ID) { - if (is_null($fileid)) { - $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex()); + $this->setFileVersions(); + $this->loadSelectedFiles(); + $this->loadFileVersions(); + $this->goToPath(); + } elseif ($param->CurrentStepIndex === 2) { + $this->loadRequiredVolumes(); + } elseif ($param->CurrentStepIndex === 3) { + if (isset($_SESSION['file_relocation'])) { + $this->file_relocation_opt = $_SESSION['file_relocation']; } - $fileProperties = $this->getFileVersions($fileid); - } else { - if (is_null($fileid)) { - $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex()); + } elseif ($param->CurrentStepIndex === 4) { + if ($this->Request->contains('file_relocation')) { + $_SESSION['file_relocation'] = $this->Request['file_relocation']; } - $fileProperties = $this->getBrowserFile($fileid); - } - if($fileProperties['name'] != $this->browser_root_dir['name'] && $fileProperties['name'] != $this->browser_up_dir['name']) { - $this->markFileToRestore($fileid, $fileProperties); - $this->prepareFilesToRestore(); + $this->file_relocation_opt = $_SESSION['file_relocation']; } } - public function removeSelectedFile($sender, $param) { - $fileid = $param->CallbackParameter; - $this->unmarkFileToRestore($fileid); - $this->prepareFilesToRestore(); - } - - public function getVersions($sender, $param) { - list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4); - if($filenameid == 0) { - $this->setBrowserPath($filename); - return; + /** + * Wizard prev button callback actions. + * + * @param TWizard $sender sender object + * @param TWizardNavigationEventParameter $param sender parameters + * @return none + */ + public function wizardPrev($sender, $param) { + if ($param->CurrentStepIndex === 2) { + $this->restore_single_jobid = $_SESSION['restore_single_jobid']; + $this->loadBackupsForClient(); + } elseif ($param->CurrentStepIndex === 3) { + $this->setFileVersions(); + $this->loadSelectedFiles(); + $this->loadFileVersions(); + $this->goToPath(); + } elseif ($param->CurrentStepIndex === 5) { + $this->file_relocation_opt = $_SESSION['file_relocation']; } - $clientname = $this->BackupClientName->SelectedValue; - $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output; - $fileVersions = $this->getModule('misc')->parseFileVersions($filename, $versions); - $this->setFileVersions($fileVersions); - $this->VersionsDataGrid->dataSource = $fileVersions; - $this->VersionsDataGrid->dataBind(); - $this->prepareFilesToRestore(); - } - - public function refreshSelectedFiles($sender, $param) { - $this->prepareFilesToRestore(); - $this->SelectedVersionsDropper->render($param->NewWriter); - } - - public function NextStep($sender, $param) { - } - - public function PreviousStep($sender, $param) { } + /** + * Cancel wizard. + * + * @return none + */ public function wizardStop($sender, $param) { + $this->resetWizard(); $this->goToDefaultPage(); } - public function setJobs($sender, $param) { - $jobs_list = $jobs_group_list = array(); - $clientid = null; - for ($i = 0; $i < count($this->clients); $i++) { - if ($this->clients[$i]->name === $this->BackupClientName->SelectedValue) { - $clientid = $this->clients[$i]->clientid; - break; - } - } - if(is_array($this->jobs)) { - foreach($this->jobs as $job) { - if(array_key_exists($job->level, $this->job_levels_to_restore) && $job->type == 'B' && $job->jobstatus == 'T' && $job->clientid == $clientid) { - $jobs_list[$job->jobid] = sprintf('[%s] %s, %s, %s', $job->jobid, $job->name, $this->job_levels_to_restore[$job->level], $job->endtime); - $jobs_group_list[$job->name] = $job->name; - } - } - } - - $fileset_list = array(); - for ($i = 0; $i < count($this->filesets); $i++) { - $fileset_list[$this->filesets[$i]->filesetid] = $this->filesets[$i]->fileset . ' (' . $this->filesets[$i]->createtime . ')'; - } - asort($fileset_list); - - $this->BackupToRestore->dataSource = $jobs_list; - $this->BackupToRestore->dataBind(); - $this->GroupBackupToRestore->dataSource = $jobs_group_list; - $this->GroupBackupToRestore->dataBind(); - $this->GroupBackupFileSet->dataSource = $fileset_list; - $this->GroupBackupFileSet->dataBind(); - $this->setRestoreClients($sender, $param); - } - - public function setBackupClients($sender, $param) { - if(!$this->IsPostBack) { - $client_list = array(); - foreach($this->clients as $client) { - $client_list[$client->name] = $client->name; - } - $this->BackupClientName->dataSource = $client_list; - $this->BackupClientName->dataBind(); + /** + * Load backup clients list (step 1). + * + * @param TActiveDropDownList $sender sender object + * @param TCommandParameter $param parameters object + * @return none + */ + public function loadBackupClients() { + $client_list = array(); + $clients = $this->getModule('api')->get(array('clients'))->output; + for ($i = 0; $i < count($clients); $i++) { + $client_list[$clients[$i]->name] = $clients[$i]->name; } - } - - public function setRestoreClients($sender, $param) { - if(!$this->IsPostBack || $sender->ID == $this->BackupClientName->ID) { - $client_list = array(); - foreach($this->clients as $client) { - $client_list[$client->name] = $client->name; - } - $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue; - $this->RestoreClient->dataSource = $client_list; - $this->RestoreClient->dataBind(); + asort($client_list); + $this->BackupClientName->dataSource = $client_list; + $this->BackupClientName->dataBind(); + } + + /** + * Load restore client list. + * + * @return none + */ + public function loadRestoreClients() { + $client_list = array(); + $clients = $this->getModule('api')->get(array('clients'))->output; + for ($i = 0; $i < count($clients); $i++) { + $client_list[$clients[$i]->name] = $clients[$i]->name; } - } - - public function setBackupClient($sender, $param) { - $this->ClientToRestore->SelectedValue = $param->SelectedValue; - } - - public function setBackupSelection($sender, $param) { + $this->RestoreClient->SelectedValue = $this->BackupClientName->SelectedValue; + $this->RestoreClient->dataSource = $client_list; + $this->RestoreClient->dataBind(); + } + + /** + * Load backups for selected client (Step 2). + * + * @return none + */ + public function loadBackupsForClient() { + $clientid = $this->getBackupClientId(); + $jobs_for_client = $this->getModule('api')->get(array('clients', 'jobs', $clientid))->output; + $jobs = $this->getModule('misc')->objectToArray($jobs_for_client); + $this->BackupsToRestore->DataSource = array_filter($jobs, array($this, 'isBackupJobToRestore')); + $this->BackupsToRestore->dataBind(); + } + + /** + * Check if job can be used in restore. + * + * @param array $job job properties + * @return true if job should be listed to restore, otherwise false + */ + private function isBackupJobToRestore($job) { + return ($job['type'] === 'B' && in_array($job['level'], $this->joblevel) && in_array($job['jobstatus'], $this->jobstatus)); + } + + public function loadBackupSelection($sender, $param) { $this->GroupBackupToRestoreField->Display = ($sender->ID == $this->GroupBackupSelection->ID) ? 'Dynamic' : 'None'; $this->BackupToRestoreField->Display = ($sender->ID == $this->OnlySelectedBackupSelection->ID) ? 'Dynamic' : 'None'; - $this->setBrowserFiles(array()); - $this->setFileVersions(array()); - $this->setFilesToRestore(array()); + $this->setBrowserFiles(); + $this->setFileVersions(); + $this->setFilesToRestore(); $this->markFileToRestore(null, null); $_SESSION['restore_path'] = array(); } - public function resetFileBrowser($sender, $param) { - $this->markFileToRestore(null, null); - $this->setBrowserPath($this->browser_root_dir['name']); - } - - private function prepareBrowserFiles($files) { - $this->setBrowserFiles($files); - $this->DataGridFiles->dataSource = $files; - @$this->DataGridFiles->dataBind(); - } - - private function prepareVersionsToRestore() { - $this->VersionsDataGrid->dataSource = $_SESSION['files_versions']; - $this->VersionsDataGrid->dataBind(); - } - private function prepareFilesToRestore() { - $this->SelectedVersionsDataGrid->dataSource = $_SESSION['restore']; - $this->SelectedVersionsDataGrid->dataBind(); - } - - private function setBrowserPath($path) { - if(!empty($path)) { - if($path == $this->browser_up_dir['name']) { - array_pop($_SESSION['restore_path']); - } elseif($path == $this->browser_root_dir['name']) { - $_SESSION['restore_path'] = array(); - } else { - array_push($_SESSION['restore_path'], $path); + /** + * Get selected backup client identifier. + * + * @return mixed client identifier or null if no clientid found + */ + public function getBackupClientId() { + $clientid = null; + $clients = $this->getModule('api')->get(array('clients'))->output; + for ($i = 0; $i < count($clients); $i++) { + if ($clients[$i]->name === $this->BackupClientName->SelectedValue) { + $clientid = $clients[$i]->clientid; + break; + } + } + return $clientid; + } + + /** + * Load backup jobs to restore for group most recent backups feature. + * + * @return none + */ + public function loadGroupBackupToRestore() { + $jobs = $this->getModule('api')->get(array('jobs'))->output; + $jobs = $this->getModule('misc')->objectToArray($jobs); + $clientid = $this->getBackupClientId(); + $job_group_list = array(); + for ($i = 0; $i < count($jobs); $i++) { + $job = $this->getModule('misc')->objectToArray($jobs[$i]); + if ($this->isBackupJobToRestore($jobs[$i]) && $jobs[$i]['clientid'] === $clientid) { + $job_group_list[$jobs[$i]['name']] = $jobs[$i]['name']; } } - $this->setBrowserLocalizator(); - $this->prepareBrowserContent(); - } - private function getBrowserPath($stringFormat = false) { - return ($stringFormat === true) ? implode($_SESSION['restore_path']) : $_SESSION['restore_path']; + $this->GroupBackupToRestore->dataSource = $job_group_list; + $this->GroupBackupToRestore->dataBind(); } - private function setBrowserLocalizator() { - $localization = $this->getBrowserPath(true); - $this->PathField->HeaderText = mb_strlen($localization) > 56 ? '...' . mb_substr($localization, -56) : $localization; + /** + * Load filesets to restore for group most recent backups feature. + * + * @return none + */ + public function loadGroupFileSetToRestore() { + $filesets = $this->getModule('api')->get(array('filesets', 'info'))->output; + $fileset_list = array(); + for ($i = 0; $i < count($filesets); $i++) { + $fileset_list[$filesets[$i]->filesetid] = $filesets[$i]->fileset . ' (' . $filesets[$i]->createtime . ')'; + } + asort($fileset_list); + + $this->GroupBackupFileSet->dataSource = $fileset_list; + $this->GroupBackupFileSet->dataBind(); } + /** + * Prepare left file browser content. + * + * @return none + */ private function prepareBrowserContent() { $jobids = $this->getElementaryBackup(); $elements = array(); - if (!is_null($jobids)) { - // generating Bvfs may takes a moment - $this->generateBvfsCacheByJobids($jobids); - $bvfs_dirs_list = $this->getModule('api')->set(array('bvfs', 'lsdirs'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true))); - $bvfs_dirs = is_object($bvfs_dirs_list) ? $bvfs_dirs_list->output : array(); - $dirs = $this->getModule('misc')->parseBvfsList($bvfs_dirs); - $bvfs_files_list = $this->getModule('api')->set(array('bvfs', 'lsfiles'), array('jobids' => $jobids, 'path' => $this->getBrowserPath(true))); - $bvfs_files = is_object($bvfs_files_list) ? $bvfs_files_list->output : array(); - $files = $this->getModule('misc')->parseBvfsList($bvfs_files); + if (!empty($jobids)) { + // generating Bvfs may take a moment + $this->generateBvfsCache($jobids); + + // get directories list + $bvfs_dirs = $this->getModule('api')->set( + array('bvfs', 'lsdirs'), + array('jobids' => $jobids, 'path' => implode($_SESSION['restore_path'])) + ); + $dirs = $this->getModule('misc')->parseBvfsList($bvfs_dirs->output); + + // get files list + $bvfs_files = $this->getModule('api')->set( + array('bvfs', 'lsfiles'), + array('jobids' => $jobids, 'path' => implode($_SESSION['restore_path'])) + ); + $files = $this->getModule('misc')->parseBvfsList($bvfs_files->output); + $elements = array_merge($dirs, $files); - if(count($this->getBrowserPath()) > 0) { + if(count($_SESSION['restore_path']) > 0) { array_unshift($elements, $this->browser_root_dir); } } - $this->prepareBrowserFiles($elements); + $this->loadBrowserFiles($elements); } + /* + * Get single elementary backup job identifiers. + * + * @return string comma separated job identifiers + */ private function getElementaryBackup() { - $jobids = null; - if($this->OnlySelectedBackupSelection->Checked === true) { - $jobs = $this->getModule('api')->get(array('bvfs', 'getjobids', $this->BackupToRestore->SelectedValue)); + $jobids = ''; + if($this->OnlySelectedBackupSelection->Checked && isset($_SESSION['restore_single_jobid'])) { + $jobs = $this->getModule('api')->get( + array('bvfs', 'getjobids', $_SESSION['restore_single_jobid']) + ); $ids = is_object($jobs) ? $jobs->output : array(); - foreach($ids as $jobid) { + foreach ($ids as $jobid) { if(preg_match('/^([\d\,]+)$/', $jobid, $match) == 1) { $jobids = $match[1]; break; @@ -294,7 +333,7 @@ class RestoreWizard extends BaculumWebPage $this->GroupBackupFileSet->SelectedValue ); $jobs_recent = $this->getModule('api')->get($params); - if(count($jobs_recent->output) > 0) { + if (count($jobs_recent->output) > 0) { $ids = $jobs_recent->output; $jobids = implode(',', $ids); } @@ -302,14 +341,210 @@ class RestoreWizard extends BaculumWebPage return $jobids; } - private function generateBvfsCacheByJobids($jobids) { - $this->getModule('api')->set(array('bvfs', 'update'), array('jobids' => $jobids)); + /** + * Load path callback method. + * Used for manually typed paths in path field. + * + * @param TActiveLinkButton $sender sender object + * @param TEventParameter $param events parameter + * @return none + */ + public function loadPath($sender, $param) { + $path = explode('/', $this->PathField->Text); + $path_len = count($path); + for ($i = 0; $i < count($path); $i++) { + if ($i == ($path_len - 1) && empty($path[$i])) { + // last path dir is slash so not add slash to last element + break; + } + $path[$i] .= '/'; + } + $this->goToPath($path, true); + } + + /** + * Go to specific path in the file browser. + * There is possible to pass both single directory 'somedir' + * or whole path '/etc/somedir'. + * + * @param string $path path to go + * @param bool $full_path determines if $path param is full path or relative path (singel directory) + * @return none + */ + private function goToPath($path = '', $full_path = false) { + if(!empty($path) && !$full_path) { + if($path == $this->browser_up_dir['name']) { + array_pop($_SESSION['restore_path']); + } elseif($path == $this->browser_root_dir['name']) { + $_SESSION['restore_path'] = array(); + } else { + array_push($_SESSION['restore_path'], $path); + } + } + if ($full_path && is_array($path)) { + $_SESSION['restore_path'] = $path; + } + $this->setBrowserPath(); + $this->prepareBrowserContent(); + } + + /** + * Add/mark file to restore. + * Used as callback to drag&drop browser elements. + * + * @param object $sender sender object + * @param object $param param object + * @return none + */ + public function addFileToRestore($sender, $param) { + $fileid = null; + $source_element_id = null; + $file_prop = array(); + if (isset($param->CallbackParameter)) { + $id_parts = explode('_', $sender->ClientID, 6); + $source_element_id = $id_parts[3]; + $fileid = $param->CallbackParameter; + } else { + $control = $param->getDroppedControl(); + $item = $control->getNamingContainer(); + $id_parts = explode('_', $param->getDragElementID(), 6); + $source_element_id = $id_parts[3]; + } + if($source_element_id == $this->VersionsDataGrid->ID) { + if (is_null($fileid)) { + $fileid = $this->VersionsDataGrid->getDataKeys()->itemAt($item->getItemIndex()); + } + $file_prop = $this->getFileVersions($fileid); + } else { + if (is_null($fileid)) { + $fileid = $this->DataGridFiles->getDataKeys()->itemAt($item->getItemIndex()); + } + $file_prop = $this->getBrowserFile($fileid); + } + if($file_prop['name'] != $this->browser_root_dir['name'] && $file_prop['name'] != $this->browser_up_dir['name']) { + $this->markFileToRestore($fileid, $file_prop); + $this->loadSelectedFiles(); + } + } + + /** + * Remove file from files marked to restre. + * + * @param TActiveImageButton $sender remove button object + * @param TEventParameter $param param object + * @return none + */ + public function removeSelectedFile($sender, $param) { + $fileid = $param->CallbackParameter; + $this->unmarkFileToRestore($fileid); + $this->loadSelectedFiles(); + } + + /** + * Get file backed up versions. + * Called as callback on file element click. + * + * @param TCallback $sender sender object + * @param object $param param object + * @return none + */ + public function getVersions($sender, $param) { + list($filename, $pathid, $filenameid, $jobid) = explode('|', $param->CallbackParameter, 4); + if($filenameid == 0) { + $this->goToPath($filename); + return; + } + $clientname = $this->BackupClientName->SelectedValue; + $versions = $this->getModule('api')->get(array('bvfs', 'versions', $clientname, $jobid, $pathid, $filenameid))->output; + $file_versions = $this->getModule('misc')->parseFileVersions($filename, $versions); + $this->setFileVersions($file_versions); + $this->VersionsDataGrid->dataSource = $file_versions; + $this->VersionsDataGrid->dataBind(); + $this->loadSelectedFiles(); + } + + /** + * Refresh/re-render selected files list. + * + * @param TDropContainer $sender sender object + * @param TEventParameter $param param object + * @return none + */ + public function refreshSelectedFiles($sender, $param) { + $this->loadSelectedFiles(); + $this->SelectedVersionsDropper->render($param->NewWriter); + } + + /* + * Load file browser files to list. + * + * @param array $files files to list. + * @return none + */ + private function loadBrowserFiles($files) { + $this->setBrowserFiles($files); + $this->DataGridFiles->dataSource = $files; + $this->DataGridFiles->dataBind(); + } + + /** + * Load file versions area. + * + * @return none; + */ + private function loadFileVersions() { + $this->VersionsDataGrid->dataSource = $_SESSION['files_versions']; + $this->VersionsDataGrid->dataBind(); + } + + /** + * Load selected files in drop area. + * + * @return none + */ + private function loadSelectedFiles() { + $this->SelectedVersionsDataGrid->dataSource = $_SESSION['restore']; + $this->SelectedVersionsDataGrid->dataBind(); } - private function setFileVersions($versions) { + /** + * Set file browser path field. + * + * @return none + */ + private function setBrowserPath() { + $this->PathField->Text = implode($_SESSION['restore_path']); + } + + /** + * Generate Bvfs cache by job identifiers. + * + * @param string $jobids comma separated job identifiers + * @return none + */ + private function generateBvfsCache($jobids) { + $this->getModule('api')->set( + array('bvfs', 'update'), + array('jobids' => $jobids) + ); + } + + /** + * Set versions for selected file. + * + * @param array $versions file versions data + * @return none + */ + private function setFileVersions($versions = array()) { $_SESSION['files_versions'] = $versions; } + /** + * Get file versions for specified fileid. + * + * @param integer $fileid file identifier + * @return none + */ private function getFileVersions($fileid) { $versions = array(); foreach($_SESSION['files_versions'] as $file) { @@ -321,10 +556,22 @@ class RestoreWizard extends BaculumWebPage return $versions; } - private function setBrowserFiles($files) { + /** + * Set browser files. + * + * @param array $files file list + * @return none + */ + private function setBrowserFiles($files = array()) { $_SESSION['files_browser'] = $files; } + /** + * Get browser file by fileid. + * + * @param integer $fileid file identifier + * @return none + */ private function getBrowserFile($fileid) { $element = array(); foreach($_SESSION['files_browser'] as $file) { @@ -336,6 +583,13 @@ class RestoreWizard extends BaculumWebPage return $element; } + /** + * Mark file to restore. + * + * @param integer $fileid file identifier + * @param array $file file properties to mark + * @return none + */ private function markFileToRestore($fileid, $file) { if($fileid === null) { $_SESSION['restore'] = array(); @@ -344,60 +598,119 @@ class RestoreWizard extends BaculumWebPage } } + /** + * Unmark file to restore. + * + * @param integer $fileid file identifier + * @return none + */ private function unmarkFileToRestore($fileid) { if(array_key_exists($fileid, $_SESSION['restore'])) { unset($_SESSION['restore'][$fileid]); } } + /** + * Get files to restore. + * + * @return array list with files to restore + */ public function getFilesToRestore() { return $_SESSION['restore']; } - public function setFilesToRestore($files) { + /** + * Set files to restore + * + * @param array $files files to restore + * @return none + */ + public function setFilesToRestore($files = array()) { $_SESSION['restore'] = $files; } - public function getRestoreElements($asObject = false) { + /** + * Get all restore elements (fileids and dirids). + * + * @param bool $as_object return result as object + * @return array list fileids and dirids + */ + public function getRestoreElements($as_object = false) { $fileids = array(); $dirids = array(); - foreach($this->getFilesToRestore() as $fileid => $properties) { - if($properties['type'] == 'dir') { + $findexes = array(); + foreach ($this->getFilesToRestore() as $fileid => $properties) { + if ($properties['type'] == 'dir') { $dirids[] = $properties['pathid']; - } elseif($properties['type'] == 'file') { + } elseif ($properties['type'] == 'file') { $fileids[] = $fileid; + if ($properties['lstat']['linkfi'] !== 0) { + $findexes[] = $properties['jobid'] . ',' . $properties['lstat']['linkfi']; + } } } - $ret = array('fileid' => $fileids, 'dirid' => $dirids); - if($asObject === true) { + $ret = array('fileid' => $fileids, 'dirid' => $dirids, 'findex' => $findexes); + if($as_object === true) { $ret = (object)$ret; } return $ret; } + /** + * Wizard finish method. + * + * @return none + */ public function wizardCompleted() { $jobids = $this->getElementaryBackup(); $path = self::BVFS_PATH_PREFIX . getmypid(); $restore_elements = $this->getRestoreElements(); $cmd_props = array('jobids' => $jobids, 'path' => $path); + $is_element = false; if(count($restore_elements['fileid']) > 0) { $cmd_props['fileid'] = implode(',', $restore_elements['fileid']); + $is_element = true; } if(count($restore_elements['dirid']) > 0) { $cmd_props['dirid'] = implode(',', $restore_elements['dirid']); + $is_element = true; } + if (count($restore_elements['findex']) > 0) { + $cmd_props['findex'] = implode(',', $restore_elements['findex']); + $is_element = true; + } + + $jobid = null; + if ($is_element) { + $this->getModule('api')->create(array('bvfs', 'restore'), $cmd_props); + $restore_props = array(); + $restore_props['rpath'] = $path; + $restore_props['client'] = $this->RestoreClient->SelectedValue; + $restore_props['priority'] = intval($this->RestoreJobPriority->Text); + if ($_SESSION['file_relocation'] == 2) { + if (!empty($this->RestoreStripPrefix->Text)) { + $restore_props['strip_prefix'] = $this->RestoreStripPrefix->Text; + } + if (!empty($this->RestoreAddPrefix->Text)) { + $restore_props['add_prefix'] = $this->RestoreAddPrefix->Text; + } + if (!empty($this->RestoreAddSuffix->Text)) { + $restore_props['add_suffix'] = $this->RestoreAddSuffix->Text; + } + } elseif ($_SESSION['file_relocation'] == 3) { + if (!empty($this->RestoreRegexWhere->Text)) { + $restore_props['regex_where'] = $this->RestoreRegexWhere->Text; + } + } + if (!array_key_exists('add_prefix', $restore_props)) { + $restore_props['where'] = $this->RestorePath->Text; + } + $restore_props['replace'] = $this->ReplaceFiles->SelectedValue; + $restore_props['restorejob'] = $this->RestoreJob->SelectedValue; - $this->getModule('api')->create(array('bvfs', 'restore'), $cmd_props); - $restore_props = array(); - $restore_props['rpath'] = $path; - $restore_props['client'] = $this->RestoreClient->SelectedValue; - $restore_props['priority'] = intval($this->RestoreJobPriority->Text); - $restore_props['where'] = $this->RestorePath->Text; - $restore_props['replace'] = $this->ReplaceFiles->SelectedValue; - $restore_props['restorejob'] = $this->RestoreJob->SelectedValue; - - $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restore_props); - $jobid = $this->getModule('misc')->findJobIdStartedJob($ret->output); + $ret = $this->getModule('api')->create(array('jobs', 'restore'), $restore_props); + $jobid = $this->getModule('misc')->findJobIdStartedJob($ret->output); + } $url_params = array('open' => 'Job'); if (is_numeric($jobid)) { $url_params['id'] = $jobid; @@ -405,8 +718,13 @@ class RestoreWizard extends BaculumWebPage $this->goToDefaultPage($url_params); } - private function setRestoreJobs() { - $restore_job_tasks = $this->Application->getModule('api')->get(array('jobs', 'tasks', 'type', 'R'))->output; + /** + * Load restore jobs on the list. + * + * @return none + */ + private function loadRestoreJobs() { + $restore_job_tasks = $this->getModule('api')->get(array('jobs', 'tasks', 'type', 'R'))->output; $jobs = array(); foreach ($restore_job_tasks as $director => $restore_jobs) { $jobs = array_merge($jobs, $restore_jobs); @@ -414,5 +732,40 @@ class RestoreWizard extends BaculumWebPage $this->RestoreJob->DataSource = array_combine($jobs, $jobs); $this->RestoreJob->dataBind(); } + + private function loadRequiredVolumes() { + $volumes = array(); + foreach ($this->getFilesToRestore() as $fileid => $props) { + // it can be expensive for many restore paths + $result = $this->getModule('api')->get(array('volumes', 'required', $props['jobid'], $fileid)); + if ($result->error === 0) { + for ($i = 0; $i < count($result->output); $i++) { + $volumes[$result->output[$i]->volume] = array( + 'volume' => $result->output[$i]->volume, + 'inchanger' => $result->output[$i]->inchanger + ); + } + } + } + $this->RestoreVolumes->DataSource = array_values($volumes); + $this->RestoreVolumes->dataBind(); + } + + /** + * Reset wizard. + * All fields are back to initial form. + * + * @return none + */ + private function resetWizard() { + $this->setBrowserFiles(); + $this->setFileVersions(); + $this->setFilesToRestore(); + $this->markFileToRestore(null, null); + $this->loadRestoreJobs(); + $_SESSION['restore_path'] = array(); + $_SESSION['restore_single_jobid'] = null; + unset($_SESSION['file_relocation']); + } } ?> diff --git a/gui/baculum/themes/Baculum-v1/restore-wizard.css b/gui/baculum/themes/Baculum-v1/restore-wizard.css new file mode 100644 index 0000000000..b10ac8b3dc --- /dev/null +++ b/gui/baculum/themes/Baculum-v1/restore-wizard.css @@ -0,0 +1,70 @@ +.wizard { +} + +.steps { + background-image: none; + min-height: 520px; +} + +#restore-browser { + width: 100%; + height: 100%; +} + +#restore-browser-files { + width: 315px; + height: 434px; +} + +#restore-browser-files, #restore-browser-versions, #restore-browser-selected { + overflow: auto; + width: 474px; + background-color: white; + border-radius: 4px; + padding: 4px; + -moz-user-select: -moz-none; + -webkit-user-select: none; + -ms-user-select: none; +} + +#restore-browser-files { + height: 506px; +} + +#restore-browser-versions { + height: 206px; +} + +#restore-browser-selected { + height: 282px; +} + +#restore-browser-files-loading { + position: absolute; + z-index: 10; + width: 482px; + height: 514px; + border-radius: 4px; + background: rgba(182,182,182,0.7) url('progress.gif') no-repeat center center; +} + +.restore-browser-element-size { + float: right; + width: 100px; +} + +.restore-browser-element-size { + line-height: 24px; +} + +.file-browser-watermark { + padding: 77px 10px; + text-align: center; + font-size: 21px; + color: rgb(185, 184, 184); +} + +#backup-to-restore-field > div { + height: 467px; + overflow-y: auto; +} -- 2.39.2