style: format code and add prettier configuration files

This commit is contained in:
Jan Gleytenhoover 2025-01-21 13:29:09 +01:00
parent 3e0b17ebe6
commit 395c1bc75f
Signed by: jank
GPG key ID: 50620ADD22CD330B
39 changed files with 338 additions and 207 deletions

View file

@ -29,4 +29,3 @@ jobs:
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}

3
.prettierignore Normal file
View file

@ -0,0 +1,3 @@
# Ignore artifacts:
build
coverage

1
.prettierrc Normal file
View file

@ -0,0 +1 @@
{}

View file

@ -16,9 +16,7 @@
"outputPath": "dist/jklink",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": [
{
@ -86,10 +84,7 @@
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"assets": [
{

17
package-lock.json generated
View file

@ -38,6 +38,7 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.5.1",
"prettier": "3.4.2",
"tailwindcss": "^3.4.17",
"typescript": "~5.6.2"
}
@ -10845,6 +10846,22 @@
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/prettier": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz",
"integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/proc-log": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",

View file

@ -40,6 +40,7 @@
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"postcss": "^8.5.1",
"prettier": "3.4.2",
"tailwindcss": "^3.4.17",
"typescript": "~5.6.2"
}

View file

@ -1,11 +1,14 @@
module.exports = {
branches: ['prod'],
branches: ["prod"],
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/changelog',
["@saithodev/semantic-release-gitea", {
"giteaUrl": "https://git.kjan.de"
}],
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"@saithodev/semantic-release-gitea",
{
giteaUrl: "https://git.kjan.de",
},
],
],
};

View file

@ -24,6 +24,8 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, jklink');
expect(compiled.querySelector('h1')?.textContent).toContain(
'Hello, jklink',
);
});
});

View file

@ -5,7 +5,6 @@ import { RouterOutlet } from '@angular/router';
selector: 'app-root',
imports: [RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css'
styleUrl: './app.component.css',
})
export class AppComponent {
}
export class AppComponent {}

View file

@ -5,5 +5,9 @@ import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
export const appConfig: ApplicationConfig = {
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync()]
providers: [
provideZoneChangeDetection({ eventCoalescing: true }),
provideRouter(routes),
provideAnimationsAsync(),
],
};

View file

@ -25,7 +25,7 @@ export const routes: Routes = [
component: ViewLinkComponent,
},
{
path: "**",
redirectTo: "",
path: '**',
redirectTo: '',
},
];

View file

@ -1,5 +1,5 @@
<h2 mat-dialog-title>{{data.title}}</h2>
<mat-dialog-content>{{data.description}}</mat-dialog-content>
<h2 mat-dialog-title>{{ data.title }}</h2>
<mat-dialog-content>{{ data.description }}</mat-dialog-content>
<mat-dialog-actions>
<button mat-flat-button color="warn" (click)="close()">No</button>
<button mat-flat-button (click)="accept()">Yes</button>

View file

@ -8,9 +8,8 @@ describe('VisitLinkConfirmationComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ConfirmationModalComponent]
})
.compileComponents();
imports: [ConfirmationModalComponent],
}).compileComponents();
fixture = TestBed.createComponent(ConfirmationModalComponent);
component = fixture.componentInstance;

View file

@ -12,9 +12,14 @@ import { ConfirmationModalDto } from '../models/confirmation-modal';
@Component({
selector: 'app-confirmation-modal',
imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButtonModule],
imports: [
MatDialogTitle,
MatDialogContent,
MatDialogActions,
MatButtonModule,
],
templateUrl: './confirmation-modal.component.html',
styleUrl: './confirmation-modal.component.css'
styleUrl: './confirmation-modal.component.css',
})
export class ConfirmationModalComponent {
public data: ConfirmationModalDto = inject(MAT_DIALOG_DATA);

View file

@ -1,17 +1,24 @@
<div class="mx-auto container">
<app-navbar></app-navbar>
<button mat-flat-button class="mt-3" color="warn" (click)="back()">Back</button>
<button mat-flat-button class="mt-3" color="warn" (click)="back()">
Back
</button>
<mat-card class="mt-3 p-3" appearance="outlined">
<form class="flex flex-col" [formGroup]="createLinkForm">
<mat-form-field appearance="outline">
<mat-error>{{errorMessages['name']}}</mat-error>
<mat-error>{{ errorMessages["name"] }}</mat-error>
<mat-label>Name</mat-label>
<input formControlName="name" matInput placeholder="My Awesome link">
<input formControlName="name" matInput placeholder="My Awesome link" />
</mat-form-field>
<mat-form-field appearance="outline">
<mat-error>{{errorMessages['link']}}</mat-error>
<mat-error>{{ errorMessages["link"] }}</mat-error>
<mat-label>Link</mat-label>
<input formControlName="link" matInput type="url" placeholder="https://kjan.de">
<input
formControlName="link"
matInput
type="url"
placeholder="https://kjan.de"
/>
</mat-form-field>
<button mat-flat-button type="submit" (click)="submit()">Create</button>
</form>

View file

@ -8,9 +8,8 @@ describe('CreateLinkComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [CreateLinkComponent]
})
.compileComponents();
imports: [CreateLinkComponent],
}).compileComponents();
fixture = TestBed.createComponent(CreateLinkComponent);
component = fixture.componentInstance;

View file

@ -1,6 +1,11 @@
import { Component } from '@angular/core';
import { NavbarComponent } from '../navbar/navbar.component';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import {
FormControl,
FormGroup,
ReactiveFormsModule,
Validators,
} from '@angular/forms';
import { LinkService } from '../service/link.service';
import { Router } from '@angular/router';
import { MatCardModule } from '@angular/material/card';
@ -11,31 +16,45 @@ import { debounceTime } from 'rxjs';
@Component({
selector: 'app-create-link',
imports: [NavbarComponent, ReactiveFormsModule, MatCardModule, MatFormFieldModule, MatInputModule, MatButtonModule],
imports: [
NavbarComponent,
ReactiveFormsModule,
MatCardModule,
MatFormFieldModule,
MatInputModule,
MatButtonModule,
],
templateUrl: './create-link.component.html',
styleUrl: './create-link.component.css'
styleUrl: './create-link.component.css',
})
export class CreateLinkComponent {
public createLinkForm!: FormGroup;
public requestFailed: boolean = false;
public errorMessages: Record<string, string> = {};
constructor(private linkService: LinkService, private router: Router) { }
constructor(
private linkService: LinkService,
private router: Router,
) {}
private validationErrorMessages: Record<string, string> = {
required: "This field is required",
pattern: "This must be a valid url",
required: 'This field is required',
pattern: 'This must be a valid url',
};
updateErrorMessages(): void {
this.errorMessages = {};
Object.keys(this.createLinkForm.controls).forEach(field => {
Object.keys(this.createLinkForm.controls).forEach((field) => {
const control = this.createLinkForm.get(field);
if (control && control.errors) {
this.errorMessages[field] = Object.keys(control.errors)
.map(errorKey => this.validationErrorMessages[errorKey] || `Unknown error: ${errorKey}`)
.map(
(errorKey) =>
this.validationErrorMessages[errorKey] ||
`Unknown error: ${errorKey}`,
)
.join(' ');
}
});
@ -48,7 +67,12 @@ export class CreateLinkComponent {
ngOnInit(): void {
this.createLinkForm = new FormGroup({
name: new FormControl('', Validators.required),
link: new FormControl('', [Validators.required, Validators.pattern(/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/)]),
link: new FormControl('', [
Validators.required,
Validators.pattern(
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/,
),
]),
});
this.createLinkForm.valueChanges.subscribe(() => {
this.updateErrorMessages();
@ -56,16 +80,18 @@ export class CreateLinkComponent {
}
submit() {
if (!this.createLinkForm.valid) {
return;
}
this.requestFailed = false;
this.linkService.createLink({
this.linkService
.createLink({
name: this.createLinkForm.get('name')?.value,
link: this.createLinkForm.get('link')?.value,
}).catch(() => this.requestFailed = true).finally(() => {
})
.catch(() => (this.requestFailed = true))
.finally(() => {
if (!this.requestFailed) {
this.router.navigate(['dashboard']);
}

View file

@ -1,54 +1,72 @@
<div class="mx-auto container">
<app-navbar></app-navbar>
<div class="overflow-x-auto">
<button mat-flat-button color="secondary" class="my-3" (click)="createLink()">Create new Link</button>
<button
mat-flat-button
color="secondary"
class="my-3"
(click)="createLink()"
>
Create new Link
</button>
<mat-card appearance="outlined">
<mat-card-content>
<table mat-table [dataSource]="links" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- Position Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> ID </th>
<th mat-header-cell *matHeaderCellDef>ID</th>
<td mat-cell *matCellDef="let element">
<a (click)="goToLink(element)" class="link">
{{element.id}}
{{ element.id }}
</a>
</td>
</ng-container>
<!-- Name Column -->
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Name </th>
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
<th mat-header-cell *matHeaderCellDef>Name</th>
<td mat-cell *matCellDef="let element">{{ element.name }}</td>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="link">
<th mat-header-cell *matHeaderCellDef> Link </th>
<td mat-cell *matCellDef="let element"> {{element.link}} </td>
<th mat-header-cell *matHeaderCellDef>Link</th>
<td mat-cell *matCellDef="let element">{{ element.link }}</td>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="shortLink">
<th mat-header-cell *matHeaderCellDef> Short link </th>
<th mat-header-cell *matHeaderCellDef>Short link</th>
<td mat-cell *matCellDef="let element">
<button mat-flat-button class="my-3" (click)="copyLink(element.id)">Copy short link</button>
<button
mat-flat-button
class="my-3"
(click)="copyLink(element.id)"
>
Copy short link
</button>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef> Actions </th>
<th mat-header-cell *matHeaderCellDef>Actions</th>
<td mat-cell *matCellDef="let element">
<button mat-flat-button color="warn" (click)="deleteLink(element)">Delete</button>
<button
mat-flat-button
color="warn"
(click)="deleteLink(element)"
>
Delete
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
</mat-card-content>
</mat-card>

View file

@ -8,9 +8,8 @@ describe('DashboardComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DashboardComponent]
})
.compileComponents();
imports: [DashboardComponent],
}).compileComponents();
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;

View file

@ -15,29 +15,38 @@ import { MatSnackBar } from '@angular/material/snack-bar';
selector: 'app-dashboard',
imports: [NavbarComponent, MatTableModule, MatCardModule, MatButtonModule],
templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.css'
styleUrl: './dashboard.component.css',
})
export class DashboardComponent {
public links: Link[] = [];
displayedColumns: string[] = ['id', 'name', 'link', 'shortLink', 'actions'];
constructor(private linkService: LinkService, private router: Router, private dialog: MatDialog, private snackBar: MatSnackBar) { };
constructor(
private linkService: LinkService,
private router: Router,
private dialog: MatDialog,
private snackBar: MatSnackBar,
) {}
copyLink(id: string) {
navigator.clipboard.writeText(this.getShortLink(id));
}
getShortLink(id: string): string {
return "https://" + window.location.hostname + '/' + id;
return 'https://' + window.location.hostname + '/' + id;
}
goToLink(link: Link) {
this.dialog.open(ConfirmationModalComponent, {
this.dialog
.open(ConfirmationModalComponent, {
data: {
title: "Are you sure?",
description: "Are you sure that you want to open " + link.link + " now?",
title: 'Are you sure?',
description:
'Are you sure that you want to open ' + link.link + ' now?',
},
}).afterClosed().subscribe((accepted: Boolean) => {
})
.afterClosed()
.subscribe((accepted: Boolean) => {
if (accepted) {
this.router.navigate([link.id]);
}
@ -45,10 +54,9 @@ export class DashboardComponent {
}
ngOnInit(): void {
this.linkService.getLinks().then(links => {
this.linkService.getLinks().then((links) => {
this.links = links;
});
}
createLink() {
@ -56,25 +64,31 @@ export class DashboardComponent {
}
deleteLink(link: Link) {
this.dialog.open(ConfirmationModalComponent, {
this.dialog
.open(ConfirmationModalComponent, {
data: {
title: "Are you sure?",
description: "Are you sure that you want to delete " + link.name + "?",
}
}).afterClosed().subscribe((accepted: boolean) => {
title: 'Are you sure?',
description:
'Are you sure that you want to delete ' + link.name + '?',
},
})
.afterClosed()
.subscribe((accepted: boolean) => {
if (accepted) {
this.linkService.deleteLink(link.id).catch(() => {
const errorNotification = this.snackBar.open("Something went wrong.");
const errorNotification = this.snackBar.open(
'Something went wrong.',
);
setTimeout(() => {
errorNotification.dismiss();
}, 5000);
});
this.links = this.links.filter(givenLink => {
this.links = this.links.filter((givenLink) => {
return givenLink.id != link.id;
});
const notification = this.snackBar.open(link.name + " was deleted.");
const notification = this.snackBar.open(link.name + ' was deleted.');
setTimeout(() => {
notification.dismiss();
}, 2000);

View file

@ -1,8 +1,15 @@
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<img class="mx-auto h-10 w-auto" src="https://tailwindui.com/plus/img/logos/mark.svg?color=indigo&shade=600"
alt="Your Company">
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Sign in to your account</h2>
<img
class="mx-auto h-10 w-auto"
src="https://tailwindui.com/plus/img/logos/mark.svg?color=indigo&shade=600"
alt="Your Company"
/>
<h2
class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900"
>
Sign in to your account
</h2>
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
@ -10,33 +17,58 @@
@if (invalidCredentials) {
<div class="mt-2">
<p
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-red-500 outline outline-red-500 outline-2 -outline-offset-2 sm:text-sm/6">
Invalid Credentials</p>
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-red-500 outline outline-red-500 outline-2 -outline-offset-2 sm:text-sm/6"
>
Invalid Credentials
</p>
</div>
}
<div>
<label for="email" class="block text-sm/6 font-medium text-gray-900">Email address</label>
<label for="email" class="block text-sm/6 font-medium text-gray-900"
>Email address</label
>
<div class="mt-2">
<input formControlName="email" type="email" name="email" id="email" autocomplete="email" required
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
<input
formControlName="email"
type="email"
name="email"
id="email"
autocomplete="email"
required
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
/>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<label for="password" class="block text-sm/6 font-medium text-gray-900">Password</label>
<label
for="password"
class="block text-sm/6 font-medium text-gray-900"
>Password</label
>
</div>
<div class="mt-2">
<input formControlName="password" type="password" name="password" id="password"
autocomplete="current-password" required
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6">
<input
formControlName="password"
type="password"
name="password"
id="password"
autocomplete="current-password"
required
class="block w-full rounded-md bg-white px-3 py-1.5 text-base text-gray-900 outline outline-1 -outline-offset-1 outline-gray-300 placeholder:text-gray-400 focus:outline focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 sm:text-sm/6"
/>
</div>
</div>
<div>
<button (click)="submit()" type="submit"
class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign
in</button>
<button
(click)="submit()"
type="submit"
class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm/6 font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
>
Sign in
</button>
</div>
</form>
</div>

View file

@ -8,9 +8,8 @@ describe('LoginComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [LoginComponent]
})
.compileComponents();
imports: [LoginComponent],
}).compileComponents();
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;

View file

@ -8,14 +8,14 @@ import { Router } from '@angular/router';
selector: 'app-login',
imports: [ReactiveFormsModule],
templateUrl: './login.component.html',
styleUrl: './login.component.css'
styleUrl: './login.component.css',
})
export class LoginComponent {
public loginForm!: FormGroup;
public invalidCredentials = false;
private pb = new PocketBase(environment.POCKETBASE);
constructor(private router: Router) { };
constructor(private router: Router) {}
ngOnInit(): void {
this.loginForm = new FormGroup({
@ -29,12 +29,16 @@ export class LoginComponent {
}
submit() {
this.pb.collection("users").authWithPassword(
this.pb
.collection('users')
.authWithPassword(
this.loginForm.get('email')?.value,
this.loginForm.get('password')?.value
).then(() => {
this.loginForm.get('password')?.value,
)
.then(() => {
this.router.navigate(['dashboard']);
}).catch(() => {
})
.catch(() => {
this.invalidCredentials = true;
});
}

View file

@ -1,4 +1,4 @@
export interface ConfirmationModalDto {
title: string,
description: string,
title: string;
description: string;
}

View file

@ -8,9 +8,8 @@ describe('NavbarComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [NavbarComponent]
})
.compileComponents();
imports: [NavbarComponent],
}).compileComponents();
fixture = TestBed.createComponent(NavbarComponent);
component = fixture.componentInstance;

View file

@ -7,6 +7,4 @@ import { Component, ViewEncapsulation } from '@angular/core';
styleUrl: './navbar.component.css',
encapsulation: ViewEncapsulation.None,
})
export class NavbarComponent {
}
export class NavbarComponent {}

View file

@ -5,20 +5,26 @@ import {
GuardResult,
MaybeAsync,
Router,
RouterStateSnapshot
RouterStateSnapshot,
} from '@angular/router';
import PocketBase from 'pocketbase';
import { environment } from '../../environments/environment';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private router: Router) { };
constructor(private router: Router) {}
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
async canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Promise<boolean> {
const pb = new PocketBase(environment.POCKETBASE);
await pb.collection('users').authRefresh().catch(() => this.router.navigate(['']));
await pb
.collection('users')
.authRefresh()
.catch(() => this.router.navigate(['']));
if (pb.authStore.isValid) {
return true;

View file

@ -1,11 +1,10 @@
import { Injectable } from "@angular/core";
import { environment } from "../../environments/environment";
import { Injectable } from '@angular/core';
import { environment } from '../../environments/environment';
import PocketBase, { RecordModel } from 'pocketbase';
import { Link } from "../models/link";
import { Link } from '../models/link';
@Injectable({
providedIn: 'root'
providedIn: 'root',
})
export class LinkService {
private pb = new PocketBase(environment.POCKETBASE);
@ -24,9 +23,9 @@ export class LinkService {
createLink(link: any): Promise<RecordModel> {
return this.pb.collection('links').create({
'name': link.name,
'link': link.link,
'owner': this.pb.authStore.record?.id,
name: link.name,
link: link.link,
owner: this.pb.authStore.record?.id,
});
}
}

View file

@ -1,3 +1,6 @@
<p>Your are being redirected.</p>
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5944102294748899"
crossorigin="anonymous"></script>
<script
async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5944102294748899"
crossorigin="anonymous"
></script>

View file

@ -8,9 +8,8 @@ describe('ViewLinkComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ViewLinkComponent]
})
.compileComponents();
imports: [ViewLinkComponent],
}).compileComponents();
fixture = TestBed.createComponent(ViewLinkComponent);
component = fixture.componentInstance;

View file

@ -6,13 +6,19 @@ import { ActivatedRoute, Router } from '@angular/router';
selector: 'app-view-link',
imports: [],
templateUrl: './view-link.component.html',
styleUrl: './view-link.component.css'
styleUrl: './view-link.component.css',
})
export class ViewLinkComponent {
constructor(private linkService: LinkService, private route: ActivatedRoute, private router: Router) { }
constructor(
private linkService: LinkService,
private route: ActivatedRoute,
private router: Router,
) {}
ngOnInit(): void {
this.linkService.getLink(this.route.snapshot.params['link']).then(link => {
this.linkService
.getLink(this.route.snapshot.params['link'])
.then((link) => {
window.location.href = link.link;
});
}

View file

@ -1,3 +1,3 @@
export const environment = {
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de'
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de',
};

View file

@ -1,3 +1,3 @@
export const environment = {
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de'
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de',
};

View file

@ -1,15 +1,21 @@
<!doctype html>
<html class="h-full" lang="en" data-theme="light">
<head>
<meta charset="utf-8">
<head>
<meta charset="utf-8" />
<title>Jklink</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body class="h-full base-100 mat-typography" >
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/icon?family=Material+Icons"
rel="stylesheet"
/>
</head>
<body class="h-full base-100 mat-typography">
<app-root></app-root>
</body>
</body>
</html>

View file

@ -2,5 +2,6 @@ import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
bootstrapApplication(AppComponent, appConfig).catch((err) =>
console.error(err),
);

View file

@ -1,4 +1,4 @@
@use '@angular/material' as mat;
@use "@angular/material" as mat;
@tailwind base;
@tailwind components;
@tailwind utilities;

View file

@ -1,8 +1,6 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./src/**/*.{html,ts}",
],
content: ["./src/**/*.{html,ts}"],
theme: {
extend: {},
},
@ -10,5 +8,4 @@ module.exports = {
preflight: false,
},
plugins: [],
}
};

View file

@ -6,10 +6,6 @@
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts"
],
"include": [
"src/**/*.d.ts"
]
"files": ["src/main.ts"],
"include": ["src/**/*.d.ts"]
}

View file

@ -4,12 +4,7 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
"types": ["jasmine"]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}