summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
Diffstat (limited to 'webapp')
-rw-r--r--webapp/components/admin_console/ldap_settings.jsx21
-rw-r--r--webapp/components/admin_console/saml_settings.jsx21
-rw-r--r--webapp/components/user_profile.jsx17
-rw-r--r--webapp/components/user_settings/user_settings_general.jsx122
-rw-r--r--webapp/i18n/en.json9
-rw-r--r--webapp/utils/constants.jsx4
6 files changed, 193 insertions, 1 deletions
diff --git a/webapp/components/admin_console/ldap_settings.jsx b/webapp/components/admin_console/ldap_settings.jsx
index 5aa23fde6..b774d34f3 100644
--- a/webapp/components/admin_console/ldap_settings.jsx
+++ b/webapp/components/admin_console/ldap_settings.jsx
@@ -38,6 +38,7 @@ export default class LdapSettings extends AdminSettings {
config.LdapSettings.NicknameAttribute = this.state.nicknameAttribute;
config.LdapSettings.EmailAttribute = this.state.emailAttribute;
config.LdapSettings.UsernameAttribute = this.state.usernameAttribute;
+ config.LdapSettings.PositionAttribute = this.state.positionAttribute;
config.LdapSettings.IdAttribute = this.state.idAttribute;
config.LdapSettings.SyncIntervalMinutes = this.parseIntNonZero(this.state.syncIntervalMinutes);
config.LdapSettings.SkipCertificateVerification = this.state.skipCertificateVerification;
@@ -63,6 +64,7 @@ export default class LdapSettings extends AdminSettings {
nicknameAttribute: config.LdapSettings.NicknameAttribute,
emailAttribute: config.LdapSettings.EmailAttribute,
usernameAttribute: config.LdapSettings.UsernameAttribute,
+ positionAttribute: config.LdapSettings.PositionAttribute,
idAttribute: config.LdapSettings.IdAttribute,
syncIntervalMinutes: config.LdapSettings.SyncIntervalMinutes,
skipCertificateVerification: config.LdapSettings.SkipCertificateVerification,
@@ -300,6 +302,25 @@ export default class LdapSettings extends AdminSettings {
disabled={!this.state.enable}
/>
<TextSetting
+ id='positionAttribute'
+ label={
+ <FormattedMessage
+ id='admin.ldap.positionAttrTitle'
+ defaultMessage='Position Attribute:'
+ />
+ }
+ placeholder={Utils.localizeMessage('admin.ldap.positionAttrEx', 'E.g.: "title"')}
+ helpText={
+ <FormattedMessage
+ id='admin.ldap.positionAttrDesc'
+ defaultMessage='(Optional) The attribute in the AD/LDAP server that will be used to populate the position field in Mattermost.'
+ />
+ }
+ value={this.state.positionAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <TextSetting
id='emailAttribute'
label={
<FormattedMessage
diff --git a/webapp/components/admin_console/saml_settings.jsx b/webapp/components/admin_console/saml_settings.jsx
index c7cd73399..1391df0b6 100644
--- a/webapp/components/admin_console/saml_settings.jsx
+++ b/webapp/components/admin_console/saml_settings.jsx
@@ -41,6 +41,7 @@ export default class SamlSettings extends AdminSettings {
config.SamlSettings.EmailAttribute = this.state.emailAttribute;
config.SamlSettings.UsernameAttribute = this.state.usernameAttribute;
config.SamlSettings.NicknameAttribute = this.state.nicknameAttribute;
+ config.SamlSettings.PositionAttribute = this.state.positionAttribute;
config.SamlSettings.LocaleAttribute = this.state.localeAttribute;
config.SamlSettings.LoginButtonText = this.state.loginButtonText;
@@ -65,6 +66,7 @@ export default class SamlSettings extends AdminSettings {
emailAttribute: settings.EmailAttribute,
usernameAttribute: settings.UsernameAttribute,
nicknameAttribute: settings.NicknameAttribute,
+ positionAttribute: settings.PositionAttribute,
localeAttribute: settings.LocaleAttribute,
loginButtonText: settings.LoginButtonText
};
@@ -509,6 +511,25 @@ export default class SamlSettings extends AdminSettings {
disabled={!this.state.enable}
/>
<TextSetting
+ id='positionAttribute'
+ label={
+ <FormattedMessage
+ id='admin.saml.positionAttrTitle'
+ defaultMessage='Position Attribute:'
+ />
+ }
+ placeholder={Utils.localizeMessage('admin.saml.positionAttrEx', 'E.g.: "Role"')}
+ helpText={
+ <FormattedMessage
+ id='admin.saml.positionAttrDesc'
+ defaultMessage='(Optional) The attribute in the SAML Assertion that will be used to populate the position of users in Mattermost.'
+ />
+ }
+ value={this.state.positionAttribute}
+ onChange={this.handleChange}
+ disabled={!this.state.enable}
+ />
+ <TextSetting
id='localeAttribute'
label={
<FormattedMessage
diff --git a/webapp/components/user_profile.jsx b/webapp/components/user_profile.jsx
index 21dbf9699..9cf2464cd 100644
--- a/webapp/components/user_profile.jsx
+++ b/webapp/components/user_profile.jsx
@@ -182,6 +182,23 @@ export default class UserProfile extends React.Component {
dataContent.push(webrtc);
+ const position = this.props.user.position.substring(0, Constants.MAX_POSITION_LENGTH);
+ if (position) {
+ dataContent.push(
+ <div
+ data-toggle='tooltip'
+ title={position}
+ key='user-popover-position'
+ >
+ <p
+ className='text-nowrap'
+ >
+ {position}
+ </p>
+ </div>
+ );
+ }
+
if (global.window.mm_config.ShowEmailAddress === 'true' || UserStore.isSystemAdminForCurrentUser() || this.props.user === UserStore.getCurrentUser()) {
dataContent.push(
<div
diff --git a/webapp/components/user_settings/user_settings_general.jsx b/webapp/components/user_settings/user_settings_general.jsx
index b9db1389f..abc0e02f0 100644
--- a/webapp/components/user_settings/user_settings_general.jsx
+++ b/webapp/components/user_settings/user_settings_general.jsx
@@ -69,6 +69,10 @@ const holders = defineMessages({
close: {
id: 'user.settings.general.close',
defaultMessage: 'Close'
+ },
+ position: {
+ id: 'user.settings.general.position',
+ defaultMessage: 'Position'
}
});
@@ -85,6 +89,7 @@ class UserSettingsGeneralTab extends React.Component {
this.submitEmail = this.submitEmail.bind(this);
this.submitUser = this.submitUser.bind(this);
this.submitPicture = this.submitPicture.bind(this);
+ this.submitPosition = this.submitPosition.bind(this);
this.updateUsername = this.updateUsername.bind(this);
this.updateFirstName = this.updateFirstName.bind(this);
@@ -94,6 +99,7 @@ class UserSettingsGeneralTab extends React.Component {
this.updateConfirmEmail = this.updateConfirmEmail.bind(this);
this.updatePicture = this.updatePicture.bind(this);
this.updateSection = this.updateSection.bind(this);
+ this.updatePosition = this.updatePosition.bind(this);
this.state = this.setupInitialState(props);
}
@@ -249,6 +255,22 @@ class UserSettingsGeneralTab extends React.Component {
);
}
+ submitPosition(e) {
+ e.preventDefault();
+
+ const user = Object.assign({}, this.props.user);
+ const position = this.state.position.trim();
+
+ if (user.position === position) {
+ this.updateSection('');
+ return;
+ }
+
+ user.position = position;
+
+ this.submitUser(user, Constants.UserUpdateEvents.Position, false);
+ }
+
updateUsername(e) {
this.setState({username: e.target.value});
}
@@ -265,6 +287,10 @@ class UserSettingsGeneralTab extends React.Component {
this.setState({nickname: e.target.value});
}
+ updatePosition(e) {
+ this.setState({position: e.target.value});
+ }
+
updateEmail(e) {
this.setState({email: e.target.value});
}
@@ -302,6 +328,7 @@ class UserSettingsGeneralTab extends React.Component {
firstName: user.first_name,
lastName: user.last_name,
nickname: user.nickname,
+ position: user.position,
email: user.email,
confirmEmail: '',
picture: null,
@@ -936,6 +963,99 @@ class UserSettingsGeneralTab extends React.Component {
);
}
+ let positionSection;
+ if (this.props.activeSection === 'position') {
+ let extraInfo;
+ let submit = null;
+ if ((this.props.user.auth_service === 'ldap' || this.props.user.auth_service === Constants.SAML_SERVICE) && global.window.mm_config.PositionAttributeSet === 'true') {
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.field_handled_externally'
+ defaultMessage='This field is handled through your login provider. If you want to change it, you need to do so though your login provider.'
+ />
+ </span>
+ );
+ } else {
+ let positionLabel = (
+ <FormattedMessage
+ id='user.settings.general.position'
+ defaultMessage='Position'
+ />
+ );
+ if (Utils.isMobile()) {
+ positionLabel = '';
+ }
+
+ inputs.push(
+ <div
+ key='positionSetting'
+ className='form-group'
+ >
+ <label className='col-sm-5 control-label'>{positionLabel}</label>
+ <div className='col-sm-7'>
+ <input
+ className='form-control'
+ type='text'
+ onChange={this.updatePosition}
+ value={this.state.position}
+ maxLength={Constants.MAX_POSITION_LENGTH}
+ autoCapitalize='off'
+ />
+ </div>
+ </div>
+ );
+
+ extraInfo = (
+ <span>
+ <FormattedMessage
+ id='user.settings.general.positionExtra'
+ defaultMessage='Tell your teammates what you do.'
+ />
+ </span>
+ );
+
+ submit = this.submitPosition;
+ }
+
+ positionSection = (
+ <SettingItemMax
+ title={formatMessage(holders.position)}
+ inputs={inputs}
+ submit={submit}
+ server_error={serverError}
+ client_error={clientError}
+ updateSection={(e) => {
+ this.updateSection('');
+ e.preventDefault();
+ }}
+ extraInfo={extraInfo}
+ />
+ );
+ } else {
+ let describe = '';
+ if (user.position) {
+ describe = user.position;
+ } else {
+ describe = (
+ <FormattedMessage
+ id='user.settings.general.emptyPosition'
+ defaultMessage="Click 'Edit' to add your job title / position"
+ />
+ );
+ }
+
+ positionSection = (
+ <SettingItemMin
+ title={formatMessage(holders.position)}
+ describe={describe}
+ updateSection={() => {
+ this.updateSection('position');
+ }}
+ />
+ );
+ }
+
const emailSection = this.createEmailSection();
let pictureSection;
@@ -1030,6 +1150,8 @@ class UserSettingsGeneralTab extends React.Component {
<div className='divider-light'/>
{nicknameSection}
<div className='divider-light'/>
+ {positionSection}
+ <div className='divider-light'/>
{emailSection}
<div className='divider-light'/>
{pictureSection}
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index c7198817f..3658b40ae 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -441,6 +441,9 @@
"admin.ldap.portDesc": "The port Mattermost will use to connect to the AD/LDAP server. Default is 389.",
"admin.ldap.portEx": "E.g.: \"389\"",
"admin.ldap.portTitle": "AD/LDAP Port:",
+ "admin.ldap.positionAttrEx": "E.g.: \"title\"",
+ "admin.ldap.positionAttrDesc": "(Optional) The attribute in the AD/LDAP server that will be used to populate the position field in Mattermost.",
+ "admin.ldap.positionAttrTitle": "Position Attribute:",
"admin.ldap.queryDesc": "The timeout value for queries to the AD/LDAP server. Increase if you are getting timeout errors caused by a slow AD/LDAP server.",
"admin.ldap.queryEx": "E.g.: \"60\"",
"admin.ldap.queryTitle": "Query Timeout (seconds):",
@@ -614,6 +617,9 @@
"admin.saml.nicknameAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the nickname of users in Mattermost.",
"admin.saml.nicknameAttrEx": "E.g.: \"Nickname\"",
"admin.saml.nicknameAttrTitle": "Nickname Attribute:",
+ "admin.saml.positionAttrDesc": "(Optional) The attribute in the SAML Assertion that will be used to populate the position of users in Mattermost.",
+ "admin.saml.positionAttrEx": "E.g.: \"Role\"",
+ "admin.saml.positionAttrTitle": "Position Attribute:",
"admin.saml.privateKeyFileFileDesc": "The private key used to decrypt SAML Assertions from the Identity Provider.",
"admin.saml.privateKeyFileFileRemoveDesc": "Remove the private key used to decrypt SAML Assertions from the Identity Provider.",
"admin.saml.privateKeyFileTitle": "Service Provider Private Key:",
@@ -1953,6 +1959,7 @@
"user.settings.general.emailUnchanged": "Your new email address is the same as your old email address.",
"user.settings.general.emptyName": "Click 'Edit' to add your full name",
"user.settings.general.emptyNickname": "Click 'Edit' to add a nickname",
+ "user.settings.general.emptyPosition": "Click 'Edit' to add your job title / position",
"user.settings.general.field_handled_externally": "This field is handled through your login provider. If you want to change it, you need to do so through your login provider.",
"user.settings.general.firstName": "First Name",
"user.settings.general.fullName": "Full Name",
@@ -1969,6 +1976,8 @@
"user.settings.general.nicknameExtra": "Use Nickname for a name you might be called that is different from your first name and username. This is most often used when two or more people have similar sounding names and usernames.",
"user.settings.general.notificationsExtra": "By default, you will receive mention notifications when someone types your first name. Go to {notify} settings to change this default.",
"user.settings.general.notificationsLink": "Notifications",
+ "user.settings.general.position": "Position",
+ "user.settings.general.positionExtra": "Tell your teammates what you do.",
"user.settings.general.primaryEmail": "Primary Email",
"user.settings.general.profilePicture": "Profile Picture",
"user.settings.general.title": "General Settings",
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 1eac2732b..94fa19ea9 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -264,7 +264,8 @@ export const Constants = {
FULLNAME: 'fullname',
NICKNAME: 'nickname',
EMAIL: 'email',
- LANGUAGE: 'language'
+ LANGUAGE: 'language',
+ POSITION: 'position'
},
ScrollTypes: {
@@ -835,6 +836,7 @@ export const Constants = {
MAX_NICKNAME_LENGTH: 22,
MIN_PASSWORD_LENGTH: 5,
MAX_PASSWORD_LENGTH: 64,
+ MAX_POSITION_LENGTH: 35,
MIN_TRIGGER_LENGTH: 1,
MAX_TRIGGER_LENGTH: 128,
MAX_TEXTSETTING_LENGTH: 1024,