Skip to content

Commit

Permalink
Fix #974 Extra infromation on Profile
Browse files Browse the repository at this point in the history
Shows information on user profile
- [x] Location with link to map pin
- [x] Accepted HowTos
- [x] Accepted Events

User stats are computed via firebase function triggered by database changes
  • Loading branch information
alromh87 committed Sep 5, 2020
1 parent e59c90a commit 40b7deb
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 14 deletions.
81 changes: 81 additions & 0 deletions functions/src/Integrations/user-stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as functions from 'firebase-functions'
import { db } from '../Firebase/firestoreDB'


export const countHowTos = functions.firestore
.document('v3_howtos/{id}')
.onWrite(async (change, context) => {

updateStats(change, 'v3_howtos', 'howToCount')

})

export const countEvents = functions.firestore
.document('v3_events/{id}')
.onWrite(async (change, context) => {

updateStats(change, 'v3_events', 'eventCount')

})

function updateStats(change, collection, target){

const info = change.after.exists ? change.after.data() : null
const prevInfo = change.before.exists ? change.before.data() : null
const userStatsRef = db.collection('v3_users/');

let delta = 0

if (info !== null && info.moderation === 'accepted' && prevInfo !== null && prevInfo.Moderation !== 'accepted') { // Increment if now accepted and previously different
delta = 1
} else if (prevInfo !== null && prevInfo.moderation === 'accepted' && (info === null || info.moderation !== 'accepted')) { // Decrement if previously accepted and now erased or moderation changed
delta = -1
} else {
return null
}

console.log('Update ', collection, ' delta: ', delta )

return userStatsRef.doc(info._createdBy).update({'_stats':{
[target]: admin.firestore.FieldValue.increment(delta)
}}).catch(e => {
console.log(e);
// In case stats for user are inexistent we compute from all his records, Only triggers if no user exist (new Collection)
// computeUserStats(info._createdBy)
})
}

// Compute one user stats
function computeUserStats(owner){

const userStatsRef = db.collection('v3_users/')

db.collection('v3_howtos').where("_createdBy", "==", owner).where("moderation", "==", "accepted")
.get()
.then(querySnapshot => {
let count = 0;
querySnapshot.forEach(doc => {
count++;
});
console.log('Accepted howtos for', owner ,',count: ', count);
userStatsRef.doc(owner).set({'_stats':{
howToCount: count
}}, {merge: true});
return null
}).catch(() => null);

db.collection('v3_events').where("_createdBy", "==", owner).where("moderation", "==", "accepted")
.get()
.then(querySnapshot => {
let count = 0;
querySnapshot.forEach(doc => {
count++;
});
console.log('Accepted events for', owner ,',count: ', count);
userStatsRef.doc(owner).set({'_stats':{
eventCount: count
}}, {merge: true});
return null
}).catch(() => null);
}

3 changes: 3 additions & 0 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as IntegrationsSlack from './Integrations/firebase-slack'
import * as IntegrationsDiscord from './Integrations/firebase-discord'
import { FirebaseUserBackup } from './Integrations/firebase-userBackup'
import * as IntegrationsEmail from './Integrations/firebase-email'
import * as UserStats from './Integrations/user-stats'
import * as Admin from './admin'

// the following endpoints are exposed for use by various triggers
Expand All @@ -23,6 +24,8 @@ exports.notifyHowToAccepted = IntegrationsDiscord.notifyHowToAccepted
exports.notifyEventAccepted = IntegrationsDiscord.notifyEventAccepted
exports.firebaseUserBackup = FirebaseUserBackup
exports.emailNotificationDemo = IntegrationsEmail.notifyEmailDemo
exports.countEvents = UserStats.countEvents
exports.countHowTos = UserStats.countHowTos
// CC Note, 2020-04-40
// folder-based naming conventions should be encourage from now on
exports.adminGetUserEmail = Admin.getUserEmail
6 changes: 6 additions & 0 deletions src/models/user.models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface IUser {
country?: string | null
location?: ILocation | null
year?: ISODateString
_stats?: IUserStats
}

interface IExternalLink {
Expand All @@ -51,6 +52,11 @@ interface IExternalLink {
| 'instagram'
}

interface IUserStats {
howToCount: number
eventCount: number
}

export type IUserDB = IUser & DBDoc

export type UserRole = 'super-admin' | 'subscriber' | 'admin'
45 changes: 31 additions & 14 deletions src/pages/User/content/UserPage/UserPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,9 @@ export class UserPage extends React.Component<
}
// Comment on 6.05.20 by BG : renderCommitmentBox commented for now, will be reused with #974
public renderUserStatsBox(user: IUserPP) {
console.log('user.location', user.location)
if (!user._stats) {
user._stats = { howToCount: 0, eventCount: 0 }
}

return (
<UserStatsBox>
Expand All @@ -239,25 +241,35 @@ export class UserPage extends React.Component<
</ElWithBeforeIcon>
</UserStatsBoxItem>
)} */}
<Link to={'/map/#' + user.userName}>
<UserStatsBoxItem>
<Icon glyph="location-on"></Icon>
<span> {user.location?.country}</span>
</UserStatsBoxItem>
</Link>
{user.location && (
<Link to={'/map/#' + user.userName}>
<UserStatsBoxItem>
<Icon glyph="location-on"></Icon>
<span> {user.location?.country}</span>
</UserStatsBoxItem>
</Link>
)}
{/* {isV4Member && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={V4MemberIcon}>
V4 Member
</ElWithBeforeIcon>
</UserStatsBoxItem>
)} */}
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={EventsIcon}>0</ElWithBeforeIcon>
</UserStatsBoxItem>
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={HowToCountIcon}>0</ElWithBeforeIcon>
</UserStatsBoxItem>
{user._stats.eventCount > 0 && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={EventsIcon}>
{user._stats.eventCount}
</ElWithBeforeIcon>
</UserStatsBoxItem>
)}
{user._stats.howToCount > 0 && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={HowToCountIcon}>
{user._stats.howToCount}
</ElWithBeforeIcon>
</UserStatsBoxItem>
)}
</UserStatsBox>
)
}
Expand Down Expand Up @@ -384,7 +396,12 @@ export class UserPage extends React.Component<
)
}
// TODO check if user exist and have created how-to or events
const shouldRenderUserStatsBox = user && user.location ? true : false
const shouldRenderUserStatsBox =
user &&
(user.location ||
(user._stats && (user._stats.howToCount || user._stats.eventCount)))
? true
: false

return (
<ProfileWrapper mt={4} mb={6}>
Expand Down

0 comments on commit 40b7deb

Please sign in to comment.