feat: auth page
This commit is contained in:
34
apps/NwaifuAnime/src/app/components/auth/auth.component.html
Normal file
34
apps/NwaifuAnime/src/app/components/auth/auth.component.html
Normal file
@@ -0,0 +1,34 @@
|
||||
<div class="flex flex-col m-6">
|
||||
<div class="mangalib-auth">
|
||||
<h2>Авторизация в MangaLib</h2>
|
||||
<ol class="list-decimal flex flex-col gap-4">
|
||||
<li>
|
||||
<p class="font-bold">Авторизация через токен</p>
|
||||
<div class="flex flex-row gap-4">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Token"
|
||||
class="outline-none border-md border px-2"
|
||||
#libSocialToken
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
(click)="setLibSocialToken()"
|
||||
class="hover:bg-slate-600 bg-slate-400 p-3 rounded-md text-white"
|
||||
>
|
||||
Сохранить
|
||||
</button>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
Вход через скрипт TamperMonkey. Если нет кнопки, значит вы не установили скрипт
|
||||
<a
|
||||
href="https://test-front.mangalib.me"
|
||||
class="hover:bg-slate-600 bg-slate-400 p-3 rounded-md text-white tamperMonkey"
|
||||
>
|
||||
Вход
|
||||
</a>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
.tamperMonkey {
|
||||
display: none;
|
||||
}
|
||||
58
apps/NwaifuAnime/src/app/components/auth/auth.component.ts
Normal file
58
apps/NwaifuAnime/src/app/components/auth/auth.component.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from "@angular/core";
|
||||
import { ActivatedRoute, Router, RouterLink } from "@angular/router";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
import { RulibAuthService } from "../../services/parsers/rulib/rulib.auth.service";
|
||||
import { EAuthTokenService } from "./enum";
|
||||
|
||||
@Component({
|
||||
selector: "app-auth",
|
||||
templateUrl: "./auth.component.html",
|
||||
styleUrls: ["./auth.component.less"],
|
||||
standalone: true,
|
||||
imports: [CommonModule, RouterLink],
|
||||
})
|
||||
export class AuthComponent implements AfterViewInit, OnDestroy {
|
||||
private destroy$ = new Subject<void>();
|
||||
@ViewChild("libSocialToken") libSocialToken: ElementRef<HTMLInputElement> | null = null;
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private rulibAuthService: RulibAuthService,
|
||||
) {}
|
||||
|
||||
private setToken(service: EAuthTokenService, token: string) {
|
||||
switch (service) {
|
||||
case EAuthTokenService.RULIB:
|
||||
this.rulibAuthService.setToken(token);
|
||||
break;
|
||||
default:
|
||||
this.router.navigate(["/", "auth"]);
|
||||
return;
|
||||
}
|
||||
this.router.navigate(["/"]);
|
||||
}
|
||||
|
||||
setLibSocialToken() {
|
||||
if (this.libSocialToken) {
|
||||
const token = this.libSocialToken.nativeElement.value;
|
||||
this.setToken(EAuthTokenService.RULIB, token);
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.route.queryParams.pipe(takeUntil(this.destroy$)).subscribe((params) => {
|
||||
const { token, service } = params;
|
||||
if (token && service) {
|
||||
this.setToken(service as EAuthTokenService, token);
|
||||
}
|
||||
});
|
||||
if (this.libSocialToken) {
|
||||
this.libSocialToken.nativeElement.value = this.rulibAuthService.getToken();
|
||||
}
|
||||
}
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
}
|
||||
3
apps/NwaifuAnime/src/app/components/auth/enum.ts
Normal file
3
apps/NwaifuAnime/src/app/components/auth/enum.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export enum EAuthTokenService {
|
||||
RULIB = "rulib",
|
||||
}
|
||||
@@ -1,38 +1,44 @@
|
||||
<div class="flex flex-col items-center">
|
||||
@if (needAuth) {
|
||||
<h1>Необходима авторизация</h1>
|
||||
<a routerLink="/auth" class="text-center bg-slate-600 text-white p-3 rounded-md mb-4">Войти</a>
|
||||
}
|
||||
@if (detail_item) {
|
||||
<h1>{{ detail_item.name }}</h1>
|
||||
<h2>{{ detail_item.rus_name }}</h2>
|
||||
<img [src]="detail_item.cover.default" [alt]="detail_item.slug" />
|
||||
|
||||
<details class="w-full">
|
||||
<summary class="text-center sticky top-0 bg-white z-10 py-2">
|
||||
<h3>Главы</h3>
|
||||
</summary>
|
||||
<div class="flex flex-col items-center pb-16">
|
||||
@for (chapter of chapters.data; track $index) {
|
||||
<a
|
||||
routerLink="/reader"
|
||||
[queryParams]="{
|
||||
url: detail_item.slug_url,
|
||||
chapter: chapter.number,
|
||||
volume: chapter.volume,
|
||||
}"
|
||||
[title]="chapter.name"
|
||||
class="p-3 text-white bg-slate-600 w-[300px] mt-3 rounded-lg"
|
||||
>
|
||||
<h3>
|
||||
<strong>{{ chapter.number }}.</strong> {{ chapter.name || "Нет названия" }}
|
||||
</h3>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</details>
|
||||
<a
|
||||
routerLink="/reader"
|
||||
class="p-3 text-white bg-slate-600 w-[300px] mt-5 rounded-lg text-center"
|
||||
[queryParams]="{ url: detail_item.slug_url, volume: 1, chapter: 1 }"
|
||||
>
|
||||
Читать
|
||||
</a>
|
||||
@if (!needAuth) {
|
||||
<details class="w-full">
|
||||
<summary class="text-center sticky top-0 bg-white z-10 py-2">
|
||||
<h3>Главы</h3>
|
||||
</summary>
|
||||
<div class="flex flex-col items-center pb-16">
|
||||
@for (chapter of chapters.data; track $index) {
|
||||
<a
|
||||
routerLink="/reader"
|
||||
[queryParams]="{
|
||||
url: detail_item.slug_url,
|
||||
chapter: chapter.number,
|
||||
volume: chapter.volume,
|
||||
}"
|
||||
[title]="chapter.name"
|
||||
class="p-3 text-white bg-slate-600 w-[300px] mt-3 rounded-lg"
|
||||
>
|
||||
<h3>
|
||||
<strong>{{ chapter.number }}.</strong> {{ chapter.name || "Нет названия" }}
|
||||
</h3>
|
||||
</a>
|
||||
}
|
||||
</div>
|
||||
</details>
|
||||
<a
|
||||
routerLink="/reader"
|
||||
class="p-3 text-white bg-slate-600 w-[300px] mt-5 rounded-lg text-center"
|
||||
[queryParams]="{ url: detail_item.slug_url, volume: 1, chapter: 1 }"
|
||||
>
|
||||
Читать
|
||||
</a>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { SearchService } from "../../services/search.service";
|
||||
export class DetailComponent implements AfterViewInit, OnDestroy {
|
||||
detail_item: Data | null = null;
|
||||
chapters: IRulibChaptersResult = { data: [] };
|
||||
needAuth: boolean = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
@@ -27,15 +28,27 @@ export class DetailComponent implements AfterViewInit, OnDestroy {
|
||||
this.searchService
|
||||
.getDetails(url)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((data) => {
|
||||
this.detail_item = data.data;
|
||||
.subscribe({
|
||||
next: (data) => {
|
||||
this.detail_item = data.data;
|
||||
},
|
||||
error: (error) => {
|
||||
console.log(error);
|
||||
},
|
||||
});
|
||||
this.searchService
|
||||
.getChapters(url)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((data) => {
|
||||
this.chapters = data;
|
||||
console.log(data);
|
||||
.subscribe({
|
||||
next: (data) => {
|
||||
this.chapters = data;
|
||||
if (data.data.length === 0) {
|
||||
this.needAuth = true;
|
||||
}
|
||||
},
|
||||
error: (error) => {
|
||||
console.log(error);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user