Website: update /releases, /announcements, and /guides article category pages (#27048)

Closes: #26203 

Changes:
- Updated the article category page for release posts, announcements,
and guides to match the latest wireframes
This commit is contained in:
Eric 2025-03-13 17:52:36 -05:00 committed by GitHub
parent 6aa1626fb8
commit 7e678509be
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 121 additions and 69 deletions

View file

@ -47,8 +47,9 @@ module.exports = {
return page;
}
});
articles = _.sortBy(articles, 'meta.publishedOn');
}
// Sort articles in descending order by publish date.
articles = _.sortByOrder(articles, 'meta.publishedOn', 'DESC');
let pageTitleForMeta = 'Fleet blog';
let pageDescriptionForMeta = 'Read the latest articles written by Fleet.';

View file

@ -55,12 +55,10 @@ parasails.registerPage('articles', {
this.categoryDescription = 'Read the latest articles from the Fleet team and community.';
break;
}
// Sorting articles on the page based on their 'publishedOn' date.
this.sortArticlesByDate();
},
mounted: async function() {
if(['Articles', 'Announcements', 'Guides'].includes(this.articleCategory)) {
if(['Articles', 'Announcements', 'Guides', 'Releases'].includes(this.articleCategory)) {
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',
@ -83,32 +81,5 @@ parasails.registerPage('articles', {
// ╩╝╚╝ ╩ ╚═╝╩╚═╩ ╩╚═╝ ╩ ╩╚═╝╝╚╝╚═╝
methods: {
sortArticlesByDate: function() {
this.selectedArticles = this.articles.sort((a, b)=>{
if (a.meta['publishedOn'] > b.meta['publishedOn']) {
return -1;
}
if (b.meta['publishedOn'] > a.meta['publishedOn']){
return 1;
}
});
},
clickCopyRssLink: function(articleCategory) {
let rssButton = $('a[purpose="rss-button"]');
if(typeof navigator.clipboard !== 'undefined' && rssButton) {
// If this heading has already been clicked and still has the copied class we'll just ignore this click
if(!$(rssButton).hasClass('copied')) {
navigator.clipboard.writeText('https://fleetdm.com/rss/'+articleCategory);
// Add the copied class to the header to notify the user that the link has been copied.
$(rssButton).addClass('copied');
// Remove the copied class 5 seconds later, so we can notify the user again if they re-cick on this heading
setTimeout(()=>{$(rssButton).removeClass('copied');}, 5000);
}
} else {
window.open('https://fleetdm.com/rss/'+articleCategory, '_blank');
}
},
}
});

View file

@ -32,7 +32,6 @@
}
[purpose='category-title'] {
padding-bottom: 40px;
margin-right: 25px;
p {
margin-bottom: 0px;
}
@ -62,6 +61,8 @@
line-height: 21px;
text-decoration: none;
width: 168px;
margin-right: 8px;
height: 37px;
img {
width: 16px;
height: 16px;
@ -200,7 +201,79 @@
}
}
[purpose='article-row'] {
padding: 24px 0px;
border-bottom: 1px solid #E2E4EA;
cursor: pointer;
text-decoration: none;
color: unset;
[purpose='animated-arrow'] {
margin-left: 32px;
stroke-width: 2px;
height: 12px;
width: 12px;
fill: none;
// stroke: #FF5C83; « Note: this is overridden by the arrow-color prop;
}
[purpose='arrow-line'] {
opacity: 0;
transition: opacity 10ms ease-out;
}
[purpose='chevron'] {
transition: transform 200ms ease-out;
}
&:hover {
text-decoration: none;
[purpose='button-text'] {
color: @core-fleet-black;
}
[purpose='arrow-line'] {
opacity: 1;
transition: opacity 300ms ease-out;
}
[purpose='chevron'] {
transform: translateX(5px);
}
}
[purpose='publish-date'] {
font-size: 12px;
padding-top: 8px;
[parasails-component='js-timestamp'] {
font-size: 12px;
}
}
}
[purpose='article-link'] {
color: unset;
text-decoration: none;
&:hover {
text-decoration: none;
}
}
[purpose='article-name'] {
margin-bottom: 0px;
text-decoration: none;
color: #192147;
font-size: 16px;
font-weight: 800;
line-height: 24px;
}
[purpose='article-description'] {
color: #515774;
/* Body SM (FKA Card text) */
font-family: Inter;
font-size: 14px;
font-style: normal;
font-weight: 400;
line-height: 21px; /* 150% */
p {
margin-top: 8px;
margin-bottom: 8px;
}
}
[purpose='articles'] {
width: 100%;
max-width: 100%;
@ -356,9 +429,6 @@
[purpose='page-container'] {
padding: 64px 32px;
}
[purpose='category-title'] {
margin-right: 20px;
}
[purpose='guide-card'] {
max-width: unset;
}
@ -401,7 +471,13 @@
width: 100%;
}
}
[purpose='changelog-button'] {
margin-left: 0px;
margin-bottom: 16px;
width: 100%;
}
[purpose='category-title'] {
margin-right: 0px;
p {
margin-bottom: 16px;
}

View file

@ -1,34 +1,53 @@
<div id="articles" v-cloak>
<div style="max-width: 1200px;" class="container-fluid mx-auto" purpose="page-container">
<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">
<div class="d-flex flex-md-row flex-column justify-content-between align-items-md-end">
<div class="d-flex flex-column justify-content-between align-self-start float-left">
<h1>{{articleCategory}}</h1>
<p>{{categoryDescription}}</p>
</div>
<div purpose="search" id="docsearch-query" v-if="['Articles', 'Announcements', 'Guides'].includes(articleCategory)">
<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 purpose="search-and-releases-button" class="d-flex flex-md-row flex-column">
<div class="d-flex flex-column align-self-md-end" v-if="category === 'releases'">
<a purpose="changelog-button" href="https://github.com/fleetdm/fleet/releases" target="_blank" no-icon><img alt="GitHub logo" src="/images/logo-github-dark-24x24@2x.png"/>View changelog</a>
</div>
<div purpose="search" id="docsearch-query" v-if="['articles', 'announcements', 'guides', 'releases'].includes(category)">
<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>
<div class="d-flex flex-column align-self-md-end" v-if="articleCategory === 'Releases'">
<a purpose="changelog-button" href="https://github.com/fleetdm/fleet/releases" target="_blank" no-icon><img alt="GitHub logo" src="/images/logo-github-dark-24x24@2x.png"/>View changelog</a>
</div>
</div>
</div>
<div purpose="articles" class="card-deck d-flex justify-content-center" v-if="articleCategory !== 'Guides'">
<div purpose="article-card" class="card" v-for="article in selectedArticles">
<div purpose="article-rows" v-if="['guides', 'announcements', 'releases', 'articles'].includes(category)">
<a :href="article.url" purpose="article-row" class="d-flex flex-lg-row flex-row justify-content-between" v-for="article in articles">
<div purpose="article-name-and-description" class="d-flex flex-column">
<div class="d-flex flex-column">
<p purpose="article-name">{{article.meta.articleTitle}}</p>
</div>
<div purpose="article-description" v-if="article.meta.description"><p>{{article.meta.description}}</p></div>
<div purpose="publish-date"><js-timestamp format="billing" :at="article.meta.publishedOn"></js-timestamp></div>
</div>
<div class="d-flex flex-column justify-content-center">
<svg purpose="animated-arrow" style="stroke: #192147;" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
<path purpose="arrow-line" d="M1 6H9" stroke-width="2" stroke-linecap="round"/>
<path purpose="chevron" d="M1.35712 1L5.64283 6L1.35712 11" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</a>
</div>
<div purpose="articles" class="card-deck d-flex justify-content-center" v-else>
<div purpose="article-card" class="card" v-for="article in articles">
<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>
@ -48,21 +67,6 @@
<div purpose="article-card" class="card invisible mb-0 d-none d-sm-flex">
</div>
</div>
<div purpose="guides-category-page" v-else>
<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>