diff --git a/api/src/api_graphql/input/short_url_create_input.py b/api/src/api_graphql/input/short_url_create_input.py index c5f0fea..bb01aca 100644 --- a/api/src/api_graphql/input/short_url_create_input.py +++ b/api/src/api_graphql/input/short_url_create_input.py @@ -12,7 +12,7 @@ class ShortUrlCreateInput(InputABC): self._target_url = self.option("targetUrl", str, required=True) self._description = self.option("description", str) self._group_id = self.option("groupId", int) - self._loading_screen = self.option("loadingScreen", str) + self._loading_screen = self.option("loadingScreen", bool) @property def short_url(self) -> str: diff --git a/api/src/api_graphql/input/short_url_update_input.py b/api/src/api_graphql/input/short_url_update_input.py index d9628e7..2e4bb13 100644 --- a/api/src/api_graphql/input/short_url_update_input.py +++ b/api/src/api_graphql/input/short_url_update_input.py @@ -13,7 +13,7 @@ class ShortUrlUpdateInput(InputABC): self._target_url = self.option("targetUrl", str) self._description = self.option("description", str) self._group_id = self.option("groupId", int) - self._loading_screen = self.option("loadingScreen", str) + self._loading_screen = self.option("loadingScreen", bool) @property def id(self) -> int: diff --git a/version.txt b/version.txt index 341cf11..7dff5b8 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.2.0 \ No newline at end of file +0.2.1 \ No newline at end of file diff --git a/web/.eslintrc.json b/web/.eslintrc.json new file mode 100644 index 0000000..4f76606 --- /dev/null +++ b/web/.eslintrc.json @@ -0,0 +1,56 @@ +{ + "root": true, + "ignorePatterns": [ + "projects/**/*" + ], + "overrides": [ + { + "files": [ + "*.ts" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:@angular-eslint/recommended", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "rules": { + "@angular-eslint/component-class-suffix": [ + "error", + { + "suffixes": [ + "Page", + "Component" + ] + } + ], + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ] + } + }, + { + "files": [ + "*.html" + ], + "extends": [ + "plugin:@angular-eslint/template/recommended", + "plugin:@angular-eslint/template/accessibility" + ], + "rules": {} + } + ] +} diff --git a/web/.prettierrc.json b/web/.prettierrc.json new file mode 100644 index 0000000..33508a3 --- /dev/null +++ b/web/.prettierrc.json @@ -0,0 +1,12 @@ +{ + "tabWidth": 2, + "useTabs": false, + "singleQuote": true, + "semi": true, + "bracketSpacing": true, + "arrowParens": "avoid", + "trailingComma": "es5", + "bracketSameLine": true, + "printWidth": 80, + "endOfLine": "auto" +} diff --git a/web/src/app/components/redirect/redirect.component.ts b/web/src/app/components/redirect/redirect.component.ts index 5f90766..30e1ea4 100644 --- a/web/src/app/components/redirect/redirect.component.ts +++ b/web/src/app/components/redirect/redirect.component.ts @@ -1,17 +1,16 @@ -import { Component, OnInit } from "@angular/core"; -import { SidebarService } from "src/app/service/sidebar.service"; -import { Router } from "@angular/router"; -import { HttpClient } from "@angular/common/http"; -import { ShortUrlDto } from "src/app/model/entities/short-url"; -import { SettingsService } from "src/app/service/settings.service"; -import { AppSettings } from "src/app/model/config/app-settings"; -import { GuiService } from "src/app/service/gui.service"; -import { SpinnerService } from "src/app/service/spinner.service"; +import { Component, OnInit } from '@angular/core'; +import { SidebarService } from 'src/app/service/sidebar.service'; +import { Router } from '@angular/router'; +import { HttpClient } from '@angular/common/http'; +import { ShortUrlDto } from 'src/app/model/entities/short-url'; +import { SettingsService } from 'src/app/service/settings.service'; +import { AppSettings } from 'src/app/model/config/app-settings'; +import { GuiService } from 'src/app/service/gui.service'; @Component({ - selector: "app-redirect", - templateUrl: "./redirect.component.html", - styleUrl: "./redirect.component.scss", + selector: 'app-redirect', + templateUrl: './redirect.component.html', + styleUrl: './redirect.component.scss', }) export class RedirectComponent implements OnInit { defaultSecs = 5; @@ -24,7 +23,7 @@ export class RedirectComponent implements OnInit { private router: Router, private http: HttpClient, private settingsService: SettingsService, - private gui: GuiService, + private gui: GuiService ) { this.sidebar.hide(); this.gui.hide(); @@ -36,19 +35,19 @@ export class RedirectComponent implements OnInit { handleUrl() { let shortUrl = this.router.url; - if (shortUrl === "/") { + if (shortUrl === '/') { return; } - if (shortUrl.startsWith("/")) { + if (shortUrl.startsWith('/')) { shortUrl = shortUrl.substring(1); } this.http .get(`${this.settings.api.url}/find/${shortUrl}`) - .subscribe(async (response) => { + .subscribe(async response => { if (!response) { - await this.router.navigate(["/404"]); + await this.router.navigate(['/404']); return; } diff --git a/web/src/app/core/init-keycloak.ts b/web/src/app/core/init-keycloak.ts index 48785ff..11aa944 100644 --- a/web/src/app/core/init-keycloak.ts +++ b/web/src/app/core/init-keycloak.ts @@ -1,10 +1,9 @@ -import { KeycloakService } from "keycloak-angular"; -import { environment } from "src/environments/environment"; -import { SettingsService } from "src/app/service/settings.service"; +import { KeycloakService } from 'keycloak-angular'; +import { SettingsService } from 'src/app/service/settings.service'; export function initializeKeycloak( keycloak: KeycloakService, - settings: SettingsService, + settings: SettingsService ): Promise { return keycloak.init({ config: { @@ -13,7 +12,7 @@ export function initializeKeycloak( clientId: settings.settings.keycloak.clientId, }, initOptions: { - onLoad: "check-sso", + onLoad: 'check-sso', }, enableBearerInterceptor: false, }); diff --git a/web/src/app/model/entities/group.ts b/web/src/app/model/entities/group.ts index bb544b9..5437ff1 100644 --- a/web/src/app/model/entities/group.ts +++ b/web/src/app/model/entities/group.ts @@ -1,5 +1,4 @@ -import { DbModel } from "src/app/model/entities/db-model"; -import { Permission } from "src/app/model/entities/role"; +import { DbModel } from 'src/app/model/entities/db-model'; export interface Group extends DbModel { name: string; diff --git a/web/src/app/model/entities/short-url.ts b/web/src/app/model/entities/short-url.ts index f235ef3..3007473 100644 --- a/web/src/app/model/entities/short-url.ts +++ b/web/src/app/model/entities/short-url.ts @@ -1,11 +1,11 @@ -import { DbModel } from "src/app/model/entities/db-model"; -import { Permission } from "src/app/model/entities/role"; -import { Group } from "src/app/model/entities/group"; +import { DbModel } from 'src/app/model/entities/db-model'; +import { Group } from 'src/app/model/entities/group'; export interface ShortUrl extends DbModel { shortUrl: string; targetUrl: string; description: string; + loadingScreen: boolean; visits: number; group?: Group; } @@ -20,6 +20,7 @@ export interface ShortUrlCreateInput { shortUrl: string; targetUrl: string; description: string; + loadingScreen: boolean; groupId: number; } @@ -28,5 +29,6 @@ export interface ShortUrlUpdateInput { shortUrl: string; targetUrl: string; description: string; + loadingScreen: boolean; groupId: number; } diff --git a/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.html b/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.html index fd10e36..a078c82 100644 --- a/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.html +++ b/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.html @@ -44,17 +44,26 @@ formControlName="description"/>
-

{{ 'common.group' | translate }}

- {{ 'short_url.loading_screen' | translate }}

+
+ [binary]="true" + formControlName="loadingScreen"/> +
+
+

{{ 'common.group' | translate }}

+
+ +
diff --git a/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.ts b/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.ts index 50d2077..e8849f8 100644 --- a/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.ts +++ b/web/src/app/modules/admin/short-urls/form-page/short-url-form-page.component.ts @@ -1,19 +1,19 @@ -import { Component } from "@angular/core"; -import { FormControl, FormGroup, Validators } from "@angular/forms"; -import { ToastService } from "src/app/service/toast.service"; -import { FormPageBase } from "src/app/core/base/form-page-base"; +import { Component } from '@angular/core'; +import { FormControl, FormGroup, Validators } from '@angular/forms'; +import { ToastService } from 'src/app/service/toast.service'; +import { FormPageBase } from 'src/app/core/base/form-page-base'; import { ShortUrl, ShortUrlCreateInput, ShortUrlUpdateInput, -} from "src/app/model/entities/short-url"; -import { ShortUrlsDataService } from "src/app/modules/admin/short-urls/short-urls.data.service"; -import { Group } from "src/app/model/entities/group"; +} from 'src/app/model/entities/short-url'; +import { ShortUrlsDataService } from 'src/app/modules/admin/short-urls/short-urls.data.service'; +import { Group } from 'src/app/model/entities/group'; @Component({ - selector: "app-short-url-form-page", - templateUrl: "./short-url-form-page.component.html", - styleUrl: "./short-url-form-page.component.scss", + selector: 'app-short-url-form-page', + templateUrl: './short-url-form-page.component.html', + styleUrl: './short-url-form-page.component.scss', }) export class ShortUrlFormPageComponent extends FormPageBase< ShortUrl, @@ -25,7 +25,7 @@ export class ShortUrlFormPageComponent extends FormPageBase< constructor(private toast: ToastService) { super(); - this.dataService.getAllGroups().subscribe((groups) => { + this.dataService.getAllGroups().subscribe(groups => { this.groups = groups; }); @@ -38,7 +38,7 @@ export class ShortUrlFormPageComponent extends FormPageBase< this.dataService .load([{ id: { equal: this.nodeId } }]) - .subscribe((apiKey) => { + .subscribe(apiKey => { this.node = apiKey.nodes[0]; this.setForm(this.node); }); @@ -53,22 +53,23 @@ export class ShortUrlFormPageComponent extends FormPageBase< id: new FormControl(undefined), shortUrl: new FormControl( undefined, - Validators.required, + Validators.required ), targetUrl: new FormControl( undefined, - Validators.required, + Validators.required ), description: new FormControl(undefined), + loadingScreen: new FormControl(undefined), groupId: new FormControl(undefined), }); - this.form.controls["id"].disable(); + this.form.controls['id'].disable(); } private generateRandomString(length: number): string { const characters = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - let result = ""; + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let result = ''; const charactersLength = characters.length; for (let i = 0; i < length; i++) { result += characters.charAt(Math.floor(Math.random() * charactersLength)); @@ -77,56 +78,63 @@ export class ShortUrlFormPageComponent extends FormPageBase< } setForm(node?: ShortUrl) { - this.form.controls["id"].setValue(node?.id); - this.form.controls["shortUrl"].setValue( - node?.shortUrl ?? this.generateRandomString(8), + this.form.controls['id'].setValue(node?.id); + this.form.controls['shortUrl'].setValue( + node?.shortUrl ?? this.generateRandomString(8) ); - this.form.controls["targetUrl"].setValue(node?.targetUrl); - this.form.controls["description"].setValue(node?.description); - this.form.controls["groupId"].setValue(node?.group?.id); + this.form.controls['targetUrl'].setValue(node?.targetUrl); + this.form.controls['description'].setValue(node?.description); + this.form.controls['loadingScreen'].setValue(node?.loadingScreen); + this.form.controls['groupId'].setValue(node?.group?.id); } getCreateInput(): ShortUrlCreateInput { return { - shortUrl: this.form.controls["shortUrl"].value ?? undefined, - targetUrl: this.form.controls["targetUrl"].pristine + shortUrl: this.form.controls['shortUrl'].value ?? undefined, + targetUrl: this.form.controls['targetUrl'].pristine ? undefined - : (this.form.controls["targetUrl"].value ?? undefined), - description: this.form.controls["description"].pristine + : (this.form.controls['targetUrl'].value ?? undefined), + description: this.form.controls['description'].pristine ? undefined - : (this.form.controls["description"].value ?? undefined), - groupId: this.form.controls["groupId"].pristine + : (this.form.controls['description'].value ?? undefined), + loadingScreen: this.form.controls['loadingScreen'].pristine ? undefined - : (this.form.controls["groupId"].value ?? undefined), + : (this.form.controls['loadingScreen'].value ?? undefined), + groupId: this.form.controls['groupId'].pristine + ? undefined + : (this.form.controls['groupId'].value ?? undefined), }; } getUpdateInput(): ShortUrlUpdateInput { if (!this.node?.id) { - throw new Error("Node id is missing"); + throw new Error('Node id is missing'); } return { - id: this.form.controls["id"].value, - shortUrl: this.form.controls["shortUrl"].pristine + id: this.form.controls['id'].value, + shortUrl: this.form.controls['shortUrl'].pristine ? undefined - : (this.form.controls["shortUrl"].value ?? undefined), - targetUrl: this.form.controls["targetUrl"].pristine + : (this.form.controls['shortUrl'].value ?? undefined), + targetUrl: this.form.controls['targetUrl'].pristine ? undefined - : (this.form.controls["targetUrl"].value ?? undefined), - description: this.form.controls["description"].pristine + : (this.form.controls['targetUrl'].value ?? undefined), + description: this.form.controls['description'].pristine ? undefined - : (this.form.controls["description"].value ?? undefined), - groupId: this.form.controls["groupId"].pristine + : (this.form.controls['description'].value ?? undefined), + loadingScreen: this.form.controls['loadingScreen'].pristine ? undefined - : (this.form.controls["groupId"].value ?? undefined), + : (this.form.controls['loadingScreen'].value ?? undefined), + groupId: this.form.controls['groupId'].pristine + ? undefined + : (this.form.controls['groupId'].value ?? undefined), }; } create(apiKey: ShortUrlCreateInput): void { this.dataService.create(apiKey).subscribe(() => { this.spinner.hide(); - this.toast.success("action.created"); + this.toast.success('action.created'); this.close(); }); } @@ -134,7 +142,7 @@ export class ShortUrlFormPageComponent extends FormPageBase< update(apiKey: ShortUrlUpdateInput): void { this.dataService.update(apiKey).subscribe(() => { this.spinner.hide(); - this.toast.success("action.created"); + this.toast.success('action.created'); this.close(); }); } diff --git a/web/src/app/modules/admin/short-urls/short-urls.data.service.ts b/web/src/app/modules/admin/short-urls/short-urls.data.service.ts index cd40395..7b865f8 100644 --- a/web/src/app/modules/admin/short-urls/short-urls.data.service.ts +++ b/web/src/app/modules/admin/short-urls/short-urls.data.service.ts @@ -1,25 +1,25 @@ -import { Injectable, Provider } from "@angular/core"; -import { Observable } from "rxjs"; +import { Injectable, Provider } from '@angular/core'; +import { Observable } from 'rxjs'; import { Create, Delete, PageDataService, Restore, Update, -} from "src/app/core/base/page.data.service"; -import { Filter } from "src/app/model/graphql/filter/filter.model"; -import { Sort } from "src/app/model/graphql/filter/sort.model"; -import { Apollo, gql } from "apollo-angular"; -import { QueryResult } from "src/app/model/entities/query-result"; -import { DB_MODEL_FRAGMENT } from "src/app/model/graphql/db-model.query"; -import { catchError, map } from "rxjs/operators"; -import { SpinnerService } from "src/app/service/spinner.service"; +} from 'src/app/core/base/page.data.service'; +import { Filter } from 'src/app/model/graphql/filter/filter.model'; +import { Sort } from 'src/app/model/graphql/filter/sort.model'; +import { Apollo, gql } from 'apollo-angular'; +import { QueryResult } from 'src/app/model/entities/query-result'; +import { DB_MODEL_FRAGMENT } from 'src/app/model/graphql/db-model.query'; +import { catchError, map } from 'rxjs/operators'; +import { SpinnerService } from 'src/app/service/spinner.service'; import { ShortUrl, ShortUrlCreateInput, ShortUrlUpdateInput, -} from "src/app/model/entities/short-url"; -import { Group } from "src/app/model/entities/group"; +} from 'src/app/model/entities/short-url'; +import { Group } from 'src/app/model/entities/group'; @Injectable() export class ShortUrlsDataService @@ -32,7 +32,7 @@ export class ShortUrlsDataService { constructor( private spinner: SpinnerService, - private apollo: Apollo, + private apollo: Apollo ) { super(); } @@ -41,7 +41,7 @@ export class ShortUrlsDataService filter?: Filter[] | undefined, sort?: Sort[] | undefined, skip?: number | undefined, - take?: number | undefined, + take?: number | undefined ): Observable> { return this.apollo .query<{ shortUrls: QueryResult }>({ @@ -60,6 +60,7 @@ export class ShortUrlsDataService shortUrl targetUrl description + loadingScreen visits group { id @@ -81,12 +82,12 @@ export class ShortUrlsDataService }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data.shortUrls)); + .pipe(map(result => result.data.shortUrls)); } loadById(id: number): Observable { @@ -99,6 +100,7 @@ export class ShortUrlsDataService shortUrl targetUrl description + loadingScreen visits group { id @@ -116,12 +118,12 @@ export class ShortUrlsDataService }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data.shortUrls.nodes[0])); + .pipe(map(result => result.data.shortUrls.nodes[0])); } create(object: ShortUrlCreateInput): Observable { @@ -146,17 +148,18 @@ export class ShortUrlsDataService shortUrl: object.shortUrl, targetUrl: object.targetUrl, description: object.description, + loadingScreen: object.loadingScreen, groupId: object.groupId, }, }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data?.shortUrl.create)); + .pipe(map(result => result.data?.shortUrl.create)); } update(object: ShortUrlUpdateInput): Observable { @@ -182,17 +185,18 @@ export class ShortUrlsDataService shortUrl: object.shortUrl, targetUrl: object.targetUrl, description: object.description, + loadingScreen: object.loadingScreen, groupId: object.groupId, }, }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data?.shortUrl.update)); + .pipe(map(result => result.data?.shortUrl.update)); } delete(object: ShortUrl): Observable { @@ -210,12 +214,12 @@ export class ShortUrlsDataService }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data?.shortUrl.delete ?? false)); + .pipe(map(result => result.data?.shortUrl.delete ?? false)); } restore(object: ShortUrl): Observable { @@ -233,12 +237,12 @@ export class ShortUrlsDataService }, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data?.shortUrl.restore ?? false)); + .pipe(map(result => result.data?.shortUrl.restore ?? false)); } getAllGroups() { @@ -256,12 +260,12 @@ export class ShortUrlsDataService `, }) .pipe( - catchError((err) => { + catchError(err => { this.spinner.hide(); throw err; - }), + }) ) - .pipe(map((result) => result.data.groups.nodes)); + .pipe(map(result => result.data.groups.nodes)); } static provide(): Provider[] { diff --git a/web/src/app/modules/admin/short-urls/short-urls.page.html b/web/src/app/modules/admin/short-urls/short-urls.page.html index 72ea87f..6cd1b3d 100644 --- a/web/src/app/modules/admin/short-urls/short-urls.page.html +++ b/web/src/app/modules/admin/short-urls/short-urls.page.html @@ -14,7 +14,13 @@
{{ 'short_url.visits' | translate }}: - {{ url.visits }} + {{ url.visits }} +
+
+ {{ 'short_url.loading_screen' | translate }}: + +
+
diff --git a/web/src/app/modules/admin/short-urls/short-urls.page.ts b/web/src/app/modules/admin/short-urls/short-urls.page.ts index 882c1ad..ee30890 100644 --- a/web/src/app/modules/admin/short-urls/short-urls.page.ts +++ b/web/src/app/modules/admin/short-urls/short-urls.page.ts @@ -1,18 +1,18 @@ -import { Component, OnInit } from "@angular/core"; -import { PageBase } from "src/app/core/base/page-base"; -import { ToastService } from "src/app/service/toast.service"; -import { ConfirmationDialogService } from "src/app/service/confirmation-dialog.service"; -import { PermissionsEnum } from "src/app/model/auth/permissionsEnum"; -import { ShortUrl } from "src/app/model/entities/short-url"; -import { ShortUrlsDataService } from "src/app/modules/admin/short-urls/short-urls.data.service"; -import { ShortUrlsColumns } from "src/app/modules/admin/short-urls/short-urls.columns"; -import { AuthService } from "src/app/service/auth.service"; -import { Filter } from "src/app/model/graphql/filter/filter.model"; +import { Component, OnInit } from '@angular/core'; +import { PageBase } from 'src/app/core/base/page-base'; +import { ToastService } from 'src/app/service/toast.service'; +import { ConfirmationDialogService } from 'src/app/service/confirmation-dialog.service'; +import { PermissionsEnum } from 'src/app/model/auth/permissionsEnum'; +import { ShortUrl } from 'src/app/model/entities/short-url'; +import { ShortUrlsDataService } from 'src/app/modules/admin/short-urls/short-urls.data.service'; +import { ShortUrlsColumns } from 'src/app/modules/admin/short-urls/short-urls.columns'; +import { AuthService } from 'src/app/service/auth.service'; +import { Filter } from 'src/app/model/graphql/filter/filter.model'; @Component({ - selector: "app-short-urls", - templateUrl: "./short-urls.page.html", - styleUrl: "./short-urls.page.scss", + selector: 'app-short-urls', + templateUrl: './short-urls.page.html', + styleUrl: './short-urls.page.scss', }) export class ShortUrlsPage extends PageBase @@ -28,7 +28,7 @@ export class ShortUrlsPage private hide_deleted_filter: Filter = { deleted: { equal: false } }; get showDeleted() { return !this.filter.some( - (f) => JSON.stringify(f) === JSON.stringify(this.hide_deleted_filter), + f => JSON.stringify(f) === JSON.stringify(this.hide_deleted_filter) ); } @@ -43,7 +43,7 @@ export class ShortUrlsPage constructor( private toast: ToastService, private confirmation: ConfirmationDialogService, - private auth: AuthService, + private auth: AuthService ) { super(true, { read: [PermissionsEnum.shortUrls], @@ -57,19 +57,19 @@ export class ShortUrlsPage async ngOnInit() { this.hasPermissions = { read: await this.auth.hasAnyPermissionLazy( - this.requiredPermissions.read ?? [], + this.requiredPermissions.read ?? [] ), create: await this.auth.hasAnyPermissionLazy( - this.requiredPermissions.create ?? [], + this.requiredPermissions.create ?? [] ), update: await this.auth.hasAnyPermissionLazy( - this.requiredPermissions.update ?? [], + this.requiredPermissions.update ?? [] ), delete: await this.auth.hasAnyPermissionLazy( - this.requiredPermissions.delete ?? [], + this.requiredPermissions.delete ?? [] ), restore: await this.auth.hasAnyPermissionLazy( - this.requiredPermissions.restore ?? [], + this.requiredPermissions.restore ?? [] ), }; } @@ -78,29 +78,22 @@ export class ShortUrlsPage this.loading = true; this.dataService .load(this.filter, this.sort, this.skip, this.take) - .subscribe((result) => { + .subscribe(result => { this.result = result; this.shortUrlsWithoutGroup = this.getShortUrlsWithoutGroup(); this.groupedShortUrls = this.getShortUrlsWithGroup(); - - console.warn( - "result", - result, - this.shortUrlsWithoutGroup, - this.groupedShortUrls, - ); this.loading = false; }); } delete(group: ShortUrl): void { this.confirmation.confirmDialog({ - header: "dialog.delete.header", - message: "dialog.delete.message", + header: 'dialog.delete.header', + message: 'dialog.delete.message', accept: () => { this.loading = true; this.dataService.delete(group).subscribe(() => { - this.toast.success("action.deleted"); + this.toast.success('action.deleted'); this.load(); }); }, @@ -110,12 +103,12 @@ export class ShortUrlsPage restore(group: ShortUrl): void { this.confirmation.confirmDialog({ - header: "dialog.restore.header", - message: "dialog.restore.message", + header: 'dialog.restore.header', + message: 'dialog.restore.message', accept: () => { this.loading = true; this.dataService.restore(group).subscribe(() => { - this.toast.success("action.restored"); + this.toast.success('action.restored'); this.load(); }); }, @@ -144,23 +137,23 @@ export class ShortUrlsPage } open(url: string) { - window.open(url, "_blank"); + window.open(url, '_blank'); } copy(val: string) { navigator.clipboard.writeText(`${window.origin}/${val}`).then(() => { - this.toast.info("common.copied", "common.copied_to_clipboard"); + this.toast.info('common.copied', 'common.copied_to_clipboard'); }); } getShortUrlsWithoutGroup(): ShortUrl[] { - return this.result.nodes.filter((shortUrl) => !shortUrl.group); + return this.result.nodes.filter(shortUrl => !shortUrl.group); } getShortUrlsWithGroup() { const groupedShortUrls: { [key: string]: ShortUrl[] } = {}; - this.result.nodes.forEach((shortUrl) => { + this.result.nodes.forEach(shortUrl => { if (!shortUrl.group) return; const groupName = shortUrl.group.name; diff --git a/web/src/app/modules/shared/components/side-menu/side-menu.component.html b/web/src/app/modules/shared/components/side-menu/side-menu.component.html index fa94594..d257a08 100644 --- a/web/src/app/modules/shared/components/side-menu/side-menu.component.html +++ b/web/src/app/modules/shared/components/side-menu/side-menu.component.html @@ -1,5 +1,5 @@ -
- +
diff --git a/web/src/app/modules/shared/shared.module.ts b/web/src/app/modules/shared/shared.module.ts index 07f5b8a..fe2ab48 100644 --- a/web/src/app/modules/shared/shared.module.ts +++ b/web/src/app/modules/shared/shared.module.ts @@ -1,67 +1,66 @@ -import { inject, NgModule } from "@angular/core"; -import { CommonModule } from "@angular/common"; -import { FormsModule, ReactiveFormsModule } from "@angular/forms"; -import { StepsModule } from "primeng/steps"; -import { DialogModule } from "primeng/dialog"; -import { ToastModule } from "primeng/toast"; -import { ProgressSpinnerModule } from "primeng/progressspinner"; -import { ButtonModule } from "primeng/button"; -import { ButtonGroupModule } from "primeng/buttongroup"; -import { ConfirmDialogModule } from "primeng/confirmdialog"; -import { TableModule } from "primeng/table"; -import { InputTextModule } from "primeng/inputtext"; -import { CheckboxModule } from "primeng/checkbox"; -import { DropdownModule } from "primeng/dropdown"; -import { TranslateModule } from "@ngx-translate/core"; -import { ImageModule } from "primeng/image"; -import { TabMenuModule } from "primeng/tabmenu"; -import { MenubarModule } from "primeng/menubar"; -import { PanelMenuModule } from "primeng/panelmenu"; -import { CardModule } from "primeng/card"; -import { MultiSelectModule } from "primeng/multiselect"; -import { SplitButtonModule } from "primeng/splitbutton"; -import { CalendarModule } from "primeng/calendar"; -import { PaginatorModule } from "primeng/paginator"; -import { DataViewModule } from "primeng/dataview"; -import { TagModule } from "primeng/tag"; -import { SidebarModule } from "primeng/sidebar"; -import { FileUploadModule } from "primeng/fileupload"; -import { MenuModule } from "primeng/menu"; -import { ChipModule } from "primeng/chip"; -import { BadgeModule } from "primeng/badge"; -import { ContextMenuModule } from "primeng/contextmenu"; -import { DragDropModule } from "primeng/dragdrop"; -import { InputSwitchModule } from "primeng/inputswitch"; -import { SelectButtonModule } from "primeng/selectbutton"; -import { BreadcrumbModule } from "primeng/breadcrumb"; -import { OverlayPanelModule } from "primeng/overlaypanel"; -import { TerminalModule } from "primeng/terminal"; -import { RatingModule } from "primeng/rating"; -import { FocusTrapModule } from "primeng/focustrap"; -import { InputMaskModule } from "primeng/inputmask"; -import { TriStateCheckboxModule } from "primeng/tristatecheckbox"; -import { InputTextareaModule } from "primeng/inputtextarea"; -import { MenuBarComponent } from "src/app/modules/shared/components/menu-bar/menu-bar.component"; -import { SideMenuComponent } from "./components/side-menu/side-menu.component"; +import { inject, NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { StepsModule } from 'primeng/steps'; +import { DialogModule } from 'primeng/dialog'; +import { ToastModule } from 'primeng/toast'; +import { ProgressSpinnerModule } from 'primeng/progressspinner'; +import { ButtonModule } from 'primeng/button'; +import { ButtonGroupModule } from 'primeng/buttongroup'; +import { ConfirmDialogModule } from 'primeng/confirmdialog'; +import { TableModule } from 'primeng/table'; +import { InputTextModule } from 'primeng/inputtext'; +import { CheckboxModule } from 'primeng/checkbox'; +import { DropdownModule } from 'primeng/dropdown'; +import { TranslateModule } from '@ngx-translate/core'; +import { ImageModule } from 'primeng/image'; +import { TabMenuModule } from 'primeng/tabmenu'; +import { MenubarModule } from 'primeng/menubar'; +import { PanelMenuModule } from 'primeng/panelmenu'; +import { CardModule } from 'primeng/card'; +import { MultiSelectModule } from 'primeng/multiselect'; +import { SplitButtonModule } from 'primeng/splitbutton'; +import { CalendarModule } from 'primeng/calendar'; +import { PaginatorModule } from 'primeng/paginator'; +import { DataViewModule } from 'primeng/dataview'; +import { TagModule } from 'primeng/tag'; +import { SidebarModule } from 'primeng/sidebar'; +import { FileUploadModule } from 'primeng/fileupload'; +import { MenuModule } from 'primeng/menu'; +import { ChipModule } from 'primeng/chip'; +import { BadgeModule } from 'primeng/badge'; +import { ContextMenuModule } from 'primeng/contextmenu'; +import { DragDropModule } from 'primeng/dragdrop'; +import { InputSwitchModule } from 'primeng/inputswitch'; +import { SelectButtonModule } from 'primeng/selectbutton'; +import { BreadcrumbModule } from 'primeng/breadcrumb'; +import { OverlayPanelModule } from 'primeng/overlaypanel'; +import { TerminalModule } from 'primeng/terminal'; +import { RatingModule } from 'primeng/rating'; +import { FocusTrapModule } from 'primeng/focustrap'; +import { InputMaskModule } from 'primeng/inputmask'; +import { TriStateCheckboxModule } from 'primeng/tristatecheckbox'; +import { InputTextareaModule } from 'primeng/inputtextarea'; +import { MenuBarComponent } from 'src/app/modules/shared/components/menu-bar/menu-bar.component'; +import { SideMenuComponent } from './components/side-menu/side-menu.component'; import { CustomActionDirective, TableComponent, -} from "./components/table/table.component"; -import { BoolPipe } from "src/app/modules/shared/pipes/bool.pipe"; -import { CustomDatePipe } from "src/app/modules/shared/pipes/customDate.pipe"; -import { FormPageComponent } from "src/app/modules/shared/components/slidein/form-page.component"; +} from './components/table/table.component'; +import { BoolPipe } from 'src/app/modules/shared/pipes/bool.pipe'; +import { CustomDatePipe } from 'src/app/modules/shared/pipes/customDate.pipe'; +import { FormPageComponent } from 'src/app/modules/shared/components/slidein/form-page.component'; import { FormPageContentDirective, FormPageHeaderDirective, -} from "src/app/modules/shared/form"; -import { ProtectPipe } from "./pipes/protect.pipe"; -import { provideApollo } from "apollo-angular"; -import { HttpLink } from "apollo-angular/http"; -import { environment } from "src/environments/environment"; -import { InMemoryCache } from "@apollo/client/core"; -import { provideHttpClient, withInterceptors } from "@angular/common/http"; -import { tokenInterceptor } from "src/app/core/token.interceptor"; -import { SettingsService } from "src/app/service/settings.service"; +} from 'src/app/modules/shared/form'; +import { ProtectPipe } from './pipes/protect.pipe'; +import { provideApollo } from 'apollo-angular'; +import { HttpLink } from 'apollo-angular/http'; +import { InMemoryCache } from '@apollo/client/core'; +import { provideHttpClient, withInterceptors } from '@angular/common/http'; +import { tokenInterceptor } from 'src/app/core/token.interceptor'; +import { SettingsService } from 'src/app/service/settings.service'; const sharedModules = [ StepsModule, @@ -137,13 +136,13 @@ const sharedComponents = [ defaultOptions: { watchQuery: { - fetchPolicy: "no-cache", + fetchPolicy: 'no-cache', }, query: { - fetchPolicy: "no-cache", + fetchPolicy: 'no-cache', }, mutate: { - fetchPolicy: "no-cache", + fetchPolicy: 'no-cache', }, }, }; diff --git a/web/src/app/service/gui.service.ts b/web/src/app/service/gui.service.ts index 8f47821..565f058 100644 --- a/web/src/app/service/gui.service.ts +++ b/web/src/app/service/gui.service.ts @@ -1,13 +1,13 @@ -import { HostListener, Injectable } from "@angular/core"; -import { BehaviorSubject, filter } from "rxjs"; -import { Logger } from "src/app/service/logger.service"; -import { NavigationEnd, Router } from "@angular/router"; -import { SidebarService } from "src/app/service/sidebar.service"; +import { HostListener, Injectable } from '@angular/core'; +import { BehaviorSubject, filter } from 'rxjs'; +import { Logger } from 'src/app/service/logger.service'; +import { NavigationEnd, Router } from '@angular/router'; +import { SidebarService } from 'src/app/service/sidebar.service'; -const logger = new Logger("GuiService"); +const logger = new Logger('GuiService'); @Injectable({ - providedIn: "root", + providedIn: 'root', }) export class GuiService { isMobile$ = new BehaviorSubject(this.isMobileByWindowWith()); @@ -17,10 +17,10 @@ export class GuiService { constructor( private router: Router, - private sidebarService: SidebarService, + private sidebarService: SidebarService ) { this.router.events - .pipe(filter((event) => event instanceof NavigationEnd)) + .pipe(filter(event => event instanceof NavigationEnd)) .subscribe(() => { if (this.isMobile$.value) { this.sidebarService.hide(); @@ -28,8 +28,8 @@ export class GuiService { }); } - @HostListener("window:resize", ["$event"]) - onResize(event: any) { + @HostListener('window:resize', ['$event']) + onResize() { this.checkWindowSize(); } @@ -42,7 +42,7 @@ export class GuiService { } public checkWindowSize() { - logger.debug("check window size", { + logger.debug('check window size', { mobile: this.isMobileByWindowWith(), tablet: this.isTabletByWindowWith(), size: window.innerWidth, @@ -64,9 +64,9 @@ export class GuiService { b = parseInt(hex.slice(5, 7), 16); if (alpha) { - return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")"; + return 'rgba(' + r + ', ' + g + ', ' + b + ', ' + alpha + ')'; } else { - return "rgb(" + r + ", " + g + ", " + b + ")"; + return 'rgb(' + r + ', ' + g + ', ' + b + ')'; } } diff --git a/web/src/assets/i18n/de.json b/web/src/assets/i18n/de.json index 09be44b..a4f93a9 100644 --- a/web/src/assets/i18n/de.json +++ b/web/src/assets/i18n/de.json @@ -107,6 +107,7 @@ }, "short_url": { "count_header": "Url(s)", + "loading_screen": "Ladebildschirm", "short_url": "URL", "target_url": "Ziel", "visits": "Aufrufe" diff --git a/web/src/assets/i18n/en.json b/web/src/assets/i18n/en.json index 6676e80..fa5add5 100644 --- a/web/src/assets/i18n/en.json +++ b/web/src/assets/i18n/en.json @@ -107,6 +107,7 @@ }, "short_url": { "count_header": "Url(s)", + "loading_screen": "Loading screen", "short_url": "URL", "target_url": "Target", "visits": "Visits"