Skip to content
This repository has been archived by the owner on Dec 9, 2024. It is now read-only.

Commit

Permalink
Merge pull request #412 from B77Mills/addDirectoryCompsToMonorail
Browse files Browse the repository at this point in the history
Add directory components/reusable parts to theme monorail
  • Loading branch information
brandonbk authored Aug 23, 2022
2 parents e746b40 + 0d9a0e3 commit 03e955a
Show file tree
Hide file tree
Showing 25 changed files with 786 additions and 0 deletions.
78 changes: 78 additions & 0 deletions packages/marko-web-theme-monorail/browser/company-search.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<template>
<div ref="companySearch" class="company-search">
<autocomplete
ref="autocomplete"
:search="searchCompanies"
:class="errorClass"
placeholder="Search Companies..."
aria-label="Search Companies..."
:get-result-value="getResultValue"
:debounce-time="500"
@submit="handleSubmit"
/>
</div>
</template>

<script>
import Autocomplete from '@trevoreyre/autocomplete-vue';
const path = '/__company-search?searchQuery=';
export default {
inject: ['EventBus'],
components: { Autocomplete },
data: () => ({
errorClass: '',
}),
methods: {
// We want to display the title
getResultValue(result) {
return result.shortName;
},
// Open the selected company in a new window
handleSubmit(result) {
// Handle when the result is an error or missing context link
if (!result.siteContext || !result.siteContext.path) {
this.$refs.autocomplete.value = '';
return;
}
this.emitAction();
window.location.href = result.siteContext.path;
},
searchCompanies(input) {
this.errorClass = '';
if (input.length < 3) {
return [];
}
return this.getCompanyResults(input);
},
async getCompanyResults(input) {
try {
const url = `${path}${encodeURI(input)}`;
const res = await fetch(url);
const json = await res.json();
if (!res.ok) throw new Error(json.message || res.statusText);
return json.nodes;
} catch (error) {
const errorNodes = [{
id: 'error',
shortName: error.message,
}];
this.errorClass = 'errors';
return errorNodes;
}
},
emitAction() {
const payload = {
category: 'Content Header Search',
action: 'Click',
label: 'Website Section Page',
};
this.EventBus.$emit('content-header-search', payload);
},
},
};
</script>
8 changes: 8 additions & 0 deletions packages/marko-web-theme-monorail/browser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ const InlineNewsletterForm = () => import(/* webpackChunkName: "theme-inline-new
const MenuToggleButton = () => import(/* webpackChunkName: "theme-menu-toggle-button" */ './menu-toggle-button.vue');
const NewsletterCloseButton = () => import(/* webpackChunkName: "theme-newsletter-close-button" */ './newsletter-close-button.vue');
const NewsletterToggleButton = () => import(/* webpackChunkName: "theme-newsletter-toggle-button" */ './newsletter-toggle-button.vue');
const CompanySearch = () => import(/* webpackChunkName: "theme-company-search" */ './company-search.vue');
const SectionSearch = () => import(/* webpackChunkName: "theme-section-search" */ './section-search.vue');
const SiteNewsletterMenu = () => import(/* webpackChunkName: "theme-site-newsletter-menu" */ './site-newsletter-menu.vue');
const WufooForm = () => import(/* webpackChunkName: "theme-wufoo-form" */ './wufoo-form.vue');
const TopStoriesMenu = () => import(/* webpackChunkName: "theme-top-stories-menu" */ './top-stories-menu.vue');
Expand Down Expand Up @@ -111,6 +113,12 @@ export default (Browser, config = {
Browser.register('ThemeNewsletterToggleButton', NewsletterToggleButton, {
provide: { EventBus },
});
Browser.register('ThemeCompanySearch', CompanySearch, {
provide: { EventBus },
});
Browser.register('ThemeSectionSearch', SectionSearch, {
provide: { EventBus },
});
Browser.register('ThemeTopStoriesMenu', TopStoriesMenu);
Browser.register('WufooForm', WufooForm);
Browser.register('RevealAdHandler', RevealAdHandler);
Expand Down
89 changes: 89 additions & 0 deletions packages/marko-web-theme-monorail/browser/section-search.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<template>
<div ref="search" class="section-search" :class="{'open':openSuggestion}">
<input
v-model="selection"
class="form-control"
type="text"
placeholder="Search Categories..."
>
<div v-if="selection" class="list-group">
<div v-for="suggestion in matches" :key="suggestion" class="list-group-item">
<a :href="'/'+suggestion.alias" @click="emitAction()">
{{ suggestion.name }}
</a>
</div>
</div>
</div>
</template>

<script>
export default {
inject: ['EventBus'],
props: {
sections: {
type: Array,
required: true,
},
},
data() {
return {
open: false,
current: 0,
selection: '',
};
},
computed: {
matches() {
return this.sections.filter((section) => {
const match = section.name.toLowerCase().indexOf(this.selection.toLowerCase()) >= 0;
return match;
});
// return this.sectionNames.filter((str) => {
// const match = str.toLowerCase().indexOf(this.selection.toLowerCase()) >= 0;
// return match;
// });
},
openSuggestion() {
return this.selection !== ''
&& this.matches.length !== 0
&& this.open === true;
},
},
mounted() {
this.addListeners();
},
beforeDestroy() {
this.removeListeners();
},
methods: {
detectOutclick(event) {
const el = this.$refs.search;
if (!el.contains(event.target) && el !== event.target) {
this.selection = '';
}
},
addListeners() {
document.addEventListener('click', this.detectOutclick.bind(this));
document.addEventListener('touchstart', this.detectOutclick.bind(this));
},
removeListeners() {
document.removeEventListener('click', this.detectOutclick.bind(this));
document.removeEventListener('touchstart', this.detectOutclick.bind(this));
},
emitAction() {
const payload = {
category: 'Content Header Search',
action: 'Click',
label: 'Website Section Page',
};
this.EventBus.$emit('content-header-search', payload);
},
},
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<marko-web-browser-component name="ThemeCompanySearch" />
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
"@consent-checkboxes": "array",
"@initially-expanded": "boolean"
},
"<theme-company-search-block>": {
"template": "./company-search.marko"
},
"<theme-full-width-native-ad-block>": {
"template": "./full-width-native-ad.marko"
},
Expand Down Expand Up @@ -142,6 +145,9 @@
"<theme-section-list-block>": {
"template": "./section-list.marko"
},
"<theme-section-search-block>": {
"template": "./section-search.marko"
},
"<theme-section-title-feed-block>": {
"template": "./section-title-feed.marko",
"<query-params>": {},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import queryFragment from "../../graphql/fragments/sections-search"
import { getChildSectionsById } from "../../utils/get-child-sections-by-id";

$ const { sectionIds, includeSelf } = input;

<if(sectionIds.length)>
<marko-web-query|{ nodes: parent }|
name="website-sections"
params={ includeIds: sectionIds, queryFragment }
>
$ const nodesById = getChildSectionsById(parent[0], {}, includeSelf);
<marko-web-browser-component name="ThemeSectionSearch" props={ sections: Object.values(nodesById) } />
</marko-web-query>
</if>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
$ const { facets, title, description, aliases, initiallyExpanded, searchQuery } = input;

<if(facets.length)>
<div class='directory-facets'>
<if(title)>
<h3 class="directory-facets__title">
${title}
</h3>
</if>
<if(description)>
<div class="directory-facets__description">
$!{description}
</div>
</if>
<theme-directory-facet-list
facets=facets
aliases=aliases
active-id=input.activeId
search-query=searchQuery
initially-expanded=initiallyExpanded
/>
</div>
</if>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"<theme-directory-facet-container>": {
"template": "./facet-container.marko",
"@facets": {
"type": "array",
"required": true
},
"@title": "string",
"@description": "string",
"@content-type": "string",
"@search-query": "string",
"@initially-expanded": {
"type": "boolean",
"default-value": false
},
"@active-id": {
"type": "string",
"required": true
},
"@aliases": {
"type": "array",
"required": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { getAsArray } from "@parameter1/base-cms-object-path";

$ const block = "directory-facets";

$ const {
facets,
activeId,
aliases,
initiallyExpanded,
searchQuery
} = input;

$ const isActiveId = ({id}) => (activeId && (`${activeId}` === `${id}`));
$ facets.sort((a, b) => a.name.localeCompare(b.name));
<if(facets && facets.length)>
$ const expandedClass = (initiallyExpanded) ? `${block}__list ${block}__list--open` : `${block}__list`;
<div class=expandedClass>
<for|facet| of=facets>
$ const children = getAsArray(facet, "children.edges").map(({ node }) => node);
$ const isOpen = aliases.includes(facet.alias);
$ const isActive = isActiveId(facet);

$ const classNames = [`${block}__item`, `${block}__item--${facet.id}`];
$ const linkClasses = [`${block}__link`]
$ if (isOpen) classNames.push(`${block}__item--open`);
$ if (isActive) linkClasses.push(`${block}__link--active`);
<div class=classNames>
$ const facetLink = searchQuery ? `/${facet.alias}?searchQuery=${searchQuery}` : `/${facet.alias}`;
<a class=linkClasses href=facetLink>
${facet.name}
</a>
<if(children.length)>
<theme-menu-toggle-button
class-name=`${block}__toggle`
targets=[`.${block}__item--${facet.id}`]
toggle-class=`${block}__item--open`
initially-expanded=isOpen
icon-modifiers=["sm"]
icon-name="plus"
expanded-icon-name="dash"
/>
</if>
<if(isActive)>
<marko-web-browser-component
name="GlobalAutoScroll"
props={
containerTarget: `.${block} > .${block}__list`,
elementTarget: `.${block}__link--active`,
offset: -12,
}
/>
</if>
<theme-directory-facet-list
facets=children
active-id=activeId
aliases=aliases
search-query=searchQuery
/>
</div>
</for>
</div>
</if>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"<theme-directory-facet-list>": {
"template": "./facet-list.marko",
"@search-query": "string",
"@facets": {
"type": "array",
"required": true
},
"@active-id": {
"type": "string",
"required": true
},
"@aliases": {
"type": "array",
"required": true
},
"@initially-expanded": {
"type": "boolean",
"default-value": false
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { getAsArray } from "@parameter1/base-cms-object-path";

$ const facets = getAsArray(input, "facets");
$ const aliases = getAsArray(input, "aliases");
<theme-directory-facet-container
facets=facets
aliases=aliases
content-type=input.contentType
search-query=input.searchQuery
title=input.title
description=input.description
active-id=input.activeId
initially-expanded=input.initiallyExpanded
/>
Loading

0 comments on commit 03e955a

Please sign in to comment.