Skip to content
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
1 change: 1 addition & 0 deletions app/api/server/lib/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export async function findUsersToAutocomplete({ uid, selector }) {
fields: {
name: 1,
username: 1,
nickname: 1,
status: 1,
avatarETag: 1,
},
Expand Down
4 changes: 4 additions & 0 deletions app/api/server/v1/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ API.v1.addRoute('users.create', { authRequired: true }, {
username: String,
active: Match.Maybe(Boolean),
bio: Match.Maybe(String),
nickname: Match.Maybe(String),
statusText: Match.Maybe(String),
roles: Match.Maybe(Array),
joinDefaultChannels: Match.Maybe(Boolean),
Expand Down Expand Up @@ -436,6 +437,7 @@ API.v1.addRoute('users.update', { authRequired: true, twoFactorRequired: true },
password: Match.Maybe(String),
username: Match.Maybe(String),
bio: Match.Maybe(String),
nickname: Match.Maybe(String),
statusText: Match.Maybe(String),
active: Match.Maybe(Boolean),
roles: Match.Maybe(Array),
Expand Down Expand Up @@ -473,6 +475,7 @@ API.v1.addRoute('users.updateOwnBasicInfo', { authRequired: true }, {
email: Match.Maybe(String),
name: Match.Maybe(String),
username: Match.Maybe(String),
nickname: Match.Maybe(String),
statusText: Match.Maybe(String),
currentPassword: Match.Maybe(String),
newPassword: Match.Maybe(String),
Expand All @@ -484,6 +487,7 @@ API.v1.addRoute('users.updateOwnBasicInfo', { authRequired: true }, {
email: this.bodyParams.data.email,
realname: this.bodyParams.data.name,
username: this.bodyParams.data.username,
nickname: this.bodyParams.data.nickname,
statusText: this.bodyParams.data.statusText,
newPassword: this.bodyParams.data.newPassword,
typedPassword: this.bodyParams.data.currentPassword,
Expand Down
4 changes: 2 additions & 2 deletions app/apps/client/gameCenter/invitePlayers.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ Template.InvitePlayers.helpers({
roomModifier() {
return (filter, text = '') => {
const f = filter.get();
return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), (part) => `<strong>${ part }</strong>`) }`;
return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get(), 'i'), (part) => `<strong>${ part }</strong>`) }`;
};
},
userModifier() {
return (filter, text = '') => {
const f = filter.get();
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), (part) => `<strong>${ part }</strong>`) }`;
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get(), 'i'), (part) => `<strong>${ part }</strong>`) }`;
};
},
nameSuggestion() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ Template.CreateDiscussion.helpers({
roomModifier() {
return (filter, text = '') => {
const f = filter.get();
return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), (part) => `<strong>${ part }</strong>`) }`;
return `#${ f.length === 0 ? text : text.replace(new RegExp(filter.get(), 'i'), (part) => `<strong>${ part }</strong>`) }`;
};
},
userModifier() {
return (filter, text = '') => {
const f = filter.get();
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), (part) => `<strong>${ part }</strong>`) }`;
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get(), 'i'), (part) => `<strong>${ part }</strong>`) }`;
};
},
nameSuggestion() {
Expand Down
1 change: 1 addition & 0 deletions app/lib/server/functions/getFullUserData.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const logger = new Logger('getFullUserData');
const defaultFields = {
name: 1,
username: 1,
nickname: 1,
status: 1,
utcOffset: 1,
type: 1,
Expand Down
19 changes: 19 additions & 0 deletions app/lib/server/functions/saveUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,23 @@ const handleBio = (updateUser, bio) => {
}
};

const handleNickname = (updateUser, nickname) => {
if (nickname) {
if (nickname.trim()) {
if (typeof nickname !== 'string' || nickname.length > 120) {
throw new Meteor.Error('error-invalid-field', 'nickname', {
method: 'saveUserProfile',
});
}
updateUser.$set = updateUser.$set || {};
updateUser.$set.nickname = nickname;
} else {
updateUser.$unset = updateUser.$unset || {};
updateUser.$unset.nickname = 1;
}
}
};

export const saveUser = function(userId, userData) {
validateUserData(userId, userData);
let sendPassword = false;
Expand Down Expand Up @@ -261,6 +278,7 @@ export const saveUser = function(userId, userData) {
}

handleBio(updateUser, userData.bio);
handleNickname(updateUser, userData.nickname);

Meteor.users.update({ _id }, updateUser);

Expand Down Expand Up @@ -320,6 +338,7 @@ export const saveUser = function(userId, userData) {
};

handleBio(updateUser, userData.bio);
handleNickname(updateUser, userData.nickname);

if (userData.roles) {
updateUser.$set.roles = userData.roles;
Expand Down
2 changes: 1 addition & 1 deletion app/lib/server/startup/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ settings.addGroup('Accounts', function() {
type: 'boolean',
public: true,
});
this.add('Accounts_SearchFields', 'username, name, bio', {
this.add('Accounts_SearchFields', 'username, name, bio, nickname', {
type: 'string',
});
this.add('Accounts_Directory_DefaultView', 'channels', {
Expand Down
18 changes: 17 additions & 1 deletion app/models/server/models/Users.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export class Users extends Base {

this.tryEnsureIndex({ roles: 1 }, { sparse: 1 });
this.tryEnsureIndex({ name: 1 });
this.tryEnsureIndex({ bio: 1 });
this.tryEnsureIndex({ bio: 1 }, { sparse: 1 });
this.tryEnsureIndex({ nickname: 1 }, { sparse: 1 });
this.tryEnsureIndex({ createdAt: 1 });
this.tryEnsureIndex({ lastLogin: 1 });
this.tryEnsureIndex({ status: 1 });
Expand Down Expand Up @@ -1151,6 +1152,21 @@ export class Users extends Base {
return this.update(_id, update);
}

setNickname(_id, nickname = '') {
const update = {
...nickname.trim() ? {
$set: {
nickname,
},
} : {
$unset: {
nickname: 1,
},
},
};
return this.update(_id, update);
}

clearSettings(_id) {
const update = {
$set: {
Expand Down
2 changes: 2 additions & 0 deletions app/models/server/raw/Users.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ export class UsersRaw extends BaseRaw {
username: termRegex,
}, {
name: termRegex,
}, {
nickname: termRegex,
}],
active: true,
type: {
Expand Down
10 changes: 10 additions & 0 deletions app/ui-account/client/accountProfile.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@
</label>
</div>
</div>
<div class="rc-form-group">
<div class="rc-input rc-w100 padded">
<label class="rc-input__label">
<div class="rc-input__title">{{_ "Nickname"}}</div>
<div class="rc-input__wrapper">
<input type="text" class="rc-input__element" name="nickname" id="nickname" maxlength="120" placeholder="{{_ "Nickname_Placeholder" }}" value="{{get 'nickname'}}"/>
</div>
</label>
</div>
</div>
<div class="rc-form-group rc-grid">
{{#with canChange=allowEmailChange}}
<div class="rc-input rc-w50 padded {{#if emailInvalid}}rc-input--error{{/if}}">
Expand Down
11 changes: 8 additions & 3 deletions app/ui-account/client/accountProfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Template.accountProfile.helpers({
const statusType = instance.statusType.get();
const statusText = instance.fields.get('statusText');
const bio = instance.fields.get('bio');
const nickname = instance.fields.get('nickname');
const username = instance.username.get();
const password = instance.password.get();
const confirmationPassword = instance.confirmationPassword.get();
Expand All @@ -141,7 +142,7 @@ Template.accountProfile.helpers({
}
}

if (!avatar && user.bio === bio && user.name === realname && user.username === username && getUserEmailAddress(user) === email && statusText === user.statusText && !password && statusType === user.status) {
if (!avatar && user.bio === bio && user.nickname === nickname && user.name === realname && user.username === username && getUserEmailAddress(user) === email && statusText === user.statusText && !password && statusType === user.status) {
return ret;
}

Expand Down Expand Up @@ -212,6 +213,7 @@ Template.accountProfile.onCreated(function() {
this.fields = new ReactiveDict({
statusText: user.statusText,
bio: user.bio,
nickname: user.nickname,
});

const self = this;
Expand Down Expand Up @@ -302,9 +304,12 @@ Template.accountProfile.onCreated(function() {
data.statusText = s.trim(self.fields.get('statusText'));
}

if (s.trim(self.fields.get('bio')) !== user.statusText) {
if (s.trim(self.fields.get('bio')) !== user.bio) {
data.bio = s.trim(self.fields.get('bio'));
}
if (s.trim(self.fields.get('nickname')) !== user.nickname) {
data.nickname = s.trim(self.fields.get('nickname'));
}
if (self.statusType.get() !== user.statusType) {
data.statusType = self.statusType.get();
}
Expand Down Expand Up @@ -438,7 +443,7 @@ Template.accountProfile.events({
instance.confirmationPassword.set('');
}
},
'input [name=bio], input [name=statusText]'(e, instance) {
'input [name=bio], input [name=statusText], input [name=nickname]'(e, instance) {
instance.fields.set(e.target.name, e.target.value);
},
'input [name=confirmation-password]'(e, instance) {
Expand Down
2 changes: 1 addition & 1 deletion app/ui-flextab/client/tabs/membersList.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
{{> avatar url=avatarUrl}}
<div class="rc-member-list__username">
{{# userPresence uid=user._id}}<div class="rc-member-list__status rc-member-list__status--{{status}}"></div>{{/userPresence}}
{{ignored}} {{displayName}} {{utcOffset}}
{{ignored}} {{displayName}}{{#if user.nickname}} ({{user.nickname}}){{/if}} {{utcOffset}}
</div>
{{> icon user=. block="rc-member-list__menu js-more" icon="menu" }}
</li>
Expand Down
2 changes: 1 addition & 1 deletion app/ui-flextab/client/tabs/userInfo.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ <h1 class="contextual-bar__header-title">{{_ "User_Info"}}</h1>
<div class="rc-user-info__avatar">
{{> avatar username=username}}
</div>
<h3 title="{{name}}" class="rc-user-info__name">{{name}}</h3>
<h3 title="{{name}}" class="rc-user-info__name">{{name}}{{#if nickname}} ({{nickname}}){{/if}}</h3>
{{#if username}}<p class="rc-user-info__username">@{{username}}</p>{{/if}}
{{# userPresence uid=uid}}<span class="rc-header__status rc-user-info__status">
<div class="rc-header__status-bullet rc-header__status-bullet--{{userStatus}}" title="{{_ userStatus}}"></div>
Expand Down
4 changes: 4 additions & 0 deletions app/ui-flextab/client/tabs/userInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ Template.userInfo.helpers({
const user = Template.instance().user.get();
return user.bio && user.bio.trim();
},
nickname() {
const user = Template.instance().user.get();
return user.nickname?.trim();
},
bio() {
const user = Template.instance().user.get();
return Markdown.parse(user.bio);
Expand Down
11 changes: 8 additions & 3 deletions app/ui-message/client/popup/messagePopupConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ const fetchUsersFromServer = _.throttle(async (filterText, records, rid, cb) =>

users
.slice(0, 5)
.forEach(({ username, name, status, avatarETag }) => {
.forEach(({ username, nickname, name, status, avatarETag }) => {
if (records.length < 5) {
records.push({
_id: username,
username,
nickname,
name,
status,
avatarETag,
Expand Down Expand Up @@ -260,16 +261,18 @@ Template.messagePopupConfig.helpers({
{
fields: {
username: 1,
nickname: 1,
name: 1,
status: 1,
},
limit: 5 - usernamesAlreadyFetched.length,
},
)
.fetch()
.map(({ username, name, status }) => ({
.map(({ username, name, status, nickname }) => ({
_id: username,
username,
nickname,
name,
status,
sort: 1,
Expand Down Expand Up @@ -301,15 +304,17 @@ Template.messagePopupConfig.helpers({
{
fields: {
username: 1,
nickname: 1,
name: 1,
status: 1,
},
limit: 5 - usernamesAlreadyFetched.length,
})
.fetch()
.map(({ username, name, status }) => ({
.map(({ username, name, status, nickname }) => ({
_id: username,
username,
nickname,
name,
status,
sort: 1,
Expand Down
2 changes: 1 addition & 1 deletion app/ui-message/client/popup/messagePopupUser.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
<div class="popup-user-status border-transparent-dark popup-user-status-{{status}}"></div>
<div class="popup-user-avatar" style="background-image:url({{avatarUrlFromUsername username avatarETag}});"></div>
{{/unless}}
<strong>{{username}}</strong> {{name}}
<strong>{{username}}</strong> {{name}}{{#if nickname}} ({{nickname}}){{/if}}
</template>
4 changes: 2 additions & 2 deletions app/ui/client/components/popupList.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
{{>avatar username=item.username}}
</span>
{{#if showRealNames}}
<span class="rc-popup-list__item-name">{{item.name}} ({{{modifier item.username}}})</span>
<span class="rc-popup-list__item-name">{{{modifier item.name}}}{{#if item.nickname}} ({{{modifier item.nickname}}}){{/if}} ({{{modifier item.username}}})</span>
{{else}}
<span class="rc-popup-list__item-name">{{{modifier item.username}}}</span>
<span class="rc-popup-list__item-name">{{{modifier item.username}}}{{#if item.nickname}} ({{item.nickname}}){{/if}}</span>
{{/if}}
</li>
</template>
Expand Down
2 changes: 1 addition & 1 deletion app/ui/client/views/app/CreateDirectMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Template.CreateDirectMessage.helpers({
userModifier() {
return (filter, text = '') => {
const f = filter.get();
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get()), (part) => `<strong>${ part }</strong>`) }`;
return `@${ f.length === 0 ? text : text.replace(new RegExp(filter.get(), 'i'), (part) => `<strong>${ part }</strong>`) }`;
};
},
nameSuggestion() {
Expand Down
1 change: 1 addition & 0 deletions app/utils/server/functions/getDefaultUserFields.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const getDefaultUserFields = () => ({
name: 1,
username: 1,
nickname: 1,
emails: 1,
status: 1,
statusDefault: 1,
Expand Down
1 change: 1 addition & 0 deletions client/admin/users/AddUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function AddUser({ roles, ...props }) {
username: '',
statusText: '',
bio: '',
nickname: '',
email: '',
password: '',
verified: false,
Expand Down
1 change: 1 addition & 0 deletions client/admin/users/EditUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const getInitialValue = (data) => ({
username: data.username,
status: data.status,
bio: data.bio ?? '',
nickname: data.nickname ?? '',
email: (data.emails && data.emails[0].address) || '',
verified: (data.emails && data.emails[0].verified) || false,
setRandomPassword: false,
Expand Down
8 changes: 8 additions & 0 deletions client/admin/users/UserForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app
verified,
statusText,
bio,
nickname,
password,
setRandomPassword,
requirePasswordChange,
Expand All @@ -33,6 +34,7 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app
handleVerified,
handleStatusText,
handleBio,
handleNickname,
handlePassword,
handleSetRandomPassword,
handleRequirePasswordChange,
Expand Down Expand Up @@ -79,6 +81,12 @@ export default function UserForm({ formValues, formHandlers, availableRoles, app
<TextAreaInput rows={3} flexGrow={1} value={bio} onChange={handleBio} addon={<Icon name='edit' size='x20' alignSelf='center'/>}/>
</Field.Row>
</Field>, [bio, handleBio, t])}
{useMemo(() => <Field>
<Field.Label>{t('Nickname')}</Field.Label>
<Field.Row>
<TextInput flexGrow={1} value={nickname} onChange={handleNickname} addon={<Icon name='edit' size='x20' alignSelf='center'/>}/>
</Field.Row>
</Field>, [nickname, handleNickname, t])}
{useMemo(() => <Field>
<Field.Label>{t('Password')}</Field.Label>
<Field.Row>
Expand Down
Loading