Add support for Supporter badges
This commit is contained in:
parent
2adcbaa7c2
commit
b0d32b6578
api/chalicelib/api
web
.yarn
src/components
@ -71,7 +71,7 @@ def create(user, data):
|
||||
|
||||
def get(user, username, path):
|
||||
db = database.get_db()
|
||||
owner = db.users.find_one({'username': username}, {'_id': 1, 'username': 1, 'avatar': 1})
|
||||
owner = db.users.find_one({'username': username}, {'_id': 1, 'username': 1, 'avatar': 1, 'isSilverSupporter': 1})
|
||||
if not owner: raise util.errors.NotFound('User not found')
|
||||
project = db.projects.find_one({'user': owner['_id'], 'path': path})
|
||||
if not project: raise util.errors.NotFound('Project not found')
|
||||
|
@ -8,7 +8,7 @@ def all(user, params):
|
||||
expression = re.compile(params['query'], re.IGNORECASE)
|
||||
db = database.get_db()
|
||||
|
||||
users = list(db.users.find({'username': expression}, {'username': 1, 'avatar': 1}).limit(10).sort('username', pymongo.ASCENDING))
|
||||
users = list(db.users.find({'username': expression}, {'username': 1, 'avatar': 1, 'isSilverSupporter': 1}).limit(10).sort('username', pymongo.ASCENDING))
|
||||
for u in users:
|
||||
if 'avatar' in u:
|
||||
u['avatarUrl'] = uploads.get_presigned_url('users/{0}/{1}'.format(u['_id'], u['avatar']))
|
||||
@ -36,7 +36,7 @@ def users(user, params):
|
||||
if not params or 'username' not in params: raise util.errors.BadRequest('Username parameter needed')
|
||||
expression = re.compile(params['username'], re.IGNORECASE)
|
||||
db = database.get_db()
|
||||
users = list(db.users.find({'username': expression}, {'username': 1, 'avatar': 1}).limit(5).sort('username', pymongo.ASCENDING))
|
||||
users = list(db.users.find({'username': expression}, {'username': 1, 'avatar': 1, 'isSilverSupporter': 1}).limit(5).sort('username', pymongo.ASCENDING))
|
||||
for u in users:
|
||||
if 'avatar' in u:
|
||||
u['avatarUrl'] = uploads.get_presigned_url('users/{0}/{1}'.format(u['_id'], u['avatar']))
|
||||
@ -60,7 +60,7 @@ def discover(user):
|
||||
if len(projects) >= count: break
|
||||
|
||||
interest_fields = ['bio', 'avatar', 'website', 'facebook', 'twitter', 'instagram', 'location']
|
||||
all_users = list(db.users.find({'_id': {'$ne': user['_id']}, '$or': list(map(lambda f: {f: {'$exists': True}}, interest_fields))}, {'username': 1, 'avatar': 1}))
|
||||
all_users = list(db.users.find({'_id': {'$ne': user['_id']}, '$or': list(map(lambda f: {f: {'$exists': True}}, interest_fields))}, {'username': 1, 'avatar': 1, 'isSilverSupporter': 1}))
|
||||
random.shuffle(all_users)
|
||||
for u in all_users:
|
||||
if 'avatar' in u:
|
||||
|
@ -15,11 +15,12 @@ def me(user):
|
||||
'groups': user.get('groups', []),
|
||||
'subscriptions': user.get('subscriptions'),
|
||||
'finishedTours': user.get('completedTours', []) + user.get('skippedTours', []),
|
||||
'isSilverSupporter': user.get('isSilverSupporter'),
|
||||
}
|
||||
|
||||
def get(user, username):
|
||||
db = database.get_db()
|
||||
fetch_user = db.users.find_one({'username': username}, {'username': 1, 'createdAt': 1, 'avatar': 1, 'avatarBlurHash': 1, 'bio': 1, 'location': 1, 'website': 1, 'twitter': 1, 'facebook': 1, 'linkedIn': 1, 'instagram': 1})
|
||||
fetch_user = db.users.find_one({'username': username}, {'username': 1, 'createdAt': 1, 'avatar': 1, 'avatarBlurHash': 1, 'bio': 1, 'location': 1, 'website': 1, 'twitter': 1, 'facebook': 1, 'linkedIn': 1, 'instagram': 1, 'isSilverSupporter': 1})
|
||||
if not fetch_user:
|
||||
raise util.errors.NotFound('User not found')
|
||||
project_query = {'user': fetch_user['_id']}
|
||||
|
BIN
web/.yarn/cache/esbuild-darwin-arm64-npm-0.15.14-c511cc10d8-8.zip
vendored
Normal file
BIN
web/.yarn/cache/esbuild-darwin-arm64-npm-0.15.14-c511cc10d8-8.zip
vendored
Normal file
Binary file not shown.
Binary file not shown.
@ -9,6 +9,7 @@ import utils from '../../utils/utils.js';
|
||||
|
||||
import logoLight from '../../images/logo/light.png';
|
||||
import UserChip from './UserChip';
|
||||
import SupporterBadge from './SupporterBadge';
|
||||
|
||||
const StyledNavBar = styled.div`
|
||||
height:60px;
|
||||
@ -185,11 +186,7 @@ function NavBar() {
|
||||
</span>
|
||||
|
||||
<Dropdown direction="left" pointing="top right" icon={null} style={{marginLeft: 10}}
|
||||
trigger={
|
||||
<div style={{
|
||||
display: 'inline-block', width: 33, height: 33, borderRadius: '50%', backgroundSize: 'cover', backgroundPosition: 'center center', backgroundImage: `url(${utils.avatarUrl(user)})`, verticalAlign: 'middle', boxShadow: '0px 5px 10px rgba(0,0,0,0.1)', border: '2px solid white'
|
||||
}} />
|
||||
}
|
||||
trigger={<UserChip user={user} withoutLink avatarOnly />}
|
||||
>
|
||||
<Dropdown.Menu style={{ minWidth: '200px', paddingTop: 10 }}>
|
||||
{user &&
|
||||
@ -201,6 +198,7 @@ function NavBar() {
|
||||
<span>{user.username}</span>
|
||||
</Dropdown.Header>
|
||||
}
|
||||
{user?.isSilverSupporter && <Dropdown.Header><SupporterBadge type='silver' /></Dropdown.Header>}
|
||||
<Dropdown.Divider />
|
||||
<Link to="/" className="item">Projects</Link>
|
||||
{user &&<Link to={`/${user.username}`} className="item">Profile</Link>}
|
||||
|
21
web/src/components/includes/SupporterBadge.jsx
Normal file
21
web/src/components/includes/SupporterBadge.jsx
Normal file
@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { Icon, Popup, Label, Button } from 'semantic-ui-react';
|
||||
|
||||
export default function SupporterBadge({ type, compact }) {
|
||||
if (type === 'silver')
|
||||
return (
|
||||
compact ?
|
||||
<Popup basic
|
||||
trigger={<Label size='mini' circular color='black' style={{borderRadius: '50%', width: 20, height: 20}} icon='trophy' />
|
||||
}
|
||||
>
|
||||
<Popup.Content>Silver Supporter</Popup.Content>
|
||||
</Popup>
|
||||
:
|
||||
<Label color='black' icon>
|
||||
<Icon name='trophy' />
|
||||
<Label.Detail>Silver Supporter</Label.Detail>
|
||||
</Label>
|
||||
);
|
||||
return null;
|
||||
}
|
@ -3,28 +3,40 @@ import { Link } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
import utils from '../../utils/utils.js';
|
||||
|
||||
const Avatar = styled.div`
|
||||
display: inline-block;
|
||||
width: ${props => props.compact ? 15 : 30}px;
|
||||
height: ${props => props.compact ? 15 : 30}px;
|
||||
border-radius: 50%;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
background-image: url(${props => utils.cropUrl(utils.avatarUrl(props.user), 50, 50)});
|
||||
vertical-align: middle;
|
||||
margin-right: ${props => props.compact ? 4 : 8}px;
|
||||
`;
|
||||
const Username = styled.span`
|
||||
font-size: ${props => props.compact ? 10 : 12}px;
|
||||
`;
|
||||
import SupporterBadge from './SupporterBadge';
|
||||
|
||||
function UserChip({ user, compact, meta, style }) {
|
||||
const Avatar = styled.div`
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
width: ${props => props.compact ? 15 : 30}px;
|
||||
height: ${props => props.compact ? 15 : 30}px;
|
||||
border-radius: 50%;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
background-image: url(${props => utils.cropUrl(utils.avatarUrl(props.user), 50, 50)});
|
||||
vertical-align: middle;
|
||||
margin-right: ${props => props.avatarOnly ? 0 : (props.compact ? 4 : 8)}px;
|
||||
`;
|
||||
const Badge = styled.div`
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
left: -8px;
|
||||
`;
|
||||
const Username = styled.span`
|
||||
font-size: ${props => props.compact ? 10 : 12}px;
|
||||
`;
|
||||
|
||||
function UserChip({ user, compact, meta, withoutLink, avatarOnly, style }) {
|
||||
if (!user) return null;
|
||||
return (
|
||||
<Link to={`/${user.username}`} style={style || {}}>
|
||||
<Avatar compact={compact} user={user} />
|
||||
<Username compact={compact}>{user.username}</Username>
|
||||
{meta && <span style={{color:'rgb(180,180,180)', fontSize: 10, marginLeft: 10}}>{meta}</span>}
|
||||
<Link to={withoutLink ? '#' : `/${user.username}`} style={style || {}}>
|
||||
<Avatar compact={compact} user={user} avatarOnly={avatarOnly}>
|
||||
{user.isSilverSupporter && <Badge><SupporterBadge compact type='silver' /></Badge>}
|
||||
</Avatar>
|
||||
{!avatarOnly && <>
|
||||
<Username compact={compact}>{user.username}</Username>
|
||||
{meta && <span style={{color:'rgb(180,180,180)', fontSize: 10, marginLeft: 10}}>{meta}</span>}
|
||||
</>}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import actions from '../../../actions';
|
||||
import api from '../../../api';
|
||||
|
||||
import BlurrableImage from '../../includes/BlurrableImage';
|
||||
import SupporterBadge from '../../includes/SupporterBadge';
|
||||
|
||||
function Profile() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -69,6 +70,9 @@ function Profile() {
|
||||
Joined {moment(profileUser.createdAt).fromNow()}
|
||||
</span>
|
||||
</Card.Meta>
|
||||
{profileUser.isSilverSupporter &&
|
||||
<div style={{marginTop: 10}}><SupporterBadge type='silver' /></div>
|
||||
}
|
||||
</Card.Content>
|
||||
{profileUser.location
|
||||
&& (
|
||||
|
Loading…
Reference in New Issue
Block a user