diff options
Diffstat (limited to 'apps/settings/src')
-rw-r--r-- | apps/settings/src/components/UserList.vue | 171 | ||||
-rw-r--r-- | apps/settings/src/components/UserList/UserRow.vue | 124 | ||||
-rw-r--r-- | apps/settings/src/components/UserList/UserRowSimple.vue | 49 |
3 files changed, 188 insertions, 156 deletions
diff --git a/apps/settings/src/components/UserList.vue b/apps/settings/src/components/UserList.vue index 6aa61ccf8da..d2ab07dae50 100644 --- a/apps/settings/src/components/UserList.vue +++ b/apps/settings/src/components/UserList.vue @@ -21,7 +21,11 @@ --> <template> - <div id="app-content" class="user-list-grid" @scroll.passive="onScroll"> + <table id="app-content" + role="grid" + :aria-label="t('settings', 'User\'s table')" + class="user-list-grid" + @scroll.passive="onScroll"> <NcModal v-if="showConfig.showNewUserForm" size="small" @close="closeModal"> <form id="new-user" :disabled="loading.all" @@ -152,85 +156,92 @@ </div> </form> </NcModal> - <div id="grid-header" - :class="{'sticky': scrolled && !showConfig.showNewUserForm}" - class="row"> - <div id="headerAvatar" class="avatar" /> - <div id="headerName" class="name"> - <div class="subtitle"> - <strong> - {{ t('settings', 'Display name') }} - </strong> - </div> - {{ t('settings', 'Username') }} - </div> - <div id="headerPassword" class="password"> - {{ t('settings', 'Password') }} - </div> - <div id="headerAddress" class="mailAddress"> - {{ t('settings', 'Email') }} - </div> - <div id="headerGroups" class="groups"> - {{ t('settings', 'Groups') }} - </div> - <div v-if="subAdminsGroups.length>0 && settings.isAdmin" - id="headerSubAdmins" - class="subadmins"> - {{ t('settings', 'Group admin for') }} - </div> - <div id="headerQuota" class="quota"> - {{ t('settings', 'Quota') }} - </div> - <div v-if="showConfig.showLanguages" - id="headerLanguages" - class="languages"> - {{ t('settings', 'Language') }} - </div> + <tbody> + <tr id="grid-header" + :class="{'sticky': scrolled && !showConfig.showNewUserForm}" + class="row"> + <th id="headerAvatar" class="avatar"> + <span class="hidden-visually"> {{ t('settings', 'Avatar') }} </span> + </th> + <th id="headerName" class="name"> + <div class="subtitle"> + <strong> + {{ t('settings', 'Display name') }} + </strong> + </div> + {{ t('settings', 'Username') }} + </th> + <th id="headerPassword" class="password"> + {{ t('settings', 'Password') }} + </th> + <th id="headerAddress" class="mailAddress"> + {{ t('settings', 'Email') }} + </th> + <th id="headerGroups" class="groups"> + {{ t('settings', 'Groups') }} + </th> + <th v-if="subAdminsGroups.length>0 && settings.isAdmin" + id="headerSubAdmins" + class="subadmins"> + {{ t('settings', 'Group admin for') }} + </th> + <th id="headerQuota" class="quota"> + {{ t('settings', 'Quota') }} + </th> + <th v-if="showConfig.showLanguages" + id="headerLanguages" + class="languages"> + {{ t('settings', 'Language') }} + </th> - <div v-if="showConfig.showUserBackend || showConfig.showStoragePath" - class="headerUserBackend userBackend"> - <div v-if="showConfig.showUserBackend" class="userBackend"> - {{ t('settings', 'User backend') }} - </div> - <div v-if="showConfig.showStoragePath" - class="subtitle storageLocation"> - {{ t('settings', 'Storage location') }} - </div> - </div> - <div v-if="showConfig.showLastLogin" - class="headerLastLogin lastLogin"> - {{ t('settings', 'Last login') }} - </div> + <th v-if="showConfig.showUserBackend || showConfig.showStoragePath" + class="headerUserBackend userBackend"> + <div v-if="showConfig.showUserBackend" class="userBackend"> + {{ t('settings', 'User backend') }} + </div> + <div v-if="showConfig.showStoragePath" + class="subtitle storageLocation"> + {{ t('settings', 'Storage location') }} + </div> + </th> + <th v-if="showConfig.showLastLogin" + class="headerLastLogin lastLogin"> + {{ t('settings', 'Last login') }} + </th> - <div class="userActions" /> - </div> + <th class="userActions hidden-visually"> + {{ t('settings', 'User actions') }} + </th> + </tr> - <user-row v-for="user in filteredUsers" - :key="user.id" - :external-actions="externalActions" - :groups="groups" - :languages="languages" - :quota-options="quotaOptions" - :settings="settings" - :show-config="showConfig" - :sub-admins-groups="subAdminsGroups" - :user="user" - :is-dark-theme="isDarkTheme" /> - <InfiniteLoading ref="infiniteLoading" @infinite="infiniteHandler"> - <div slot="spinner"> - <div class="users-icon-loading icon-loading" /> - </div> - <div slot="no-more"> - <div class="users-list-end" /> - </div> - <div slot="no-results"> - <div id="emptycontent"> - <div class="icon-contacts-dark" /> - <h2>{{ t('settings', 'No users in here') }}</h2> + <user-row v-for="user in filteredUsers" + :key="user.id" + :external-actions="externalActions" + :groups="groups" + :languages="languages" + :quota-options="quotaOptions" + :settings="settings" + :show-config="showConfig" + :sub-admins-groups="subAdminsGroups" + :user="user" + :is-dark-theme="isDarkTheme" /> + + <InfiniteLoading ref="infiniteLoading" @infinite="infiniteHandler"> + <div slot="spinner"> + <div class="users-icon-loading icon-loading" /> + </div> + <div slot="no-more"> + <div class="users-list-end" /> </div> - </div> - </InfiniteLoading> - </div> + <div slot="no-results"> + <div id="emptycontent"> + <div class="icon-contacts-dark" /> + <h2>{{ t('settings', 'No users in here') }}</h2> + </div> + </div> + </InfiniteLoading> + </tbody> + </table> </template> <script> @@ -642,4 +653,12 @@ export default { * prevent it). */ width: 0; } + + #app-content tbody tr { + &:hover, + &:focus, + &:active { + background-color: var(--color-main-background); + } + } </style> diff --git a/apps/settings/src/components/UserList/UserRow.vue b/apps/settings/src/components/UserList/UserRow.vue index ed42db76e07..4007c551901 100644 --- a/apps/settings/src/components/UserList/UserRow.vue +++ b/apps/settings/src/components/UserList/UserRow.vue @@ -56,23 +56,23 @@ :user="user" :is-dark-theme="isDarkTheme" :class="{'row--menu-opened': openedMenu}" /> - <div v-else + <tr v-else :class="{ 'disabled': loading.delete || loading.disable, 'row--menu-opened': openedMenu }" :data-id="user.id" class="row row--editable"> - <div :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}" + <td :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}" class="avatar"> <img v-if="!loading.delete && !loading.disable && !loading.wipe" :src="generateAvatar(user.id, isDarkTheme)" alt="" height="32" width="32"> - </div> + </td> <!-- dirty hack to ellipsis on two lines --> - <div v-if="user.backendCapabilities.setDisplayName" class="displayName"> + <td v-if="user.backendCapabilities.setDisplayName" class="displayName"> <form :class="{'icon-loading-small': loading.displayName}" class="displayName" @submit.prevent="updateDisplayName"> @@ -90,53 +90,56 @@ type="submit" value=""> </form> - </div> - <div v-else class="name"> + </td> + <td v-else class="name"> {{ user.id }} <div class="displayName subtitle"> <div :title="user.displayname.length > 20 ? user.displayname : ''" class="cellText"> {{ user.displayname }} </div> </div> - </div> - <form v-if="settings.canChangePassword && user.backendCapabilities.setPassword" - :class="{'icon-loading-small': loading.password}" - class="password" - @submit.prevent="updatePassword"> - <label class="hidden-visually" :for="'password'+user.id+rand">{{ t('settings', 'Add new password') }}</label> - <input :id="'password'+user.id+rand" - ref="password" - :disabled="loading.password || loading.all" - :minlength="minPasswordLength" - maxlength="469" - :placeholder="t('settings', 'Add new password')" - autocapitalize="off" - autocomplete="new-password" - autocorrect="off" - required - spellcheck="false" - type="password" - value=""> - <input class="icon-confirm" type="submit" value=""> - </form> - <div v-else /> - <form :class="{'icon-loading-small': loading.mailAddress}" - class="mailAddress" - @submit.prevent="updateEmail"> - <label class="hidden-visually" :for="'mailAddress'+user.id+rand">{{ t('settings', 'Add new email address') }}</label> - <input :id="'mailAddress'+user.id+rand" - ref="mailAddress" - :disabled="loading.mailAddress||loading.all" - :placeholder="t('settings', 'Add new email address')" - :value="user.email" - autocapitalize="off" - autocomplete="new-password" - autocorrect="off" - spellcheck="false" - type="email"> - <input class="icon-confirm" type="submit" value=""> - </form> - <div :class="{'icon-loading-small': loading.groups}" class="groups"> + </td> + <td v-if="settings.canChangePassword && user.backendCapabilities.setPassword"> + <form :class="{'icon-loading-small': loading.password}" + class="password" + @submit.prevent="updatePassword"> + <label class="hidden-visually" :for="'password'+user.id+rand">{{ t('settings', 'Add new password') }}</label> + <input :id="'password'+user.id+rand" + ref="password" + :disabled="loading.password || loading.all" + :minlength="minPasswordLength" + maxlength="469" + :placeholder="t('settings', 'Add new password')" + autocapitalize="off" + autocomplete="new-password" + autocorrect="off" + required + spellcheck="false" + type="password" + value=""> + <input class="icon-confirm" type="submit" value=""> + </form> + </td> + <td v-else /> + <td> + <form :class="{'icon-loading-small': loading.mailAddress}" + class="mailAddress" + @submit.prevent="updateEmail"> + <label class="hidden-visually" :for="'mailAddress'+user.id+rand">{{ t('settings', 'Add new email address') }}</label> + <input :id="'mailAddress'+user.id+rand" + ref="mailAddress" + :disabled="loading.mailAddress||loading.all" + :placeholder="t('settings', 'Add new email address')" + :value="user.email" + autocapitalize="off" + autocomplete="new-password" + autocorrect="off" + spellcheck="false" + type="email"> + <input class="icon-confirm" type="submit" value=""> + </form> + </td> + <td :class="{'icon-loading-small': loading.groups}" class="groups"> <label class="hidden-visually" :for="'groups'+user.id+rand">{{ t('settings', 'Add user to group') }}</label> <NcMultiselect :id="'groups'+user.id+rand" :close-on-select="false" @@ -157,8 +160,8 @@ @tag="createGroup"> <span slot="noResult">{{ t('settings', 'No results') }}</span> </NcMultiselect> - </div> - <div v-if="subAdminsGroups.length>0 && settings.isAdmin" + </td> + <td v-if="subAdminsGroups.length>0 && settings.isAdmin" :class="{'icon-loading-small': loading.subadmins}" class="subadmins"> <label class="hidden-visually" :for="'subadmins'+user.id+rand">{{ t('settings', 'Set user as admin for') }}</label> @@ -178,8 +181,8 @@ @select="addUserSubAdmin"> <span slot="noResult">{{ t('settings', 'No results') }}</span> </NcMultiselect> - </div> - <div :title="usedSpace" + </td> + <td :title="usedSpace" :class="{'icon-loading-small': loading.quota}" class="quota"> <label class="hidden-visually" :for="'quota'+user.id+rand">{{ t('settings', 'Select user quota') }}</label> @@ -196,8 +199,8 @@ track-by="id" @input="setUserQuota" @tag="validateQuota" /> - </div> - <div v-if="showConfig.showLanguages" + </td> + <td v-if="showConfig.showLanguages" :class="{'icon-loading-small': loading.languages}" class="languages"> <label class="hidden-visually" :for="'language'+user.id+rand">{{ t('settings', 'Set the language') }}</label> @@ -213,14 +216,14 @@ label="name" track-by="code" @input="setUserLanguage" /> - </div> + </td> <!-- don't show this on edit mode --> - <div v-if="showConfig.showStoragePath || showConfig.showUserBackend" + <td v-if="showConfig.showStoragePath || showConfig.showUserBackend" class="storageLocation" /> - <div v-if="showConfig.showLastLogin" /> + <td v-if="showConfig.showLastLogin" /> - <div class="userActions"> + <td class="userActions"> <div v-if="!loading.all" class="toggleUserActions"> <NcActions> @@ -242,8 +245,8 @@ <div class="icon-checkmark" /> {{ feedbackMessage }} </div> - </div> - </div> + </td> + </tr> </template> <script> @@ -697,4 +700,11 @@ export default { .row::v-deep .multiselect__single { z-index: auto !important; } + .displayName input, + .password input, + .mailAddress input { + width: 100%; + height: 44px!important; + border: 2px solid var(--color-border-dark); + } </style> diff --git a/apps/settings/src/components/UserList/UserRowSimple.vue b/apps/settings/src/components/UserList/UserRowSimple.vue index 8f5e3ae8e84..ed63d25d93c 100644 --- a/apps/settings/src/components/UserList/UserRowSimple.vue +++ b/apps/settings/src/components/UserList/UserRowSimple.vue @@ -1,16 +1,16 @@ <template> - <div class="row" + <tr class="row" :class="{'disabled': loading.delete || loading.disable}" :data-id="user.id"> - <div class="avatar" :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}"> + <td class="avatar" :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}"> <img v-if="!loading.delete && !loading.disable && !loading.wipe" alt="" width="32" height="32" :src="generateAvatar(user.id, isDarkTheme)"> - </div> + </td> <!-- dirty hack to ellipsis on two lines --> - <div class="name"> + <td class="name"> <div class="displayName subtitle"> <div :title="user.displayname.length > 20 ? user.displayname : ''" class="cellText"> <strong> @@ -19,20 +19,20 @@ </div> </div> {{ user.id }} - </div> - <div /> - <div class="mailAddress"> + </td> + <td /> + <td class="mailAddress"> <div :title="user.email !== null && user.email.length > 20 ? user.email : ''" class="cellText"> {{ user.email }} </div> - </div> - <div class="groups"> + </td> + <td class="groups"> {{ userGroupsLabels }} - </div> - <div v-if="subAdminsGroups.length > 0 && settings.isAdmin" class="subAdminsGroups"> + </td> + <td v-if="subAdminsGroups.length > 0 && settings.isAdmin" class="subAdminsGroups"> {{ userSubAdminsGroupsLabels }} - </div> - <div class="userQuota"> + </td> + <td class="userQuota"> <div class="quota"> {{ userQuota }} ({{ usedSpace }}) <progress class="quota-user-progress" @@ -40,23 +40,23 @@ :value="usedQuota" max="100" /> </div> - </div> - <div v-if="showConfig.showLanguages" class="languages"> + </td> + <td v-if="showConfig.showLanguages" class="languages"> {{ userLanguage.name }} - </div> - <div v-if="showConfig.showUserBackend || showConfig.showStoragePath" class="userBackend"> + </td> + <td v-if="showConfig.showUserBackend || showConfig.showStoragePath" class="userBackend"> <div v-if="showConfig.showUserBackend" class="userBackend"> {{ user.backend }} </div> <div v-if="showConfig.showStoragePath" :title="user.storageLocation" class="storageLocation subtitle"> {{ user.storageLocation }} </div> - </div> - <div v-if="showConfig.showLastLogin" :title="userLastLoginTooltip" class="lastLogin"> + </td> + <td v-if="showConfig.showLastLogin" :title="userLastLoginTooltip" class="lastLogin"> {{ userLastLogin }} - </div> + </td> - <div class="userActions"> + <td class="userActions"> <div v-if="canEdit && !loading.all" class="toggleUserActions"> <NcActions> <NcActionButton icon="icon-rename" @@ -78,8 +78,8 @@ <div class="icon-checkmark" /> {{ feedbackMessage }} </div> - </div> - </div> + </td> + </tr> </template> <script> @@ -202,4 +202,7 @@ export default { background-color: var(--color-main-background); border: 0; } + .row .name { + padding-left: 0px!important; + } </style> |