From 409dcdbc9ac9edee1b6c8c582e3f21b6b86b3ece Mon Sep 17 00:00:00 2001 From: Adhidarma Hadiwinoto <me@adhisimon.org> Date: Tue, 10 Dec 2019 11:02:24 +0700 Subject: [PATCH] awal webadmin --- index.js | 1 + lib/webadmin/index.js | 29 +++++++ lib/webadmin/router/config.js | 87 +++++++++++++++++++ package.json | 1 + .../assets/img/favicons/android-chrome-192x192.png | Bin 0 -> 1935 bytes .../assets/img/favicons/apple-touch-icon.png | Bin 0 -> 1738 bytes .../assets/img/favicons/browserconfig.xml | 9 ++ .../assets/img/favicons/favicon-16x16.png | Bin 0 -> 310 bytes .../assets/img/favicons/favicon-32x32.png | Bin 0 -> 491 bytes webadmin-statics/assets/img/favicons/favicon.ico | Bin 0 -> 5430 bytes webadmin-statics/assets/img/favicons/manifest.json | 20 +++++ .../assets/img/favicons/mstile-150x150.png | Bin 0 -> 1428 bytes .../assets/img/favicons/safari-pinned-tab.svg | 4 + webadmin-statics/assets/starter-template.css | 7 ++ webadmin-views/config.include.addmodem.html | 8 ++ webadmin-views/config.index.html | 80 ++++++++++++++++++ webadmin-views/template.starter.html | 92 +++++++++++++++++++++ 17 files changed, 338 insertions(+) create mode 100644 lib/webadmin/router/config.js create mode 100644 webadmin-statics/assets/img/favicons/android-chrome-192x192.png create mode 100644 webadmin-statics/assets/img/favicons/apple-touch-icon.png create mode 100644 webadmin-statics/assets/img/favicons/browserconfig.xml create mode 100644 webadmin-statics/assets/img/favicons/favicon-16x16.png create mode 100644 webadmin-statics/assets/img/favicons/favicon-32x32.png create mode 100644 webadmin-statics/assets/img/favicons/favicon.ico create mode 100644 webadmin-statics/assets/img/favicons/manifest.json create mode 100644 webadmin-statics/assets/img/favicons/mstile-150x150.png create mode 100644 webadmin-statics/assets/img/favicons/safari-pinned-tab.svg create mode 100644 webadmin-statics/assets/starter-template.css create mode 100644 webadmin-views/config.include.addmodem.html create mode 100644 webadmin-views/config.index.html create mode 100644 webadmin-views/template.starter.html diff --git a/index.js b/index.js index c2836d2..aee7edc 100644 --- a/index.js +++ b/index.js @@ -15,3 +15,4 @@ const transport = require('./lib/transport'); messagingClient.setTransport(transport); require('./lib/apiserver'); +require('./lib/webadmin'); \ No newline at end of file diff --git a/lib/webadmin/index.js b/lib/webadmin/index.js index 3290748..f6d3b0e 100644 --- a/lib/webadmin/index.js +++ b/lib/webadmin/index.js @@ -1,11 +1,40 @@ const express = require('express'); +const morgan = require('morgan'); +const rfs = require('rotating-file-stream'); +const nunjucks = require('nunjucks'); +const moment = require('moment'); const config = require('komodo-sdk/config'); const logger = require('komodo-sdk/logger'); +const routerConfig = require('./router/config'); const app = express(); +nunjucks.configure('./webadmin-views', { + autoescape: true, + express: app, + noCache: true, +}); + +app.use(express.static('./webadmin-statics')); + +const accessLogStream = rfs.createStream( + (time, index) => { + const ts = time ? `.${moment(time).format('YYYY-MM-DD')}` : ''; + const idx = index ? `.${index}` : ''; + return `apiserver.access_log${ts}${idx}`; + }, + { + interval: '1d', + path: './logs', + }, +); + +app.use(morgan('combined', { stream: accessLogStream })); + +app.use('/config', routerConfig); + const listenPort = (config.webadmin && config.webadmin.port) || 21923; app.listen(listenPort, () => { logger.info(`WEBADMIN listen on port ${listenPort}`); diff --git a/lib/webadmin/router/config.js b/lib/webadmin/router/config.js new file mode 100644 index 0000000..c70c867 --- /dev/null +++ b/lib/webadmin/router/config.js @@ -0,0 +1,87 @@ +const fs = require('fs'); +const express = require('express'); + +const config = require('komodo-sdk/config'); + +const router = express.Router(); +module.exports = router; + +function composeNewModem(name, params) { + return { + name, + outgoing: (params && params.outgoing) || false, + prefix: (params && params.prefix) || [], + }; +} + +async function writeConfigFile() { + try { + await fs.promises.writeFile('config.json', JSON.stringify(config, null, 4)); + } catch (e) { + // + } +} + +function pageMain(req, res) { + res.render('config.index.html', { + config: JSON.stringify(config, null, 4), + modems: config.modems, + baseUrl: req.baseUrl, + }); +} + +async function pageSetOutgoing(req, res) { + const modemName = (req.params.modemName || '').trim(); + if (!modemName) { + res.end('Invalid modem name'); + return; + } + + const idx = (config.modems || []).findIndex((modem) => modem.name === modemName); + if (idx < 0) { + res.end('No modem matched'); + return; + } + + config.modems[idx].outgoing = req.params.newValue === '1' || req.params.newValue === 'true'; + + await writeConfigFile(); + + res.redirect(`${req.baseUrl}`); +} + +async function pageDelPrefix(req, res) { + const modemName = (req.params.modemName || '').trim(); + if (!modemName) { + res.end('Invalid modem name'); + return; + } + + const prefix = (req.params.prefix || '').trim(); + if (!prefix) { + res.end('Invalid prefix'); + return; + } + + const modemIdx = (config.modems || []).findIndex((modem) => modem.name === modemName); + if (modemIdx < 0) { + res.end('No modem matched'); + return; + } + + const prefixIdx = (config.modems[modemIdx].prefix || []).indexOf(prefix); + if (prefixIdx < 0) { + res.end('No prefix matched'); + return; + } + + config.modems[modemIdx].prefix.splice(prefixIdx, 1); + + await writeConfigFile(); + + res.redirect(`${req.baseUrl}`); +} + +router.get('/', pageMain); +router.get('/modem/set-outgoing/:modemName/:newValue', pageSetOutgoing); +router.get('/modem/del-prefix/:modemName/:prefix', pageDelPrefix); diff --git a/package.json b/package.json index 3d33051..0e65415 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "locks": "^0.2.2", "moment": "^2.24.0", "morgan": "^1.9.1", + "nunjucks": "^3.2.0", "rotating-file-stream": "^2.0.0", "uniqid": "^5.2.0" }, diff --git a/webadmin-statics/assets/img/favicons/android-chrome-192x192.png b/webadmin-statics/assets/img/favicons/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..547386f3714c7b0a58c5fe519863f4a11e039b91 GIT binary patch literal 1935 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 aUnL;$nB=BNU<n?~8Za?5Hz?J66!|X%TjVkT literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/apple-touch-icon.png b/webadmin-statics/assets/img/favicons/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..447cec2c47da7a30359729a36d3c5096dbde5a15 GIT binary patch literal 1738 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 literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/browserconfig.xml b/webadmin-statics/assets/img/favicons/browserconfig.xml new file mode 100644 index 0000000..30422dc --- /dev/null +++ b/webadmin-statics/assets/img/favicons/browserconfig.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<browserconfig> + <msapplication> + <tile> + <square150x150logo src="/assets/img/favicons/mstile-150x150.png"/> + <TileColor>#563d7c</TileColor> + </tile> + </msapplication> +</browserconfig> diff --git a/webadmin-statics/assets/img/favicons/favicon-16x16.png b/webadmin-statics/assets/img/favicons/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..5f7d11880f60757cd3f1de2681def0e59e6b81b2 GIT binary patch literal 310 zcmV-60m=S}P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0002}Nkl<ZcmZRG zvZ)XZx2tIhv#ogv#Q%xJFF|@hdKsXa|C573dKvKBOxPt1=z<d)SN-3x<PaRMUvdyE zmgv=r)esB=j_$qm|KGoV{~z3b4#tn~z5M_8@8AD_e*gKO8Qe{r0l$9zMiHw>o&FyL z)-F6io&ouh{a^zYPu)SJ7ykbHe_;DLFh0EN!vA-#Km9*_<of>@mqwxt0Q-6C>SJ(x z{o;fF-@pC*Kecr&sa`<ftLN|kfARDk1qPhE_y5nIzyBj0>WK0JN?N#d`VKg1kM6ld z&;=k3p!kR5dpDo{KYjSx|M?TQ{*QKUz%YQ~q)c&UqBuJP06X(p%mL%EV*mgE07*qo IM6N<$f{ZYjO#lD@ literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/favicon-32x32.png b/webadmin-statics/assets/img/favicons/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..d752fd5d71545548fb0baf3f3a1b500e13e520b9 GIT binary patch literal 491 zcmV<H0Tlj;P)<h;3K|Lk000e1NJLTq001BW001Be1^@s6b9#F800059Nkl<Zcmc$g zgOcn(7=`Cm?t5I@wr$(Cy|%rDwQbwBt@NBtr^aUIRDI*g|D`PfAh2)w(<S?tJ@w?N z<{><=F+_H4Pg+Y}S9mzE{ONA~iwPbuVuIEb1gH(;;tB~`TOw<Ah=eB<s1{M6nhFpR z1&GAhj}EMOh9hfU8fNuNizSQ-e0l5#Q!+I<gSN&VMEIoP?6wcA1+-;u9{Fi|0V$Cp zHKtgL!ps_>sA@Wz`)n^TKfj>&cZXI!M|@;HRC8(fXLbUVhvyuinpfA|*b2})mWL36 zQ=8wh6$tT2hCH?9ZMGi+3-cVFTy)an^CLfG#Ft`jb{;gHZT<F{1*T+tbP6{P{SbE@ z;1)ReJI33m3$E<@s>QVf-|+WcC<-!bguy4z?^nTW2O%ZQD;4r|w)V3ZczE_dRC8?I zYqkP(Mrf~w3<dJisvytg#0(BBe`Zqwo#%mL>t5mgT`#0W7lY#n<jF~{5N8_Fj0{cS z-1ZOb1?ZNYkx+)~2fy299e8l&Ki%^ULbqW*$2fd{9*D)|LM$d44|t<=z?<a*-Z2^Q huGxThP6xbu4ge7hh~d=wl@kB}002ovPDHLkV1f@j-Y)<E literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/favicon.ico b/webadmin-statics/assets/img/favicons/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b48b3442ad90fd9b5bcbef8a9f703c1852de1561 GIT binary patch literal 5430 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 literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/manifest.json b/webadmin-statics/assets/img/favicons/manifest.json new file mode 100644 index 0000000..2709f42 --- /dev/null +++ b/webadmin-statics/assets/img/favicons/manifest.json @@ -0,0 +1,20 @@ +{ + "name": "Bootstrap", + "short_name": "Bootstrap", + "icons": [ + { + "src": "/assets/img/favicons/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/assets/img/favicons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "start_url": "/?utm_source=a2hs", + "theme_color": "#563d7c", + "background_color": "#563d7c", + "display": "standalone" +} diff --git a/webadmin-statics/assets/img/favicons/mstile-150x150.png b/webadmin-statics/assets/img/favicons/mstile-150x150.png new file mode 100644 index 0000000000000000000000000000000000000000..bb87faf74f15ea00e1a38555dc6162fb117a4fbe GIT binary patch literal 1428 zcmbW0X;2af6vuJR%{8UdHi^ourctxf#!5C1EYB=-%~jMi(<IXh1!KJp4?H7OR8m9| za|!am3(v}1F|SNRElol3zym=syw+xC`mi7O&F{_p|L?tT|9SDYFbfqWkP-j@P_eQ! zwF3a;fZtnDetTkr{3T=CEZAPRH`}%jhN1tPd{Xs0cGugAuIge=ab83I^J?<b62g;L zXtz|jad?0C=+@TOw^iBT$8q-S)<`79(I{+cVxFE=>ur}HldZj`zID0!WQsqB3wW`) zxk<*CPzYt|v4s+`)C(3XoDt0k7M4WIfnFI1n>bgqNR(>|?s0B5zI1eGvg}oJV(?1= ze~y*k=zlA@y}sYig|M-)(cd*v!|JGEaX1YFxkUCr&uDyLUdx+4f0yJUT0O=ijTB#$ z8pZUnPwZ^re(W0Yyp9u#R=y4ksLACiSVlr%-kNN^qj3P`meR`^{?PH+<;oLx%jn>H zBx20#y0Z6!ePa`2vy1cM`PrqENT!>4WJ6WYeY=FJqV{{X@uCGuUPe_`5{p5ptFP={ zUt3R$DG*LC-ZI7BznRDzonDp7ykK#@e<l$kUX6VgFtY2OhW<@Wsi<JKbTob9jZBYy znOa$1^|Z!?`(|Y(vW5qE<;)g*INifKrn0cj$s_{lOo+qK*adA1bK;)%VNzU?qjA{0 za0%)3EWn-E-8PhtD_E9Dhx>W1X4s~h-hkVw&2=AGFB@Kxs_Goe?6)IV4X}gV1ZV}) z>bOf=NyCYU$?H3!R`$Qu9wG6P9{~XJ##W{#_JMN3dO4Ntb2%MZ#z5ny0JN=t6x8BK z=pl7wd0haJsTf})%}LW-JpGqZ6Y<+lNb}btZcSllHwTv=2ga^x8c+=`N%{wZERm|? zEqoI+bZE%H=bWO;^VkUmCr@#up*jNwBB^GAZs=K7U%nwZoNyErq~4|q(gX$@>4{?~ ziHNgp{(5|BOCKRN6M9w7=eUX)-Aa#0J=JH6138aB%MO7npH#}#sjWS?r_^J(;^8)z z)j}ps?uAr0K89_~I)^<xkJ5<!7g`?^Qd3!76%rV%>lfJJA{H%+ciRHBbu{3RVnUD3 z#Jh$QMES%dJD_zh=Z>a1q?oHe@s6yfKfa%$A!`3}f1jL1Nf3khu}q@OO0#OkD%>4} zmS{o%CoQxm&ZFFeBCAT#{9hFhaJud&DQM*iG!D|EDKvZP`CvQ>t2G7DQefl?=m+UI z3e7=1A{gk1otc8n+$pOsM(bUy_ugT+vk=^g%chx89WeL`%pu|8_~evuAHAk^5hYn! z-hDt(kL01DUlL34hCc|BmKeuGnVYM$boS2wj^IM5{x&o){K{lB%6%^NCI@?C?etCu zTLw7YLs1`r$a(N6+z<ZXjNhorVHfaTYwM0sF#H<*nL9cO%;hkkzO#HV!V^xl!vIS) zdkz{}KylDCAsFF8)egoV!D6N%OA13Y!J-mY6c!9b19-6<U1gqy1l$^VrW8$9<a=@< zFokPW0qMY0QZ`LwNj1RW(e=4)kh8}Xn7qk0=l#MS9rP`?_;Ph;{A|{6%>@?5cx42l zMWzUUtA!qwnjE`q(s^tUQf!l>V&0{j?W2Rj=b!uegkZJWL+25mi~N~4xf*`KOUDO) zOxIY&{QcfdUnv_qa-uaS`V&Ydvi(CMz1_sxyxX1mJ?~<_b>xDP(w>B$0Jse{JEBJM zE9cbS57&%$MRl}fDZycfQn>vjH78fK7lZsdN_=i}z8urAD5$iYEm~VE2pif(t}9&F wBlEVoh^TyH8K;>sM4_gWJt}{^!hgh*kV{n)N<e?YEb{xt$_!>&c*Q;PAM!lYqW}N^ literal 0 HcmV?d00001 diff --git a/webadmin-statics/assets/img/favicons/safari-pinned-tab.svg b/webadmin-statics/assets/img/favicons/safari-pinned-tab.svg new file mode 100644 index 0000000..ddeeb53 --- /dev/null +++ b/webadmin-statics/assets/img/favicons/safari-pinned-tab.svg @@ -0,0 +1,4 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="933.333" height="933.333" version="1" viewBox="0 0 700 700"> + <path d="M104.5.7C89.2 2.6 77.4 6.2 63.8 13.2 41.7 24.5 24.5 41.7 13.2 63.8 7.5 75.1 4.8 82.3 2.3 94 .6 102.1.5 114.3.5 350s.1 247.9 1.8 256c2.5 11.7 5.2 18.9 10.9 30.2 11.3 22.1 28.5 39.3 50.6 50.6 11.3 5.7 18.5 8.4 30.2 10.9 8.1 1.7 20.3 1.8 256 1.8s247.9-.1 256-1.8c11.7-2.5 18.9-5.2 30.2-10.9 22.1-11.3 39.3-28.5 50.6-50.6 5.7-11.3 8.4-18.5 10.9-30.2 1.7-8.1 1.8-20.3 1.8-256s-.1-247.9-1.8-256c-2.5-11.7-5.2-18.9-10.9-30.2C670.9 32.6 642.9 11 607 2.4 599.9.7 587.2.6 353.5.4 218.2.3 106.2.5 104.5.7zm315.3 153.6c47.4 9 75.3 30.5 85.6 65.9 5.1 17.8 5.6 43.1 1.1 60.3-2 7.5-7.9 20.3-12.2 26.4-8 11.3-21.9 22.8-36 30-3.5 1.7-6.3 3.5-6.3 3.9 0 .5 2.3 1.4 5.1 2 2.8.7 8.5 2.6 12.7 4.3 37.2 14.8 58.1 50.4 58.2 99 0 28.6-9 53.9-25.7 71.8-18.8 20.3-45.2 32.9-83.3 39.8-8.5 1.5-20.9 1.7-119.2 2l-109.8.4V151.9l110.8.4c95.5.3 111.8.6 119 2z"/> + <path d="M262 266.5v56.6l65.3-.4c57.2-.3 65.9-.5 70.7-2 15.8-4.8 28.7-14.9 34.4-27.1 4.4-9.2 5.6-15.3 5.6-28.4-.1-25.1-7.5-39.8-24.3-47.7-14.1-6.7-14.2-6.7-86.4-7.2l-65.3-.5v56.7zm0 171.5v64.1l71.3-.3c69.8-.3 71.4-.4 79-2.6 11.4-3.2 19.2-7.7 27.2-15.7 12.1-12 16.8-24.9 16.8-46 0-20.8-5.1-34.3-17.3-45.9-7.9-7.4-15.8-11.6-28.1-14.7-8.1-2.1-10.5-2.2-78.6-2.6l-70.3-.5V438z"/> +</svg> diff --git a/webadmin-statics/assets/starter-template.css b/webadmin-statics/assets/starter-template.css new file mode 100644 index 0000000..0b1d089 --- /dev/null +++ b/webadmin-statics/assets/starter-template.css @@ -0,0 +1,7 @@ +body { + padding-top: 5rem; +} +.starter-template { + padding: 3rem 1.5rem; + text-align: left; +} diff --git a/webadmin-views/config.include.addmodem.html b/webadmin-views/config.include.addmodem.html new file mode 100644 index 0000000..a3de4b6 --- /dev/null +++ b/webadmin-views/config.include.addmodem.html @@ -0,0 +1,8 @@ +<div class="card"> + <div class="card-header bg-info"> + <h3>Tambah Modem</3> + </div> + <div class="card-body"> + + </div> +</div> \ No newline at end of file diff --git a/webadmin-views/config.index.html b/webadmin-views/config.index.html new file mode 100644 index 0000000..b1e9931 --- /dev/null +++ b/webadmin-views/config.index.html @@ -0,0 +1,80 @@ +{% extends "template.starter.html" %} + +{% block content %} + +<!-- +<code> +{{ config | nl2br | safe }} +</code> +--> + +{% for modem in modems %} +<div class="card"> + <div class="card-header bg-info"> + <h3>{{ modem.name }}</3> + </div> + <div class="card-body"> + + <dl class="row"> + <dt class="col-sm-3">Outgoing</dt> + <dd class="col-sm-9"> + {% if modem.outgoing %} + {% set newValue = 0 %} + {% else %} + {% set newValue = 1 %} + {% endif %} + <a href="{{ baseUrl }}/modem/set-outgoing/{{ modem.name | urlencode }}/{{ newValue }}" onclick="return window.confirm('Apakah anda yakin ingin mengubah status outgoing modem {{ modem.name }} menjadi {{ not modem.outgoing }}?');"> + {{ modem.outgoing }} + </a> + </dd> + </dl> + + <dl class="row"> + <dt class="col-sm-3">IMSI</dt> + <dd class="col-sm-9"> + {{ modem.imsi or '-' }} + <br> + [<a href="{{ baseUrl }}/modem/set-imsi/{{ modem.name | urlencode }}"> + edit + </a>] + </dd> + </dl> + + <dl class="row"> + <dt class="col-sm-3">Prefix</dt> + <dd class="col-sm-9"> + {% for prefix_item in modem.prefix %} + {{ prefix_item }} + <a href="{{ baseUrl }}/modem/del-prefix/{{ modem.name | urlencode }}/{{ prefix_item | urlencode}}" onclick="return window.confirm('Apakah anda yakin ingin mengapus prefix {{ prefix_item }} dari modem {{ modem.name }}?');"> + x + </a> + <br> + {% endfor %} + + [ + <a href="{{ baseUrl }}/modem/add-prefix/{{ modem.name | urlencode }}"> + tambah + </a> + ] + </dd> + </dl> + + <dl class="row"> + <dt class="col-sm-3">Custom IP</dt> + <dd class="col-sm-9"> + {{ modem.ip or 'none' }} + <br> + [<a href="{{ baseUrl }}/modem/set-ip/{{ modem.name | urlencode }}"> + edit + </a>] + </dd> + </dl> + + </div> +</div> +<br> +{% endfor %} + +{% include "config.include.addmodem.html" %} + +{% endblock %} \ No newline at end of file diff --git a/webadmin-views/template.starter.html b/webadmin-views/template.starter.html new file mode 100644 index 0000000..66096ee --- /dev/null +++ b/webadmin-views/template.starter.html @@ -0,0 +1,92 @@ + +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> + <meta name="description" content=""> + <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors"> + <meta name="generator" content="Jekyll v3.8.6"> + <title>Starter Template ยท Bootstrap</title> + + <!-- Bootstrap core CSS --> + <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous"> + + <!-- Favicons --> + <link rel="apple-touch-icon" href="/assets/img/favicons/apple-touch-icon.png" sizes="180x180"> + <link rel="icon" href="/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png"> + <link rel="icon" href="/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png"> + <link rel="manifest" href="/assets/img/favicons/manifest.json"> + <link rel="mask-icon" href="/assets/img/favicons/safari-pinned-tab.svg" color="#563d7c"> + <link rel="icon" href="/assets/img/favicons/favicon.ico"> + <meta name="msapplication-config" content="/assets/img/favicons/browserconfig.xml"> + <meta name="theme-color" content="#563d7c"> + + + <style> + .bd-placeholder-img { + font-size: 1.125rem; + text-anchor: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + + @media (min-width: 768px) { + .bd-placeholder-img-lg { + font-size: 3.5rem; + } + } + </style> + <!-- Custom styles for this template --> + <link href="/assets/starter-template.css" rel="stylesheet"> + </head> + <body> + <nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top"> + <a class="navbar-brand" href="#">Navbar</a> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault" aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + + <div class="collapse navbar-collapse" id="navbarsExampleDefault"> + <ul class="navbar-nav mr-auto"> + <li class="nav-item active"> + <a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a> + </li> + <li class="nav-item"> + <a class="nav-link" href="#">Link</a> + </li> + <li class="nav-item"> + <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a> + </li> + <li class="nav-item dropdown"> + <a class="nav-link dropdown-toggle" href="#" id="dropdown01" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a> + <div class="dropdown-menu" aria-labelledby="dropdown01"> + <a class="dropdown-item" href="#">Action</a> + <a class="dropdown-item" href="#">Another action</a> + <a class="dropdown-item" href="#">Something else here</a> + </div> + </li> + </ul> + <form class="form-inline my-2 my-lg-0"> + <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search"> + <button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button> + </form> + </div> +</nav> + +<main role="main" class="container"> + + <div class="starter-template"> + {% block content %} + + {% endblock %} + </div> + +</main><!-- /.container --> + +<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script> +<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script> +<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script> +</html> -- 1.9.0