summaryrefslogtreecommitdiffstats
path: root/apps/settings/src
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/src')
-rw-r--r--apps/settings/src/components/UserList.vue171
-rw-r--r--apps/settings/src/components/UserList/UserRow.vue124
-rw-r--r--apps/settings/src/components/UserList/UserRowSimple.vue49
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>