Notification preferences
</a>
- <button class="btn" [disabled]="!hasUnreadNotifications()" (click)="markAllAsRead()">
+ <div class="peertube-select-container peertube-select-button ml-2">
+ <select [(ngModel)]="notificationSortType" (ngModelChange)="onNotificationSortTypeChanged()" class="form-control">
+ <option value="undefined" disabled>Sort by</option>
+ <option value="created" i18n>Newest first</option>
+ <option value="unread-created" i18n>Unread first</option>
+ </select>
+ </div>
+
+ <button class="btn ml-auto" [disabled]="!hasUnreadNotifications()" (click)="markAllAsRead()">
<ng-container *ngIf="hasUnreadNotifications()">
<my-global-icon iconName="inbox-full" aria-hidden="true"></my-global-icon>
.header {
display: flex;
- justify-content: space-between;
font-size: 15px;
margin-bottom: 20px;
@include grey-button;
@include button-with-icon(20px, 3px, -1px);
}
+
+ .peertube-select-container {
+ @include peertube-select-container(auto);
+ }
}
+
my-user-notifications {
font-size: 15px;
}
export class MyAccountNotificationsComponent {
@ViewChild('userNotification', { static: true }) userNotification: UserNotificationsComponent
+ notificationSortType = 'created'
+
markAllAsRead () {
this.userNotification.markAllAsRead()
}
hasUnreadNotifications () {
return this.userNotification.notifications.filter(n => n.read === false).length !== 0
}
+
+ onNotificationSortTypeChanged () {}
}
import { ResultList, UserNotification as UserNotificationServer, UserNotificationSetting } from '@shared/models'
import { environment } from '../../../../environments/environment'
import { UserNotification } from './user-notification.model'
+import { SortMeta } from 'primeng/api'
@Injectable()
export class UserNotificationService {
private userNotificationSocket: UserNotificationSocket
) {}
- listMyNotifications (pagination: ComponentPaginationLight, unread?: boolean, ignoreLoadingBar = false) {
+ listMyNotifications (parameters: {
+ pagination: ComponentPaginationLight
+ ignoreLoadingBar?: boolean
+ unread?: boolean,
+ sort?: SortMeta
+ }) {
+ const { pagination, ignoreLoadingBar, unread, sort } = parameters
+
let params = new HttpParams()
- params = this.restService.addRestGetParams(params, this.restService.componentPaginationToRestPagination(pagination))
+ params = this.restService.addRestGetParams(params, this.restService.componentPaginationToRestPagination(pagination), sort)
if (unread) params = params.append('unread', `${unread}`)
}
countUnreadNotifications () {
- return this.listMyNotifications({ currentPage: 1, itemsPerPage: 0 }, true)
+ return this.listMyNotifications({ pagination: { currentPage: 1, itemsPerPage: 0 }, ignoreLoadingBar: true, unread: true })
.pipe(map(n => n.total))
}
@Output() notificationsLoaded = new EventEmitter()
notifications: UserNotification[] = []
+ sortField = 'createdAt'
// So we can access it in the template
UserNotificationType = UserNotificationType
totalItems: null
}
- this.loadMoreNotifications()
+ this.loadNotifications()
if (this.markAllAsReadSubject) {
this.markAllAsReadSubject.subscribe(() => this.markAllAsRead())
}
}
- loadMoreNotifications () {
- this.userNotificationService.listMyNotifications(this.componentPagination, undefined, this.ignoreLoadingBar)
+ loadNotifications (reset?: boolean) {
+ this.userNotificationService.listMyNotifications({
+ pagination: this.componentPagination,
+ ignoreLoadingBar: this.ignoreLoadingBar,
+ sort: {
+ field: this.sortField,
+ order: this.sortField === 'createdAt' ? -1 : 1
+ }
+ })
.subscribe(
result => {
- this.notifications = this.notifications.concat(result.data)
+ this.notifications = reset ? result.data : this.notifications.concat(result.data)
this.componentPagination.totalItems = result.total
this.notificationsLoaded.emit()
this.componentPagination.currentPage++
if (hasMoreItems(this.componentPagination)) {
- this.loadMoreNotifications()
+ this.loadNotifications()
}
}
err => this.notifier.error(err.message)
)
}
+
+ changeSortColumn (column: string) {
+ this.componentPagination = {
+ currentPage: 1,
+ itemsPerPage: this.itemsPerPage,
+ totalItems: null
+ }
+ this.sortField = column
+ this.loadNotifications(true)
+ }
}
color: #000;
}
}
+
+ &.peertube-select-button {
+ @include grey-button;
+
+ select,
+ option {
+ font-weight: $font-semibold;
+ color: pvar(--greyForegroundColor);
+ border: none;
+ }
+ }
}
// Thanks: https://codepen.io/triss90/pen/XNEdRe/
}
}
+@mixin table-badge {
+ border-radius: 2px;
+ padding: 1/4em 1/2em;
+ text-transform: uppercase;
+ font-weight: $font-bold;
+ font-size: 12px;
+ letter-spacing: 1/3px;
+
+ &.badge-banned,
+ &.badge-red {
+ background-color: #ffcdd2;
+ color: #c63737;
+ }
+
+ &.badge-banned {
+ text-decoration: line-through;
+ }
+
+ &.badge-yellow {
+ background-color: #feedaf;
+ color: #8a5340;
+ }
+
+ &.badge-brown {
+ background-color: #ffd8b2;
+ color: #805b36;
+ }
+
+ &.badge-green {
+ background-color: #c8e6c9;
+ color: #256029;
+ }
+
+ &.badge-blue {
+ background-color: #b3e5fc;
+ color: #23547b;
+ }
+
+ &.badge-purple {
+ background-color: #eccfff;
+ color: #694382;
+ }
+}
@mixin avatar ($size) {
object-fit: cover;
overflow: hidden;
font-size: 0.75rem;
border-radius: 0.25rem;
+ color: gray;
.progress-bar {
color: pvar(--mainBackgroundColor);
text-align: center;
white-space: nowrap;
transition: width 0.6s ease;
+ isolation: isolate;
+
+ &:after {
+ content: attr(valuenow-formatted);
+ position: absolute;
+ margin-left: .2rem;
+ mix-blend-mode: screen;
+ color: gray;
+ }
&.secondary {
background-color: pvar(--secondaryColor);
}
}
+
+ .progress-bar + span {
+ position: relative;
+ top: -1px;
+ }
}
@mixin breadcrumb {
&:last-child td {
border-bottom: none !important;
}
+
+ &:focus + tr > td,
+ &:focus > td {
+ box-shadow: none !important;
+ }
}
.expander {
// Sortable columns per schema
const SORTABLE_COLUMNS = {
- USERS: [ 'id', 'username', 'videoQuotaUsed', 'createdAt' ],
+ USERS: [ 'id', 'username', 'videoQuotaUsed', 'createdAt', 'lastLoginDate', 'role' ],
USER_SUBSCRIPTIONS: [ 'id', 'createdAt' ],
ACCOUNTS: [ 'createdAt' ],
JOBS: [ 'createdAt' ],
ACCOUNTS_BLOCKLIST: [ 'createdAt' ],
SERVERS_BLOCKLIST: [ 'createdAt' ],
- USER_NOTIFICATIONS: [ 'createdAt' ],
+ USER_NOTIFICATIONS: [ 'createdAt', 'read' ],
VIDEO_PLAYLISTS: [ 'displayName', 'createdAt', 'updatedAt' ],