Files
fleet/website/api/controllers/articles/view-basic-article.js
T
Eric 5cefa9d5bb Website: use git to get lastModifiedAt timestamps for markdown and yaml files, show last updated date on article pages (#48918)
Changes:
- Updated the "Test Fleet website" and "Deploy Fleet website" workflows
to include the full git history when checking out the repo.
- Updated the website's build-static-content script to use git to build
lastModifiedAt timestamps for Markdown and YAML files on the website.
- Updated the article template page and article category pages to show a
timestamp of when an article's Markdown file was last changed, if it was
updated >3 days after it was published.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Articles now conditionally display an **Updated** timestamp when they
were substantially modified after publication.
* The **Updated** indicator is shown on both article listing pages and
individual article pages (including mobile/desktop headers).

* **Bug Fixes**
* Timestamp rendering is now more consistent, helping readers
distinguish original publish dates from later edits.

* **Styling**
* Added styling to support the new “updated timestamp” label and
timestamp formatting within article cards.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-09 13:18:56 -05:00

105 lines
4.0 KiB
JavaScript
Vendored

module.exports = {
friendlyName: 'View blog article',
description: 'Display "Blog article" page.',
urlWildcardSuffix: 'pageUrlSuffix',
inputs: {
pageUrlSuffix : {
description: 'The relative path to the blog article page from within this route.',
example: 'guides/deploying-fleet-on-render',
type: 'string',
defaultsTo: ''
}
},
exits: {
success: { viewTemplatePath: 'pages/articles/basic-article' },
badConfig: { responseType: 'badConfig' },
notFound: { responseType: 'notFound' },
redirect: { responseType: 'redirect' },
},
fn: async function ({pageUrlSuffix}) {
if (!_.isObject(sails.config.builtStaticContent) || !_.isArray(sails.config.builtStaticContent.markdownPages) || !sails.config.builtStaticContent.compiledPagePartialsAppPath) {
throw {badConfig: 'builtStaticContent.markdownPages'};
}
// Serve appropriate page content.
let thisPage = _.find(sails.config.builtStaticContent.markdownPages, { url: this.req.path });
if (!thisPage) {// If there's no EXACTLY matching content page, try a revised version of the URL suffix that's lowercase, with all slashes deduped, and any leading or trailing slash removed (leading slashes are only possible if this is a regex, rather than "/*" route)
let revisedPageUrlSuffix = pageUrlSuffix.toLowerCase().replace(/\/+/g, '/').replace(/^\/+/,'').replace(/\/+$/,'');
thisPage = _.find(sails.config.builtStaticContent.markdownPages, (page)=>{return _.endsWith(page.url, revisedPageUrlSuffix); });
if (thisPage) {// If we matched a page with the revised suffix, then redirect to that rather than rendering it, so the URL gets cleaned up.
throw {redirect: thisPage.url};
} else {// If no page could be found even with the revised suffix, then throw a 404 error.
throw 'notFound';
}
}
// Setting the pages meta title and description from the articles meta tags, as well as an article image, if provided.
// Note: Every article page should have a 'articleTitle' and a 'authorFullName' meta tag.
// Note: Leaving title and description as `undefined` in our view means we'll default to the generic title and description set in layout.ejs.
let pageTitleForMeta;
if(thisPage.meta.articleTitle) {
pageTitleForMeta = thisPage.meta.articleTitle;
}//fi
let pageDescriptionForMeta;
if(thisPage.meta.description){
pageDescriptionForMeta = thisPage.meta.description;
} else if(thisPage.meta.articleTitle && thisPage.meta.authorFullName) {
pageDescriptionForMeta = _.trimRight(thisPage.meta.articleTitle, '.') + ' by ' + thisPage.meta.authorFullName;
}//fi
// If an article was updated three days after it was published, we'll show the user the date when it was last updated.
let showUpdatedTimestamp = false;
let publishedAt = new Date(thisPage.meta.publishedOn).getTime();
if(publishedAt + (1000 * 60 * 60 * 24 * 3) <= thisPage.lastModifiedAt) {
showUpdatedTimestamp = true;
}
let articleCategorySlug = this.req.path.split('/')[1];
// console.log(articleCategorySlug);
let categoryFriendlyNamesByCategorySlug = {
'releases': 'Releases',
'guides': 'Guides',
'securing': 'Security articles',
'engineering': 'Engineering articles',
'announcements': 'Announcements',
'podcasts': 'Podcasts',
'report': 'Reports',
'articles': 'Blog',
};
let categoryFriendlyName = categoryFriendlyNamesByCategorySlug[articleCategorySlug];
// Respond with view.
return {
path: require('path'),
thisPage: thisPage,
showUpdatedTimestamp,
markdownPages: sails.config.builtStaticContent.markdownPages,
compiledPagePartialsAppPath: sails.config.builtStaticContent.compiledPagePartialsAppPath,
pageTitleForMeta,
pageDescriptionForMeta,
pageImageForMeta: thisPage.meta.articleImageUrl || undefined,
articleCategorySlug,
categoryFriendlyName,
currentSection: 'more',
algoliaPublicKey: sails.config.custom.algoliaPublicKey,
};
}
};