Added ui support for loading screen setting
This commit is contained in:
parent
7b6cef1ae5
commit
ff341ddcb5
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -1 +1 @@
|
||||
0.2.0
|
||||
0.2.1
|
56
web/.eslintrc.json
Normal file
56
web/.eslintrc.json
Normal file
@ -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": {}
|
||||
}
|
||||
]
|
||||
}
|
12
web/.prettierrc.json
Normal file
12
web/.prettierrc.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"singleQuote": true,
|
||||
"semi": true,
|
||||
"bracketSpacing": true,
|
||||
"arrowParens": "avoid",
|
||||
"trailingComma": "es5",
|
||||
"bracketSameLine": true,
|
||||
"printWidth": 80,
|
||||
"endOfLine": "auto"
|
||||
}
|
@ -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<ShortUrlDto | undefined>(`${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;
|
||||
}
|
||||
|
||||
|
@ -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<boolean> {
|
||||
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,
|
||||
});
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -44,9 +44,17 @@
|
||||
formControlName="description"/>
|
||||
</div>
|
||||
<div class="form-page-input">
|
||||
<p class="label">{{ 'common.group' | translate }}</p>
|
||||
<p-dropdown
|
||||
<p class="label">{{ 'short_url.loading_screen' | translate }}</p>
|
||||
<p-checkbox
|
||||
class="value"
|
||||
[binary]="true"
|
||||
formControlName="loadingScreen"/>
|
||||
</div>
|
||||
<div class="form-page-input">
|
||||
<p class="label">{{ 'common.group' | translate }}</p>
|
||||
<div
|
||||
class="value">
|
||||
<p-dropdown
|
||||
[options]="groups"
|
||||
formControlName="groupId"
|
||||
[showClear]="true"
|
||||
@ -56,5 +64,6 @@
|
||||
optionValue="id"
|
||||
></p-dropdown>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</app-form-page>
|
||||
|
@ -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<number | undefined>(undefined),
|
||||
shortUrl: new FormControl<string | undefined>(
|
||||
undefined,
|
||||
Validators.required,
|
||||
Validators.required
|
||||
),
|
||||
targetUrl: new FormControl<string | undefined>(
|
||||
undefined,
|
||||
Validators.required,
|
||||
Validators.required
|
||||
),
|
||||
description: new FormControl<string | undefined>(undefined),
|
||||
loadingScreen: new FormControl<boolean | undefined>(undefined),
|
||||
groupId: new FormControl<number | undefined>(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();
|
||||
});
|
||||
}
|
||||
|
@ -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<QueryResult<ShortUrl>> {
|
||||
return this.apollo
|
||||
.query<{ shortUrls: QueryResult<ShortUrl> }>({
|
||||
@ -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<ShortUrl> {
|
||||
@ -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<ShortUrl | undefined> {
|
||||
@ -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<ShortUrl | undefined> {
|
||||
@ -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<boolean> {
|
||||
@ -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<boolean> {
|
||||
@ -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[] {
|
||||
|
@ -14,7 +14,13 @@
|
||||
</div>
|
||||
<div class="grid-container">
|
||||
<span class="grid-label font-bold">{{ 'short_url.visits' | translate }}:</span>
|
||||
<span class="grid-value">{{ url.visits }}</span>
|
||||
<span class="grid-value highlight2">{{ url.visits }}</span>
|
||||
</div>
|
||||
<div class="grid-container">
|
||||
<span class="grid-label font-bold">{{ 'short_url.loading_screen' | translate }}:</span>
|
||||
<span class="grid-value">
|
||||
<div class="pi pi-{{ url.loadingScreen ? 'check-circle' : 'times-circle' }}"></div>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end">
|
||||
|
@ -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<ShortUrl, ShortUrlsDataService, ShortUrlsColumns>
|
||||
@ -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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<ng-template #menuBtn let-element>
|
||||
<button
|
||||
<a
|
||||
class="flex w-full gap-5 items-center justify-center p-2 rounded-xl hover:bg hover:cursor-pointer"
|
||||
(click)="(element.command)"
|
||||
[routerLink]="element.routerLink">
|
||||
@ -15,7 +15,7 @@
|
||||
<span class="pi pi-angle-right"></span>
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</a>
|
||||
</ng-template>
|
||||
|
||||
<div
|
||||
|
@ -1,7 +1,7 @@
|
||||
<p-sidebar
|
||||
[visible]="true"
|
||||
position="right"
|
||||
[style]="{ width: 'min-content', minWidth: '350px' }"
|
||||
[style]="{ width: 'min-content', minWidth: '450px' }"
|
||||
(onHide)="onClose.emit()"
|
||||
(visibleChange)="!$event ? onClose.emit() : undefined">
|
||||
<ng-template pTemplate="headless">
|
||||
|
@ -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',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -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<boolean>(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 + ')';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@
|
||||
},
|
||||
"short_url": {
|
||||
"count_header": "Url(s)",
|
||||
"loading_screen": "Ladebildschirm",
|
||||
"short_url": "URL",
|
||||
"target_url": "Ziel",
|
||||
"visits": "Aufrufe"
|
||||
|
@ -107,6 +107,7 @@
|
||||
},
|
||||
"short_url": {
|
||||
"count_header": "Url(s)",
|
||||
"loading_screen": "Loading screen",
|
||||
"short_url": "URL",
|
||||
"target_url": "Target",
|
||||
"visits": "Visits"
|
||||
|
Loading…
Reference in New Issue
Block a user