Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/974 extra infos profile #1040

Merged
merged 13 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions functions/src/Integrations/user-stats.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as functions from 'firebase-functions'
import { db } from '../Firebase/firestoreDB'


export const countHowTos = functions.firestore
.document('v3_howtos/{id}')
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
.onWrite(async (change, context) => {
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
updateStats(change, 'howToCount')
})

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

async function updateStats(change, 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 ', info._createdBy, ' ', target, ' delta: ', delta )

let user = await userStatsRef.doc(info._createdBy).get();
let stats = null;
if(user && user.exists){
if(!user.stats){
console.log('No previous stats for ', user.id ,' -> compute'),
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
stats = await computeUserStats(info._createdBy);
console.log(user._id, ': ', stats);
}else{
stats = user.stats;
if (!(target in user.stats)) stats[target] = 0;
}
if(stats){
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
user.ref.update({
stats: stats
}, {merge: true}).then(() =>{
return true
}).catch(e => {
console.error('Could not update user stats, error: ', e);
});
}
}else{
console.error('Fatal(updateStats): user not found for ', target, ': ', info._createdBy)
}
return false
}

// Compute one user stats
async function computeUserStats(owner){
console.log("Calculando para ", owner);

stats = {};
try {
stats.howToCount = await db.collection('v3_howtos').where("_createdBy", "==", owner).where("moderation", "==", "accepted")
.get()
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
.then(querySnapshot => {
let count = 0;
querySnapshot.forEach(doc => {
count++;
});
return count
});

stats.eventCount = await db.collection('v3_events').where("_createdBy", "==", owner).where("moderation", "==", "accepted")
.get()
.then(querySnapshot => {
let count = 0;
querySnapshot.forEach(doc => {
count++;
});
return count
});

return stats
} catch(e) {
console.error('Error compute:',e)
}
return null
}
3 changes: 3 additions & 0 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as IntegrationsDiscord from './Integrations/firebase-discord'
import * as UserTriggers from './Integrations/user-triggers'
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 @@ -25,6 +26,8 @@ exports.notifyEventAccepted = IntegrationsDiscord.notifyEventAccepted
exports.handleUserChanges = UserTriggers.handleUserChanges
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
2 changes: 1 addition & 1 deletion scripts/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ checkBrowsers(paths.appPath, isInteractive)
function build(previousFileSizes) {
console.log('Creating an optimized production build...')

let compiler = webpack(config)
const compiler = webpack(config)
return new Promise((resolve, reject) => {
compiler.run((err, stats) => {
let messages
Expand Down
1 change: 0 additions & 1 deletion src/components/ElWithBeforeIcon/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const ElWithBeforeIcon: FunctionComponent<IProps> = ({

return (
<Box
mr={4}
pl="30px"
sx={{
position: 'relative',
Expand Down
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
alromh87 marked this conversation as resolved.
Show resolved Hide resolved
eventCount: number
}

export type IUserDB = IUser & DBDoc

export type UserRole = 'super-admin' | 'subscriber' | 'admin'
115 changes: 73 additions & 42 deletions src/pages/User/content/UserPage/UserPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ import Slider from 'react-slick'
import styled from 'styled-components'
import Icon from 'src/components/Icons'
import Flex from 'src/components/Flex'
// import ElWithBeforeIcon from 'src/components/ElWithBeforeIcon'
import ElWithBeforeIcon from 'src/components/ElWithBeforeIcon'
import { zIndex } from 'src/themes/styled.theme'
import Workspace from 'src/pages/User/workspace/Workspace'
import { Text } from 'src/components/Text'
import { Link } from 'src/components/Links'

import theme from 'src/themes/styled.theme'
import { replaceDashesWithSpaces } from 'src/utils/helpers'
Expand All @@ -33,9 +34,9 @@ import PPIcon from 'src/assets/images/plastic-types/pp.svg'
import PSIcon from 'src/assets/images/plastic-types/ps.svg'
import PVCIcon from 'src/assets/images/plastic-types/pvc.svg'

// import EventsIcon from 'src/assets/icons/icon-events.svg'
import EventsIcon from 'src/assets/icons/icon-events.svg'
// import ExpertIcon from 'src/assets/icons/icon-expert.svg'
// import HowToCountIcon from 'src/assets/icons/icon-how-to.svg'
import HowToCountIcon from 'src/assets/icons/icon-how-to.svg'
// import V4MemberIcon from 'src/assets/icons/icon-v4-member.svg'

import { IUploadedFileMeta } from 'src/stores/storage'
Expand Down Expand Up @@ -114,21 +115,24 @@ const MobileBadge = styled.div`
}
`

// const CommitmentBox = styled.div`
// border: 2px solid black;
// border-radius: 10px;
// padding: 20px;
// background-color: ${theme.colors.background};
// margin-bottom: 20px;
// `
const UserStatsBox = styled.div`
margin-top: 15px;
border: 2px solid black;
border-radius: 10px;
padding: 10px;
background-color: ${theme.colors.background};
margin-bottom: 20px;
`

// const CommitmentBoxItem = styled.div`
// margin-top: 15px;
const UserStatsBoxItem = styled.div`
margin-top: 15px;
display: flex;
align-items: center;

// &:first-child {
// margin-top: 0;
// }
// `
&:first-child {
margin-top: 0;
}
`

const ProfileWrapper = styled(Box)`
/* margin-top: 40px;
Expand Down Expand Up @@ -225,32 +229,50 @@ export class UserPage extends React.Component<
})
}
// Comment on 6.05.20 by BG : renderCommitmentBox commented for now, will be reused with #974
// public renderCommitmentBox(isExpert?: boolean, isV4Member?: boolean) {
// return (
// <CommitmentBox>
// {isExpert && (
// <CommitmentBoxItem>
// <ElWithBeforeIcon IconUrl={ExpertIcon} height="25px">
// Expert
// </ElWithBeforeIcon>
// </CommitmentBoxItem>
// )}
// {isV4Member && (
// <CommitmentBoxItem>
// <ElWithBeforeIcon IconUrl={V4MemberIcon}>
// V4 Member
// </ElWithBeforeIcon>
// </CommitmentBoxItem>
// )}
// <CommitmentBoxItem>
// <ElWithBeforeIcon IconUrl={EventsIcon}>0</ElWithBeforeIcon>
// </CommitmentBoxItem>
// <CommitmentBoxItem>
// <ElWithBeforeIcon IconUrl={HowToCountIcon}>0</ElWithBeforeIcon>
// </CommitmentBoxItem>
// </CommitmentBox>
// )
// }
public renderUserStatsBox(user: IUserPP) {
if (!user.stats) {
user.stats = { howToCount: 0, eventCount: 0 }
}

return (
<UserStatsBox>
{/* {isExpert && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={ExpertIcon} height="25px">
Expert
</ElWithBeforeIcon>
</UserStatsBoxItem>
)} */}
{user.location && (
<Link color={'black'} to={'/map/#' + user.userName}>
<UserStatsBoxItem>
<Icon glyph="location-on" size="25"></Icon>
<Box ml="5px">{user.location?.country}</Box>
</UserStatsBoxItem>
</Link>
)}
{/* {isV4Member && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={V4MemberIcon}>
V4 Member
</ElWithBeforeIcon>
</UserStatsBoxItem>
)} */}
{user.stats.howToCount > 0 && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={HowToCountIcon} />
How-to: {user.stats.howToCount}
</UserStatsBoxItem>
)}
{user.stats.eventCount > 0 && (
<UserStatsBoxItem>
<ElWithBeforeIcon IconUrl={EventsIcon} />
Events: {user.stats.eventCount}
</UserStatsBoxItem>
)}
</UserStatsBox>
)
}

public renderPlasticTypes(plasticTypes: Array<PlasticTypeLabel>) {
function renderIcon(type: string) {
Expand Down Expand Up @@ -373,6 +395,13 @@ export class UserPage extends React.Component<
},
)
}
// TODO check if user exist and have created how-to or events
const shouldRenderUserStatsBox =
user &&
(user.location ||
(user.stats && (user.stats.howToCount || user.stats.eventCount)))
? true
: false

return (
<ProfileWrapper mt={4} mb={6}>
Expand Down Expand Up @@ -448,6 +477,8 @@ export class UserPage extends React.Component<
>
<MobileBadge>
<Image src={workspaceBadgeSrc} />

{shouldRenderUserStatsBox && this.renderUserStatsBox(user)}
</MobileBadge>
</Box>
</ProfileContentWrapper>
Expand Down