Merge pull request #38458 from nextcloud/revert/37870-Fix_table_view

Revert "Fix table view"
pull/38459/head
Julia Kirschenheuter 2023-05-25 15:26:55 +07:00 committed by GitHub
commit 3d36420736
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 189 additions and 205 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1417,8 +1417,14 @@ 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 {
@ -1462,6 +1468,10 @@ 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;
}
@ -1471,7 +1481,8 @@ doesnotexist:-o-prefocus, .strengthify-wrapper {
width: 100%;
}
> td,
> div,
> .displayName > form,
> form {
grid-row: 1;
display: inline-flex;

@ -21,7 +21,7 @@
-->
<template>
<table id="app-content"
<div id="app-content"
role="grid"
:aria-label="t('settings', 'User\'s table')"
class="user-list-grid"
@ -154,9 +154,9 @@
:options="possibleManagers"
:placeholder="t('settings', 'Select user manager')"
class="multiselect-vue"
@search-change="searchUserManager"
label="displayname"
track-by="id">
track-by="id"
@search-change="searchUserManager">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</NcMultiselect>
</div>
@ -170,95 +170,89 @@
</div>
</form>
</NcModal>
<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>
<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>
<th id="headerManager" class="manager">
{{ t('settings', 'Manager') }}
</th>
<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"
:users="users"
:is-dark-theme="isDarkTheme" />
<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>
<InfiniteLoading ref="infiniteLoading" @infinite="infiniteHandler">
<div slot="spinner">
<div class="users-icon-loading icon-loading" />
<div v-if="showConfig.showUserBackend || showConfig.showStoragePath"
class="headerUserBackend userBackend">
<div v-if="showConfig.showUserBackend" class="userBackend">
{{ t('settings', 'User backend') }}
</div>
<div slot="no-more">
<div class="users-list-end" />
<div v-if="showConfig.showStoragePath"
class="subtitle storageLocation">
{{ t('settings', 'Storage location') }}
</div>
<div slot="no-results">
<div id="emptycontent">
<div class="icon-contacts-dark" />
<h2>{{ t('settings', 'No users in here') }}</h2>
</div>
</div>
<div v-if="showConfig.showLastLogin"
class="headerLastLogin lastLogin">
{{ t('settings', 'Last login') }}
</div>
<div id="headerManager" class="manager">
{{ t('settings', 'Manager') }}
</div>
<div class="userActions" />
</div>
<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"
:users="users"
: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>
</div>
</InfiniteLoading>
</tbody>
</table>
</div>
</InfiniteLoading>
</div>
</template>
<script>
@ -685,12 +679,4 @@ 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}" />
<tr v-else
<div v-else
:class="{
'disabled': loading.delete || loading.disable,
'row--menu-opened': openedMenu
}"
:data-id="user.id"
class="row row--editable">
<td :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}"
<div :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">
</td>
</div>
<!-- dirty hack to ellipsis on two lines -->
<td v-if="user.backendCapabilities.setDisplayName" class="displayName">
<div v-if="user.backendCapabilities.setDisplayName" class="displayName">
<form :class="{'icon-loading-small': loading.displayName}"
class="displayName"
@submit.prevent="updateDisplayName">
@ -90,56 +90,53 @@
type="submit"
value="">
</form>
</td>
<td v-else class="name">
</div>
<div v-else class="name">
{{ user.id }}
<div class="displayName subtitle">
<div :title="user.displayname.length > 20 ? user.displayname : ''" class="cellText">
{{ user.displayname }}
</div>
</div>
</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">
</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">
<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"
@ -160,8 +157,8 @@
@tag="createGroup">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</NcMultiselect>
</td>
<td v-if="subAdminsGroups.length>0 && settings.isAdmin"
</div>
<div 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>
@ -181,8 +178,8 @@
@select="addUserSubAdmin">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</NcMultiselect>
</td>
<td :title="usedSpace"
</div>
<div :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>
@ -199,8 +196,8 @@
track-by="id"
@input="setUserQuota"
@tag="validateQuota" />
</td>
<td v-if="showConfig.showLanguages"
</div>
<div 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>
@ -216,8 +213,8 @@
label="name"
track-by="code"
@input="setUserLanguage" />
</td>
<td :class="{'icon-loading-small': loading.manager}" class="managers">
</div>
<div :class="{'icon-loading-small': loading.manager}" class="managers">
<NcMultiselect ref="manager"
v-model="currentManager"
:close-on-select="true"
@ -232,14 +229,14 @@
@select="updateUserManager">
<span slot="noResult">{{ t('settings', 'No results') }}</span>
</NcMultiselect>
</td>
</div>
<!-- don't show this on edit mode -->
<td v-if="showConfig.showStoragePath || showConfig.showUserBackend"
<div v-if="showConfig.showStoragePath || showConfig.showUserBackend"
class="storageLocation" />
<td v-if="showConfig.showLastLogin" />
<div v-if="showConfig.showLastLogin" />
<td class="userActions">
<div class="userActions">
<div v-if="!loading.all"
class="toggleUserActions">
<NcActions>
@ -263,8 +260,8 @@
<div class="icon-checkmark" />
{{ feedbackMessage }}
</div>
</td>
</tr>
</div>
</div>
</template>
<script>
@ -758,11 +755,4 @@ 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>
<tr class="row"
<div class="row"
:class="{'disabled': loading.delete || loading.disable}"
:data-id="user.id">
<td class="avatar" :class="{'icon-loading-small': loading.delete || loading.disable || loading.wipe}">
<div 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)">
</td>
</div>
<!-- dirty hack to ellipsis on two lines -->
<td class="name">
<div 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 }}
</td>
<td />
<td class="mailAddress">
</div>
<div />
<div class="mailAddress">
<div :title="user.email !== null && user.email.length > 20 ? user.email : ''" class="cellText">
{{ user.email }}
</div>
</td>
<td class="groups">
</div>
<div class="groups">
{{ userGroupsLabels }}
</td>
<td v-if="subAdminsGroups.length > 0 && settings.isAdmin" class="subAdminsGroups">
</div>
<div v-if="subAdminsGroups.length > 0 && settings.isAdmin" class="subAdminsGroups">
{{ userSubAdminsGroupsLabels }}
</td>
<td class="userQuota">
</div>
<div class="userQuota">
<div class="quota">
{{ userQuota }} ({{ usedSpace }})
<progress class="quota-user-progress"
@ -40,25 +40,25 @@
:value="usedQuota"
max="100" />
</div>
</td>
<td v-if="showConfig.showLanguages" class="languages">
</div>
<div v-if="showConfig.showLanguages" class="languages">
{{ userLanguage.name }}
</td>
<td v-if="showConfig.showUserBackend || showConfig.showStoragePath" class="userBackend">
</div>
<div 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>
</td>
<td v-if="showConfig.showLastLogin" :title="userLastLoginTooltip" class="lastLogin">
</div>
<div v-if="showConfig.showLastLogin" :title="userLastLoginTooltip" class="lastLogin">
{{ userLastLogin }}
</td>
<td class="managers">
</div>
<div class="managers">
{{ user.manager }}
</td>
<td class="userActions">
</div>
<div class="userActions">
<div v-if="canEdit && !loading.all" class="toggleUserActions">
<NcActions>
<NcActionButton icon="icon-rename"
@ -81,8 +81,8 @@
<div class="icon-checkmark" />
{{ feedbackMessage }}
</div>
</td>
</tr>
</div>
</div>
</template>
<script>
@ -205,7 +205,4 @@ 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("table.user-list-grid tr.row[data-id=$user]")->
return Locator::forThe()->css("div.user-list-grid div.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("//table[@class='user-list-grid']//*[normalize-space() = '$column']")->
return Locator::forThe()->xpath("//div[@class='user-list-grid']//div[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("table.user-list-grid tr.row.row--editable[data-id=$user]")->
return Locator::forThe()->css("div.user-list-grid div.row.row--editable[data-id=$user]")->
describedAs("I see the edit mode is on for the user $user in Users Settings");
}