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