-
Notifications
You must be signed in to change notification settings - Fork 12
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
New Theme for Zendesk Help Center #154
Open
peterdj
wants to merge
6
commits into
master
Choose a base branch
from
new_theme
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
7d2e854
Add new theme that uses InstantSearch and Autocomplete
peterdj de4aa8a
update name
peterdj dc3b32e
Add the zip file
peterdj 727fecf
Add screenshot
peterdj 88e9cdc
Updating the docs
peterdj 689075e
change to warn
peterdj File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,16 @@ In most cases, this should be enough to have an up-to-date search. | |
However, if you'd rather have it updated right now, like when you add a lot of support articles, you can manually trigger a full reindex. | ||
On this page, just click the "Reindex" button in the bottom right corner. A few minutes later, your search index will be updated. | ||
|
||
## Adding the Algolia Help Center Theme | ||
|
||
You can use the Algolia Help Center Theme. You can import the theme from the Zendesk Theme Marketplace. | ||
Also, you can download from here: https://cdn.jsdelivr.net/gh/algolia/algoliasearch-zendesk@new_theme/theme/Algolia-search/Algolia-search.zip | ||
|
||
This theme has an admin section where you update your index, keys and other settings | ||
<div align="center"> | ||
<img src="https://cdn.jsdelivr.net/gh/algolia/algoliasearch-zendesk@new_theme/theme/Algolia-search/screenshots/AdminScreen.png" alt="Admin Section" /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, won't those links break when we'll delete the branch? |
||
</div> | ||
|
||
## Updating your Help Center theme | ||
|
||
Once your data has been extracted to Algolia, you need to update your Help Center theme in order to replace the search feature by Algolia. | ||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
|
||
const setupSearch = function(appName, algoliaApiKey, index, useAutocomplete, querySuggestionIndex, useDebounce) { | ||
|
||
const searchClient = algoliasearch(appName, algoliaApiKey); | ||
|
||
// Initialize a Router | ||
// See https://www.algolia.com/doc/api-reference/widgets/history-router/js/ | ||
const historyRouter = instantsearch.routers.history(); | ||
|
||
const search = instantsearch({ | ||
indexName: index, | ||
searchClient, | ||
routing: historyRouter, | ||
}); | ||
|
||
const virtualSearchBox = instantsearch.connectors.connectSearchBox(() => {})({}); | ||
const realSearchBox = instantsearch.widgets.searchBox({ | ||
container: '#searchbox', | ||
}); | ||
const searchBox = (useAutocomplete)? virtualSearchBox : realSearchBox; | ||
|
||
const truncate = (input) => input.length > 50 ? `${input.substring(0, 50)}...` : input; | ||
|
||
|
||
search.addWidgets([ | ||
searchBox, | ||
instantsearch.widgets.hierarchicalMenu({ | ||
container: '#category-list', | ||
attributes: ['category.title', 'section.full_path'], | ||
}), | ||
instantsearch.widgets.refinementList({ | ||
container: '#section-list', | ||
attribute: 'section.title', | ||
}), | ||
instantsearch.widgets.hits({ | ||
container: '#hits', | ||
templates: { | ||
item(hit) { | ||
let createdAt = moment(hit.created_at_iso).fromNow(); | ||
let lastComment = ''; | ||
const body = truncate(hit.body_safe); | ||
const urlLabel = hit.title.replace(/[\s,\?, \!]/g,'-'); | ||
const url = '/hc/en-us/articles/' + hit.id + '-' + urlLabel; | ||
console.log(url); | ||
return `<div> | ||
<div class="hit-description">${createdAt} <span style="float:right;">${lastComment} votes ${hit.vote_sum}<span></div> | ||
<div class="hit-name"><a href="${url}" target="_blank">${hit.title}</a></div> | ||
<div class="hit-description">${body}</div> | ||
<div class="hit-description">${hit.label_names}</div> | ||
</div>`; | ||
} | ||
} | ||
}), | ||
instantsearch.widgets.pagination({ | ||
container: '#pagination', | ||
}), | ||
]); | ||
|
||
search.start(); | ||
|
||
if ( useAutocomplete ) { | ||
const settings = { | ||
articleIndex: index, | ||
querySuggestionIndex: querySuggestionIndex, | ||
useDebounce: useDebounce | ||
} | ||
setupAutocomplete(settings, searchClient, search, historyRouter); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
function setupAutocomplete(settings, searchClient, search, historyRouter) { | ||
|
||
function setInstantSearchUiState(indexUiState) { | ||
search.setUiState(uiState => ({ | ||
...uiState, | ||
[settings.articleIndex]: { | ||
...uiState[settings.articleIndex], | ||
// We reset the page when the search state changes. | ||
page: 1, | ||
...indexUiState, | ||
}, | ||
})); | ||
} | ||
|
||
// Return the InstantSearch index UI state. | ||
function getInstantSearchUiState() { | ||
const uiState = historyRouter.read() | ||
|
||
return (uiState && uiState[settings.articleIndex]) || {} | ||
} | ||
|
||
// Build URLs that InstantSearch understands. | ||
function getInstantSearchUrl(indexUiState) { | ||
return search.createURL({ [settings.articleIndex]: indexUiState }); | ||
} | ||
|
||
// Detect when an event is modified with a special key to let the browser | ||
// trigger its default behavior. | ||
function isModifierEvent(event) { | ||
const isMiddleClick = event.button === 1; | ||
|
||
return ( | ||
isMiddleClick || | ||
event.altKey || | ||
event.ctrlKey || | ||
event.metaKey || | ||
event.shiftKey | ||
); | ||
} | ||
|
||
function onSelect({ setIsOpen, setQuery, event, query }) { | ||
// You want to trigger the default browser behavior if the event is modified. | ||
if (isModifierEvent(event)) { | ||
return; | ||
} | ||
|
||
setQuery(query); | ||
setIsOpen(false); | ||
setInstantSearchUiState({ query }); | ||
} | ||
|
||
function getItemUrl({ query }) { | ||
return getInstantSearchUrl({ query }); | ||
} | ||
|
||
function createItemWrapperTemplate({ query, children, html}) { | ||
const uiState = { query }; | ||
return html`<a | ||
class="aa-ItemLink" | ||
href="${getInstantSearchUrl(uiState)}" | ||
onClick="${(event) => { | ||
if (!isModifierEvent(event)) { | ||
// Bypass the original link behavior if there's no event modifier | ||
// to set the InstantSearch UI state without reloading the page. | ||
event.preventDefault(); | ||
} | ||
}}" | ||
> | ||
${children} | ||
</a>`; | ||
} | ||
|
||
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({ | ||
key: 'instantsearch', | ||
limit: 3, | ||
transformSource({ source }) { | ||
return { | ||
...source, | ||
getItemUrl({ item }) { | ||
return getItemUrl({ | ||
query: item.label, | ||
}); | ||
}, | ||
onSelect({ setIsOpen, setQuery, item, event }) { | ||
onSelect({ | ||
setQuery, | ||
setIsOpen, | ||
event, | ||
query: item.label, | ||
}); | ||
}, | ||
// Update the default `item` template to wrap it with a link | ||
// and plug it to the InstantSearch router. | ||
templates: { | ||
...source.templates, | ||
item(params) { | ||
const { children } = source.templates.item(params).props; | ||
|
||
return createItemWrapperTemplate({ | ||
query: params.item.label, | ||
children, | ||
html: params.html, | ||
}); | ||
}, | ||
}, | ||
}; | ||
}, | ||
}); | ||
|
||
const querySuggestionsPlugin = createQuerySuggestionsPlugin({ | ||
searchClient, | ||
indexName: settings.querySuggestionIndex, | ||
getSearchParams() { | ||
// This creates a shared `hitsPerPage` value once the duplicates | ||
// between recent searches and Query Suggestions are removed. | ||
return recentSearchesPlugin.data.getAlgoliaSearchParams({ | ||
hitsPerPage: 6, | ||
}); | ||
}, | ||
transformSource({ source }) { | ||
return { | ||
...source, | ||
sourceId: 'querySuggestionsPlugin', | ||
getItemUrl({ item }) { | ||
return getItemUrl({ | ||
query: item.name, | ||
}); | ||
}, | ||
onSelect({ setIsOpen, setQuery, event, item }) { | ||
onSelect({ | ||
setQuery, | ||
setIsOpen, | ||
event, | ||
query: item.label, | ||
}); | ||
}, | ||
getItems(params) { | ||
// We don't display Query Suggestions when there's no query. | ||
if (!params.state.query) { | ||
return []; | ||
} | ||
return source.getItems(params); | ||
}, | ||
templates: { | ||
...source.templates, | ||
item(params) { | ||
const { children } = source.templates.item(params).props; | ||
return createItemWrapperTemplate({ | ||
query: params.item.name, | ||
children, | ||
html: params.html, | ||
}); | ||
}, | ||
}, | ||
}; | ||
}, | ||
}); | ||
|
||
const searchPageState = getInstantSearchUiState(); | ||
|
||
function debounce(fn, time) { | ||
let timerId = undefined | ||
|
||
return function(...args) { | ||
if (timerId) { | ||
clearTimeout(timerId) | ||
} | ||
|
||
timerId = setTimeout(() => fn(...args), time) | ||
} | ||
} | ||
|
||
const debouncedSetInstantSearchUiState = debounce(setInstantSearchUiState, 500) | ||
|
||
autocomplete({ | ||
container: '#autocomplete', | ||
placeholder: 'Search for Articles', | ||
detachedMediaQuery: 'none', | ||
openOnFocus: true, | ||
plugins: [recentSearchesPlugin,querySuggestionsPlugin], | ||
initialState: { | ||
query: searchPageState.query || '', | ||
}, | ||
onSubmit({ state }) { | ||
setInstantSearchUiState({ query: state.query }) | ||
}, | ||
onReset() { | ||
setInstantSearchUiState({ query: '' }) | ||
}, | ||
onStateChange({ prevState, state }) { | ||
if (prevState.query !== state.query) { | ||
if ( settings.useDebounce ) { | ||
debouncedSetInstantSearchUiState({ query: state.query }) | ||
} else { | ||
setInstantSearchUiState({ query: state.query }); | ||
} | ||
} | ||
}, | ||
}); | ||
} | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should have the
.zip
directly with the source code