Website: update guides category page (#21859)

Closes: #21798

Changes:
- Updated the layout and styles for the /guides page.
- Upgraded the version of DocSearch the website uses

---------

Co-authored-by: Mike Thomas <78363703+mike-j-thomas@users.noreply.github.com>
This commit is contained in:
Eric 2024-09-05 20:45:01 -05:00 committed by GitHub
parent 12094d5305
commit cb2c266774
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 302 additions and 58 deletions

View file

@ -48,6 +48,7 @@ module.exports = {
return page;
}
});
articles = _.sortBy(articles, 'meta.publishedOn');
}
let pageTitleForMeta = 'Fleet blog';
@ -107,6 +108,7 @@ module.exports = {
currentSection,
pageTitleForMeta,
pageDescriptionForMeta,
algoliaPublicKey: sails.config.custom.algoliaPublicKey,
};
}

File diff suppressed because one or more lines are too long

View file

@ -62,7 +62,22 @@ parasails.registerPage('articles', {
},
mounted: async function() {
//…
if(this.category === 'guides') {
if(this.algoliaPublicKey) {// Note: Docsearch will only be enabled if sails.config.custom.algoliaPublicKey is set. If the value is undefined, the handbook search will be disabled.
docsearch({
appId: 'NZXAYZXDGH',
apiKey: this.algoliaPublicKey,
indexName: 'fleetdm',
container: '#docsearch-query',
placeholder: 'Search',
debug: false,
clickAnalytics: true,
searchParameters: {
facetFilters: ['section:guides']
},
});
}
}
},
// ╦╔╗╔╔╦╗╔═╗╦═╗╔═╗╔═╗╔╦╗╦╔═╗╔╗╔╔═╗

View file

@ -1,6 +1,7 @@
#articles {
padding-left: 24px;
padding-right: 24px;
[purpose='page-container'] {
padding: 64px;
}
[purpose='categories-and-search'] {
padding-top: 40px;
@ -30,9 +31,15 @@
}
}
[purpose='category-title'] {
padding-top: 80px;
padding-bottom: 40px;
}
[purpose='guides-category-page'] {
[purpose='category-title'] {
margin-left: 12px;
margin-right: 6px;
}
}
[purpose='rss-button'] {
padding: 4px 8px;
cursor: pointer;
@ -49,7 +56,6 @@
font-size: 16px;
}
}
[purpose='rss-button'].copied::after {
content: 'Link copied';
display: flex;
@ -74,11 +80,100 @@
100% {opacity: 0;}
}
[purpose='search'] {
// Note: We're using classes here to override the default Docsearch styles;
button {
width: 100%;
cursor: text;
margin: 0;
}
.DocSearch-Button {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
border: 1px solid @core-fleet-black-25;
background-color: #FFF;
padding: 6px;
height: 36px;
margin: 0;
width: 256px;
}
.DocSearch-Button:hover {
box-shadow: none;
border: 1px solid @core-fleet-black-25;
color: @core-fleet-black-50;
}
.DocSearch-Search-Icon {
margin-left: 10px;
height: 16px;
width: 16px;
color: @core-fleet-black-50;
stroke-width: 3px;
}
.DocSearch-Button-Keys {
display: none;
}
.input-group:focus-within {
border: 1px solid @core-vibrant-blue;
}
.DocSearch-Button-Placeholder {
font-size: 16px;
font-weight: 400;
padding-left: 12px;
}
[purpose='disabled-search'] {
input {
padding-top: 6px;
padding-bottom: 6px;
border: none;
} &::placeholder {
font-size: 16px;
line-height: 24px;
}
.input-group {
border-top-left-radius: 6px;
border-bottom-left-radius: 6px;
border-top-right-radius: 6px;
border-bottom-right-radius: 6px;
border: 1px solid @core-fleet-black-25;
background: #FFF;
}
.input-group:focus-within {
border: 1px solid @core-vibrant-blue;
}
.docsearch-input {
height: 100%;
width: 98%;
}
.docsearch-input:focus-visible {
outline: none;
}
.ds-input:focus {
outline: rgba(0, 0, 0, 0);
}
.input-group-text {
color: @core-fleet-black-50;
}
.form-control {
height: 36px;
padding: 0px;
font-size: 16px;
} &:focus {
border: none;
}
}
}
[purpose='articles'] {
padding-bottom: 80px;
width: 100%;
max-width: 100%;
[purpose='article-card'] {
a {
text-decoration: none;
color: @core-fleet-black-75;
}
margin-left: 10px;
margin-right: 10px;
margin-bottom: 40px;
@ -123,6 +218,71 @@
}
}
}
[purpose='guides'] {
column-count: 3;
margin-left: -2px;
margin-right: 14px;
}
[purpose='guide-card'] {
&:hover {
box-shadow: 0px 4px 16px 0px #E2E4EA;
}
max-width: 343px;
margin-left: 12px;
margin-right: 12px;
margin-bottom: 24px;
border-radius: 16px;
box-shadow: none;
border: 1px solid #E2E4EA;
display: inline-block;
img {
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
a {
text-decoration: none;
color: @core-fleet-black-75;
}
[purpose='article-card-body'] {
padding: 32px;
[purpose='category-name'] {
text-transform: uppercase;
color: @core-fleet-black-50;
font-size: 12px;
font-weight: 700;
line-height: 20px;
text-decoration: none;
}
p {
color: #515774;
font-size: 14px;
font-weight: 400;
line-height: 150%;
}
[purpose='article-title'] {
display: block;
text-decoration: none;
color: @core-fleet-black;
margin-bottom: 16px;
h5 {
font-weight: 800;
font-size: 16px;
line-height: 120%;
}
}
[purpose='article-details'] {
font-size: 12px;
line-height: 28px;
span {
color: @core-fleet-black-50;
}
p {
margin-bottom: 0px;
}
}
}
}
@media (min-width: 1200px) {
@ -131,8 +291,6 @@
margin-right: 10px;
}
[purpose='articles'] {
margin-left: -25px;
margin-right: -25px;
[purpose='article-card'] {
flex: 1 1 350px;
margin-left: 20px;
@ -155,8 +313,12 @@
@media (max-width: 991px) {
padding-left: 40px;
padding-right: 40px;
[purpose='page-container'] {
padding: 64px 32px;
}
[purpose='guide-card'] {
max-width: unset;
}
[purpose='categories-and-search'] {
padding-top: 40px;
[purpose='categories'] {
@ -171,9 +333,6 @@
}
}
}
[purpose='category-title'] {
padding-top: 60px;
}
[purpose='articles'] {
[purpose='article-card'] {
flex: 1 1 330px;
@ -182,27 +341,49 @@
margin-left: -10px;
margin-right: -10px;
}
[purpose='search'] {
.DocSearch-Button {
margin-left: 24px;
width: 200px;
}
}
}
@media (max-width: 767px) {
[purpose='categories-and-search'] {
[purpose='search'] {
width: 100%;
}
}
[purpose='guides'] {
column-count: 2;
}
[purpose='articles'] {
margin: 0 auto;
column-count: 2;
[purpose='article-card'] {
max-width: 100%;
}
}
[purpose='search'] {
.DocSearch-Button {
margin-top: 0px;
margin-left: 0px;
width: 100%;
}
}
}
@media (max-width: 576px) {
padding-left: 24px;
padding-right: 24px;
[purpose='page-container'] {
padding: 32px 24px;
}
[purpose='guides'] {
column-count: 1;
}
[purpose='articles'] {
margin-left: -10px;
margin-right: -10px;
@ -211,5 +392,15 @@
max-width: 100%;
}
}
[purpose='guide-card'] {
width: 100%;
}
[purpose='search'] {
.DocSearch-Button {
margin-top: 0px;
margin-left: 0px;
width: 100%;
}
}
}
}

View file

@ -1,50 +1,87 @@
<div id="articles" v-cloak>
<div style="max-width: 1200px;" class="container-fluid p-0">
<div class="mx-auto">
<div purpose="categories-and-search" class="d-flex flex-lg-row flex-column justify-content-lg-between justify-content-md-center justify-content-start" v-if="isArticlesLandingPage">
<div purpose="categories" class="d-flex flex-lg-row flex-column justify-content-start">
<div purpose="category-filter" :class="[ filter === 'all' ? 'selected' : '']" @click="filterBy('all')">All</div>
<div purpose="category-filter" :class="[ filter === 'engineering' ? 'selected' : '']" @click="filterBy('engineering')">Engineering</div>
<div purpose="category-filter" :class="[ filter === 'security' ? 'selected' : '']" @click="filterBy('security')">Security</div>
<div purpose="category-filter" :class="[ filter === 'announcements' ? 'selected' : '']" @click="filterBy('announcements')">Announcements</div>
<div purpose="category-filter" :class="[ filter === 'guides' ? 'selected' : '']" @click="filterBy('guides')">Guides</div>
<div purpose="category-filter" :class="[ filter === 'success stories' ? 'selected' : '']" @click="filterBy('success stories')">Success stories</div>
<div purpose="category-filter" :class="[ filter === 'podcasts' ? 'selected' : '']" @click="filterBy('podcasts')">Podcasts</div>
<div purpose="category-filter" :class="[ filter === 'releases' ? 'selected' : '']" @click="filterBy('releases')">Releases</div>
<div style="max-width: 1200px;" class="container-fluid mx-auto" purpose="page-container">
<div v-if="category !== 'guides'">
<div purpose="categories-and-search" class="d-flex flex-lg-row flex-column justify-content-lg-between justify-content-md-center justify-content-start" v-if="isArticlesLandingPage">
<div purpose="categories" class="d-flex flex-lg-row flex-column justify-content-start">
<div purpose="category-filter" :class="[ filter === 'all' ? 'selected' : '']" @click="filterBy('all')">All</div>
<div purpose="category-filter" :class="[ filter === 'engineering' ? 'selected' : '']" @click="filterBy('engineering')">Engineering</div>
<div purpose="category-filter" :class="[ filter === 'security' ? 'selected' : '']" @click="filterBy('security')">Security</div>
<div purpose="category-filter" :class="[ filter === 'announcements' ? 'selected' : '']" @click="filterBy('announcements')">Announcements</div>
<div purpose="category-filter" :class="[ filter === 'guides' ? 'selected' : '']" @click="filterBy('guides')">Guides</div>
<div purpose="category-filter" :class="[ filter === 'success stories' ? 'selected' : '']" @click="filterBy('success stories')">Success stories</div>
<div purpose="category-filter" :class="[ filter === 'podcasts' ? 'selected' : '']" @click="filterBy('podcasts')">Podcasts</div>
<div purpose="category-filter" :class="[ filter === 'releases' ? 'selected' : '']" @click="filterBy('releases')">Releases</div>
</div>
</div>
<div purpose="category-title" v-else>
<h1>{{articleCategory}}</h1>
<div class="d-flex flex-sm-row flex-column justify-content-between">
<p>{{categoryDescription}}</p>
<a purpose="rss-button" class="px-0 px-sm-2 pt-sm-1" @click="clickCopyRssLink(category)" target="_blank"><span>Subscribe</span></a>
</div>
</div>
<div purpose="articles" class="card-deck d-flex justify-content-center">
<div purpose="article-card" class="card" v-for="article in selectedArticles">
<a purpose="article-card-link" :href="article.url">
<img style="width: 100%; height: auto;" :src="[article.meta.articleImageUrl ? article.meta.articleImageUrl : '/images/blog-fleet-logo-white-background-800x450@2x.png']" alt="Article hero image">
</a>
<div purpose="article-card-body" class="card-body d-flex flex-column">
<p purpose="category-name" class="pb-2 mb-0">{{article.meta.category}}</p>
<a purpose="article-title" :href="article.url"><h5>{{article.meta.articleTitle}}</h5></a>
<div purpose="article-details" class="d-flex mt-auto flex-row align-items-center">
<img alt="The author's GitHub profile picture" style="height: 32px; width: 32px; border-radius: 100%;" :src="'https://github.com/'+article.meta.authorGitHubUsername+'.png?size=200'">
<p class="pl-2 font-weight-bold">{{article.meta.authorFullName}}</p>
</div>
</div>
</div>
<div purpose="category-title" v-else>
<h1>{{articleCategory}}</h1>
<div class="d-flex flex-sm-row flex-column justify-content-between">
<p>{{categoryDescription}}</p>
<a purpose="rss-button" class="px-0 px-sm-2 pt-sm-1" @click="clickCopyRssLink(category)" target="_blank"><span>Subscribe</span></a>
</div>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
<div purpose="articles" class="card-deck d-flex justify-content-center" v-if="selectedArticles.length > 0">
<div purpose="article-card" class="card" v-for="article in selectedArticles">
<a purpose="article-card-link" :href="article.url">
<img style="width: 100%; height: auto;" :src="[article.meta.articleImageUrl ? article.meta.articleImageUrl : '/images/blog-fleet-logo-white-background-800x450@2x.png']" alt="Article hero image">
</a>
<div purpose="article-card-body" class="card-body d-flex flex-column">
<p purpose="category-name" class="pb-2 mb-0">{{article.meta.category}}</p>
<a purpose="article-title" :href="article.url"><h5>{{article.meta.articleTitle}}</h5></a>
<div purpose="article-details" class="d-flex mt-auto flex-row align-items-center">
<img alt="The author's GitHub profile picture" style="height: 32px; width: 32px; border-radius: 100%;" :src="'https://github.com/'+article.meta.authorGitHubUsername+'.png?size=200'">
<p class="pl-2 font-weight-bold">{{article.meta.authorFullName}}</p>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
</div>
</div>
<div purpose="guides-category-page" v-else>
<div purpose="category-title">
<div class="d-flex flex-md-row flex-column justify-content-between align-items-md-center">
<div class="d-flex flex-column justify-content-between">
<h1>Guides</h1>
<p>Learn more about how to use Fleet to accomplish your goals.</p>
</div>
<div purpose="search" id="docsearch-query">
<div purpose="disabled-search" class="d-flex w-100">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text border-0 bg-transparent pl-3" >
<img style="height: 16px; width: 16px;" class="search" alt="search" src="/images/icon-search-16x16@2x.png">
</span>
</div>
<div class="form-control border-0 ">
<input class="docsearch-input pr-1"
placeholder="Search" aria-label="Search"
/>
</div>
</div>
</div>
</div>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
</div>
<div v-else>
<h2 class="text-muted mx-auto">No articles to display</h2>
</div>
</div>
<div purpose="guides" class="card-columns">
<div purpose="guide-card" class="card" v-for="article in selectedArticles">
<a :href="article.url">
<div purpose="article-card-body" class="card-body d-flex flex-column">
<div purpose="article-title"><h5>{{article.meta.articleTitle}}</h5></div>
<p class="small" v-if="article.meta.description">{{article.meta.description}}</p>
<div purpose="article-details" class="d-flex mt-auto flex-row align-items-center">
<js-timestamp :at="article.meta.publishedOn" format="timeago" always-show-year="true"></js-timestamp>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>