Improve (accessibility title) and move action-buttons on left in tables (#2980)

* Improve and move action-buttons on left in tables

* Focus on my-delete and my-button

* Correct spaces syntax

* Move user-action dropdown on the left

Co-authored-by: kimsible <kimsible@users.noreply.github.com>
pull/3011/head
Kim 2020-07-31 11:30:57 +02:00 committed by GitHub
parent 8d987ec63e
commit 30814423ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 104 additions and 73 deletions

View File

@ -24,16 +24,24 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;">Actions</th>
<th i18n>Follower handle</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 100px;" i18n pSortableColumn="score">Score <p-sortIcon field="score"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 150px;"></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-follow>
<tr>
<td class="action-cell">
<ng-container *ngIf="follow.state === 'pending'">
<my-button i18n-title title="Accept" icon="tick" (click)="acceptFollower(follow)"></my-button>
<my-button i18n-title title="Refuse" icon="cross" (click)="rejectFollower(follow)"></my-button>
</ng-container>
<my-delete-button label *ngIf="follow.state === 'accepted'" (click)="deleteFollower(follow)"></my-delete-button>
</td>
<td>
<a [href]="follow.follower.url" i18n-title title="Open actor page in a new tab" target="_blank" rel="noopener noreferrer">
{{ follow.follower.name + '@' + follow.follower.host }}
@ -50,15 +58,6 @@
<td>{{ follow.score }}</td>
<td>{{ follow.createdAt | date: 'short' }}</td>
<td class="action-cell">
<ng-container *ngIf="follow.state === 'pending'">
<my-button i18n-title title="Accept" icon="tick" (click)="acceptFollower(follow)"></my-button>
<my-button i18n-title title="Refuse" icon="cross" (click)="rejectFollower(follow)"></my-button>
</ng-container>
<my-delete-button *ngIf="follow.state === 'accepted'" (click)="deleteFollower(follow)"></my-delete-button>
</td>
</tr>
</ng-template>

View File

@ -28,16 +28,19 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;">Action</th>
<th i18n>Host</th>
<th style="width: 100px;" i18n pSortableColumn="state">State <p-sortIcon field="state"></p-sortIcon></th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 160px;" i18n pSortableColumn="redundancyAllowed">Redundancy allowed <p-sortIcon field="redundancyAllowed"></p-sortIcon></th>
<th style="width: 150px;"></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-follow>
<tr>
<td class="action-cell">
<my-delete-button label (click)="removeFollowing(follow)"></my-delete-button>
</td>
<td>
<a [href]="'https://' + follow.following.host" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer">
{{ follow.following.host }}
@ -58,9 +61,6 @@
[host]="follow.following.host" [redundancyAllowed]="follow.following.hostRedundancyAllowed"
></my-redundancy-checkbox>
</td>
<td class="action-cell">
<my-delete-button (click)="removeFollowing(follow)"></my-delete-button>
</td>
</tr>
</ng-template>

View File

@ -24,22 +24,25 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 40px;"></th>
<th style="width: 150px;">Action</th>
<th style="width: 160px;" i18n *ngIf="isDisplayingRemoteVideos()">Strategy</th>
<th i18n pSortableColumn="name">Video <p-sortIcon field="name"></p-sortIcon></th >
<th style="width: 100px;" i18n *ngIf="isDisplayingRemoteVideos()">Total size</th>
<th style="width: 150px;"></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-expanded="expanded" let-redundancy>
<tr>
<td>
<span class="expander" i18n-ngbTooltip ngbTooltip="List redundancies" [pRowToggler]="redundancy">
<i [ngClass]="expanded ? 'glyphicon glyphicon-menu-down' : 'glyphicon glyphicon-menu-right'"></i>
</span>
</td>
<td class="action-cell">
<my-delete-button label (click)="removeRedundancy(redundancy)"></my-delete-button>
</td>
<td *ngIf="isDisplayingRemoteVideos()">{{ getRedundancyStrategy(redundancy) }}</td>
<td>
@ -50,10 +53,6 @@
</td>
<td *ngIf="isDisplayingRemoteVideos()">{{ getTotalSize(redundancy) | bytes: 1 }}</td>
<td class="action-cell">
<my-delete-button (click)="removeRedundancy(redundancy)"></my-delete-button>
</td>
</tr>
</ng-template>

View File

@ -19,14 +19,18 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;">Action</th> <!-- column for action buttons -->
<th style="width: 100%;" i18n>Account</th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 150px;"></th> <!-- column for action buttons -->
</tr>
</ng-template>
<ng-template pTemplate="body" let-accountBlock>
<tr>
<td class="action-cell">
<button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
</td>
<td>
<a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
<div class="chip two-lines">
@ -45,9 +49,6 @@
</td>
<td>{{ accountBlock.createdAt | date: 'short' }}</td>
<td class="action-cell">
<button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
</td>
</tr>
</ng-template>

View File

@ -61,7 +61,7 @@
<th style="width: 60px;">
<div class="c-hand" ngbDropdown placement="bottom-right auto" container="body" autoClose="outside">
<my-global-icon iconName="columns" ngbDropdownToggle></my-global-icon>
<div role="menu" class="dropdown-menu" ngbDropdownMenu>
<div class="dropdown-header" i18n>Table parameters</div>
<div ngbDropdownItem class="dropdown-item">
@ -95,6 +95,12 @@
</span>
</td>
<td class="action-cell">
<my-user-moderation-dropdown *ngIf="!isInSelectionMode()" [user]="user" container="body"
(userChanged)="onUserChanged()" (userDeleted)="onUserChanged()">
</my-user-moderation-dropdown>
</td>
<td *ngIf="getColumn('username')">
<a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
<div class="chip two-lines">
@ -161,14 +167,6 @@
<td *ngIf="getColumn('createdAt')" [title]="user.createdAt">{{ user.createdAt | date: 'short' }}</td>
<td *ngIf="getColumn('lastLoginDate')" [title]="user.lastLoginDate">{{ user.lastLoginDate | date: 'short' }}</td>
<td class="action-cell">
<my-user-moderation-dropdown
*ngIf="!isInSelectionMode()"
[user]="user" container="body" (userChanged)="onUserChanged()" (userDeleted)="onUserChanged()"
>
</my-user-moderation-dropdown>
</td>
</tr>
</ng-template>

View File

@ -34,8 +34,8 @@
<div i18n class="video-channel-videos">{videoChannel.videosCount, plural, =0 {No videos} =1 {1 video} other {{{ videoChannel.videosCount }} videos}}</div>
<div class="video-channel-buttons">
<my-edit-button [routerLink]="[ 'update', videoChannel.nameWithHost ]"></my-edit-button>
<my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
<my-edit-button label [routerLink]="[ 'update', videoChannel.nameWithHost ]"></my-edit-button>
<my-delete-button label (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
</div>
<div *ngIf="!isInSmallView" class="w-100 d-flex justify-content-end">

View File

@ -15,6 +15,7 @@
>
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;" i18n>Actions</th>
<th style="width: 35%;" i18n>Initiator</th>
<th style="width: 65%;" i18n>Video</th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">
@ -22,12 +23,17 @@
<p-sortIcon field="createdAt"></p-sortIcon>
</th>
<th style="width: 100px;" i18n>Status</th>
<th style="width: 130px;" i18n>Action</th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-videoChangeOwnership>
<tr>
<td class="action-cell">
<ng-container *ngIf="videoChangeOwnership.status === 'WAITING'">
<my-button i18n-title title="Accept" icon="tick" (click)="openAcceptModal(videoChangeOwnership)"></my-button>
<my-button i18n-title title="Refuse" icon="cross" (click)="refuse(videoChangeOwnership)"></my-button>
</ng-container>
</td>
<td>
<a [href]="videoChangeOwnership.initiatorAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
<div class="chip two-lines">
@ -64,14 +70,8 @@
<td>{{ videoChangeOwnership.createdAt | date: 'short' }}</td>
<td>
<span class="badge" [ngClass]="getStatusClass(videoChangeOwnership.status)">{{ videoChangeOwnership.status }}</span>
</td>
<td class="action-cell">
<ng-container *ngIf="videoChangeOwnership.status === 'WAITING'">
<my-button i18n-label label="Accept" icon="tick" (click)="openAcceptModal(videoChangeOwnership)"></my-button>
<my-button i18n-label label="Refuse" icon="cross" (click)="refuse(videoChangeOwnership)"></my-button>
</ng-container>
<span class="badge"
[ngClass]="getStatusClass(videoChangeOwnership.status)">{{ videoChangeOwnership.status }}</span>
</td>
</tr>
</ng-template>

View File

@ -13,11 +13,11 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 40px;"></th>
<th style="width: 70px">Action</th>
<th style="width: 45%" i18n>Target</th>
<th style="width: 55%" i18n>Video</th>
<th style="width: 150px" i18n>State</th>
<th style="width: 150px" i18n pSortableColumn="createdAt">Created <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 70px"></th>
</tr>
</ng-template>
@ -29,6 +29,11 @@
</span>
</td>
<td class="action-cell">
<my-edit-button *ngIf="isVideoImportSuccess(videoImport) && videoImport.video"
[routerLink]="getEditVideoUrl(videoImport.video)"></my-edit-button>
</td>
<td>
<a *ngIf="videoImport.targetUrl; else torrent" [href]="videoImport.targetUrl" target="_blank" rel="noopener noreferrer">{{ videoImport.targetUrl }}</a>
<ng-template #torrent>
@ -52,10 +57,6 @@
</td>
<td>{{ videoImport.createdAt | date: 'short' }}</td>
<td class="action-cell">
<my-edit-button label=" " *ngIf="isVideoImportSuccess(videoImport) && videoImport.video" [routerLink]="getEditVideoUrl(videoImport.video)"></my-edit-button>
</td>
</tr>
</ng-template>

View File

@ -24,9 +24,9 @@
</div>
<div *ngIf="isRegularPlaylist(playlist)" class="video-playlist-buttons">
<my-delete-button (click)="deleteVideoPlaylist(playlist)"></my-delete-button>
<my-delete-button label (click)="deleteVideoPlaylist(playlist)"></my-delete-button>
<my-edit-button [routerLink]="[ 'update', playlist.uuid ]"></my-edit-button>
<my-edit-button label [routerLink]="[ 'update', playlist.uuid ]"></my-edit-button>
</div>
</div>
</div>

View File

@ -31,9 +31,9 @@
<ng-template ptTemplate="rowButtons" let-video>
<div class="action-button">
<my-delete-button (click)="deleteVideo(video)"></my-delete-button>
<my-delete-button label (click)="deleteVideo(video)"></my-delete-button>
<my-edit-button [routerLink]="[ '/videos', 'update', video.uuid ]"></my-edit-button>
<my-edit-button label [routerLink]="[ '/videos', 'update', video.uuid ]"></my-edit-button>
<my-button i18n-label label="Change ownership"
className="action-button-change-ownership grey-button"

View File

@ -1,8 +1,8 @@
<span class="action-button" [ngClass]="getClasses()" [title]="getTitle()" tabindex="0">
<span class="action-button" [ngClass]="getClasses()" [ngbTooltip]="getTitle()" tabindex="0">
<my-global-icon *ngIf="!loading" [iconName]="icon"></my-global-icon>
<my-small-loader [loading]="loading"></my-small-loader>
<span class="button-label">{{ label }}</span>
<span *ngIf="label" class="button-label">{{ label }}</span>
<ng-content></ng-content>
</span>

View File

@ -1,6 +1,10 @@
@import '_variables';
@import '_mixins';
:host {
outline: none;
}
my-small-loader ::ng-deep .root {
display: inline-block;
margin: 0 3px 0 0;

View File

@ -1,6 +1,5 @@
<span class="action-button action-button-delete grey-button" [title]="title" role="button" tabindex="0">
<span class="action-button action-button-delete grey-button" [ngbTooltip]="title" role="button" tabindex="0">
<my-global-icon iconName="delete" aria-hidden="true"></my-global-icon>
<span class="button-label" *ngIf="label">{{ label }}</span>
<span class="button-label" i18n *ngIf="!label">Delete</span>
</span>

View File

@ -9,12 +9,23 @@ import { I18n } from '@ngx-translate/i18n-polyfill'
export class DeleteButtonComponent implements OnInit {
@Input() label: string
title: string
@Input() title: string
constructor (private i18n: I18n) { }
ngOnInit () {
this.title = this.label || this.i18n('Delete')
// <my-delete-button /> No label
if (this.label === undefined && !this.title) {
this.title = this.i18n('Delete')
}
// <my-delete-button label /> Use default label
if (this.label === '') {
this.label = this.i18n('Delete')
if (!this.title) {
this.title = this.label
}
}
}
}

View File

@ -1,6 +1,5 @@
<a class="action-button action-button-edit grey-button" [routerLink]="routerLink" i18n-title title="Update">
<a class="action-button action-button-edit grey-button" [routerLink]="routerLink" [ngbTooltip]="title">
<my-global-icon iconName="edit" aria-hidden="true"></my-global-icon>
<span class="button-label" *ngIf="label">{{ label }}</span>
<span class="button-label" i18n *ngIf="!label">Update</span>
</a>

View File

@ -1,4 +1,5 @@
import { Component, Input } from '@angular/core'
import { Component, Input, OnInit } from '@angular/core'
import { I18n } from '@ngx-translate/i18n-polyfill'
@Component({
selector: 'my-edit-button',
@ -6,7 +7,26 @@ import { Component, Input } from '@angular/core'
templateUrl: './edit-button.component.html'
})
export class EditButtonComponent {
export class EditButtonComponent implements OnInit {
@Input() label: string
@Input() title: string
@Input() routerLink: string[] | string = []
constructor (private i18n: I18n) { }
ngOnInit () {
// <my-edit-button /> No label
if (this.label === undefined && !this.title) {
this.title = this.i18n('Update')
}
// <my-edit-button label /> Use default label
if (this.label === '') {
this.label = this.i18n('Update')
if (!this.title) {
this.title = this.label
}
}
}
}

View File

@ -24,14 +24,17 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;">Action</th> <!-- column for action buttons -->
<th style="width: 100%;" i18n>Account</th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 150px;"></th> <!-- column for action buttons -->
</tr>
</ng-template>
<ng-template pTemplate="body" let-accountBlock>
<tr>
<td class="action-cell">
<button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
</td>
<td>
<a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
<div class="chip two-lines">
@ -50,9 +53,6 @@
</td>
<td>{{ accountBlock.createdAt | date: 'short' }}</td>
<td class="action-cell">
<button class="unblock-button" (click)="unblockAccount(accountBlock)" i18n>Unmute</button>
</td>
</tr>
</ng-template>

View File

@ -28,14 +28,17 @@
<ng-template pTemplate="header">
<tr>
<th style="width: 150px;">Action</th> <!-- column for action buttons -->
<th style="width: 100%;" i18n>Instance</th>
<th style="width: 150px;" i18n pSortableColumn="createdAt">Muted at <p-sortIcon field="createdAt"></p-sortIcon></th>
<th style="width: 150px;"></th> <!-- column for action buttons -->
</tr>
</ng-template>
<ng-template pTemplate="body" let-serverBlock>
<tr>
<td class="action-cell">
<button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button>
</td>
<td>
<a [href]="'https://' + serverBlock.blockedServer.host" i18n-title title="Open instance in a new tab" target="_blank" rel="noopener noreferrer">
{{ serverBlock.blockedServer.host }}
@ -43,9 +46,6 @@
</a>
</td>
<td>{{ serverBlock.createdAt | date: 'short' }}</td>
<td class="action-cell">
<button class="unblock-button" (click)="unblockServer(serverBlock)" i18n>Unmute</button>
</td>
</tr>
</ng-template>

View File

@ -19,7 +19,7 @@ export class UserModerationDropdownComponent implements OnInit, OnChanges {
@Input() prependActions: DropdownAction<{ user: User, account: Account }>[]
@Input() buttonSize: 'normal' | 'small' = 'normal'
@Input() placement = 'left-top left-bottom auto'
@Input() placement = 'right-top right-bottom auto'
@Input() label: string
@Input() container: 'body' | undefined = undefined