Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MWPW-166134] MMM: added last seen manifest search #3540

Open
wants to merge 4 commits into
base: stage
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 63 additions & 15 deletions libs/blocks/mmm/mmm.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ import { getMepPopup, API_URLS } from '../../features/personalization/preview.js
const SEARCH_CRITERIA_CHANGE_EVENT = 'mmm-search-change';
let cachedSearchCriteria = '';
export const DEBOUNCE_TIME = 800;
const SEARCH_CONTAINER = '.mmm-search-container';
const LAST_SEEN_OPTIONS = {
day: { value: 'Day', key: 'day' },
week: { value: 'Week', key: 'week' },
month: { value: 'Month', key: 'month' },
threeMonths: { value: '3 Months', key: 'threeMonths' },
sixMonths: { value: '6 Months', key: 'sixMonths' },
year: { value: 'Year', key: 'year' },
all: { value: 'All', key: 'all' },
};
const SEARCH_INITIAL_VALUES = {
lastSeenManifest: LAST_SEEN_OPTIONS.threeMonths.key,
pageNum: 1,
};

async function toggleDrawer(target, dd, pageId) {
const el = target.closest('button');
Expand Down Expand Up @@ -72,12 +86,18 @@ function createButtonDetailsPair(mmmEl, page) {
mmmEl.append(dt, dd);
}

/**
* This function should be fired by any search criteria field change event
* Or by page number change event
* @param {Number} pageNum - optional. Number of the clicked page.
* @param {Event} event - optional. Page number click Event object.
*/
function filterPageList(pageNum, event) {
const shareUrl = new URL(`${window.location.origin}${window.location.pathname}`);
const searchValues = {};
const activeSearchWithShortKeyword = event?.target?.value && event.target.value.length < 2;

document.querySelector('.mmm-search-container').querySelectorAll('input, select').forEach((field) => {
document.querySelector(SEARCH_CONTAINER).querySelectorAll('input, select').forEach((field) => {
const id = field.getAttribute('id').split('-').pop();
const { value, tagName } = field;
searchValues[id] = {
Expand All @@ -91,16 +111,14 @@ function filterPageList(pageNum, event) {
shareUrl.searchParams.set('pageNum', pageNum || 1);
searchValues.pageNum = { value: pageNum || 1, tagName: 'A' };

// This event triggers an API call with beloww search criterias and a re-render
// assemble event details object with all filter criterias
const detail = {};
Object.keys(searchValues).forEach((key) => {
detail[key] = searchValues[key].value;
});
// This event triggers an API call with most recent search criteria and a forces a re-render
if (!activeSearchWithShortKeyword) {
document.dispatchEvent(new CustomEvent(SEARCH_CRITERIA_CHANGE_EVENT, {
detail: {
urls: searchValues.urls?.value,
geos: searchValues.geos?.value,
pages: searchValues.pages?.value,
pageNum: searchValues.pageNum?.value,
},
}));
document.dispatchEvent(new CustomEvent(SEARCH_CRITERIA_CHANGE_EVENT, { detail }));
}

document.querySelectorAll('button.copy-to-clipboard').forEach((button) => {
Expand Down Expand Up @@ -168,7 +186,7 @@ function createShareButton() {
}

function createDropdowns(data, sharedUrlSettings) {
const searchContainer = document.querySelector('.mmm-search-container');
const searchContainer = document.querySelector(SEARCH_CONTAINER);
const dropdownForm = createTag(
'div',
{ id: 'mmm-dropdown-container', class: 'mmm-form-container' },
Expand Down Expand Up @@ -204,7 +222,7 @@ function debounce(func) {
}

function createSearchField(data, sharedUrlSettings) {
const searchContainer = document.querySelector('.mmm-search-container');
const searchContainer = document.querySelector(SEARCH_CONTAINER);
const searchForm = createTag(
'div',
{ id: 'mmm-search-urls-container', class: 'mmm-form-container' },
Expand All @@ -221,13 +239,38 @@ function createSearchField(data, sharedUrlSettings) {
searchField.addEventListener('change', debounce((event) => filterPageList(null, event)));
}

function isSelectedLastSeenDropdownOption(key) {
const searchKey = new URL(window.location.href).searchParams.get('lastSeenManifest');
if (searchKey) return searchKey === key;
return LAST_SEEN_OPTIONS[key].key === SEARCH_INITIAL_VALUES.lastSeenManifest;
}

function createLastSeenManifestDD() {
const searchContainer = document.querySelector(SEARCH_CONTAINER);
const dd = createTag(
'div',
{ id: 'mmm-dropdown-lastSeenManifest', class: 'mmm-form-container' },
`<div>
<label for="mmm-lastSeenManifest">Manifests seen in the last:</label>
<select id="mmm-lastSeenManifest" type="text" name="mmm-lastSeenManifest" class="text-field-input">
${Object.keys(LAST_SEEN_OPTIONS).map((key) => `
<option value="${LAST_SEEN_OPTIONS[key].key}" ${isSelectedLastSeenDropdownOption(LAST_SEEN_OPTIONS[key].key) ? 'selected' : ''}>${LAST_SEEN_OPTIONS[key].value}</option>
`)}
</select>
</div>`,
);
dd.addEventListener('change', () => filterPageList());
searchContainer.append(dd);
}

async function createForm(el) {
const data = parseData(el);
const urlParams = new URLSearchParams(window.location.search);
const sharedUrlSettings = Object.fromEntries(urlParams.entries());
const searchContainer = createTag('div', { class: 'mmm-search-container' });
const searchContainer = createTag('div', { class: SEARCH_CONTAINER.slice(1) });
document.querySelector('.mmm-container').parentNode.prepend(searchContainer);
createDropdowns(data, sharedUrlSettings);
createLastSeenManifestDD();
createSearchField(data, sharedUrlSettings);
}

Expand Down Expand Up @@ -300,12 +343,12 @@ async function createPageList(el, search) {
role: 'presentation',
});
mmmElContainer.append(mmmEl);
const url = `${API_URLS.pageList}${search ? getSearchParams(search) : window.location.search || '?pageNum=1'}`;
const url = `${API_URLS.pageList}${getSearchParams(search ?? SEARCH_INITIAL_VALUES)}`;
const response = await fetchData(
url,
DATA_TYPE.JSON,
);
response.result.map((page) => createButtonDetailsPair(mmmEl, page));
response.result?.map((page) => createButtonDetailsPair(mmmEl, page));
const section = createTag('div', { id: 'mep-section', class: 'section' });
const main = document.querySelector('main');
el.replaceWith(mmmElContainer);
Expand All @@ -318,6 +361,11 @@ async function createPageList(el, search) {
handlePaginationClicks();
}

/**
* This function creates a listener to search criteria changes
* and will fires an API call when event is received.
* The search criteria change event is fired inside filterPageList()
*/
function subscribeToSearchCriteriaChanges() {
document.addEventListener(SEARCH_CRITERIA_CHANGE_EVENT, (el) => {
const searchCriteria = JSON.stringify(el?.detail || {});
Expand Down
10 changes: 7 additions & 3 deletions test/blocks/mmm/mmm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,9 @@ describe('MMM', () => {
expect(copyButton.dataset.destination).to.include('geos');
expect(copyButton.dataset.destination).to.not.include('pages');
expect(copyButton.dataset.destination).to.not.include('urls');

const pageDropdown = document.querySelector('#mmm-dropdown-pages');
expect(pageDropdown).to.exist;

pageDropdown.options[2].selected = true;
pageDropdown.dispatchEvent(event);
expect(copyButton.dataset.destination).to.include('geos');
Expand All @@ -177,12 +177,16 @@ describe('MMM', () => {
expect(copyButton.dataset.destination).to.include('pages');
expect(copyButton.dataset.destination).to.not.include('urls');

const lastSeenManifestDropdown = document.querySelector('#mmm-lastSeenManifest');
lastSeenManifestDropdown.options[0].selected = true;
lastSeenManifestDropdown.dispatchEvent(event);
expect(copyButton.dataset.destination).to.include('lastSeenManifest');

const mmmSearchQuery = document.querySelector('#mmm-search-urls');
expect(mmmSearchQuery).to.exist;
mmmSearchQuery.value = 'pricing';
mmmSearchQuery.dispatchEvent(event);
// await debounce time
await delay(DEBOUNCE_TIME + 1);
await delay(DEBOUNCE_TIME + 1); // await debounce time
expect(copyButton.dataset.destination).to.not.include('geos');
expect(copyButton.dataset.destination).to.include('pages');
expect(copyButton.dataset.destination).to.include('urls');
Expand Down
Loading