From 5be510b6c00ea9e9f053374b3de0fcaa12728a51 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Tue, 12 Mar 2024 16:15:12 +0200
Subject: [PATCH] kb(grid): Revamp KB for column header alignment in hierarchy
(#1970)
Co-authored-by: Dimo Dimov <961014+dimodi@users.noreply.github.com>
---
.../grid-align-columns-hierarchy.md | 254 ++++++++++--------
.../grid-align-hierarchical-columns.png | Bin 19179 -> 0 bytes
2 files changed, 141 insertions(+), 113 deletions(-)
delete mode 100644 knowledge-base/images/grid-align-hierarchical-columns.png
diff --git a/knowledge-base/grid-align-columns-hierarchy.md b/knowledge-base/grid-align-columns-hierarchy.md
index 8da95757e..0e726ea63 100644
--- a/knowledge-base/grid-align-columns-hierarchy.md
+++ b/knowledge-base/grid-align-columns-hierarchy.md
@@ -1,172 +1,200 @@
---
-title: Align Columns in Hierarchical Grid
-description: How to align columns in nested detail template of a hierarchical grid.
+title: Align Column Headers in Grid Hierarchy
+description: How to align column headers in the nested detail template of a hierarchy Grid.
type: how-to
-page_title: Align Columns in Hierarchical Grid
+page_title: How to Align Columns Headers at Different Grid Hierarchy Levels
slug: grid-kb-align-columns-hierarchy
position:
tags:
-ticketid: 1468988
+ticketid: 1468988, 1522877, 1644195
res_type: kb
---
## Environment
+
-
-
-
Product
-
Grid for Blazor
-
-
+
+
+
Product
+
Grid for Blazor
+
+
-
## Description
-I want to showcase hierarchical data in the grid and to make the DetailTemplate columns match the main column headers.
-## Solution
-While generally a task for a treelist type of component, you can show self-referencing data in a grid through its detail templates and if the field names match, you can even use the only the headers from the main grid.
+This KB article answers the following questions:
-To align the columns of nested grid detail templates, you need to:
+* How to configure a hierarchy Grid and make the `DetailTemplate` Grid column headers align with the master Grid column headers?
+* How to define the detail Grid columns, so that they match the master Grid columns?
+* How to align the column borders of nested child Grids with the column borders of the parent Grid?
+
+## Solution
-* set a width to the grid that matches the width of its columns
-* set width to the columns of the nested grids that match the column widths of the main grid
- * the first column of each child grid must have width smaller than the first column of the main grid with the size of the hierarchy expand column times the levels of hierarchy that you have
-* add styles that remove the scrollbars from the grid to clean out the UI and reduce distortions that they can cause
-* optionally, hide the headers of the nested grids
+The best reason to align Grid column headers across hierarchy levels is when the Grid displays a self-referencing hierarchy. There are two ways to achieve the desired appearance and aligned columns:
->caption The result from the code snippet below
+* Use a [TreeList component]({%slug treelist-overview%}). It may be a better option than the Grid, because the TreeList supports a random number of hierarchy levels and there is no need to define and configure each level separately. The TreeList uses the same column and column header for each data item property at any level.
+* Use a Grid with [additional CSS code]({%slug themes-override%}) to align the columns at all hierarchy levels.
-![Align Hierarchical Grid Columns](images/grid-align-hierarchical-columns.png)
+The steps below describe how to align columns when using a Grid hierarchy.
+1. Set a [custom CSS `Class`]({%slug grid-overview%}#grid-parameters) to the master (parent) Grid, so that the custom styles do not affect other Grid instances.
+1. Use the custom CSS class to:
+ 1. Remove the padding of the `DetailTemplate` container (`td.k-detail-cell`).
+ 1. Disable the vertical scrollbar of the Grid data area (`div.k-grid-content`).
+ 1. Remove the empty space in the Grid header area, which is above the vertical scrollbar (`div.k-grid-header`).
+ 1. Remove the right border of the detail Grids (`.k-grid`).
+1. Set the same column `Width` to the columns from all hierarchy levels, that should align with one another.
+1. Set widths to all columns, except the first one of each Grid. This will allow the first column to expand and collapse automatically, depending on the hierarchy level and the available space.
+1. If the number of hierarchy levels is greater than two, use [named `context` variables for the Grid `DetailTemplate`]({%slug nest-renderfragment%}).
+1. (optional) Remove the header area of the detail Grids. This makes sense only if the detail Grids have no enabled features that rely on column headers, for example, sorting or filtering.
>caption Align the columns in hierarchical grids
````CSHTML
-@* Three levels of grids - note how the first columns of the nested grids have the width of the detail expand cell subtracted twice
- for the Default Theme, it is 2*32px but that can vary between themes and based on the font-size of the page.
- Also, the main grid has a width that matches closely the sum of the column widths and the horizontal scrollbars
- are hidden in order to produce cleaner UX *@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
- @{
- var currGridData = GetLevelData(firstLevelItem.Id);
-
-
-
-
-
-
-
- @{
- var currGridData = GetLevelData(secondLevelItem.Id);
-
-
-
-
-
-
-
- }
-
-
+@if (HideDetailHeaders)
+{
+
+}
@code {
- List MainLevelsData { get; set; }
- List AllData { get; set; }
+ private List GridData { get; set; } = new();
+
+ private bool HideDetailHeaders { get; set; }
- public class SelfReferencingHierarchyModel
+ private void OnGridStateInit(GridStateEventArgs args)
{
- public int Id { get; set; }
- public int? ParentId { get; set; }
- public string Field1 { get; set; }
- public string Field2 { get; set; }
+ // Expand the master Grid rows automatically
+ args.GridState.ExpandedItems = GridData.Where(x => x.ParentId == null).ToList();
}
protected override void OnInitialized()
{
- AllData = new List();
+ GridData = LoadFlat();
+
+ base.OnInitialized();
+ }
+
+ #region Grid Data Generation
+
+ private const int TreeLevels = 3;
+ private int RootItems { get; set; } = 2;
+ private int ItemsPerLevel { get; set; } = 2;
+ private int IdCounter { get; set; } = 1;
+
+ private List LoadFlat()
+ {
+ List items = new List();
- //generate top level items
- for (int i = 0; i < 35; i++)
+ PopulateChildren(items, null, 1);
+
+ return items;
+ }
+
+ private void PopulateChildren(List items, int? parentId, int level)
+ {
+ var itemCount = level == 1 ? RootItems : ItemsPerLevel;
+ for (int i = 1; i <= itemCount; i++)
{
- AllData.Add(new SelfReferencingHierarchyModel
+ var itemId = IdCounter++;
+ items.Add(new GridItem()
{
- Id = i,
- Field1 = $"main level {i}",
- Field2 = $"main level field 2 - {i}"
+ Id = itemId,
+ ParentId = parentId,
+ Text = $"Level {level} Item {i}",
+ Quantity = Random.Shared.Next(0, 1000),
+ Date = new DateTime(Random.Shared.Next(2000, 2030), Random.Shared.Next(1, 13), Random.Shared.Next(1, 29))
});
- for (int j = 0; j < 12; j++)
+ if (level < TreeLevels)
{
- //generate first level items - note the Id and ParentId logic
- AllData.Add(new SelfReferencingHierarchyModel
- {
- Id = 100 + j,
- ParentId = i,
- Field1 = $"first level {j}",
- Field2 = $"first level field 2 - {j}"
- });
-
- for (int k = 0; k < 12; k++)
- {
- //generate second level items - note the Id and ParentId logic
- AllData.Add(new SelfReferencingHierarchyModel
- {
- Id = 6000 * j + k, // does not really produce unique IDs here, but for this sample it does not matter
- ParentId = 100 + j,
- Field1 = $"second level {j}",
- Field2 = $"second level field 2 - {j}"
- });
- }
+ PopulateChildren(items, itemId, level + 1);
}
}
-
- MainLevelsData = AllData.Where(itm => itm.ParentId == null).ToList();
}
- List GetLevelData(int parentId)
+ #endregion Grid Data Generation
+
+ public class GridItem
{
- return AllData.Where(itm => itm.ParentId == parentId).ToList();
+ public int Id { get; set; }
+ public int? ParentId { get; set; }
+ public string Text { get; set; } = string.Empty;
+ public int Quantity { get; set; }
+ public DateTime Date { get; set; }
}
}
````
+## See Also
-
+* [Grid Hierarchy]({%slug components/grid/features/hierarchy%})
+* [Using custom CSS with Telerik Blazor components]({%slug themes-override%})
+* [TreeList component documentation]({%slug treelist-overview%})
diff --git a/knowledge-base/images/grid-align-hierarchical-columns.png b/knowledge-base/images/grid-align-hierarchical-columns.png
deleted file mode 100644
index efd7486ba55e3ec300a2937680612b7b9d3008d5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 19179
zcmb_^1wb6lvMvb;7TjGoxVwemED{I=cXxLuxXa=mWO0{8Lm&{`Ed+ND?!n%Y{O8_x
z?Y(o)Ik3CE)74!))ALpJS6u_)@8zXXkO+}rU|>+Bf#OOqFt9-AI|l(4TEog*2nPf6
z4E$bBS>o~W@#5m*^73+je}8>_-NeM?dUodVarpAGH^syxW#loz#3Z5jVyoVFxzgLj
z2V&w~y#*Dgnn1Q6dy`B|Qin~FdY3LPh94h&>$iF@FRPa>9=9RTu8$)rm&?`Ol}ivG
zsMdsPZjYOpG;EfyiF1w6NjN~6QRv6haWuDFE7^~D%UQ1(@RQ99*xp3
zm+SABFCXe>9zE+5OcEcBytW>Pe^q+Tom?Ir9o5y<6%-VhSbEgwuhX=y2pf;dG%l9Ek&
zFUP8TtA`)Ah98F^Bar3FYM;VFlhl;D6cgz0@@21gRrT1|*!660UVr0OJ;c|ies~+w
zyHq_|>yzZ|n%B3}TUCAgDeu83{V^i?-qY*$le4$CNi}p5s+JRadmj?h?|UyFdWShI
zIzK^g8-}xly0e14vxSX?r-?C)vW2Y&^e!J#eqMxu0d7i*izvI#{Y|({1h$Qqc
zTKQ_+7f+Em_VGafc;`Vf6nC!1>lWqyQ06&T{g0|q3hY54Gsm@EokK+chzP3xub+<^
zPOo6{ckue}z77lpHV=)%YTVN>h(E6t1q`quXh@S|ZoU^)#S9bYON>i;L8*xP+W56U
zFi{Ng?-zXoNbvvE!cyNZkdD-IQdeklu9a78yRspRd
zfi2|`pXI7i642?&ex7hO@BA9TAY9$9$vED*t6`}mZf!k80V!()yU=*?rghtMfoe-#
z-etrBE0KJeADa#v3ajP83LnVhnHfe8NkKi4Q_k}Q)(7S5?nu$c13yU@F;*;=dn!mM
zE$TG2)zz@*c&EV36CO!SUq&a6R1WkgCVrGRSqp-)N&F4zn61wXz-Tx`4&p`ZFGAW7SVh`J;s|~
zj;Bo7j`1kS8N~C5yZ+}X{PLs7hziCZA1>gxP7U^Z3lG$mjZ
zW7ZNQeml$>g3#|I-k=$@!AGgZBzj5=s=%f2i0M-u)T3AwzQUbw2{S^4O!o!_RY05Q
z&RSx|Z<||lA@)0QHl#yq2({ipJ4IJeLp$}TCd3I!8I?%`v)2tqBUFika?SOa^U%RE
zIRQvM_Q-QrBJBobwJB_uEmh0IU(q3ZK_62$N$28;-mPY5CVboHMo=q5rwZq75NXm3
z#+Uw9gVH%o{|!hPV}o9)>L5Qex0{vsH$<%gsGxR>{{{-Fk_b@v~h!y73tI5xwLrqIoW)}?7f=X
zl(+dl!2>}C++%)B^Xe@T;;w%P3>&Ug`lp0*RYJu2RC^SM_aW$O!m-i>mhZb*ota&?
zkOVM4yd1=y07WDN=`@aoL$dJY+
z?4V$-qgY1g$7^-mj54NMr;bwE2@Yj;AOC4>2wpdkBv$#PxQH#}z*Le(4v5Jv}}W9!T>hL&wA>uP~D4d&mjN!CjN1WbJ$m$HbIW
zwZ*YiYia}vtOISEv$n{qgI=yWyfp@H_oq>#+1||I?8KJ*KzHnSlO}#2lrB)2!yH*H
z(OrsW#Nc=9v>Aayh`U3s7TxwPID$reD^vJx$!JmDC#h{oJDN}
zNW6B_%Hp@Z?0IaiD{ptuLNXY|rKYpKmpVB&LIPpgjbMEk0~LrA+{6fDflnuD@Q+BgYWnvc6yCIn1Or14rzDJHr+o`SAdQnf!W(TJ+d
z7&uS^Qeg*d{^+BBV+_<=8NHA5_ClrbFujv<~ouF-~{d!igG3Mn-
z`{v?|AsSL%{2@0Gea;*gsn9r(Gp)w><*8#g`8aW~M8*HNoHmQgj`1)@G0*u$v{MEz
z>k@!2LlfZNR#Xow-1UN#hjHX{gX&!A<23h59IjJl2(Cx~s(cA?w!jz)vkXmM=7HZ3
z8?;TW>RbyNrsE6UU@ph^3FL3czQoA$DNYiLPQ!0W(qQt*60?_m8_FMeh*{Jw9!dq%k+Va;o^|_75ew6uOaOl
z%&oTQpHA$zR3H;xrIZtiZV9R}Ri!U~mqpCEi0ck`~+w+1vcPs_Z
zY2{9`$hD`zm01WbQ%}jMNyOpzkQ)B+Z#`UVLz}1G-3%ua_KZRsc(tzk2Gq4ImPrh7;ajwf|5jcM3Xx>OAiQ8j-{^R-
zYIvR^=p8nch+ZoJ9AT?f!H9Q?vQ`P&Ag0p7q2TN7Q~f)tzhF+>gzxK@;UOSuA@=iS
z&(cFbxf^6e9b=*^;^Q)njLHCj?H@n>R^2iS2}lYvAeTY)7Zp2sPgx(DJV$xCrSjNO
zN24=VhUeF{++eq6U1x&GBqP1xk>lK&R&ch}=FHzp8RLRp8SvzJzl$^>iADj|)Ztg@
z5uny*L=sd+{^Wt58iY*%HI`K9gXW3E2J3Bc#`JW`Xzl4^boWyhGL2pJ7;;is+|yc4
z9PehXsVaG$J(9c9{gpd`L5pvqUf|Y$eZ(!tNN^x5*?4Y?2k#iwI(1^-oog07g&ZQ!
zhH2o2M}_kXW$0X8`G>{DHEBMm&~W#Vif4AxfZda?t=JxoOM6py{iVscpy~%z&+?M3
zOrwQ@m|zCf?yuOgW<~1e0r|O@l9WFW4Z)*G#uySS+_y>+QIegi;kBmC1(DsK8V5yj
zhII~0Po8NQNmewDB(40oDqqa{6A+)yhU~*H2eoRYMYT4dI0165<;G`o0ngbBUEPj{?gIU45-mLO{hSNA!BcTdA@Ju^EN<77S{{
z1BAy>^~V^<=2!-93REZ66c|+FDz^tRgJq<)$V*sMHroTQf{8zxSj`w2Q@DXYf_!_H
zE%3uX#kRrk)D&VXD@4nUtEe+d&W+%p5tWPLlNkPBjcxA+Qc#`X)mq>q)@hjMOfl)%
z`wM-V$SGrCTTK#}FsSykW-DnFMvn7y{18>YQ5ydZ6-JKh~~c6T8BNhv%A8tL7!YMcD*tVR)|ef0Fn
zy*-Z~cNz4l6td-JC)6+gy+Y}LDVv~S
z=MCzq0V-LxEn6zk7-s3=z?oOI{PsyhC~s!e67M
z$ekQ=r3ku;1WitF4)50$)NU73-0s_M^N9tgK=yVDH$V2Dd7kWScAe@%%wp=Kn$5cw
z;#I#ZyMdWTWacNmW*Y@jKA8Ph_luhHhysI?&PeVHxk2$lIA108Lb)%Kq(vw4zypOoRtt!kmI2i{DnvI*yo{scHg0@3QN%@Ejz91IsVO-L&@L^d%$a;rmI
zm*!!bxbD@8zcl>-h7%P@zQ>p+X#`;!DSD}jgecfn?ba(BKVyEL5tZ*-5=dM
z`j<3WQe~eaQLy0De(o8H={)F8gthFy?0*o&T@EIm&}N0FW;pH$BMMf7YqN5OjrC3x
zBeK~vlgYyn?JHHWC=D%5JrMGxQCm}bc?-Ra8-*YQh+&+0%;0+lH0a8JAX*`a4@jp%
zfSl?>Ysseu0!8xp0{$UkeiHd2#YX#@-OF8Oibsrgw27W=-{A%G=f%?|_~4lLPb*Oq
zGQ{y|Alj(`f9ODY?-}5swPB(a#7}2|^uH2@ss@6&jI6%yt!sbx?s$x{ou?%j@{fN@
zi@Kuok=d*SFHVo4<{47|ccqj;)AeR)rRiQhIv}l;?aMNXg_=a}Q0)ekiFiKn;A|v!
z;kYI9m=6UopEx@W@WJO!CBWEZI2V>aQk1JCBG5Cu;Xw6kyJD2Rs@=RUO)G;#^;C8b5@RucJr3D`!hK&kGkR5xrMwO*`0m}s66O9)7luI8Z8*c+3GOx1-{zg
zZxV66h~^luv&;dW5sK6vrsGoL!vPpv-`FL*kgoQe545#9(3;h>so>YqNdEaxZO3ixqI1|Hc
zMG8s+M8%2o!y{+7s#9D~vmluze@fj79wZd&cVAYOrIIYxfk21|vpy>E9Qu6??^j(h
zt-#I9i5&TDyyvyEvIahBhB*y<_6Z<7q5ztkA7N8>{0pZoPxCdEM&rG5J;b!RY4E
z!Nv}Ym5Ip2mQzklWOv9(p$I$lthj)x)%-_#eaU3sIn87*L|=$3q4
zW9VG&JI0K5%|g-xgO&jq9yhlPOF-W6h9u>S6R0)ti&j99x6VGb2Y>5q|C|-MgEdb0
z>Qgh8GX5{5g=qb9a=^CwEImR$pK1dVl+q+s1VAZ`N!j09-N{9fB`XN8bx#8hgodWX
z%l|XII080VC8UsL-{jpCmp*)Qvi{dx8wq$&w
zx3S;+$pNqXH`OBo>5iV4IR^LbNlmYS;an!Ple)~qOkQBbeM!SFY+##cq;iK*V!Fu}
z&+;|*!|e|OopOew783F(#1x6C?O=#$AkznyHed2Y!18DZY;=!{7*e289*hH7Mv|s-
z{2LM&JWDy`kv5(82)hQn+k-)=%+2VXtmJQcQoxn$#sH>LxO_cbX`sKXrYOUvdvhma
zwP_m}K_r~qY!CYqzuGJ?wSCjFT`FzW*b
z0CwI#1Cn`dJ+cDYNx$ggqnTPOqNj8_`kim*V?gy{?qOvP*<@Zf
zFj?J--}+(eUr@ARgP$4s+4&vyN-;P|P+7QhPqEHf1N}}EIoI=Tq7wu1EUESS=GZVj
z)h+GD*{pZJFH98hj_uuyCNl>{h!C;iuIUeOXNOieB}E6dD|0P8Jj4(nCWXCrbZ0&F
zX?zqfw&zu|1>p6z{|4WAWSao@Gng;~{OenVdm{W4woGb-&Qc@d*V?axjQ{aZRZ&l>
zA!1LMN^h>^x92e0h!&4yu=cOP_hM)rNpY8GZ(!6!=l-MMZL4be8aKN5G-FSIgnM+y
zbE%w8%9ZmFZ?Qcp6JQ3lL^>pODH}`BUi(j%yI^r7*1`S{Gdt0D>-g6kJ7L*nY1Aj$Av>?_dkyeq?
zhS6rp>3h}`Ks^4|!io}Jb}5J{0*7Xvo(0S(?M(@K&Oik?`f{}YBHFHO>^a0?=S2~k
zlt0oJdTTjn{w|R#dB;u1+WD@VSh4d|qIRJ;SP@#82-zCIUy3L*^oF0&Fy$ny>c^XUk~TU}
zQpj(@d6H^kFM^nmb`NR@;gRDU^n)`!3Gj&15?+TVUwjFQQ)jM0?_i}^+)f$8p`I7y
zTSe@$Ux^b&Pm$HG7_tTd`|yP)-YA7WhB`
z0=S)gZ*f*u2fo?+#7(sEdF52_6K&$KU1`&c+fhJmz(u-
zVf1gTar^DNN5Z^!!HS5T5pA6+~o
zi=^fs7iAP&CJgMU`H#&r5qC+xeq~i_7c%mdVnwZlc6_N83~d}#CJO9f>r|lttmChi
zLUl*kt3Y*2HvRem@my*!AV)%d@m!po6P;5Z4VRukw9TdBQ4&-j7HO-)ZZZ@*y2!zT
z`66@$9i!e6&7l}gS5&CY4a_Vp5)EGK3vx^fAe8O~A#T#Ye0mF(3i;L@6s$<`_h)M
zf0B-QcqK24UYLN2?>2N728}t+qGRrd+qcPB*f}L{aJN4){IXH_H^?1k=gaSwGmvhNGs88T^KA{W&khl?6Vs5&o|(aqFES7nu%1Im}3XCUpjs0JlbLCfmTWQca%_l72bFQ=1n;TxbP$2t;v
zy)Z`1LWvr6&hMI;J=VHz%M2_JgZ;2%T(dgaj7jC8ZNlvHBf_%w#y+6CZC_B2k>H
zNU2VQ!N(woPA*H@+N4ATum-kJyBqg`v?)Ro(`&fVwMlj+<=7?hClV1NM8Bu@E?NOa
zMSv7tckOx1x>eO@VJQdvMtA>0a=B5hJ@T3(D2Kc@H>vyvBql}S8j3)92#M9^5~8;P
z*dY$BoTAk(eOI*ZKp-Mzf(webjf<}ggKf($jIVr=<}V=4_>JO2<+@LkYh@njI04Y6
zc^iO(h=;)tw%QQi?zZ2KKoIO$AgScwjr?!$oF;lQJs9*Z*5j*Bzj#=gjdzCWYDEAsNQeqSrg{Oe-)fV_uQtN
z49NE)5!et6m_oR$QH09rtdIPC#YS^`8)h!iWzd+;*9FeXQwV9eyuuc1^5I)g2hxqV
zEV2QkhnFN=ABR+MC;p%1^dp|qa?+_UzrYM|p5KiRxS!?a^zA-lzP1S$H-7#6Qn+y&
zj&;LFU!yV(^^<6~E=!70U7s<*S1J&r{%eYhEC#L;na!8qAfgeUfojgT*qCBVFL5^`
zBAM85l#p>+dXDMBk@ZO^Jg#z_Kf>$b)xcT#%pfQnC4Rg7+7lCmgWBSjyXH#i6yDQ*
zRNp;!ZIVdLD*7H%yVk^!bwfvAu~MJFHxvnvt9Wv?4_Tc<1A)!%eE1tXBqq+6^eZg7
zRX7>bFE}orM^jOtMMjW9P0vRE{#FCs`KFFWeL7t3UhAs_SS)5q%gE_x4cM6ISF~Wf
zZ5dBi;og3dwnP#$Z`H3Ih~+=8tPsLi<6luAznZB2BCgX;NHhv$|7tE8Jk62?U5A)#
zKn$DLO`Wv%rfmWfxUl%O(MF$LD&ym-{RVZ&gj`XEwp5=OrMecd$mxS1#>B3gi5Spx
zs^dn?fe-8v*)_z@$9fQWbnV`=BN=*=-XMn>^m)**E7D1VLgKs>_bpH&4iq0+lp*Zb|jtWurC@J&iL3C9(xl$|OuYI~x&j2PUl2+_5MGjZS)#tZeiiSYqZ
zON__*AIDAd6#*Vnxz@M=mAsWJRAQgojWEJtIgPQTu9@tUg2X+dV_lmV?mvhVy>3kk
z4$`dF*L-L=dlSze6xu{Mvs;sbHb%#X^w#4eE>#m*7IMyk(T&$ze$7+{BSEa(pM
zUBUaByL;F)fB7Gn{R;#)Uj(4kvae6ugkp2!nulGDqfd08-+}4(mtS2=X>I%{;tu$M
z7$S5+*e`wFYoousQpR4ZbfL195Etnt`6SVe=SDW=H^g-%3@QR2Y7dO`V&98;K-9217}*~YWK9dvw-td~=Q
zF^2tH#eb0gb-%gEY~1=_%OR?m|T%DAZArGf3$#O`X!h}DwsnZ(uJCo0=#8D
zsJrRD<&GV*IdE6*7OyQAu=Q{eOh16wIMks_6XBJB;N(Y0X$doex*+B?Rx!Hq2Rz~R
z+{|O*KUtctjstA##rYc>c6bKeY>!MIJEnG8Tn^@aPzQAyCi@mn`@7TQ3xKkfdO`#^
z{aQwpZB8AiNQ!2OmE^Mn4ASZsrA8MdAICyqmaeW8AAMTQKg8)a}Pl0R^Fs|nwF>`hZ4(k^LAH$#l7GK!=3gBN9+cC9|;a3zWS
zI|~WTM?)#}zN6)IU+n%)%+v^D!WQk^x|#OMENp2nunE4Fs0>KFg&V?KYb~>rE|CpF
zZgDN4yg{j$8z?>bhh(6oLI^R!r##j;J2EK8E$HEz#y1ImCSj
zPk}uTxiAvoW>&qL!Vn+1y5-#JD#U6V^|PyZacXcvZpQYU1B9ft+`ei@5$~2Tg*1D&89cr^dP5cMEA(S!RPqb`7^>eWD!2M>&2$~*yIwNS
zYf;s(DdlGdf%qO+lm%^j)3Lw-0OUx$EiS7VuU56UGrX(5$yvg3xnTs=&rO0b(O=9;
zfW^3rHLEfDOBJw-m2#=K-FihKh+GdH5e5Wv3Vov^lB4~n1N|k5=R2>$UVH??ctGD_
zFXG_;?SL=xMfLl;LK@kvpaR*C>i5sk5yNmOLBtMWNiRUa7|wsX0LX%pt9~@8W}EI8
zCVkP+u&v(Qs;xh$)92>9>$ELbzgf&W(AXaQTFUkIZO3VK+pnF8{NwJ=4Q
zNYyfleFd4O%7tyPuOUyoklbIQbTMWP9W?Vp}NH!m+yb;{!Brc7E>c>SUS)*&32N
zLbOOqaSaS2)|peR#dPsPoZxL!!{MGY7kuku!|eE`#e@I3nLyW4n*tt7mY+vvrFMH^
z>^q+j-P+dA(!b!^n(o&^&gn@O>u)0;fW4?`SQ7&>7s8efs+O@reGVT`Qt*?C=Vjx*
zEPM=#GY?F5_ypYUCdS)t622dl)M$2W%YUb~Wlmmnj4MvYv2H${IPl`-Zb#z+h(^&g
zoRKrB__k4`v$LohF@Y}PM4F~wij5TLHDpjSTEuWvJ=6uOlHz^(45_{*dOSCDNLZ7r
zfT(1G@Xa^v?tpp$y%O<7KMXK%eNf1$uPo>dPw#%=Cnplk0<2nqYQt98d8!R!naT%#
z`2i3dVkd?AfvZ?USgH78w(CL5hgMdOC7-Pha#}Gl)0posk2@CNhONcJ>W(?`ETB%9Kp{r)$(j(MQVrP(umYB0NO4>I?YBE*@HvfgsV6{k-lYJ=F`b@adTO7Hkg_O
z(1|dLv%V#&wGLp6U+{ROCNrrTd~Jni9n6!gt8R4u?!gclRV%=9I$4yNu8V@3s9}DY
z586p9?v%{9m+rwdP)^kzG-Ka=JfOaPvlH@pTtR6-Y98C0k65a#5Idg2fcLW-Bh$F@
zSGHntorg&DTvcd>s)p=OvdiQ>10Hm5p7yU47{Sy)Fm%U$;7?*q5f0*L0NuxD|C26D
z6sgdLZlmV^l_&eJU0(y^$sQ$P<9}Qb(sBia)hT
zq{_c$9VIL%4?_FYo6@Qfu=*tldE0-6&g@uz|%U1ow0*&}$CO6BlJnF{GcE%1*
z`TL2^Mft1abPIYXe`YIWcYm2ytglsi6Q`M(G}lYE(Nq%hd&t+oWjuOZKtKbU&{7m1
zBx41{*TmY@y{E@Lu$Q##$!pWXE(Xg7L7DKx^*+UTx?_{K{pB~w1%lyIq%cL%GE?{S
z2+wky7>F%~%sOoMIV|Y>ppXA`q;ObMKe6Zkmatbj7)z-zh
z=6tBZ&q3zX=H7)Ux*f1P=`*)$8gH5Fz@QB^1e(rYe~&F2w{yX-U5$8I*Bmm|^LTIs^vg}M;U3B%KyA!GIW3L87MS=#u5uDso(5Z@aNGf4(sI(*
z*3Khp+QeF1z4!BryEm#R$95I&v~S{rc9!2Z4PddkxN-N;l7
za85>l-th@;7n$M(3|u%mTzDKlD=-N9`u0(TGDw6H0Edi8kp#b+IY=P7=l}0j&{{VA
zI0S<@-x@d5DtTB%;)ZTe0Ol`r`W>;zim;azvN%^hcy1Ed3u@l)#i!sML|#1Fj1u$5
z_ly|Wmq_3GENoGyg^x`xr=$%rA-qTVy}p$~=_X?$@F*q|$|2pa+`V%M)^|WB*Xmd+
zc&_!0iKDy*YIQ)XvJB_>DYE{C))TYX^0opO^LcNHIS-E_YnC_3HbIV7{rL`ZfRmln
zAC8QB-XeNH`>`Kh0M^`xQr&ovld@okmCxtOTMa6SU8vU)})8a!UFj`AZUR+}0
zdn$0bN6$@4g5TFM)_P>X6t`#ux`$mQ0mn$!KizuDuoMQ2l(E`B_SFEtLu+^!E#GA`
zJj7QtXMC7_MRPV|oYfz8Zdz6^qi~S0d^m{HjH;fdduJ!!a&COI)C8P^(!0S@A_q|7
zD@r9~BXLVJ
z5KA000JxMM0Q|KB2uwUGzwB!c7l&Z&9v>Fd8+@+SzL^pRn}|!$=QF>sswJQdxBU=_
zf{7Iy0d7-aemh&XG&O?Ve@QDy%LWMy0~&^0k&m@mL}CjfQNC=CpuC~-0G2Ko1~N_1
zX*5LU$YRiAMxvl&mAH%QR2RAmWLig3T8!2L12U_YP8(lO7z|SB;HSK{Pj08UAh1x@
zwx$gS>l8{%=o-FL1o!_Ed-+Ii73OU46Xah6ycvbSGyo$WATE|St&B>Cf}ZkKqXm9j
z=cNI_IUD6}JMLo~iek3ktY`W+Ny;Jo9kVFIia!?ye6)npA}%~ceFI?tjQI0nxc}6!
z!w(w~21#7pk`a-CNVwtwDxX3EAxL3cngjxas1X0@;_R)sWyMl;r9n+ed!eE%fS6mu
z%jSgji1Ya-W<`k?)0S?Tzf%==6`EOVt=4BoC)=in8LP%BJLPy|kaeu~yRHPsly@jn
zi&kt`nwxLhqr(!VH{ed`_4u{*LF{gJF7LYP9Dmtf8RlE*=~cLO`a8)lK^9Eve0;V&
zDTr59OUNAE9$WfzgYpj{sZJH#7n^x#hOx^QRVttsqQ#KytdNFFQ{=;DuO<(F3D4$A
zm6>C?P$L(wiltM)bJ+V10YcP9Nwhc3*(d#DjhQ%T`?`_MGxSFuUg87?46TdNj*$Jt
zkjm$uW?Zcpl&l~b`hCjt$K{Oeui9c!=d4~S#*r;^@=+x?4}bjmOTd&j5!I!tJJSkB
ze8NvS-FQat;1=%A0a3h^nxk_Z8n8WH&2V&56uo)lXO%QNuwgGP@hd^|C5U~Sz!Nl;
zJ7kwA7t+v;QNjz+q6BS->2aJf@4xLI(-JzfZyKV!*R2Qu8vLLOQ$7W9Nq}XrP^7+x
zzf*HoxVpNSxeh77+r6^H5l51B+APsI9Oa;#4pQgk#F#DLji?;lTkWV44(=+z-Q}^u
z!6o`eTqEsTK*7jut|wlKGH!p(H5=od+8!jPJJQTGr$a~`D*NWoc#b=t+PhBOZe5Cw
z&6l(oLAZEdE=4QQ!|m1IGZ2YW5=;N9ij14EdP8aTbRLUfRjABVn%tD9YyAGN`IVh+rkM&$IcDForX+FjZ{C*er}F-Ib#Sw;R$K6?9I{
z&W;VQ6AVYat-%xWH2y`yIoR5FKnMK;VfG%8($4SD|M{K0
zT9pt?ZL+itWiJN>T6K`wxW@t+J>f?ai>t@Y;$>p@ovthuZZ&a|#l8S>t#Jr#c@ms-
zQI>5Sr__F`YIeR)0CtfKv3`u{T%Gnf74fnz8ieYRL?^OS(<085I()j_<@s+sb(b|Q0|gw|$_0eZ>xd$!ziCXHC3J7dFe1g$zXWy9la0aH6f
z%EF$*pey4d_f)N|4tO_##MPa#znwOKv(B*P-siz;&Xdb7<#jXhR5Q&083yH41eAe$
z=Kd4F`fnkrqIf-+iU?V=<0^X6&iw@20L|Ga*uJtf>4L(Rxi|?0is`1De?%DADZcPLWeKDAb8yMF?%)Q<((R$;~{k{b=I?qZ`yUax9?Xu8hof@yT9=H7NVqFEp2SSw6
zZzKQ)DUPV(^M@Es6C0=Bw-lcor-%k&w=^V&a|@J6Pp7ww_Nj+3bRugt`xku9;5|13`-6dQ5E-6jQ`lXdjknyg
zm|xIFrhh{jqXEe-ecjs8!7+peE!>qdLNm7+QWN<3UX6w99v_|6|kMLOpxg7NIt1pPA2uWpKLczq_N
zUMD&d*elU~?A~lc-?BtyN^%6@vDh87uu4Hk_`XMBx^y3N{ta%zpPYhv^$=c=DQ09n
zFrrk@`|&U}us(CECG%#I_~D
z2;G3^#M2TKkh8KqlVKZmwU{{wC3*KCoW?siEjUvqi&~N|+pKQ+^6p#iBIxjp;{+zX
z#?TTE3wjYXs)PWKXUMs96kiv5uEZ9r8e{l?-GcKxKe)D1kB0nBB#YVLQKdE#q5hni
zdZSXp5V`_Lgb7B9#3SRJh|peg6Hx~mEm^C3x29Ei5DxoC3Kdt>I?z?sy@FZ+iyIRr
z)MzG*l>@tWKZ@TEQUY?`KBc=rH{rk0DA|M_!KQwo}PUC-(lwOK^r~Y
z-EZ7iY;j6aO$~%V2hoPIB`7fMMJlYHfcX+q`-ED&e?<6%+O~w-MuFk-28tjJ8Yz9$
zjPdKdg*SG*?|_^`I*}WiHlo*e8!@Chxf;H6v_VDu#n#W&-RAlp5hjYWiY_0^%57qP
z5Zj;Sm>XEq_!sH12icK-6QWVE8(5Ewm2mzIB9z36!18OA;eL
zd-{0I1V16aMm3i8>;Vl-!`*|230N3C@=J9wb|xVku*`dWkT0qrCIw_JRavWX_@%EK
zdyflzO$vF*?fBKqFord;GF2=_9Lhx`H*F6!!Ba9vKp+|=mD9Mk&B@PrZ+^wy`-KJ<
z6SJ4n3e-Q%5wJ|l6$MV6N2B-R#rAegy%lSp`>u^00*|^${u>a7n+?9An_%(JS)HCw
z19t_285S;=TpmY=_p|uc8bqS`?0IWrp4|C?q3Dwd$^>#Efr{9GeQ^uToKgx_&WSFD
zulT$zimbL6hbPTZwa*P~lA`IxXQ}=#EYHhx0n@3XOKLrR%0)!O%@20(>-aVtzo&_5
znd=GR?+M>!wc>_Deg7^=VN1Qh@>OP(-SL18QT+PIB9vCH_f_g`5F1;M+Wl#E^D1G(SO!D9G)uPL
z$1IDYR6eH>XMQ&Szt@HTCv$`k4s>=s*~mR1VaYBGg2NDzvMDX|nxB@gn-qOb_?s<6
zCVpvesgkNvT=-HhvwLu##qgo??Sxbe1{m>|>P5YuRMsDY^I7%mZWaTKl&rPlj&
z^HmQ)cjf)N(mb-C==$G!f$2?_w#cPJO7AF?4~9de2`S_5kA-@f
z%`Pa~L}%xhLZD#~)QrH5S*}pRPWYiYryWg33IP+0Y?UqVr2MYeQ9_n>c}+vT?3(Bg
z4dKK;C|ER}aZ+)b5b-?WJajCaC*Dzj*gY|JC7lft+KM$O$uZP~@DLG7!$3Y=3fv3pTs$OJJ>eFWSeGKV;QcULjLtoAm&Lh8(8KFooK
zNIv7SFn_A_%Eh}
zgFR>N_jAAbx;g{K{_Xx-rNx{kAC1NDim1=rYeKIBjZaT+tkE$>8TYxMVP}LDmkz41
zRGg){ZSd7$_n-(FpHkeOuRNBYSiw5PGb|yL-&{VPykCk
z0a(pOXD~qA>aR$^PT&Cg=YgDsou!SVpZu`ElUlPb8Tr{RjB52kr%c(wkcjrbTGoy0
z&b>Q3VP$9)3&1Y%3WaiX#UriCzQRmpH4k{1GIxomz@%lCH9-L7H+-9Iip|2>5hr%v
zP`YGL9rcf}rV4Cz2o!L}Z}H};aQ+ol7jJFbEk2MwrrNwoXUP|&JZVSxlb>1q*U^W+
zh({^y9orK(FN1Ovn*TR>-sAByYnvE-y{S06iNFO9RZQT
zcJ-yZ^+*hR{Q8f43h}bVEpN-g%C?yL-tD1E9dPc&qrwNmfQ6mJDVSnbV#_dI_-d}*SBaC8B7tU)#KWspTh2dj;mU5_~X!dKKb
z@X0(86?}4jlourdo4D6YU+kIjw)-C8q+Ln|7`wEv-rOAfkWha*%EgpvMo#4_wRX8D
zc6t94s@k4*_x5Hmi__{v)@$Z2t>oze6|Ch(UIWz~vVCwa-bb&YA^$YBNjFPdiwJ%lp!I3gh|r=SnJl7)@{ej_Y`1Jd~jXBgg#)~Rw+9fb(98^
z?FPJZljx_JS$@Afm%%a2)Z0u9E3$TEF`3@(W?7&riX3L|KaUh?;I*&+Y7QCJ^|)3hn+AFZgeRLMToD?YyhfCyAlj|5g0_
zZ_Hj~jeN1~ajoARJrmV{j~+9%t5C>m>QKlUjtf7fQo^x9mEz9*RykHTZ}v+$>S|WD
zGV=^Yl$6FAYJ5^Y+$787n{0Zh|NeddT?i4BPzEcG+p_XEcP<766P!Pi_dBz^eM5lL
zmsMe*>!TG~$8x2JSfC9jhpf`@#W!5#_kN36+ioW@bZ%7{0MGI6B|Qz-e}Y~hGK@r4
z4FgA**JDo(;~P6;k@>{qSUEts!iUxhXFtamZ<{8oJ7jF#skRV|b|d&UfX*RJxwdYy
zGn56YEtDek;*vdi9?d<|xw9HAi7g<_B$Kq-0C2_w3M^JfSn;=3%Hc`2Ufv}oCQr+k
z-n&fQpjI`7Zdmi4h!P!Ss5yOu?%Hj@+9SQwW+DRv+g}ERj5gPZ#7lL&Rg*|B>Lr%d
zQDZIpjb;J{s{b3!s312sAR3X5YmjFVc?IjSRyL8@N43s4?%a$!?sw(~ra$e@(~4RlUc4)OnWG@s
z7lsPHvk89j(o1|UX
zoo4|rwy|$z`$U|+xz(cBZpH8&lZfIE+Gmb2!zKQSn0I=%?R@TiF6%7bq`QH&gKPaL
zyqs43yng5U4gLj@;op$=SHPLUDbgZ_a03q);GBVeiuNb#x$!Je93fB~NXiP_U}-fy
zn-fP5ao}ftT{PBJ8>%gssD!)`XiS7Go?!}6l-0DtP<(%KyCpG|KvsTR;c}hDjju~reI4E~vPRXH*kAkQITJq)P
z7DgjN(+bh{AzXCzo28m}s`84zMCykjl*TqwR1Ra&0Y{q^xv7BSEGh5b`Nk@P-YZVP
zN1%jCIT?*mOK$%BM6Z;8dtLBM1_-hgHC|r$nL+vPc0iiFX)%7;h$`p2{x)8Hf2w))
zyLip4&%sPf#Ch}nga|i{=NBdh%BeDHTs>`Y!qs{WGp5ozuwI6OGpOS^C0!7`62CMo
zrN-?EFTN63^SBO{4$0e68uC>ah5IWN#KKSY5=do^tSDJI4?|s)8rZM7?j%8b&&26L;n=O`7K6sEf{8hDfT$np
z6It0q!=FI*E%61m>_0(lSJcXy;CoP|Op`8?sc91MEjO*wy#^EJVQwg1e@392`o-p
zpU+6oK2Wy+zudP?SqlTyqBt-M-9fCc9OMDZe(JZdv(>=O(!9Bky%2A5*%6v}Kk^Ja
zKQ9paDuT++T<*J>di()3Fan8#uS8g!it;0aD0cW1L4-Jh1SOd85AYu6Ta5@|^zlC$
ztjBsHc%DZpXNVngA|M96KoNaTAre^e3IUNY=!Iwi9EE>ejtGz(V2&^PT$S{1|CI<@
ac5snt3kRRF6X(2ps+E?I7q1l65BNV!;pXQ6