diff --git a/package.json b/package.json
index 0dc91bf..9d625ee 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"@fortawesome/free-brands-svg-icons": "^6.4.2",
"@fortawesome/free-regular-svg-icons": "^6.4.2",
"@fortawesome/free-solid-svg-icons": "^6.4.2",
+ "@ngneat/dialog": "5.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index b26c8b9..45ad71a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -44,6 +44,9 @@ dependencies:
'@fortawesome/free-solid-svg-icons':
specifier: ^6.4.2
version: 6.5.1
+ '@ngneat/dialog':
+ specifier: 5.0.0
+ version: 5.0.0(@angular/core@17.2.3)
rxjs:
specifier: ~7.8.0
version: 7.8.1
@@ -2433,6 +2436,15 @@ packages:
call-bind: 1.0.7
dev: true
+ /@ngneat/dialog@5.0.0(@angular/core@17.2.3):
+ resolution: {integrity: sha512-+qLGaLcNXQ5PVtlv4htqHsJ4JV9TZ+wy89rtYMsno/jZuB63usMITPEB7TgtEPgpbyDDcYVagA6eQqYMEgZPOA==}
+ peerDependencies:
+ '@angular/core': '>=17.0.0'
+ dependencies:
+ '@angular/core': 17.2.3(rxjs@7.8.1)(zone.js@0.14.4)
+ tslib: 2.3.1
+ dev: false
+
/@ngtools/webpack@17.2.2(@angular/compiler-cli@17.2.3)(typescript@5.3.3)(webpack@5.90.1):
resolution: {integrity: sha512-HgvClGO6WVq4VA5d0ZvlDG5hrj8lQzRH99Gt87URm7G8E5XkatysdOsMqUQsJz+OwFWhP4PvTRWVblpBDiDl/A==}
engines: {node: ^18.13.0 || >=20.9.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'}
@@ -5893,8 +5905,6 @@ packages:
peerDependenciesMeta:
webpack:
optional: true
- webpack-sources:
- optional: true
dependencies:
webpack: 5.90.1(esbuild@0.20.0)
webpack-sources: 3.2.3
@@ -8054,6 +8064,10 @@ packages:
strip-bom: 3.0.0
dev: true
+ /tslib@2.3.1:
+ resolution: {integrity: sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==}
+ dev: false
+
/tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 72a5291..5496f27 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -2,5 +2,6 @@
+
diff --git a/src/app/app.component.less b/src/app/app.component.less
index ff8bb98..7e65688 100644
--- a/src/app/app.component.less
+++ b/src/app/app.component.less
@@ -2,6 +2,7 @@
display: block;
width: 100%;
height: calc(100% - 2rem);
- background: url("../assets/img/wallpaper.png");
- background-size: cover;
+ background-image: url("../assets/img/wallpaper.png");
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
}
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 0b7248f..876f596 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,12 +1,12 @@
import { Component } from "@angular/core";
-import { RouterOutlet } from "@angular/router";
import { DockComponent } from "./modules/dock/dock.component";
+import { ModalComponent } from "./modules/modal/modal.component";
import { PanelComponent } from "./modules/panel/panel.component";
@Component({
selector: "app-root",
standalone: true,
- imports: [RouterOutlet, PanelComponent, DockComponent],
+ imports: [PanelComponent, DockComponent, ModalComponent],
templateUrl: "./app.component.html",
styleUrl: "./app.component.less",
})
diff --git a/src/app/app.config.ts b/src/app/app.config.ts
index 6c6ef60..2af3ac9 100644
--- a/src/app/app.config.ts
+++ b/src/app/app.config.ts
@@ -1,8 +1,24 @@
-import { ApplicationConfig } from '@angular/core';
-import { provideRouter } from '@angular/router';
+import { APP_INITIALIZER, ApplicationConfig } from "@angular/core";
+import { provideRouter } from "@angular/router";
-import { routes } from './app.routes';
+import { provideHttpClient } from "@angular/common/http";
+import { routes } from "./app.routes";
+import { TranslateService } from "./services/translate.service";
+
+export function setupTranslateServiceFactory(service: TranslateService) {
+ return () => service.use("en");
+}
export const appConfig: ApplicationConfig = {
- providers: [provideRouter(routes)]
+ providers: [
+ provideRouter(routes),
+ provideHttpClient(),
+ TranslateService,
+ {
+ provide: APP_INITIALIZER,
+ useFactory: setupTranslateServiceFactory,
+ deps: [TranslateService],
+ multi: true,
+ },
+ ],
};
diff --git a/src/app/modules/dock/dock.component.ts b/src/app/modules/dock/dock.component.ts
index 24a7212..a1a7a3b 100644
--- a/src/app/modules/dock/dock.component.ts
+++ b/src/app/modules/dock/dock.component.ts
@@ -16,19 +16,19 @@ export class DockComponent {
id: 0,
svg: "../../../assets/svg/logo-telegram.svg",
url: "https://t.me/neur0w0men",
- text: "Telegram channel",
+ text: "TELEGRAM_LABEL",
},
{
id: 1,
svg: "../../../assets/svg/logo-github.svg",
url: "https://github.com/MrSedan",
- text: "Admin's GitHub",
+ text: "GITHUB_LABEL",
},
{
id: 2,
svg: "../../../assets/svg/logo-gitea.svg",
url: "https://git.nwaifu.su",
- text: "Gitea",
+ text: "GITEA_LABEL",
},
];
}
diff --git a/src/app/modules/link/link.component.html b/src/app/modules/link/link.component.html
index 522d164..580ecaa 100644
--- a/src/app/modules/link/link.component.html
+++ b/src/app/modules/link/link.component.html
@@ -1,4 +1,4 @@
- {{ text }}
+ {{ text | translate }}
diff --git a/src/app/modules/link/link.component.ts b/src/app/modules/link/link.component.ts
index 31036bc..fe786e9 100644
--- a/src/app/modules/link/link.component.ts
+++ b/src/app/modules/link/link.component.ts
@@ -1,10 +1,11 @@
import { CommonModule } from "@angular/common";
import { Component, Input } from "@angular/core";
+import { TranslationPipe } from "../../pipes/translation.pipe";
@Component({
standalone: true,
selector: "app-link",
- imports: [CommonModule],
+ imports: [CommonModule, TranslationPipe],
templateUrl: "./link.component.html",
styleUrls: ["./link.component.less"],
})
diff --git a/src/app/modules/modal/modal.component.html b/src/app/modules/modal/modal.component.html
new file mode 100644
index 0000000..c69b526
--- /dev/null
+++ b/src/app/modules/modal/modal.component.html
@@ -0,0 +1 @@
+
diff --git a/src/app/modules/modal/modal.component.less b/src/app/modules/modal/modal.component.less
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/modules/modal/modal.component.ts b/src/app/modules/modal/modal.component.ts
new file mode 100644
index 0000000..48fd4ae
--- /dev/null
+++ b/src/app/modules/modal/modal.component.ts
@@ -0,0 +1,31 @@
+import { CommonModule } from "@angular/common";
+import { AfterViewInit, Component, ElementRef, ViewChild } from "@angular/core";
+import { DialogRef, DialogService } from "@ngneat/dialog";
+import { WindowComponent } from "../window/window.component";
+
+@Component({
+ selector: "app-modal",
+ templateUrl: "./modal.component.html",
+ styleUrls: ["./modal.component.less"],
+ imports: [CommonModule],
+ standalone: true,
+})
+export class ModalComponent implements AfterViewInit {
+ dialogRef: DialogRef | undefined = undefined;
+ @ViewChild("modal") modal: ElementRef | undefined = undefined;
+ constructor(private dialogService: DialogService, private ref: ElementRef) {}
+ ngAfterViewInit(): void {
+ this.dialogRef = this.dialogService.open(WindowComponent, {
+ resizable: true,
+ draggable: true,
+ backdrop: false,
+ closeButton: false,
+ container: this.modal ?? this.ref,
+ enableClose: false,
+ dragConstraint: "constrain",
+ id: "info-modal",
+ minWidth: "300px",
+ minHeight: "10rem",
+ });
+ }
+}
diff --git a/src/app/modules/panel/panel.component.html b/src/app/modules/panel/panel.component.html
index 0da7a76..0350ee5 100644
--- a/src/app/modules/panel/panel.component.html
+++ b/src/app/modules/panel/panel.component.html
@@ -7,7 +7,14 @@
{{ time }}
+
+
en - English
+
ru - Русский
+
ja - 日本語
+
diff --git a/src/app/modules/panel/panel.component.less b/src/app/modules/panel/panel.component.less
index 9238921..94daf1d 100644
--- a/src/app/modules/panel/panel.component.less
+++ b/src/app/modules/panel/panel.component.less
@@ -1,4 +1,5 @@
.panel {
+ z-index: 99999;
position: relative;
left: 0;
top: 0;
@@ -62,3 +63,43 @@
cursor: pointer;
}
}
+.lang-choose {
+ position: absolute;
+ display: none;
+ &.active {
+ display: flex;
+ }
+ top: 0;
+ flex-direction: column;
+ justify-content: space-around;
+ gap: 0;
+ background-color: var(--black);
+ margin-block-start: 3rem;
+ z-index: 9999;
+ margin-inline-end: 1rem;
+ color: var(--white);
+ padding: 1rem 0;
+ border-radius: 15px;
+ &::before {
+ content: "";
+ position: absolute;
+ left: 50%;
+ transform: translateX(-50%) rotate(45deg);
+ vertical-align: middle;
+ top: -0.5rem;
+ width: 0;
+ height: 0;
+ border: 10px solid var(--black);
+ }
+ p {
+ line-height: 2rem;
+ width: 100%;
+ padding: 0.5rem 1rem;
+ user-select: none;
+ -webkit-user-select: none;
+ cursor: pointer;
+ &:hover {
+ background-color: #000;
+ }
+ }
+}
diff --git a/src/app/modules/panel/panel.component.ts b/src/app/modules/panel/panel.component.ts
index 50737c4..09f5f0d 100644
--- a/src/app/modules/panel/panel.component.ts
+++ b/src/app/modules/panel/panel.component.ts
@@ -1,9 +1,10 @@
import { CommonModule } from "@angular/common";
-import { Component } from "@angular/core";
+import { Component, ElementRef, HostListener, ViewChild } from "@angular/core";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { faGithub } from "@fortawesome/free-brands-svg-icons";
import { faPowerOff, faVolumeHigh } from "@fortawesome/free-solid-svg-icons";
import { PanelSevice } from "../../services/panel.service";
+import { TranslateService } from "../../services/translate.service";
@Component({
standalone: true,
@@ -17,7 +18,11 @@ export class PanelComponent {
faGithub = faGithub;
faVolume = faVolumeHigh;
faPower = faPowerOff;
- constructor(private panelService: PanelSevice) {
+ showLangModalBool = false;
+ @ViewChild("lang_modal") langModal: ElementRef | null = null;
+ @ViewChild("lang_btn") langBtn: ElementRef | null = null;
+
+ constructor(private panelService: PanelSevice, private translateService: TranslateService) {
this.time = this.getTime();
setInterval(() => {
this.time = this.getTime();
@@ -26,7 +31,7 @@ export class PanelComponent {
private getTime() {
const time = this.panelService.getTime();
- return time.toLocaleDateString("en-US", {
+ return time.toLocaleDateString(this.translateService.translate("TIME_SCHEMA"), {
month: "short",
day: "numeric",
hour: "numeric",
@@ -37,4 +42,31 @@ export class PanelComponent {
goToSource() {
window.open("https://git.nwaifu.su/neuro_llc/NwaifuWeb", "_blank");
}
+
+ @HostListener("window:resize")
+ private moveLangModal() {
+ if (!this.langModal || !this.langBtn) {
+ return;
+ }
+
+ const x = this.langBtn.nativeElement.getBoundingClientRect().x;
+ this.langModal.nativeElement.style.left = `calc(${x}px - 3.5rem)`;
+ }
+
+ toggleModal() {
+ if (this.langModal) {
+ this.langModal.nativeElement.classList.toggle("active");
+ if (this.langModal.nativeElement.classList.contains("active")) {
+ this.moveLangModal();
+ }
+ }
+ }
+
+ useLang(lang: string) {
+ this.translateService.use(lang);
+ }
+
+ getLang() {
+ return this.translateService.lang;
+ }
}
diff --git a/src/app/modules/window/window.component.html b/src/app/modules/window/window.component.html
new file mode 100644
index 0000000..bd377db
--- /dev/null
+++ b/src/app/modules/window/window.component.html
@@ -0,0 +1,10 @@
+
+
{{ modal_title | translate }}
+
+
+
+
+
+
+
{{ modal_text | translate }}
+
diff --git a/src/app/modules/window/window.component.less b/src/app/modules/window/window.component.less
new file mode 100644
index 0000000..59f4306
--- /dev/null
+++ b/src/app/modules/window/window.component.less
@@ -0,0 +1,24 @@
+.panel {
+ width: 100%;
+ display: flex;
+ height: 3rem;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ padding: 0 1rem;
+ background-color: var(--black);
+ color: var(--white);
+ span {
+ font-size: 600;
+ }
+ .btns {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-end;
+ align-items: center;
+ gap: 1rem;
+ }
+}
+.content {
+ margin: 1rem;
+}
diff --git a/src/app/modules/window/window.component.ts b/src/app/modules/window/window.component.ts
new file mode 100644
index 0000000..db5642a
--- /dev/null
+++ b/src/app/modules/window/window.component.ts
@@ -0,0 +1,22 @@
+import { CommonModule } from "@angular/common";
+import { Component } from "@angular/core";
+import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
+import { faBars, faXmark } from "@fortawesome/free-solid-svg-icons";
+import { DialogRef } from "@ngneat/dialog";
+import { TranslationPipe } from "../../pipes/translation.pipe";
+
+@Component({
+ selector: "app-window",
+ standalone: true,
+ imports: [CommonModule, FontAwesomeModule, TranslationPipe],
+ templateUrl: "./window.component.html",
+ styleUrls: ["./window.component.less"],
+ // changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class WindowComponent {
+ modal_text = "MODAL_TEXT";
+ modal_title = "MODAL_TITLE";
+ faClose = faXmark;
+ faMenu = faBars;
+ constructor(public ref: DialogRef) {}
+}
diff --git a/src/app/pipes/translation.pipe.ts b/src/app/pipes/translation.pipe.ts
new file mode 100644
index 0000000..de13ada
--- /dev/null
+++ b/src/app/pipes/translation.pipe.ts
@@ -0,0 +1,14 @@
+import { Pipe, PipeTransform } from "@angular/core";
+import { TranslateService } from "../services/translate.service";
+
+@Pipe({
+ name: "translate",
+ standalone: true,
+ pure: false,
+})
+export class TranslationPipe implements PipeTransform {
+ constructor(private translateService: TranslateService) {}
+ transform(key: string) {
+ return this.translateService.data[key] ?? key;
+ }
+}
diff --git a/src/app/services/translate.service.ts b/src/app/services/translate.service.ts
new file mode 100644
index 0000000..94c5502
--- /dev/null
+++ b/src/app/services/translate.service.ts
@@ -0,0 +1,30 @@
+import { HttpClient } from "@angular/common/http";
+import { Injectable } from "@angular/core";
+
+@Injectable({ providedIn: "root" })
+export class TranslateService {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ data: Record = {};
+ lang = "en";
+ constructor(private http: HttpClient) {}
+ use(lang: string): Promise