mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-08 04:03:12 +03:00
ffe5416b77
closes https://github.com/TryGhost/Team/issues/572 Role selection when inviting users was updated to show information about each staff role. This change updates the staff edit screen to use the same UI for changing the role of an existing user. - added `select-user-role` modal which uses `<GhRoleSelection>` to allow role selection - replaced the `<select>` input for changing a user's role with a button that triggers the role selection modal - role is not set unless the "Set role" button is clicked after making a selection, cancel or close will leave the original role selected
400 lines
23 KiB
Handlebars
400 lines
23 KiB
Handlebars
<section class="gh-canvas">
|
|
<GhCanvasHeader class="gh-canvas-header">
|
|
<h2 class="gh-canvas-title" data-test-screen-title>
|
|
<LinkTo @route="staff" data-test-staff-link={{true}}>Staff</LinkTo>
|
|
<span>{{svg-jar "arrow-right"}}</span>
|
|
{{this.user.name}}
|
|
|
|
{{#if this.user.isSuspended}}
|
|
<span class="gh-badge suspended" data-test-suspended-badge>Suspended</span>
|
|
{{/if}}
|
|
</h2>
|
|
|
|
{{#if this.showLeaveSettingsModal}}
|
|
<GhFullscreenModal @modal="leave-settings"
|
|
@confirm={{action "leaveSettings"}}
|
|
@close={{action "toggleLeaveSettingsModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
|
|
<section class="view-actions">
|
|
{{#if this.userActionsAreVisible}}
|
|
<span class="dropdown">
|
|
<GhDropdownButton @dropdownName="user-actions-menu" @classNames="gh-btn gh-btn-white gh-btn-icon only-has-icon user-actions-cog" @title="User Actions" data-test-user-actions={{true}}>
|
|
<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 {{action "toggleTransferOwnerModal"}}>
|
|
Make Owner
|
|
</button>
|
|
{{#if this.showTransferOwnerModal}}
|
|
<GhFullscreenModal @modal="transfer-owner"
|
|
@confirm={{action "transferOwnership"}}
|
|
@close={{action "toggleTransferOwnerModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
</li>
|
|
{{/if}}
|
|
{{#if this.deleteUserActionIsVisible}}
|
|
<li>
|
|
<button {{action "toggleDeleteUserModal"}} class="delete" data-test-delete-button>
|
|
Delete User
|
|
</button>
|
|
</li>
|
|
{{#if this.user.isActive}}
|
|
<li>
|
|
<button {{action "toggleSuspendUserModal"}} class="suspend" data-test-suspend-button>
|
|
Suspend User
|
|
</button>
|
|
</li>
|
|
{{/if}}
|
|
{{#if this.user.isSuspended}}
|
|
<li>
|
|
<button {{action "toggleUnsuspendUserModal"}} class="unsuspend" data-test-unsuspend-button>
|
|
Un-suspend User
|
|
</button>
|
|
</li>
|
|
{{/if}}
|
|
{{/if}}
|
|
</GhDropdown>
|
|
</span>
|
|
{{/if}}
|
|
|
|
<GhTaskButton @class="gh-btn gh-btn-primary gh-btn-icon" @task={{this.save}} data-test-save-button={{true}} />
|
|
|
|
{{#if this.showDeleteUserModal}}
|
|
<GhFullscreenModal @modal="delete-user"
|
|
@model={{this.user}}
|
|
@confirm={{action (perform this.deleteUser)}}
|
|
@close={{action "toggleDeleteUserModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
|
|
{{#if this.showSuspendUserModal}}
|
|
<GhFullscreenModal @modal="suspend-user"
|
|
@model={{this.user}}
|
|
@confirm={{action "suspendUser"}}
|
|
@close={{action "toggleSuspendUserModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
|
|
{{#if this.showUnsuspendUserModal}}
|
|
<GhFullscreenModal @modal="unsuspend-user"
|
|
@model={{this.user}}
|
|
@confirm={{action "unsuspendUser"}}
|
|
@close={{action "toggleUnsuspendUserModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
</section>
|
|
</GhCanvasHeader>
|
|
|
|
{{#if 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 class="user-profile" novalidate="novalidate" autocomplete="off" {{action (perform this.save) on="submit"}}>
|
|
|
|
<figure class="user-cover" style={{background-image-style this.user.coverImageUrl}}>
|
|
<button type="button" class="gh-btn gh-btn-default user-cover-edit" {{action "toggleUploadCoverModal"}}><span>Change Cover</span></button>
|
|
{{#if this.showUploadCoverModal}}
|
|
<GhFullscreenModal @modal="upload-image"
|
|
@model={{hash model=this.user imageProperty="coverImage"}}
|
|
@close={{action "toggleUploadCoverModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
</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" {{action "toggleUploadImageModal"}} class="edit-user-image">Edit Picture</button>
|
|
{{#if this.showUploadImageModal}}
|
|
<GhFullscreenModal @modal="upload-image"
|
|
@model={{hash model=this.user imageProperty="profileImage" paramsHash=(hash purpose="profile_image")}}
|
|
@close={{action "toggleUploadImageModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
</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>
|
|
<GhTextInput
|
|
@id="user-name"
|
|
@class="user-name"
|
|
@placeholder="Full Name"
|
|
@autocorrect="off"
|
|
@value={{readonly this.user.name}}
|
|
@input={{action (mut this.user.name) value="target.value"}}
|
|
@focus-out={{action "validate" "name" target=this.user}}
|
|
data-test-name-input={{true}}
|
|
/>
|
|
{{#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 recognise you</p>
|
|
{{/if}}
|
|
</GhFormGroup>
|
|
|
|
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="slug">
|
|
<label for="user-slug">Slug</label>
|
|
<GhTextInput
|
|
@class="user-name"
|
|
@id="user-slug"
|
|
@name="user"
|
|
@placeholder="Slug"
|
|
@selectOnClick="true"
|
|
@autocorrect="off"
|
|
@value={{readonly this.slugValue}}
|
|
@input={{action (mut this.slugValue) value="target.value"}}
|
|
@focus-out={{action (perform this.updateSlug this.slugValue)}}
|
|
data-test-slug-input={{true}}
|
|
/>
|
|
<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}}
|
|
<GhTextInput
|
|
@type="email"
|
|
@id="user-email"
|
|
@name="email"
|
|
@placeholder="Email Address"
|
|
@autocapitalize="off"
|
|
@autocorrect="off"
|
|
@autocomplete="off"
|
|
@value={{readonly this.user.email}}
|
|
@input={{action (mut this.user.email) value="target.value"}}
|
|
@focus-out={{action "validate" "email" target=this.user}}
|
|
data-test-email-input={{true}}
|
|
/>
|
|
<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>
|
|
<div class="gh-input pointer" {{on "click" (action "toggleRoleSelectionModal")}}>{{this.user.role.name}}</div>
|
|
<p>What permissions should this user have?</p>
|
|
</div>
|
|
|
|
{{#if this.showRoleSelectionModal}}
|
|
<GhFullscreenModal
|
|
@modal="select-user-role"
|
|
@model={{readonly this.user.role}}
|
|
@confirm={{action "changeRole"}}
|
|
@close={{action "toggleRoleSelectionModal"}}
|
|
/>
|
|
{{/if}}
|
|
{{/if}}
|
|
|
|
<GhFormGroup @errors={{this.user.errors}} @hasValidated={{this.user.hasValidated}} @property="location">
|
|
<label for="user-location">Location</label>
|
|
<GhTextInput
|
|
@id="user-location"
|
|
@value={{readonly this.user.location}}
|
|
@input={{action (mut this.user.location) value="target.value"}}
|
|
@focus-out={{action "validate" "location" target=this.user}}
|
|
data-test-location-input={{true}} />
|
|
<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>
|
|
<GhTextInput
|
|
@type="url"
|
|
@id="user-website"
|
|
@autocapitalize="off"
|
|
@autocorrect="off"
|
|
@autocomplete="off"
|
|
@value={{readonly this.user.website}}
|
|
@input={{action (mut this.user.website) value="target.value"}}
|
|
@focus-out={{action "validate" "website" target=this.user}}
|
|
data-test-website-input={{true}} />
|
|
<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>
|
|
<GhTextInput
|
|
@type="url"
|
|
@placeholder="https://www.facebook.com/username"
|
|
@autocorrect="off"
|
|
@id="user-facebook"
|
|
@name="user[facebook]"
|
|
@value={{readonly this.user.facebook}}
|
|
@input={{action (mut this._scratchFacebook) value="target.value"}}
|
|
@focus-out={{action "validateFacebookUrl"}}
|
|
data-test-facebook-input={{true}}
|
|
/>
|
|
<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>
|
|
<GhTextInput
|
|
@type="url"
|
|
@placeholder="https://twitter.com/username"
|
|
@autocorrect="off"
|
|
@id="user-twitter"
|
|
@name="user[twitter]"
|
|
@value={{readonly this.user.twitter}}
|
|
@input={{action (mut this._scratchTwitter) value="target.value"}}
|
|
@focus-out={{action "validateTwitterUrl"}}
|
|
data-test-twitter-input={{true}}
|
|
/>
|
|
<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>
|
|
<GhTextarea
|
|
@id="user-bio"
|
|
@value={{readonly this.user.bio}}
|
|
@input={{action (mut this.user.bio) value="target.value"}}
|
|
@focus-out={{action "validate" "bio" target=this.user}}
|
|
data-test-bio-input={{true}}
|
|
/>
|
|
<GhErrorMessage @errors={{this.user.errors}} @property="bio" data-test-error="user-bio" />
|
|
<p>
|
|
Write about you, in 200 characters or less.
|
|
{{gh-count-characters this.user.bio}}
|
|
</p>
|
|
</GhFormGroup>
|
|
|
|
</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" {{action (perform this.user.saveNewPassword) on="submit"}}>
|
|
<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>
|
|
<GhTextInput
|
|
@type="password"
|
|
@id="user-password-old"
|
|
@autocomplete="current-password"
|
|
@value={{readonly this.user.password}}
|
|
@input={{action "updatePassword" value="target.value"}}
|
|
@keyEvents={{hash
|
|
Enter=(action (perform this.user.saveNewPassword))
|
|
}}
|
|
data-test-old-pass-input={{true}}
|
|
/>
|
|
<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>
|
|
<GhTextInput
|
|
@value={{readonly this.user.newPassword}}
|
|
@type="password"
|
|
@autocomplete="new-password"
|
|
@id="user-password-new"
|
|
@input={{action "updateNewPassword" value="target.value"}}
|
|
@keyEvents={{hash
|
|
Enter=(action (perform this.user.saveNewPassword))
|
|
}}
|
|
data-test-new-pass-input={{true}}
|
|
/>
|
|
<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>
|
|
<GhTextInput
|
|
@value={{readonly this.user.ne2Password}}
|
|
@type="password"
|
|
@id="user-new-password-verification"
|
|
@input={{action "updateNe2Password" value="target.value"}}
|
|
@keyEvents={{hash
|
|
Enter=(action (perform this.user.saveNewPassword))
|
|
}}
|
|
data-test-ne2-pass-input={{true}}
|
|
/>
|
|
<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.user.saveNewPassword}} 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.copyContentKey.isRunning "hide-child-instant"}}">
|
|
<GhTextInput
|
|
@id="personal-token"
|
|
@value={{readonly this.personalToken}}
|
|
@readonly
|
|
@type="text"
|
|
onclick="this.select()"
|
|
/>
|
|
<div class="app-api-personal-token-buttons child">
|
|
<button type="button" {{action "confirmRegenerateTokenModal"}} class="app-button-regenerate" data-tooltip="Regenerate">
|
|
{{svg-jar "reload" class="w4 h4 stroke-midgrey"}}
|
|
</button>
|
|
<button type="button" {{action (perform this.copyContentKey)}} class="app-button-copy">
|
|
{{#if this.copyContentKey.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}}
|
|
{{#if this.showRegenerateTokenModal}}
|
|
<GhFullscreenModal @modal="regenerate-token"
|
|
@confirm={{action "regenerateToken"}}
|
|
@close={{action "cancelRegenerateTokenModal"}}
|
|
@modifier="action wide" />
|
|
{{/if}}
|
|
|
|
</GhFormGroup>
|
|
</fieldset>
|
|
</div>
|
|
</form>
|
|
{{/if}}
|
|
</div>
|
|
</section>
|
|
</section>
|