scripts/apps/users/views/edit-form.html
<form ng-if="!loading" name="userForm" data-test-id="user-details-form">
<div>
<div class="action-bar" ng-class="{show:dirty}" data-test-id="action-bar">
<div class="button-group button-group--end button-group--comfort">
<button id="cancel-edit-btn" type="button" class="btn" ng-click="cancel()" ng-disabled="!dirty" translate data-test-id="cancel">Cancel</button>
<button id="save-edit-btn" type="submit" class="btn btn--primary" ng-click="userForm.$valid && save()" ng-disabled="userForm.$invalid || !dirty" translate data-test-id="save">Save</button>
</div>
</div>
<div class="profile-info editmode">
<div class="profile-info__navigation">
<nav class="sd-left-nav sd-left-nav--blanc sd-width--xxx-small sd-margin-t--3">
<button class="sd-left-nav__btn" ng-class="{'sd-left-nav__btn--active': !activeNavigation || checkNavigation('user-general')}" ng-click="goTo('user-general')" translate>General</button>
<button class="sd-left-nav__btn" ng-class="{'sd-left-nav__btn--active': checkNavigation('user-password')}" ng-click="goTo('user-password')" translate>Password</button>
<button class="sd-left-nav__btn" ng-class="{'sd-left-nav__btn--active': checkNavigation('user-desk')}" ng-click="goTo('user-desk')" translate>Default desk</button>
<button class="sd-left-nav__btn" ng-class="{'sd-left-nav__btn--active': checkNavigation('user-language')}" ng-click="goTo('user-language')" translate>Language</button>
<button class="sd-left-nav__btn" ng-class="{'sd-left-nav__btn--active': checkNavigation('authorDetails')}" ng-click="goTo('authorDetails')" ng-show="user.is_author" translate>Author info</button>
</nav>
</div>
<div class="profile-info__content">
<!-- General content -->
<div class="details-info">
<div
id="user-general"
class="sd-container sd-container--flex sd-container--gap-none sd-container--direction-column sd-radius--medium sd-panel-bg--gradient-1 sd-shadow--z2 sd-padding--3 sd-state--focus sd-margin-b--3"
>
<div class="header-info">
<div class="sd-container sd-container--flex">
<span class="sd-margin-e--auto">
<span class="label label--translucent label--alert" ng-if="user._id && !user.is_enabled" translate>disabled</span>
<span class="label label--translucent label--warning" ng-if="user._id && user.is_enabled && !user.is_active" translate>inactive</span>
<span class="label label--translucent label--success" ng-if="user._id && user.is_enabled && user.is_active" translate>active</span>
</span>
<div class="active"
ng-show="user.is_enabled"
ng-if="!profile && user._id && !dirty"
sd-tooltip="{{ _active ? 'Deactivate user' : 'Activate user' | translate }}"
flow="left">
<span sd-switch ng-model="user.is_active" ng-click="toggleStatus(user.is_active)"></span>
</div>
</div>
<div class="profile-pic">
<sd-user-avatar data-user="userImmutable" data-size="'xx-large'"></sd-user-avatar>
<div class="profile-pic__change">
<button
ng-if="canChangeAvatar"
class="icn-btn"
aria-label="{{'Change avatar' | translate }}"
ng-click="editPicture()">
<i class="icon-photo" aria-label="edit" aria-hidden="true"></i>
</button>
</div>
</div>
<h2>{{ user.display_name}}</h2>
<h5>{{ user.username}}</h5>
<div class="field__member_since sd-text sd-text--normal sd-text-align--center sd-text--sans sd-text-color--light sd-margin-b--1-5 sd-font-size--small" sd-info-item ng-show="user._id">
<span for="created" translate>Member since</span>
<span id="created" class="info-value date-time" sd-reldate datetime="user._created"></span>
</div>
<div class="button-group button-group--center button-group--compact sd-margin-b--2 sd-flex--wrap sd-flex--justify-center">
<div class="tag-label" ng-if="roles[user.role]" translate>{{roles[user.role].name}}</div>
<div class="tag-label" ng-show="user.is_author" translate>Author</div>
<div class="tag-label tag-label--highlight1" ng-show="user.user_type == 'administrator'" translate>Administrator</div>
</div>
</div>
<div class="field__full_name form__group form__group--default form__group--mb-3" sd-info-item ng-show="user._id">
<div class="form__item">
<div class="sd-input sd-input--disabled">
<label class="sd-input__label" for="display-name" translate>full name</label>
<input class="sd-input__input" type="text" name="fullName" id="display-name" ng-model="user.display_name" disabled>
</div>
</div>
</div>
<div class="field__first_name form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input sd-input--required">
<label class="sd-input__label" for="first-name" translate>first name</label>
<input class="sd-input__input" type="text" name="first_name" id="first-name" ng-model="user.first_name" required ng-readonly="user._readonly && user._readonly.first_name" data-test-id="field--first_name">
<div class="sd-input__message-box">
<div ng-show="userForm.first_name.$error.required" class="sd-input__message" translate>This field is required.</div>
</div>
</div>
</div>
</div>
<div class="field__last_name form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input sd-input--required">
<label class="sd-input__label" for="last-name" translate>last name</label>
<input class="sd-input__input" type="text" name="last_name" id="last-name" ng-model="user.last_name" required ng-readonly="user._readonly && user._readonly.last_name" data-test-id="field--last_name">
<div class="sd-input__message-box">
<div class="sd-input__message" ng-show="userForm.last_name.$error.required" translate>This field is required.</div>
</div>
</div>
</div>
</div>
<div class="field__username form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input sd-input--required">
<label class="sd-input__label" for="username" translate>username</label>
<input class="sd-input__input" type="text" name="username" id="username"
ng-model="user.username"
ng-model-options="{
updateOn: 'default blur',
debounce: {'default': 500, 'blur': 0} }"
ng-readonly="user._id"
ng-pattern="usernamePattern"
sd-user-unique data-unique-field="username" data-exclude="user"
required
data-test-id="field--username">
<div class="sd-input__message-box">
<div class="sd-input__message" ng-show="userForm.username.$error.required" translate>This field is required.</div>
<div class="sd-input__message" ng-show="userForm.username.$error.unique || error.username.conflict" sd-valid-error translate>sorry, this username is already taken.</div>
<div class="sd-input__message" ng-show="userForm.username.$error.pattern" sd-valid-info>
<i class="icon-info-sign-warning"></i>
<span translate>please use only letters (a-z), numbers (0-9), dashes (—), underscores (_), apostrophes (') and periods (.)</span>
</div>
</div>
</div>
</div>
</div>
<div class="field__email form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input sd-input--required">
<label class="sd-input__label" for="email" translate>email</label>
<input class="sd-input__input" type="email" name="email" id="email"
ng-model="user.email"
sd-user-unique data-unique-field="email" data-exclude="user"
ng-readonly="user._readonly && user._readonly.email"
required
data-test-id="field--email">
<div class="sd-input__message-box">
<div class="sd-input__message" ng-show="userForm.email.$error.required" translate>This field is required.</div>
<div class="sd-input__message" ng-show="userForm.email.$error.email" sd-valid-info>
<i class="icon-info-sign-warning"></i>
<span translate>please provide a valid email address</span>
</div>
<div class="sd-input__message" ng-show="error.email" sd-valid-info>
<i class="icon-info-sign-warning"></i>
<span translate>{{error.email}}</span>
</div>
<div class="sd-input__message" ng-show="userForm.email.$error.unique || error.email.unique" sd-valid-error translate>sorry, a user with this email already exists</div>
</div>
</div>
</div>
</div>
<div class="user_role field__role form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input sd-input--is-select">
<label class="sd-input__label" for="user_role" translate>Role</label>
<select class="sd-input__select"
ng-focus="focused()"
ng-disabled="!privileges.users"
ng-model="user.role"
name="user_role"
id="user_role"
ng-options="role._id as role.name for role in roles">
</select>
</div>
</div>
</div>
<div sd-info-item class="user_type sd-check__group-new sd-check__group-new--vertical" ng-if="privileges.users && isNetworkSubscription()" style="margin-bottom: 20px;">
<sd-check ng-true-value="administrator" ng-false-value="user" ng-model="user.user_type" name="user_type" id="user_type">{{ :: 'Administrator'|translate }}</sd-check>
<sd-check ng-model="user.is_author" name="user_author" id="user_author">{{ :: 'Author'|translate }}</sd-check>
<sd-check ng-if="user.is_author" ng-model="user.private" name="user_private" id="user_private">{{'Private' | translate }}</sd-check>
</div>
<div class="field__phone_number form__group form__group--default form__group--mb-3" sd-info-item ng-hide="profileConfig.phone === false">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="phone" translate>phone number</label>
<input class="sd-input__input" type="text" name="phone" id="phone" ng-model="user.phone">
</div>
</div>
</div>
<div class="form__group form__group--default form__group--mb-3" ng-hide="profileConfig.jid === false || !xmppEnabled">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="jid" translate>Jabber Identifier (JID)</label>
<input class="sd-input__input" type="text" name="jid" id="jid" ng-model="user.jid">
</div>
</div>
</div>
<div class="form__group form__group--default form__group--mb-3" ng-hide="!$root.config.features.slackNotifications">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="slack_username">Slack Username</label>
<input class="sd-input__input" type="text" name="slack_username" id="slack_username" ng-model="user.slack_username">
<div class="sd-input__message-box">
<span class="sd-input__hint" translate>Your Slack user name without the leading @</span>
</div>
</div>
</div>
</div>
</div>
<h3 id="user-password" class="sd-heading sd-text-align--left sd-text--sans sd-heading--h3 sd-margin-b--0-5" translate>Password</h3>
<div class="sd-container sd-container--flex sd-container--gap-none sd-container--direction-column sd-radius--medium sd-panel-bg--000 sd-shadow--z2 sd-padding--3 sd-state--focus sd-margin-b--3">
<div sd-info-item class="password button-group button-group--center button-group--comfort" ng-if="features.reset_user_password && user._id && !profile && user.is_enabled && _active" id="password-reset-trigger">
<span class="change-btn btn btn--hollow btn--primary" ng-click="show.reset_password = !show.reset_password" ng-show="!show.reset_password" translate>reset password</span>
</div>
<div sd-info-item class="password button-group button-group--center button-group--comfort" ng-if="features.reset_user_password && user._id && profile" id="password-change-trigger">
<span class="change-btn btn btn--hollow btn--primary" ng-click="show.change_password = !show.change_password" ng-show="!show.change_password" translate>change password</span>
</div>
</div>
<h3 id="user-desk" class="sd-heading sd-text-align--left sd-text--sans sd-heading--h3 sd-margin-b--0-5" translate>Default desk</h3>
<div class="sd-container sd-container--flex sd-container--gap-none sd-container--direction-column sd-radius--medium sd-panel-bg--000 sd-shadow--z2 sd-padding--3 sd-state--focus sd-margin-b--3">
<div sd-info-item class="form__group form__group--default form__group--mb-0 form__group--inline-label" ng-if="userDesks && userDesks.length > 0">
<div class="form__item">
<div class="sd-input sd-input--is-select">
<label class="sd-input__label a11y-only" for="user_default_desk" translate>Default Desk</label>
<select class="sd-input__select" ng-model="user.desk" name="user_default_desk" id="user_default_desk" ng-options="desk._id as desk.name for desk in userDesks">
<option value="" ng-click="user.desk = null" translate>No desk selected</option>
</select>
</div>
</div>
</div>
</div>
<h3 id="user-language" class="sd-heading sd-text-align--left sd-text--sans sd-heading--h3 sd-margin-b--0-5" translate>Language</h3>
<div class="sd-container sd-container--flex sd-container--gap-none sd-container--direction-column sd-radius--medium sd-panel-bg--000 sd-shadow--z2 sd-padding--3 sd-state--focus sd-margin-b--3">
<div sd-info-item class="field__language form__group form__group--default form__group--mb-0 form__group--inline-label">
<div class="form__item">
<div class="sd-input sd-input--is-select">
<label class="sd-input__label a11y-only" for="user_language" translate>Language</label>
<select class="sd-input__select" ng-focus="focused()" ng-model="user.language" name="user_language" id="user_language" ng-options="lang.code as lang.nativeName for lang in languages"></select>
<div class="sd-input__message-box">
<div class="sd-input__hint">
<a href="https://www.transifex.com/projects/p/superdesk/" target="_blank">{{ :: "Help us translate Superdesk" | translate }}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- END General content -->
<!-- Author content -->
<div class="details-info" ng-show="user.is_author" id="authorDetails">
<h3 class="sd-heading sd-text-align--left sd-text--sans sd-heading--h3 sd-margin-b--0-5" translate>Author info</h3>
<div class="sd-container sd-container--flex sd-container--gap-none sd-container--direction-column sd-radius--medium sd-panel-bg--000 sd-shadow--z2 sd-padding--3 sd-state--focus sd-margin-b--4">
<div class="field__email form__group form__group--default form__group--mb-3" sd-info-item ng-if="!hideSignOff">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="sign_off" translate>Sign-Off</label>
<input class="sd-input__input" type="text" name="sign_off" id="sign_off" ng-model="user.sign_off" ng-pattern="signOffPattern">
<div class="sd-input__message-box">
<div class="sd-input__message" ng-show="userForm.sign_off.$error.pattern || error.sign_off" sd-valid-info>
<i class="icon-info-sign-warning"></i>
<span translate>Invalid format. Only Alphanumerics are allowed.</span>
</div>
</div>
</div>
</div>
</div>
<div class="field__email form__group form__group--default form__group--mb-3" sd-info-item>
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="byline" translate>Byline</label>
<input class="sd-input__input" type="text" name="byline" id="byline" ng-model="user.byline">
</div>
</div>
</div>
<div sd-info-item class="field__email form__group form__group--default form__group--mb-3" ng-if="privileges.users">
<div class="form__item">
<div class="sd-input" ng-disabled="!user.is_author">
<label class="sd-input__label" for="job_title" translate>Job Title</label>
<select class="sd-input__select" ng-focus="focused()" ng-model="user.job_title" name="job_title" id="job_title" ng-options="job.qcode as job.name for job in metadata.job_titles" ng-disabled="!user.is_author"></select>
</div>
</div>
</div>
<div sd-info-item class="field__email form__group form__group--default form__group--mb-3" ng-if="privileges.users">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="biography">{{ :: 'Biography'|translate }}</label>
<textarea class="sd-input__input" id="biography" sd-auto-height ng-model="user.biography" ng-disabled="!user.is_author"></textarea>
</div>
</div>
</div>
<div sd-info-item class="field__email form__group form__group--default form__group--mb-3" ng-if="privileges.users">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="facebook">{{ :: 'Facebook'|translate }}</label>
<input id="facebook"
type="text"
name="facebook"
class="sd-input__input"
ng-model="user.facebook"
ng-disabled="!user.is_author">
<div class="sd-input__message-box">
<div class="sd-input__hint">{{ :: 'e.g. superdeskman from https://www.facebook.com/superdeskman'|translate }}</div>
</div>
</div>
</div>
</div>
<div sd-info-item class="field__email form__group form__group--default form__group--mb-3" ng-if="privileges.users">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="instagram">{{ :: 'Instagram'|translate }}</label>
<input id="instagram"
type="text"
name="instagram"
class="sd-input__input"
ng-model="user.instagram"
ng-disabled="!user.is_author">
<div class="sd-input__message-box">
<div class="sd-input__hint">{{ :: 'e.g. superdeskman from https://www.instagram.com/superdeskman'|translate }}</div>
</div>
</div>
</div>
</div>
<div sd-info-item class="field__email form__group form__group--default form__group--mb-2" ng-if="privileges.users">
<div class="form__item">
<div class="sd-input">
<label class="sd-input__label" for="twitter">{{ :: 'Twitter'|translate }}</label>
<input id="twitter"
type="text"
name="twitter"
class="sd-input__input"
ng-model="user.twitter"
ng-disabled="!user.is_author"
ng-pattern="twitterPattern">
<div class="sd-input__message-box">
<div class="sd-input__hint">{{ :: 'e.g. @superdeskman'|translate }}</div>
<div class="sd-input__message" ng-show="userForm.twitter.$error.pattern" sd-valid-info>
<i class="icon-info-sign-warning"></i>
<span translate>Please provide a valid twitter account</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div><!-- END Author Tab content -->
</div>
</div>
</form>
<div sd-modal data-model="features.reset_user_password && show.reset_password && user._id" class="modal--tabs">
<div class="modal__header">
<button class="modal__close pull-right" ng-click="show.reset_password = false"><i class="icon-close-small"></i></button>
<h3 class="modal__heading">Reset password</h3>
</div>
<div class="modal__body" sd-reset-password>
<div class="modal__body-content">
<p translate>Do you want to reset the password for user {{user.full_name}} ?</p>
</div>
<div class="modal__body-footer">
<button class="btn" ng-click="show.reset_password = false">Cancel</button>
<button class="btn btn--primary" ng-click="resetPassword()">Reset password</button>
</div>
</div>
</div>
<div sd-modal data-model="features.reset_user_password && show.change_password && user._id" class="modal--tabs">
<div class="modal__header">
<button class="modal__close pull-right" ng-click="show.change_password = false"><i class="icon-close-small"></i></button>
<h3 class="modal__heading">Change password</h3>
</div>
<div class="modal__body" sd-change-password>
<div class="modal__body-content">
<form name="changePasswordForm">
<div class="content">
<div class="field">
<label translate>current</label>
<input name="old" type="password" ng-model="oldPwd" required>
<p sd-valid-error ng-show="oldPasswordInvalid">sorry, but this is not the original password.</p>
</div>
<div class="field">
<label translate>new</label>
<input sd-password-strength name="new" type="password" ng-model="newPwd" required>
</div>
<div class="field">
<label translate>confirm</label>
<input name="confirm" type="password" ng-model="_confirm" required
sd-password-confirm ng-model="_confirm" data-password="newPwd">
<p sd-valid-error ng-show="changePasswordForm.confirm.$error.confirm">confirm doesn't match new password yet.</p>
</div>
</div>
</form>
</div>
<div class="modal__body-footer">
<button class="btn" ng-click="show.change_password = false" translate>Cancel</button>
<button class="btn btn--primary"
ng-click="changePasswordForm.$valid && changePassword(oldPwd, newPwd)"
ng-disabled="changePasswordForm.$invalid"
translate>
Save password
</button>
</div>
</div>
</div>