IMPR: caching service worker and minor improvements

This commit is contained in:
Tony Air 2021-02-18 09:12:01 +07:00
parent 025cb00bc1
commit 0dc2834870
24 changed files with 961 additions and 137 deletions

View File

@ -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>

View 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>

View 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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 213 KiB

59
src/img/logo.svg Normal file
View 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

View File

@ -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">

View File

@ -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}`, () => {

View File

@ -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('not-found'); el.classList.add(`response-${e.status}`);
/*switch (e.status) {
case 404:
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`);
}); });

View 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;

View File

@ -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);

View File

@ -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(
Title: 'Not Found', Object.assign(ui.empty_state, {
CSSClass: 'graphql__not-found', Title: 'Not Found',
Summary: 'Not Found', CSSClass: 'graphql__status-404',
loading: false, Summary: 'The page is not found.',
}); 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 (

View File

@ -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
View 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
View 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}`);
});

View File

@ -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;
} }
} }

View File

@ -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

View 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;
}
}

View 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;
}
}
}

View File

@ -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 {

View File

@ -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: (

View 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
View 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;

View File

@ -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,

View File

@ -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,