Fix table view

Signed-off-by: julia.kirschenheuter <julia.kirschenheuter@nextcloud.com>
pull/37870/head
julia.kirschenheuter 2023-04-21 16:33:10 +07:00
parent 9d2d3d482b
commit cb852ef63b
11 changed files with 200 additions and 179 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1418,14 +1418,8 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
.userActions {
display: flex;
justify-content: flex-end;
position: sticky;
right: 0px;
min-width: 88px;
background-color: var(--color-main-background);
}
&.row--editable .userActions {
z-index: 10;
}
.subtitle {
@ -1469,10 +1463,6 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
}
&:hover {
input:not([type='submit']):not(:focus):not(:active) {
border-color: var(--color-border) !important;
}
&:not(#grid-header) {
box-shadow: 5px 0 0 var(--color-primary-element) inset;
}
@ -1482,8 +1472,7 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
width: 100%;
}
> div,
> .displayName > form,
> td,
> form {
grid-row: 1;
display: inline-flex;

@ -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,42 +156,45 @@
</div>
</form>
</NcModal>
<div id="grid-header"
<tbody>
<tr id="grid-header"
:class="{'sticky': scrolled && !showConfig.showNewUserForm}"
class="row">
<div id="headerAvatar" class="avatar" />
<div id="headerName" class="name">
<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') }}
</div>
<div id="headerPassword" class="password">
</th>
<th id="headerPassword" class="password">
{{ t('settings', 'Password') }}
</div>
<div id="headerAddress" class="mailAddress">
</th>
<th id="headerAddress" class="mailAddress">
{{ t('settings', 'Email') }}
</div>
<div id="headerGroups" class="groups">
</th>
<th id="headerGroups" class="groups">
{{ t('settings', 'Groups') }}
</div>
<div v-if="subAdminsGroups.length>0 && settings.isAdmin"
</th>
<th v-if="subAdminsGroups.length>0 && settings.isAdmin"
id="headerSubAdmins"
class="subadmins">
{{ t('settings', 'Group admin for') }}
</div>
<div id="headerQuota" class="quota">
</th>
<th id="headerQuota" class="quota">
{{ t('settings', 'Quota') }}
</div>
<div v-if="showConfig.showLanguages"
</th>
<th v-if="showConfig.showLanguages"
id="headerLanguages"
class="languages">
{{ t('settings', 'Language') }}
</div>
</th>
<div v-if="showConfig.showUserBackend || showConfig.showStoragePath"
<th v-if="showConfig.showUserBackend || showConfig.showStoragePath"
class="headerUserBackend userBackend">
<div v-if="showConfig.showUserBackend" class="userBackend">
{{ t('settings', 'User backend') }}
@ -196,14 +203,16 @@
class="subtitle storageLocation">
{{ t('settings', 'Storage location') }}
</div>
</div>
<div v-if="showConfig.showLastLogin"
</th>
<th v-if="showConfig.showLastLogin"
class="headerLastLogin lastLogin">
{{ t('settings', 'Last login') }}
</div>
</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"
@ -216,6 +225,7 @@
: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" />
@ -230,7 +240,8 @@
</div>
</div>
</InfiniteLoading>
</div>
</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>

@ -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,17 +90,17 @@
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}"
</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>
@ -119,7 +119,9 @@
value="">
<input class="icon-confirm" type="submit" value="">
</form>
<div v-else />
</td>
<td v-else />
<td>
<form :class="{'icon-loading-small': loading.mailAddress}"
class="mailAddress"
@submit.prevent="updateEmail">
@ -136,7 +138,8 @@
type="email">
<input class="icon-confirm" type="submit" value="">
</form>
<div :class="{'icon-loading-small': loading.groups}" class="groups">
</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>

@ -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>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -82,7 +82,7 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function rowForUser($user) {
return Locator::forThe()->css("div.user-list-grid div.row[data-id=$user]")->
return Locator::forThe()->css("table.user-list-grid tr.row[data-id=$user]")->
describedAs("Row for user $user in Users Settings");
}
@ -144,7 +144,7 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function theColumn($column) {
return Locator::forThe()->xpath("//div[@class='user-list-grid']//div[normalize-space() = '$column']")->
return Locator::forThe()->xpath("//table[@class='user-list-grid']//*[normalize-space() = '$column']")->
describedAs("The $column column in Users Settings");
}
@ -170,7 +170,7 @@ class UsersSettingsContext implements Context, ActorAwareInterface {
* @return Locator
*/
public static function editModeOn($user) {
return Locator::forThe()->css("div.user-list-grid div.row.row--editable[data-id=$user]")->
return Locator::forThe()->css("table.user-list-grid tr.row.row--editable[data-id=$user]")->
describedAs("I see the edit mode is on for the user $user in Users Settings");
}