Ghost/ghost/admin/app/templates/settings/staff/user.hbs
Rishabh Garg dc811af070
Merged mentions UI and email lab flags (#16518)
closes https://github.com/TryGhost/Team/issues/2851

We had two separate flags to manage the Mentions beta, one for showing
UI and other for sending emails. This change combines them both under
the single `webmentions` flag that was previously only used to show the
UI.
2023-03-29 01:12:56 +05:30

479 lines
29 KiB
Handlebars

<section class="gh-canvas" {{on-key "cmd+s" this.saveViaKeyboard}}>
<GhCanvasHeader class="gh-canvas-header">
{{!-- Remove breadcrumbs for Authors and Contributors --}}
{{#if this.currentUser.isAuthorOrContributor}}
<h2 class="gh-canvas-title" data-test-screen-title>Your profile</h2>
{{else}}
<div class="flex flex-column">
<div class="gh-canvas-breadcrumb" data-test-breadcrumb>
{{#unless this.session.user.isEditor}}
<LinkTo @route="settings">
Settings
</LinkTo>
{{svg-jar "arrow-right-small"}}
{{/unless}}
<LinkTo @route="settings.staff" data-test-staff-link={{true}}>
Staff
</LinkTo>
{{svg-jar "arrow-right-small"}} Profile
</div>
<h2 class="gh-canvas-title" data-test-screen-title>
{{this.user.name}}
{{#if this.user.isSuspended}}
<span class="gh-badge suspended" data-test-suspended-badge>Suspended</span>
{{/if}}
</h2>
</div>
{{/if}}
<section class="view-actions">
{{#if (or this.userActionsAreVisible this.session.user.isAdmin)}}
<span class="dropdown">
<GhDropdownButton @dropdownName="user-actions-menu" @classNames="gh-btn gh-btn-white gh-btn-icon icon-only user-actions-cog" @title="User Actions" data-test-user-actions>
<span>
{{svg-jar "settings"}}
<span class="hidden">User Settings</span>
</span>
</GhDropdownButton>
<GhDropdown @name="user-actions-menu" @tagName="ul" @classNames="user-actions-menu dropdown-menu dropdown-align-right">
{{#if this.canMakeOwner}}
<li>
<button type="button" {{on "click" this.transferOwnership}}>
Make owner
</button>
</li>
{{/if}}
{{#if this.deleteUserActionIsVisible}}
<li>
<button class="delete" data-test-delete-button type="button" {{on "click" this.deleteUser}}>
Delete user
</button>
</li>
{{#if this.user.isActive}}
<li>
<button class="suspend" data-test-suspend-button type="button" {{on "click" this.suspendUser}}>
Suspend user
</button>
</li>
{{/if}}
{{#if this.user.isSuspended}}
<li>
<button class="unsuspend" data-test-unsuspend-button type="button" {{on "click" this.unsuspendUser}}>
Un-suspend user
</button>
</li>
{{/if}}
{{/if}}
<li>
<LinkTo @route="settings.history" @query={{hash user=this.user.id}}>
<span>View user activity</span>
</LinkTo>
</li>
</GhDropdown>
</span>
{{/if}}
<GhTaskButton @class="gh-btn gh-btn-primary gh-btn-icon" @task={{this.saveTask}} data-test-save-button />
</section>
</GhCanvasHeader>
{{#if this.user.isLocked}}
<p class="gh-box gh-box-alert">{{svg-jar "info"}}This user account is locked. To sign in, ask this user to perform a password reset on their account.</p>
{{/if}}
{{!-- <div class="bg-"> --}}
<section>
<div class="gm-main view-container settings-user">
<form id="user-settings-form" class="user-profile" novalidate="novalidate" autocomplete="off" {{on "submit" (perform this.saveTask)}}>
<figure class="user-cover" style={{background-image-style this.user.coverImageUrl}}>
<button type="button" class="gh-btn gh-btn-default user-cover-edit" {{on "click" this.changeCoverImage}}><span>Change cover</span></button>
</figure>
<figure class="user-image bg-whitegrey">
<div id="user-image" class="img" style={{background-image-style this.user.profileImageUrl}}><span class="hidden">{{this.user.name}}"s picture</span></div>
<button type="button" class="edit-user-image" {{on "click" this.changeProfileImage}}>Edit picture</button>
</figure>
<div class="pa5">
<fieldset class="user-details-bottom">
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="name" class="first-form-group">
<label for="user-name">Full name</label>
<input
type="text"
id="user-name"
class="gh-input user-name"
autocorrect="off"
value={{this.user.name}}
{{on "input" (fn this.setModelProperty "name")}}
{{on "blur" (fn this.validateModelProperty "name")}}
data-test-name-input
/>
{{#if this.user.errors.name}}
<GhErrorMessage @errors={{this.user.errors}} @property="name" data-test-error="user-name" />
{{else}}
<p>Use your real name so people can recognize you</p>
{{/if}}
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="slug">
<label for="user-slug">Slug</label>
<input
type="text"
id="user-slug"
class="gh-input user-slug"
autocorrect="off"
value={{this.slugValue}}
{{on "input" this.setSlugValue}}
{{on "blur" (perform this.updateSlugTask)}}
{{select-on-click}}
data-test-slug-input
/>
<p><GhBlogUrl />/author/{{this.slugValue}}</p>
<GhErrorMessage @errors={{this.user.errors}} @property="slug" data-test-error="user-slug" />
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="email">
<label for="user-email">Email</label>
{{!-- Administrators only see text of Owner's email address but not input --}}
{{#if this.canChangeEmail}}
<input
type="email"
id="user-email"
class="gh-input"
placeholder="jamie@example.com"
autocapitalize="off"
autocorrect="off"
autocomplete="off"
value={{this.user.email}}
{{on "input" (fn this.setModelProperty "email")}}
{{on "blur" (fn this.validateModelProperty "email")}}
data-test-email-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="email" data-test-error="user-email" />
{{else}}
<span>{{this.user.email}}</span>
{{/if}}
<p>Used for notifications</p>
</GhFormGroup>
{{#if this.rolesDropdownIsVisible}}
<div class="form-group">
<label for="user-role">Role</label>
<button type="button" class="gh-input tl" {{on "click" this.selectRole}}>{{this.user.role.name}}{{svg-jar "arrow-down-small"}}</button>
<p>What permissions should this user have?</p>
</div>
{{/if}}
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="location">
<label for="user-location">Location</label>
<input
type="text"
id="user-location"
class="gh-input"
value={{this.user.location}}
{{on "input" (fn this.setModelProperty "location")}}
{{on "blur" (fn this.validateModelProperty "location")}}
data-test-location-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="location" data-test-error="user-location" />
<p>Where in the world do you live?</p>
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="website">
<label for="user-website">Website</label>
<input
type="url"
id="user-website"
class="gh-input"
autocapitalize="off"
autocorrect="off"
autocomplete="off"
value={{this.user.website}}
{{on "input" (fn this.setModelProperty "website")}}
{{on "blur" (fn this.validateModelProperty "website")}}
data-test-website-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="website" data-test-error="user-website" />
<p>Have a website or blog other than this one? Link it!</p>
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="facebook">
<label for="user-facebook">Facebook profile</label>
<GhFacebookUrlInput
id="user-facebook"
@scratchValue={{this.scratchValues.facebook}}
@setScratchValue={{fn this.setScratchValue "facebook"}}
@model={{this.user}}
@modelProperty="facebook"
/>
<GhErrorMessage @errors={{this.user.errors}} @property="facebook" data-test-error="user-facebook" />
<p>URL of your personal Facebook Profile</p>
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="twitter">
<label for="user-twitter">Twitter profile</label>
<GhTwitterUrlInput
id="user-twitter"
@scratchValue={{this.scratchValues.twitter}}
@setScratchValue={{fn this.setScratchValue "twitter"}}
@model={{this.user}}
@modelProperty="twitter"
/>
<GhErrorMessage @errors={{this.user.errors}} @property="twitter" data-test-error="user-twitter" />
<p>URL of your personal Twitter profile</p>
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="bio" class="bio-container">
<label for="user-bio">Bio</label>
<textarea
id="user-bio"
class="gh-input"
{{on "input" (fn this.setModelProperty "bio")}}
{{on "blur" (fn this.validateModelProperty "bio")}}
data-test-bio-input
>{{this.user.bio}}</textarea>
<GhErrorMessage @errors={{this.user.errors}} @property="bio" data-test-error="user-bio" />
<p>
Recommended: <strong>200</strong> characters.
You've used {{gh-count-down-characters this.user.bio 200}}
</p>
</GhFormGroup>
{{#if this.membersUtils.isMembersEnabled}}
<div class="user-settings-subgroup">
<h4 class="user-settings-heading">Email notifications</h4>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="email">
<div class="user-setting-toggle">
<div>
<label for="user-email">Comments</label>
<p>Every time a member comments on one of your posts</p>
</div>
<div class="for-switch small">
<label class="switch" for="comment-notifications">
<input
id="comment-notifications"
type="checkbox"
checked={{this.user.commentNotifications}}
class="gh-input"
{{on "change" this.toggleCommentNotifications}}
data-test-checkbox="comment-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
{{#if this.user.isAdmin}}
{{#if (feature 'webmentions')}}
<div class="user-setting-toggle">
<div>
<label for="user-email">Mentions</label>
<p>Every time another site links to your work.</p>
</div>
<div class="for-switch small">
<label class="switch" for="mention-notifications" data-test-label="mention-notifications">
<input
id="mention-notifications"
type="checkbox"
checked={{this.user.mentionNotifications}}
class="gh-input"
{{on "change" this.toggleMentionNotifications}}
data-test-checkbox="mention-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
{{/if}}
{{#if this.canToggleMemberAlerts}}
<div class="user-setting-toggle">
<div>
<label for="user-email">New signups</label>
<p>Every time a new free member signs up</p>
</div>
<div class="for-switch small">
<label class="switch" for="free-signup-notifications" data-test-label="free-signup-notifications">
<input
id="free-signup-notifications"
type="checkbox"
checked={{this.user.freeMemberSignupNotification}}
class="gh-input"
{{on "change" (fn this.toggleMemberEmailAlerts 'free-signup')}}
data-test-checkbox="free-signup-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
{{#if this.membersUtils.paidMembersEnabled}}
<div class="user-setting-toggle">
<div>
<label for="user-email">New paid members</label>
<p>Every time a member starts a new paid subscription</p>
</div>
<div class="for-switch small">
<label class="switch" for="paid-started-notifications" data-test-label="paid-started-notifications">
<input
id="paid-started-notifications"
type="checkbox"
checked={{this.user.paidSubscriptionStartedNotification}}
class="gh-input"
{{on "change" (fn this.toggleMemberEmailAlerts 'paid-started')}}
data-test-checkbox="paid-started-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
<div class="user-setting-toggle">
<div>
<label for="user-email">Paid member cancellations</label>
<p>Every time a member cancels their paid subscription</p>
</div>
<div class="for-switch small">
<label class="switch" for="paid-canceled-notifications" data-test-label="paid-canceled-notifications">
<input
id="paid-canceled-notifications"
type="checkbox"
checked={{this.user.paidSubscriptionCanceledNotification}}
class="gh-input"
{{on "change" (fn this.toggleMemberEmailAlerts 'paid-canceled')}}
data-test-checkbox="paid-canceled-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
{{/if}}
<div class="user-setting-toggle">
<div>
<label for="user-email">Milestones</label>
<p>Occasional summaries of your audience & revenue growth</p>
</div>
<div class="for-switch small">
<label class="switch" for="milestone-notifications" data-test-label="milestone-notifications">
<input
id="milestone-notifications"
type="checkbox"
checked={{this.user.milestoneNotifications}}
class="gh-input"
{{on "change" this.toggleMilestoneNotifications}}
data-test-checkbox="milestone-notifications"
>
<span class="input-toggle-component"></span>
</label>
</div>
</div>
{{/if}}
{{/if}}
</GhFormGroup>
</div>
{{/if}}
</fieldset>
</div>
</form> {{! user details form }}
{{!-- If an administrator is viewing Owner's profile then hide inputs for change password --}}
{{#if this.canChangePassword}}
<form id="password-reset" class="user-profile" novalidate="novalidate" autocomplete="off" {{on "submit" this.submitPasswordForm}}>
<div class="pa5">
<fieldset class="user-details-form">
{{#if this.isOwnProfile}}
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="password">
<label for="user-password-old">Old password</label>
<input
type="password"
id="user-password-old"
class="gh-input"
autocomplete="current-password"
value={{this.user.password}}
{{on "input" (fn this.setModelProperty "password")}}
{{on "input" (fn this.clearModelErrors "password")}}
data-test-old-pass-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="password" data-test-error="user-old-pass" />
</GhFormGroup>
{{/if}}
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="newPassword">
<label for="user-password-new">New password</label>
<input
type="password"
id="user-password-new"
class="gh-input"
autocomplete="new-password"
value={{this.user.newPassword}}
{{on "input" (fn this.setModelProperty "newPassword")}}
{{on "input" (fn this.clearModelErrors "newPassword")}}
data-test-new-pass-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="newPassword" data-test-error="user-new-pass" />
</GhFormGroup>
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="ne2Password">
<label for="user-new-password-verification">Verify password</label>
<input
type="password"
id="user-new-password-verification"
class="gh-input"
value={{this.user.ne2Password}}
{{on "input" (fn this.setModelProperty "ne2Password")}}
{{on "input" (fn this.clearModelErrors "ne2Password")}}
data-test-ne2-pass-input
/>
<GhErrorMessage @errors={{this.user.errors}} @property="ne2Password" data-test-error="user-ne2-pass" />
</GhFormGroup>
<div class="form-group">
<GhTaskButton @buttonText="Change Password" @idleClass="gh-btn-red" @class="gh-btn gh-btn-icon button-change-password" @task={{this.saveNewPasswordTask}} data-test-save-pw-button="true" />
</div>
</fieldset>
</div>
</form> {{! change password form }}
{{/if}}
{{#if this.isOwnProfile}}
<form class="user-profile">
<div class="pa5">
<fieldset class="user-details-form">
<GhFormGroup>
<label for="personal-token">Staff access token</label>
<div class="relative flex items-center {{unless this.copyContentKeyTask.isRunning "hide-child-instant"}}">
<input
type="text"
id="personal-token"
class="gh-input"
value={{this.personalToken}}
readonly
{{select-on-click}}
/>
<div class="app-api-personal-token-buttons child">
<button type="button" class="app-button-regenerate" {{on "click" this.regenerateStaffToken}} data-tooltip="Regenerate">
{{svg-jar "reload" class="w4 h4 stroke-midgrey"}}
</button>
<button type="button" class="app-button-copy" {{on "click" (perform this.copyContentKeyTask)}}>
{{#if this.copyContentKeyTask.isRunning}}
{{svg-jar "check-circle" class="w3 v-mid mr2 stroke-white"}} Copied
{{else}}
Copy
{{/if}}
</button>
</div>
</div>
<p>
Give apps personal access without sharing your email/password.
</p>
{{#if this.personalTokenRegenerated}}
<p class="green">Staff access token was successfully regenerated </p>
{{/if}}
</GhFormGroup>
</fieldset>
</div>
</form>
{{/if}}
</div>
</section>
</section>