From fc584eddbe695e08befed621802aaea281019c9a Mon Sep 17 00:00:00 2001 From: Dan Scott Date: Fri, 14 Apr 2017 00:29:04 -0400 Subject: [PATCH] Add Progressive Web App examples and docs Reflect the state of the Evergreen PWA as presented at the 2017 Evergreen International Conference. Signed-off-by: Dan Scott --- Open-ILS/examples/pwa/README.adoc | 128 ++++++++++++++++++ Open-ILS/examples/pwa/sw-precache.js | 47 +++++++ .../pwa/templates/opac/parts/sw-register.tt2 | 61 +++++++++ Open-ILS/examples/pwa/web/images/icon192.png | Bin 0 -> 9964 bytes Open-ILS/examples/pwa/web/images/icon48.png | Bin 0 -> 1798 bytes Open-ILS/examples/pwa/web/images/icon96.png | Bin 0 -> 4126 bytes Open-ILS/examples/pwa/web/manifest.json | 27 ++++ 7 files changed, 263 insertions(+) create mode 100644 Open-ILS/examples/pwa/README.adoc create mode 100644 Open-ILS/examples/pwa/sw-precache.js create mode 100644 Open-ILS/examples/pwa/templates/opac/parts/sw-register.tt2 create mode 100644 Open-ILS/examples/pwa/web/images/icon192.png create mode 100644 Open-ILS/examples/pwa/web/images/icon48.png create mode 100644 Open-ILS/examples/pwa/web/images/icon96.png create mode 100644 Open-ILS/examples/pwa/web/manifest.json diff --git a/Open-ILS/examples/pwa/README.adoc b/Open-ILS/examples/pwa/README.adoc new file mode 100644 index 0000000000..8bc0e2393b --- /dev/null +++ b/Open-ILS/examples/pwa/README.adoc @@ -0,0 +1,128 @@ += Progressive Web App (PWA) = + +This document and associated samples will help reproduce the state of the PWA +demonstrated at the Evergreen International Conference 2017 by Dan Scott during +his talk https://stuff.coffeecode.net/2017/evergreen-progressive-web-app[We aim +to misbehave - Evergreen: Progressive Web App]. + +For a very basic PWA, we need to offer: + +. a manifest to give browsers the URL, icons, descriptions, and theme they need + to launch in a fashion similar to native apps +. a service worker that can handle poor or entirely offline network conditions + by intercepting network requests and rerouting them to a dedicated local + cache (if necessary). By bypassing the network, we can also reduce the overall + bandwidth consumed and improve the performance of the application. + +We will focus on the public catalogue at /eg/opac and specifically the My Account +section at /eg/opac/myopac. However, the service worker must be registered at +the highest scope to exert control over its assets, and the existence of a +number of relevant CSS and JavaScript files under paths like /js and /css means +it will have to be registered at the root (/). + +== Create the service worker == + +. In the `service-worker` directory, run `npm install` to install the + `sw-precache` package. +. Adjust `sw-precache.js` to reflect your site's logo files, etc. +. Run `node_modules/sw-precache/cli.js --config sw-precache.js` to generate + the `service-worker.js` file, based on the configuration in `sw-precache.js` +. Copy `service-worker.js` into the `web` directory. +. Copy the service worker registration template into the public catalogue + templates directory: ++ +[source,bash] +------------------------------------------------------------ +cp templates/opac/parts/sw-register.tt2 /openils/var/templates/opac/parts/. +------------------------------------------------------------ ++ +. Add the service worker registration code to the `` section of + `templates/opac/parts/base.tt2`: ++ +[source,txt] +------------------------------------------------------------ +[% INCLUDE 'opac/parts/sw-register.tt2' %] +------------------------------------------------------------ + +== Add a manifest == + +. Add the following lines to `templates/opac/parts/base.tt2`: ++ +[source,html] +------------------------------------------------------------ + + + +------------------------------------------------------------ ++ +. Adjust the manifest details to suit your theme and site name: +.. Keep the `name` and `short_name` fields to 12 characters or + less, and keep them the same. +.. Also match the `theme-color` `` value with the `theme_color` field in + the manifest. + +== Deploy the code! == + +. Copy the contents of the `web` directory into `/openils/var/web`: ++ +[source,bash] +------------------------------------------------------------ +cp -r web/* /openils/var/web/. +------------------------------------------------------------ + +== Optimizations == + +If you are running the staff client with requests proxied by nginx, you can +take advantage of the support that has been built into modern versions of +nginx for the https://http2.github.io/[HTTP/2] protocol and gain the advantages +of multiplexing by simply adding 'http2' to your `listen` line: + +[source,txt] +------------------------------------------------------------ +server { + listen 443 ssl http2; +------------------------------------------------------------ + +We're loading Dojo on every page, even though by default the only page that +absolutely requires it is the advanced search page. This results in +approximately an extra half-second initial page load time, which makes +https://developers.google.com/web/tools/lighthouse/[Lighthouse] unhappy about +our performance. The https://bugs.launchpad.net/evergreen/+bug/1411699[Don't +load Dojo widgets] branch shifts the requirement to only the advanced search +page. + +Our "My Account" pages are currently hard-coded as `Expires: -1` and +`Cache-Control: no-store` which makes browsers reluctant to cache them, +understandably. The behaviour of the `sw-precache` generator appears to be to +respect the header and not cache the request. Commit e7f11d5 in this branch +removes the hard-coded setting from `EGCatLoader.pm` and enables us to control +this in the HTTP server configuration instead. + +See https://bugs.launchpad.net/evergreen/+bug/1681095[Extend browser +cache-busting branch] for a way to greatly extend the cache expiration for all +non-HTML assets while still allowing changes to propagate quickly, if +necessary. + +== Limitations == + +There are currently many! + +As the public catalogue currently appends stateful GET params to URLs, even when +accessing `My Account`, the cached content can often only be accessed if you +follow the same path to access a given page when offline. For example, if you +start a session by searching for "Potter", and then click on "My Account", any +of the account pages you visit will have a `;query=Potter` param attached to +their URL. If you happen to perform a different search, then access "My Account", +you may not be able to access the page at all, or you might see different cached +results. + +Searching offline doesn't make much sense anyway. Ideally we would detect when +network conditions are bad and serve up an offline page with options greyed out +if they are unlikely to work, with highlighting of options that are available +offline. + +== Icon credits == + +The icons in `web/images` are based on the PWA logo made freely available by +Chris Love at https://github.com/docluv/pwa-logo under the terms _The logo +should be considered publically available for everyone to use._ diff --git a/Open-ILS/examples/pwa/sw-precache.js b/Open-ILS/examples/pwa/sw-precache.js new file mode 100644 index 0000000000..dff6001dac --- /dev/null +++ b/Open-ILS/examples/pwa/sw-precache.js @@ -0,0 +1,47 @@ +module.exports = { + staticFileGlobs: [ + '/openils/var/web/favicon.ico', + '/openils/var/web/offline.html', + '/openils/var/web/js/sw-register.js', + '/openils/var/web/css/skin/default/opac/semiauto.css', + '/openils/var/web/js/ui/default/opac/simple.js', + '/openils/var/web/opac/images/small_logo.png', + '/openils/var/web/opac/images/progressbar_green.png', + '/openils/var/web/opac/images/main_logo.png', + '/openils/var/web/opac/images/eg_tiny_logo.png' + ], + stripPrefix: '/openils/var/web/', + runtimeCaching: [ + // aggressively cache images + { + urlPattern: /\.(gif|jpg|jpeg|png)$/, + handler: 'fastest' + }, + // aggressively cache stylesheets and JavaScript + { + urlPattern: /\.(css|js)$/, + handler: 'fastest' + }, + // cache added content too + { + urlPattern: /\/opac\/extras\/ac\//, + handler: 'fastest' + }, + // results can take a long time to respond + { + urlPattern: /\/eg\/opac\/results\//, + handler: 'networkFirst', + options: { + networkTimeoutSeconds: 60 + } + }, + // prefer the network, but fall back to the cache + { + urlPattern: /\/(eg|js|opac|staff)\//, + handler: 'networkFirst', + options: { + networkTimeoutSeconds: 4 + } + } + ] +}; diff --git a/Open-ILS/examples/pwa/templates/opac/parts/sw-register.tt2 b/Open-ILS/examples/pwa/templates/opac/parts/sw-register.tt2 new file mode 100644 index 0000000000..c9681abbe9 --- /dev/null +++ b/Open-ILS/examples/pwa/templates/opac/parts/sw-register.tt2 @@ -0,0 +1,61 @@ + diff --git a/Open-ILS/examples/pwa/web/images/icon192.png b/Open-ILS/examples/pwa/web/images/icon192.png new file mode 100644 index 0000000000000000000000000000000000000000..b978eb0b02336605e2c762761844b250ff3a98e5 GIT binary patch literal 9964 zcmd^FRaYG0vK=hAy99TFy9Esn!6kTbpWv>8yOZDnf+fM--QC^Y-Qjc|@5B8A=ge9& zU(4#A>XKc%sybX*Ng5T22nhrNp~}igssd~Kzc0c&;8%6o79Ln&EyNVXK%k0PoOt(DURn}ZfzN|P zlOM3aJIgA5g5Q84#NnoXHDV42foRTUCB@X;7f&)hzEN&sg@doc@BSiK0KT zPp*KXX)`UMEI&l!`S(u#*KG{zN?zxFM}&?$u!rn=AoO1bauN?C+=o(drJPE&aLrGx zfJU6O%W+c9AeG5+x+N%WZMdZR{-Jvm>+){Md%~Wu{gMzU?lOrN-W)Im0`bKXH7u;u zMh79^lW?~YvFchczEl|$M|_D(`IW^qfHbe=cD9Jn|u98HOxA4TzfX`S7f3(8fvwlU6io~u9q zone7aPc+TT9$aA{FGSGeKd`@P{)9|E1+I6WT`&BxEmK2}_sG*q|Cm0+^=?s2D(eb< z;z0xi-6?i6-i+}D^j+#qg5Wsn_7HmxDj{FjTq@@(W)(dR3OEx|hHlR*Mjgji!%l$i z!#1NPF6xK8%%5_KH)c}};y~p@;av^Vm8QT_4T+JRlu9!W$}I%HK8?>MoNqS7qH>_X z#P$XCZFQJe6+A8dU}xRI`>Lslr=g)yzhb|*xVV3GB=45!>%QDj?#XIt8X0Ms4!cp`Mucg7fv?s8~`X z1>H{1Z6h)<_dHMOU3^X@4HxO|O7QK2=YOL=MaFgxwG@#I~j@duD3(X#!EUC!;5fMlv zXwpQmY~R4R?oMz+sRBhh)`gXwN>&vCQw&AF!Qh)MP}^H*5Nse~8G{}|7F7jh-{<+Ql%EQ&7V~lo$2)_cwIh z^^ODcb-3H2(d#3cNQ^)2^J~d5qmzBiuc(M0^Eq|G!NDOfpk`%_752KtKzZkJzAiSn z#D#5u#5x{<%VcS3Nlr&cXa6iLEKDNonN(X_n^a3fx3perIJi63syqDlJod@^!iZ;8 z4+d6JJVAzD4kxVRM#YadHWN>m?x#*#c({b}S=%H7TkkdTl-HOfb4XN7>oq3C3z z7c+^4f1v8c*-A@+9dJn<=t-gx>u_A#>Ms-Qc zp_%-4z9!VxR+><<=P9`7Nm5q0h1z{VxvWgAkrA8$E=Bv*<^jOi1cZcQ2rikGl^kd! ze45Dt)hxGk;$LW6*k41Fe}V z_|qn4K$49&?bpD~(Hy_iE=qtX`9~~u4UK;aK|)4Wn~eF+;Q*(ss@mD=^F$BWiui4Q zo`B5vo}$iSEi0%eE#sX0^$Z`)?8@&|i+$-RdGFvMmGrFugN=)t-^sU=sOL1~QY&YV z;@&gCx5hmnQ;RV}QUN@_!9-m3Fgk~{(A>}8Q?sjtu>nqt#AkJUefAK~RraPXDlRr2 z%Mx~PS>2cFG8Wg(ZzW5#P-=3AHhSKBHlJ+EzFi!% zan>R47_spk+_hTIFuI?Nhgy#bLT&HvPL7YaSDFoh%p~Jws8_K^GKV-T_O!fT zjdUk31Lm7<4d#K7<6<~~b-mZNMrXJKK1 zi;Jt=^XBm0DP9Irs#WHAI9;4%Kj5Huwq5tC2qlld5H5*TNR+4`2p)##TPE0lGps_&Pwvzl%%P&O8aj>A$zGAR3Y<$&(- z@KE=7KoE7)TO966NJyAlT#Q&aC2MEL403JC)H3u*R;KShm?}gJ7H4P@nKD~NXy0+H z@Og3ta4*z23SE!aVRd_ZAd%tbW^a%1`H*#2?JfeF`;d;P8Dz{jh7R5J&Q~OZU!*tt zwFiML<8o^8HA97Q2pP9@ePSp70KI*dhDFX1by!<3L!q9QTyfx4tMY#K7US)rA0t=h z5U&R$AtAxV&As8;q*G~%s492tDyUm$Z)R&7g^bT)x@>>ZoCdvc;#zCB)SJSrn?Q+i zw$juGMAi9&Dn7ac!FhDq9@x_FcG{0Rx+qoc@?0g%@2=^^`z2lY`N8lZ%i$UHF!A8` zbdxX2o9^GpNVod?LYL>8jy<%Jp!byvdXr`&_A8^y_4PG)yC3t*moJ-sB<1Wp3K6SuTQ8D)W zTPIBbzOWASd$I9(?lF8ik8ZCXB>cOGyvkAk8nXx&foT95GlHAlCWh{f^NlVcpGU5OlW%;mZP!;1-mjvyUycW4qjZW?His8LZ_oH%d~WP< z>sp$d%iR~&RosC56o4nfAOvUAm{7}v+PB*yE=uSo5II1S`m;mcB+IB zhfsoK3mo6{^zz(Y0W1YbqO7m~zRk_PF8%V-(bLO|lU7pL1dbe%Q(K$T;&r!q0Q&3t2baF~rskwygw6W7AGc3nK`N@^F&i0bDmY~om5z=ecm`(XXyUf9y{-8Q zljT+)uU&k1s0buf-vh(lD(eFIKZ>7*&#|STq5N)YW8W@9C8#}~Ay7jGq52}oGe>#B zzq@f3^i*G3x=_tZbKDuOg#zO*7$mxryce;}w%+yU-HZv>B{dfHH@!%)L0vX$xIo-UOb8#@V(Ik2ax0;lCW+tIpI@m zJH~lF_b^=@Z9R!ogwew-WV2?9e^y4}erf*;MH5Jqr)YA2LMjdGuMpw}a(~ei=Y@s} zKSGg?QCAA48G{46swcA+<*JlPAp7iLEblxhvB_5KPX}m|pr@2knriBJ4x}(`Y z@{2ny9#^zv-sfV2Q-pnlb*`Z+IhBlyFVe!y-<%>-cAMu&wyoy6i$<++=XthVB6c9cJUMJi<4y#ck<`Qz@NeR2VyGfyZ3eoL5Slgz=7ukug$^IDCwV(FM*b)t- zH##kLPgtXp2AL0a;;xR3b>*E17o}pw$Esj7c;;R6_84L`}f%PIRwHeJjmcH$_$Ps?2 z7js9MYLFw+&lFx_Dg5`=l?jOo(8dUoi3hl6runwL`O#x;xa+6g9#9HZ5LVlK3j&r46E;Q=}Peo zbn-=5$w>uSV=Ey9h$^{bWSc9zW*zJdB+~tRin%#_{D8S5v$a;A>FMd=hnp!%e_STb za<4o4%BreFaS|X^iAzgM3;ej&dxWRiQ2x6409jri(0jzvSaO<0VQv(|lQpo2f~D~T zclN!#g41pTz(RNoDWMLOganaBgR*#Ygq@}uwEw81su|@D^gkYVw%W42vqKZi2juSp znpO*e>$_0IU~D86nuVA}XGT`eb9Y+Xuc+1Rf7C0+Bth?Br8RQ&pfRzPM9!~<{5adS zUW?M-R=I|wZ`q914n9%t-^eO_=Zg?ZUrABQPg-ttiA<#X%po8^gfC`g#Sn`2{^!r1 zUq}CDszNDf^laQ;Y;p1OTG(n-fVC%AaGB&k%8vel1mh|pUD2t_pZbEj^sB&u^3H$Q zm)}QY_~7};IM&egm%Vj?4Bxg$eYeiw@9Sw~=&28g&`f@Oe^}{dQ%sB%c}-I*RHE^C zWn^LkTzxNN2e0r0&d;12|B#Rn_g@(807<4(%ILpuOb{1+v9Uj#<;#0-VQWl`EC?V& z@5Y_9$D{yhrviPBc;=9KV-EHq8%n5rgZTRe43dBf<1l#hF!xeVZ_H5G(E7RBL);vq;x}MKGderP0qbrdyHUXADu)FG1n_^S z$hU_aRmy8A~>CT@bXI{nmK)KhS%mO)HVc^lqoew7OodBr-+l=V&DGb7{-#r0Y zBB#2V%b<7MzD`Y3Gi2?ou&RpFWDb;*!P-EtDuLG0 zX&6+t%f?MhA!jj$c_Y`m4n)`;-9QK{SFFlK48q(NMfcE?|j{65~0Ggj4uDq`&q@6TR zX$v;S^YZclZk7}g5#gSax?*2gS&5ZB##_h`qxN)AxQ9k^`Th4Fr%DfrV}dD2B2iu- zSO88VnMWxbb$ljsT=!ETW5xnX@rtqZE#!!f)E6K5kXK!&+i5NI=#2LIm_484HAeS* zooeSjZ_EYc zB!OdRL$pltQH7Eb`{LU4*hdLBUn*PUkR z5|=J8FP9(4;+0jXF)oSk>X;7WkXtyrr0v97Gf(k^lm^mi&CS^Sh|S0fg|*6RTpeHZ zRj+5_Kzi;aNg*8IzYfh8QbHtBK644_ybhDo)7=1=qLiI`PbOe+^6~Yruao~1m+$=d z?+=4RLkFj)zuMaT?1|S0H6&gq|CEEVx3!8IZY{1oS6VP@TMo@1RHdC8Q^q5aFmK|J zG(R{Qajrk_kau+dteaG~p9m(_uy614EBz(?IX(A^<>yX>0Lj^&HZd`ga}1eE!JJ)N8|&{!n3;v)2rN%f>+HvXKlHg3Rs7Xy?ff3=+DZ8)>RWZlWvJ_;(_xPFu4O<Xo$g`Bv zabGn>JE2dAEX#;%vXgT-D|Wt~@SbFxT2tfz1pQJ>2WY9Z>Or^mhxz4ESgb{{AF$*F z`AtpfqU3Q&Y$rFK3@j|aYHD0=v434L8Q+bSZevNOaNscX1r0OK79EHm-B{kvR#9{_ z+hJO#2xt?pVarhCwXue!1&a6$NnZsaI^Ah_<#^-jJrHvfDJ1?teek}(x1RUTNzzzC zF4oD8Wm+1YR}P!VWxxxo7}L0FjG*-Sn@I63KSFfLWxtWPY0dAq&O~Ewc#jkI(2BFG z>*zVs6x|>G4%II*`js-B2#-uU=bKV9P$J0MhFrxE4xNZkR)V{ zI8{y+xk*W7tu}DM9fHcDhje~&hPFX03l48=84MK>Kp<;-`M!#0jDV+ZuJX2ngywC7 zslns~6>iMg&+1g+twuV;gBz!{ZEi{*wT9mtMNLp?ti|x1`zB7mf4b!XQUw?I(cN7v zI;1KJBM?Z=)WKc;CG>9h=f*(QY3?3O7E?{vlm1KA!h#MhGzdV9di95d2wG9w2&8X84{GMhvdcL>| z;a}!5hSI7;nf1Z6CkYwV9ph3#U_%j0>Fe06@vwdHW_W6C2y>d6Yx(OTw6H0bXcp_ZEtV4;x;rQx6f zK_~;b_LspGQ^{}3KsVt#rv+X37myrZ>y`tL42zI*W zx{1AQg*L^dxY39Xx#SW^?Jxt7?0{q*_pzhaqU;yB{fb<(E#earu>Q3W zb#!!|S9`y9e0){s1d-#FjK8O5M=kW+5C+aVc+k3~v7@b-58c|KeVo3!T=w_#wH3;B-s=d|hGEhL@Dy%uWKa z6JrZ`*@B=9<2|x9ay{X5JI@w9K($lb<;nY%OTsZWt> zJp7`;Z}&MIQwxhKfa)I}9&R2rYA?U(0ku(T6b`5zXoLgZ5p^xCKJ<3i20e9k_3@>p zr>`De9hffX8C?af_jfkH88q0N*_pn(p-zzhawSx#@gpS4+)vo8 z8w=XHwqzM{bk^~Lt}(XuCW$D#ZNbCa@|EsUL1=m#$czk#-_lqJnLx@E*e@?HiL+^E z2L~P%gP5-r+;qOqh*_&Z4qw3@yeBi%Y|1|2omS61y)tqtZg6rhS+(}gWug(nuCQ_H zoXv(zKy}~vNlJ=OEPvJ3+cSI8V*1u-r!e4NgxTdoVV`lh)9*(1ZDU0#{0nINf-M^w<}a>6RSOhXSomFTUhbE@(7DLH~u|&zwlwIc@j_*I2GQ zgY7fcvQ^;h=dhb8o~HF0)|9G}R^?A0k;5@U4tG!kjIq;<5grshzx37L+vE4Ot@TR# z%_-d_PUNGqO2i$r{|IBt`K=i(9?Qx!F}6v`i`m6CUu`wTN%trOl zv`uq{b~Z{%NG2`I$R~8Z1Cdb}jXj)%GNV_GZ<1cw;_M^MEP1-0t)%|0T zWM`rw&81GQtrI;I0#v3OE#jZ7_YjN=N8WI{$LiYJ%T=$lkrAICR_O!zm!L6V@^`Ul zQ&#b>%9R0?YL`(|M1@BuRS=l4Fft;yqd=RY*(wwb?;b_^mk^ih z*-3fTb#>**F>;EFt?(#i=uV%d2rYxqUomF=2oFCNBCTb;U`yT=%5*^`mlZj+BH@X< zwtnGi60&~e6cTnjyjr>r%nKOG`z6w$lDy3UAGumm!gzbUAfck7qS}yd(idaq+(4Wr zO(hxy=2OtsCHC;}NJ>iTzLJ)gm#;vV0M@T3tDlXr{1b_-ZXYX$IL=x&BQ1v$B zfJ6bUwX_J6a$w4rmlYL}V<3!AOt2S9l%2aU>3(TdJHb^*F(8l@*CeI1fZ80;Kq#=p zrZ1HFBL+;!90mC4zn1uLzFQX576pbgU^_4@%<< zN8Mwb)Xi|qiX@-Q4HbjU8Qv8E6Oc2XGq0$a81sG|d)8igDv+{tsX;wB;PliU?}N6e zy!_B|vM$M~%HQ$H#eHmSCp$WfqiDgiVe8Kd7mnOJ--qupt*zB{;F;VQE}}=3CMuNa zlj19cMLw`5gG9sE0phpZ=I3Y6N=*eW#Z0jcSWd7~utCvSXn5&8uIVUeBJ&f&z1Yzc zDkC?(n~OaRAV6>cJcU{x~eMJR~6j#CrZE<;`8%@ z?pPKf_ZGGi**538ntx@5ZuHc7@IC{~ZglW2B35u+lS6j{iEPWM%bL)3WUkEQZYS zgT(+U4q7p#W_54kZO{H*efxWzZE=%eypo?8A4#&n43`?Wso3PA)8E>QJt{u_bXf-`8Kl zvzbT&Z;!xD3}0UL6Z@M1UEoamE<01_Gmboj&Sd#_z5iox5m-j{rL0)I`GnWJW_w_$ zvspHLSe;`Rxw>hZ1w7#Bvae5#;KN)pxMaC@d@9^5X*&EeHH;Oa9}W6d?DcGw1D8|5 z<%#*bg6j*2NIvi1-v8jn8yQBZdAZ^w?;h|v7>)BMZD&(sXEOm4M>Ajnaj>!TGP7|q zb8xG3unBPS2(WQ5v9SrTu`LvM*Z!Xi>>Nz3%su}93ySW$|Gn1+lKrG4`B&U1@IQs3 B5J&(3 literal 0 HcmV?d00001 diff --git a/Open-ILS/examples/pwa/web/images/icon48.png b/Open-ILS/examples/pwa/web/images/icon48.png new file mode 100644 index 0000000000000000000000000000000000000000..cae1525a93eed499ce9d832834300ae56c20e35f GIT binary patch literal 1798 zcmZ{lc{tnY7RP_3Qv1?NBQeyPQRPa7P?c6BR7&g`HL=GomQEVWs4Y~hmYR;G)Y?%U zN-42i7gc-J61v!HnTjQ~g(8;R^v`>r=bq~c z3nl{LmVRJjTw)V?Rp3Pc#&&GiOII_0tjb?*053l^m|QT93+k;sp7aGPP+XsWh=*7H z&K<4XTQFi8ak-I&Ow@3sn(?MI#xaoZ&M7*~25j>`mraV`BUN}VT4iH@G*3Gzdf0y% z#V-;Qu@V00)|WdTMCL!hDht}q=z0GlRpX@j)F3RuMjfjQt@2}QS@ScwBxc6OLu=fYEAQ8C6_ntW!vvG4&-zE$z&PkP{BV?D3s$? zg+>w-3N?t_R$ZawF&MVn2S=d%8JJA_F+Hp8DvDr+I9jF~#O@!uX5-!XTQhqSi%R&T zI8)v)&1Asqq&_f`uA&)9tUq&BW@`8TMTr zxAP+i{mRXyDWPC+dZ&dprZc!t6A_M|2ZLu9-Rsgie7y?;8Cxf`pl&)}Jn&i*VPIg6 z%vX~ZCcg_AfR6a-Mi?oinyKVyyTKm!2L-GdzUUnJbAcxD`H5iO{J};%1N3{v&N}z% z`L5LHZS{xU#m{@2cL}WZnU?+NtLgGr?sd+Ow*hqL!AzCwe!;;$BvK+tr@0LC%vRv6 zYPQJV4r#?9e72fmDax|cy6S+x-}d?|3klGuYsxYvbL@lMyu7!(F4CPFe}1zQ;w!BZe0vY#ChRNC7vaEIL zVzNsll-PNA+U?XhUH8wp_&*kftm4fYl({rfpF6|R$4^m7@1RQz7*`*7FT zdl(v$btp>uoU;EVqg1hT*2*bLu#NpF^|<$yDsE?YmoYOlSZ0yqL?lk@-chUAr~A>J zAqomGNx{&yPgQoR^-%^9um3O^$Z!vXdP+>RiU^zFM<+9yLo*1mV@VTAb+SX7^JVH@ zu?1da#|wJlEkD6yB}Tt~;S?4sfIuKw2t?^8@sR#1jZ=VlGHtBf8gc1T{4n$4hNG@d zeUov2M}RbI*aY2CV_=p%&=qw<>DQ${eS_r>W+&5~;<6%ZsBgCP=SCj7!!wJZD#!xGOGRoq2h+8IaP%{Q zY@c`Ehl3jzccUP3a*HR&haX2KT@m^SL?=D)b7(VBHmzqHZJTH!{$8v2lL?z(al!6f zh|pxzyxgmVhWV|_TM*JMpXlhP{r&wFm&u1_OM8b;ii&*6Wb&fBvS?lS8-|$D`Ikdk z8Ec~OP2u{z_-Vm0ZsOa;HVxk2Cy=cBfVv)0CNs68+b!WQ$XThr=nkuX3=4hXM(v82 z)Qj)pn~@GKT~|N_B@_S#R%}1HroH!7WZdHeSL7p$W!!fDZhUz7`yzrK9Jd12@z~8p3rh!r_K+_(WNB f!+#0LAtZmF$p0^RvETJ$;{iBRD{Qrid%}MJRuMn_ literal 0 HcmV?d00001 diff --git a/Open-ILS/examples/pwa/web/images/icon96.png b/Open-ILS/examples/pwa/web/images/icon96.png new file mode 100644 index 0000000000000000000000000000000000000000..d7d101d601b6e5901dd568bc59dde091032ec3d2 GIT binary patch literal 4126 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 ZFTDPLfs*sye}4i1RYfg@O1Ne4e*m*yrR@L! literal 0 HcmV?d00001 diff --git a/Open-ILS/examples/pwa/web/manifest.json b/Open-ILS/examples/pwa/web/manifest.json new file mode 100644 index 0000000000..364d51e566 --- /dev/null +++ b/Open-ILS/examples/pwa/web/manifest.json @@ -0,0 +1,27 @@ + + "short_name": "Shiny Cap'n", + "name": "Shiny Cap'n", + "description": "A shiny Evergreen progressive web app (PWA)", + "background_color": "#007a54", + "theme_color": "#007a54", + "icons": [ + { + "src": "/images/icon48.png", + "type": "image/png", + "sizes": "48x48" + }, + { + "src": "/images/icon96.png", + "type": "image/png", + "sizes": "96x96" + }, + { + "src": "/images/icon192.png", + "type": "image/png", + "sizes": "192x192" + } + ], + "start_url": "/eg/opac/home", + "display": "standalone", + "orientation": "portrait" +} -- 2.43.2