From 0bc860eab8488919176893778bde72f71a631220 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Wed, 2 Sep 2020 09:45:56 +0200 Subject: [PATCH 1/8] whiteboard component and code added --- .../whiteboard.widget.component.html | 18 ++++++++ .../whiteboard.widget.component.scss | 0 .../whiteboard/whiteboard.widget.component.ts | 46 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 web/app/configs/widget/whiteboard/whiteboard.widget.component.html create mode 100644 web/app/configs/widget/whiteboard/whiteboard.widget.component.scss create mode 100644 web/app/configs/widget/whiteboard/whiteboard.widget.component.ts diff --git a/web/app/configs/widget/whiteboard/whiteboard.widget.component.html b/web/app/configs/widget/whiteboard/whiteboard.widget.component.html new file mode 100644 index 0000000..49e80b1 --- /dev/null +++ b/web/app/configs/widget/whiteboard/whiteboard.widget.component.html @@ -0,0 +1,18 @@ + + + + + + diff --git a/web/app/configs/widget/whiteboard/whiteboard.widget.component.scss b/web/app/configs/widget/whiteboard/whiteboard.widget.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/web/app/configs/widget/whiteboard/whiteboard.widget.component.ts b/web/app/configs/widget/whiteboard/whiteboard.widget.component.ts new file mode 100644 index 0000000..e10cd98 --- /dev/null +++ b/web/app/configs/widget/whiteboard/whiteboard.widget.component.ts @@ -0,0 +1,46 @@ +import { WidgetComponent } from "../widget.component"; +import { Component } from "@angular/core"; +import { EditableWidget, WIDGET_WHITEBOARD } from "../../../shared/models/widget"; +import * as url from "url"; +import { SessionStorage } from "../../../shared/SessionStorage"; +import { NameService } from "../../../shared/services/name.service"; +import { FE_WhiteBoardWidget } from "../../../shared/models/integration"; + +@Component({ + templateUrl: "whiteboard.widget.component.html", + styleUrls: ["whiteboard.widget.component.scss"], +}) +export class WhiteboardWidgetComponent extends WidgetComponent { + private whiteBoardWidget: FE_WhiteBoardWidget = SessionStorage.editIntegration; + + constructor(private nameService: NameService) { + super(WIDGET_WHITEBOARD, "Whiteboard", "generic", "whiteboard", "boardName"); + } + protected OnWidgetsDiscovered(widgets: EditableWidget[]): void { + console.log(widgets); + for (const widget of widgets) { + if (!widget.dimension.newUrl.startsWith("http://") && !widget.dimension.newUrl.startsWith("https://")) { + const parsedUrl = url.parse(widget.url, true); + const boardName = parsedUrl.query["boardName"]; + + // Set the new URL so that it unpacks correctly + widget.url = `https://dev-whiteboard.nordeck.net/?whiteboardid=${boardName}`; + } + } + } + + protected OnNewWidgetPrepared(widget: EditableWidget): void { + const name = this.nameService.getHumanReadableName(); + + let template = "https://dev-whiteboard.nordeck.net/?whiteboardid=$roomId_$boardName"; + if (this.whiteBoardWidget.options && this.whiteBoardWidget.options.defaultUrl) { + template = this.whiteBoardWidget.options.defaultUrl; + } + + template = template.replace("$roomId", encodeURIComponent(SessionStorage.roomId)); + template = template.replace("$boardName", encodeURIComponent(name)); + + widget.dimension.newUrl = template; + widget.dimension.newName = name; + } +} From 402cec5b4182012cdf831a6854dceaf736bdb55e Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Wed, 2 Sep 2020 09:50:39 +0200 Subject: [PATCH 2/8] whiteboard component declaration added in app module and routing path added in app routing --- web/app/app.module.ts | 2 ++ web/app/app.routing.ts | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/web/app/app.module.ts b/web/app/app.module.ts index 6f5496e..7263068 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -118,6 +118,7 @@ import { CKEditorModule } from "@ckeditor/ckeditor5-angular"; import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component"; import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/publish/publish.component"; import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component"; +import { WhiteboardWidgetComponent } from "./configs/widget/whiteboard/whiteboard.widget.component"; @NgModule({ imports: [ @@ -215,6 +216,7 @@ import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.compo AdminNewEditTermsComponent, AdminTermsNewEditPublishDialogComponent, TermsWidgetWrapperComponent, + WhiteboardWidgetComponent // Vendor ], diff --git a/web/app/app.routing.ts b/web/app/app.routing.ts index 1086ea8..fa62463 100644 --- a/web/app/app.routing.ts +++ b/web/app/app.routing.ts @@ -47,6 +47,7 @@ import { ManagerTestWidgetWrapperComponent } from "./widget-wrappers/manager-tes import { AdminTermsComponent } from "./admin/terms/terms.component"; import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.component"; import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component"; +import { WhiteboardWidgetComponent } from "./configs/widget/whiteboard/whiteboard.widget.component"; const routes: Routes = [ {path: "", component: HomeComponent}, @@ -225,6 +226,11 @@ const routes: Routes = [ component: SpotifyWidgetConfigComponent, data: {breadcrumb: "Spotify Widgets", name: "Spotify Widgets"}, }, + { + path: "whiteboard", + component: WhiteboardWidgetComponent, + data: {breadcrumb: "Whiteboard Widgets", name: "Whiteboard Widgets"}, + }, ], }, { From 3140b467b2b343f33955e6e0f399b4238ce2c136 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Wed, 2 Sep 2020 09:56:08 +0200 Subject: [PATCH 3/8] widget whiteboard added in widget model and in integrations registry --- web/app/shared/models/widget.ts | 1 + web/app/shared/registry/integrations.registry.ts | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/web/app/shared/models/widget.ts b/web/app/shared/models/widget.ts index 37d853a..9c9c06b 100644 --- a/web/app/shared/models/widget.ts +++ b/web/app/shared/models/widget.ts @@ -11,6 +11,7 @@ export const WIDGET_TWITCH = ["twitch", "dimension-twitch"]; // TODO: m.* namesp export const WIDGET_STICKER_PICKER = ["m.stickerpicker"]; export const WIDGET_TRADINGVIEW = ["tradingview", "dimension-tradingview"]; // TODO: Use m.tradingview (https://github.com/turt2live/matrix-dimension/issues/261) export const WIDGET_SPOTIFY = ["m.spotify", "spotify", "dimension-spotify"]; +export const WIDGET_WHITEBOARD = ["whiteboard", "phoenix-whiteboard"]; export interface EditableWidget { /** diff --git a/web/app/shared/registry/integrations.registry.ts b/web/app/shared/registry/integrations.registry.ts index 3d902b9..7024c82 100644 --- a/web/app/shared/registry/integrations.registry.ts +++ b/web/app/shared/registry/integrations.registry.ts @@ -10,7 +10,8 @@ import { WIDGET_STICKER_PICKER, WIDGET_TRADINGVIEW, WIDGET_TWITCH, - WIDGET_YOUTUBE + WIDGET_YOUTUBE, + WIDGET_WHITEBOARD } from "../models/widget"; import { FE_Integration } from "../models/integration"; @@ -65,6 +66,9 @@ export class IntegrationsRegistry { "stickerpicker": { types: WIDGET_STICKER_PICKER, }, + "whiteboard": { + type: WIDGET_WHITEBOARD, + } }, }; From 7a2cfaf5df93b9bc026450cbb7e7fb8766c9b665 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Wed, 2 Sep 2020 10:05:50 +0200 Subject: [PATCH 4/8] whiteboard avatar image added and integration added in db and home component --- src/db/migrations/20171218203245-AddWidgets.ts | 8 ++++++++ web/app/home/home.component.html | 4 ++++ web/app/shared/models/integration.ts | 8 +++++++- web/public/img/avatars/whiteboard.png | Bin 0 -> 12472 bytes 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 web/public/img/avatars/whiteboard.png diff --git a/src/db/migrations/20171218203245-AddWidgets.ts b/src/db/migrations/20171218203245-AddWidgets.ts index 5cbddbb..44da97b 100644 --- a/src/db/migrations/20171218203245-AddWidgets.ts +++ b/src/db/migrations/20171218203245-AddWidgets.ts @@ -32,6 +32,14 @@ export default { description: "Collaborate on documents with members of your room.", optionsJson: '{"defaultUrl":"https://scalar.vector.im/etherpad/p/$roomId_$padName"}', }, + { + type: "whiteboard", + name: "Whiteboard", + avatarUrl: "/img/avatars/whiteboard.png", + isEnabled: true, + isPublic: true, + description: "A whiteboard app embedded in the room.", + }, { type: "googlecalendar", name: "Google Calendar", diff --git a/web/app/home/home.component.html b/web/app/home/home.component.html index 20c63ea..2a858a9 100644 --- a/web/app/home/home.component.html +++ b/web/app/home/home.component.html @@ -73,6 +73,10 @@ Custom Widget +
+ + Whiteboard +
diff --git a/web/app/shared/models/integration.ts b/web/app/shared/models/integration.ts index a841e4d..d059c84 100644 --- a/web/app/shared/models/integration.ts +++ b/web/app/shared/models/integration.ts @@ -88,8 +88,14 @@ export interface FE_JitsiWidget extends FE_Widget { }; } +export interface FE_WhiteBoardWidget extends FE_Widget { + options: { + defaultUrl: string; + }; +} + export interface FE_IntegrationRequirement { condition: "publicRoom" | "canSendEventTypes" | "userInRoom"; argument: any; expectedValue: any; -} \ No newline at end of file +} diff --git a/web/public/img/avatars/whiteboard.png b/web/public/img/avatars/whiteboard.png new file mode 100644 index 0000000000000000000000000000000000000000..a246526b524676d0c107867b60265dfcc04dcaa0 GIT binary patch literal 12472 zcmeHtXH-*N^Y0Et6cBh6Md?ZtP>?1NN>G%hfYLiCO$Z%AFR>yJx)kXT(xivpi%5xd z5JHh65fDPJQgaXQd)K{R?$`V6pS7}ba?U<`&&-)K`!_Sckf$2T7pa-40RR_ORUT>q zKn5L>f%E5}pB?WXhtLm&`vX;-^U%ltywwNj{{{6uq@#t8C&(ci%?eTaW zdHv#*x}5=g6S=Rq((ExI%hK_c_o_libtm&n7}p!Ni?T%P+{P&rSS{!NzU`W5e}OYkU&t4nf$ z3tBe&Y|A|+<#JEH-G-rX{u>Cg8n5|=wXnj$7pkbKHI5sWS;J~x zuhK}j-G();!kxq{u4M0trLw^*eC#Lxk_r zd+dlDToG>WN(J5}#hdptt_vZ8e)Wtca;SZm*ltj&^B{hd2%6||kLW;^mmmweZpVxF zwl3vfXPI%GS|LubruaP+$T?x@SSF|=uo6MO?G0--ada6rjKI79+opMe^vv;0kW&Gv z^3Q7;n;NNos`0?tq<-8V?%;nkrsaKl*Wt1xdDC&!=4Q<4z~EB&&24q%#dAs+GElPX zfl`ki%w<#RDo8rPv~91)#+|nKoFmA$O@G6l2)jvtv)dgM6s{SwmL`{Hpaf>f@^KoT zRRXqfp>(KSsJ~eix?vNP^tHa zo)wd?e6hdjEUK&iqvyg0E{Sdwz@-r2uu=r1Nv{ee{yKL!admZfc_!}GXI!xuEtWTJ z4&KI&$!Z`n=)vos-jZtcqg;v9=df>a`Oms>bY7{7Lx)+iwc9 zDvK3WmSv?7n>zR#=zz^tbCX$9*N^-)eWl4hBPcRV%wSkCmr9JTiAySMjENdFSaWl9 zka#|u*F~V8g;xGVQK-gL_K>5iZ-I??kt8Dg4L5&PpvjZFFZ4Phn?H%TCsG0PXJ9tF zU_n^wd+cUVd;X!TNb3jdaLMd&AFy#1GF85}+tG}Q3_jkgVHQrMv>3cEbWq7HyvJY4 zYjX{lWrCK+(GIPsbE;)S+IEwNS7SU87dEnp3^Ck-kU$S%=!C*utADN#a0a4Ey??i> zle=ZX-w$M9-Ndt%r?cx1174b21a`Og_+S#Hfn1kuN1eCOge=JyYAFoqqS~=_-oj{n zEP*UTC1(~+Udl%ejtRK(VWo-Mx(df^B5Pi+`u@~Gne3u_ks?6#Qt&dw{Z`Fl%<9)V>>=$wJsmH zZ7LKU8#1Vf2FgxQ)BX!u1e;_@!m4_wPi`tY&fOyR&kT5Py%f9)sgZt75FyX~35+p2 zH6HCHa67s}Q`2sP+3N&&OPa>59Za{L0F{1O5;MP(S1MJnn7pOUlhC>K+P)jA*qs#? z@`bQs_m%FCD(S4r*q{Y?F!yR+QnMik5r&uEn=dUqsmBZkn=VFWsbATqGA`sWzVcc6 z#iNsPD8iMESEsKELbKXREmF?Dm1g2_W;DHJ*OYI)#8 zgPnq=t=ah~XBFLrQqx2>QDt>TO3HOz0H7^}SqeD5eX3fQpVT)QUWt{g1Sx+*-YMt5 zXcqc36aQnh$DJI^eksG8rhl<%+UsdU_+}gOIjX@D1I+s0y44=*>n*@te^CJo=kGBm zi>F!#1;U6X2jpkX(G4<}uPI@RES61zOQlNbGyr|Ibb|S))|SJhp(2{k?l%|z!nax) zKPutV%go;F02ry}M%Vg($Iyoxk`Ct)(T5IP8beVsfFn)P+2JQ*K@Vp#_JKeS7{~N>$~M*(AH`=jo+v=dh=NJ1ox@1c2W0265W9tknTiL}A&ao?n+-j(<|-J`81#{rGs!8vu)v@AvNIB91mz zHSvBKb-_SG>R&!4{=-)_f62kXOX*lFN#1V{g%Zx!_k!JxrIHt3`sN!+4uDe2^6yhu zBnjCV`~`V_mh0WS%Ys<57!Qla`vA0jC}PR$P#)QSX<_OG1V&Gr{xh9}_N3^7`z~w7 z0@>4BjAdmD`^(bO0OUnWnEzQ?`f^~`06vSF4PmqIHCAC|GlK$qep#Y6eu<$*Yqxj4 zifP&{6_JXIk|p`#J0I>1=VQSSk8HVLZ_`pf$(CwdSl#lPP}cY{Lz>qYclEcu6if~> zo_l_@l-roQH&XU!CSrBcW814a8*gUzNhc+oN+~&acXwA;>F8_H0(eNJXCwG;7%4as zp)_-tj98qb2P*HdwJNclqn_jeD>WLXCkLcrMO)TrofK6T@l&qKhSD4|hR!{Vky&-F z$m;6hf_`&WgvhEYD;+@RNO?b4C2stloJ1Y0pT2TCu-et9wwP~6Zdv% z`*-dR(t{|twtWNnU8}h)atW{LM5ftn#oJUDq0fO!-cS=~+ddB&XU;n!9vY&$_5R2)UUp7{6wp@{7 zbM4vO4aUMN;uA*hQE;k%nMbvyy8L{$%MPJJTetB;4nxH6jZeE&B1uNw-S$PoyB7mh zlH}vAyoG_KI8}?@q>xx%zNoA!q+1bX#+oTb`wIj>Gln_d5rj1)d~s)Q%}9zTFW!C7 zH^KrKDh`E7T9;;Wk#Z_GZ6Un5^Z*87Le+sE?Ec}7K(W`lcLg<3os zFLQW-g*hgAqC6VD9i4;e7D(- z|5Y6?08YrUY3BMv`MuWdCcChfkS-N5zIl(HkDl|F4emGxRqg5T{+tLbn$oiylfKEt zc26XikTXA$=9tQ|ct;!DTgm&ws{1(49}gyy9Wpcv(Syr`eg;$S-kx*zGEisVLG> zKOS>-zCLidfH`QBqu8Xz4P4G@Xoztd@>hqs%A0r z(`)s1r|(>mDUQvB@rB??*`s3VFT$Y2;WiSlumV2^EI6v-@_jAcrLly@(&CvVO7BI5 zLVZcz{q35VL$Zy9oE_3XAY-Jl)`v5ipkrB3U475#>x>G|?sm<`WwHTt?1bLjBm(?( zBJ`=}n=w*8vwI2N-Idm@=POo*!Neyfg``hi;47nvnw(JR#0K z@&QDRBZ*rhlo^e!G*1ACiT!5l>6eU1KYEs5lEE(w*lJZQC$vtufC2+=h3zFn4KFQa zy^c3@cXRG&bp&&wR8B^=qb@iWa{(Z)pp`ySiy363*PBDWLuxM5v^=9)NN!r902aTu z3_o-6E?$zE4$i6M^DH!~u*O8B#dsy%xB!{spm2~sIKq{U9F#J3sN}K^MgL){46zi2 zd*;{EY~ZLOpA}PjQauTPMP{7?y(@Ip7#V0}mA1Fbv5-6Z=L5CC&l=z>+|FOgWIKltC z4F8`Z!7Ua9)zeaD-fj$s(MTXarD_i|~7qrEdy!z;g|`M{?t z!7@$&cPtCgC*9VVj)j|S;!Wzo8ZWhtJ8B|6=0RI`iQ{eJLFGw^=}s_9p3y4nhsx*5 zj|A}v9zR}5v&m$e=Db=D)=j3Wc+o2)bO>f!6h`corAO;luQZlcnRjyhD85eh+oV(N zNjD?fys`0diPLS#d6SVb`}w+_naR&XxuKU{n?5)2;olHE7Fzw7UhK4?7Q43|GkLEK}Ff%jP8`-6&0Asmh zYfalJo?nCjHcro(&4o=d*;BVt?B9DezR5@FRG>5nSw*M9Pb!XICMzvxMP|UnPLbH` zW}|%(wJXU6(Ex~R)Y|Kka+{2yIkH0$Ox>px>?7Mti!iWap0f38LWc=ms2nC*!LxDO zqUxXi%VdB#Gn&{Uu9#2Ll31nEbbKn~wo4M2oXmV*$Pa)@eDp_EA958Gtjiih_ou5S z0xQ#*cIV(3!G7T`)#TIK)~t$}DzJaE`vZ-1x+ zCv0Ft)){sO+u)ZzX+yH;$s;``ez8sWAPSTpn^<>LJW7&5rgT(Gu4^dx-5VM&?~t&f zdmxV#w;dgOxNrr69U@I~pKHrI?4HC{y>YIHuf_k24)f@XChSaf#F+Wy{wzf$Z5w`u zoWo=1qrW1@B(h&ANer1XJ!Uf6&7wA8_97erm*);bLxnh>-jt8XFMO3oIY6b}8P}hb zf`?8z3hGvVX5=eVh~%CxQ(|+B=EdN|S4Sg7>iMqqNpa?`W*ba)>&6M_-J3#c0tJBz z+whJBvE`oX4#`uwN*&m>VzKmRwoNFfem%6z0}B5a6<1yb><`HS z#hp(QuuF!7?3_1041hyr75+qtwY>Bq;B0(CR`6A)AjE`5u(BbqgUrGnKJHRd;#)th z2*B(Uo??>C-;Q16C6&xqMrJxhhL&Y!^ZjDmG`}zZ9l-x8&Su7cH;y7^EU6e*ISn(= zog@Yl5;RK&CXu5fe%Am<>NB!au5B9JP-ht>?&_O8;SBdFkJlg31DHV5VdDD`%L10r z$3!_=0Mx6qoAZ5@0s8^2vFrjZmrB)tvl}%;$vn!hZmFt%XQx~+Rtm!X>g9oc0ouRx z8uvokgZ}V^Sc#0vnspQH>&c(0=YVh6k%Z<`FQZ1!fdAxd{L>R!!woX3Lkr<79^3m( zJjhrdW}*0^r6dz=nD^eV*mM!Co5O$gOH51p12=_t=1R;T&$&SF$BzY5UB{&o$K#;g ze94^>(uTU@c!kIpDQDTE;r4#~)>r2J?$vTA>-NgZ8n*X4@pGK2G7U>Oc_^yX$u6N? zYhrvUm=bWhHXBWqtY!}e_^r=WYSYgIRR`|8S+`r#&z5KSoaoOOA+^K zH7WShYGmFlOz80Z6YGx18J2g;%u)aJapxBd4m#3dBIY$22ny8Bxfp4a~)5I(S!EuPk9uRIc}HSM)M5SiirVOkSGIme$;P|%kvozGC=6f@rlC?2 zNi8P$iPd?FYxQ&g$^_~URbQ4D0^qsmf}bF}?18(QccR>&3{V_x3_Ot2wk^h~!i{mV zb`ZLGStxPXQBFU-*{Nkd=f1-1>ni`ek0*h}vYF4$fvcY!D1?nWVQTk2Q8^3WTc)^3 z@;v=jJEi>X`)PqyzvE6V6msMWf(v-vSGVa;^8OWEy|=XI@9gn4g|9?{cR6n5Mz1s< z0AI?!Upr#zm#z7GWdGH2SDh_AU9P_Vv-rKk0K;v{>%A`*YGGg_W`rnu*xC20${BI^ zQshAH&3-G6qA@Kkt%n9Fz{EeKJ34U?12_E*m0zMAW7e=8(=Nw9eonQ&z)q}yKHEPW zBO`InGtr37Yuh4*y;Ws=YI_#Aiu%5DK!MB?x9o_lxLIc8#Ib2GM$`VD4E{s7mL%Alppcxw1FyyyhM0Q6Yc5OhU4su z(woO&2p(ep9#w719r^8+NHf<|@^G)A21;Tf->w{o-IN&pb`wqO=Ax+^(&~jXwSrIq zVJ&c0nKTDiHsWc#WMNP!*NJ-j+|xmCUIc#wR1_PpH=p>ZI@k4yU^LTPzbL};f=5j7 z|4du2zUgL-`{@SvKD=`ij^u4`6xGB4*)o zMU9(l?Sdx3VBpXx&;n;Vr5W0H-}E+g}7=dQrkI*SD8&aT_Rw zklj_ga`}ph?X?`yr;h9HY-9@F`Ip_AKUUyS5jXDHu(!N?29&xB9`W@Ehwd{~*J!{v zWg-6)D3HfXPq+Jm&q}ascZkEuxA&H=vZ4nbnq9n~=DFM8V`&4 zTYkV6lIUAfrM@5PfQfvYo=?S!Sr;fR7%?k+(DF8&IXx|eVnuKsU*t7&nwf<+S@dQi z!Z6g77UB)eBz=xa5}8Y{k&ipykSM){&MolyIY!c1sCzXCuzxr<3j2*&TU(>U-xzvL zcK3n4r>SpVp-pX{$hZ8j6bhhkyrI!tYX#n!VPZR;@(Xf{r$8x>nLdRGZ@Y_hKG`(w zucLzjNnz8v`$HvXE4KkINHcz7|7wuo6kipIa+U^if%PM1JO zdIxz=^?wJ};E$N0IcM_^5;P>C9*sL~h^QeiAlv9jeC0^5y6lx|`P5HZ^3(&85KVTM z3|r*AbKD$o+F@N?e<1 zrgnN%MJtL~41nhf69s*z5Ea*Rit&dx zctS?gmF=rOBRZf<$9=I2>N|0@K~@-QGjP_U6z?G)j;EdUg+i{;^@-HFTHW z!u%FEvamW+U*y>WU$GcyQK{T_4tl6p4>j$$xq6qDmT)zFzqqJd%={N(6Q0DcY(h5h zjaUtWW#MM`TIlQhL|#6qs3ck8Z}>y1g{c|uvL0;LZ`$0x2$Wirp98`m*OdI`{LRIL zvGh$+m#=vIIlyJb71`AAS0cBYg%RCY+L63T3KfkDhJp}!u+DlsCYQSi>fOa)R#Kqu zU9p$nEK^x<+JRgwcj_O=+dG|1svHU+13V>1TFHHCao{cTU%6l|k8ivW8&e$J>yP7W zWQ0KlPvy+u-&#*n0@`ZhlP!Z>qwl zya)Qvyvu0HV}GjTu`dqtF3}bS7B3NoUfV|HH- ze=unFV1t3>E04%EYx?ef```oGo`LD^WJzTS?Y$R2X~D8<&r)tP|Cbr)>AKJ3gi7Qy z0PV7LiS6sG$eO;*VsDcX6ovQgveja)hVI_GrNvXB z<#aAhsO87+tfp;Zi|#Cx9z(sof$j0YU!N^0SnOp%X4B!N-zPp9NtS6Weg@8sca`+s z6u`=_!O4%Uv&*3{_M%XJ0s5mG-jT8jZ*wv0-F3r|-MzKv5PhEO$hcUnMYF!TV6+x; zjBQ*iPsOW!>}Ywvs3Ppz16Y*D>TAkWC3rh3V*hRqF|^oeI?p>@&3L|_XWn%2T25o{ zM^Z46VWVGnn~9ZYNet@RJwMFUH1((;GC=yOEDI+~$CN>5TW>`)p{(`s-uU~ok=^~~ z2Bo9^t*8h&LnLW(ep@(=0H-=093GA>_#UVq7^kbM#rg=^di)h&QC4#GCnT1=Z&FV6 z1-S!aeW*({Ue@~iotW^jm!21KAU_&_?{LS{$Jy0m0{UZ8a z*YSg?TmS(u?tFp|`Fti+9Te=`PWrZ<(R`k%>N=K-+ z@9jAeM*`uAe+~BVZK3>~&x$6>%-Omzr)|t9wmRX{QEX$&a0cc!rDuIgdr@6V9HHSt zl6toMl=yh5(1<$JI9s!4Y8%hGuy1%(K~|(7PcxNZs=$&CvMBS3?r6F-O;n9R2i>Xu zIznxK`KhY8xSn~%v)hsJV+!QgkXG3<4Yt}XIs|uaN>gx+>~2#8i5xJ$^8t)te5_wp z0HEJ*+1~BLY+J@GrutK+7w8&mLnwgZ?&sIU^FrC%u+J185Pt?En5_QdJOHnCzf4?jKT2r& z1rMfaore9nt!x_-h5!^rcSKv)p8w+ji>f9rR4mLfP-06N<7Tuf*YNJ zre=TQ%IFZUPmMYc$f$KFRCKC!#!VKxiyKFIfimO6enzGssCC=*vY1FKL}3WNL0fD~ zltRgc=T`yp^|2*6nC?FZr{}DZ2BxN_2O+MLHma+|yA3i@gKE(O3Su#U2e zJih`qj}gFPy-);l=p_C`X&@&jS6fw-t**E1l1d3?c_#I6PYznitD6aM6)_5TD$e>M zl84YKl+N6ZbKptz0j-Rn{hw+Q3>+~Hm|$I~(HD?zR3PIVZ1u|Jhp-x_J(OcipBuDK z%}NRe{7(A%H3Tx8A_Jub@pomeDl_rynfeVX2w`@?>sx?#ZV!^j%7L*X1p1mQRTNz^KB zp{rrK_~*0L5Uvmzcg&uN*+Cihx~1B37w(inOy&t8WL$z!BL#5J;XR30HgF}Dxk21=PY(5yX=AP%hp)%t&!!7+{cg~XzXQ@Atg*!A* zA~UyH{n)tq51e9XJ%>a1AOhp$k*cWG?M!=iYi=$d7cO|7)$;NuM6{JD)%`=$=Ho-y z<#FNqJ}jT$_B=$v3MI0>ycmr;{q(#2+hC-pmshUar8Sib2UwSbQ0h(G$pbn)M5F8Y z+@eXR01enFuy03!RK@*7L zgZnn1v}Rr*VOwlnNk8ZeFL}d7=z!vVk!U3V4|eB8W-Sg3|x)N z(Dgn#M-6P zdb8-ADoBVvsHG3FN*;1mSi!u1ZSrZvd!UJ|dcG-({|=t#-LuvDqG>qb=3he-)$hO} z)rR_@^b$vwkMW&JGAkysI_cu75A4BYIO7fCI&EewwRF)R?dPuqnC1MXd0!o<7WooJh-&j z`%{33tK@|hX#q@DEyVlM;w30QrbO$_L02sM*3QsvMD*METOc9T3+Eb>0}+S{Oy^x! zHEW>4Q<05}(}*u5O?W@#-E;7Vmy9xjRi^zJFDnKc$rRRJM!W_FUKeI5n+8X5U#{#R zpzk~b{^MD#2Js|H^tmldb~GP8#kcYytW?xYmQ-@qj|_hia1dkN`%^EGD(aBTW#oV+ zBF>`}GI&0DTnhb>9=XEfe2uP?Ar%>jpd@~yym99_{>F0LA=%S7h@*D*kAC}6nDH4@ z*3-RxwOh|<4PrNak~(PvP#<_&Hr7tIR)P`~^~8q1;zsPHeNm=i1c)?JLb#ldHkksk ztRprA9lE%;x0iFsoV2_VCXX5%6or3-+%Pn=D!sN3fTH3?M!B2(5SvRhR!@HKTS&3? z53UhP&i_;sVz@u+JDGS+3gAVcu6jW8dPHxT?;hSqbC0ajoKH1 z`Ox2QnGA`TI;{)C3tPv2!eJs_|YW z3fjaTys$d)-uligT>Pj~#SvPYa1i9o`xz)G6e8S9sMVHa(K=Vr1&b(-8{^j@XxTxg z00taJ(`)s$OA_$`g+zu*6>C^tV%{vo?8DjXXS-vVh+5OksD+(p^%YKQ;NXz=4AN|3Rf(Nhi0D z2rcq6hRG{OnF~eP@_CbFeq~+wPy|K^$STgNCTFBPI@K>JR8e2aW;-)!^c(;MSo7JE z%21tw)V+chtQV5g(JMd8>I^lfJs=zwdDT+JW6+1`&^3VhUueXb-dP%mvl4A;SOS~| zo-N5_oXI#}*I?f)EnVP$-4Z)gASqPu7zc$UhPpFEq&M^!(qqdmV&X$qJ}~$M6`Nuh z4@4IzK$O+V-zR%k;YrbI>aZI7)9m4JkB>ywOZ_Brw5Dtl)m`^NN+$0z&0ea<>ae^# zUkH>b-fW{rgISuAweNb9TJB7o5|l0J*ems$f5bF=T2a)X#R<`1iwlbxJtO()HJKF1 z8`x8$u}!j;cI<0VbT!R|z*@K3f^D%PZ6@GeIxAWvcwmUEZ~U(#$pCHHy}kMJgRWLN zWJ5wI83S?_%7ES*Tm=wm(n|ESu#frCo;d!x(#)K;303|#2M+c<208@ zi{^eb{+(Kt9I~-Mf@9!2A_Mw&zpck@Lc0Xv!oh?(|awOma)U8RTj0hJi1 zI%2VU$2AW5l|ZeA<{F6hsStAx@fj}@vAJ*uVRoEHpyi4QCF8^~7c_gO{Bk}zJQRo! z1M6j>q#@M%TceT?FZcZpL<6(hsn$@ub|e{7I84j+F`g{LvJbv%&Mg_~V^GiuAsf=4 zxt}dfKmGfMf{O-si~F3j*MEA?Try8hO1_!6+`xOtvV^N)k8I#=G9!J*9N)*X=`Y1FS&%OKT`gV!rbmQMo6cHE1+v7|V z*o`XVkc`9!mL6}j>@KkR7FGI=bp15M={B1;Z1+`Pf(s3}=$pB0s=AH@>S^5{x~-ae vfpw2f)!FEiU-%r0QkW#>3(V7O(#o0ib1n literal 0 HcmV?d00001 From 4a524777a91d2d74efb5727f6c7741823409b091 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Thu, 29 Oct 2020 16:14:24 +0100 Subject: [PATCH 5/8] removed empty line from end of file --- web/app/shared/models/integration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/shared/models/integration.ts b/web/app/shared/models/integration.ts index d059c84..1255e84 100644 --- a/web/app/shared/models/integration.ts +++ b/web/app/shared/models/integration.ts @@ -98,4 +98,4 @@ export interface FE_IntegrationRequirement { condition: "publicRoom" | "canSendEventTypes" | "userInRoom"; argument: any; expectedValue: any; -} +} \ No newline at end of file From d62956fb8d0c6a12a8dccefd83572b5e305146a1 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Fri, 4 Dec 2020 16:12:03 +0100 Subject: [PATCH 6/8] removed whiteboard entry from add widget db file and added in a new db file specific for whiteboard --- .../migrations/20171218203245-AddWidgets.ts | 10 +------- .../20201204142645-AddWhiteboardWidget.ts | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/db/migrations/20201204142645-AddWhiteboardWidget.ts diff --git a/src/db/migrations/20171218203245-AddWidgets.ts b/src/db/migrations/20171218203245-AddWidgets.ts index 44da97b..9d60881 100644 --- a/src/db/migrations/20171218203245-AddWidgets.ts +++ b/src/db/migrations/20171218203245-AddWidgets.ts @@ -32,14 +32,6 @@ export default { description: "Collaborate on documents with members of your room.", optionsJson: '{"defaultUrl":"https://scalar.vector.im/etherpad/p/$roomId_$padName"}', }, - { - type: "whiteboard", - name: "Whiteboard", - avatarUrl: "/img/avatars/whiteboard.png", - isEnabled: true, - isPublic: true, - description: "A whiteboard app embedded in the room.", - }, { type: "googlecalendar", name: "Google Calendar", @@ -86,4 +78,4 @@ export default { down: (queryInterface: QueryInterface) => { return queryInterface.dropTable("dimension_widgets"); } -} \ No newline at end of file +} diff --git a/src/db/migrations/20201204142645-AddWhiteboardWidget.ts b/src/db/migrations/20201204142645-AddWhiteboardWidget.ts new file mode 100644 index 0000000..68192c4 --- /dev/null +++ b/src/db/migrations/20201204142645-AddWhiteboardWidget.ts @@ -0,0 +1,24 @@ +import { QueryInterface } from "sequelize"; + +export default { + up: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.bulkInsert("dimension_widgets", [ + { + type: "whiteboard", + name: "Whiteboard", + avatarUrl: "/img/avatars/whiteboard.png", + isEnabled: true, + isPublic: true, + description: "A whiteboard app embedded in the room.", + optionsJson: '{"defaultUrl":"https://cloud13.de/testwhiteboard/?whiteboardid=$roomId_$boardName"}', + } + ])); + }, + down: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.bulkDelete("dimension_widgets", { + type: "whiteboard", + })); + } +} From 8e10af4c96a265919138bbb9212fda6a409e70bd Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Fri, 4 Dec 2020 17:47:45 +0100 Subject: [PATCH 7/8] created new config component for whiteboard in admin area with editable board url --- src/integrations/Widget.ts | 4 +++ .../whiteboard/whiteboard.component.html | 22 ++++++++++++ .../whiteboard/whiteboard.component.scss | 0 .../whiteboard/whiteboard.component.ts | 35 +++++++++++++++++++ web/app/admin/widgets/widgets.component.ts | 4 ++- web/app/app.module.ts | 5 ++- 6 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 web/app/admin/widgets/whiteboard/whiteboard.component.html create mode 100644 web/app/admin/widgets/whiteboard/whiteboard.component.scss create mode 100644 web/app/admin/widgets/whiteboard/whiteboard.component.ts diff --git a/src/integrations/Widget.ts b/src/integrations/Widget.ts index e29da8c..c348834 100644 --- a/src/integrations/Widget.ts +++ b/src/integrations/Widget.ts @@ -5,6 +5,10 @@ export interface EtherpadWidgetOptions { defaultUrl: string; } +export interface WhiteboardWidgetOptions { + defaultUrl: string; +} + export interface JitsiWidgetOptions { jitsiDomain: string; scriptUrl: string; diff --git a/web/app/admin/widgets/whiteboard/whiteboard.component.html b/web/app/admin/widgets/whiteboard/whiteboard.component.html new file mode 100644 index 0000000..68fc80c --- /dev/null +++ b/web/app/admin/widgets/whiteboard/whiteboard.component.html @@ -0,0 +1,22 @@ +
+
+

Whiteboard Widget Configuration

+
+
+ +
+ +
diff --git a/web/app/admin/widgets/whiteboard/whiteboard.component.scss b/web/app/admin/widgets/whiteboard/whiteboard.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/web/app/admin/widgets/whiteboard/whiteboard.component.ts b/web/app/admin/widgets/whiteboard/whiteboard.component.ts new file mode 100644 index 0000000..6b9c01b --- /dev/null +++ b/web/app/admin/widgets/whiteboard/whiteboard.component.ts @@ -0,0 +1,35 @@ +import { Component } from "@angular/core"; +import { FE_WhiteBoardWidget } from "../../../shared/models/integration"; +import { ToasterService } from "angular2-toaster"; +import { DialogRef, ModalComponent } from "ngx-modialog"; +import { WidgetConfigDialogContext } from "../widgets.component"; +import { AdminIntegrationsApiService } from "../../../shared/services/admin/admin-integrations-api.service"; + +@Component({ + templateUrl: "./whiteboard.component.html", + styleUrls: ["./whiteboard.component.scss", "../config-dialog.scss"], +}) +export class AdminWidgetWhiteboardConfigComponent implements ModalComponent { + + public isUpdating = false; + public widget: FE_WhiteBoardWidget; + private originalWidget: FE_WhiteBoardWidget; + + constructor(public dialog: DialogRef, private adminIntegrationsApi: AdminIntegrationsApiService, private toaster: ToasterService) { + this.originalWidget = dialog.context.widget; + this.widget = JSON.parse(JSON.stringify(this.originalWidget)); + } + + public save() { + this.isUpdating = true; + this.adminIntegrationsApi.setIntegrationOptions(this.widget.category, this.widget.type, this.widget.options).then(() => { + this.originalWidget.options = this.widget.options; + this.toaster.pop("success", "Widget updated"); + this.dialog.close(); + }).catch(err => { + this.isUpdating = false; + console.error(err); + this.toaster.pop("error", "Error updating widget"); + }); + } +} diff --git a/web/app/admin/widgets/widgets.component.ts b/web/app/admin/widgets/widgets.component.ts index 5debd8e..6aab37c 100644 --- a/web/app/admin/widgets/widgets.component.ts +++ b/web/app/admin/widgets/widgets.component.ts @@ -6,6 +6,7 @@ import { Modal, overlayConfigFactory } from "ngx-modialog"; import { BSModalContext } from "ngx-modialog/plugins/bootstrap"; import { AdminWidgetJitsiConfigComponent } from "./jitsi/jitsi.component"; import { AdminIntegrationsApiService } from "../../shared/services/admin/admin-integrations-api.service"; +import { AdminWidgetWhiteboardConfigComponent } from "./whiteboard/whiteboard.component"; export class WidgetConfigDialogContext extends BSModalContext { public widget: FE_Widget; @@ -50,6 +51,7 @@ export class AdminWidgetsComponent { if (widget.type === "etherpad") component = AdminWidgetEtherpadConfigComponent; if (widget.type === "jitsi") component = AdminWidgetJitsiConfigComponent; + if (widget.type === "whiteboard") component = AdminWidgetWhiteboardConfigComponent; if (!component) { console.error("No known dialog component for " + widget.type); @@ -67,6 +69,6 @@ export class AdminWidgetsComponent { public hasConfiguration(widget: FE_Widget) { // Currently only Jitsi and Etherpad have additional configuration - return widget.type === "jitsi" || widget.type === "etherpad"; + return widget.type === "jitsi" || widget.type === "etherpad" || widget.type === "whiteboard"; } } diff --git a/web/app/app.module.ts b/web/app/app.module.ts index 7263068..7eb6e69 100644 --- a/web/app/app.module.ts +++ b/web/app/app.module.ts @@ -119,6 +119,7 @@ import { AdminNewEditTermsComponent } from "./admin/terms/new-edit/new-edit.comp import { AdminTermsNewEditPublishDialogComponent } from "./admin/terms/new-edit/publish/publish.component"; import { TermsWidgetWrapperComponent } from "./widget-wrappers/terms/terms.component"; import { WhiteboardWidgetComponent } from "./configs/widget/whiteboard/whiteboard.widget.component"; +import { AdminWidgetWhiteboardConfigComponent } from "./admin/widgets/whiteboard/whiteboard.component"; @NgModule({ imports: [ @@ -216,7 +217,8 @@ import { WhiteboardWidgetComponent } from "./configs/widget/whiteboard/whiteboar AdminNewEditTermsComponent, AdminTermsNewEditPublishDialogComponent, TermsWidgetWrapperComponent, - WhiteboardWidgetComponent + WhiteboardWidgetComponent, + AdminWidgetWhiteboardConfigComponent // Vendor ], @@ -273,6 +275,7 @@ import { WhiteboardWidgetComponent } from "./configs/widget/whiteboard/whiteboar AdminSlackBridgeManageSelfhostedComponent, AdminLogoutConfirmationDialogComponent, AdminTermsNewEditPublishDialogComponent, + AdminWidgetWhiteboardConfigComponent ] }) export class AppModule { From 9131ad9bb6aeb56e1f49396510d9d0f0f70e20a2 Mon Sep 17 00:00:00 2001 From: nurjinn jafar Date: Tue, 15 Dec 2020 12:22:39 +0100 Subject: [PATCH 8/8] whiteboard avatar changed --- web/public/img/avatars/whiteboard.png | Bin 12472 -> 2915 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/web/public/img/avatars/whiteboard.png b/web/public/img/avatars/whiteboard.png index a246526b524676d0c107867b60265dfcc04dcaa0..526d1559ce78f1ada19c6e927790f719fc3dd3f2 100644 GIT binary patch literal 2915 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 IQ@7av0yLLiQvd(} literal 12472 zcmeHtXH-*N^Y0Et6cBh6Md?ZtP>?1NN>G%hfYLiCO$Z%AFR>yJx)kXT(xivpi%5xd z5JHh65fDPJQgaXQd)K{R?$`V6pS7}ba?U<`&&-)K`!_Sckf$2T7pa-40RR_ORUT>q zKn5L>f%E5}pB?WXhtLm&`vX;-^U%ltywwNj{{{6uq@#t8C&(ci%?eTaW zdHv#*x}5=g6S=Rq((ExI%hK_c_o_libtm&n7}p!Ni?T%P+{P&rSS{!NzU`W5e}OYkU&t4nf$ z3tBe&Y|A|+<#JEH-G-rX{u>Cg8n5|=wXnj$7pkbKHI5sWS;J~x zuhK}j-G();!kxq{u4M0trLw^*eC#Lxk_r zd+dlDToG>WN(J5}#hdptt_vZ8e)Wtca;SZm*ltj&^B{hd2%6||kLW;^mmmweZpVxF zwl3vfXPI%GS|LubruaP+$T?x@SSF|=uo6MO?G0--ada6rjKI79+opMe^vv;0kW&Gv z^3Q7;n;NNos`0?tq<-8V?%;nkrsaKl*Wt1xdDC&!=4Q<4z~EB&&24q%#dAs+GElPX zfl`ki%w<#RDo8rPv~91)#+|nKoFmA$O@G6l2)jvtv)dgM6s{SwmL`{Hpaf>f@^KoT zRRXqfp>(KSsJ~eix?vNP^tHa zo)wd?e6hdjEUK&iqvyg0E{Sdwz@-r2uu=r1Nv{ee{yKL!admZfc_!}GXI!xuEtWTJ z4&KI&$!Z`n=)vos-jZtcqg;v9=df>a`Oms>bY7{7Lx)+iwc9 zDvK3WmSv?7n>zR#=zz^tbCX$9*N^-)eWl4hBPcRV%wSkCmr9JTiAySMjENdFSaWl9 zka#|u*F~V8g;xGVQK-gL_K>5iZ-I??kt8Dg4L5&PpvjZFFZ4Phn?H%TCsG0PXJ9tF zU_n^wd+cUVd;X!TNb3jdaLMd&AFy#1GF85}+tG}Q3_jkgVHQrMv>3cEbWq7HyvJY4 zYjX{lWrCK+(GIPsbE;)S+IEwNS7SU87dEnp3^Ck-kU$S%=!C*utADN#a0a4Ey??i> zle=ZX-w$M9-Ndt%r?cx1174b21a`Og_+S#Hfn1kuN1eCOge=JyYAFoqqS~=_-oj{n zEP*UTC1(~+Udl%ejtRK(VWo-Mx(df^B5Pi+`u@~Gne3u_ks?6#Qt&dw{Z`Fl%<9)V>>=$wJsmH zZ7LKU8#1Vf2FgxQ)BX!u1e;_@!m4_wPi`tY&fOyR&kT5Py%f9)sgZt75FyX~35+p2 zH6HCHa67s}Q`2sP+3N&&OPa>59Za{L0F{1O5;MP(S1MJnn7pOUlhC>K+P)jA*qs#? z@`bQs_m%FCD(S4r*q{Y?F!yR+QnMik5r&uEn=dUqsmBZkn=VFWsbATqGA`sWzVcc6 z#iNsPD8iMESEsKELbKXREmF?Dm1g2_W;DHJ*OYI)#8 zgPnq=t=ah~XBFLrQqx2>QDt>TO3HOz0H7^}SqeD5eX3fQpVT)QUWt{g1Sx+*-YMt5 zXcqc36aQnh$DJI^eksG8rhl<%+UsdU_+}gOIjX@D1I+s0y44=*>n*@te^CJo=kGBm zi>F!#1;U6X2jpkX(G4<}uPI@RES61zOQlNbGyr|Ibb|S))|SJhp(2{k?l%|z!nax) zKPutV%go;F02ry}M%Vg($Iyoxk`Ct)(T5IP8beVsfFn)P+2JQ*K@Vp#_JKeS7{~N>$~M*(AH`=jo+v=dh=NJ1ox@1c2W0265W9tknTiL}A&ao?n+-j(<|-J`81#{rGs!8vu)v@AvNIB91mz zHSvBKb-_SG>R&!4{=-)_f62kXOX*lFN#1V{g%Zx!_k!JxrIHt3`sN!+4uDe2^6yhu zBnjCV`~`V_mh0WS%Ys<57!Qla`vA0jC}PR$P#)QSX<_OG1V&Gr{xh9}_N3^7`z~w7 z0@>4BjAdmD`^(bO0OUnWnEzQ?`f^~`06vSF4PmqIHCAC|GlK$qep#Y6eu<$*Yqxj4 zifP&{6_JXIk|p`#J0I>1=VQSSk8HVLZ_`pf$(CwdSl#lPP}cY{Lz>qYclEcu6if~> zo_l_@l-roQH&XU!CSrBcW814a8*gUzNhc+oN+~&acXwA;>F8_H0(eNJXCwG;7%4as zp)_-tj98qb2P*HdwJNclqn_jeD>WLXCkLcrMO)TrofK6T@l&qKhSD4|hR!{Vky&-F z$m;6hf_`&WgvhEYD;+@RNO?b4C2stloJ1Y0pT2TCu-et9wwP~6Zdv% z`*-dR(t{|twtWNnU8}h)atW{LM5ftn#oJUDq0fO!-cS=~+ddB&XU;n!9vY&$_5R2)UUp7{6wp@{7 zbM4vO4aUMN;uA*hQE;k%nMbvyy8L{$%MPJJTetB;4nxH6jZeE&B1uNw-S$PoyB7mh zlH}vAyoG_KI8}?@q>xx%zNoA!q+1bX#+oTb`wIj>Gln_d5rj1)d~s)Q%}9zTFW!C7 zH^KrKDh`E7T9;;Wk#Z_GZ6Un5^Z*87Le+sE?Ec}7K(W`lcLg<3os zFLQW-g*hgAqC6VD9i4;e7D(- z|5Y6?08YrUY3BMv`MuWdCcChfkS-N5zIl(HkDl|F4emGxRqg5T{+tLbn$oiylfKEt zc26XikTXA$=9tQ|ct;!DTgm&ws{1(49}gyy9Wpcv(Syr`eg;$S-kx*zGEisVLG> zKOS>-zCLidfH`QBqu8Xz4P4G@Xoztd@>hqs%A0r z(`)s1r|(>mDUQvB@rB??*`s3VFT$Y2;WiSlumV2^EI6v-@_jAcrLly@(&CvVO7BI5 zLVZcz{q35VL$Zy9oE_3XAY-Jl)`v5ipkrB3U475#>x>G|?sm<`WwHTt?1bLjBm(?( zBJ`=}n=w*8vwI2N-Idm@=POo*!Neyfg``hi;47nvnw(JR#0K z@&QDRBZ*rhlo^e!G*1ACiT!5l>6eU1KYEs5lEE(w*lJZQC$vtufC2+=h3zFn4KFQa zy^c3@cXRG&bp&&wR8B^=qb@iWa{(Z)pp`ySiy363*PBDWLuxM5v^=9)NN!r902aTu z3_o-6E?$zE4$i6M^DH!~u*O8B#dsy%xB!{spm2~sIKq{U9F#J3sN}K^MgL){46zi2 zd*;{EY~ZLOpA}PjQauTPMP{7?y(@Ip7#V0}mA1Fbv5-6Z=L5CC&l=z>+|FOgWIKltC z4F8`Z!7Ua9)zeaD-fj$s(MTXarD_i|~7qrEdy!z;g|`M{?t z!7@$&cPtCgC*9VVj)j|S;!Wzo8ZWhtJ8B|6=0RI`iQ{eJLFGw^=}s_9p3y4nhsx*5 zj|A}v9zR}5v&m$e=Db=D)=j3Wc+o2)bO>f!6h`corAO;luQZlcnRjyhD85eh+oV(N zNjD?fys`0diPLS#d6SVb`}w+_naR&XxuKU{n?5)2;olHE7Fzw7UhK4?7Q43|GkLEK}Ff%jP8`-6&0Asmh zYfalJo?nCjHcro(&4o=d*;BVt?B9DezR5@FRG>5nSw*M9Pb!XICMzvxMP|UnPLbH` zW}|%(wJXU6(Ex~R)Y|Kka+{2yIkH0$Ox>px>?7Mti!iWap0f38LWc=ms2nC*!LxDO zqUxXi%VdB#Gn&{Uu9#2Ll31nEbbKn~wo4M2oXmV*$Pa)@eDp_EA958Gtjiih_ou5S z0xQ#*cIV(3!G7T`)#TIK)~t$}DzJaE`vZ-1x+ zCv0Ft)){sO+u)ZzX+yH;$s;``ez8sWAPSTpn^<>LJW7&5rgT(Gu4^dx-5VM&?~t&f zdmxV#w;dgOxNrr69U@I~pKHrI?4HC{y>YIHuf_k24)f@XChSaf#F+Wy{wzf$Z5w`u zoWo=1qrW1@B(h&ANer1XJ!Uf6&7wA8_97erm*);bLxnh>-jt8XFMO3oIY6b}8P}hb zf`?8z3hGvVX5=eVh~%CxQ(|+B=EdN|S4Sg7>iMqqNpa?`W*ba)>&6M_-J3#c0tJBz z+whJBvE`oX4#`uwN*&m>VzKmRwoNFfem%6z0}B5a6<1yb><`HS z#hp(QuuF!7?3_1041hyr75+qtwY>Bq;B0(CR`6A)AjE`5u(BbqgUrGnKJHRd;#)th z2*B(Uo??>C-;Q16C6&xqMrJxhhL&Y!^ZjDmG`}zZ9l-x8&Su7cH;y7^EU6e*ISn(= zog@Yl5;RK&CXu5fe%Am<>NB!au5B9JP-ht>?&_O8;SBdFkJlg31DHV5VdDD`%L10r z$3!_=0Mx6qoAZ5@0s8^2vFrjZmrB)tvl}%;$vn!hZmFt%XQx~+Rtm!X>g9oc0ouRx z8uvokgZ}V^Sc#0vnspQH>&c(0=YVh6k%Z<`FQZ1!fdAxd{L>R!!woX3Lkr<79^3m( zJjhrdW}*0^r6dz=nD^eV*mM!Co5O$gOH51p12=_t=1R;T&$&SF$BzY5UB{&o$K#;g ze94^>(uTU@c!kIpDQDTE;r4#~)>r2J?$vTA>-NgZ8n*X4@pGK2G7U>Oc_^yX$u6N? zYhrvUm=bWhHXBWqtY!}e_^r=WYSYgIRR`|8S+`r#&z5KSoaoOOA+^K zH7WShYGmFlOz80Z6YGx18J2g;%u)aJapxBd4m#3dBIY$22ny8Bxfp4a~)5I(S!EuPk9uRIc}HSM)M5SiirVOkSGIme$;P|%kvozGC=6f@rlC?2 zNi8P$iPd?FYxQ&g$^_~URbQ4D0^qsmf}bF}?18(QccR>&3{V_x3_Ot2wk^h~!i{mV zb`ZLGStxPXQBFU-*{Nkd=f1-1>ni`ek0*h}vYF4$fvcY!D1?nWVQTk2Q8^3WTc)^3 z@;v=jJEi>X`)PqyzvE6V6msMWf(v-vSGVa;^8OWEy|=XI@9gn4g|9?{cR6n5Mz1s< z0AI?!Upr#zm#z7GWdGH2SDh_AU9P_Vv-rKk0K;v{>%A`*YGGg_W`rnu*xC20${BI^ zQshAH&3-G6qA@Kkt%n9Fz{EeKJ34U?12_E*m0zMAW7e=8(=Nw9eonQ&z)q}yKHEPW zBO`InGtr37Yuh4*y;Ws=YI_#Aiu%5DK!MB?x9o_lxLIc8#Ib2GM$`VD4E{s7mL%Alppcxw1FyyyhM0Q6Yc5OhU4su z(woO&2p(ep9#w719r^8+NHf<|@^G)A21;Tf->w{o-IN&pb`wqO=Ax+^(&~jXwSrIq zVJ&c0nKTDiHsWc#WMNP!*NJ-j+|xmCUIc#wR1_PpH=p>ZI@k4yU^LTPzbL};f=5j7 z|4du2zUgL-`{@SvKD=`ij^u4`6xGB4*)o zMU9(l?Sdx3VBpXx&;n;Vr5W0H-}E+g}7=dQrkI*SD8&aT_Rw zklj_ga`}ph?X?`yr;h9HY-9@F`Ip_AKUUyS5jXDHu(!N?29&xB9`W@Ehwd{~*J!{v zWg-6)D3HfXPq+Jm&q}ascZkEuxA&H=vZ4nbnq9n~=DFM8V`&4 zTYkV6lIUAfrM@5PfQfvYo=?S!Sr;fR7%?k+(DF8&IXx|eVnuKsU*t7&nwf<+S@dQi z!Z6g77UB)eBz=xa5}8Y{k&ipykSM){&MolyIY!c1sCzXCuzxr<3j2*&TU(>U-xzvL zcK3n4r>SpVp-pX{$hZ8j6bhhkyrI!tYX#n!VPZR;@(Xf{r$8x>nLdRGZ@Y_hKG`(w zucLzjNnz8v`$HvXE4KkINHcz7|7wuo6kipIa+U^if%PM1JO zdIxz=^?wJ};E$N0IcM_^5;P>C9*sL~h^QeiAlv9jeC0^5y6lx|`P5HZ^3(&85KVTM z3|r*AbKD$o+F@N?e<1 zrgnN%MJtL~41nhf69s*z5Ea*Rit&dx zctS?gmF=rOBRZf<$9=I2>N|0@K~@-QGjP_U6z?G)j;EdUg+i{;^@-HFTHW z!u%FEvamW+U*y>WU$GcyQK{T_4tl6p4>j$$xq6qDmT)zFzqqJd%={N(6Q0DcY(h5h zjaUtWW#MM`TIlQhL|#6qs3ck8Z}>y1g{c|uvL0;LZ`$0x2$Wirp98`m*OdI`{LRIL zvGh$+m#=vIIlyJb71`AAS0cBYg%RCY+L63T3KfkDhJp}!u+DlsCYQSi>fOa)R#Kqu zU9p$nEK^x<+JRgwcj_O=+dG|1svHU+13V>1TFHHCao{cTU%6l|k8ivW8&e$J>yP7W zWQ0KlPvy+u-&#*n0@`ZhlP!Z>qwl zya)Qvyvu0HV}GjTu`dqtF3}bS7B3NoUfV|HH- ze=unFV1t3>E04%EYx?ef```oGo`LD^WJzTS?Y$R2X~D8<&r)tP|Cbr)>AKJ3gi7Qy z0PV7LiS6sG$eO;*VsDcX6ovQgveja)hVI_GrNvXB z<#aAhsO87+tfp;Zi|#Cx9z(sof$j0YU!N^0SnOp%X4B!N-zPp9NtS6Weg@8sca`+s z6u`=_!O4%Uv&*3{_M%XJ0s5mG-jT8jZ*wv0-F3r|-MzKv5PhEO$hcUnMYF!TV6+x; zjBQ*iPsOW!>}Ywvs3Ppz16Y*D>TAkWC3rh3V*hRqF|^oeI?p>@&3L|_XWn%2T25o{ zM^Z46VWVGnn~9ZYNet@RJwMFUH1((;GC=yOEDI+~$CN>5TW>`)p{(`s-uU~ok=^~~ z2Bo9^t*8h&LnLW(ep@(=0H-=093GA>_#UVq7^kbM#rg=^di)h&QC4#GCnT1=Z&FV6 z1-S!aeW*({Ue@~iotW^jm!21KAU_&_?{LS{$Jy0m0{UZ8a z*YSg?TmS(u?tFp|`Fti+9Te=`PWrZ<(R`k%>N=K-+ z@9jAeM*`uAe+~BVZK3>~&x$6>%-Omzr)|t9wmRX{QEX$&a0cc!rDuIgdr@6V9HHSt zl6toMl=yh5(1<$JI9s!4Y8%hGuy1%(K~|(7PcxNZs=$&CvMBS3?r6F-O;n9R2i>Xu zIznxK`KhY8xSn~%v)hsJV+!QgkXG3<4Yt}XIs|uaN>gx+>~2#8i5xJ$^8t)te5_wp z0HEJ*+1~BLY+J@GrutK+7w8&mLnwgZ?&sIU^FrC%u+J185Pt?En5_QdJOHnCzf4?jKT2r& z1rMfaore9nt!x_-h5!^rcSKv)p8w+ji>f9rR4mLfP-06N<7Tuf*YNJ zre=TQ%IFZUPmMYc$f$KFRCKC!#!VKxiyKFIfimO6enzGssCC=*vY1FKL}3WNL0fD~ zltRgc=T`yp^|2*6nC?FZr{}DZ2BxN_2O+MLHma+|yA3i@gKE(O3Su#U2e zJih`qj}gFPy-);l=p_C`X&@&jS6fw-t**E1l1d3?c_#I6PYznitD6aM6)_5TD$e>M zl84YKl+N6ZbKptz0j-Rn{hw+Q3>+~Hm|$I~(HD?zR3PIVZ1u|Jhp-x_J(OcipBuDK z%}NRe{7(A%H3Tx8A_Jub@pomeDl_rynfeVX2w`@?>sx?#ZV!^j%7L*X1p1mQRTNz^KB zp{rrK_~*0L5Uvmzcg&uN*+Cihx~1B37w(inOy&t8WL$z!BL#5J;XR30HgF}Dxk21=PY(5yX=AP%hp)%t&!!7+{cg~XzXQ@Atg*!A* zA~UyH{n)tq51e9XJ%>a1AOhp$k*cWG?M!=iYi=$d7cO|7)$;NuM6{JD)%`=$=Ho-y z<#FNqJ}jT$_B=$v3MI0>ycmr;{q(#2+hC-pmshUar8Sib2UwSbQ0h(G$pbn)M5F8Y z+@eXR01enFuy03!RK@*7L zgZnn1v}Rr*VOwlnNk8ZeFL}d7=z!vVk!U3V4|eB8W-Sg3|x)N z(Dgn#M-6P zdb8-ADoBVvsHG3FN*;1mSi!u1ZSrZvd!UJ|dcG-({|=t#-LuvDqG>qb=3he-)$hO} z)rR_@^b$vwkMW&JGAkysI_cu75A4BYIO7fCI&EewwRF)R?dPuqnC1MXd0!o<7WooJh-&j z`%{33tK@|hX#q@DEyVlM;w30QrbO$_L02sM*3QsvMD*METOc9T3+Eb>0}+S{Oy^x! zHEW>4Q<05}(}*u5O?W@#-E;7Vmy9xjRi^zJFDnKc$rRRJM!W_FUKeI5n+8X5U#{#R zpzk~b{^MD#2Js|H^tmldb~GP8#kcYytW?xYmQ-@qj|_hia1dkN`%^EGD(aBTW#oV+ zBF>`}GI&0DTnhb>9=XEfe2uP?Ar%>jpd@~yym99_{>F0LA=%S7h@*D*kAC}6nDH4@ z*3-RxwOh|<4PrNak~(PvP#<_&Hr7tIR)P`~^~8q1;zsPHeNm=i1c)?JLb#ldHkksk ztRprA9lE%;x0iFsoV2_VCXX5%6or3-+%Pn=D!sN3fTH3?M!B2(5SvRhR!@HKTS&3? z53UhP&i_;sVz@u+JDGS+3gAVcu6jW8dPHxT?;hSqbC0ajoKH1 z`Ox2QnGA`TI;{)C3tPv2!eJs_|YW z3fjaTys$d)-uligT>Pj~#SvPYa1i9o`xz)G6e8S9sMVHa(K=Vr1&b(-8{^j@XxTxg z00taJ(`)s$OA_$`g+zu*6>C^tV%{vo?8DjXXS-vVh+5OksD+(p^%YKQ;NXz=4AN|3Rf(Nhi0D z2rcq6hRG{OnF~eP@_CbFeq~+wPy|K^$STgNCTFBPI@K>JR8e2aW;-)!^c(;MSo7JE z%21tw)V+chtQV5g(JMd8>I^lfJs=zwdDT+JW6+1`&^3VhUueXb-dP%mvl4A;SOS~| zo-N5_oXI#}*I?f)EnVP$-4Z)gASqPu7zc$UhPpFEq&M^!(qqdmV&X$qJ}~$M6`Nuh z4@4IzK$O+V-zR%k;YrbI>aZI7)9m4JkB>ywOZ_Brw5Dtl)m`^NN+$0z&0ea<>ae^# zUkH>b-fW{rgISuAweNb9TJB7o5|l0J*ems$f5bF=T2a)X#R<`1iwlbxJtO()HJKF1 z8`x8$u}!j;cI<0VbT!R|z*@K3f^D%PZ6@GeIxAWvcwmUEZ~U(#$pCHHy}kMJgRWLN zWJ5wI83S?_%7ES*Tm=wm(n|ESu#frCo;d!x(#)K;303|#2M+c<208@ zi{^eb{+(Kt9I~-Mf@9!2A_Mw&zpck@Lc0Xv!oh?(|awOma)U8RTj0hJi1 zI%2VU$2AW5l|ZeA<{F6hsStAx@fj}@vAJ*uVRoEHpyi4QCF8^~7c_gO{Bk}zJQRo! z1M6j>q#@M%TceT?FZcZpL<6(hsn$@ub|e{7I84j+F`g{LvJbv%&Mg_~V^GiuAsf=4 zxt}dfKmGfMf{O-si~F3j*MEA?Try8hO1_!6+`xOtvV^N)k8I#=G9!J*9N)*X=`Y1FS&%OKT`gV!rbmQMo6cHE1+v7|V z*o`XVkc`9!mL6}j>@KkR7FGI=bp15M={B1;Z1+`Pf(s3}=$pB0s=AH@>S^5{x~-ae vfpw2f)!FEiU-%r0QkW#>3(V7O(#o0ib1n