parent
3a30881d7c
commit
cf1a95e340
@ -0,0 +1,24 @@
|
||||
// comment.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const { CommentStats, CommentStatsDefaults } = require(path.join(__dirname, 'lib', 'resource-stats.js'));
|
||||
|
||||
const CommentSchema = new Schema({
|
||||
created: { type: Date, default: Date.now, required: true, index: 1 },
|
||||
resourceType: { type: String, enum: ['Post', 'Page', 'Newsletter'], required: true },
|
||||
resource: { type: Schema.ObjectId, required: true, index: 1, refPath: 'resourceType' },
|
||||
replyTo: { type: Schema.ObjectId, index: 1, ref: 'Comment' },
|
||||
author: { type: Schema.ObjectId, required: true, index: 1, ref: 'User' },
|
||||
content: { type: String, required: true, maxlength: 3000 },
|
||||
stats: { type: CommentStats, default: CommentStatsDefaults, required: true },
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Comment', CommentSchema);
|
@ -0,0 +1,35 @@
|
||||
// lib/resource-stats.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
module.exports.ResourceStats = new Schema({
|
||||
totalViewCount: { type: Number, default: 0, required: true },
|
||||
upvoteCount: { type: Number, default: 0, required: true },
|
||||
downvoteCount: { type: Number, default: 0, required: true },
|
||||
commentCount: { type: Number, default: 0, required: true },
|
||||
});
|
||||
|
||||
module.exports.ResourceStatsDefaults = {
|
||||
totalViewCount: 0,
|
||||
upvoteCount: 0,
|
||||
downvoteCount: 0,
|
||||
commentCount: 0,
|
||||
};
|
||||
|
||||
module.exports.CommentStats = new Schema({
|
||||
upvoteCount: { type: Number, default: 0, required: true },
|
||||
downvoteCount: { type: Number, default: 0, required: true },
|
||||
replyCount: { type: Number, default: 0, required: true },
|
||||
});
|
||||
|
||||
module.exports.CommentStatsDefaults = {
|
||||
upvoteCount: 0,
|
||||
downvoteCount: 0,
|
||||
replyCount: 0,
|
||||
};
|
@ -0,0 +1,30 @@
|
||||
// resource-view.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const RESOURCE_TYPE_LIST = ['Page', 'Post', 'Newsletter'];
|
||||
|
||||
const ResourceViewSchema = new Schema({
|
||||
created: { type: Date, default: Date.now, required: true, index: 1, expires: '30d' },
|
||||
resourceType: { type: String, enum: RESOURCE_TYPE_LIST, required: true },
|
||||
resource: { type: Schema.ObjectId, required: true, index: 1, refPath: 'resourceType' },
|
||||
uniqueKey: { type: String, required: true, index: 1 },
|
||||
viewCount: { type: Number, default: 0, required: true },
|
||||
});
|
||||
|
||||
ResourceViewSchema.index({
|
||||
created: 1,
|
||||
resourceType: 1,
|
||||
resource: 1,
|
||||
uniqueKey: 1,
|
||||
}, {
|
||||
name: 'res_view_daily_unique',
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('ResourceView', ResourceViewSchema);
|
@ -0,0 +1,72 @@
|
||||
// resource.js
|
||||
// Copyright (C) 2021 Digital Telepresence, LLC
|
||||
// License: Apache-2.0
|
||||
|
||||
'use strict';
|
||||
|
||||
const { SiteService } = require('../../lib/site-lib');
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
const ResourceView = mongoose.model('ResourceView');
|
||||
|
||||
class ResourceService extends SiteService {
|
||||
|
||||
constructor (dtp) {
|
||||
super(dtp, module.exports);
|
||||
this.populateResourceView = [
|
||||
{
|
||||
path: 'resource',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Records 24-hour unique view counts for a given resource happening on a
|
||||
* given ExpressJS Request. Views are uniqued by stripping time from the
|
||||
* current Date, and upserting a tracking object in MongoDB.
|
||||
*
|
||||
* @param {Request} req
|
||||
* @param {String} resourceType 'Post', 'Page', or 'Newsletter'
|
||||
* @param {mongoose.Types.ObjectId} resourceId The _id of the object for which
|
||||
* a view is being tracked.
|
||||
*/
|
||||
async recordView (req, resourceType, resourceId) {
|
||||
const CURRENT_DAY = new Date();
|
||||
CURRENT_DAY.setHours(0, 0, 0, 0);
|
||||
|
||||
let uniqueKey = req.ip.toString().trim().toLowerCase();
|
||||
if (req.user) {
|
||||
uniqueKey += `:user:${req.user._id.toString()}`;
|
||||
}
|
||||
|
||||
const response = await ResourceView.updateOne(
|
||||
{
|
||||
created: CURRENT_DAY,
|
||||
resourceType,
|
||||
resource: resourceId,
|
||||
uniqueKey,
|
||||
},
|
||||
{
|
||||
$inc: { viewCount: 1 },
|
||||
},
|
||||
{ upsert: true },
|
||||
);
|
||||
this.log.debug('resource view', { response });
|
||||
if (response.upsertedCount > 0) {
|
||||
const Model = mongoose.model(resourceType);
|
||||
await Model.updateOne(
|
||||
{ _id: resourceId },
|
||||
{
|
||||
$inc: { 'stats.totalViewCount': 1 },
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
slug: 'resource',
|
||||
name: 'resource',
|
||||
create: (dtp) => { return new ResourceService(dtp); },
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
button(type="button", onclick= "return window.history.back();").uk-button.dtp-button-primary
|
||||
button(type="button", onclick= "return dtp.app.goBack();").uk-button.dtp-button-primary
|
||||
span
|
||||
i.fas.fa-chevron-left
|
||||
span.uk-margin-small-left Back
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,13 @@
|
||||
[program:dtp-sites]
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 dtp-sites.js
|
||||
directory=/home/dtp/live/dtp-sites
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=3
|
||||
stopsignal=INT
|
||||
stderr_logfile=/var/log/dtp-sites/dtp-sites.err.log
|
||||
stdout_logfile=/var/log/dtp-sites/dtp-sites.out.log
|
||||
user=dtp
|
||||
environment=HOME='/home/dtp/live/dtp-sites',HTTP_BIND_PORT=30%(process_num)02d,NODE_ENV=production,LOGNAME=dtp-sites
|
@ -0,0 +1,13 @@
|
||||
[program:host-services]
|
||||
numprocs=1
|
||||
process_name=%(program_name)s_%(process_num)02d
|
||||
command=/home/dtp/.nvm/versions/node/v16.13.0/bin/node --optimize_for_size --max_old_space_size=1024 --gc_interval=100 app/workers/host-services.js
|
||||
directory=/home/dtp/live/dtp-sites
|
||||
autostart=true
|
||||
autorestart=true
|
||||
startretries=3
|
||||
stopsignal=INT
|
||||
stderr_logfile=/var/log/dtp-sites/host-services.err.log
|
||||
stdout_logfile=/var/log/dtp-sites/host-services.out.log
|
||||
user=dtp
|
||||
environment=HOME='/home/dtp/live/dtp-sites',HTTP_BIND_PORT=30%(process_num)02d,NODE_ENV=production,LOGNAME=host-services
|
Loading…
Reference in new issue