diff --git a/static/js/cookie-consent-listener.js b/static/js/cookie-consent-listener.js index 25ccaca..afa446c 100644 --- a/static/js/cookie-consent-listener.js +++ b/static/js/cookie-consent-listener.js @@ -1,6 +1,5 @@ let gaInitialized = false; document.addEventListener('cookieconsent_allowed', () => { - console.log('allowed'); if (gaInitialized === true) return; const script = document.createElement('script'); script.src = 'https://www.googletagmanager.com/gtag/js?id=G-TW89K2P8L4'; diff --git a/static/js/cookie-consent.js b/static/js/cookie-consent.js index 866b2fe..65ddb59 100644 --- a/static/js/cookie-consent.js +++ b/static/js/cookie-consent.js @@ -31,10 +31,10 @@ const cookieConsent = (function () { View our cookie policy @@ -49,6 +49,8 @@ const cookieConsent = (function () { const wrapper = document.createElement("div"); wrapper.innerHTML = modalHTML; document.body.appendChild(wrapper) + document.getElementById('cookie-decline').addEventListener('click', cookieConsent.deny); + document.getElementById('cookie-allow').addEventListener('click', cookieConsent.allow); } diff --git a/static/js/main.js b/static/js/main.js index e0012e4..12b17ba 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -1,5 +1,5 @@ document.querySelectorAll('[data-modal]').forEach(item => { - item.onclick = () => { + item.addEventListener('click', () => { const modal = document.getElementById(item.dataset.modal); modal.style.display = 'block'; modal.querySelector('.btn-primary').focus(); @@ -8,22 +8,23 @@ document.querySelectorAll('[data-modal]').forEach(item => { dc.classList.add('close'); setTimeout(() => dc.classList.remove('close'), 100); } - } + }) }) -window.onclick = e => { - if (e.target.classList.contains('modal')) { - e.target.style.display = "none"; +window.addEventListener('click', (e)=>{ + const {target} = e; + if (target.classList.contains('modal')) { + target.style.display = "none"; } - if (!e.target.closest('.dropdown-select') || e.target.parentElement.classList.contains('dropdown-select_options')) { + if (!target.closest('.dropdown-select') || target.parentElement.classList.contains('dropdown-select_options')) { document.querySelectorAll('.dropdown-select').forEach(item => item.classList.remove('opened')) } -} +}) -document.querySelectorAll('.dropdown-select span').forEach(item => item.onclick = () => { +document.querySelectorAll('.dropdown-select span').forEach(item => item.addEventListener('click', () => { item.closest('.dropdown-select').classList.toggle('opened') -}); +})); const versionsDropdown = document.querySelector('.dropdown-select.versions'); if (versionsDropdown) { @@ -39,7 +40,6 @@ document.onkeyup = e => { } } -const closeModal = (el) => el.closest('.modal').style.display = 'none'; const fakeLogin = (el) => { el.style.display = 'none'; @@ -47,32 +47,34 @@ const fakeLogin = (el) => { } document.querySelectorAll('.tabs div[data-tab]').forEach(item => { - item.onclick = function () { + item.addEventListener('click', () => { document.querySelector('div[data-tab].active').classList.remove('active'); item.classList.add('active'); document.querySelector('.tabs-content.opened').classList.remove('opened'); document.getElementById(`tab${item.dataset.tab}`).classList.add('opened'); - } + }) }) const collapse = document.querySelector('.collapse'); const dropDownHandler = function (element) { - const openedClass = "opened"; - document.querySelector('li.dropdown.opened').classList.remove('opened'); - const li = element.closest('li'); - if (li.className.indexOf(openedClass) == -1) { - li.className += ` ${openedClass}`; - } else { - li.className = li.className.replace(` ${openedClass}`, ""); + document.querySelectorAll('.dropdown-item-onclick.opened').forEach((el)=> el !== element && el.classList.toggle('opened') ); + + if(window.matchMedia("(pointer: coarse)").matches) { + element.classList.toggle('opened'); } } +document.querySelectorAll('.dropdown-item-onclick').forEach(element=>{ + element.addEventListener('click', (e)=>dropDownHandler(e.target)); +}) -const openMenuHandler = function (collapseMenu) { +const openMenuHandler = function () { + const collapseMenu = document.getElementById('openMenuToggle'); const menu = document.querySelector('.main-menu .links'); const openedClass = "opened"; + document.querySelectorAll('.dropdown-item-onclick.opened').forEach((element)=>element.classList.toggle('opened')); if (collapseMenu.className.indexOf(openedClass) == -1) { collapseMenu.className += ` ${openedClass}`; menu.className += ` d-b`; @@ -81,6 +83,7 @@ const openMenuHandler = function (collapseMenu) { menu.className = menu.className.replace(` d-b`, ""); } } +document.getElementById('openMenuToggle').addEventListener('click', () => openMenuHandler()); const allTags = el => { const tags = document.querySelector('.modules-right-tags_list'); @@ -92,6 +95,10 @@ const allTags = el => { tags.classList.add('opened'); } } +const allTagsElement = document.getElementById('all-tags'); +allTagsElement?.addEventListener('click',(e)=>{ + allTags(e.target); +}) let tm; const cl = document.querySelector('.copy-link.bi-link-45deg'); @@ -126,3 +133,15 @@ String.prototype.capitalize = function() { // remove all chars except alphanumeric, spaces and . , _ - const sanitizeString = str => str !== null ? str.replace(/[^a-z0-9\.\s,_-]/gim,"") : null; +const publishModalElement = document.querySelector('[data-modal="publishModal"]'); +publishModalElement.addEventListener('click', ()=>{ + const closeModal = (el) => el.closest('.modal').style.display = 'none'; + document.querySelectorAll('.close-modal-click').forEach(element => { + element.addEventListener('click', e=> closeModal(e.target)); + }) + document.querySelectorAll('.opened').forEach(element=>element.classList.toggle('opened')) + const menu = document.querySelector('.links.d-b'); + if (menu){ + menu.classList.toggle('d-b'); + } +}) \ No newline at end of file diff --git a/static/js/modules-list.js b/static/js/modules-list.js index 34ce8af..c171933 100644 --- a/static/js/modules-list.js +++ b/static/js/modules-list.js @@ -9,7 +9,25 @@ const sortOptions = { }; let sort = sortOptions.alphabetic; +const modulesList = function (query, tags = []) { + let ids = []; + modules = []; + if (query.length > 0) { + flexSearchIndex.search(query).forEach(item => ids.push(...item.result)); + [...new Set(ids)].map(key => { + modules.push(pagesIndex[key]) + }); + } else { + modules = Object.keys(pagesIndex).map(key => pagesIndex[key]); + } + if (tags.length > 0) { + // if we merge module tags and tags from the filter and unique array length will be the same as module tags length, + // then all filtered tags intersect with module tags + modules = modules.filter(item => [...new Set([...item.tags, ...tags])].length == (item.tags.length )) + } + return modules; +} // if sorting is selected from the dropdown then do not change it automatically const changeDefaultSorting = newSortOption => (getSearchParam('sort') == null) && (sort = newSortOption) @@ -76,18 +94,32 @@ const orderChanged = (e) => { document.querySelectorAll('.sort-by .dropdown-select_options div').forEach(item => item.addEventListener('click', orderChanged)) +const createTagElement = (tag, remove = false)=>{ + const li = document.createElement('li'); + const a = document.createElement('a'); + a.textContent = tag; + a.addEventListener('click',()=>remove ? removeTag(tag) : selectTag(tag)); + li.appendChild(a); + if (remove){ + const i = document.createElement('i'); + i.className = 'bi bi-x'; + li.appendChild(i); + } + return li; +} + document.addEventListener('TAGS_LOADED', function (e) { const selectedTags = getTags(); - let tagsHtml = ''; - tags.forEach(tag => tagsHtml += tag == 'Supported' ? '' : `
  • ${sanitizeString(tag)}
  • `); - document.querySelector('ul.tags').innerHTML = tagsHtml; - if (selectedTags.length) { - document.querySelector('.modules-applied-tags').style.display = 'block'; + const tagElements = [...tags].map(tag => tag === 'Supported' ? null : createTagElement(sanitizeString(tag))).filter(Boolean); + document.querySelector('ul.tags').append(...tagElements); + const appliedTagsElement = document.querySelector('.modules-applied-tags') + if (appliedTagsElement && selectedTags.length) { + appliedTagsElement.style.display = 'block'; searchParts.tags.push(...selectedTags); document.dispatchEvent(new Event('RENDER')) - document.querySelector('.modules-applied-tags ul').innerHTML = selectedTags.map(item => `
  • ${sanitizeString(item)}
  • `).join(''); - } else { - document.querySelector('.modules-applied-tags').style.display = 'none'; + document.querySelector('.modules-applied-tags ul').append(...selectedTags.map(item => createTagElement(sanitizeString(item, true)))); + } else if (appliedTagsElement) { + appliedTagsElement.style.display = 'none'; } }) @@ -145,6 +177,9 @@ const selectTag = function (tag) { tags.forEach(item => searchParams.append('tag', item)) location.search = searchParams.toString(); } +document.getElementById('supported-tag').addEventListener('click',(e)=>{ + selectTag('supported'); +}) const removeTag = function (tag) { const searchParams = new URLSearchParams(location.search); @@ -161,77 +196,115 @@ const removeAllTags = function () { searchParams.delete('tag') location.search = searchParams.toString(); } +document.getElementById('removeAllTags').addEventListener('click', removeAllTags) const getTags = () => (new URLSearchParams(location.search)).getAll('tag'); -const modulesList = function (query, tags = []) { - let ids = []; - modules = []; - if (query.length > 0) { - flexSearchIndex.search(query).forEach(item => ids.push(...item.result)); - [...new Set(ids)].map(key => { - modules.push(pagesIndex[key]) - }); - } else { - modules = Object.keys(pagesIndex).map(key => pagesIndex[key]); - } - if (tags.length > 0) { - // if we merge module tags and tags from the filter and unique array length will be the same as module tags length, - // then all filtered tags intersect with module tags - modules = modules.filter(item => [...new Set([...item.tags, ...tags])].length == (item.tags.length )) - } - return modules; -} function renderModules(results) { pagination.maxPage = Math.ceil(modules.length / pagination.perPage); - resultsWrapper.innerHTML = ''; - document.querySelectorAll('.pagesCount').forEach(item => item.innerHTML = modules.length); + resultsWrapper.replaceChildren(); + document.querySelectorAll('.pagesCount').forEach(item => item.textContent = modules.length); initPaginationHtml(); if (!results.length || !resultsWrapper) { return; } - resultsWrapper.innerHTML = ''; + resultsWrapper.replaceChildren(); let modulesHTML = ''; - results.forEach(function (result) { - modulesHTML += ` -
    -
    -
    -
    -
    -
    - -
    -
    - ${result.title} -
    by ${result.author.name}
    -
    -
    -
    -

    - ${result.description} -

    -
    -
      - ${result.tags.map(tag => `
    • - ${tag} -
    • `).join('')} -
    -
    -
    -
    -
    ${result.version ? 'Version: ' + result.version : ''}
    -
    Updated: ${result.updated}
    -
    Total downloads: ${result.downloads}
    -
    -
    -
    ` + results.forEach(function(result) { + const article = document.createElement('article'); + article.className = 'modules-item'; + + const flexDiv = document.createElement('div'); + flexDiv.className = 'flex flex-space-between'; + + const leftDiv = document.createElement('div'); + + const itemNameDiv = document.createElement('div'); + itemNameDiv.className = 'modules-item_name flex-grow'; + + const flexAlignDiv = document.createElement('div'); + flexAlignDiv.className = 'flex flex--align_center'; + + const avatarDiv = document.createElement('div'); + avatarDiv.className = 'modules-item_avatar'; + + const avatarImg = document.createElement('img'); + avatarImg.width = 32; + avatarImg.height = 32; + avatarImg.src = result.author.image; + avatarDiv.appendChild(avatarImg); + + const infoDiv = document.createElement('div'); + + const titleLink = document.createElement('a'); + titleLink.href = result.href; + titleLink.className = 'modules-item_title'; + titleLink.textContent = result.title; + + const authorDiv = document.createElement('div'); + authorDiv.className = 'modules-item_author'; + authorDiv.textContent = `by ${result.author.name}`; + + infoDiv.appendChild(titleLink); + infoDiv.appendChild(authorDiv); + + flexAlignDiv.appendChild(avatarDiv); + flexAlignDiv.appendChild(infoDiv); + itemNameDiv.appendChild(flexAlignDiv); + + const descriptionP = document.createElement('p'); + descriptionP.className = 'modules-item_description'; + descriptionP.textContent = result.description; + + const tagsDiv = document.createElement('div'); + tagsDiv.className = 'modules-item_tags tags'; + + const tagsUl = document.createElement('ul'); + result.tags.forEach(tag => { + const tagLi = document.createElement('li'); + tagLi.className = tag.toLowerCase(); + + const tagA = document.createElement('a'); + tagA.href = '#'; + tagA.addEventListener('click', ()=> selectTag(tag)); + tagA.textContent = tag; + tagLi.appendChild(tagA); + tagsUl.appendChild(tagLi); + }); + tagsDiv.appendChild(tagsUl); + + leftDiv.appendChild(itemNameDiv); + leftDiv.appendChild(descriptionP); + leftDiv.appendChild(tagsDiv); + + const rightDiv = document.createElement('div'); + rightDiv.className = 'right-info'; + + if (result.version) { + const versionDiv = document.createElement('div'); + versionDiv.textContent = `Version: ${result.version}`; + rightDiv.appendChild(versionDiv); + } + + const updatedDiv = document.createElement('div'); + updatedDiv.textContent = `Updated: ${result.updated}`; + rightDiv.appendChild(updatedDiv); + + const downloadsDiv = document.createElement('div'); + downloadsDiv.textContent = `Total downloads: ${result.downloads}`; + rightDiv.appendChild(downloadsDiv); + + flexDiv.appendChild(leftDiv); + flexDiv.appendChild(rightDiv); + + article.appendChild(flexDiv); + + resultsWrapper.appendChild(article); }); - resultsWrapper.innerHTML = modulesHTML; } const paginate = (items, perPage, page) => items.slice((page - 1) * perPage, page * perPage); @@ -324,5 +397,5 @@ const initPaginationHtml = () => { sortBy.querySelector('span > div').innerText = sort.capitalize().replace('-', ' '); } - perPageDropdown.querySelector('span > div').innerHTML = pagination.perPage; + perPageDropdown.querySelector('span > div').textContent = pagination.perPage; } diff --git a/themes/cfbs-theme/layouts/partials/list.html b/themes/cfbs-theme/layouts/partials/list.html index 03b413b..13bfb6e 100644 --- a/themes/cfbs-theme/layouts/partials/list.html +++ b/themes/cfbs-theme/layouts/partials/list.html @@ -26,7 +26,7 @@

    Applied tags

    - Clear all + Clear all
    @@ -56,12 +56,12 @@

    Applied tags

    Tags

    - +
    Modules that are supported and tested by CFEngine.
      diff --git a/themes/cfbs-theme/layouts/partials/nav.html b/themes/cfbs-theme/layouts/partials/nav.html index f0a7b93..a16c87e 100644 --- a/themes/cfbs-theme/layouts/partials/nav.html +++ b/themes/cfbs-theme/layouts/partials/nav.html @@ -13,7 +13,7 @@ -
      - - +
      + +
      diff --git a/themes/cfbs-theme/layouts/partials/publishModule.html b/themes/cfbs-theme/layouts/partials/publishModule.html index 9830b0e..9a38919 100644 --- a/themes/cfbs-theme/layouts/partials/publishModule.html +++ b/themes/cfbs-theme/layouts/partials/publishModule.html @@ -2,14 +2,15 @@
    + diff --git a/themes/cfbs-theme/styles/less/header.less b/themes/cfbs-theme/styles/less/header.less index 9fbfcc0..547d833 100644 --- a/themes/cfbs-theme/styles/less/header.less +++ b/themes/cfbs-theme/styles/less/header.less @@ -125,15 +125,16 @@ header { svg { vertical-align: middle; } - - > ul > li > a { - &:hover { - color: @orange; - } - @media @tablet-down { - &:focus { + @media (hover: hover){ + > ul > li > a { + &:hover { color: @orange; } + @media @tablet-down { + &:focus { + color: @orange; + } + } } } @@ -251,8 +252,7 @@ header { font-weight: bold; font-size: 1.6rem; line-height: 2rem; - padding-left: 2.5rem; - margin: 1.6rem 0; + padding: 1.6rem 0 1.6rem 2.5rem; } } @@ -279,6 +279,8 @@ header { font-size: 14px; line-height: 16px; color: @MainMenuTextColor; + padding: 0 0 0 2.5rem; + margin: 1.6rem 0; } } } @@ -460,38 +462,48 @@ header { margin-left: 1rem; vertical-align: sub; } - - &:hover &-content { - height: auto; - min-width: 16rem; - width: max-content; - overflow: visible; - } - - @media screen and @tablet-down { - &:focus &-content, &:focus-within &-content{ + @media (hover: hover) { + &:hover &-content { height: auto; min-width: 16rem; width: max-content; overflow: visible; } } - - &:hover { - > a { - color: @orange; - } - + &-item-onclick.opened{ + color: @orange; i.bi-chevron-down { transform: rotate(180deg); color: @orange; } + } + &-item-onclick.opened ~ i.bi-chevron-down{ + transform: rotate(180deg); + color: @orange; + } + &-item-onclick.opened ~ &-content { + height: auto; + min-width: 16rem; + width: max-content; + overflow: visible; + } + @media (hover: hover) { + &:hover { + > a { + color: @orange; + } + + i.bi-chevron-down { + transform: rotate(180deg); + color: @orange; + } - div.close { - height: 0; - width: 0; - min-width: 0; - overflow: hidden; + div.close { + height: 0; + width: 0; + min-width: 0; + overflow: hidden; + } } } } \ No newline at end of file diff --git a/themes/cfbs-theme/styles/less/modulePage.less b/themes/cfbs-theme/styles/less/modulePage.less index d0553d1..ea38db7 100644 --- a/themes/cfbs-theme/styles/less/modulePage.less +++ b/themes/cfbs-theme/styles/less/modulePage.less @@ -34,7 +34,7 @@ .module-desc { grid-area: description; } @media @phone-down { - padding-top: 9.2rem; + margin-top: 9.2rem; } .breadcrumbs { diff --git a/themes/cfbs-theme/styles/less/modules.less b/themes/cfbs-theme/styles/less/modules.less index b7e6f0a..e552949 100644 --- a/themes/cfbs-theme/styles/less/modules.less +++ b/themes/cfbs-theme/styles/less/modules.less @@ -14,7 +14,7 @@ } @media @phone-down { - padding-top: 9.2rem; + margin-top: 9.2rem; } @media @phone-down { @@ -73,6 +73,7 @@ a, i { color: @gray-400; text-decoration: none; + cursor: pointer; } a { line-height: 2rem;