From 75981989b0937622d891834d4db2fc07945d7c9f Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Tue, 23 May 2017 16:19:47 +1200 Subject: [PATCH 1/2] Docs for React DI --- .../How_Tos/Extend_CMS_Interface.md | 346 +++++++++++++++++- docs/en/_images/react-di-1.png | Bin 0 -> 20062 bytes docs/en/_images/react-di-2.png | Bin 0 -> 35555 bytes docs/en/_images/react-di-3.png | Bin 0 -> 36116 bytes 4 files changed, 330 insertions(+), 16 deletions(-) create mode 100644 docs/en/_images/react-di-1.png create mode 100644 docs/en/_images/react-di-2.png create mode 100644 docs/en/_images/react-di-3.png diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md index 84fbad81e..d84c287eb 100644 --- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md +++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md @@ -204,26 +204,340 @@ To make the actions more user-friendly you can also use alternating buttons as detailed in the [CMS Alternating Button](cms_alternating_button) how-to. -## ReactJS in SilverStripe +## React components -### SilverStripeComponent +Some admin modules render their UI with React, a popular Javascript library created by Facebook. +For these sections, rendering happens via client side scripts that create and inject HTML +declaratively using data structures. These UI elements are known as "components" and +represent the fundamental building block of a React-rendered interface. -The base class for SilverStripe React components. If you're building React components for the CMS, this is the class you want to extend. `SilverStripeComponent` extends `React.Component` and adds some handy CMS specific behaviour. - -### Creating a component - -__my-component.js__ -```javascript -import SilverStripeComponent from 'silverstripe-component'; - -class MyComponent extends SilverStripeComponent { - -} - -export default MyComponent; +For example, a component expressed like this: +```js + + + +``` + +Might actually render HTML that looks like this: +```html +
+
+ +
+ +
+``` + +This syntax is known as JSX. It is transpiled at build time into native Javascript calls +to the React API. While optional, it is recommended to express components this way. + +This documentation will stop short of explaining React in-depth, as there is much better +documentation available all over the web. We recommend: +* [The Official React Tutorial](https://facebook.github.io/react/tutorial/tutorial.html) +* [Build With React](http://buildwithreact.com/tutorial) + +#### A few words about ES6 +The remainder of this tutorial is written in [ECMAScript 6](http://es6-features.org/#Constants), or _ES6_ +for short. This is the new spec for Javascript (currently ES5) that is as of this writing +only partially implmented in modern browsers. Because it doesn't yet enjoy vast native support, +it has to be [transpiled](https://www.stevefenton.co.uk/2012/11/compiling-vs-transpiling/) in order to work +in a browser. This transpiling can be done using a variety of toolchains, but the basic + principle is that a browser-ready, ES5 version of your code is generated in your dev + environment as part of your workflow. Often called a "bundle," you should rarely have + to see this file. It is effectively an invisible layer that translates modern ES6 + code into something a browser can parse. As browsers evolve, this step will become less + necessary. (Although, it is worth noting that because transpiling comes at such a low cost, + and browsers are relatively slow to catch up, we'll probably be using it for the + foreseeable future in order to adopt new features beyond ES6). + + As stated above, there are many ways to solve the problem of transpiling. The toolchain + we use in core SilverStripe modules includes: + * [Babel](http://babeljs.io) (ES6 transpiler) + * [Webpack](http://webpack.js.org) (Module bundler) + +### Customising React components + +React components can be customised in a similar way to PHP classes, using a dependency +injection API. The key difference is that components are not overriden the way backend +services are. Rather, new components are composed using [higher order components](https://facebook.github.io/react/docs/higher-order-components.html). +This has the inherent advantage of allowing all thidparty code to have an influence +over the behaviour, state, and UI of a component. + +#### A simple higher order component + +Using our example above, let's create a customised `PhotoItem` that allows a badge, +perhaps indicating that it is new to the gallery. + +```js +const enhancePhoto = (PhotoItem) => (props) { + const badge = props.isNew ? +
New!
: + null; + + return ( +
+ {badge} + +
+ ); +} + +const EnhancedPhotoItem = enhancedPhoto(PhotoItem); + + +``` + +Alternatively, this component could be expressed with an ES6 class, rather than a simple +function. + +```js +const enhancePhoto = (PhotoItem) => { + return class EnhancedPhotoItem extends React.Component { + render() { + const badge = this.props.isNew ? +
New!
: + null; + + return ( +
+ {badge} + +
+ ); + + } + } +} +``` + +When components are stateless, using a simple function in lieu of a class is recommended. + +#### Using the injector to customise a core component + +Let's make a more awesome text field. Because the `TextField` component is fetched +through the injector, we can override it and augment it with our own functionality. + +In this example, we'll add a simple character count below the text field. + +First, let's create our higher order component. +__my-module/js/components/CharacterCounter.js__ +```js +import React from 'react'; + +const CharacterCounter = (TextField) => (props) => { + return ( +
+ + Character count: {props.value.length} +
+ ); +} + +export default CharacterCounter; +``` + +Now let's add this higher order component to the injector. + +__my-module/js/main.js__ +```js +import Injector from 'lib/Injector'; +import CharacterCounter from './components/CharacterCounter'; + +Injector.update( + { + name: 'my-module', + }, + wrap => { + wrap('TextField', CharacterCounter); + } +); +``` + +Much like the configuration layer, we need to specify a name for this mutation. This +will help other modules negotiate their priority over the injector in relation to yours. + +The second parameter of the `update` argument is a callback which receives a `wrap()` function +that allows you to mutate the DI container with a wrapper for the component. Remember, this function does not _replace_ +the component -- it enhances it with new functionality. + +The last thing we'll have to do is make sure this script gets loaded into the admin +page. + +__my-module/\_config/config.yml__ + +```yaml + --- + Name: my-module + --- + SilverStripe\Admin\LeftAndMain: + extra_requirements_javascript: + # The name of this file will depend on how you've configured your build process + - 'my-module/js/dist/main.bundle.js' +``` +Now that the customisation is applied, our text fields look like this: + +![](../../../_images/react-di-1.png) + +Let's add another customisation to TextField. If the text goes beyond a specified +length, let's throw a warning in the UI. + +__my-module/js/components/TextLengthChecker.js__ +```js +const TextLengthCheker = (TextField) => (props) => { + const {limit, value } = props; + const invalid = limit !== undefined && value.length > limit; + + return ( +
+ + {invalid && + + {`Text is too long! Must be ${limit} characters`} + + } +
+ ); +} + +export default TextLengthChecker; +``` + +We'll apply this one to the injector as well, but let's do it under a different name. +For the purposes of demonstration, let's imagine this customisation comes from another +module. + +__my-module/js/main.js__ +```js +import Injector from 'lib/Injector'; +import TextLengthChecker from './components/TextLengthChecker'; + +Injector.update( + { + name: 'my-other-module', + }, + wrap => { + wrap('TextField', TextLengthChecker); + } +); +``` + +Now, both components have applied themselves to the textfield. + +![](../../../_images/react-di-2.png) + + +##### Getting multiple customisations to work together + +Both these enhancements are nice, but what would be even better is if they could +work together collaboratively so that the character count only appeared when the user +input got within a certain range of the limit. In order to do that, we'll need to be +sure that the `TextLengthChecker` customisation is loaded ahead of the `CharacterCounter` +customisation. + +First let's update the character counter to show characters _remaining_, which is +much more useful. We'll also update the API to allow a `warningBuffer` prop. This is +the amount of characters the input can be within the `limit` before the warning shows. + +__my-module/js/components/CharacterCounter.js__ +```js +import React from 'react'; + +const CharacterCounter = (TextField) => (props) => { + const { warningBuffer, limit, value: { length } } = props; + const remainingChars = limit - length; + const showWarning = length + warningBuffer >= limit; + return ( +
+ + {showWarning && + Characters remaining: {remainingChars} + } +
+ ); +} + +export default CharacterCounter; +``` + +Now, when we apply this customisation, we need to be sure it loads _after_ the length +checker in the middleware chain, as it relies on the prop `limit`. We can do that by specifying priority using `before` and `after` +metadata to the customisation. + +__my-module/js/main.js__ +```js +import Injector from 'lib/Injector'; +import CharacterCounter from './components/CharacterCounter'; +import TextLengthChecker from './components/TextLengthChecker'; +Injector.update( + { + name: 'my-module', + after: 'my-other-module', + }, + wrap => { + wrap('TextField', CharacterCounter); + } +); +Injector.update( + { + name: 'my-other-module', + before: 'my-module', + }, + wrap => { + wrap('TextField', TextLengthChecker); + } +); +``` + +Now, both components play together nicely. + +![](../../../_images/react-di-3.png) + +### Registering new React components + +If you've created a module using React, it's a good idea to afford other developers an +API to enhance those components. To do that, simply register them with `Injector`. + +__my-public-module/js/main.js__ +```js +import Injector from 'lib/Injector'; + +Injector.register('MyComponent', MyComponent); +``` + +Now other developers can customise your components with `Injector.update()`. + +Note: Overwriting components by calling `register()` multiple times for the same +service name is discouraged, and will throw an error. Should you really need to do this, +you can pass `{ force: true }` as the third argument to the `register()` function. + +### Using the injector within your component + +If your component has dependencies, you can add the injector via context using the `withInjector` +higher order component. + +__my-module/js/components/Gallery.js__ +```js +import React from 'react'; +import { withInjector } from 'lib/Injector'; + +class Gallery extends React.Component { + render() { + const GalleryItem = this.context.injector.get('GalleryItem'); + return ( +
+ {this.props.items.map(item => ( + + ))} +
+ ); + } +} + +export default withInjector(Gallery); ``` -That's how you create a SilverStripe React component! ### Interfacing with legacy CMS JavaScript diff --git a/docs/en/_images/react-di-1.png b/docs/en/_images/react-di-1.png new file mode 100644 index 0000000000000000000000000000000000000000..6b49649d9b2eea6c2166b0d8f833e15078d8e8e3 GIT binary patch literal 20062 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 MPgg&ebxsLQ04rOm1^@s6 literal 0 HcmV?d00001 diff --git a/docs/en/_images/react-di-2.png b/docs/en/_images/react-di-2.png new file mode 100644 index 0000000000000000000000000000000000000000..1f0075605f10e94c683028017325d41ff60dc0a2 GIT binary patch literal 35555 zcmc$_V|ZL`*DxHLO=GLEZL4wPh7&Zl?TH$*v70tVW3!FbSQFdkJH77bd)~Xbeto~* zIrbcT=G-Ti*E-i;XM~E93@Q=<5(ESUs+_Fk2M7pgBM1mc7z8+Qi;{&_7X$gu9m~m`!Tje124FyiJonP)6olmk(ls*CRA(Cw7 zo0@b=*dgYF1Oe)Cq#WdI5pw%5ytz;{1Nn?He89|nN3={5 zI48IjCTQtD^o2b=aYTu*ujXT+`1MYdQ|+Ad^Vr_)YC;w@34RX-J(oTn5%o9xQC+i7 zN+mFAzY}5ft0>+c;=;h>oJlcJycJ14I}b zG8oGM__D2(_;3%)SO~uYG00mi3KERy{yRBuPcqVlj+l>ThSqWPMi-gb^n6(VyR=klkYiM+8bnsge-=ngZRb06c-x4sH6!)AlLqtGtLaUb8o2a z?pXF5`ys6xzCf6MpOW!aKtxs-LDi?jB$(KW5cA1oR`!ocNxJWbdq~f!%j=JR5Z_zc z)cg4S@`*V2sJ)=d2uw~Ckol=BKW1{@J(V_qg6Uw>&vs;cqz4g~c~nzS@B+LXmabE8 zU&Nt?VioiD@VM=D*KMSP7&w5;6@0Pd2zy8qCJA6*;4=oa55MD!frNY>Pzh=gN8W{` zG(tP5h9B*Oz72q2#gq)di$f^x!B>W#kGo)GMQ4QT%Y9o0N!X=Xg>?v-yoSLGwcjP@ zfTjmEE5^`>O498*foc%wcM6F@fgmn!fdD-reu;_Ii&QP6hsi<(fhdt5CrO1bCjk?V z_a%%`?0vlJPfb&v52261Owmztt$6ND;mL?g3j25#THps&E_GZkseyuu5*C8U{@kf? zPM3Ed190+6$44w+y)eop#`0z-7A@fKk%&7Xio-39;L^CZBdeJJn zs|d<4pGSGB(aO*tK4Uq;jrNv<7Et<49MOca3DhE$0;W+{$lwV zj5LV!4(S*P6G<No7|PudqaAm^M2J?>(Fun;AzD&?){r{9H*@bwXuA z(XocY&@q1fQ(sS{)>{E=5jBl(De5?`^co8KQp?Ih@@>k#G6fR~mcn&ZA4zPn%Ol;g zuS2dQMspX(C3f}h#l862Vpf#=%L{W&^EXR5^}mUJQ`jq+L@g3FgEdn#OJUdb40LKb zN8D-|gr-Nq7Dz@&wn@gOhgYxoep!;BuBZX6-t=ASySMsSsT&(B5Hq-MjWvb!nw^=w z`FFV0Co6I*e5)d>u<4J}_rEoM6aU_rHZM&r&G~RL-pQ%JCC*vHscB6#(O7V1_W2lZ zm93R+XkhxYCFzB#b6IihJLOu*TFs04ZCs{e%>d2fnUCdO-1vbu3ml z(HevYY$+V|riby>=q@V6@>#T5P5j<2>8@}tS1!RW&aMr+*|SGeQ{xvCL*t9N?jI|) za`H}!#%5P@{iR>1)w1@6hK=n$85ms??&84^hNHR>*5RQLq~rG!;1J9Z2y^G-H4zjM z*s@x&@AJ&?WSa_(H7?u+Mg&Ea$~FIbmpJr}RB=RMLoqddCgVEIGCed6J53`)i2dsq z?~F0dO4bfDu{wtzKkMe~CafYp^6M1qrs%FziI-=V-)b(FFZ5&fH$`K8F2!@7O}9F- z&a&6HUA8O$V0}`vP_w`AYCXFxJhL7!BzYN``NcitR(T{LpwSZH7U~x5W`D$V#CN@Q z-9Ti47KnySOhB~4`;qUQ$enk^*_c<+>Er(N=H>7CKAl~?jim$Q!-T_{k*$i-bnC(c zq*(?#7#@*^P&=As;TD0GohDMpm!X~o%BhV2nK77J#8yOa8W&FjuNonDZ#NINwuCk} zPgf5@kJ>hd)|`91I|twEyVlbmrz59AyAKOvGs?T}ODB{=SzI};Go%;j=PYOTh$^Vz zsB;9TRO76yOjZ0aMj3=Ho2}6u+q*`PKffn`++lq*vzK=}zZO9$sEY=UKy9iXd!otQvUpZ(s zsA8MUNul4CR%g=!Q^Un0*>0}Q*Oz5`Uq8`~7>)6!E6Bzu3&#oe#u#Z;!G93{P+xTE ztevTtsijAH3}?qOme>$;L-Cu#Ro_ZE-F)G`ZpG!~vgT4)II1K0N zWM*Ph;sv2n$St_AOyBhsbTXT6W5pM{T|-Y&ds!?QCz(E~PhZK8v;6M6GzOe47m>)j zGxwyPrT$=a*KRkvYj|V#>&J)1$(qSL>`d%g&4u!%RwoaQ{qHHiM@!wy$SW|*nrdgf zZMXQ7U11NJXOur0HUu{1nf5$Hb8s6lIWsOcMbyZ(elu~N+XgcA>(1EVFQm6$xiuMj z9&u;c4mJ2LjV`aW_n6C!C@p6d33ME;pENfJSh(wlT1w56tY<$8jotJgwLO*|RBAlb z-6S7BG#gfR6tI6k7f+Vg_zjr_U0OO}<>-3S^$lJZ{f^YCq`G2Wzf@J%3y%ng)bCFB z+}=GVgv646->Ysr?N_z!0RDjdeq1x3>(kZV6)|cAsx8gCYzwPP3&H1>k&_2yf=ot{ zB0sAu%fY?;sUCBrQIyOPp+$G*BR#FD&&6RoSfi`Wtasu=edAGD%&-Rh{_{8IUl_8r zlnh)uyw=kXe%v37&K{&^rN_R2E(gwVc2b%NnRy64E`KCkd{>uccVj2wKJ~I)q)XmV zv5MBQ>_&4v+Sa0W;px?F5Gm&uUv^wv{7> zqz^+omD|rD&&NF7JU#YWty5kNFKrtS#eqKqX-I2CQ2ZG03a`GM*BS&x_Yz(g%o1si{GFw2(p&w5qXw1U&^Zdwa{l#<$@XAw1GB zdgsXX;Rg`R$yO|t)j|*ft&ozpp+#Y)@kj&sc|U*Gll+EuU88qt1tAO9(_`-pp%TFV zmQzp=k5BLsyZxz37b5dGzU_`mJmls<-|fwGh2az8Bh?EGiMged;$!4LlZr9sHYr z_TXJRI{027Cn=`x0eP4OpZQj5q2HQAOd(Bmj7Uj}%>g*Yu@jKJH_f5XY6M3K#~O&q zk$wMd2VY4DyYDk!Fdpmb-j@Il2HL8sGw+;qPw&;eqhmw?0Rd#?C!?0HEgxQ5noF}Q zzBkZ+njN!rb)gc4dUa(f|4xhe`hx2Z8wa z1&cTIx(P8U90FE5LX-pl_2jt_Cit(`BMW?knG3;yY4J|tHIQ$O7@=RmO{GEs_11_Q zYQ*#}@cuvx_1Wwd&;c;-B?F+!By+!@yaF0gC7>GRZ#)p=L?aMX0+JCp6UqOk2pJ?2 zYs%}UH?)|LNL6nFKe4}tP!zJC{a^H^rVxeHq!?EK{!P|^Kg5Q6jmrNMVoTu~)gGAR zD*P~y&911fp5Wr*x#P96w$gWXbyYg!;^ch$mig=C}Dqd{?lp3xTw|K8Lz&&9>n(%ihTmUg^!vqo7BnnrJU zO~LVGm_en0w$t;{;|lKquXkUwdFRS!MW{Q;j^T1#fEgU-6^m9;ipz#*LO(Us)nN|% zg}7IiJ;$Dox?xEg|0PEH3V$FJQfFzqZnlmuceY(G@l$HUl^GdfGT=PwxFM++gYso( zZfpAX%eH;K-)>UZzQy|4ElPyv@pGQtm4?>!1BQW2j!SxJWzI&5whx>8-A_!kwom)C zok=jSf!}%$UX1aWf{-v{33DLlun%k7W!Yh?ufn`C+i@jpl=9$rt=8HAQkB^Q(-AZO zje?er93&3JI@;e7Dmsrv8v#+fF1O>w)H)ti?eI}oS6^PMD*#h?y1G_IpDZ_Y!co}rr|I#_MH?#tfI5;1C z?-|!d1#j}_h6GJ^&+M{(%s7A?_}vwtmAss5T0k?4%Pbwk(-MBjVjj~u=#Ck-f~*_7 z{{PaPYD5=rNbb!>$|WH5jQm@ps_zI45ps5`ZEo(~$MtFnxY?Ai6eti4lhzxu{+Qpo z2{CcSMeVCEc6iB3n^z0;HU8!{H@62vggi@=WEn)pZNIMFB^M7&-1Vw=+@eRp)svTr zvfxvu_x?O?u(Np%cW-&qJ$;w`@xP#ALriLen92)b-E^Er{Mw{bYu*H=`UbP`$?)eU zT~!H;jNY2{YKgF>Jr2KXzcD^vStAWqa^Z({hGSsH3&>yGC(CtT4*%@Ch@IRk(~?^N z(;N*^3lua0`dyY_>XeiD-QVHb&4sIGPoOQ@ZJ`M{th%)tecs5Qm~H-b(tcu;=QxaA zumsiS-EcARFRM1L3UyHj;eGcbqAT5)b-Q|iS>QG=42M8+_6c2RUvYDzk>IMzuTlB6 zh3q3^RYtA~Bk}ECc0HME<<0V1Hxj92tQ5Uec-@r`Bke0Jo>%>`uaRB=pt?P(S?B7i z>*Q4F>Co#sAT;lk=amFbAPi4I9gZ}tI;QIJ_4gQ$X-*8HP*VKON7^{i25h6$SRznW zcug}cL%5;RmwhFn2dEQRWF}JQUckPPNfcMNK^E&T4NZ+E=di3pugj7l-Z9eGO0R+f zwJaSlQjv4?N5_M?di6%e8|vz0)27<+y*dfJmQ?M6A)h!JpU#IA+=t^h^dw9QO3S}F z`nT-AL8?L#e-!&0V-?0f^M%e{E;zQ76X6)G*dzv4XpLo8BeUtshX>S;q-3-l)vxGv zUpkRKKA5;49KBrTqwQQT_?kD2Ww!uQWBz67lyVPY(zr4KJGOwf3S{P{?l!QHu#=(i z9V0Y=0V%(cGtO-J8v`z3C|RZU<_fQrrrpQ4#^s8X&bt#lJxmg_0syae@S1 zHC8koii<3<>?5tDKW4YwMq2AjNrkpJ-0s#^*_o~(^yTwQUTMi%)doj~aV6=%4NNE1%Jz3!BJ5k7)`4D`O z*Fy^bI9S?$DdhhP2ivR{@XPDxzd|4t*1*Wfpx_iiqf{i;$jXFO`**T`ap!_6@R*`I zlDYHzjmEOPx8~$g_yJ84VCoZ&g51Q)}>Ogjo*3bAh2Rs*-JktvWirzJqKm$Om5E4@v<`$xycV_B|p!Ho(BB2v$qp zn%+n|Q> zJrKkePsQ76LKf%$qRIafR~}i3b3)EFjd3Rti|bYMacli_5t(h?Qf}wN#+1Xi(jddz z;(z(tC4`cY4~l{1kwt@-N=1^%Z}jK@n&iePAe-1UksKv<48V6^1x-#nXWEnHCD^o2 zqV<}Ro`KZA;B=cTEehyTymcFcTThmi+=XM;`d`UO7c0VTxR0UjA6* zpk8#k5IfA&HwL?BL2C)C`Fv!#WUZ&91CRd8spXN}EOp}|FzCfOKS@(1h#ftVSrtij zFM|LFeW{0{dSVVgp2G0tx9087WGeEheX(z0!%kN~P|rK%qdTkbfe}M!_uhWZm1%6K`ljWJRE)qSp;)mK{jieUHq@H;uwF zH|USTVuQ(5{P1l9!Yoo!J^;_AgQ+qM}{ zlsuj!RecZYOn}DFnUk6Oe(8C*!CQYmCeYEBQ>WC`6w|B?S#121CQj*R6boO#C3$fj zJW9I43y&x0_kQ{ogk;(YHr5NB7+hB}fn8c8CAQAJ*Cssi>xDOEL_^=yKX=d;<)$JB z$;UjroPT|R zhEn`>`6SKnJ3~#e{x(i0ep8#pPfLgU8Iw&Zr~fvNNKith40;`~rAz$snk^c*<<~*T zZH5|?*qX3n+c#?6sKyGYSpI;J?Sd*3U3=qh-y<4epSsOv2sYI7;hWYL3 zrZ2yg36=y_x$hM&{^eI(xB{Q$ryGei%jKgg)LHPnddPZ>zPEqaOu+?EG^z)LdUrXX z5@QuxL0@a* z)BS5bBMjVg&hozT-syjmaqATeIijUN5igZ~z9o;?%VwRwU$^h_0HB{xhLKyFHq zIFEtC{Z^ z9}8~~UUG6K*S)(n( z3AVc&EZ_D|B_=)^gx_VeTn0qYTfglvc{h3v$1}RnntHHU8VSW1ok;liMm})zO%+rb zcr*8;y}CZ??N}cSh$(=(cH_$T3^HI<)nHXcuf4STzJknzDGTy6%A)Bc>!(uldrmD3 zDu0y62gPC0w-Xd0qe!C>nz2^Sz6Ttihf{vb-kzQY`qQ2i{_rXXx~BZ zLEqAoNOaaxl+_>@!eAQwX&-VXR*&+{Jh&_QZa<|Bi5jR30z z12oSw>KT?^ZTRhwUyziYm;6Zo5y}W7?R9|7{+Z_w8-&q#ezX*2sxkUmI7V7W zbt*uJDFr9_zj-AJRYV1W30|pjpqC)5(FBfp&8jr36dRiw`o`x(>pKl27dnbD3RGzp zgoM#9m17o5ClxtY=R`;)O9)Hau zPO6JwbItXwQ6txDqhKaZ_CA2PP1Sx6vNVaLYNit-Y!o&TGr}*6)rP#4osoP!onI}0 z+)l*qLp^4#+(vawlS(VXMfo#`asCyDwq(h^!J{~X!77r#s76N)-wc3t8o;nJxJuMgIopo1qCkg@~zQ@d*1f%#Q%;JMVsD) zV;ON#G(WORB2_uHxenvLQYUvxaO}Q(jCb)$K*w#tvAgS{?!f22CWJtA;Q?pfmXBiC zI$q(joC41FHGr4k{r|HBw!?wn7rxQ}72~On=7pq@d*TIhea5G0?8DKgTHTf3?)diY z*Z<_P+{DkGVujtbmT%E>QhU&D+ZH{7U7bg@+>PTdq$W&sFl6a#i-y+ZX8vlzftSB@6VzEt#yMGE|;jmJF~$2KlnhHB-4;5gcN$0VBPLC%ksk3+ID8 zZ=}g~<*`6m_bTJ zozWk9x>|b*ss_$()#ERTo zBPodcwGHJKnE{a#lLe2St0jQ{Tq!~|4vtiPq~t)8#I%vHcvG`OD860e+`)9eQpN0~ zKHjF6(4`g$Oil9qhn){QrTOqW`t^cV8#pInryO4$9S9Xg=Rsxdi8W_2F?25lMek`| zGOJ+&XkR{NrSo1RHI9Y<$Hban?4$(1_Atb_zs5l_5CThQ=LjMI%8;K=?nK z6)Ss!lLF1uIJ%r{xX#<7SAhM#UCAGK8KS{fj)+*?f`Nqh?ZaG+{6aid%Rfw4=0Whc z5q%aa-+C0oO5aKl?XwD#pq=&P!Q1cGRW6myUsZf>9%PzmsMK|d4}EMZ6fqpadnENs zI9C5Pl+W&C`HdRqLP(oH#B0UIAb(waf%T1Xm^_-umUe^3suWRo&pgt_sSCAWLtdA2 zI+JI`w{MQ%3}K@=cCz$a=&Mu)`>UKGoEtbBzf9qtS{>12axeLw8&-PekPLF5S|>*0 z17?MJEQzW?8)@eF1H!u;pX(xJEQOSV26bues%NMD7otHNFE>>ZTpf!pH^+jdbpo5E zYl9816x~nXKC}O3PPl{|!Zov=2*ph>&$Z8V_gAc6dOY25xw&#*eXxcK+e*>rXBhCw z7GNqJWKA_EPh}_c4$N{9H$1%`-b|43O$Ff-yI!j_oCf*&%tK#z;c@?rcb}vld1C^< z`g~fzldnd3(;=ge-te;X^?(0=tKNF>fOV77C${Vv*q zr|v4o%dCWQ-4G4IFB)QBZPN{CpwMxvy`Iq*l?w=H0(eAcTO&s@QQY%hyI+L+>81tA{id-%audbA(`8xYJDZ6F0;@qE27`_4(8# ziCB@1fqP&ZsoIU9vFsrbj&qKHG0&( zF@uk4I07NLIpV&8tCM|TWxbr;Vza|)^OK)x*5VLF=-$EoK!nsm?d9gj)%w(e>qGfc z#iIQeM@&ADn!s-Jj6IYCUl^i^uo}2EI?W zC)itC=g!I(tz@@$;hwP-jgK|QKP7J5uldAbqA3pTI(Ecv76=my60T1sDL30{CXt3< zcan+Gs1U1C-?d_XPSdu&(g?Ze5+iaOK%+z*+xhWa6-|rMznp zSULG?_&9Bt6X9~7_CJGCEl{@B^Ka)I@VH&~n^L7Cv2WE(-qm;4feNmF&|vJS>=xi{ z4iP@q@D;)inUX&5bVL|>+$n zSg-^g`x$)&9s|0OrfIX9vNae*>QK}ti|c%_?1q%o6PV-lnZ+G*!jx#T)flFWeKO6Jew@N}Ci^EJ*q zuXZ0+FQ>hsphE0~XCL-QOjI+RbLT&X3UO8yBi@6QhR^r-P=Mu^$QU@OI=l*Vs#E~M zAdX*!ZGXEJy<6FF#e6f<@~t1zVEo~@x^$3vh@YmvyUgqh%bukWYWx*f;s z9^c)KbQ|vJ8Ggle&L8jL8lbLANL*zm#-2%d82Gp*WSnlBiVVYnrpbO1vB`IoYfDJl zt50i9mPF#TIkwm|6p<1Dc?X2=-{xQ1o#vpqJo&dZuf9~G*tguKXH1%B>Wa0~p0q8Z zol7;vdh1r)31b3jE%x(oclm54v_1CklCHQFv1S`bwlf;D&wu-WDZ;twSFj2F25Ojd zp}f&$3;4j$Mz`zeb&+-RM8_J|2|3#ceBa&*t{2SkzNEt}p2W(tYx^;qM3O&ZcC2sT z2=?yMcm%p6UgUf%o;MyJ{8B?FNGbQq@5=1b^743)bF|&T2#?zX>Vl5) zgLg3;&vm@}P`$3rzITPu2nO0&IZHQps-RnldtBZ)+ThrhiJjxi-O0|gg8dio<{WJc zsS{P-C%v$2gG;2YJR8yJ%^E>z-bw-z33M&J_MDRlAd|C4qTBW zApc6+{lu?p!G#^=p?$9pqt!1fVK0v8KU-9CL@wLyuQRTEAGt-m(2r_^PcfwNoV+JA zc;JKrxzR}D9|N^N#N#l}?hn`%OsXQM7`>b*3nRA{G+^~y)6>&0J69?=uqbtCdi95*)#0Kru!tWDnT%SsSi|e;Z6r0*bVl&`<@>*MIvBc<*vhU_As6ZkhU)V)k9Uv}b6e}x{P#%gfk3s2{T8=uf zYnoE@JE0_{`i>ca)kunAZc+C!3^-w;+_8q9r*$&vtbElyoRVMo zJ>lk(@oDq%NZcXC6Uy#x>a7XjP?$UY_HM^D3Hj(L#`}=&Q!xZcY`SX_nSp)wmH1O= z^3T~?g^=c9r%VhNSYcTnrkyA|69=gE_W%f?DC@H34?yi+6+NO_G$C6PyQU%18XG17 zA(ET+>KpISt^1~_n3vKHH^l+J)(9{65|QQpqToE|T~AHit87VS0U%ffUvwm5a7x?c z@A>@QOeKZKf>Pvqbq>9{YWUXUp4iKf7rn?I{p9Iy96=Qcm?-xEMEPbT+7j27r$>4B zUtBM^(${>+B533UhM6I-?s?8)t5 zAxPx9OS)ui93oCkV9GCPTh674O3>qojo96%F|aQ> z!Y$N-4uXe7z`cPboDBye0k6AGVF>^^e!_jE61>FgpTe%zcr)9$qe-0)>$=`za}U4m zsj&GX-ip7))z+Sl3NPY_+FhmH`33>+Lup$D0wKw}a1#fFDDnoYCUn4rL+#zX*|5Eqd|Q-M7&F51*DLcoO5UA^wV%RR77U1n z6o>qnJ?lW{py++00TXb zY~1sQv#&WV@|A7#=K3PqZKwMOXfFp=2TO=DByUiDO&#>KR_U5DQ)Zf3Ula^%48jaP z#MR1x3wlA;(s;yn<|6bK_o|DHE;iYRDu)h4_b8x7C)xoo$h+Fv!c0e^(HZ2A${-IS z(#+r}q_Bfo&%}~cmZTMVCc|$k-#V^)65AUNJ&*t7ZbZ}m*%-X%NP$iz+#xrC&(O?{9rL(r9cTYuQO$G)R~e4g15 z+_USz{RFu|sIa>>t}?8)@EFv&@g0!xclvB$xu30!cDUo^=gyMe@|V`tn|-31RWkP| zlqN}jew4ZE`~|0Cg}Ce$nM3oTfL`OFT%&_zTq2^LCHi|KSOpc-yLLt4Hx7 z(g6U7HE2)+8WQ0}id6~`jCss{FLl5+UOr7-lfVJenjrAPRPcjS_s`plCuWM>l}{~1 z!@qUv!5%{}qT$MZ6`<)-poK2vJg=wDkGJn}m!|tf3*n%cE(0#oi+p2rCy1P-!x9j@ zRh*d|TaJ4uz#19L)SwDteL*9Q#lU&2Uv%OSf%)JD9malXe>YbQ3{28r3l#X1jKdIv zIKf7$LSVfksrkd{N<)BiG!~1O?b-s1wJM11?H(C^c0G7w2KTjq{*4g67NQO$j#i+y zh*vasd832u;{8-r`qxHVJ%isJ(HzI61y=>wt{+-MPiG!O8fMg;^q#u`rw{RGV|RDf za|5g@C=U@%jc81|_sK+`HZ=q#9qVT+@|hl`cnCQ-KTKp`{ALLASpeyzmDYs~i>R5f z^Q*3KI~@I(m(E3V{%wwY*Xs-*R3y-Rve+O-RW>W|tFgUms)b^#P>>Nq4qrY0-72}o z!_0C`84yYLV=lsDROpD;eNv~OwHl2$-KtW5=aAe_D8`rRVQwr%1~nD^M6UvK&lqj& zcE{i>Wj`*JHWi&`q;y3x%$uU{haMJZYAsaQVMhIrT-v;iTicb>3=HUS?0y*rmyrbksgE#hGAhI?) zDvIMjtT}v;-59GM+2OD0>$?Cm;({5nHIcS6(!t+0)X1bk+vY#k5HAoIk@d z=Mi|&T^#xjaY*;&;a;G+opU}KS3a;Y(4n4xT%Q0C+FZe?bfN*O7jjQ@X*@pLU z@$Nl97|?Mqz+CCIV(`@#X3x{6;L$W{7C06PR^gi?EgP-`z}UgF_hj6|VbnLjY&?Sb zjiR%!I2Z!X2>DDL>9{t|fMTIK?#$yw^Sn6;jB-m`MRZ-oDee_y-{btjCPm~2N56AA zT@ddXA&AWsCuNCM4@)ADC2e7diY9wWuzPHxFxb$JPCn|QS5_v75gyvHJm3Es%vaxwHWKCa&J25@WE7v7A(_mqa>S+WQkQnQRa z-0|e7#5|AV09McIt+|x(s^K5n*C4W@z!E#kEv6f5lLY@$92E&RJAY^%SBD+syGLnd zt8FAwK^{XG$g+4l8O^eqw(7XrNV8n{>*Nl2_sbZEcS#NMV!4O8wVP*j98c}y$`Ko5 zGPX1%pI-I0fq5`C3l|7fQ|}?NTmTsXgt<{$NJp)C?Yy(hy2O`uq&BF26y2Pso(R&hHRz6PRIxtxMxS`D9GjfdnkYT@N^#w$5+4eH{(6HAVw=TUhaGEY zF3646^(J}Hen7sE|4oPWIP(zx^oJASYB{JOwamC8s?Uy$$HXO?7>?!57Ol~gRw8ty zpaYbPiQDlFRJPE_Q}>$BuqkFL9NUf;m4_;-*!|(k7s0+}B%?BEbd#ZGABN+5$3@Z{ z{r5w)9v{dof09jBF*6fqe2u{ag?rnB%^}z&tfe1u(V3e8{_p`HEO!+FtepjvH(Pyd z4h`?;_x1Sn>@vP$hpNL2{D&(E2y0oAkSUV11J3p0%-$=41nlC&HjCwNXYiL2UR&fp4J~h zOznj^%+l;eC=krwK@lq~cu@htWI^F}@du-yfFxT`hM!y=b)p51N$y}aW81D{z{!;a z*T$s&=yLtIMS`U&pwuafWO^PhgJ+c>JUr;zmQD`S5-wBaO5z>X*4MZlG$6}3#_>;# z-a>Zk8lsk{Sk@k9JmMu?5A{IQ3lPIn}66=6Z>Q{mJA$9F@KB zn*lvRP6W613Hi@-9Gef7M(W&#HS+Cjb{zpnzh6n+cD1%7n<>)i|Ku60!kEeKc~YIa z;@3h4af!@nZC`(hGO_9*XUs$slSW@k$< z6k~)+%#IDLmEj5j(FLinEX#)|B(&`;zz7CTl0o(@5L~!ZVi24seJ_Pa!#TWQT|vJw zZvAN7ypioO!(tqDQ6KneR;0T%R1qG{A?ikdn#T(x_FCG=kg(1%nRZscd2He19XQ$0RgJf3h2;8geZ0>lHEWL z)5i64NAOKLQWz3V#>y?&=O@9Zeja08KU1tE1KH$ zg;kt{ze%Y=6{(+a0@!yUfuig3GnvN1-Di&)F0FY0s-BF>XM+ddsOdQwKQ|c7873ub zT?O0Lw*rTVSHirHnzML5!jOmFrFh76TC!}6or8LjaFSHDJ0#ix$Xd$5jrX500Edo~z537YPht2_M4vH9E$u$@kwdW+=LEZZ{ zm4+Yqv|b$j_-hTSwh#{x(X@AF?Xas?qE;jxMh9FM0Ksxw!pwTwoyIXFj8n`l!;|eK z?K@oq6bFEQI`RM`RVe5-4f9{URxN2(>Tl}1Me$l>Et33+B#Qj*5oLbf^ACBj zxY<&oLW|%z1+txJ2JEq-2%L0ni}jcgYE7&Yc`;XwDl;?N-F{Tp7Wk|%W|IH7)`LD= zVgZge{9LRVG_J7hN@#<{!RoB4TNo-;QjO=D&{Or5T!s_}g+r=w@t9<>0zeQ$xrCK` zBurs&lozqjCH5#cY{X6EXzC0)2=w>C>kO(|u*Suexn-yo*8K=90AA{d+^a&K;hz67 zzaEL%p@r;GRZYB$ogw~7?n&OR^)i@x`CdQEZ)a;NL5b%UI{USGAQ$T=?G-QKR@57~ zurZmZnH|CXOp@BW@F9i}2$*tgMS>N(-*K3O4egXicZI$`jxA^H)VI0Y8`)7rG+h=~ zHVR#inhIUWB*P3{Tv<8ifVB@GgYFn%7ljKix{g)T1) zM#zt{=qwr-@RYvF96t`ZX+F&4-lW`-woX7m@T8+i=nRk^Y~^!6{KV!4Q;^NP>pFeGMdW@{jpySGT2PcR5MXDaC;U8&d=7hSeWLub<~3d$x`KQd zM!ek&ATD(;q9H#t!n7aDYOpqUGwg$#{OuV7s=9x)8UaOFC-OxmFu3!Q)+Y@+<8poX@GQq)U552^PRZ&3+<254#~jQ8Ak1 zTETPxNmrp3Jb0~kAxLPRF-JMcUc4MPj#Y+X3!_g!o+Wq52>V4hT~*||4+8`Hqy^n) zhnz2)T7%c>cs%o4-K#}w&0@}R!Ks+D1;DN&X;<0Hsb9Uzqqpn|wQ}33)uy+_;;QZb z^@3T;8YRa1$!=``FMokS=Z~d_@eMy1NUv3piw-JY)dZgpfKpm+Yh?x-USR;|=$qlt1;fjF7DZw4IFcZw{gPx4%x$j-7qWJ2xmhp@^U>AP3^U z{3%#SMln2?`r2Ucq03+#f$6d?ryhVhc{+eAy9w`^mDSE24$Ue3u9aL~e8^LW5=86!C^Xwh_gy zHZJkoCs4=(R=(*~e3cvg>CPUDIwq>&nrz=`>|ti!47RhQ!()#GHz;2=fSz_9{j9wX zbUH&SLntV@3J8*<#*4|xD?D8WfU)hBdq zo+iiPPxEg&Gb!{>lsO{uY?>c~NDeA=XONe#M%h-uR;7pxd`Jvw@Is6rZ5DC^4Ul-@ zwU@U0JR5xDI&`J`5#4cd1VPVzD9i5LoAfSwq$IC+`Oqm%|IO|PD7Q9gQy4hYDzvPR zwMUb~*mRCF$WlA_jv?bT&Q^%ZP!p|E)DF8k7W^BTKqIEN^V>Jp`{Mx zesW}Ydz&(YKZ?1X`0cgWTKtswJ@}cQLVuc)io^rtW`6vvmqM$n(`m+FGrU+uXWN|Rr>w=`9YZxrVjt#^kg&{j}pd{1_NKNKQeE+0Pw`WJq3|?&(L<_b3Lo*fcb~JdF5^o(1hx$H7BzF z8E9XI-^91M^15`Gng&~kg2}s@A;egk(9{>;2Py=F$H#smy9ERUF@)c8)q_-Y-;a|Q zJtO;r`|K+Fq(+LgJ*6|+hBjQ?OZPJ26s#a|ae`vsC%j_OpSk1dFG)OXD#)Y>!%01k zsGn$?Z27dFZHXLu+?qI>xXkFTGz|>0)U_;ooLzb!{qWG+3rVVavXQJAZV=R-Ur2A;=hpa;>b!^)0l6ljH29}&aYJ6j(fLzY|=Y)Sg5}d3ijJT8J zDZ z4$7&~g5SGQrm{cbtVUm*EF{zV=vq^FY|fsYt;wg9jeyL~_~-EZQA$wD`BI=F#uvoi zd=!7h+~xQykOU>syyBROTLUgHkrf7ZQ-hC7v>?R>_@Ln@Q)7h^@1_k9Q{W6dN%q&y ze@zJllo*s5a3%tz5CLMM^7G0cKVU~i(S*3v8UQjuRmF^loA15b;Uj3oW)i$5X(^9@oAhUc*XFub?AEoTjVajr|~>P z1c0tk)OQ-A*W?ccGyXi-harAfWBdkt5w2XQKwI7`xj&{j{U{vE&_hD01vLSYo;bZ!RiIg|+=w^FYqjw3xyp3bB__y=(6gB=QM@4uOoJcuc8b7*#s zJS^fD9&Yd|*Jz*5x^2Gw>PZrqj+aT@agQGnBL1ukj7s2@nuRpj&Y7k0!B;%gV3C$) zPdNB%|m!%F$AbNx4j!Ra9wSREq(M@nFZ?!q0%Ghf!q$V}tH*JHWisMt<)NeG?( zHE1r9R*Ks867W~yX0Oba5~u{DBSEiRJTr-Xci)VfW4x{A4sloD>oaUI7&Q7z6G-h> zN_V^o<9B<=Vr)35IV$K3`>?I$dyj~gANPd(lfL%#XPOb)>uNFfsTS7 z>0+zAuUEH!)*&g2=xY0vOVv1fW__4Y<-JPQ-+J=%rYDDg z%|CQt2v~~7^H>I9%idL@fhF(obrs<2ONj{T$S6fzWz)5 z6(vT5g5>usl-P4lR86+vBWF5RG|o`Xdzj{T$$IiVZz+*LlC#I8ZiPwAJ+UVX_)dsq zAFCbTy8aZ&j&T6{FV5jke5ep-?ZDwm#0u`Wl>U&j4DZ7Q_=YHyqt5c$u?>?`x4kKc zr)VrkwG@V}ll4&OK8_(F<0BZC8pAV`c<{5=i^8%CL!2lWnGAYgz_1+_K634>3U zgV%cb>c!r(eW+!jyzfsYC3;k(Cz;InhBMYv?4B|Ys8j5~5uK!R+#==GXOUf2NBiOx zLVqqu;5%^y6{NSc7_3a+Ej2Y%q<^Afk#M6+sc)oPxgfDJwsMzEZnu7QyC_mEc!e0u zsMC3K5UBE^)se3@2|T8ZvITah?)q`uQM+c(C0fYym6TY5AXw|a-wGi_(>}i|TZpu# zfpy5t7JR`q_KU-!#U_4r2k66xg$prmMG;h@2nxBa?XfQxoqDhUK>58+Vr}==pczE2 z;7``U-Ai+o);;X|HSj?*CNiqsXYN-2{}?+4lrL+UFFsO7A!+6;OPdh@+x(q&nDd`* zV8$b(`ZtHIvGh?+smVpoK~&*feyg2oN+w*QJ^aE~K-?))4!SC9RVPhfX>7<9*yY$5 zYqfH|$L7y{1@URVzt{&0R4r*p!^Qi+_O+k{5~FnQSy65Em%&cD)<)M7TbV$+3y`X* zY7^2R&q`M;A*fc@W3M*LW~aI>La5wdvp0I0?O9uNo$I?k^Zu9Wb;JMF#xW*JW5@E- z(0s8M;s%M?Pox3rUS9$7$;V@O8&Z{(r7w70B^dGnWP<610MO_0i^>^sLKP)9vm@%R zsQ#N`$W;%cBl&VI#Ravry1$~qeYcwT->P3Cj&@RC~mQzwJ6{gxH2I5x42qv4h@}8p| z+37X<-oX026|BxK>F+gHKpu?Ak;k(ju!n_8)TQnpj0tn8K6x^rW`*eB^cE#?eh0Us zM3CtDa_KE0q{;q{@y`sF+7I_>D8|b?IUU_r-mrtO-yNvee?X-P-9asK7hw1@}zj!Gn#z zG~aL*l>w6O%knwF@5!2Ac^)Z5^)J|Ue>Lcc>US;g>xBBg_AecV7?K0BAHOwX3K?~I z5aO&t{VeHb(G*(E-&>ZmG^nr561tp}5{$!B*@iT%cz3hbe{Ou#jxxMgdB1MHo6 z9YF53-yZ|n-WbCgjte5*2T<|>VlbOersnN$X1C?qTD^?du6~(26)Fq^H>XVXuM)ns zIabEad8e>#g6}V@H|0@DZrUAy42~xMme+;iC(~rjS<(kHDTZH*-Z+(6UkrdvBU+p{~v6UjPuW_d02EBCwk?hu(M|EnTRibaQ#X zzGT0umz`%usg1<66mSJ$C4+#cqIm$bR&@9=gYMu9aA<07KzC;|HD{1xYO zZzQF$#GocvNp#bd!k2?#r0tDbYwBgmC#TYx0hW@_@s+N|uYD3L(f~}D#u$v#!4lEf z;Dh^m$>S~;Pl}q^=7VVLW;LGN?jlT-6Kw}80&~!(vE!6R<~!mM91oWok(-N{bs=~+ z2U|j?`aI7z_Gl^^J<@iiLaBk3pT@X5S;S?p^x-mgM3fI}$H}LqnDTOIgH<4!mYu9${aeC=6RuaMn{M6QJ*)DZsA#BWn=j zN8$m1%4x}Yu0AF4JH!uH&3@dT-Pfz$-DkbiM-7h#4L3J!NuhH-M~lW+`M-!T;odK95~cMw0)mgR?Br}- z?&I#y;r#i3C6a!77!x|aUa&>%=Z<%r4i^%>;XLZv4QrI*GjFg+o`@IU8OGv#dRe2j z@DS8|Y9IgA_dVkZGCGfaEKGIr#V9owKaPosBlEG)e zFH{%^_5&v}&{kCxFPWQeMzVoZa~glJ|0GI(7|Qv{nw-xw6cTYQ^L~a;kRd)*=zJcj z<$8K8P9~Z|P|vrft|^062?;8$vV;08T%HeaHolK{dS?#hcvoltc84-QNwL0;6gU@y zDm1j>iJkzf>NOFMvTAC0?B7|GG$a>S>(g4jgW@-8V0VG(H!iHr#MesU)l|zNXPfD&jwcBzdlig7#^G=g zVQIbAF%C^=rKqMizox^5n(>IPPnLRzi={Qm-i&+_mHUb}kTnH#AYd@_!pP^u%@k6- zJ8nGF=P*wMYK5#3gxu-zE<0vb9@sMdasK%zk+Fp|sL3Vpv>Xfoy%60R93M2sMn{6o zWzckP-cq#!mmPky8v=mP58CQ**Z6qE z5ut;aoiac3>wT$fGpS;8@8l>wPMzknL(9%b@VnOw$;&pJKBrUUfZBMJV0w zUN+nfSXho!$WYLdm9$wWLUZRIY510%^J;K@UX4xogt*~}fNa8r>fI8j@p6&ckyqEH zh&$>#ou08Luy@0*k&0s+zPQT|AqLFvtUr2c1!<-hXRznu$8A0>4OkBe=Z+>j^65 zH`=8~B}D+2Lj5twP)Ia0b@cFaw=Y_=@z|)q=A%_{SFHTyAvZ0H@X3u0ntt-IM?(N-pG>6U5$pzpm|$c2bzF_H>HL&Ba)_<2+MO20TTsRgx7SKpW4Z^O7o zdLqQg3A4BHRQ_JkHxAkaiL^;4k|+rfF9>Wd<*-voVp(SmSHf?(_3lLh=4?-dWz+j@ z-%KpkRlV&g$r^6Fgi_ST-Cxe}R3x`8-MKUzP`S+C)z|kav4X?@Nc`W^_$6a;qI@HH z^C_|6j=!!<#mnyv{~Za=uhO48k)m6+nl1-5@?Ti>KfXakQ$R%$>I!hGmv#BfC+Evg zvvCu2tzy)p%UsrasbAOMdhd>O!Zo(#L*s7PfY_`r7lZJ1WaRX$H=*75LQNg>_fVeP z0Ye~b;Pn80E4yEWBS%=}MiF-bmd)+%C#<|M^Da#zNrJf#Sc!r*rGD8CU%XO@K>5>} zBsAd5k9-qbTf{^VTAQ}BR%xEQ6BUKII{_hTpbdDgRN*GAan@m*S-980fc=lUhL|9V zIXn0ckrl1(gc`@&=SLipdU}_y&3vp6-Y-q1Ek8i0Q8cnzn~JlLuxZWC^Hteaf(6;PgVF7{4;P|IGwwW$_x>46RQVXN}_baP*NamUDdBgwJb!R((XTLi^ zzs5+K#9PYf?$=WVDSx+mm+=ORr^bKcQ5oteTcHSN%c#K-v|20HZSyZZBcE<*DUM?J zmh)2cYe-}NU?BqGBZumQ<_D4$3yPspdPkvlfgzrGIt~GMXGz<|hw>;h={EKK{uW~I zzmYrpw`5_dXL|6^3tiIii*xBpPU5M+T6NfMGA#pJe*ijA5d}+IAIgZoECEbg5ducF zoRf0)QAZN%(CS3!&+V3lT`C^3()!J#B_30$3#X8R1@t}53V*o#qGwH(J_6svDsNV6 z!w&EblvXl0^3uK1Hl=|N>u8jWUbpA9E&;mk*Hp%PMP;+C1WZ&mh-{uLzrdZi@k6}0 z{vWBiAK@n=pq_?{DJ$sB!>_Dh1tX)DxAi*Ujtx9Aw}?R%$YMKbw|!MOUwLiewe8yL z{+7|UhvP=y*a*SGMSkze>Y?U8<~*ki3Q76ey+WswXz!K_|6mJXht2ICkG7woei?_- zF%id+3&9zYCT3xB?Ur-KvPw;kWelEhvLz@s%o+0`qVaXO z`q%7D#G+YHN1$^*T`O6&u4kc@YE*c@%1`CNlEB71j43x~n<*;`u5Z)oEEHY;Qgbb` z0lOWT(!Qhp6<(pZHG`I(GhZ{4`Bh49V4pRlPjGV&%C_GKA$tsVI+pdKB1VZjG9ew= zp7KH@7PVoIT$XwCY|?mM?|EoEi|?)Uq7hcvAQa~dqS z0-buq zi^ba(?F65@>~1pB)1WZwzL{I{xad+HnOk^?f^Ub}>$uYD(LbgAKx@cv_Y-Qs6QD33 zc(R?$gMVO1HP<7OK>ZQ#p{=FkczgIu{Dg}J<1X2SK5Sb19p}w04G9;_GA^7RO5S zb3Ybg8_YVbi-RYmk{fPJ46b>AS?kKpK+BjTf;7H9tK8;O9aH!~{ zUAEGA`?uCQ7pAEktkmZ!rd#hrp;ZU1DMJ*hyeSpUn-Tq+CD}_V_v_C8O3C43YJCjH zFoYC+(CM2$`u)4EK@P8=+dI}r{_AZ2KX{ip+~T%4m{XJJk3Ap0iF}7Ud8kL=!u~iw z{nmfrz@0oM@fnN$t3G4@yL$g?RpgI8!GXDa8hG2J9iP&A?X4C^a4RVg?<#x$Xg#x`7#G^QKc z<1O4fSwDI)P*K$VV-g7V6wjzddWVi4ey{O;qS|b-Q`#W^6 zkobKPgd<_!u2<`;B21L}dWaV)3yq62vm$D53l2`>cy|%1LgoE=n+ko}{q*IS{mpJ1 zg{d+mXN^VhQ~4+Mrgz!NP!-7JQEN)}Q6q~`rY1)VYf$>5kPb%!9L?e`ZTylga?jnT zqS(a1a?ll_qm-S)fImjEuaWGDw&;aTbk2XVUbo zauAAcM|`pk7M;H7o(9%{4|CK_!O7SVf5M8~%+_?E0aQ7}G7tGq^p%8qA6sAl9o4VL8j zCxp+Vxc4`7L-0A`YRPKVn}W_KH5Bd%LeP63%M!B7JD$X;9lqY#GWuNCX>MgXW9U%e zamWwR+Jou9uGYuO7i*1+EE?CTVwO!(D%}KH&O)fN?P}B%vo+jxof?NIf#Rlz%fiRD zGYtRps{36>iCLj0YFUiAEVIR^7KI==Dyuea+;7bK%W9mvjf)0IsQR39oXQI$hKI>l z1?sRknX(HB2p;%Z4E=0VE{2RPTksL-a9;ssDwe>dZW0@Va^JBRU_GU#!jjq`RX~Hs$4PI zKyyEH(WzqY7*hguS(;XUkH?GYk;VcJh0b8Ix0Up%O!X8dk-|Nvn?5I4W;eGKRa8%R zC9{HcU7{P&Da-F27MP_GO@3@A-M-t{TYvID%MtiaD#HRLkJ-f$a#mC%wpHw3Y0}$(QCcX~hPds2C%1O+N>-a$>EP8DmPp~^()}pcrGiqJb zvXI{kz@u;5N><@>D%`Z81A79btvseCG_sFl)1~%$Y!+ERHS)9_x{sar(N&dY$qv6_ zakq3H5j%crl~+D0p#n57sGa`mLWR?vcG|T7nW%Fg>AHW*W_!>G*}L!dmMs0YWQ4k% zJ#mi&ql3+lc7mP0kDYzFL;Zork<)trcB80_AqUae_K0|)&2HJ81Nb2a``opt(WmK_ zD}o4ywE(aaWsh6y{Q|ulS3YlkoG8`SD9&7tfeikq5*kXd^8pDvcAj8`*6XOH!rENO zm&+*IDWj2Vj~e-<*ZqacV@QD2bL7U{$L1-Ml~wdXF!h_dT@w|b4FdJtp%ASNla?HD zF=CzkA$FetQD6l2j3X$j;Z(jKmvqMzFM;br+vc~|^O0Xd#N)LjC8l%BgF!!y&p(?9 zU)I}N?1l5udyIvJ4cgD!*c_?^#cAN4-D0J_gif!=&l7^w>hj*DVsvwDJL;+5Bi<_P zwLLm1&ha5pb1yqq;pEZ@I-&-Q@4w8G+A`LpBtjpW*5%kuv8lA^M;l2r4S`}EIFF%n z)vZU+GUJX<>jDO|m^UQ~1MYg9&}O)Z;`QdbvWMhOOJpcRWJT`-E>5c{`G8u({7mFv zG8mz9)VUYzn!)n9l?3@#-5m29Yd%<3e^Z8<$Ih`=;3Sfqf>$8{Ur|Eu}I=?+f-3C9{z>H;{^Fyw;OU za}4IK-hGqy9(fU%0Vvx2!Q%9q6{4#fbC9-~UL~8wpg!SmVjY#2Hpd&VUNx;JUQWGn zjGCCX++kj%aIfd_mMt$CXIc+JRc6VOKf1&KP;kCFu07a|zw04WI3rTcKCVhfy|q)M zaL&&zYf;x?Ct)fHp=7@3C1=|ez3;!QOXL2i^)|fH82GHJmz>UNM2PTvxL55rGLDiE z=#P&2ol<{4pQCU!8%m<++q%oe!(JwGxTmZhTl!FfE_?KCCIBUGw;=EPA}#Uzyu(S2 zl7if(qv$(gZQ1U&9A1hIw11M8M8%9=xJ6v5@?`lYag|4W`S*D%7qh7q1YU#*(S>km z831?Ra+zm3&}Ze|7vI%={`~xPjQhhib-9?tqDc}9kL=~?ZGf*WcnfE*x!8&r>;4u} z4A5hJIE-=@kRM zl{Ic+FU^>88@nhTE0;7^lKYvWnT`XFsOj1(6juLVU0H8#k`8VreaYc?^t?3=t?LaD zJ*y-z1$d6ORUS{1s8A4spPxG+nGncGn{o$YGMQEVfQdys_rzzU`{_f&OMnySYv*sD zz7mMCqyY-!TYAEIv5)klmE2kI+1S=Ou%!y&hK{UZU!6W z;AKACzCGr|n*R79s#7)Nu)!4dPRITobAwCPx3K!G2>WhD617h15||4X_UoqLS%s_n zrdz%Ur*tp+d)U0`kuuQS{m!nx41j|3%I+(={<3El-ffS($$3LG6pz5hK)C3tu3GgL zwi(E7_rD}Vu%|?Z3`Y4CISKZF7M?mZez>AgH6iUL0Pl%1I+E*(9BWLFu)fj7F{Wvi zR=0iAKJ!`w361`nt4VR?n}^%UJ-e#x#~Z+Y&yKrlxbj>+H_f+lyK`LyAUxEPpfZ`akkS8 zXH6xWm9^S)ikYU+aBFY`lqYA}Ts>f`KI#fXB~~W?@}0W9;6A>{#&IN_&gBiMbpX$H zvZ#W0R`_7y_lC76{W@<%7APL9E2Pm!aBe`T(=jFHz^nMP5eWsI@tXen8-`>yU=L`);e`&QxD%L4a%l7b}ww#wX-YB-MRrN_P?*n%r zVG$Hp&JrqPLwFXQ>Ne^YUKt`f2pVXPP`D>HP)-RK!sHhqUohi;+|40dvU&9`=XfjE z#M7*L=J$=*G>0vk?wz-Pyd0H8sxwDO;G2Z+_<=PiL??F{ny{b1+e`D?(Zsejw zl~_&b^(~C(!_w^6b5a(q!47EUXXDajzlTef1|QQAA=OvgKPb+L)n_cqV($c?GfuG| ziV8gx1H)WH6)!T5OTKn@R&y-a*m8^<`1pRBRN3|Bh`WpTtW#`LV*iJoAr^@bvL$dp zu8hYdL_XO}CBv>ZIPec`r-EqOv>7>IMKOq!gH=brJt5H0AG;%~7vL>@TEDrv>j7P% z(X-eD#G+}p9{YMcLsRuWO~=0_W))Q)dj+p;fppLbqQML#-~tOplQk(8v|qD#+oCdT zgcW(mMW^o$4)Bm|CnvLg2=cxx#E@0DRt+OP!T{VI>UEPs{+?I#I7)3W1e{ z&f1hoS@eo%#ONoBXf@sw_X=z=$+Q8Ix+6M;r49lZ5jJ&$IU>yuS`EFFv4izk^d56& zeqa?S6N-JJ(AQv0-UFi+JyG7ifMbP9Uo{r6P(p|1Q43Y-W9Gfpj5|xgxL+eCxNaG9 z3;G#-yl%mA3h%sTm#gO4j#yLX23PrAc|Q16!4$G+J5SX^l;{jⅇmNvEnx7^@q0( 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 literal 0 HcmV?d00001 diff --git a/docs/en/_images/react-di-3.png b/docs/en/_images/react-di-3.png new file mode 100644 index 0000000000000000000000000000000000000000..ee975b0bf6c6f9bafe27348ffe2c88b425d48b26 GIT binary patch literal 36116 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

1Tm^Lp$e4g(*#oA(}2xZ1c{BA+Y47d=Q0d? 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 Date: Thu, 25 May 2017 15:55:28 +1200 Subject: [PATCH 2/2] update docs with new api --- .../How_Tos/Extend_CMS_Interface.md | 241 +++++++++++++----- 1 file changed, 172 insertions(+), 69 deletions(-) diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md index d84c287eb..ab3611446 100644 --- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md +++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Extend_CMS_Interface.md @@ -245,18 +245,56 @@ only partially implmented in modern browsers. Because it doesn't yet enjoy vast it has to be [transpiled](https://www.stevefenton.co.uk/2012/11/compiling-vs-transpiling/) in order to work in a browser. This transpiling can be done using a variety of toolchains, but the basic principle is that a browser-ready, ES5 version of your code is generated in your dev - environment as part of your workflow. Often called a "bundle," you should rarely have - to see this file. It is effectively an invisible layer that translates modern ES6 - code into something a browser can parse. As browsers evolve, this step will become less - necessary. (Although, it is worth noting that because transpiling comes at such a low cost, - and browsers are relatively slow to catch up, we'll probably be using it for the - foreseeable future in order to adopt new features beyond ES6). + environment as part of your workflow. As stated above, there are many ways to solve the problem of transpiling. The toolchain we use in core SilverStripe modules includes: * [Babel](http://babeljs.io) (ES6 transpiler) * [Webpack](http://webpack.js.org) (Module bundler) - + +### Using dependencies within your component + +If your component has dependencies, you can add them via the injector using the `inject()` +higher order component. The function accepts the following arguments: + +```js +inject(Component, [dependencies], mapDependenciesToProps) +``` +* **Component** The component definition to inject into +* **[dependencies]**: An array of dependencies (or a string, if just one) +* **mapDependenciesToProps**: (optional) All depdencies are passed into this function as params. The function +is expected to return a map of props to dependencies. If this parameter is not specified, +the prop names and the service names will mirror each other. + +__my-module/js/components/Gallery.js__ +```js +import React from 'react'; +import { inject } from 'lib/Injector'; + +class Gallery extends React.Component { + render() { + const { SearchComponent, ItemComponent } = this.props; + return ( +

+ + {this.props.items.map(item => ( + + ))} +
+ ); + } +} + +export default inject( + Gallery, + ['GalleryItem', 'SearchBar'], + (GalleryItem, SearchBar) => ({ + ItemComponent: GalleryItem, + SearchComponent: SearchBar + }) + ); +``` + ### Customising React components React components can be customised in a similar way to PHP classes, using a dependency @@ -271,7 +309,7 @@ Using our example above, let's create a customised `PhotoItem` that allows a bad perhaps indicating that it is new to the gallery. ```js -const enhancePhoto = (PhotoItem) => (props) { +const enhancedPhoto = (PhotoItem) => (props) => { const badge = props.isNew ?
New!
: null; @@ -293,7 +331,7 @@ Alternatively, this component could be expressed with an ES6 class, rather than function. ```js -const enhancePhoto = (PhotoItem) => { +const enhancedPhoto = (PhotoItem) => { return class EnhancedPhotoItem extends React.Component { render() { const badge = this.props.isNew ? @@ -345,25 +383,20 @@ __my-module/js/main.js__ import Injector from 'lib/Injector'; import CharacterCounter from './components/CharacterCounter'; -Injector.update( - { - name: 'my-module', - }, - wrap => { - wrap('TextField', CharacterCounter); - } -); +Injector.transform('my-transformation', (update) => { + update('TextField', CharacterCounter); +}); ``` -Much like the configuration layer, we need to specify a name for this mutation. This +Much like the configuration layer, we need to specify a name for this transformation. This will help other modules negotiate their priority over the injector in relation to yours. -The second parameter of the `update` argument is a callback which receives a `wrap()` function +The second parameter of the `transform` argument is a callback which receives a `update()` function that allows you to mutate the DI container with a wrapper for the component. Remember, this function does not _replace_ the component -- it enhances it with new functionality. -The last thing we'll have to do is make sure this script gets loaded into the admin -page. +The last thing we'll have to do is transpile our code and load the resulting bundle file +into the admin page. __my-module/\_config/config.yml__ @@ -413,21 +446,15 @@ __my-module/js/main.js__ import Injector from 'lib/Injector'; import TextLengthChecker from './components/TextLengthChecker'; -Injector.update( - { - name: 'my-other-module', - }, - wrap => { - wrap('TextField', TextLengthChecker); - } -); +Injector.transform('my-other-transformation', (update) => { + update('TextField', TextLengthChecker); +}); ``` Now, both components have applied themselves to the textfield. ![](../../../_images/react-di-2.png) - ##### Getting multiple customisations to work together Both these enhancements are nice, but what would be even better is if they could @@ -465,35 +492,116 @@ Now, when we apply this customisation, we need to be sure it loads _after_ the l checker in the middleware chain, as it relies on the prop `limit`. We can do that by specifying priority using `before` and `after` metadata to the customisation. -__my-module/js/main.js__ +For this example, we'll imagine these two enhancements come from different modules. + +__module-a/js/main.js__ ```js import Injector from 'lib/Injector'; import CharacterCounter from './components/CharacterCounter'; -import TextLengthChecker from './components/TextLengthChecker'; -Injector.update( - { - name: 'my-module', - after: 'my-other-module', - }, - wrap => { - wrap('TextField', CharacterCounter); - } -); -Injector.update( - { - name: 'my-other-module', - before: 'my-module', - }, - wrap => { - wrap('TextField', TextLengthChecker); - } +Injector.transform( + 'my-transformation', + (update) => update('TextField', CharacterCounter), + { after: 'my-other-transformation' } ); ``` -Now, both components play together nicely. +__module-b/js/main.js__ +```js +import Injector from 'lib/Injector'; +import TextLengthChecker from './components/TextLengthChecker'; + +Injector.transform( + 'my-other-transformation', + (update) => update('TextField', TextLengthChecker), + { before: 'my-transformation' } +); +``` + +Now, both components, coming from different modules, play together nicely, in the correct +order. ![](../../../_images/react-di-3.png) +`before` and `after` also accept arrays of constraints. + +```js +Injector.transform( + 'my-transformation', + (update) => update('TextField', TextLengthChecker), + { before: ['my-transformation', 'some-other-transformation'] } +); +``` + +#### Using the * flag + +If you really want to be sure your customisation gets loaded first or last, you can use +`*` as your `before` or `after` reference. + +```js +Injector.transform( + 'my-transformation', + (update) => update('TextField', FinalTransform), + { after: '*' } +); +``` +**Note**: This flag can only be used once per transformation. +The following are not allowed: +* `{ before: ['*', 'something-else'] }` +* `{ after: '*', before: 'something-else' }` + +### Helpful tip: Name your higher order components + +Now that we have multiple enhancements happening to the same component, it will be really +useful for debugging purposes to reveal the names of each enhancement on the `displayName` of + the component. This will really help you when viewing the rendered component tree in + [React Dev Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi?hl=en). + + For this, you can use the third parameter of the `update()` function. It takes an arbitrary + name for the enhancement you're applying. + + __module-a/js/main.js__ + ```js + (update) => update('TextField', CharacterCounter, 'CharacterCounter') + ``` + __module-b/js/main.js__ + ```js + (update) => update('TextField', TextLengthChecker, 'TextLengthChecker') + ``` +### Dealing with events +Let's make a new customisation that customises the behaviour of a button. We'll have +all form actions throw a `window.confirm()` message before executing their action. Further, +we'll apply some new style to the button if it is in a loading state. + +__my-module/js/components/ConfirmingFormButton.js__ +```js +import React from 'react'; + +export default (FormAction) => (props) => { + const newProps = { + ...props, + data: { + ...props.data, + buttonStyle: props.loading ? 'danger' : props.data.buttonStyle + }, + handleClick(e) { + if(window.confirm('Did you really mean to click this?')) { + props.handleClick(e); + } + } + } + + return +} +``` + +__my-module/js/main.js__ +```js +import ConfirmingFormButton from './components/ConfirmingFormButton'; + +Injector.transform('my-transformation', (update) => { + update('FormAction', ConfirmingFormButton, 'ConfirmingFormButton'); +}); +``` ### Registering new React components If you've created a module using React, it's a good idea to afford other developers an @@ -512,33 +620,28 @@ Note: Overwriting components by calling `register()` multiple times for the same service name is discouraged, and will throw an error. Should you really need to do this, you can pass `{ force: true }` as the third argument to the `register()` function. -### Using the injector within your component +### Using the injector directly within your component -If your component has dependencies, you can add the injector via context using the `withInjector` -higher order component. +On rare occasions, you may just want direct access to the injector in your component. If +your dependency requirements are dynamic, for example, you won't be able to explicitly +declare them in `inject()`. In cases like this, use `withInjector()`. This higher order +component puts the `Injector` instance in `context`. -__my-module/js/components/Gallery.js__ ```js -import React from 'react'; -import { withInjector } from 'lib/Injector'; - -class Gallery extends React.Component { - render() { - const GalleryItem = this.context.injector.get('GalleryItem'); - return ( -
- {this.props.items.map(item => ( - - ))} -
- ); +class MyGallery extends React.Component { + render () { +
+ {this.props.items.map(item => { + const Component = this.context.injector.get(item.type); + return + })} +
} } -export default withInjector(Gallery); +export default withInjector(MyGallery); ``` - ### Interfacing with legacy CMS JavaScript One of the great things about ReactJS is that it works great with DOM based libraries like jQuery and Entwine. To allow legacy-land scripts to notify your React component about changes, add the following.