'use strict';
const { TemplateHelper } = require('@squeep/html-template-helper');
-
+const { Message } = require('../enum');
/**
* Render a topic as a row of details.
- * @param {Object} topic
- * @param {Object[]} subscribers
- * @param {Boolean} detailsLink
- * @returns {String}
+ * @param {object} topic topic
+ * @param {object[]} subscribers subscribers
+ * @param {boolean} detailsLink link to details
+ * @returns {string} html
*/
function renderTopicRow(topic, subscribers, detailsLink = true) {
if (!topic) {
return `<tr>
<th scope="row">${detailsLink ? '<a href="topic/' + topic.id + '">' : ''}${topic.url}${detailsLink ? '</a>' : ''}</th>
<td>${subscribers.length}</td>
- <td>${TemplateHelper.dateOrNot(topic.created, 'Unknown')}</td>
+ <td>${TemplateHelper.dateFormat(topic.created, Message.EndOfTime, Message.BeginningOfTime, Message.Unknown)}</td>
<td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsPreferred)}</td>
<td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsMin)}</td>
<td>${TemplateHelper.secondsToPeriod(topic.leaseSecondsMax)}</td>
<td>${topic.publisherValidationUrl ? topic.publisherValidationUrl : 'None'}</td>
<td>${topic.isActive}</td>
<td>${topic.isDeleted}</td>
- <td>${TemplateHelper.dateOrNot(topic.lastPublish, 'Never')}</td>
- <td>${TemplateHelper.dateOrNot(topic.contentFetchNextAttempt, 'Next Publish')}</td>
+ <td>${TemplateHelper.dateFormat(topic.lastPublish, Message.EndOfTime, Message.Never, Message.Never)}</td>
+ <td>${TemplateHelper.dateFormat(topic.contentFetchNextAttempt, Message.NextPublish, Message.Pending, Message.NextPublish)}</td>
<td>${topic.contentFetchAttemptsSinceSuccess}</td>
- <td>${TemplateHelper.dateOrNot(topic.contentUpdated, 'Never')}</td>
+ <td>${TemplateHelper.dateFormat(topic.contentUpdated, Message.EndOfTime, Message.Never, Message.Never)}</td>
<td>${topic.contentType}</td>
<td>${topic.id}</td>
</tr>`;
/**
* Render the header row for topic details.
- * @returns {String}
+ * @returns {string} html
*/
function renderTopicRowHeader() {
return `<tr>
<th scope="col">Content Fetch Failures</th>
<th scope="col">Content Updated</th>
<th scope="col">Content Type</th>
- <th scope="col">ID</th>
+ <th scope="col">Internal Id</th>
</tr>`;
}
/**
* Render a subscription as a row of details.
- * @param {Object} subscription
- * @returns {String}
+ * @param {object} subscription subscription
+ * @returns {string} html
*/
function renderSubscriptionRow(subscription) {
if (!subscription) {
</tr>`;
}
return `<tr>
- <td scope="row">${subscription.callback}</td>
- <td>${TemplateHelper.dateOrNot(subscription.created, 'Unknown')}</td>
- <td>${TemplateHelper.dateOrNot(subscription.verified, 'Never')}</td>
- <td>${TemplateHelper.dateOrNot(subscription.expires, 'Never')}</td>
+ <td>${subscription.callback}</td>
+ <td>${TemplateHelper.dateFormat(subscription.created, Message.EndOfTime, Message.BeginningOfTime, Message.Unknown)}</td>
+ <td>${TemplateHelper.dateFormat(subscription.verified, Message.EndOfTime, Message.Never, Message.Never)}</td>
+ <td>${TemplateHelper.dateFormat(subscription.expires, Message.Never, Message.BeginningOfTime, Message.Never)}</td>
<td>${!!subscription.secret}</td>
<td>${subscription.signatureAlgorithm}</td>
<td>${subscription.httpRemoteAddr}</td>
<td>${subscription.httpFrom}</td>
- <td>${TemplateHelper.dateOrNot(subscription.contentDelivered, 'Never')}</td>
+ <td>${TemplateHelper.dateFormat(subscription.contentDelivered, Message.EndOfTime, Message.Never, Message.Never)}</td>
<td>${subscription.deliveryAttemptsSinceSuccess}</td>
- <td>${TemplateHelper.dateOrNot(subscription.deliveryNextAttempt, 'Next Publish')}</td>
+ <td>${TemplateHelper.dateFormat(subscription.deliveryNextAttempt, Message.EndOfTime, Message.NextPublish, Message.NextPublish)}</td>
<td>${subscription.id}</td>
</tr>`;
}
/**
* Render a row of headers for subscription details.
- * @returns {String}
+ * @returns {string} html
*/
function renderSubscriptionRowHeader() {
return `<tr>
<th scope="col">Content Delivered</th>
<th scope="col">Content Delivery Failures</th>
<th scope="col">Next Delivery</th>
- <th scope="col">ID</th>
+ <th scope="col">Internal Id</th>
</tr>
`;
}
+/**
+ * Escape some xml things in strings.
+ * @param {string} string string to escape
+ * @returns {string} escaped
+ */
+function xmlEscape(string) {
+ if (typeof string === 'number') {
+ return string;
+ }
+ if (typeof string !== 'string') {
+ return undefined;
+ }
+ // eslint-disable-next-line security/detect-object-injection
+ return string.replace(/[<>&'"]/, (c) => ({
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ '\'': ''',
+ '"': '"',
+ }[c]));
+}
+
+
+/**
+ * Add common site links to navigation header.
+ * @param {number} pagePathLevel depth from root
+ * @param {object} ctx context
+ * @param {object} options options
+ */
+function navLinks(pagePathLevel, ctx, options) {
+ if (!options.navLinks) {
+ options.navLinks = [];
+ }
+ const rootPath = '../'.repeat(pagePathLevel);
+
+ if (options.pageIdentifier !== 'admin') {
+ options.navLinks.push({
+ text: 'Admin',
+ href: `${rootPath}admin/`,
+ });
+ }
+}
+
+
module.exports = Object.assign(Object.create(TemplateHelper), {
+ navLinks,
+ xmlEscape,
renderTopicRowHeader,
renderTopicRow,
renderSubscriptionRowHeader,
renderSubscriptionRow,
-});
\ No newline at end of file
+});