mirror of
https://github.com/a2nt/webpack-bootstrap-ui-kit.git
synced 2024-10-22 11:05:45 +02:00
IMPR: caching service worker and minor improvements
This commit is contained in:
parent
025cb00bc1
commit
0dc2834870
@ -1,4 +1,4 @@
|
|||||||
<nav id="Navigation" class="fixed-top navbar navbar-expand-lg">
|
<nav id="Navigation" class="navbar navbar-expand-lg">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<a class="navbar-brand" href="#">UI Kit</a>
|
<a class="navbar-brand" href="#">UI Kit</a>
|
||||||
|
|
||||||
|
36
src/html/_components/Alerts.html
Normal file
36
src/html/_components/Alerts.html
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<div id="SiteWideAlerts" class="offline-message">
|
||||||
|
<div
|
||||||
|
class="alert alert-danger alert-offline alert-dismissible fade show"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<div class="typography">
|
||||||
|
The Internet connection is missing right now, but you're able to
|
||||||
|
browse previously opened pages offline.
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="btn btn-danger btn-close"
|
||||||
|
data-bs-dismiss="alert"
|
||||||
|
aria-label="Close"
|
||||||
|
>
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<noscript>
|
||||||
|
<div class="main-bn alert alert-fixed-top alert-danger" role="alert">
|
||||||
|
Please, enable javascript.
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
|
|
||||||
|
<!--[if lt IE 11
|
||||||
|
]><div class="main-bn alert alert-danger" role="alert">
|
||||||
|
<a
|
||||||
|
href="https://www.google.com/chrome/browser/desktop/"
|
||||||
|
classs="alert-link"
|
||||||
|
>
|
||||||
|
You are using an outdated browser. For a faster, safer browsing
|
||||||
|
experience, upgrade for free today.
|
||||||
|
</a>
|
||||||
|
</div><!
|
||||||
|
[endif]-->
|
||||||
|
</div>
|
132
src/html/_components/LoadingSpinner.html
Normal file
132
src/html/_components/LoadingSpinner.html
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
<style>
|
||||||
|
body,
|
||||||
|
html {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #fff;
|
||||||
|
color: #333;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
#PageLoading {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100% !important;
|
||||||
|
height: 100% !important;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-ms-flex-align: center;
|
||||||
|
align-items: center;
|
||||||
|
-ms-flex-pack: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
will-change: opacity;
|
||||||
|
background: #212529;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
#PageLoading .logo {
|
||||||
|
filter: invert(1);
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
.main-bn {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 99999999;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
background: #ff0000;
|
||||||
|
}
|
||||||
|
img,
|
||||||
|
iframe {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
.loading-spinner {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.lds-ellipsis {
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div {
|
||||||
|
position: absolute;
|
||||||
|
top: 27px;
|
||||||
|
width: 11px;
|
||||||
|
height: 11px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #888;
|
||||||
|
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(1) {
|
||||||
|
left: 6px;
|
||||||
|
animation: lds-ellipsis1 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(2) {
|
||||||
|
left: 6px;
|
||||||
|
animation: lds-ellipsis2 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(3) {
|
||||||
|
left: 26px;
|
||||||
|
animation: lds-ellipsis2 0.6s infinite;
|
||||||
|
}
|
||||||
|
.lds-ellipsis div:nth-child(4) {
|
||||||
|
left: 45px;
|
||||||
|
animation: lds-ellipsis3 0.6s infinite;
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis1 {
|
||||||
|
0% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis3 {
|
||||||
|
0% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: scale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes lds-ellipsis2 {
|
||||||
|
0% {
|
||||||
|
transform: translate(0, 0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translate(19px, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html,
|
||||||
|
body {
|
||||||
|
color: #212121;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: #007bff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div id="PageLoading">
|
||||||
|
<div class="loading-spinner">
|
||||||
|
<img
|
||||||
|
class="logo"
|
||||||
|
src="../../img/logo.svg"
|
||||||
|
width="200"
|
||||||
|
alt="UI Kit"
|
||||||
|
/><br />
|
||||||
|
<div class="lds-ellipsis">
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
<div></div>
|
||||||
|
</div>
|
||||||
|
<br />
|
||||||
|
LOADING ...
|
||||||
|
</div>
|
||||||
|
</div>
|
BIN
src/img/logo.png
BIN
src/img/logo.png
Binary file not shown.
Before Width: | Height: | Size: 213 KiB |
59
src/img/logo.svg
Normal file
59
src/img/logo.svg
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
version="1.1"
|
||||||
|
id="svg192"
|
||||||
|
width="428"
|
||||||
|
height="428"
|
||||||
|
viewBox="0 0 428 428"
|
||||||
|
sodipodi:docname="Tony.jpg.svg"
|
||||||
|
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||||
|
<metadata
|
||||||
|
id="metadata198">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs196" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1366"
|
||||||
|
inkscape:window-height="768"
|
||||||
|
id="namedview194"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="1.317757"
|
||||||
|
inkscape:cx="214"
|
||||||
|
inkscape:cy="214"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="g200" />
|
||||||
|
<g
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Image"
|
||||||
|
id="g200">
|
||||||
|
<path
|
||||||
|
d="m 181,383.58077 c 0,-0.23058 0.72754,-3.25909 1.61675,-6.73001 1.97697,-7.71687 1.44479,-18.73402 -1.16417,-24.10076 -2.12511,-4.37145 -3.68034,-4.74029 -5.27063,-1.25 -1.48991,3.27001 -2.9789,3.17252 -3.81834,-0.25 -1.00541,-4.09921 -4.71741,-9.12638 -8.7744,-11.88317 -3.04429,-2.06865 -6.17805,-2.7485 -20.34392,-4.41347 -21.51358,-2.52859 -36.86021,-5.25489 -51.24529,-9.10363 -15.955859,-4.26901 -18.952271,-4.72225 -31.668213,-4.79012 -6.142516,-0.0328 -11.904428,-0.34212 -12.804247,-0.68742 -1.439631,-0.55243 -1.368944,-0.91211 0.588823,-2.99605 1.223671,-1.30254 2.035582,-2.52663 1.804247,-2.72019 C 49.689274,314.46238 45.45,313.37179 40.5,312.23242 31.18871,310.08918 18,304.77524 18,303.16682 c 0,-0.50425 1.267592,-1.17034 2.816871,-1.48019 3.027711,-0.60555 15.381466,-8.53309 15.874152,-10.18663 0.163877,-0.55 -3.28168,-2.07262 -7.656794,-3.3836 C 18.540277,284.97195 3,275.39033 3,272.06456 3,271.4141 5.6989118,271 9.9382768,271 17.643494,271 48.70993,267.26171 50.820545,266.08055 51.749787,265.56052 48.587352,262.61388 40.582557,256.54118 34.212151,251.70838 29,247.55801 29,247.31812 c 0,-0.5493 -0.04282,-0.57417 15.219132,8.83794 C 52.304772,261.14251 57.977494,264 59.790993,264 63.253915,264 72,261.13113 72,259.99523 72,259.2902 64.073295,246.92663 33.535023,200 c -7.529076,-11.56955 -7.784916,-12 -7.132319,-12 0.477287,0 9.758096,12.0849 13.823411,18 0.945006,1.375 4.093224,5.72599 6.996039,9.66887 2.902815,3.94288 11.048475,15.08038 18.101467,24.75 7.791689,10.68237 13.481425,17.5812 14.5,17.5813 3.221494,3.3e-4 19.738298,-9.10131 25.682259,-14.15231 6.923,-5.88294 8.15354,-7.58844 6.59774,-9.14424 C 110.47716,233.07716 110.75814,232 112.80887,232 c 0.99488,0 2.68238,-0.65055 3.75,-1.44567 1.85917,-1.38462 1.8039,-1.49431 -1.30887,-2.59782 -4.4683,-1.58406 -4.07265,-2.60606 1.32208,-3.41505 5.93585,-0.89013 7.79886,-2.89571 12.93015,-13.9196 9.88167,-21.22943 16.77454,-49.28231 19.54161,-79.53121 1.24313,-13.58959 0.86363,-43.89554 -0.59452,-47.4771 -0.50051,-1.229389 -0.37973,-1.751847 0.34678,-1.5 1.71558,0.594711 12.0548,22.35153 13.90105,29.25195 0.90272,3.37398 1.9787,6.52554 2.39106,7.00348 0.41236,0.47794 1.64003,-0.87206 2.72815,-3 3.47214,-6.79011 9.68304,-12.90731 15.71534,-15.478248 L 189.14118,97.5 l -0.3844,-5.75 c -0.21142,-3.1625 -0.10677,-5.75 0.23255,-5.75 0.33932,0 2.58691,2.793394 4.99463,6.207542 2.40772,3.414148 4.55598,5.672629 4.77391,5.018847 0.21793,-0.653782 -0.31344,-4.62031 -1.18082,-8.814506 C 195.76916,79.669859 195.71289,79 196.78643,79 c 1.16651,0 11.13661,16.77342 18.25996,30.72006 3.43281,6.72103 6.59209,12.00337 7.02061,11.73853 0.42852,-0.26484 1.07982,-1.85057 1.44733,-3.52385 0.36752,-1.67327 3.55112,-11.77049 7.07468,-22.438263 9.28088,-28.098363 18.94754,-52.473982 21.41422,-53.998471 1.44907,-0.895578 1.29535,0.440112 -1.95666,17.001994 -10.17955,51.84237 -11.56933,96.25847 -3.97325,126.98102 1.50845,6.10096 2.61561,8.49793 4.69999,10.17536 2.18986,1.76232 2.48059,2.44529 1.47669,3.46898 -1.89729,1.93469 -1.5859,3.36315 2.75025,12.61624 8.20924,17.51807 20.54693,32.83912 34.41179,42.73289 3.48807,2.48903 6.56436,4.52551 6.83621,4.52551 0.27185,0 11.01471,-13.56185 23.87301,-30.13744 35.36004,-45.5825 35.99213,-45.63056 4.76831,-0.36256 -20.25651,29.36771 -22.79071,33.2655 -22.08798,33.97311 0.97216,0.97891 7.1932,3.52689 8.61113,3.52689 1.15524,0 9.33481,-5.76952 27.3686,-19.30466 5.10473,-3.83132 9.47842,-6.76893 9.71932,-6.52804 0.3965,0.39651 -6.93384,7.05855 -24.18692,21.9818 -3.40245,2.943 -6.21495,5.8597 -6.25,6.48156 -0.0727,1.29072 18.50401,7.39929 30.43628,10.00833 4.4,0.96207 11.97851,1.77438 16.84113,1.80512 l 8.84114,0.0559 -4.34114,3.86583 c -5.96227,5.30947 -17.07639,11.66575 -27.32755,15.62892 -4.7172,1.8237 -8.42469,3.77193 -8.23887,4.32939 0.53903,1.61707 7.67178,3.849 14.72529,4.60773 6.31627,0.67942 6.4165,0.73416 3.54598,1.93647 -1.62471,0.68051 -10.84971,2.56479 -20.5,4.1873 -18.15472,3.05235 -43.07123,9.67951 -43.01247,11.44022 0.0184,0.55228 7.33094,4.34535 16.25,8.42906 8.91907,4.08371 17.25055,8.04571 18.5144,8.80445 l 2.29791,1.37952 -2.04791,3.31359 c -2.75093,4.4511 -2.58143,5.42737 0.44815,2.58122 4.33179,-4.0695 3.60041,-1.69288 -1.97636,6.42217 -6.83029,9.93913 -6.74491,9.86241 -9.07345,8.15213 -1.89163,-1.38938 -1.89555,-1.51578 -0.13971,-4.50375 2.04957,-3.48783 1.30733,-3.98465 -1.74209,-1.16608 -2.05181,1.89648 -2.19605,1.81646 -23.56445,-13.07434 -24.41371,-17.01297 -19.75671,-15.57237 -40,-12.37359 -5.225,0.82564 -13.72771,1.80585 -18.89491,2.17825 -8.45983,0.60969 -9.72486,0.96678 -12.70992,3.58769 -3.90404,3.4278 -8.06477,11.53597 -8.99239,17.52382 -0.36212,2.3375 -1.07288,4.25 -1.57948,4.25 -1.22114,0 -4.77346,-7.90983 -4.80134,-10.69098 -0.0198,-1.97603 -2.01152,-4.54529 -2.02951,-2.61804 -0.004,0.44496 -0.47187,3.67045 -1.03935,7.16776 -1.39327,8.58641 -6.15121,18.72963 -11.20682,23.89126 C 183.0692,383.5042 181,384.88364 181,383.58077 Z m 131.19528,-34.26786 c 1.5426,-1.4779 2.80472,-3.18132 2.80472,-3.78537 0,-0.60405 -2.8125,-2.52663 -6.25,-4.27239 -3.4375,-1.74577 -12.64286,-6.56735 -20.45635,-10.71464 C 280.48015,326.39323 273.46239,323 272.69863,323 c -2.03096,0 -5.24261,3.85945 -4.125,4.95702 1.03499,1.01644 39.67114,24.01571 40.37165,24.03238 0.24491,0.006 1.70741,-1.19859 3.25,-2.67649 z m -76.4021,-19.9009 c 13.0609,-1.51417 15.1561,-2.23044 15.19151,-5.19339 0.0281,-2.35217 -2.48959,-2.28756 -10.51915,0.26992 -4.38105,1.3954 -10.77804,3.05911 -14.21554,3.69713 -3.4375,0.63802 -6.25,1.53225 -6.25,1.98718 0,1.07973 -0.1421,1.08658 15.79318,-0.76084 z m -40.78028,-1.83429 c 21.4084,-2.97793 50.17269,-10.03655 54.06584,-13.26751 0.86831,-0.72062 2.31508,-1.31021 3.21505,-1.31021 6.89306,0 35.64573,-13.79602 48.62363,-23.33045 l 5.41742,-3.98 -2.27821,-1.84477 C 302.80362,282.83015 301.15328,282 300.38922,282 299.62515,282 299,281.57152 299,281.04783 c 0,-1.71128 9.18774,1.75785 12.13578,4.58226 2.92333,2.80072 4.00827,8.54482 1.86422,9.86991 -0.55768,0.34467 -1,-0.41545 -1,-1.71848 C 312,291.37429 309.48901,287 308.10718,287 c -0.42867,0 -3.66566,2.32575 -7.19329,5.16832 -7.53127,6.06871 -23.19886,16.45128 -30.66389,20.3203 -2.8875,1.49654 -5.25,2.86626 -5.25,3.04382 0,0.17756 2.9888,1.73497 6.64178,3.46092 6.33942,2.99524 6.87433,3.083 11.75,1.92781 6.03824,-1.43064 20.65512,-6.88413 26.65371,-9.94438 5.98997,-3.05585 13.65381,-10.53564 15.01224,-14.6517 1.64081,-4.97171 -0.92824,-11.28052 -6.3909,-15.6941 -6.33891,-5.12155 -8.0528,-5.8092 -10.27869,-4.12405 -2.396,1.81393 -3.54024,1.83354 -5.90926,0.10127 -1.65566,-1.21064 -1.72144,-1.61102 -0.50544,-3.07621 1.19923,-1.44498 1.19386,-1.81358 -0.0377,-2.5929 -2.33356,-1.47662 -5.37707,-1.07241 -7.10301,0.94334 -1.09571,1.27969 -2.44766,1.72266 -4.22225,1.38342 -2.79824,-0.53491 -3.35021,-2.12609 -1.41044,-4.06586 1.90598,-1.90598 0.0764,-2.86215 -10.7,-5.59211 -13.73443,-3.47931 -29.57412,-6.02793 -50.25,-8.08529 -7.46161,-0.74248 -8.21786,0.59495 -1.33402,2.35923 5.47213,1.40246 13.66326,6.1532 16.31178,9.46059 2.56766,3.20641 2.21569,7.97712 -0.85802,11.63002 -7.29875,8.67406 -28.21556,14.01975 -54.86974,14.023 -26.43051,0.003 -47.62534,-5.41352 -54.86974,-14.023 -6.77262,-8.04881 -0.14067,-16.53057 16.86974,-21.57511 8.06493,-2.39171 4.92913,-2.86905 -9.3877,-1.42901 -20.39067,2.05096 -52.257246,7.90965 -54.455398,10.01166 -0.463704,0.44342 -0.07745,1.97474 0.858335,3.40293 1.836009,2.80211 2.049914,2.50969 -2.978449,4.07159 -0.804766,0.24997 -2.386477,-0.71925 -3.514914,-2.15382 -1.968733,-2.50284 -2.221993,-2.5573 -6.262729,-1.34666 l -4.211027,1.26165 2.225941,1.80246 C 72.998327,274.00948 74,275.26217 74,275.80188 c 0,1.93569 -4.810977,2.21358 -7.8753,0.4549 -2.902477,-1.66579 -3.177371,-1.6597 -6.329479,0.14027 -10.751052,6.13924 -15.212844,15.0271 -11.321444,22.55224 6.868443,13.2821 45.943046,26.72337 88.526223,30.45213 9.19103,0.8048 47.85419,-0.41062 58.0129,-1.8237 z m -85.34623,-10.24439 c -2.42371,-2.4237 2.19529,-5.52271 4.89365,-3.28327 1.11167,0.92261 1.19104,1.5446 0.32957,2.58262 -1.1951,1.44 -4.09489,1.82899 -5.22322,0.70065 z m -8.4375,-7.52083 C 101.84724,307.95828 104,307.65074 104,309.41667 104,310.2875 103.2875,311 102.41667,311 c -0.87084,0 -1.40521,-0.53438 -1.1875,-1.1875 z m 166.56782,-30.49278 c -2.62428,-0.69077 -3.38753,-4.41474 -1.22841,-5.99352 2.66937,-1.95189 7.83622,-1.64137 9.85779,0.59244 1.65397,1.82762 1.63761,2.01738 -0.34501,4 -1.97603,1.97603 -4.48689,2.40067 -8.28437,1.40108 z M 97.309468,275.36408 C 96.175575,272.4092 98.409166,270.5 103,270.5 c 4.97207,0 7.28674,2.24464 5.06957,4.91618 -1.8378,2.21441 -9.905349,2.17535 -10.760102,-0.0521 z M 116.5,275 c -0.83704,-1.35436 0.29243,-3 2.05902,-3 0.79254,0 1.44098,0.9 1.44098,2 0,2.07031 -2.41251,2.7596 -3.5,1 z m 138.19455,-5.11113 c -1.42616,-0.82966 -1.558,-1.34848 -0.62756,-2.46959 1.61912,-1.95092 6.83959,-1.82631 7.61011,0.18164 1.10387,2.87663 -3.42165,4.35949 -6.98255,2.28795 z M 114.7198,267.71219 c -0.7929,-2.06626 0.7554,-3.95991 2.90003,-3.54689 2.65685,0.51167 2.46124,4.25179 -0.24255,4.63757 -1.1675,0.16658 -2.36337,-0.32423 -2.65748,-1.09068 z m 153.43896,-0.0209 c -1.35917,-1.6377 -0.5444,-2.6913 2.08123,-2.6913 1.24239,0 1.79401,0.58082 1.58333,1.66713 -0.43042,2.21935 -2.25049,2.72802 -3.66456,1.02417 z m 0.25168,56.14231 c 1.80743,-2.11093 1.80672,-2.20255 -0.0278,-3.57829 -6.40586,-4.80397 -15.08946,-6.70301 -16.13149,-3.52785 -0.38742,1.18048 11.16927,9.24355 13.27657,9.26303 0.56527,0.005 1.86247,-0.96538 2.88268,-2.15689 z m -70.08122,-59.77002 c 4.84546,-1.12455 5.60969,-1.90387 3.43,-3.4977 -5.2326,-3.82617 -37.36184,-1.83517 -33.4536,2.07307 2.07971,2.0797 22.93673,3.06937 30.0236,1.42463 z M 223.3466,251.45186 C 226.90599,247.99503 227.91611,246 226.10699,246 c -0.49116,0 -1.1451,0.65692 -1.4532,1.45982 -0.3081,0.80291 -2.44877,2.82791 -4.75703,4.5 -3.18035,2.30384 -3.71324,3.04018 -2.2002,3.04018 1.09815,0 3.64067,-1.59666 5.65004,-3.54814 z m -7.47886,0.12988 c 0.66749,-0.41253 0.93999,-1.61218 0.60555,-2.6659 C 216.13337,247.84486 216.33593,247 216.93261,247 c 0.58707,0 1.06739,0.45 1.06739,1 0,3.61951 4.4966,-2.23407 6.80055,-8.85281 1.04804,-3.0108 0.93923,-3.55487 -1.06673,-5.3337 -1.43187,-1.26974 -1.66276,-1.80456 -0.64314,-1.48971 3.05835,0.94438 4.15336,-1.00228 4.67648,-8.31367 0.36873,-5.15347 0.16041,-7.43684 -0.72864,-7.9863 -0.97938,-0.6053 -0.98767,-1.25031 -0.0388,-3.02324 C 228.66473,209.88943 227.41298,198 225.42041,198 224.50884,198 224,199.07471 224,201 c 0,2.45345 -0.40991,2.99446 -2.25,2.96959 -2.07581,-0.0281 -2.108,-0.11296 -0.41588,-1.09677 1.31395,-0.76393 1.66149,-1.75416 1.22544,-3.49155 -0.41854,-1.66759 -0.13243,-2.60794 0.91588,-3.01022 1.98381,-0.76126 1.96807,-2.37105 -0.0232,-2.37105 -2.00807,0 -6.13206,4.47153 -8.63032,9.35763 -1.67333,3.27271 -1.86774,4.97453 -1.28214,11.22366 0.88069,9.39829 0.22857,12.00905 -3.21555,12.87347 l -2.69317,0.67594 2.71521,2.18465 2.71522,2.18465 -1.54342,5 c -2.91345,9.43827 -6.16812,11.2252 -10.94554,6.00947 C 196.85347,239.44919 196,239.1887 196,242.11385 c 0,3.60181 4.16626,9.89758 6.95192,10.50525 1.40144,0.30571 2.98647,0.66261 3.52227,0.7931 1.39033,0.33861 7.95316,-0.94025 9.39355,-1.83046 z M 223,218 c -1.21296,-0.78387 -1.06944,-0.9723 0.75,-0.98469 1.2375,-0.008 2.25,0.43469 2.25,0.98469 0,1.25292 -1.06124,1.25292 -3,0 z m -61.53463,32.11355 c -3.82242,-1.77019 -7.4042,-4.41111 -9.77065,-7.20411 -3.40753,-4.02173 -3.64069,-4.14566 -2.65176,-1.40944 2.25887,6.24991 9.27173,11.42888 15.45704,11.41497 2.61454,-0.006 2.22464,-0.36582 -3.03463,-2.80142 z m 80.38934,-5.78861 c -1.49511,-1.8015 -3.37278,-0.11738 -2.47566,2.22047 0.52591,1.3705 0.92093,1.45052 2.14511,0.43454 1.16462,-0.96655 1.23861,-1.56087 0.33055,-2.65501 z m -65.52802,1.57207 c 1.33144,-0.60664 3.37761,-2.80541 4.54705,-4.88615 3.55363,-6.32283 2.23454,-11.15814 -1.4923,-5.47025 -0.91557,1.39733 -2.5434,3.01089 -3.61741,3.58568 -2.80552,1.50147 -6.41405,-2.21763 -8.31284,-8.56758 L 165.9385,225.5 l 2.71522,-2.18465 2.71521,-2.18465 -2.64863,-0.66476 c -3.47148,-0.87129 -4.05083,-3.0723 -3.23929,-12.30634 0.62955,-7.16331 0.48704,-8.01513 -2.19956,-13.14687 -2.80511,-5.35812 -7.36949,-9.25802 -8.96642,-7.66109 -0.4391,0.4391 -0.012,1.23843 0.94907,1.77628 1.21424,0.67952 1.56744,1.69508 1.15755,3.32823 -0.41546,1.65534 -0.0476,2.66563 1.24423,3.41667 1.69212,0.98381 1.65993,1.06872 -0.41588,1.09677 -1.84009,0.0249 -2.25,-0.51614 -2.25,-2.96959 0,-1.92529 -0.50884,-3 -1.42041,-3 -2.02652,0 -3.24099,11.89564 -1.53913,15.0756 0.91692,1.71329 0.94413,2.42954 0.10294,2.70993 -0.66492,0.22164 -1.1434,2.58543 -1.1434,5.64858 0,7.76782 2.78893,14.49022 4.27976,10.31589 0.24554,-0.6875 0.84554,-0.87376 1.33334,-0.41392 0.50223,0.47345 -0.14137,1.66971 -1.4839,2.75811 l -2.3708,1.92203 2.8708,5.74189 c 2.31054,4.62131 3.30239,5.69673 5.08227,5.51051 1.45819,-0.15257 2.04227,0.20955 1.71473,1.06309 -1.41814,3.69564 8.59298,6.98356 13.90049,4.5653 z M 153,211 c 0,-0.55 0.92656,-1 2.05902,-1 1.13246,0 1.7809,0.45 1.44098,1 -0.33992,0.55 -1.26648,1 -2.05902,1 C 153.64844,212 153,211.55 153,211 Z m 96.82969,34.25 c 1.23593,-2.40305 0.39094,-4.25 -1.94441,-4.25 -2.44648,0 -3.50509,2.54825 -1.87471,4.51273 1.62141,1.95368 2.71798,1.87825 3.81912,-0.26273 z M 132.8,238.8 c 1.44555,-1.44555 1.58587,-5.44349 0.22067,-6.28723 -2.49847,-1.54414 -7.12926,3.88447 -5.5262,6.47828 0.852,1.37857 3.84363,1.27085 5.30553,-0.19105 z m 110.01111,-7.6239 C 243.15137,226.44701 241.80161,224 238.8528,224 c -3.47123,0 -4.48123,7.05503 -1.54587,10.79826 0.55993,0.71404 1.95744,1.16404 3.10556,1 1.68963,-0.24141 2.14681,-1.12241 2.39862,-4.62216 z m -42.35701,0.0726 c 2.84073,-4.29264 5.58421,-11.83348 9.00399,-24.74873 8.1436,-30.75543 11.20851,-37.92296 15.71258,-36.74512 1.7735,0.46378 1.96107,0.20761 1.36077,-1.85847 -1.11184,-3.82675 -4.05147,-7.36959 -6.40471,-7.71897 -2.98039,-0.44248 -6.21762,7.07704 -8.96432,20.82256 -6.2608,31.33138 -7.38187,36.49985 -9.17914,42.31875 -2.13286,6.9054 -4.91322,10.30584 -7.58747,9.27964 -1.40739,-0.54007 -1.47443,-0.39805 -0.4148,0.87872 2.00852,2.42012 3.80646,1.80117 6.4731,-2.22838 z M 186,226 c 0,-0.55 -0.84825,-1 -1.88499,-1 -4.95334,0 -8.11451,-10.8102 -13.6987,-46.8452 -4.11813,-26.57441 -7.26156,-38.21746 -10.64527,-39.42933 -2.03911,-0.7303 -4.41477,0.97906 -5.54015,3.98631 -2.27705,6.08473 -2.27534,6.2637 0.0576,6.0196 3.57449,-0.37399 7.15309,8.34264 11.81092,28.76862 8.73842,38.32065 12.69056,49.5 17.49933,49.5 C 184.91945,227 186,226.55 186,226 Z M 173.8,124.8 c 1.90049,-1.90049 1.45794,-4.8 -0.73261,-4.8 -2.00349,0 -3.66527,3.22359 -2.57292,4.99105 0.82367,1.33273 1.84052,1.27396 3.30553,-0.19105 z m 7.2,-8.38333 c 0,-1.76593 -2.15276,-1.45839 -2.77083,0.39583 -0.21771,0.65313 0.31666,1.1875 1.1875,1.1875 C 180.2875,118 181,117.2875 181,116.41667 Z M 321.22775,364.75 c 0.80178,-1.2375 3.36887,-5.2875 5.70465,-9 2.33579,-3.7125 4.57054,-6.75 4.96611,-6.75 0.39558,0 1.59274,0.64951 2.66036,1.44336 1.84937,1.37513 1.58778,1.80057 -5.53384,9 -7.38886,7.46958 -10.62608,9.67276 -7.79728,5.30664 z m 13.80405,-1.02852 c -0.0859,-2.10179 6.48584,-13.23965 11.0424,-18.71492 7.69437,-9.24572 18.64027,-16.70867 41.65793,-28.40251 22.79391,-11.58016 29.59288,-16.14244 32.98705,-22.13514 2.73995,-4.83764 2.94568,-12.41273 0.47438,-17.46683 -1.92928,-3.94558 -1.13635,-3.75305 -32.69356,-7.93836 -24.4386,-3.24119 -31.5,-4.42455 -31.5,-5.2788 0,-0.44432 2.925,-2.1527 6.5,-3.79639 15.63131,-7.18687 19.64019,-9.08332 30.5,-14.42846 6.325,-3.11312 11.275,-5.96443 11,-6.33625 -0.275,-0.37181 -3.53851,-2.13218 -7.25224,-3.91194 -19.07051,-9.1393 -25.57601,-24.06039 -21.34715,-48.96208 0.91999,-5.41739 1.8995,-11.4248 2.17667,-13.3498 0.27718,-1.925 0.92349,-4.625 1.43625,-6 1.61573,-4.33267 3.94894,-25.41758 2.92691,-26.45 -0.86002,-0.86877 -1.4753,3.16181 -1.13726,7.45 0.16943,2.1494 -2.70522,16.81694 -8.17346,41.70408 -5.53775,25.20347 -1.9099,39.48759 11.49339,45.25354 4.26277,1.83379 4.90261,2.42665 3.75728,3.4814 -1.21207,1.11623 -10.88326,7.80352 -30.11697,20.82484 -5.65721,3.82997 -7.36403,5.46886 -6.54672,6.28617 0.22933,0.22933 11.85355,2.70387 25.8316,5.49897 13.97805,2.7951 25.75617,5.61503 26.17361,6.2665 0.41744,0.65148 1.49221,3.07812 2.38837,5.39255 2.52687,6.52586 1.24009,12.44158 -3.80331,17.48498 -6.65106,6.65106 -14.60393,9.77375 -50.30697,19.753 -13.7977,3.85655 -23.02246,7.88148 -27.8964,12.17169 -5.19936,4.57666 -6.36273,3.9196 -1.3536,-0.76451 6.26467,-5.85818 13.74824,-8.84599 40.75,-16.2694 31.56309,-8.67742 42,-15.07836 42,-25.75851 0,-2.42274 -0.85232,-6.07566 -1.89404,-8.1176 l -1.89404,-3.71263 -27.10596,-5.38184 c -16.2302,-3.22247 -27.08967,-5.82948 -27.06537,-6.49753 0.0223,-0.61363 8.57232,-6.8991 19,-13.96769 C 377.46827,244.57941 386,238.46414 386,238.05852 c 0,-0.40562 -1.06961,-1.22484 -2.37691,-1.82048 -3.72666,-1.69798 -9.39041,-7.06643 -11.13871,-10.55794 -2.34485,-4.68287 -3.43407,-15.58443 -2.39096,-23.9301 1.1109,-8.8881 2.06429,-13.96741 5.39638,-28.75 3.34405,-14.83563 5.46879,-29.69854 5.49188,-38.41667 0.0252,-9.51908 0.82693,-7.98045 1.9413,3.72569 0.0424,0.44496 0.52702,0.5309 1.07702,0.19098 1.47952,-0.91439 1.24272,9.62132 -0.42704,19 -0.78336,4.4 -2.53175,13.175 -3.88529,19.5 -1.35355,6.325 -2.75417,14.66027 -3.1125,18.52282 -1.16111,12.51607 2.79402,23.96423 10.76807,31.16832 3.62549,3.2754 18.93684,11.30886 21.55411,11.30886 3.50601,0 -1.24444,2.74204 -21.64735,12.49523 -12.5125,5.98134 -23.3273,11.38519 -24.03288,12.00856 -1.34414,1.18752 0.4041,1.4942 39.67511,6.95999 9.56572,1.33137 17.73419,2.78417 18.15215,3.22845 1.39369,1.48145 3.95591,10.33516 3.93366,13.59272 -0.0121,1.76828 -0.85023,5.03855 -1.86256,7.26727 -3.20664,7.05968 -10.98643,12.68932 -31.83649,23.03765 -10.57156,5.24689 -22.62087,11.75925 -26.77626,14.47192 -9.61325,6.2756 -19.16019,15.94975 -23.21681,23.52617 -3.35805,6.27174 -6.20139,10.42416 -6.25412,9.13352 z"
|
||||||
|
id="path204" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 19 KiB |
@ -3,14 +3,19 @@
|
|||||||
<head>
|
<head>
|
||||||
<title>Webpack Bootstrap 4 UI Demo</title>
|
<title>Webpack Bootstrap 4 UI Demo</title>
|
||||||
<%= require('html-loader!./html/Head.html') %>
|
<%= require('html-loader!./html/Head.html') %>
|
||||||
|
|
||||||
<meta name="ping" content="/Security/ping" />
|
<meta name="ping" content="/Security/ping" />
|
||||||
<meta name="api_url" content="<%= GRAPHQL_URL %>" />
|
<meta name="api_url" content="<%= GRAPHQL_URL %>" />
|
||||||
|
<meta name="swversion" content="<%= SWVERSION %>" />
|
||||||
|
<base href="<%= BASE_HREF %>" />
|
||||||
</head>
|
</head>
|
||||||
<body data-default-lng="0" data-default-lat="0">
|
<body data-default-lng="0" data-default-lat="0">
|
||||||
<%= require('html-loader!./html/First.html') %> <%=
|
<%= require('html-loader!./html/_components/LoadingSpinner.html') %> <%=
|
||||||
|
require('html-loader!./html/_components/Alerts.html') %> <%=
|
||||||
|
require('html-loader!./html/First.html') %> <%=
|
||||||
require('html-loader!./html/_components/Flyout.html') %>
|
require('html-loader!./html/_components/Flyout.html') %>
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
<header id="Header" class="bg-dark">
|
<header id="Header" class="stiky-top">
|
||||||
<%= require('html-loader!./html/Navigation.html') %>
|
<%= require('html-loader!./html/Navigation.html') %>
|
||||||
</header>
|
</header>
|
||||||
<main id="MainContent" class="page-content">
|
<main id="MainContent" class="page-content">
|
||||||
|
@ -7,6 +7,7 @@ import './_main.touch';
|
|||||||
import './_main.online';
|
import './_main.online';
|
||||||
import './_main.css-screen-size';
|
import './_main.css-screen-size';
|
||||||
import './_main.links';
|
import './_main.links';
|
||||||
|
import SpinnerUI from './_main.loading-spinner';
|
||||||
|
|
||||||
const MainUI = ((W) => {
|
const MainUI = ((W) => {
|
||||||
const NAME = '_main';
|
const NAME = '_main';
|
||||||
@ -68,8 +69,12 @@ const MainUI = ((W) => {
|
|||||||
W.addEventListener(`${Events.LOADED}`, () => {
|
W.addEventListener(`${Events.LOADED}`, () => {
|
||||||
MainUI.init();
|
MainUI.init();
|
||||||
|
|
||||||
|
SpinnerUI.hide();
|
||||||
|
|
||||||
console.groupEnd('init');
|
console.groupEnd('init');
|
||||||
console.timeEnd('init');
|
console.timeEnd('init');
|
||||||
|
|
||||||
|
W.dispatchEvent(new Event(Events.LODEDANDREADY));
|
||||||
});
|
});
|
||||||
|
|
||||||
W.addEventListener(`${Events.AJAX}`, () => {
|
W.addEventListener(`${Events.AJAX}`, () => {
|
||||||
|
@ -49,17 +49,6 @@ const MainUILinks = ((W) => {
|
|||||||
static popState(e) {
|
static popState(e) {
|
||||||
const ui = this;
|
const ui = this;
|
||||||
|
|
||||||
if (!ui.GraphPage) {
|
|
||||||
console.log(
|
|
||||||
`${NAME}: [popstate] GraphPage is missing. Have to render it first`,
|
|
||||||
);
|
|
||||||
|
|
||||||
ui.GraphPage = ReactDOM.render(
|
|
||||||
<Page />,
|
|
||||||
document.getElementById('MainContent'),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.state && e.state.page) {
|
if (e.state && e.state.page) {
|
||||||
console.log(`${NAME}: [popstate] load`);
|
console.log(`${NAME}: [popstate] load`);
|
||||||
const state = JSON.parse(e.state.page);
|
const state = JSON.parse(e.state.page);
|
||||||
@ -74,6 +63,17 @@ const MainUILinks = ((W) => {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (!ui.GraphPage) {
|
||||||
|
console.log(
|
||||||
|
`${NAME}: [popstate] GraphPage is missing. Have to render it first`,
|
||||||
|
);
|
||||||
|
|
||||||
|
ui.GraphPage = ReactDOM.render(
|
||||||
|
<Page />,
|
||||||
|
document.getElementById('MainContent'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
ui.GraphPage.setState(state);
|
ui.GraphPage.setState(state);
|
||||||
} else if (e.state && e.state.landing) {
|
} else if (e.state && e.state.landing) {
|
||||||
console.log(`${NAME}: [popstate] go to landing`);
|
console.log(`${NAME}: [popstate] go to landing`);
|
||||||
@ -127,7 +127,15 @@ const MainUILinks = ((W) => {
|
|||||||
console.log(e);
|
console.log(e);
|
||||||
|
|
||||||
el.classList.remove('loading');
|
el.classList.remove('loading');
|
||||||
|
el.classList.add(`response-${e.status}`);
|
||||||
|
/*switch (e.status) {
|
||||||
|
case 404:
|
||||||
el.classList.add('not-found');
|
el.classList.add('not-found');
|
||||||
|
break;
|
||||||
|
case 523:
|
||||||
|
el.classList.add('unreachable');
|
||||||
|
break;
|
||||||
|
}*/
|
||||||
|
|
||||||
console.groupEnd(`${NAME}: load on click`);
|
console.groupEnd(`${NAME}: load on click`);
|
||||||
});
|
});
|
||||||
|
21
src/js/_components/_main.loading-spinner.js
Normal file
21
src/js/_components/_main.loading-spinner.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// browser tab visibility state detection
|
||||||
|
|
||||||
|
import Events from '../_events';
|
||||||
|
|
||||||
|
const NAME = '_main.loading-spinner';
|
||||||
|
const D = document;
|
||||||
|
const BODY = D.body;
|
||||||
|
const SPINNER = D.getElementById('PageLoading');
|
||||||
|
|
||||||
|
class SpinnerUI {
|
||||||
|
static show() {
|
||||||
|
console.log(`${NAME}: show`);
|
||||||
|
SPINNER.classList.remove('d-none');
|
||||||
|
}
|
||||||
|
static hide() {
|
||||||
|
console.log(`${NAME}: hide`);
|
||||||
|
SPINNER.classList.add('d-none');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SpinnerUI;
|
@ -79,6 +79,7 @@ export default ((W) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// current browser online state
|
// current browser online state
|
||||||
|
|
||||||
if (typeof navigator.onLine !== 'undefined') {
|
if (typeof navigator.onLine !== 'undefined') {
|
||||||
if (!navigator.onLine) {
|
if (!navigator.onLine) {
|
||||||
UPDATE_ONLINE_STATUS(false);
|
UPDATE_ONLINE_STATUS(false);
|
||||||
@ -95,7 +96,7 @@ export default ((W) => {
|
|||||||
UPDATE_ONLINE_STATUS(true);
|
UPDATE_ONLINE_STATUS(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
W.addEventListener(`${Events.LOADED}`, () => {
|
/*W.addEventListener(`${Events.LOADED}`, () => {
|
||||||
UPDATE_ONLINE_STATUS(true);
|
UPDATE_ONLINE_STATUS(true);
|
||||||
});
|
});*/
|
||||||
})(window);
|
})(window);
|
||||||
|
@ -23,7 +23,7 @@ class Page extends Component {
|
|||||||
URLSegment: null,
|
URLSegment: null,
|
||||||
ClassName: 'Page',
|
ClassName: 'Page',
|
||||||
CSSClass: null,
|
CSSClass: null,
|
||||||
Summary: null,
|
Summary: 'Loading ...',
|
||||||
Link: null,
|
Link: null,
|
||||||
URL: null,
|
URL: null,
|
||||||
Elements: [],
|
Elements: [],
|
||||||
@ -104,14 +104,25 @@ class Page extends Component {
|
|||||||
`);
|
`);
|
||||||
|
|
||||||
if (!ui.isOnline()) {
|
if (!ui.isOnline()) {
|
||||||
const resp = client.readQuery({ query });
|
const data = client.readQuery({ query });
|
||||||
|
|
||||||
if (ui.processResponse(resp)) {
|
if (data && ui.processResponse(data)) {
|
||||||
console.log(`${ui.name}: Offline cached response`);
|
console.log(`${ui.name}: Offline cached response`);
|
||||||
resolve(resp);
|
resolve(data);
|
||||||
} else {
|
} else {
|
||||||
console.log(`${ui.name}: No offline response`);
|
console.log(`${ui.name}: No offline response`);
|
||||||
reject();
|
|
||||||
|
ui.setState(
|
||||||
|
Object.assign(ui.empty_state, {
|
||||||
|
Title: 'Offline',
|
||||||
|
CSSClass: 'graphql__status-523',
|
||||||
|
Summary:
|
||||||
|
"You're Offline. The page is not available now.",
|
||||||
|
loading: false,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
reject({ status: 523 });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!ui.state.loading) {
|
if (!ui.state.loading) {
|
||||||
@ -125,13 +136,15 @@ class Page extends Component {
|
|||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
// write to cache
|
// write to cache
|
||||||
client.writeQuery({ query, data: { resp } });
|
const data = resp.data;
|
||||||
if (ui.processResponse(resp.data)) {
|
client.writeQuery({ query, data: data });
|
||||||
|
|
||||||
|
if (ui.processResponse(data)) {
|
||||||
console.log(`${ui.name}: got the server response`);
|
console.log(`${ui.name}: got the server response`);
|
||||||
resolve(resp.data);
|
resolve(data);
|
||||||
} else {
|
} else {
|
||||||
console.log(`${ui.name}: not found`);
|
console.log(`${ui.name}: not found`);
|
||||||
reject();
|
reject({ status: 404 });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -144,12 +157,14 @@ class Page extends Component {
|
|||||||
if (!data.readPages.edges.length) {
|
if (!data.readPages.edges.length) {
|
||||||
console.log(`${ui.name}: not found`);
|
console.log(`${ui.name}: not found`);
|
||||||
|
|
||||||
ui.setState({
|
ui.setState(
|
||||||
|
Object.assign(ui.empty_state, {
|
||||||
Title: 'Not Found',
|
Title: 'Not Found',
|
||||||
CSSClass: 'graphql__not-found',
|
CSSClass: 'graphql__status-404',
|
||||||
Summary: 'Not Found',
|
Summary: 'The page is not found.',
|
||||||
loading: false,
|
loading: false,
|
||||||
});
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -182,7 +197,7 @@ class Page extends Component {
|
|||||||
render() {
|
render() {
|
||||||
const ui = this;
|
const ui = this;
|
||||||
const name = ui.name;
|
const name = ui.name;
|
||||||
const className = `elemental-area page-${ui.state.CSSClass} url-${ui.state.URLSegment}`;
|
const className = `elemental-area graphql__page page-${ui.state.CSSClass} url-${ui.state.URLSegment}`;
|
||||||
|
|
||||||
const ElementItem = (props) => (
|
const ElementItem = (props) => (
|
||||||
<div dangerouslySetInnerHTML={props.html}></div>
|
<div dangerouslySetInnerHTML={props.html}></div>
|
||||||
@ -194,9 +209,9 @@ class Page extends Component {
|
|||||||
ui.state.Elements.map((el) => {
|
ui.state.Elements.map((el) => {
|
||||||
html += el.node.Render;
|
html += el.node.Render;
|
||||||
});
|
});
|
||||||
} else {
|
} else if (ui.state.Summary.length) {
|
||||||
console.log(`${ui.name}: loading`);
|
console.log(`${ui.name}: summary only`);
|
||||||
html += '<div class="loading">Loading ...</div>';
|
html += `<div class="loading">${ui.state.Summary}</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,33 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// mock service worker
|
||||||
|
/*if (process.env.NODE_ENV === 'development') {
|
||||||
|
const regeneratorRuntime = require('regenerator-runtime');
|
||||||
|
const { worker } = require('../mocks/browser');
|
||||||
|
worker.start({
|
||||||
|
serviceWorker: {
|
||||||
|
url: 'src/_graphql/mockServiceWorker.js',
|
||||||
|
options: {
|
||||||
|
scope: '/',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// caching service worker
|
||||||
|
if ('serviceWorker' in navigator) {
|
||||||
|
const baseHref = (document.getElementsByTagName('base')[0] || {}).href;
|
||||||
|
const version = (document.querySelector('meta[name="swversion"]') || {})
|
||||||
|
.content;
|
||||||
|
if (baseHref) {
|
||||||
|
navigator.serviceWorker
|
||||||
|
.register(`${baseHref}app_sw.js?v=${version}`)
|
||||||
|
.then(() => {
|
||||||
|
console.log('SW: Registered');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//import $ from 'jquery';
|
//import $ from 'jquery';
|
||||||
import '../scss/app.scss';
|
import '../scss/app.scss';
|
||||||
|
|
||||||
@ -69,20 +97,6 @@ import 'bootstrap/js/dist/tab';*/
|
|||||||
// Meta Lightbox
|
// Meta Lightbox
|
||||||
import '@a2nt/meta-lightbox-react/src/js/app';
|
import '@a2nt/meta-lightbox-react/src/js/app';
|
||||||
|
|
||||||
// mock service worker
|
|
||||||
if (process.env.NODE_ENV === 'development') {
|
|
||||||
const regeneratorRuntime = require('regenerator-runtime');
|
|
||||||
const { worker } = require('../mocks/browser');
|
|
||||||
worker.start({
|
|
||||||
serviceWorker: {
|
|
||||||
url: 'src/_graphql/mockServiceWorker.js',
|
|
||||||
options: {
|
|
||||||
scope: '/',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//import Confirmation from 'bootstrap-confirmation2/dist/bootstrap-confirmation';
|
//import Confirmation from 'bootstrap-confirmation2/dist/bootstrap-confirmation';
|
||||||
//import Table from 'bootstrap-table/dist/bootstrap-table';
|
//import Table from 'bootstrap-table/dist/bootstrap-table';
|
||||||
|
|
||||||
|
9
src/js/lib/log.js
Normal file
9
src/js/lib/log.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
var debug = process.env.NODE_ENV === 'development' ? true : false;
|
||||||
|
|
||||||
|
const log = (msg) => {
|
||||||
|
if (debug) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = log;
|
102
src/js/types/sw.js
Normal file
102
src/js/types/sw.js
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
// caches polyfill because it is not added to native yet!
|
||||||
|
var CACHE_NAME = `${UINAME}-sw`;
|
||||||
|
var debug = process.env.NODE_ENV === 'development' ? true : false;
|
||||||
|
var version = `${UIVERSION}-sw`;
|
||||||
|
|
||||||
|
var log = require('../lib/log');
|
||||||
|
var caches = require('../../thirdparty/serviceworker-caches');
|
||||||
|
|
||||||
|
if (debug) {
|
||||||
|
log('SW: debug is on');
|
||||||
|
log(`SW: CACHE_NAME: ${CACHE_NAME}`);
|
||||||
|
//log(`SW: appDomain: ${appDomain}`);
|
||||||
|
//log(`SW: lang: ${lang}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof CACHE_NAME !== 'string') {
|
||||||
|
throw new Error('Cache Name cannot be empty');
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
// skip non-get
|
||||||
|
if (event.request.method !== 'GET') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Parse the url
|
||||||
|
const requestURL = new URL(event.request.url);
|
||||||
|
|
||||||
|
//Check for our own urls
|
||||||
|
/*if (requestURL.origin !== location.origin) {
|
||||||
|
log('SW: skip external ' + event.request.url);
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
//Skip admin url's
|
||||||
|
if (
|
||||||
|
requestURL.pathname.indexOf('admin') >= 0 ||
|
||||||
|
requestURL.pathname.indexOf('Security') >= 0 ||
|
||||||
|
requestURL.pathname.indexOf('/dev') >= 0
|
||||||
|
) {
|
||||||
|
log(`SW: skip admin ${event.request.url}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Test for images
|
||||||
|
/*if (/\.(jpg|jpeg|png|gif|webp)$/.test(requestURL.pathname)) {
|
||||||
|
log('SW: skip image ' + event.request.url);
|
||||||
|
//For now we skip images but change this later to maybe some caching and/or an offline fallback
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// Clone the request for fetch and cache
|
||||||
|
// A request is a stream and can be consumed only once.
|
||||||
|
const fetchRequest = event.request.clone(),
|
||||||
|
cacheRequest = event.request.clone();
|
||||||
|
|
||||||
|
// Respond with content from fetch or cache
|
||||||
|
event.respondWith(
|
||||||
|
// Try fetch
|
||||||
|
fetch(fetchRequest)
|
||||||
|
// when fetch is successful, we update the cache
|
||||||
|
.then((response) => {
|
||||||
|
// A response is a stream and can be consumed only once.
|
||||||
|
// Because we want the browser to consume the response,
|
||||||
|
// as well as cache to consume the response, we need to
|
||||||
|
// clone it so we have 2 streams
|
||||||
|
const responseToCache = response.clone();
|
||||||
|
|
||||||
|
// and update the cache
|
||||||
|
caches.open(CACHE_NAME).then((cache) => {
|
||||||
|
// Clone the request again to use it
|
||||||
|
// as the key for our cache
|
||||||
|
const cacheSaveRequest = event.request.clone();
|
||||||
|
cache.put(cacheSaveRequest, responseToCache);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the response stream to be consumed by browser
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
|
||||||
|
// when fetch times out or fails
|
||||||
|
.catch((err) => {
|
||||||
|
log('SW: fetch failed');
|
||||||
|
// Return the promise which
|
||||||
|
// resolves on a match in cache for the current request
|
||||||
|
// or rejects if no matches are found
|
||||||
|
return caches.match(cacheRequest);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now we need to clean up resources in the previous versions
|
||||||
|
// of Service Worker scripts
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
log(`SW: activated: ${version}`);
|
||||||
|
// Destroy the cache
|
||||||
|
event.waitUntil(caches.delete(CACHE_NAME));
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('install', (e) => {
|
||||||
|
log(`SW: installing version: ${version}`);
|
||||||
|
});
|
@ -17,13 +17,28 @@
|
|||||||
@keyframes fade {
|
@keyframes fade {
|
||||||
0% {
|
0% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
filter: grayscale(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
50% {
|
50% {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
|
filter: grayscale(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
100% {
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
filter: grayscale(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes expand {
|
||||||
|
from {
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
max-height: 500rem;
|
||||||
|
max-height: 200vh;
|
||||||
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,37 @@
|
|||||||
// Google material colors Ref: https://material.io/design/color/
|
// Google material colors Ref: https://material.io/design/color/
|
||||||
@import "~material-design-color/material-color.scss";
|
@import '~material-design-color/material-color.scss';
|
||||||
|
|
||||||
// Bootstrap Color system adapter
|
// Bootstrap Color system adapter
|
||||||
|
|
||||||
$white: $clr-white !default;
|
$white: $clr-white !default;
|
||||||
$gray-100: map-get($clr-grey-list, "100") !default;
|
$gray-100: map-get($clr-grey-list, '100') !default;
|
||||||
$gray-200: map-get($clr-grey-list, "200") !default;
|
$gray-200: map-get($clr-grey-list, '200') !default;
|
||||||
$gray-300: map-get($clr-grey-list, "300") !default;
|
$gray-300: map-get($clr-grey-list, '300') !default;
|
||||||
$gray-400: map-get($clr-grey-list, "400") !default;
|
$gray-400: map-get($clr-grey-list, '400') !default;
|
||||||
$gray-500: map-get($clr-grey-list, "500") !default;
|
$gray-500: map-get($clr-grey-list, '500') !default;
|
||||||
$gray-600: map-get($clr-grey-list, "600") !default;
|
$gray-600: map-get($clr-grey-list, '600') !default;
|
||||||
$gray-700: map-get($clr-grey-list, "700") !default;
|
$gray-700: map-get($clr-grey-list, '700') !default;
|
||||||
$gray-800: map-get($clr-grey-list, "800") !default;
|
$gray-800: map-get($clr-grey-list, '800') !default;
|
||||||
$gray-900: map-get($clr-grey-list, "900") !default;
|
$gray-900: map-get($clr-grey-list, '900') !default;
|
||||||
$black: $clr-black !default;
|
$black: $clr-black !default;
|
||||||
|
|
||||||
$grays: () !default;
|
$grays: () !default;
|
||||||
|
|
||||||
// stylelint-disable-next-line scss/dollar-variable-default
|
// stylelint-disable-next-line scss/dollar-variable-default
|
||||||
$grays: map-merge(("100": $gray-100, "200": $gray-200, "300": $gray-300, "400": $gray-400, "500": $gray-500, "600": $gray-600, "700": $gray-700, "800": $gray-800, "900": $gray-900), $grays) !default;
|
$grays: map-merge(
|
||||||
|
(
|
||||||
|
'100': $gray-100,
|
||||||
|
'200': $gray-200,
|
||||||
|
'300': $gray-300,
|
||||||
|
'400': $gray-400,
|
||||||
|
'500': $gray-500,
|
||||||
|
'600': $gray-600,
|
||||||
|
'700': $gray-700,
|
||||||
|
'800': $gray-800,
|
||||||
|
'900': $gray-900
|
||||||
|
),
|
||||||
|
$grays
|
||||||
|
) !default;
|
||||||
|
|
||||||
$blue: $clr-blue !default;
|
$blue: $clr-blue !default;
|
||||||
$indigo: $clr-indigo !default;
|
$indigo: $clr-indigo !default;
|
||||||
@ -34,7 +47,24 @@ $cyan: $clr-cyan !default;
|
|||||||
$colors: () !default;
|
$colors: () !default;
|
||||||
|
|
||||||
// stylelint-disable-next-line scss/dollar-variable-default
|
// stylelint-disable-next-line scss/dollar-variable-default
|
||||||
$colors: map-merge(("blue": $blue, "indigo": $indigo, "purple": $purple, "pink": $pink, "red": $red, "orange": $orange, "yellow": $yellow, "green": $green, "teal": $teal, "cyan": $cyan, "white": $white, "gray": $gray-600, "gray-dark": $gray-800), $colors) !default;
|
$colors: map-merge(
|
||||||
|
(
|
||||||
|
'blue': $blue,
|
||||||
|
'indigo': $indigo,
|
||||||
|
'purple': $purple,
|
||||||
|
'pink': $pink,
|
||||||
|
'red': $red,
|
||||||
|
'orange': $orange,
|
||||||
|
'yellow': $yellow,
|
||||||
|
'green': $green,
|
||||||
|
'teal': $teal,
|
||||||
|
'cyan': $cyan,
|
||||||
|
'white': $white,
|
||||||
|
'gray': $gray-600,
|
||||||
|
'gray-dark': $gray-800
|
||||||
|
),
|
||||||
|
$colors
|
||||||
|
) !default;
|
||||||
|
|
||||||
$primary: $blue !default;
|
$primary: $blue !default;
|
||||||
$secondary: $gray-600 !default;
|
$secondary: $gray-600 !default;
|
||||||
@ -48,7 +78,19 @@ $dark: $gray-900 !default;
|
|||||||
$theme-colors: () !default;
|
$theme-colors: () !default;
|
||||||
|
|
||||||
// stylelint-disable-next-line scss/dollar-variable-default
|
// stylelint-disable-next-line scss/dollar-variable-default
|
||||||
$theme-colors: map-merge(("primary": $primary, "secondary": $secondary, "success": $success, "info": $info, "warning": $warning, "danger": $danger, "light": $light, "dark": $dark), $theme-colors) !default;
|
$theme-colors: map-merge(
|
||||||
|
(
|
||||||
|
'primary': $primary,
|
||||||
|
'secondary': $secondary,
|
||||||
|
'success': $success,
|
||||||
|
'info': $info,
|
||||||
|
'warning': $warning,
|
||||||
|
'danger': $danger,
|
||||||
|
'light': $light,
|
||||||
|
'dark': $dark
|
||||||
|
),
|
||||||
|
$theme-colors
|
||||||
|
) !default;
|
||||||
|
|
||||||
// UI color variables
|
// UI color variables
|
||||||
|
|
||||||
|
30
src/scss/_components/_ui.main.alerts.scss
Normal file
30
src/scss/_components/_ui.main.alerts.scss
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
@import '../_variables';
|
||||||
|
|
||||||
|
#SiteWideAlerts {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 99999;
|
||||||
|
.btn-close {
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.alert {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-offline {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-online {
|
||||||
|
.alert-offline {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-offline {
|
||||||
|
.alert-offline {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
28
src/scss/_components/_ui.main.graphql.scss
Normal file
28
src/scss/_components/_ui.main.graphql.scss
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* some basic styles
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import '../_variables';
|
||||||
|
@import '../_animations';
|
||||||
|
|
||||||
|
.loading {
|
||||||
|
animation: fade 0.5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.graphql-page {
|
||||||
|
&.response-404 {
|
||||||
|
filter: grayscale(1);
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.is-offline {
|
||||||
|
.graphql-page {
|
||||||
|
&.response-523 {
|
||||||
|
filter: grayscale(1);
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,10 +4,9 @@
|
|||||||
|
|
||||||
@import '../_variables';
|
@import '../_variables';
|
||||||
@import '../_animations';
|
@import '../_animations';
|
||||||
|
@import './_ui.main.graphql';
|
||||||
|
@import './_ui.main.alerts';
|
||||||
|
|
||||||
.loading {
|
|
||||||
animation: fade 0.8s linear infinite;
|
|
||||||
}
|
|
||||||
.pulse {
|
.pulse {
|
||||||
animation: pulse 0.8s linear infinite;
|
animation: pulse 0.8s linear infinite;
|
||||||
}
|
}
|
||||||
@ -57,8 +56,6 @@ button,
|
|||||||
&:hover,
|
&:hover,
|
||||||
&.active,
|
&.active,
|
||||||
&[aria-expanded='true'] {
|
&[aria-expanded='true'] {
|
||||||
opacity: 0.8;
|
|
||||||
|
|
||||||
> .fa,
|
> .fa,
|
||||||
> .far,
|
> .far,
|
||||||
> .fas,
|
> .fas,
|
||||||
@ -71,6 +68,11 @@ button,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&[aria-expanded='true'] {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
@ -230,44 +232,12 @@ button.nav-link {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SS-messages
|
// SS-messages
|
||||||
.alert,
|
|
||||||
.alert-info,
|
|
||||||
.alert-danger {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert + .alert {
|
.alert + .alert {
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alert {
|
/*.message {
|
||||||
.container {
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
@media (min-width: map-get($grid-breakpoints, 'sm')) {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.typography {
|
|
||||||
flex: 1 1;
|
|
||||||
}
|
|
||||||
.btn-close {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
@media (min-width: map-get($grid-breakpoints, 'sm')) {
|
|
||||||
position: static;
|
|
||||||
margin-left: 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message {
|
|
||||||
@extend .alert;
|
@extend .alert;
|
||||||
|
|
||||||
@extend .alert-info;
|
@extend .alert-info;
|
||||||
@ -289,7 +259,7 @@ button.nav-link {
|
|||||||
@extend .alert;
|
@extend .alert;
|
||||||
|
|
||||||
@extend .alert-danger;
|
@extend .alert-danger;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
.list-group-item.active {
|
.list-group-item.active {
|
||||||
a,
|
a,
|
||||||
@ -325,18 +295,6 @@ button.nav-link {
|
|||||||
transform: rotate(-90deg);
|
transform: rotate(-90deg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes expand {
|
|
||||||
from {
|
|
||||||
max-height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
max-height: 500rem;
|
|
||||||
max-height: 200vh;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
@ -387,22 +345,6 @@ button.nav-link {
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#SiteWideOffline {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 99999;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert-offline {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
body.is-offline {
|
|
||||||
.alert-offline {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[aria-expanded='true'] {
|
[aria-expanded='true'] {
|
||||||
.fa-bars {
|
.fa-bars {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
@import '_mixings';
|
@import '_mixings';
|
||||||
@import '_colors';
|
//@import '_colors';
|
||||||
|
|
||||||
// screen size - 32px (ex. 1400 - 32 = 1368)
|
// screen size - 32px (ex. 1400 - 32 = 1368)
|
||||||
$grid-breakpoints: (
|
$grid-breakpoints: (
|
||||||
|
259
src/thirdparty/google-analytics-offline.js
vendored
Normal file
259
src/thirdparty/google-analytics-offline.js
vendored
Normal file
@ -0,0 +1,259 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 Google Inc. All Rights Reserved.
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// While overkill for this specific sample in which there is only one cache,
|
||||||
|
// this is one best practice that can be followed in general to keep track of
|
||||||
|
// multiple caches used by a given service worker, and keep them all versioned.
|
||||||
|
// It maps a shorthand identifier for a cache to a specific, versioned cache name.
|
||||||
|
|
||||||
|
// Note that since global state is discarded in between service worker restarts, these
|
||||||
|
// variables will be reinitialized each time the service worker handles an event, and you
|
||||||
|
// should not attempt to change their values inside an event handler. (Treat them as constants.)
|
||||||
|
|
||||||
|
// If at any point you want to force pages that use this service worker to start using a fresh
|
||||||
|
// cache, then increment the CACHE_VERSION value. It will kick off the service worker update
|
||||||
|
// flow and the old cache(s) will be purged as part of the activate event handler when the
|
||||||
|
// updated service worker is activated.
|
||||||
|
var CACHE_VERSION = 1;
|
||||||
|
var CURRENT_CACHES = {
|
||||||
|
'offline-analytics': `offline-analytics-v${ CACHE_VERSION}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
var idbDatabase;
|
||||||
|
var IDB_VERSION = 1;
|
||||||
|
var STOP_RETRYING_AFTER = 86400000; // One day, in milliseconds.
|
||||||
|
var STORE_NAME = 'urls';
|
||||||
|
|
||||||
|
// This is basic boilerplate for interacting with IndexedDB. Adapted from
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB
|
||||||
|
function openDatabaseAndReplayRequests() {
|
||||||
|
var indexedDBOpenRequest = indexedDB.open('offline-analytics', IDB_VERSION);
|
||||||
|
|
||||||
|
// This top-level error handler will be invoked any time there's an IndexedDB-related error.
|
||||||
|
indexedDBOpenRequest.onerror = function(error) {
|
||||||
|
console.error('IndexedDB error:', error);
|
||||||
|
};
|
||||||
|
|
||||||
|
// This should only execute if there's a need to create a new database for the given IDB_VERSION.
|
||||||
|
indexedDBOpenRequest.onupgradeneeded = function() {
|
||||||
|
this.result.createObjectStore(STORE_NAME, { keyPath: 'url' });
|
||||||
|
};
|
||||||
|
|
||||||
|
// This will execute each time the database is opened.
|
||||||
|
indexedDBOpenRequest.onsuccess = function() {
|
||||||
|
idbDatabase = this.result;
|
||||||
|
replayAnalyticsRequests();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to get the object store that we care about.
|
||||||
|
function getObjectStore(storeName, mode) {
|
||||||
|
return idbDatabase.transaction(storeName, mode).objectStore(storeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replayAnalyticsRequests() {
|
||||||
|
var savedRequests = [];
|
||||||
|
|
||||||
|
getObjectStore(STORE_NAME).openCursor().onsuccess = function(event) {
|
||||||
|
// See https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#Using_a_cursor
|
||||||
|
var cursor = event.target.result;
|
||||||
|
|
||||||
|
if (cursor) {
|
||||||
|
// Keep moving the cursor forward and collecting saved requests.
|
||||||
|
savedRequests.push(cursor.value);
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
// At this point, we have all the saved requests.
|
||||||
|
console.log(
|
||||||
|
'About to replay %d saved Google Analytics requests...',
|
||||||
|
savedRequests.length,
|
||||||
|
);
|
||||||
|
|
||||||
|
savedRequests.forEach((savedRequest) => {
|
||||||
|
var queueTime = Date.now() - savedRequest.timestamp;
|
||||||
|
if (queueTime > STOP_RETRYING_AFTER) {
|
||||||
|
getObjectStore(STORE_NAME, 'readwrite').delete(savedRequest.url);
|
||||||
|
console.log(
|
||||||
|
' Request has been queued for %d milliseconds. ' +
|
||||||
|
'No longer attempting to replay.',
|
||||||
|
queueTime,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// The qt= URL parameter specifies the time delta in between right now, and when the
|
||||||
|
// /collect request was initially intended to be sent. See
|
||||||
|
// https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#qt
|
||||||
|
var requestUrl = `${savedRequest.url }&qt=${ queueTime}`;
|
||||||
|
|
||||||
|
console.log(' Replaying', requestUrl);
|
||||||
|
|
||||||
|
fetch(requestUrl)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status < 400) {
|
||||||
|
// If sending the /collect request was successful, then remove it from the IndexedDB.
|
||||||
|
getObjectStore(STORE_NAME, 'readwrite').delete(
|
||||||
|
savedRequest.url,
|
||||||
|
);
|
||||||
|
console.log(' Replaying succeeded.');
|
||||||
|
} else {
|
||||||
|
// This will be triggered if, e.g., Google Analytics returns a HTTP 50x response.
|
||||||
|
// The request will be replayed the next time the service worker starts up.
|
||||||
|
console.error(' Replaying failed:', response);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// This will be triggered if the network is still down. The request will be replayed again
|
||||||
|
// the next time the service worker starts up.
|
||||||
|
console.error(' Replaying failed:', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the IndexedDB and check for requests to replay each time the service worker starts up.
|
||||||
|
// Since the service worker is terminated fairly frequently, it should start up again for most
|
||||||
|
// page navigations. It also might start up if it's used in a background sync or a push
|
||||||
|
// notification context.
|
||||||
|
openDatabaseAndReplayRequests();
|
||||||
|
|
||||||
|
self.addEventListener('activate', (event) => {
|
||||||
|
// Delete all caches that aren't named in CURRENT_CACHES.
|
||||||
|
// While there is only one cache in this example, the same logic will handle the case where
|
||||||
|
// there are multiple versioned caches.
|
||||||
|
var expectedCacheNames = Object.keys(CURRENT_CACHES).map((key) => {
|
||||||
|
return CURRENT_CACHES[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
event.waitUntil(
|
||||||
|
// `caches` refers to the global CacheStorage object, and is defined at
|
||||||
|
// http://slightlyoff.github.io/ServiceWorker/spec/service_worker/#self-caches
|
||||||
|
caches.keys().then((cacheNames) => {
|
||||||
|
return Promise.all(
|
||||||
|
cacheNames.map((cacheName) => {
|
||||||
|
if (expectedCacheNames.indexOf(cacheName) === -1) {
|
||||||
|
// If this cache name isn't present in the array of "expected" cache names, then delete it.
|
||||||
|
console.log('Deleting out of date cache:', cacheName);
|
||||||
|
return caches.delete(cacheName);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// This sample illustrates an aggressive approach to caching, in which every valid response is
|
||||||
|
// cached and every request is first checked against the cache.
|
||||||
|
// This may not be an appropriate approach if your web application makes requests for
|
||||||
|
// arbitrary URLs as part of its normal operation (e.g. a RSS client or a news aggregator),
|
||||||
|
// as the cache could end up containing large responses that might not end up ever being accessed.
|
||||||
|
// Other approaches, like selectively caching based on response headers or only caching
|
||||||
|
// responses served from a specific domain, might be more appropriate for those use cases.
|
||||||
|
self.addEventListener('fetch', (event) => {
|
||||||
|
console.log('Handling fetch event for', event.request.url);
|
||||||
|
|
||||||
|
event.respondWith(
|
||||||
|
caches.open(CURRENT_CACHES['offline-analytics']).then((cache) => {
|
||||||
|
return cache
|
||||||
|
.match(event.request)
|
||||||
|
.then((response) => {
|
||||||
|
if (response) {
|
||||||
|
// If there is an entry in the cache for event.request, then response will be defined
|
||||||
|
// and we can just return it.
|
||||||
|
console.log(' Found response in cache:', response);
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, if there is no entry in the cache for event.request, response will be
|
||||||
|
// undefined, and we need to fetch() the resource.
|
||||||
|
console.log(
|
||||||
|
' No response for %s found in cache. ' +
|
||||||
|
'About to fetch from network...',
|
||||||
|
event.request.url,
|
||||||
|
);
|
||||||
|
|
||||||
|
// We call .clone() on the request since we might use it in the call to cache.put() later on.
|
||||||
|
// Both fetch() and cache.put() "consume" the request, so we need to make a copy.
|
||||||
|
// (see https://fetch.spec.whatwg.org/#dom-request-clone)
|
||||||
|
return fetch(event.request.clone())
|
||||||
|
.then((response) => {
|
||||||
|
console.log(
|
||||||
|
' Response for %s from network is: %O',
|
||||||
|
event.request.url,
|
||||||
|
response,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Optional: add in extra conditions here, e.g. response.type == 'basic' to only cache
|
||||||
|
// responses from the same domain. See https://fetch.spec.whatwg.org/#concept-response-type
|
||||||
|
if (response.status < 400) {
|
||||||
|
// This avoids caching responses that we know are errors (i.e. HTTP status code of 4xx or 5xx).
|
||||||
|
// One limitation is that, for non-CORS requests, we get back a filtered opaque response
|
||||||
|
// (https://fetch.spec.whatwg.org/#concept-filtered-response-opaque) which will always have a
|
||||||
|
// .status of 0, regardless of whether the underlying HTTP call was successful. Since we're
|
||||||
|
// blindly caching those opaque responses, we run the risk of caching a transient error response.
|
||||||
|
//
|
||||||
|
// We need to call .clone() on the response object to save a copy of it to the cache.
|
||||||
|
// (https://fetch.spec.whatwg.org/#dom-request-clone)
|
||||||
|
cache.put(event.request, response.clone());
|
||||||
|
} else if (response.status >= 500) {
|
||||||
|
// If this is a Google Analytics ping then we want to retry it if a HTTP 5xx response
|
||||||
|
// was returned, just like we'd retry it if the network was down.
|
||||||
|
checkForAnalyticsRequest(event.request.url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the original response object, which will be used to fulfill the resource request.
|
||||||
|
return response;
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// The catch() will be triggered for network failures. Let's see if it was a request for
|
||||||
|
// a Google Analytics ping, and save it to be retried if it was.
|
||||||
|
checkForAnalyticsRequest(event.request.url);
|
||||||
|
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
// This catch() will handle exceptions that arise from the match() or fetch() operations.
|
||||||
|
// Note that a HTTP error response (e.g. 404) will NOT trigger an exception.
|
||||||
|
// It will return a normal response object that has the appropriate error code set.
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkForAnalyticsRequest(requestUrl) {
|
||||||
|
// Construct a URL object (https://developer.mozilla.org/en-US/docs/Web/API/URL.URL)
|
||||||
|
// to make it easier to check the various components without dealing with string parsing.
|
||||||
|
var url = new URL(requestUrl);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(url.hostname === 'www.google-analytics.com' ||
|
||||||
|
url.hostname === 'ssl.google-analytics.com') &&
|
||||||
|
url.pathname === '/collect'
|
||||||
|
) {
|
||||||
|
console.log(
|
||||||
|
' Storing Google Analytics request in IndexedDB ' +
|
||||||
|
'to be replayed later.',
|
||||||
|
);
|
||||||
|
saveAnalyticsRequest(requestUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveAnalyticsRequest(requestUrl) {
|
||||||
|
getObjectStore(STORE_NAME, 'readwrite').add({
|
||||||
|
url: requestUrl,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
});
|
||||||
|
}
|
93
src/thirdparty/serviceworker-caches.js
vendored
Normal file
93
src/thirdparty/serviceworker-caches.js
vendored
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
if (!Cache.prototype.add) {
|
||||||
|
Cache.prototype.add = function add(request) {
|
||||||
|
return this.addAll([request]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Cache.prototype.addAll) {
|
||||||
|
Cache.prototype.addAll = function addAll(requests) {
|
||||||
|
var cache = this;
|
||||||
|
|
||||||
|
// Since DOMExceptions are not constructable:
|
||||||
|
function NetworkError(message) {
|
||||||
|
this.name = 'NetworkError';
|
||||||
|
this.code = 19;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
NetworkError.prototype = Object.create(Error.prototype);
|
||||||
|
|
||||||
|
return Promise.resolve()
|
||||||
|
.then(function() {
|
||||||
|
if (arguments.length < 1) throw new TypeError();
|
||||||
|
|
||||||
|
// Simulate sequence<(Request or USVString)> binding:
|
||||||
|
var sequence = [];
|
||||||
|
|
||||||
|
requests = requests.map((request) => {
|
||||||
|
if (request instanceof Request) {
|
||||||
|
return request;
|
||||||
|
} else {
|
||||||
|
return String(request); // may throw TypeError
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(
|
||||||
|
requests.map((request) => {
|
||||||
|
if (typeof request === 'string') {
|
||||||
|
request = new Request(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
var scheme = new URL(request.url).protocol;
|
||||||
|
|
||||||
|
if (scheme !== 'http:' && scheme !== 'https:') {
|
||||||
|
throw new NetworkError('Invalid scheme');
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(request.clone());
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.then((responses) => {
|
||||||
|
// TODO: check that requests don't overwrite one another
|
||||||
|
// (don't think this is possible to polyfill due to opaque responses)
|
||||||
|
return Promise.all(
|
||||||
|
responses.map((response, i) => {
|
||||||
|
return cache.put(requests[i], response);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CacheStorage.prototype.match) {
|
||||||
|
// This is probably vulnerable to race conditions (removing caches etc)
|
||||||
|
CacheStorage.prototype.match = function match(request, opts) {
|
||||||
|
var caches = this;
|
||||||
|
|
||||||
|
return this.keys().then((cacheNames) => {
|
||||||
|
var match;
|
||||||
|
|
||||||
|
return cacheNames.reduce((chain, cacheName) => {
|
||||||
|
return chain.then(() => {
|
||||||
|
return (
|
||||||
|
match ||
|
||||||
|
caches
|
||||||
|
.open(cacheName)
|
||||||
|
.then((cache) => {
|
||||||
|
return cache.match(request, opts);
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
match = response;
|
||||||
|
return match;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}, Promise.resolve());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = self.caches;
|
@ -34,10 +34,10 @@ console.log('GRAPHQL_API_KEY: ' + conf['GRAPHQL_API_KEY']);
|
|||||||
|
|
||||||
let plugins = [
|
let plugins = [
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
$: 'jquery',
|
|
||||||
jQuery: 'jquery',
|
|
||||||
react: 'React',
|
react: 'React',
|
||||||
'react-dom': 'ReactDOM',
|
'react-dom': 'ReactDOM',
|
||||||
|
/*$: 'jquery',
|
||||||
|
jQuery: 'jquery',
|
||||||
Popper: ['popper.js', 'default'],
|
Popper: ['popper.js', 'default'],
|
||||||
Util: 'exports-loader?Util!bootstrap/js/dist/util',
|
Util: 'exports-loader?Util!bootstrap/js/dist/util',
|
||||||
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
|
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
|
||||||
@ -49,7 +49,7 @@ let plugins = [
|
|||||||
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
|
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
|
||||||
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
|
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
|
||||||
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
|
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
|
||||||
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
|
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',*/
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'process.env': {
|
'process.env': {
|
||||||
@ -61,6 +61,8 @@ let plugins = [
|
|||||||
UIMetaNAME: JSON.stringify(UIMetaInfo.name),
|
UIMetaNAME: JSON.stringify(UIMetaInfo.name),
|
||||||
UIMetaVersion: JSON.stringify(UIMetaInfo.version),
|
UIMetaVersion: JSON.stringify(UIMetaInfo.version),
|
||||||
GRAPHQL_API_KEY: JSON.stringify(conf['GRAPHQL_API_KEY']),
|
GRAPHQL_API_KEY: JSON.stringify(conf['GRAPHQL_API_KEY']),
|
||||||
|
SWVERSION: JSON.stringify(`sw-${new Date().getTime()}`),
|
||||||
|
BASE_HREF: JSON.stringify(`http://${IP}:${PORT}`),
|
||||||
}),
|
}),
|
||||||
new webpack.LoaderOptionsPlugin({
|
new webpack.LoaderOptionsPlugin({
|
||||||
minimize: COMPRESS,
|
minimize: COMPRESS,
|
||||||
|
@ -122,9 +122,10 @@ const config = merge(common, {
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
$: 'jquery',
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
/*$: 'jquery',
|
||||||
jQuery: 'jquery',
|
jQuery: 'jquery',
|
||||||
'window.jQuery': 'jquery',
|
|
||||||
Popper: ['popper.js', 'default'],
|
Popper: ['popper.js', 'default'],
|
||||||
Util: 'exports-loader?Util!bootstrap/js/dist/util',
|
Util: 'exports-loader?Util!bootstrap/js/dist/util',
|
||||||
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
|
Alert: 'exports-loader?Alert!bootstrap/js/dist/alert',
|
||||||
@ -136,7 +137,7 @@ const config = merge(common, {
|
|||||||
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
|
Tooltip: 'exports-loader?Tooltip!bootstrap/js/dist/tooltip',
|
||||||
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
|
Popover: 'exports-loader?Popover!bootstrap/js/dist/popover',
|
||||||
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
|
Scrollspy: 'exports-loader?Scrollspy!bootstrap/js/dist/scrollspy',
|
||||||
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',
|
Tab: 'exports-loader?Tab!bootstrap/js/dist/tab',*/
|
||||||
}),
|
}),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
UINAME: JSON.stringify(UIInfo.name),
|
UINAME: JSON.stringify(UIInfo.name),
|
||||||
@ -145,6 +146,8 @@ const config = merge(common, {
|
|||||||
UIMetaNAME: JSON.stringify(UIMetaInfo.name),
|
UIMetaNAME: JSON.stringify(UIMetaInfo.name),
|
||||||
UIMetaVersion: JSON.stringify(UIMetaInfo.version),
|
UIMetaVersion: JSON.stringify(UIMetaInfo.version),
|
||||||
GRAPHQL_API_KEY: JSON.stringify(conf['GRAPHQL_API_KEY']),
|
GRAPHQL_API_KEY: JSON.stringify(conf['GRAPHQL_API_KEY']),
|
||||||
|
SWVERSION: JSON.stringify(`sw-${new Date().getTime()}`),
|
||||||
|
BASE_HREF: JSON.stringify(`http://${IP}:${PORT}`),
|
||||||
}),
|
}),
|
||||||
//new webpack.HotModuleReplacementPlugin(),
|
//new webpack.HotModuleReplacementPlugin(),
|
||||||
new MiniCssExtractPlugin(),
|
new MiniCssExtractPlugin(),
|
||||||
@ -166,6 +169,9 @@ const config = merge(common, {
|
|||||||
host: IP,
|
host: IP,
|
||||||
port: PORT,
|
port: PORT,
|
||||||
historyApiFallback: false,
|
historyApiFallback: false,
|
||||||
|
// disable it to test service worker
|
||||||
|
injectClient: false,
|
||||||
|
|
||||||
//hot: true,
|
//hot: true,
|
||||||
/*clientLogLevel: 'info',
|
/*clientLogLevel: 'info',
|
||||||
disableHostCheck: true,
|
disableHostCheck: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user