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

Add Discord field to user profiles #3033

Merged
merged 13 commits into from Apr 18, 2018
1 change: 1 addition & 0 deletions app/Http/Controllers/AccountController.php
Expand Up @@ -127,6 +127,7 @@ public function update()
'user_sig:string',
'user_twitter:string',
'user_website:string',
'user_discord:string',
]
);

Expand Down
21 changes: 21 additions & 0 deletions app/Models/User.php
Expand Up @@ -83,6 +83,7 @@ class User extends Model implements AuthenticatableContract, Messageable
'user_msnm' => 255,
'user_twitter' => 255,
'user_website' => 200,
'user_discord' => 37, // max 32char username + # + 4-digit discriminator
'user_from' => 30,
'user_occ' => 30,
'user_interests' => 30,
Expand Down Expand Up @@ -527,6 +528,11 @@ public function getUserWebsiteAttribute($value)
return presence($value);
}

public function getUserDiscordAttribute($value)
{
return presence($this->user_jabber);
}

public function getUserMsnmAttribute($value)
{
return presence($value);
Expand Down Expand Up @@ -558,6 +564,11 @@ public function getUserColourAttribute($value)
}
}

public function setUserDiscordAttribute($value)
{
$this->attributes['user_jabber'] = $value;
}

public function setUserColourAttribute($value)
{
// also functions for casting null to string
Expand Down Expand Up @@ -1537,6 +1548,16 @@ public function isValid()
}
}

// user_discord is an accessor for user_jabber
if ($this->isDirty('user_jabber') && present($this->user_discord)) {
// This is a basic check and not 100% compliant to Discord's spec, only validates that input:
// - is a 2-32 char username (excluding chars @#:)
// - ends with a # and 4-digit discriminator
if (!preg_match('/^[^@#:]{2,32}#\d{4}$/i', $this->user_discord)) {
$this->validationErrors()->add('user_discord', '.invalid_discord');
}
}

foreach (self::MAX_FIELD_LENGTHS as $field => $limit) {
if ($this->isDirty($field)) {
$val = $this->$field;
Expand Down
1 change: 1 addition & 0 deletions app/Transformers/UserTransformer.php
Expand Up @@ -73,6 +73,7 @@ public function transform(User $user)
'lastfm' => $user->user_lastfm,
'skype' => $user->user_msnm,
'website' => $user->user_website,
'discord' => $user->user_discord,
'playstyle' => $user->osu_playstyle,
'playmode' => $user->playmode,
'post_count' => $user->user_posts,
Expand Down
4 changes: 4 additions & 0 deletions resources/assets/coffee/_classes/tooltip-default.coffee
Expand Up @@ -77,6 +77,10 @@ class @TooltipDefault
width: 10
height: 8

# if enabled, prevents tooltip from changing position
if el.dataset.tooltipPinPosition
options.position.effect = false

el.dataset.origTitle = title

$(el).qtip options, event
Expand Down
64 changes: 64 additions & 0 deletions resources/assets/coffee/react/_components/click-to-copy.coffee
@@ -0,0 +1,64 @@
###
# Copyright 2015-2017 ppy Pty. Ltd.
#
# This file is part of osu!web. osu!web is distributed with the hope of
# attracting more community contributions to the core ecosystem of osu!.
#
# osu!web is free software: you can redistribute it and/or modify
# it under the terms of the Affero GNU General Public License version 3
# as published by the Free Software Foundation.
#
# osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with osu!web. If not, see <http://www.gnu.org/licenses/>.
###

el = React.createElement
{span, i, a} = ReactDOMFactories

bn = 'click-to-copy'

class @ClickToCopy extends React.PureComponent
componentWillUnmount: =>
@restoreTooltipText()


restoreTooltipText: =>
@api.set('content.text', @title) if @title
Timeout.clear @timer
@timer = null


click: (e) =>
e.preventDefault()
el = e.currentTarget
@api ?= $(el).qtip('api')

# copy url to clipboard
clipboard.writeText @props.value

# change tooltip text to provide feedback
@api.set 'content.text', osu.trans('common.buttons.click_to_copy_copied')

# set timer to reset tooltip text
Timeout.clear @timer
@timer = Timeout.set 1000, @restoreTooltipText
@title ?= el.getAttribute('title') || el.dataset.origTitle


render: =>
return span() if !@props.value

a
className: bn
'data-tooltip-pin-position': true
'data-tooltip-position': 'bottom center'
href: '#'
onClick: @click
title: osu.trans('common.buttons.click_to_copy')
@props.label ? @props.value
i
className: "fas fa-paste #{bn}__icon"
14 changes: 10 additions & 4 deletions resources/assets/coffee/react/profile-page/header-extra.coffee
Expand Up @@ -170,10 +170,10 @@ class ProfilePage.HeaderExtra extends React.Component
@props.user.twitter

@fancyLink
key: 'website'
icon: 'fas fa-link'
title: osu.trans 'users.show.info.website'
url: @props.user.website
key: 'discord'
icon: 'fab fa-discord'
title: osu.trans 'users.show.info.discord'
text: el(ClickToCopy, value: @props.user.discord)

@fancyLink
key: 'skype'
Expand All @@ -187,6 +187,12 @@ class ProfilePage.HeaderExtra extends React.Component
title: osu.trans 'users.show.info.lastfm'
url: "https://last.fm/user/#{@props.user.lastfm}"

@fancyLink
key: 'website'
icon: 'fas fa-link'
title: osu.trans 'users.show.info.website'
url: @props.user.website

div
className: "#{bn}__column #{bn}__column--chart #{'invisible' if @props.user.is_bot}"
div className: "#{bn}__rank-box",
Expand Down
1 change: 1 addition & 0 deletions resources/assets/less/bem-index.less
Expand Up @@ -91,6 +91,7 @@
@import "bem/changelog-chart";
@import "bem/changelog-header";
@import "bem/chart";
@import "bem/click-to-copy";
@import "bem/contest";
@import "bem/contest-art-entry";
@import "bem/contest-art-list";
Expand Down
33 changes: 33 additions & 0 deletions resources/assets/less/bem/click-to-copy.less
@@ -0,0 +1,33 @@
/**
* Copyright 2015-2017 ppy Pty. Ltd.
*
* This file is part of osu!web. osu!web is distributed with the hope of
* attracting more community contributions to the core ecosystem of osu!.
*
* osu!web is free software: you can redistribute it and/or modify
* it under the terms of the Affero GNU General Public License version 3
* as published by the Free Software Foundation.
*
* osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with osu!web. If not, see <http://www.gnu.org/licenses/>.
*/

.click-to-copy {
@top: click-to-copy;
.link-white();

&__icon {
opacity: 0;
padding-left: 5px;
color: #999;
cursor: pointer;

.@{top}:hover & {
opacity: 1;
}
}
}
1 change: 1 addition & 0 deletions resources/lang/en/accounts.php
Expand Up @@ -51,6 +51,7 @@
'user_occ' => 'occupation',
'user_twitter' => 'twitter',
'user_website' => 'website',
'user_discord' => 'discord',
],
],

Expand Down
2 changes: 2 additions & 0 deletions resources/lang/en/common.php
Expand Up @@ -30,6 +30,8 @@

'buttons' => [
'cancel' => 'Cancel',
'click_to_copy' => 'click to copy to clipboard',
'click_to_copy_copied' => 'copied to clipboard!',
'delete' => 'Delete',
'permalink' => 'permalink',
'permalink_copied' => 'link copied',
Expand Down
1 change: 1 addition & 0 deletions resources/lang/en/model_validation.php
Expand Up @@ -85,6 +85,7 @@
'contains_username' => 'Password may not contain username.',
'email_already_used' => 'Email address already used.',
'invalid_country' => 'Country not in database.',
'invalid_discord' => 'Discord username invalid.',
'invalid_email' => "Doesn't seem to be a valid email address.",
'too_short' => 'New password is too short.',
'unknown_duplicate' => 'Username or email address already used.',
Expand Down
1 change: 1 addition & 0 deletions resources/lang/en/users.php
Expand Up @@ -262,6 +262,7 @@
],
],
'info' => [
'discord' => 'Discord',
'interests' => 'Interests',
'lastfm' => 'Last.fm',
'location' => 'Current Location',
Expand Down
13 changes: 5 additions & 8 deletions resources/views/accounts/edit.blade.php
Expand Up @@ -29,19 +29,16 @@
</div>

<div class="account-edit__input-groups">
<div class="account-edit__input-group">
@include('accounts._edit_entry_simple', ['field' => 'user_msnm'])
@include('accounts._edit_entry_simple', ['field' => 'user_twitter'])
@include('accounts._edit_entry_simple', ['field' => 'user_website'])
</div>

<div class="account-edit__input-group">
@include('accounts._edit_entry_simple', ['field' => 'user_from'])
@include('accounts._edit_entry_simple', ['field' => 'user_interests'])
@include('accounts._edit_entry_simple', ['field' => 'user_occ'])
</div>

<div class="account-edit__input-group">
@include('accounts._edit_entry_simple', ['field' => 'user_interests'])
@include('accounts._edit_entry_simple', ['field' => 'user_twitter'])
@include('accounts._edit_entry_simple', ['field' => 'user_discord'])
@include('accounts._edit_entry_simple', ['field' => 'user_msnm'])
@include('accounts._edit_entry_simple', ['field' => 'user_website'])
</div>
</div>
</div>
Expand Down