mirror of
https://github.com/wassname/talk.git
synced 2026-07-05 22:02:02 +08:00
Added edge for metrics, fixed client linting errors
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import React, {PropTypes} from 'react';
|
||||
import styles from './FlagWidget.css';
|
||||
|
||||
const FlagWidget = props => {
|
||||
const FlagWidget = () => {
|
||||
return (
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
@@ -3,6 +3,7 @@ const _ = require('lodash');
|
||||
const Actions = require('./actions');
|
||||
const Assets = require('./assets');
|
||||
const Comments = require('./comments');
|
||||
const Metrics = require('./metrics');
|
||||
const Settings = require('./settings');
|
||||
const Users = require('./users');
|
||||
|
||||
@@ -18,6 +19,7 @@ module.exports = (context) => {
|
||||
Actions,
|
||||
Assets,
|
||||
Comments,
|
||||
Metrics,
|
||||
Settings,
|
||||
Users
|
||||
].map((loaders) => {
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
const _ = require('lodash');
|
||||
const CommentModel = require('../../models/comment');
|
||||
const AssetModel = require('../../models/asset');
|
||||
const ActionModel = require('../../models/action');
|
||||
|
||||
const getMetrics = (context, {from, to}) => {
|
||||
|
||||
let commentMetrics = {};
|
||||
let assetMetrics = [];
|
||||
|
||||
return ActionModel.aggregate([
|
||||
|
||||
// Find all actions that were created in the time range.
|
||||
{$match: {
|
||||
action_type: 'FLAG',
|
||||
item_type: 'COMMENTS',
|
||||
created_at: {
|
||||
$gt: from,
|
||||
$lt: to
|
||||
}
|
||||
}},
|
||||
|
||||
// Count all those items.
|
||||
{$group: {
|
||||
_id: '$item_id',
|
||||
count: {
|
||||
$sum: 1
|
||||
}
|
||||
}},
|
||||
|
||||
// Project the count to a better field.
|
||||
{$project: {
|
||||
item_id: '$_id',
|
||||
count: '$count'
|
||||
}}
|
||||
]).then((actionSummaries) => {
|
||||
|
||||
// Collect all the action summaries into a dictionary.
|
||||
actionSummaries.forEach((actionSummary) => {
|
||||
commentMetrics[actionSummary.item_id] = actionSummary.count;
|
||||
});
|
||||
|
||||
// Collect just the comment id's.
|
||||
let commentIDs = actionSummaries.map((as) => as.item_id);
|
||||
|
||||
// Find those comments.
|
||||
return CommentModel.aggregate([
|
||||
|
||||
// Get only those comments.
|
||||
{$match: {
|
||||
id: {
|
||||
$in: commentIDs
|
||||
}
|
||||
}},
|
||||
|
||||
// Group by their asset id and push in the comment id.
|
||||
{$group: {
|
||||
_id: {
|
||||
asset_id: '$asset_id'
|
||||
},
|
||||
ids: {
|
||||
$addToSet: '$id'
|
||||
}
|
||||
}},
|
||||
|
||||
// Project that data only as better fields.
|
||||
{$project: {
|
||||
asset_id: '$_id.asset_id',
|
||||
ids: '$ids'
|
||||
}}
|
||||
]);
|
||||
})
|
||||
.then((commentResults) => {
|
||||
|
||||
// Compute all the action summaries for the assets based on the time slice
|
||||
// that you requested.
|
||||
commentResults.forEach((result) => {
|
||||
let actionCount = 0;
|
||||
|
||||
result.ids.forEach((id) => {
|
||||
actionCount += commentMetrics[id];
|
||||
});
|
||||
|
||||
assetMetrics.push({
|
||||
id: result.asset_id,
|
||||
actionCount,
|
||||
actionableItemCount: result.ids.length
|
||||
});
|
||||
});
|
||||
|
||||
// Sort the assets by flag count.
|
||||
assetMetrics.sort((a, b) => {
|
||||
return b.flags - a.flags;
|
||||
});
|
||||
|
||||
// Only keep the top 10.
|
||||
assetMetrics = assetMetrics.slice(0, 10);
|
||||
|
||||
// Determine the assets that we need to return.
|
||||
return AssetModel.find({
|
||||
id: {
|
||||
$in: assetMetrics.map((asset) => asset.id)
|
||||
}
|
||||
});
|
||||
})
|
||||
.then((assets) => {
|
||||
|
||||
// Join up the assets that are returned by their id.
|
||||
let groupedAssets = _.groupBy(assets, 'id');
|
||||
|
||||
// Return from the sorted asset metrics and return their assetes.
|
||||
return assetMetrics.map(({id, actionCount, actionableItemCount}) => {
|
||||
if (id in groupedAssets) {
|
||||
let asset = groupedAssets[id][0];
|
||||
|
||||
let flagAssetActionSummary = {
|
||||
action_type: 'FLAG',
|
||||
actionCount,
|
||||
actionableItemCount
|
||||
};
|
||||
|
||||
// Add the action summaries to the asset.
|
||||
asset.action_summaries = [flagAssetActionSummary];
|
||||
|
||||
return asset;
|
||||
}
|
||||
|
||||
return null;
|
||||
}).filter((asset) => asset != null);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = (context) => ({
|
||||
Metrics: {
|
||||
get: ({from, to}) => getMetrics(context, {from, to})
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
const AssetActionSummary = {
|
||||
__resolveType({action_type}) {
|
||||
switch (action_type) {
|
||||
case 'FLAG':
|
||||
return 'FlagAssetActionSummary';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = AssetActionSummary;
|
||||
@@ -1,5 +1,6 @@
|
||||
const ActionSummary = require('./action_summary');
|
||||
const Action = require('./action');
|
||||
const AssetActionSummary = require('./asset_action_summary');
|
||||
const Asset = require('./asset');
|
||||
const Comment = require('./comment');
|
||||
const Date = require('./date');
|
||||
@@ -17,6 +18,7 @@ const ValidationUserError = require('./validation_user_error');
|
||||
module.exports = {
|
||||
ActionSummary,
|
||||
Action,
|
||||
AssetActionSummary,
|
||||
Asset,
|
||||
Comment,
|
||||
Date,
|
||||
|
||||
@@ -39,12 +39,12 @@ const RootQuery = {
|
||||
return Comments.getByQuery(query);
|
||||
},
|
||||
|
||||
metric(_, args, {user, loaders: {Assets}}) {
|
||||
metrics(_, {from, to}, {user, loaders: {Metrics}}) {
|
||||
if (user == null || !user.hasRoles('ADMIN')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Assets.getForMetrics();
|
||||
return Metrics.get({from, to});
|
||||
},
|
||||
|
||||
// This returns the current user, ensure that if we aren't logged in, we
|
||||
|
||||
+5
-18
@@ -198,16 +198,6 @@ interface AssetActionSummary {
|
||||
actionableItemCount: Int
|
||||
}
|
||||
|
||||
# A summary of counts related to all the Likes on an Asset.
|
||||
type LikeAssetActionSummary implements AssetActionSummary {
|
||||
|
||||
# Number of actions associated with actionable types on this this Asset.
|
||||
actionCount: Int
|
||||
|
||||
# Number of unique actionable types that are referenced by the actions.
|
||||
actionableItemCount: Int
|
||||
}
|
||||
|
||||
# A summary of counts related to all the Flags on an Asset.
|
||||
type FlagAssetActionSummary implements AssetActionSummary {
|
||||
|
||||
@@ -343,15 +333,12 @@ type Asset {
|
||||
# The date that the asset was closed at.
|
||||
closedAt: Date
|
||||
|
||||
# The date that the asset was created.
|
||||
created_at: Date
|
||||
|
||||
# Summary of all Actions against all entities associated with the Asset.
|
||||
# (likes, flags, etc.)
|
||||
action_summaries: [AssetActionSummary]
|
||||
|
||||
# Unique users that have commented on this Asset.
|
||||
authorCount: Int
|
||||
# The date that the asset was created.
|
||||
created_at: Date
|
||||
}
|
||||
|
||||
################################################################################
|
||||
@@ -386,7 +373,7 @@ type ValidationUserError implements UserError {
|
||||
}
|
||||
|
||||
################################################################################
|
||||
## Queries
|
||||
## Queries;
|
||||
################################################################################
|
||||
|
||||
# Establishes the ordering of the content by their created_at time stamp.
|
||||
@@ -424,8 +411,8 @@ type RootQuery {
|
||||
# The currently logged in user based on the request.
|
||||
me: User
|
||||
|
||||
# metrics
|
||||
metric: [Asset]
|
||||
# Metrics related to user actions are saturated into the assets returned.
|
||||
metrics(from: Date!, to: Date!): [Asset]
|
||||
}
|
||||
|
||||
################################################################################
|
||||
|
||||
Reference in New Issue
Block a user