Verified Commit 13902422 authored by Jamie Maynard's avatar Jamie Maynard
Browse files

Bring notifications in to the theme from handbook

parent 43c3dfbb
Loading
Loading
Loading
Loading

.gitignore

0 → 100644
+18 −0
Original line number Diff line number Diff line
# See http://help.github.com/ignore-files/ for more about ignoring files.
#
# If you find yourself ignoring temporary files generated by your text editor
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile ~/.gitignore_global

.DS_Store
.hugo_build.lock
/.idea
/resources
/public
/node_modules

/data/public

# Ignore code quality output
markdownlint-cli2-codequality.json
/scripts/issue_log
 No newline at end of file
+77 −0
Original line number Diff line number Diff line
(function() {
    function genNotification() {
        const id = crypto.randomUUID();
        const type = document.getElementById("notificationType").value;
        const icon = (() => {
            div = document.createElement('div')
            div.innerHTML = document.getElementById("notificationIcon").value;
            return div.firstChild.classList.value;
        })();
        const title = document.getElementById("notificationTitle").value;
        const url = document.getElementById("applyToURL").value;
        const messageHTML = document.getElementById("notificationHTML").value;

        let now = new Date();
        let expiry = new Date(now.getTime() + (1*24*60*60*1000))
        if (document.getElementById("expiryDate").value != "")
            expiry = new Date(Date.parse(document.getElementById("expiryDate").value));
        const autohide = document.getElementById("autoHide").checked;
        const nowStr = now.toISOString().split('T')[0] + " " + now.toTimeString().split(" ")[0];
        const expiryStr = expiry.toISOString().split('T')[0] + " " + expiry.toTimeString().split(" ")[0];
        let n = {
            "id": id,
            "type": type,
            "icon": icon,
            "title": title,
            "url": url,
            "messageHTML": messageHTML,
            "posted": nowStr,
            "expires": expiryStr,
            "autohide": autohide
        }
        if(url === "*")
            delete n['url'];
        return n
    }

    async function getPageList() {
      let response = await fetch("/sitemap.xml");
      let data = await response.text();
      generatePageList(data);
    }

    function generatePageList(xml) {
      const siteMapDoc = parser.parseFromString(xml,"text/xml");
      const pages = siteMapDoc.getElementsByTagName("url");
      Array.prototype.slice.call(pages).forEach(e => {
        // This happens in local dev where there's no git information
        // for the current file so no lastmod element.
        page = document.createElement("option")
        loc = e.getElementsByTagName("loc")[0].textContent;
        page.value = loc.split(window.location.origin)[1];
        document.getElementById("pagesList").appendChild(page);
      });
    }

    document.getElementById("testBtn").onclick = () => {
        renderNotification(genNotification(), false);
    }
    document.getElementById('createBtn').onclick = () => {
        document.getElementsByTagName('pre')[0].textContent = JSON.stringify(genNotification(),null,2);
    }
    document.getElementById('copyBtn').onclick = () => {
        navigator.clipboard.writeText(JSON.stringify(genNotification(),null,2))
        renderNotification({
                "id": crypto.randomUUID(),
                "type": "success",
                "icon": "fa-solid fa-clipboard",
                "title": "JSON Copied to Clipboard",
                "messageHTML": "<p>The notification json has been copied to the clipboard.  Please add it to the end of the notification.json file and raise a new MR to share your notification with the world.</p>",
                "expires": new Date(),
                "autohide": true
            })
    }
    document.getElementsByTagName('pre')[0].textContent = JSON.stringify(genNotification(),null,2);
    const parser = new DOMParser();
    getPageList();
})();
+1 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ $( document ).ready(() => {
        notificationPreferences.showNotifications = false;
        setCookie("notification-preferences", JSON.stringify(notificationPreferences), 365);
        delAllNotificationCookies();
        stopNotifications();
        notifications.stop();
    }

    function formControlDisabled(disable) {
+20 −16
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ async function processNotifications() {
      upcomingNotifications.push(n);
    processedNotifications.push(n.id);
  });

  notifications.forEach(n => {
    renderNotification(n);
  })
@@ -157,8 +156,13 @@ function renderNotification(notification, withCookie=true) {
  `;
  if(withCookie) {
      toastEl.addEventListener('hidden.bs.toast', () => {
          if(document.getElementById(id+"-check") != null)
          if(document.getElementById(id+"-check") != null) {
              document.getElementById(id+"-check").checked=true;
              e = document.getElementById(id+"-markBtn");
              e.textContent = "Unread";
              e.classList.remove('btn-success');
              e.classList.add("btn-danger");
            }
          switch(type) {
              case "warning":
                  setCookie("toast-"+id, true, notificationPreferences.warningHide);
@@ -276,17 +280,17 @@ $( document ).ready(() => {
  if(notificationPreferences.showNotifications) {
    startNotifications()
  }
});

export {
  getCookie as "getCookie",
  setCookie as "setCookie",
  renderNotification as "notifications.render",
  startNotifications as "notifications.start",
  stopNotifications as "nofifications.stop",
  startPageUpdates as "notifications.startPageUpdates",
  stopPageUpdates as "notifications.stopPageUpdates",
  notificationPreferences as "notifications.preferences",
  processedNotifications as "notifications.processed",
  allToasts as "notifications.toasts"
}
  // Set gloabal scope items
  globalThis.getCookie = getCookie;
  globalThis.setCookie = setCookie;
  globalThis.notificationPreferences = notificationPreferences;
  globalThis.renderNotification = renderNotification;
  globalThis.stopNotifications = stopNotifications;
  globalThis.startNotifications = startNotifications;
  globalThis.startPageUpdates = startPageUpdates;
  globalThis.stopPageUpdates = stopPageUpdates;
  globalThis.processedNotifications = processedNotifications;
  globalThis.allToasts = allToasts;
  globalThis.notificationProcess = notificationProcess;
});
+179 −0
Original line number Diff line number Diff line
// Adapted from code by Matt Walters https://www.mattwalters.net/posts/2018-03-28-hugo-and-lunr/

(function ($) {
    'use strict';

    $(document).ready(function () {
        const $searchInput = $('.td-search__input');
        const $searchParam = 'search';
        let query = getParameterByName($searchParam)?.trim() || '';
        //
        // Options for popover
        //

        $searchInput.data('html', true);
        $searchInput.data('placement', 'bottom');
        $searchInput.data(
            'template',
            '<div class="popover td-offline-search-results" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body" style="padding: 0"></div></div>'
        );

        //
        // Register handler
        //

        $searchInput.on('change', (event) => {
            render($(event.target));

            // Hide keyboard on mobile browser
            $searchInput.blur();
        });

        // Prevent reloading page by enter key on sidebar search.
        $searchInput.closest('form').on('submit', () => {
            return false;
        });

        //
        // Lunr
        //

        let idx = null; // Lunr index
        const resultDetails = new Map(); // Will hold the data for the search results (titles and summaries)

        // Set up for an Ajax call to request the JSON data file that is created by Hugo's build process
        $.ajax($searchInput.data('offline-search-index-json-src')).then(
            (data) => {
                idx = lunr(function () {
                    this.ref('ref');

                    // If you added more searchable fields to the search index, list them here.
                    // Here you can specify searchable fields to the search index - e.g. individual toxonomies for you project
                    // With "boost" you can add weighting for specific (default weighting without boost: 1)
                    this.field('title', { boost: 5 });
                    this.field('categories', { boost: 3 });
                    this.field('tags', { boost: 3 });
                    // this.field('projects', { boost: 3 }); // example for an individual toxonomy called projects
                    this.field('description', { boost: 2 });
                    this.field('body');

                    data.forEach((doc) => {
                        this.add(doc);

                        resultDetails.set(doc.ref, {
                            title: doc.title,
                            excerpt: doc.excerpt,
                        });
                    });
                });

                if (query) {
                    $searchInput.first().val(query);
                    $searchInput.first().trigger('change');
                }
            }
        );

        const render = ($targetSearchInput) => {
            // Dispose the previous result
            $searchInput.popover('dispose');

            //
            // Search
            //

            if (idx === null) {
                return;
            }

            const searchQuery = $targetSearchInput.val();
            if (searchQuery === '') {
                return;
            }

            const results = idx
                .query((q) => {
                    const tokens = lunr.tokenizer(searchQuery.toLowerCase());
                    tokens.forEach((token) => {
                        const queryString = token.toString();
                        q.term(queryString, {
                            boost: 100,
                        });
                        q.term(queryString, {
                            wildcard:
                                lunr.Query.wildcard.LEADING |
                                lunr.Query.wildcard.TRAILING,
                            boost: 10,
                        });
                        q.term(queryString, {
                            editDistance: 2,
                        });
                    });
                })
                .slice(
                    0,
                    $targetSearchInput.data('offline-search-max-results')
                );

            //
            // Make result html
            //

            const $html = $('<div class="list-group">')
              .css({
                  maxHeight: `calc(100vh - ${
                    $targetSearchInput.offset().top -
                    $(window).scrollTop() +
                    180
                  }px)`,
                  overflowY: 'auto',
              });

            if (results.length === 0) {
                $html.append(
                    $('<div class="list-group-item">').text(`No results found for query "${searchQuery}"`)
                );
            } else {
                results.forEach((r, i) => {
                    const doc = resultDetails.get(r.ref);
                    const href =
                        $searchInput.data('offline-search-base-href') +
                        r.ref.replace(/^\//, '');

                      $html.append(`
                          <a href="${href}" tabindex="${i+1}" class="list-group-item list-group-item-action">
                              <div class="d-flex w-100 justify-content-between">
                                  <h5 class="mb-1">${doc.title}</h5>
                                  <small class="text-muted">3 days ago</small>
                              </div>
                              <p class="mb-1">${doc.excerpt}</p>
                              <small class="text-muted">${r.ref}</small>
                          </a>
                      `);
                });
            }

            // Enable inline styles in popover.
            const whiteList = $.fn.tooltip.Constructor.Default.whiteList;
            whiteList['*'].push('style', 'tabindex');

            $targetSearchInput
                .data('content', $html[0].outerHTML)
                .popover({ whiteList: whiteList })
                .popover('show');

            updateQueryParam(searchQuery);
        };

      function getParameterByName(name, url) {
          if (!url) url = window.location.href;
          return new URL(url).searchParams.get(name);
      }

      function updateQueryParam(query) {
          let url = new URL(window.location)
          url.searchParams.set($searchParam, query);
          history.pushState('', '', url.toString());
        }
    });
  })(jQuery);
Loading