Upgrade to bootstrap v4.6.1, using CDN bootstrap for now (many things broken)
[ndcode_site.git] / navbar.jst
1 let assert = require('assert')
2 let XDate = require('xdate')
3
4 return async (env, head, body, scripts) => {
5   //let cart = await _require('/online_store/cart.jst')
6   let globals = await env.site.get_json('/_config/globals.json')
7   //let icon_cart_small = await env.site.get_min_svg('/_svg/icon_cart_small.svg')
8   let icon_search_mono = await env.site.get_min_svg('/_svg/icon_search_mono.svg')
9   let logo_large = await env.site.get_min_svg('/_svg/logo_large.svg')
10   let menu = await env.site.get_menu('/_menu.json')
11   let page = await _require('/page.jst')
12   //let session = await _require('/session.jst')
13
14   // initialize env.sessions, env.session_key, env.session
15   //await session(env)
16
17   // initialize env.cart
18   //await cart(env)
19
20   await page(
21     env,
22     // head
23     async _out => {
24       // extract top-level directory name
25       assert(env.parsed_url.pathname.slice(0, 1) === '/')
26       let index = env.parsed_url.pathname.indexOf('/', 1)
27       let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
28
29       title {
30         _out.push(
31           globals.site_title + ': ' + (
32             dir.length === 0 ?
33             'Home' :
34             menu.entries[menu.index[dir]].name
35           )
36         )
37       }
38
39       await head(_out)
40     },
41     // body
42     async _out => {
43       // extract top-level directory name
44       assert(env.parsed_url.pathname.slice(0, 1) === '/')
45       let index = env.parsed_url.pathname.indexOf('/', 1)
46       let dir = index === -1 ? '' : env.parsed_url.pathname.slice(1, index)
47
48       div(style="padding-left: calc(100vw - 100%);") {
49         div.container(style="margin-top: 5px; margin-bottom: 5px;") {
50           div.row {
51             div.'col-sm-8'.vbottom {
52               _out.push(logo_large)
53             }
54             div.'col-sm-4'.vbottom(style="padding-bottom: 15px;") {
55               //div {
56               //  let signed_in =
57               //    Object.prototype.hasOwnProperty.call(env.session, 'account')
58               //  span#signed-in-status {
59               //    if (signed_in)
60               //      `Signed in as ${env.session.account}.`
61               //    else
62               //      'Browsing as guest.'
63               //  }
64               //  ' '
65               //  if (signed_in)
66               //    a#sign-in(href="" hidden="") {'Sign in'}
67               //  else
68               //    a#sign-in(href="") {'Sign in'}
69               //  ' '
70               //  if (signed_in)
71               //    a#sign-out(href="") {'Sign out'}
72               //  else
73               //    a#sign-out(href="" hidden="") {'Sign out'}
74               //}
75               //p {}
76
77               //form(action="/search/index.html") {
78               //  div.input-group {
79               //    input.form-control(name="query" type="text" placeholder="Search") {}
80               //    span.input-group-btn {
81               //      button.btn.btn-default(type="submit") {
82               //        _out.push(icon_search_mono)
83               //      }
84               //    }
85               //  }
86               //}
87               form.form-inline.'my-2'.my-lg-0(action="/search/index.html") {
88                 input.form-control.mr-sm-2(name="query" type="text" placeholder="Search" aria-label="Search") {}
89                 ' '
90                 button.btn.btn-outline-success.'my-2'.my-sm-0(type="submit") {
91                   'Search'
92                 }
93               }
94             }
95             //div.'col-sm-1'.vbottom {
96             //  // a nested div is used to avoid hover colour on the padding
97             //  div.nav-li-a(style="text-align: center;") {
98             //    a(href="/online_store/view_cart/index.html") {
99             //      div.cart-icon {
100             //        _out.push(icon_cart_small)
101             //      }
102             //      div.cart-number {
103             //        div.cart-circle {
104             //          `${(env.cart.items || []).length}`
105             //        }
106             //      }
107             //    }
108             //  }
109             //}
110           }
111         }
112       }
113       nav.navbar.navbar-expand-lg.navbar-light.bg-light {
114         div.container { //div(style="padding-left: calc(100vw - 100%);") {
115           //a.navbar-brand(href="#") {'Navbar'}
116           //' '
117           button.navbar-toggler(type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation") {
118             span.navbar-toggler-icon {}
119           }
120           div.collapse.navbar-collapse#navbarSupportedContent {
121             ul.navbar-nav.mr-auto {
122               if (dir.length === 0)
123                 li.nav-item.active {
124                   a.nav-link(href="/index.html") {
125                     'Home'
126                     span.sr-only {' (current)'}
127                   }
128                 }
129               else
130                 li.nav-item {
131                   a.nav-link(href="/index.html") {'Home'}
132                 }
133               let entries = menu.entries
134               for (let i = 0; i < entries.length; ++i)
135                 if (entries[i].navbar)
136                   if (entries[i].dir === dir)
137                     li.nav-item.active {
138                       a.nav-link(href=`/${entries[i].dir}/index.html`) {
139                         `${entries[i].name}`
140                         span.sr-only {' (current)'}
141                       }
142                     }
143                   else
144                     li.nav-item {
145                       a.nav-link(href=`/${entries[i].dir}/index.html`) {
146                         `${entries[i].name}`
147                       }
148                     }
149               //li.nav-item.dropdown {
150               //  a.nav-link.dropdown-toggle#navbarDropdown(href="#" role="button" data-toggle="dropdown" aria-expanded="false") {
151               //    'Dropdown'
152               //  }
153               //  div.dropdown-menu(aria-labelledby="navbarDropdown") {
154               //    a.dropdown-item(href="#") {
155               //      'Action'
156               //    }
157               //    ' '
158               //    a.dropdown-item(href="#") {
159               //      'Another action'
160               //    }
161               //    div.dropdown-divider {}
162               //    a.dropdown-item(href="#") {
163               //      'Something else here'
164               //    }
165               //  }
166               //}
167               //li.nav-item {
168               //  a.nav-link.disabled {
169               //    'Disabled'
170               //  }
171               //}
172             }
173             ul.navbar-nav.ml-auto {
174               li.nav-item {
175                 a.nav-link#give-feedback(href="") {'Give feedback'}
176               }
177             }
178           }
179         }
180       }
181       div(style="padding-left: calc(100vw - 100%); margin-bottom: 50px;") {
182         div.container {
183           await body(_out)
184         }
185       }
186       div.footer(style="padding-left: calc(100vw - 100%);") {
187         div.container { //-fluid") {
188           a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
189             img(alt="Creative Commons License" style="border-width:0" src="/images/by-sa_3.0_88x31.png") {}
190           }
191           p {
192             'This website is '
193             a(href="https://git.ndcode.org/public/ndcode_site.git") {
194               'open source'
195             }
196             ' and licensed under a '
197             a(rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/") {
198               'Creative Commons Attribution-ShareAlike 3.0 Unported License'
199             }
200             '.'
201           }
202
203           p {'Example code fragments embedded within the text are placed in the public domain unless otherwise noted.'}
204
205           p {`Copyright © ${new XDate().getUTCFullYear()} ${globals.copyright}.`}
206         }
207       }
208
209       // hidden part
210       //div#sign-in-modal.modal.fade(role="dialog") {
211       //  div.modal-dialog {
212       //    div.modal-content {
213       //      div.modal-header {
214       //        button.close(type="button" data-dismiss="modal") {
215       //          '×'
216       //        }
217       //        h4.modal-title {
218       //          'Sign in'
219       //        }
220       //      }
221       //      div.modal-body {
222       //        form#sign-in-form(method="post" action="/sign_in.json" role="form") {
223       //          div.row {
224       //            div.col-md-12 {
225       //              div.form-group {
226       //                label(for="sign-in-form-email") {'Email'}
227       //                input.form-control#sign-in-form-email(type="text" name="email" placeholder="Please enter your email address" required="required" data-error="Email address is required.") {}
228       //                div.help-block.with-errors {}
229       //              }
230       //            }
231       //          }
232       //          div.row {
233       //            div.col-md-12 {
234       //              div.form-group {
235       //                label(for="sign-in-form-password") {'Password'}
236       //                input.form-control#sign-in-form-password(type="password" name="password" required="required" placeholder="Please enter your password" data-error="Password is required.") {}
237       //                div.help-block.with-errors {}
238       //              }
239       //            }
240       //          }
241       //          input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Sign in") {}
242       //        }
243
244       //        p {
245       //          'No account yet? '
246       //          a(href="/my_account/sign_up/index.html") {'Sign up'}
247       //        }
248
249       //        p {
250       //          'Forgot password? '
251       //          a(href="/my_account/password_reset/index.html") {'Password reset'}
252       //        }
253       //      }
254       //      div.modal-footer {
255       //        button.btn.btn-primary(type="submit" form="sign-in-form") {
256       //          'Sign in'
257       //        }
258       //        button.btn.btn-default(type="button" data-dismiss="modal") {
259       //          'Cancel'
260       //        }
261       //      }
262       //    }
263       //  }
264       //}
265
266       div#feedback-modal.modal.fade(role="dialog") {
267         div.modal-dialog {
268           div.modal-content {
269             div.modal-header {
270               button.close(type="button" data-dismiss="modal") {
271                 '×'
272               }
273               h4.modal-title {
274                 'Give feedback'
275               }
276             }
277             div.modal-body {
278               p {
279                 'Did you notice something not quite right, or just want to share your impression of this page?'
280               }
281               form#feedback-form(method="post" action="/feedback.html" role="form") {
282                 div.row {
283                   div.col-md-12 {
284                     div.form-group {
285                       label(for="feedback-form-message") {'Message *'}
286                       textarea.form-control#feedback-form-message(name="message" placeholder="Please tell us your thoughts" rows="4" required="required" data-error="Please, leave us a message.") {}
287                       div.help-block.with-errors {}
288                     }
289                   }
290                 }
291                 p {} // fix this later
292                 div.row {
293                   div.col-md-12 {
294                     p.text-muted {
295                       strong {'*'}
296                       'These fields are required.'
297                       //'Contact form template by '
298                       //a(href="https://bootstrapious.com/p/how-to-build-a-working-bootstrap-feedback-form" target="_blank") {'Bootstrapious'}
299                       //'.'
300                     }
301                   }
302                 }
303                 input.btn.btn-success.btn-send(style="display: none;" type="submit" value="Send message") {}
304               }
305             }
306             div.modal-footer {
307               button.btn.btn-primary(type="submit" form="feedback-form") {
308                 'Submit'
309               }
310               button.btn.btn-default(type="button" data-dismiss="modal") {
311                 'Cancel'
312               }
313             }
314           }
315         }
316       }
317
318       div#message-modal.modal.fade(role="dialog") {
319         div.modal-dialog {
320           div.modal-content {
321             div.modal-header {
322               button.close(type="button" data-dismiss="modal") {
323                 '×'
324               }
325               h4.modal-title {
326                 'Message'
327               }
328             }
329             div.modal-body {
330               p#message-modal-message {}
331             }
332             div.modal-footer {
333               button.btn.btn-default(type="button" data-dismiss="modal") {
334                 'Close'
335               }
336             }
337           }
338         }
339       }
340     },
341     // scripts
342     async _out => {
343       //script(src="/js/sha256.js") {}
344
345       script {
346         //function get_cookie(name) {
347         //  let entries = document.cookie.split(';');
348         //  for (let i = 0; i < entries.length; ++i) {
349         //    let fields = entries[i].split('=');
350         //    if (fields[0].trim() === name)
351         //      return decodeURIComponent(fields[1]);
352         //  }
353         //  return undefined;
354         //}
355
356         //// this function can be overridden in a further script
357         //function sign_in_out(status) {
358         //}
359
360         $(document).ready(
361           () => {
362             //// sign in form
363             //$('#sign-in').click(
364             //  () => {
365             //    $('#sign-in-form-email').text('')
366             //    $('#sign-in-form-password').text('')
367             //    $('#sign-in-modal').modal('show')
368             //    return false
369             //  }
370             //)
371             //$('#sign-in-modal').on(
372             //  'shown.bs.modal',
373             //  () => {
374             //    $('#sign-in-form-email').focus()
375             //  }
376             //)
377             //// when sign in form is submitted, do not reload the page
378             //$(document).on(
379             //  'submit',
380             //  '#sign-in-form',
381             //  e => {
382             //    e.preventDefault()
383             //    $.ajax(
384             //      {
385             //        url: '/my_account/sign_in.json',
386             //        type: 'POST',
387             //        data: {
388             //          email: $('#sign-in-form-email').val(),
389             //          password: sha256(
390             //            get_cookie('session_key') +
391             //            $('#sign-in-form-password').val()
392             //          ).toString('hex')
393             //        },
394             //        success: (data, textStatus, jqXHR) => {
395             //          $('#sign-in-modal').modal('hide')
396             //          switch (data.result) {
397             //          case 1: // success
398             //            $('#signed-in-status').text(data.signed_in_status)
399             //            $('#sign-in').hide()
400             //            $('#sign-out').show()
401             //            sign_in_out(true) // notify navbar caller
402             //            break
403             //          case 2: // redirect
404             //            location.href = data.redirect_href
405             //            break
406             //          }
407             //          $('#message-modal-message').text(data.message)
408             //          $('#message-modal').modal('show')
409             //        },
410             //        error: (jqXHR, textStatus, errorThrown) => {
411             //          $('#sign-in-modal').modal('hide')
412             //          $('#message-modal-message').text(errorThrown)
413             //          $('#message-modal').modal('show')
414             //        }
415             //      }
416             //    )
417             //  }
418             //)
419
420             //// sign out button
421             //$('#sign-out').click(
422             //  () => {
423             //    $.ajax(
424             //      {
425             //        url: '/my_account/sign_out.json',
426             //        type: 'GET',
427             //        success: (data, textStatus, jqXHR) => {
428             //          if (data.result) {
429             //            $('#signed-in-status').text(data.signed_in_status)
430             //            $('#sign-in').show()
431             //            $('#sign-out').hide()
432             //            sign_in_out(false) // notify navbar caller
433             //          }
434             //          $('#message-modal-message').text(data.message)
435             //          $('#message-modal').modal('show')
436             //        },
437             //        error: (jqXHR, textStatus, errorThrown) => {
438             //          $('#message-modal-message').text(errorThrown)
439             //          $('#message-modal').modal('show')
440             //        }
441             //      }
442             //    )
443             //    return false
444             //  }
445             //)
446
447             // feedback form
448             $('#give-feedback').click(
449               () => {
450                 $('#feedback-form-message').text('')
451                 $('#feedback-modal').modal('show')
452                 return false
453               }
454             )
455             $('#feedback-modal').on(
456               'shown.bs.modal',
457               () => {
458                 $('#feedback-form-message').focus()
459               }
460             )
461             // when feedback form is submitted, do not reload the page
462             $(document).on(
463               'submit',
464               '#feedback-form',
465               e => {
466                 e.preventDefault()
467                 $.ajax(
468                   {
469                     url: '/feedback.html',
470                     type: 'POST',
471                     data: {
472                       page: window.location.href,
473                       message: $('#feedback-form-message').val()
474                     },
475                     success: (data, textStatus, jqXHR) => {
476                       $('#feedback-modal').modal('hide')
477                       $('#message-modal-message').text(data)
478                       $('#message-modal').modal('show')
479                     },
480                     error: (jqXHR, textStatus, errorThrown) => {
481                       $('#feedback-modal').modal('hide')
482                       $('#message-modal-message').text(errorThrown)
483                       $('#message-modal').modal('show')
484                     }
485                   }
486                 )
487               }
488             )
489           }
490         )
491       }
492
493       await scripts(_out)
494     }
495   )
496 }