Polish Round 1 (#2396)

This commit is contained in:
Joe Milazzo 2023-11-04 12:29:10 -05:00 committed by GitHub
parent cf2c43d390
commit 02b002d81a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
197 changed files with 1233 additions and 1751 deletions

View file

@ -3,7 +3,7 @@ import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angula
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { Member } from 'src/app/_models/auth/member';
import { AccountService } from 'src/app/_services/account.service';
import { SentenceCasePipe } from '../../../pipe/sentence-case.pipe';
import { SentenceCasePipe } from '../../../_pipes/sentence-case.pipe';
import { NgIf } from '@angular/common';
import {TranslocoDirective} from "@ngneat/transloco";

View file

@ -1,23 +0,0 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AdminGuard } from '../_guards/admin.guard';
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
{path: '**', component: DashboardComponent, pathMatch: 'full', canActivate: [AdminGuard]},
{
path: '',
runGuardsAndResolvers: 'always',
canActivate: [AdminGuard],
children: [
{path: 'dashboard', component: DashboardComponent},
]
}
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminRoutingModule { }

View file

@ -1,95 +0,0 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { AdminRoutingModule } from './admin-routing.module';
import { DashboardComponent } from './dashboard/dashboard.component';
import {
NgbAccordionModule,
NgbCollapse,
NgbDropdownModule,
NgbNavModule,
NgbTooltipModule,
NgbTypeaheadModule
} from '@ng-bootstrap/ng-bootstrap';
import { ManageLibraryComponent } from './manage-library/manage-library.component';
import { ManageUsersComponent } from './manage-users/manage-users.component';
import { LibraryAccessModalComponent } from './_modals/library-access-modal/library-access-modal.component';
import { DirectoryPickerComponent } from './_modals/directory-picker/directory-picker.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { ResetPasswordModalComponent } from './_modals/reset-password-modal/reset-password-modal.component';
import { ManageSettingsComponent } from './manage-settings/manage-settings.component';
import { ManageSystemComponent } from './manage-system/manage-system.component';
import { InviteUserComponent } from './invite-user/invite-user.component';
import { RoleSelectorComponent } from './role-selector/role-selector.component';
import { LibrarySelectorComponent } from './library-selector/library-selector.component';
import { EditUserComponent } from './edit-user/edit-user.component';
import { UserSettingsModule } from '../user-settings/user-settings.module';
import { ManageMediaSettingsComponent } from './manage-media-settings/manage-media-settings.component';
import { ManageEmailSettingsComponent } from './manage-email-settings/manage-email-settings.component';
import { ManageTasksSettingsComponent } from './manage-tasks-settings/manage-tasks-settings.component';
import { ManageLogsComponent } from './manage-logs/manage-logs.component';
import { VirtualScrollerModule } from '@iharbeck/ngx-virtual-scroller';
import { ManageAlertsComponent } from './manage-alerts/manage-alerts.component';
import {ManageScrobbleErrorsComponent} from "./manage-scrobble-errors/manage-scrobble-errors.component";
import {DefaultValuePipe} from "../pipe/default-value.pipe";
import {LibraryTypePipe} from "../pipe/library-type.pipe";
import {TimeAgoPipe} from "../pipe/time-ago.pipe";
import {SentenceCasePipe} from "../pipe/sentence-case.pipe";
import {FilterPipe} from "../pipe/filter.pipe";
import {TagBadgeComponent} from "../shared/tag-badge/tag-badge.component";
import {LoadingComponent} from "../shared/loading/loading.component";
import {
SideNavCompanionBarComponent
} from "../sidenav/_components/side-nav-companion-bar/side-nav-companion-bar.component";
import {RouterModule} from "@angular/router";
import {LicenseComponent} from "./license/license.component";
@NgModule({
imports: [
CommonModule,
AdminRoutingModule,
ReactiveFormsModule,
RouterModule,
FormsModule,
NgbNavModule,
NgbTooltipModule,
NgbTypeaheadModule,
NgbDropdownModule,
NgbAccordionModule,
UserSettingsModule,
VirtualScrollerModule,
ManageScrobbleErrorsComponent,
DefaultValuePipe,
LibraryTypePipe,
TimeAgoPipe,
SentenceCasePipe,
FilterPipe,
TagBadgeComponent,
LoadingComponent,
SideNavCompanionBarComponent,
NgbCollapse,
ManageUsersComponent,
DashboardComponent,
ManageLibraryComponent,
LibraryAccessModalComponent,
DirectoryPickerComponent,
ResetPasswordModalComponent,
ManageSettingsComponent,
ManageSystemComponent,
InviteUserComponent,
RoleSelectorComponent,
LibrarySelectorComponent,
EditUserComponent,
ManageMediaSettingsComponent,
ManageEmailSettingsComponent,
ManageTasksSettingsComponent,
ManageLogsComponent,
ManageAlertsComponent,
LicenseComponent
],
providers: []
})
export class AdminModule { }

View file

@ -2,7 +2,7 @@ import {ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit} f
import {ActivatedRoute, RouterLink} from '@angular/router';
import {Title} from '@angular/platform-browser';
import {NavService} from '../../_services/nav.service';
import {SentenceCasePipe} from '../../pipe/sentence-case.pipe';
import {SentenceCasePipe} from '../../_pipes/sentence-case.pipe';
import {LicenseComponent} from '../license/license.component';
import {ManageTasksSettingsComponent} from '../manage-tasks-settings/manage-tasks-settings.component';
import {ServerStatsComponent} from '../../statistics/_components/server-stats/server-stats.component';

View file

@ -5,7 +5,7 @@ import { AgeRestriction } from 'src/app/_models/metadata/age-restriction';
import { Library } from 'src/app/_models/library';
import { Member } from 'src/app/_models/auth/member';
import { AccountService } from 'src/app/_services/account.service';
import { SentenceCasePipe } from '../../pipe/sentence-case.pipe';
import { SentenceCasePipe } from '../../_pipes/sentence-case.pipe';
import { RestrictionSelectorComponent } from '../../user-settings/restriction-selector/restriction-selector.component';
import { LibrarySelectorComponent } from '../library-selector/library-selector.component';
import { RoleSelectorComponent } from '../role-selector/role-selector.component';

View file

@ -47,10 +47,10 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" (click)="close()">
{{t('cancel')}}
<button type="button" class="btn btn-{{invited ? 'primary' : 'secondary'}}" (click)="close()">
{{invited ? t('cancel') : t('close')}}
</button>
<button type="button" class="btn btn-primary" (click)="invite()" [disabled]="isSending || !inviteForm.valid || emailLink !== ''">
<button *ngIf="!invited" type="button" class="btn btn-primary" (click)="invite()" [disabled]="isSending || !inviteForm.valid || emailLink !== ''">
<span *ngIf="isSending" class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
<span>{{isSending ? t('inviting') : t('invite')}}</span>
</button>

View file

@ -13,7 +13,7 @@ import { LibrarySelectorComponent } from '../library-selector/library-selector.c
import { RoleSelectorComponent } from '../role-selector/role-selector.component';
import { NgIf } from '@angular/common';
import {translate, TranslocoDirective} from "@ngneat/transloco";
import {SafeHtmlPipe} from "../../pipe/safe-html.pipe";
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
@Component({
selector: 'app-invite-user',

View file

@ -17,7 +17,7 @@ import { ServerService } from 'src/app/_services/server.service';
import { EVENTS, MessageHubService } from 'src/app/_services/message-hub.service';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import { FilterPipe } from '../../pipe/filter.pipe';
import { FilterPipe } from '../../_pipes/filter.pipe';
import { LoadingComponent } from '../../shared/loading/loading.component';
import { NgIf, NgFor } from '@angular/common';
import {TranslocoDirective} from "@ngneat/transloco";

View file

@ -7,7 +7,7 @@ import {ServerSettings} from '../_models/server-settings';
import {NgbTooltip} from '@ng-bootstrap/ng-bootstrap';
import {NgIf, NgTemplateOutlet} from '@angular/common';
import {translate, TranslocoModule, TranslocoService} from "@ngneat/transloco";
import {SafeHtmlPipe} from "../../pipe/safe-html.pipe";
import {SafeHtmlPipe} from "../../_pipes/safe-html.pipe";
import {ServerService} from "../../_services/server.service";
@Component({

View file

@ -17,13 +17,13 @@ import { Library } from 'src/app/_models/library';
import { LibraryService } from 'src/app/_services/library.service';
import { EVENTS, Message, MessageHubService } from 'src/app/_services/message-hub.service';
import {takeUntilDestroyed} from "@angular/core/rxjs-interop";
import { SentenceCasePipe } from '../../pipe/sentence-case.pipe';
import { TimeAgoPipe } from '../../pipe/time-ago.pipe';
import { LibraryTypePipe } from '../../pipe/library-type.pipe';
import { SentenceCasePipe } from '../../_pipes/sentence-case.pipe';
import { TimeAgoPipe } from '../../_pipes/time-ago.pipe';
import { LibraryTypePipe } from '../../_pipes/library-type.pipe';
import { RouterLink } from '@angular/router';
import { NgFor, NgIf } from '@angular/common';
import {translate, TranslocoModule} from "@ngneat/transloco";
import {DefaultDatePipe} from "../../pipe/default-date.pipe";
import {DefaultDatePipe} from "../../_pipes/default-date.pipe";
@Component({
selector: 'app-manage-library',

View file

@ -23,13 +23,13 @@ import {ScrobbleError} from "../../_models/scrobbling/scrobble-error";
import {SeriesService} from "../../_services/series.service";
import {EditSeriesModalComponent} from "../../cards/_modals/edit-series-modal/edit-series-modal.component";
import {NgbModal} from "@ng-bootstrap/ng-bootstrap";
import {FilterPipe} from "../../pipe/filter.pipe";
import {FilterPipe} from "../../_pipes/filter.pipe";
import {LoadingComponent} from "../../shared/loading/loading.component";
import {TranslocoModule} from "@ngneat/transloco";
import {DefaultDatePipe} from "../../pipe/default-date.pipe";
import {DefaultValuePipe} from "../../pipe/default-value.pipe";
import {DefaultDatePipe} from "../../_pipes/default-date.pipe";
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
import {TranslocoLocaleModule} from "@ngneat/transloco-locale";
import {UtcToLocalTimePipe} from "../../pipe/utc-to-local-time.pipe";
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
@Component({
selector: 'app-manage-scrobble-errors',

View file

@ -10,11 +10,11 @@ import {Job} from 'src/app/_models/job/job';
import {UpdateNotificationModalComponent} from 'src/app/shared/update-notification/update-notification-modal.component';
import {NgbModal, NgbTooltip} from '@ng-bootstrap/ng-bootstrap';
import {DownloadService} from 'src/app/shared/_services/download.service';
import {DefaultValuePipe} from '../../pipe/default-value.pipe';
import {DefaultValuePipe} from '../../_pipes/default-value.pipe';
import {AsyncPipe, DatePipe, NgFor, NgIf, NgTemplateOutlet, TitleCasePipe} from '@angular/common';
import {TranslocoModule, TranslocoService} from "@ngneat/transloco";
import {TranslocoLocaleModule} from "@ngneat/transloco-locale";
import {UtcToLocalTimePipe} from "../../pipe/utc-to-local-time.pipe";
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
interface AdhocTask {
name: string;

View file

@ -11,12 +11,7 @@
<li *ngFor="let member of members; let idx = index;" class="list-group-item no-hover">
<div>
<h4>
<span id="member-name--{{idx}}">{{member.username | titlecase}} </span>
<span *ngIf="member.username === loggedInUsername">
<i class="fas fa-star" aria-hidden="true"></i>
<span class="visually-hidden">{{t('you-alt')}}</span>
</span>
<span class="badge bg-secondary text-dark" *ngIf="member.isPending">{{t('pending-title')}}</span>
<span id="member-name--{{idx}}" [ngClass]="{'highlight': member.username === loggedInUsername}">{{member.username | titlecase}}</span>
<div class="float-end" *ngIf="canEditMember(member)">
<button class="btn btn-danger btn-sm me-2" (click)="deleteUser(member)"
placement="top" [ngbTooltip]="t('delete-user-tooltip')" [attr.aria-label]="t('delete-user-alt', {user: member.username | titlecase})">
@ -27,24 +22,37 @@
<i class="fa fa-pen" aria-hidden="true"></i>
</button>
<button *ngIf="member.isPending" class="btn btn-secondary btn-sm me-2" (click)="resendEmail(member)"
placement="top" [ngbTooltip]="t('resend-invite-tooltip')" [attr.aria-label]="t('resend-invite-alt', {user: member.username | titlecase})">{{t('resend')}}</button>
<button *ngIf="member.isPending" class="btn btn-secondary btn-sm me-2" (click)="setup(member)"
placement="top" [ngbTooltip]="t('setup-user-tooltip')" [attr.aria-label]="t('setup-user-alt', {user: member.username | titlecase})">Setup</button>
<ng-container *ngIf="member.isPending">
<button class="btn btn-secondary btn-sm me-2" (click)="resendEmail(member)"
placement="top" [ngbTooltip]="t('resend-invite-tooltip')" [attr.aria-label]="t('resend-invite-alt', {user: member.username | titlecase})"><i class="fa-solid fa-share-from-square" aria-hidden="true"></i></button>
<button class="btn btn-secondary btn-sm" (click)="setup(member)"
placement="top" [ngbTooltip]="t('setup-user-tooltip')" [attr.aria-label]="t('setup-user-alt', {user: member.username | titlecase})"><i class="fa-solid fa-sliders" aria-hidden="true"></i></button>
</ng-container>
<button *ngIf="!member.isPending" class="btn btn-secondary btn-sm" (click)="updatePassword(member)"
placement="top" [ngbTooltip]="t('change-password-tooltip')" [attr.aria-label]="t('change-password-alt', {user: member.username | titlecase})"><i class="fa fa-key" aria-hidden="true"></i></button>
</div>
</h4>
<div class="user-info">
<div>{{t('last-active-title')}}
<span>{{member.lastActive | date: 'short' | defaultDate}} <i class="presence fa fa-circle ms-1" [title]="t('online-now-tooltip')" aria-hidden="true" *ngIf="(messageHub.onlineUsers$ | async)?.includes(member.username)"></i></span>
<span class="badge bg-secondary text-dark ms-1 pending-badge" *ngIf="member.isPending; else activeTime">{{t('pending-title')}}</span>
<ng-template #activeTime>
<span>{{member.lastActiveUtc | utcToLocalTime | defaultDate}} <i class="presence fa fa-circle ms-1" [title]="t('online-now-tooltip')" aria-hidden="true" *ngIf="(messageHub.onlineUsers$ | async)?.includes(member.username)"></i></span>
</ng-template>
</div>
<div *ngIf="!hasAdminRole(member) && member.libraries.length > 0">
{{t('sharing-title')}}
<app-tag-badge *ngFor="let lib of member.libraries" class="col-auto">{{lib.name}}</app-tag-badge>
</div>
<div *ngIf="!hasAdminRole(member)">{{t('sharing-title')}} {{formatLibraries(member)}}</div>
<div class="row g-0">
<div>
{{t('roles-title')}} <span *ngIf="getRoles(member).length === 0; else showRoles">{{t('none')}}</span>
<div *ngIf="getRoles(member) as roles">
{{t('roles-title')}} <span *ngIf="roles.length === 0; else showRoles">{{null | defaultValue}}</span>
<ng-template #showRoles>
<app-tag-badge *ngFor="let role of getRoles(member)" class="col-auto">{{role}}</app-tag-badge>
<ng-container *ngIf="hasAdminRole(member); else allRoles">
<app-tag-badge class="col-auto">Admin</app-tag-badge>
</ng-container>
<ng-template #allRoles>
<app-tag-badge *ngFor="let role of roles" class="col-auto">{{role}}</app-tag-badge>
</ng-template>
</ng-template>
</div>
</div>

View file

@ -6,3 +6,11 @@
.user-info > div {
margin-top: 3px;
}
.highlight {
color: var(--primary-color);
}
.pending-badge {
font-size: 15px;
}

View file

@ -13,9 +13,12 @@ import {EditUserComponent} from '../edit-user/edit-user.component';
import {ServerService} from 'src/app/_services/server.service';
import {Router} from '@angular/router';
import {TagBadgeComponent} from '../../shared/tag-badge/tag-badge.component';
import {AsyncPipe, DatePipe, NgFor, NgIf, TitleCasePipe} from '@angular/common';
import {TranslocoModule, TranslocoService} from "@ngneat/transloco";
import {DefaultDatePipe} from "../../pipe/default-date.pipe";
import {AsyncPipe, DatePipe, NgClass, NgFor, NgIf, TitleCasePipe} from '@angular/common';
import {translate, TranslocoModule, TranslocoService} from "@ngneat/transloco";
import {DefaultDatePipe} from "../../_pipes/default-date.pipe";
import {DefaultValuePipe} from "../../_pipes/default-value.pipe";
import {ReadMoreComponent} from "../../shared/read-more/read-more.component";
import {UtcToLocalTimePipe} from "../../_pipes/utc-to-local-time.pipe";
@Component({
selector: 'app-manage-users',
@ -23,7 +26,7 @@ import {DefaultDatePipe} from "../../pipe/default-date.pipe";
styleUrls: ['./manage-users.component.scss'],
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [NgFor, NgIf, NgbTooltip, TagBadgeComponent, AsyncPipe, TitleCasePipe, DatePipe, TranslocoModule, DefaultDatePipe]
imports: [NgFor, NgIf, NgbTooltip, TagBadgeComponent, AsyncPipe, TitleCasePipe, DatePipe, TranslocoModule, DefaultDatePipe, NgClass, DefaultValuePipe, ReadMoreComponent, UtcToLocalTimePipe]
})
export class ManageUsersComponent implements OnInit {
@ -31,24 +34,24 @@ export class ManageUsersComponent implements OnInit {
loggedInUsername = '';
loadingMembers = false;
translocoService = inject(TranslocoService);
cdRef = inject(ChangeDetectorRef);
private readonly translocoService = inject(TranslocoService);
private readonly cdRef = inject(ChangeDetectorRef);
private readonly memberService = inject(MemberService);
private readonly accountService = inject(AccountService);
private readonly modalService = inject(NgbModal);
private readonly toastr = inject(ToastrService);
private readonly confirmService = inject(ConfirmService);
public readonly messageHub = inject(MessageHubService);
private readonly serverService = inject(ServerService);
private readonly router = inject(Router);
constructor(private memberService: MemberService,
private accountService: AccountService,
private modalService: NgbModal,
private toastr: ToastrService,
private confirmService: ConfirmService,
public messageHub: MessageHubService,
private serverService: ServerService,
private router: Router) {
constructor() {
this.accountService.currentUser$.pipe(take(1)).subscribe((user) => {
if (user) {
this.loggedInUsername = user.username;
this.cdRef.markForCheck();
}
});
}
ngOnInit(): void {
@ -136,7 +139,7 @@ export class ManageUsersComponent implements OnInit {
formatLibraries(member: Member) {
if (member.libraries.length === 0) {
return this.translocoService.translate('manage-users.none');
return translate('manage-users.none');
}
return member.libraries.map(item => item.name).join(', ');