Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Settings: new user row replaced by a modal #23529

Merged
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
4 changes: 2 additions & 2 deletions apps/settings/js/vue-settings-apps-users-management.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-settings-apps-users-management.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions apps/settings/js/vue-settings-personal-security.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-settings-personal-security.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions apps/settings/js/vue-settings-personal-webauthn.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-settings-personal-webauthn.js.map

Large diffs are not rendered by default.

25 changes: 0 additions & 25 deletions apps/settings/js/vue-settings-users-7f0d417cf48420602b07.js

This file was deleted.

This file was deleted.

25 changes: 25 additions & 0 deletions apps/settings/js/vue-settings-users-8cc954c720339a69daa7.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

239 changes: 130 additions & 109 deletions apps/settings/src/components/UserList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,12 @@

<template>
<div id="app-content" class="user-list-grid" @scroll.passive="onScroll">
<form v-show="showConfig.showNewUserForm"
id="new-user"
:class="{'sticky': scrolled && showConfig.showNewUserForm}"
:disabled="loading.all"
class="row"
@submit.prevent="createUser">
<div :class="loading.all?'icon-loading-small':'icon-add'" />
<div class="name">
<Modal v-if="showConfig.showNewUserForm" @close="closeModal">
<form id="new-user"
:disabled="loading.all"
class="modal__content"
@submit.prevent="createUser">
<h2>{{ t('settings','New user') }}</h2>
<input id="newusername"
ref="newusername"
v-model="newUser.id"
Expand All @@ -40,22 +38,20 @@
autocapitalize="none"
autocomplete="off"
autocorrect="off"
class="modal__item"
name="username"
pattern="[a-zA-Z0-9 _\.@\-']+"
required
type="text">
<div class="displayName">
<input id="newdisplayname"
v-model="newUser.displayName"
:placeholder="t('settings', 'Display name')"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
name="displayname"
type="text">
</div>
</div>
<div class="password">
<input id="newdisplayname"
v-model="newUser.displayName"
:placeholder="t('settings', 'Display name')"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
class="modal__item"
name="displayname"
type="text">
<input id="newuserpassword"
ref="newuserpassword"
v-model="newUser.password"
Expand All @@ -65,102 +61,96 @@
autocapitalize="none"
autocomplete="new-password"
autocorrect="off"
class="modal__item"
name="password"
type="password">
</div>
<div class="mailAddress">
<input id="newemail"
v-model="newUser.mailAddress"
:placeholder="t('settings', 'Email')"
:required="newUser.password==='' || settings.newUserRequireEmail"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
class="modal__item"
name="email"
type="email">
</div>
<div class="groups">
<!-- hidden input trick for vanilla html5 form validation -->
<input v-if="!settings.isAdmin"
id="newgroups"
:class="{'icon-loading-small': loading.groups}"
:required="!settings.isAdmin"
:value="newUser.groups"
tabindex="-1"
type="text">
<Multiselect v-model="newUser.groups"
:close-on-select="false"
:disabled="loading.groups||loading.all"
:multiple="true"
:options="canAddGroups"
:placeholder="t('settings', 'Add user to group')"
:tag-width="60"
:taggable="true"
class="multiselect-vue"
label="name"
tag-placeholder="create"
track-by="id"
@tag="createGroup">
<!-- If user is not admin, he is a subadmin.
Subadmins can't create users outside their groups
Therefore, empty select is forbidden -->
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</Multiselect>
</div>
<div v-if="subAdminsGroups.length>0 && settings.isAdmin"
class="subadmins">
<Multiselect v-model="newUser.subAdminsGroups"
:close-on-select="false"
:multiple="true"
:options="subAdminsGroups"
:placeholder="t('settings', 'Set user as admin for')"
:tag-width="60"
class="multiselect-vue"
label="name"
track-by="id">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</Multiselect>
</div>
<div class="quota">
<Multiselect v-model="newUser.quota"
:allow-empty="false"
:options="quotaOptions"
:placeholder="t('settings', 'Select user quota')"
:taggable="true"
class="multiselect-vue"
label="label"
track-by="id"
@tag="validateQuota" />
</div>
<div v-if="showConfig.showLanguages" class="languages">
<Multiselect v-model="newUser.language"
:allow-empty="false"
:options="languages"
:placeholder="t('settings', 'Default language')"
class="multiselect-vue"
group-label="label"
group-values="languages"
label="name"
track-by="code" />
</div>
<div v-if="showConfig.showStoragePath" class="storageLocation" />
<div v-if="showConfig.showUserBackend" class="userBackend" />
<div v-if="showConfig.showLastLogin" class="lastLogin" />
<div class="userActions">
<input id="newsubmit"
:title="t('settings', 'Add a new user')"
class="button primary icon-checkmark-white has-tooltip"
type="submit"
value="">
<div class="closeButton">
<Actions>
<ActionButton icon="icon-close" @click="onClose">
{{ t('settings', 'Close') }}
</ActionButton>
</Actions>
<div class="groups modal__item">
<!-- hidden input trick for vanilla html5 form validation -->
<input v-if="!settings.isAdmin"
id="newgroups"
:class="{'icon-loading-small': loading.groups}"
:required="!settings.isAdmin"
:value="newUser.groups"
tabindex="-1"
type="text">
<Multiselect v-model="newUser.groups"
:close-on-select="false"
:disabled="loading.groups||loading.all"
:multiple="true"
:options="canAddGroups"
:placeholder="t('settings', 'Add user to group')"
:tag-width="60"
:taggable="true"
class="multiselect-vue"
label="name"
tag-placeholder="create"
track-by="id"
@tag="createGroup">
<!-- If user is not admin, he is a subadmin.
Subadmins can't create users outside their groups
Therefore, empty select is forbidden -->
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</Multiselect>
</div>
</div>
</form>
<div v-if="subAdminsGroups.length>0 && settings.isAdmin"
class="subadmins modal__item">
<Multiselect v-model="newUser.subAdminsGroups"
:close-on-select="false"
:multiple="true"
:options="subAdminsGroups"
:placeholder="t('settings', 'Set user as admin for')"
:tag-width="60"
class="multiselect-vue"
label="name"
track-by="id">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</Multiselect>
</div>
<div class="quota modal__item">
<Multiselect v-model="newUser.quota"
:allow-empty="false"
:options="quotaOptions"
:placeholder="t('settings', 'Select user quota')"
:taggable="true"
class="multiselect-vue"
label="label"
track-by="id"
@tag="validateQuota" />
</div>
<div v-if="showConfig.showLanguages" class="languages modal__item">
<Multiselect v-model="newUser.language"
:allow-empty="false"
:options="languages"
:placeholder="t('settings', 'Default language')"
class="multiselect-vue"
group-label="label"
group-values="languages"
label="name"
track-by="code" />
</div>
<div v-if="showConfig.showStoragePath" class="storageLocation" />
<div v-if="showConfig.showUserBackend" class="userBackend" />
<div v-if="showConfig.showLastLogin" class="lastLogin" />
<div class="user-actions">
<button id="newsubmit"
class="button primary"
type="submit"
value="">
{{ t('settings', 'Add a new user') }}
</button>
</div>
</form>
</Modal>
<div id="grid-header"
:class="{'sticky': scrolled && !showConfig.showNewUserForm}"
class="row">
Expand Down Expand Up @@ -244,10 +234,9 @@
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import InfiniteLoading from 'vue-infinite-loading'
import Vue from 'vue'
import { Modal } from '@nextcloud/vue'
import Multiselect from '@nextcloud/vue/dist/Components/Multiselect'
import Actions from '@nextcloud/vue/dist/Components/Actions'
import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
import userRow from './UserList/UserRow'
Expand Down Expand Up @@ -276,11 +265,10 @@ const newUser = {
export default {
name: 'UserList',
components: {
Modal,
userRow,
Multiselect,
InfiniteLoading,
Actions,
ActionButton,
},
props: {
users: {
Expand Down Expand Up @@ -522,6 +510,7 @@ export default {
.then(() => {
this.resetForm()
this.$refs.newusername.focus()
this.closeModal()
})
.catch((error) => {
this.loading.all = false
Expand Down Expand Up @@ -584,13 +573,45 @@ export default {
this.$refs.infiniteLoading.stateChanger.reset()
}
},
onClose() {
closeModal() {
this.showConfig.showNewUserForm = false
},
},
}
</script>
<style scoped>
.modal-wrapper {
margin: 2vh 0;
align-items: flex-start;
}
.modal__content {
display: flex;
padding: 20px;
flex-direction: column;
align-items: center;
text-align: center;
overflow: auto;
}
.modal__item {
margin-bottom: 16px;
width: 100%;
}
.modal__item:not(:focus):not(:active) {
border-color: var(--color-border-dark);
}
.modal__item::v-deep .multiselect {
width: 100%;
}
.user-actions {
margin-top: 20px;
}
.modal__content::v-deep .multiselect__single {
text-align: left;
box-sizing: border-box;
}
.modal__content::v-deep .multiselect__content-wrapper {
box-sizing: border-box;
}
Comment on lines +608 to +614
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like an odd change, why was it needed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of the default border of 1px on each side. Without changing the box sizing, I have 2 extra pixels.

.row::v-deep .multiselect__single {
z-index: auto !important;
}
Expand Down
8 changes: 5 additions & 3 deletions apps/settings/src/views/Users.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@
<AppNavigationNew button-id="new-user-button"
:text="t('settings','New user')"
button-class="icon-add"
@click="toggleNewUserMenu" />
@click="showNewUserMenu"
@keyup.enter="showNewUserMenu"
@keyup.space="showNewUserMenu" />
<template #list>
<AppNavigationItem
id="addgroup"
Expand Down Expand Up @@ -348,8 +350,8 @@ export default {
})
},
methods: {
toggleNewUserMenu() {
this.showConfig.showNewUserForm = !this.showConfig.showNewUserForm
showNewUserMenu() {
this.showConfig.showNewUserForm = true
if (this.showConfig.showNewUserForm) {
Vue.nextTick(() => {
window.newusername.focus()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public static function newUserButton() {
* @return Locator
*/
public static function createNewUserButton() {
return Locator::forThe()->xpath("//form[@id = 'new-user']//input[@type = 'submit']")->
return Locator::forThe()->xpath("//form[@id = 'new-user']//button[@type = 'submit']")->
describedAs("Create user button in Users Settings");
}

Expand Down