style: format code and add prettier configuration files
This commit is contained in:
parent
3e0b17ebe6
commit
395c1bc75f
39 changed files with 338 additions and 207 deletions
|
@ -11,7 +11,7 @@ permissions:
|
||||||
contents: read # for checkout
|
contents: read # for checkout
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.ref }} # Ensure each branch has its own group
|
group: ${{ github.ref }} # Ensure each branch has its own group
|
||||||
cancel-in-progress: false # Prevent new runs from canceling in-progress runs
|
cancel-in-progress: false # Prevent new runs from canceling in-progress runs
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
@ -29,4 +29,3 @@ jobs:
|
||||||
with:
|
with:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
|
||||||
|
|
3
.prettierignore
Normal file
3
.prettierignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Ignore artifacts:
|
||||||
|
build
|
||||||
|
coverage
|
1
.prettierrc
Normal file
1
.prettierrc
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{}
|
|
@ -16,9 +16,7 @@
|
||||||
"outputPath": "dist/jklink",
|
"outputPath": "dist/jklink",
|
||||||
"index": "src/index.html",
|
"index": "src/index.html",
|
||||||
"browser": "src/main.ts",
|
"browser": "src/main.ts",
|
||||||
"polyfills": [
|
"polyfills": ["zone.js"],
|
||||||
"zone.js"
|
|
||||||
],
|
|
||||||
"tsConfig": "tsconfig.app.json",
|
"tsConfig": "tsconfig.app.json",
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
|
@ -86,10 +84,7 @@
|
||||||
"test": {
|
"test": {
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
"builder": "@angular-devkit/build-angular:karma",
|
||||||
"options": {
|
"options": {
|
||||||
"polyfills": [
|
"polyfills": ["zone.js", "zone.js/testing"],
|
||||||
"zone.js",
|
|
||||||
"zone.js/testing"
|
|
||||||
],
|
|
||||||
"tsConfig": "tsconfig.spec.json",
|
"tsConfig": "tsconfig.spec.json",
|
||||||
"assets": [
|
"assets": [
|
||||||
{
|
{
|
||||||
|
|
17
package-lock.json
generated
17
package-lock.json
generated
|
@ -38,6 +38,7 @@
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
|
"prettier": "3.4.2",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "~5.6.2"
|
"typescript": "~5.6.2"
|
||||||
}
|
}
|
||||||
|
@ -10845,6 +10846,22 @@
|
||||||
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
|
||||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
|
"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": {
|
"node_modules/proc-log": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
|
||||||
|
|
|
@ -40,7 +40,8 @@
|
||||||
"karma-jasmine": "~5.1.0",
|
"karma-jasmine": "~5.1.0",
|
||||||
"karma-jasmine-html-reporter": "~2.1.0",
|
"karma-jasmine-html-reporter": "~2.1.0",
|
||||||
"postcss": "^8.5.1",
|
"postcss": "^8.5.1",
|
||||||
|
"prettier": "3.4.2",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"typescript": "~5.6.2"
|
"typescript": "~5.6.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
branches: ['prod'],
|
branches: ["prod"],
|
||||||
plugins: [
|
plugins: [
|
||||||
'@semantic-release/commit-analyzer',
|
"@semantic-release/commit-analyzer",
|
||||||
'@semantic-release/release-notes-generator',
|
"@semantic-release/release-notes-generator",
|
||||||
'@semantic-release/changelog',
|
"@semantic-release/changelog",
|
||||||
["@saithodev/semantic-release-gitea", {
|
[
|
||||||
"giteaUrl": "https://git.kjan.de"
|
"@saithodev/semantic-release-gitea",
|
||||||
}],
|
{
|
||||||
|
giteaUrl: "https://git.kjan.de",
|
||||||
|
},
|
||||||
|
],
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,8 @@ describe('AppComponent', () => {
|
||||||
const fixture = TestBed.createComponent(AppComponent);
|
const fixture = TestBed.createComponent(AppComponent);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const compiled = fixture.nativeElement as HTMLElement;
|
const compiled = fixture.nativeElement as HTMLElement;
|
||||||
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, jklink');
|
expect(compiled.querySelector('h1')?.textContent).toContain(
|
||||||
|
'Hello, jklink',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { RouterOutlet } from '@angular/router';
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [RouterOutlet],
|
imports: [RouterOutlet],
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.css'
|
styleUrl: './app.component.css',
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent {}
|
||||||
}
|
|
||||||
|
|
|
@ -5,5 +5,9 @@ import { routes } from './app.routes';
|
||||||
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync()]
|
providers: [
|
||||||
|
provideZoneChangeDetection({ eventCoalescing: true }),
|
||||||
|
provideRouter(routes),
|
||||||
|
provideAnimationsAsync(),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ export const routes: Routes = [
|
||||||
component: ViewLinkComponent,
|
component: ViewLinkComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "**",
|
path: '**',
|
||||||
redirectTo: "",
|
redirectTo: '',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<h2 mat-dialog-title>{{data.title}}</h2>
|
<h2 mat-dialog-title>{{ data.title }}</h2>
|
||||||
<mat-dialog-content>{{data.description}}</mat-dialog-content>
|
<mat-dialog-content>{{ data.description }}</mat-dialog-content>
|
||||||
<mat-dialog-actions>
|
<mat-dialog-actions>
|
||||||
<button mat-flat-button color="warn" (click)="close()">No</button>
|
<button mat-flat-button color="warn" (click)="close()">No</button>
|
||||||
<button mat-flat-button (click)="accept()">Yes</button>
|
<button mat-flat-button (click)="accept()">Yes</button>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('VisitLinkConfirmationComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ConfirmationModalComponent]
|
imports: [ConfirmationModalComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(ConfirmationModalComponent);
|
fixture = TestBed.createComponent(ConfirmationModalComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -12,9 +12,14 @@ import { ConfirmationModalDto } from '../models/confirmation-modal';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-confirmation-modal',
|
selector: 'app-confirmation-modal',
|
||||||
imports: [MatDialogTitle, MatDialogContent, MatDialogActions, MatButtonModule],
|
imports: [
|
||||||
|
MatDialogTitle,
|
||||||
|
MatDialogContent,
|
||||||
|
MatDialogActions,
|
||||||
|
MatButtonModule,
|
||||||
|
],
|
||||||
templateUrl: './confirmation-modal.component.html',
|
templateUrl: './confirmation-modal.component.html',
|
||||||
styleUrl: './confirmation-modal.component.css'
|
styleUrl: './confirmation-modal.component.css',
|
||||||
})
|
})
|
||||||
export class ConfirmationModalComponent {
|
export class ConfirmationModalComponent {
|
||||||
public data: ConfirmationModalDto = inject(MAT_DIALOG_DATA);
|
public data: ConfirmationModalDto = inject(MAT_DIALOG_DATA);
|
||||||
|
|
|
@ -1,17 +1,24 @@
|
||||||
<div class="mx-auto container">
|
<div class="mx-auto container">
|
||||||
<app-navbar></app-navbar>
|
<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">
|
<mat-card class="mt-3 p-3" appearance="outlined">
|
||||||
<form class="flex flex-col" [formGroup]="createLinkForm">
|
<form class="flex flex-col" [formGroup]="createLinkForm">
|
||||||
<mat-form-field appearance="outline">
|
<mat-form-field appearance="outline">
|
||||||
<mat-error>{{errorMessages['name']}}</mat-error>
|
<mat-error>{{ errorMessages["name"] }}</mat-error>
|
||||||
<mat-label>Name</mat-label>
|
<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>
|
||||||
<mat-form-field appearance="outline">
|
<mat-form-field appearance="outline">
|
||||||
<mat-error>{{errorMessages['link']}}</mat-error>
|
<mat-error>{{ errorMessages["link"] }}</mat-error>
|
||||||
<mat-label>Link</mat-label>
|
<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>
|
</mat-form-field>
|
||||||
<button mat-flat-button type="submit" (click)="submit()">Create</button>
|
<button mat-flat-button type="submit" (click)="submit()">Create</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('CreateLinkComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [CreateLinkComponent]
|
imports: [CreateLinkComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(CreateLinkComponent);
|
fixture = TestBed.createComponent(CreateLinkComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { NavbarComponent } from '../navbar/navbar.component';
|
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 { LinkService } from '../service/link.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { MatCardModule } from '@angular/material/card';
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
@ -11,31 +16,45 @@ import { debounceTime } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-create-link',
|
selector: 'app-create-link',
|
||||||
imports: [NavbarComponent, ReactiveFormsModule, MatCardModule, MatFormFieldModule, MatInputModule, MatButtonModule],
|
imports: [
|
||||||
|
NavbarComponent,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
MatCardModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatButtonModule,
|
||||||
|
],
|
||||||
templateUrl: './create-link.component.html',
|
templateUrl: './create-link.component.html',
|
||||||
styleUrl: './create-link.component.css'
|
styleUrl: './create-link.component.css',
|
||||||
})
|
})
|
||||||
export class CreateLinkComponent {
|
export class CreateLinkComponent {
|
||||||
public createLinkForm!: FormGroup;
|
public createLinkForm!: FormGroup;
|
||||||
public requestFailed: boolean = false;
|
public requestFailed: boolean = false;
|
||||||
public errorMessages: Record<string, string> = {};
|
public errorMessages: Record<string, string> = {};
|
||||||
|
|
||||||
constructor(private linkService: LinkService, private router: Router) { }
|
constructor(
|
||||||
|
private linkService: LinkService,
|
||||||
|
private router: Router,
|
||||||
|
) {}
|
||||||
|
|
||||||
private validationErrorMessages: Record<string, string> = {
|
private validationErrorMessages: Record<string, string> = {
|
||||||
required: "This field is required",
|
required: 'This field is required',
|
||||||
pattern: "This must be a valid url",
|
pattern: 'This must be a valid url',
|
||||||
};
|
};
|
||||||
|
|
||||||
updateErrorMessages(): void {
|
updateErrorMessages(): void {
|
||||||
this.errorMessages = {};
|
this.errorMessages = {};
|
||||||
|
|
||||||
Object.keys(this.createLinkForm.controls).forEach(field => {
|
Object.keys(this.createLinkForm.controls).forEach((field) => {
|
||||||
const control = this.createLinkForm.get(field);
|
const control = this.createLinkForm.get(field);
|
||||||
|
|
||||||
if (control && control.errors) {
|
if (control && control.errors) {
|
||||||
this.errorMessages[field] = Object.keys(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(' ');
|
.join(' ');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -48,7 +67,12 @@ export class CreateLinkComponent {
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.createLinkForm = new FormGroup({
|
this.createLinkForm = new FormGroup({
|
||||||
name: new FormControl('', Validators.required),
|
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.createLinkForm.valueChanges.subscribe(() => {
|
||||||
this.updateErrorMessages();
|
this.updateErrorMessages();
|
||||||
|
@ -56,19 +80,21 @@ export class CreateLinkComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
|
||||||
if (!this.createLinkForm.valid) {
|
if (!this.createLinkForm.valid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.requestFailed = false;
|
this.requestFailed = false;
|
||||||
this.linkService.createLink({
|
this.linkService
|
||||||
name: this.createLinkForm.get('name')?.value,
|
.createLink({
|
||||||
link: this.createLinkForm.get('link')?.value,
|
name: this.createLinkForm.get('name')?.value,
|
||||||
}).catch(() => this.requestFailed = true).finally(() => {
|
link: this.createLinkForm.get('link')?.value,
|
||||||
if (!this.requestFailed) {
|
})
|
||||||
this.router.navigate(['dashboard']);
|
.catch(() => (this.requestFailed = true))
|
||||||
}
|
.finally(() => {
|
||||||
});
|
if (!this.requestFailed) {
|
||||||
|
this.router.navigate(['dashboard']);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,54 +1,72 @@
|
||||||
<div class="mx-auto container">
|
<div class="mx-auto container">
|
||||||
<app-navbar></app-navbar>
|
<app-navbar></app-navbar>
|
||||||
<div class="overflow-x-auto">
|
<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 appearance="outlined">
|
||||||
<mat-card-content>
|
<mat-card-content>
|
||||||
<table mat-table [dataSource]="links" class="mat-elevation-z8">
|
<table mat-table [dataSource]="links" class="mat-elevation-z8">
|
||||||
|
|
||||||
<!--- Note that these columns can be defined in any order.
|
<!--- Note that these columns can be defined in any order.
|
||||||
The actual rendered columns are set as a property on the row definition" -->
|
The actual rendered columns are set as a property on the row definition" -->
|
||||||
|
|
||||||
<!-- Position Column -->
|
<!-- Position Column -->
|
||||||
<ng-container matColumnDef="id">
|
<ng-container matColumnDef="id">
|
||||||
<th mat-header-cell *matHeaderCellDef> ID </th>
|
<th mat-header-cell *matHeaderCellDef>ID</th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<td mat-cell *matCellDef="let element">
|
||||||
<a (click)="goToLink(element)" class="link">
|
<a (click)="goToLink(element)" class="link">
|
||||||
{{element.id}}
|
{{ element.id }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Name Column -->
|
<!-- Name Column -->
|
||||||
<ng-container matColumnDef="name">
|
<ng-container matColumnDef="name">
|
||||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
<th mat-header-cell *matHeaderCellDef>Name</th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
<td mat-cell *matCellDef="let element">{{ element.name }}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Weight Column -->
|
<!-- Weight Column -->
|
||||||
<ng-container matColumnDef="link">
|
<ng-container matColumnDef="link">
|
||||||
<th mat-header-cell *matHeaderCellDef> Link </th>
|
<th mat-header-cell *matHeaderCellDef>Link</th>
|
||||||
<td mat-cell *matCellDef="let element"> {{element.link}} </td>
|
<td mat-cell *matCellDef="let element">{{ element.link }}</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Symbol Column -->
|
<!-- Symbol Column -->
|
||||||
<ng-container matColumnDef="shortLink">
|
<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">
|
<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>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
<ng-container matColumnDef="actions">
|
||||||
<th mat-header-cell *matHeaderCellDef> Actions </th>
|
<th mat-header-cell *matHeaderCellDef>Actions</th>
|
||||||
<td mat-cell *matCellDef="let element">
|
<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>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
<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>
|
</table>
|
||||||
</mat-card-content>
|
</mat-card-content>
|
||||||
</mat-card>
|
</mat-card>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('DashboardComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [DashboardComponent]
|
imports: [DashboardComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(DashboardComponent);
|
fixture = TestBed.createComponent(DashboardComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -15,40 +15,48 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
selector: 'app-dashboard',
|
selector: 'app-dashboard',
|
||||||
imports: [NavbarComponent, MatTableModule, MatCardModule, MatButtonModule],
|
imports: [NavbarComponent, MatTableModule, MatCardModule, MatButtonModule],
|
||||||
templateUrl: './dashboard.component.html',
|
templateUrl: './dashboard.component.html',
|
||||||
styleUrl: './dashboard.component.css'
|
styleUrl: './dashboard.component.css',
|
||||||
})
|
})
|
||||||
export class DashboardComponent {
|
export class DashboardComponent {
|
||||||
public links: Link[] = [];
|
public links: Link[] = [];
|
||||||
displayedColumns: string[] = ['id', 'name', 'link', 'shortLink', 'actions'];
|
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) {
|
copyLink(id: string) {
|
||||||
navigator.clipboard.writeText(this.getShortLink(id));
|
navigator.clipboard.writeText(this.getShortLink(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
getShortLink(id: string): string {
|
getShortLink(id: string): string {
|
||||||
return "https://" + window.location.hostname + '/' + id;
|
return 'https://' + window.location.hostname + '/' + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
goToLink(link: Link) {
|
goToLink(link: Link) {
|
||||||
this.dialog.open(ConfirmationModalComponent, {
|
this.dialog
|
||||||
data: {
|
.open(ConfirmationModalComponent, {
|
||||||
title: "Are you sure?",
|
data: {
|
||||||
description: "Are you sure that you want to open " + link.link + " now?",
|
title: 'Are you sure?',
|
||||||
},
|
description:
|
||||||
}).afterClosed().subscribe((accepted: Boolean) => {
|
'Are you sure that you want to open ' + link.link + ' now?',
|
||||||
if (accepted) {
|
},
|
||||||
this.router.navigate([link.id]);
|
})
|
||||||
}
|
.afterClosed()
|
||||||
});
|
.subscribe((accepted: Boolean) => {
|
||||||
|
if (accepted) {
|
||||||
|
this.router.navigate([link.id]);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.linkService.getLinks().then(links => {
|
this.linkService.getLinks().then((links) => {
|
||||||
this.links = links;
|
this.links = links;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createLink() {
|
createLink() {
|
||||||
|
@ -56,29 +64,35 @@ export class DashboardComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteLink(link: Link) {
|
deleteLink(link: Link) {
|
||||||
this.dialog.open(ConfirmationModalComponent, {
|
this.dialog
|
||||||
data: {
|
.open(ConfirmationModalComponent, {
|
||||||
title: "Are you sure?",
|
data: {
|
||||||
description: "Are you sure that you want to delete " + link.name + "?",
|
title: 'Are you sure?',
|
||||||
}
|
description:
|
||||||
}).afterClosed().subscribe((accepted: boolean) => {
|
'Are you sure that you want to delete ' + link.name + '?',
|
||||||
if (accepted) {
|
},
|
||||||
this.linkService.deleteLink(link.id).catch(() => {
|
})
|
||||||
const errorNotification = this.snackBar.open("Something went wrong.");
|
.afterClosed()
|
||||||
|
.subscribe((accepted: boolean) => {
|
||||||
|
if (accepted) {
|
||||||
|
this.linkService.deleteLink(link.id).catch(() => {
|
||||||
|
const errorNotification = this.snackBar.open(
|
||||||
|
'Something went wrong.',
|
||||||
|
);
|
||||||
|
setTimeout(() => {
|
||||||
|
errorNotification.dismiss();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.links = this.links.filter((givenLink) => {
|
||||||
|
return givenLink.id != link.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
const notification = this.snackBar.open(link.name + ' was deleted.');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
errorNotification.dismiss();
|
notification.dismiss();
|
||||||
}, 5000);
|
}, 2000);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
this.links = this.links.filter(givenLink => {
|
|
||||||
return givenLink.id != link.id;
|
|
||||||
});
|
|
||||||
|
|
||||||
const notification = this.snackBar.open(link.name + " was deleted.");
|
|
||||||
setTimeout(() => {
|
|
||||||
notification.dismiss();
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,74 @@
|
||||||
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
|
<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">
|
<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"
|
<img
|
||||||
alt="Your Company">
|
class="mx-auto h-10 w-auto"
|
||||||
<h2 class="mt-10 text-center text-2xl/9 font-bold tracking-tight text-gray-900">Sign in to your account</h2>
|
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>
|
||||||
|
|
||||||
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||||
<form [formGroup]="loginForm" class="space-y-6" action="#" method="POST">
|
<form [formGroup]="loginForm" class="space-y-6" action="#" method="POST">
|
||||||
@if (invalidCredentials) {
|
@if (invalidCredentials) {
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<p
|
<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">
|
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>
|
Invalid Credentials
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
<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">
|
<div class="mt-2">
|
||||||
<input formControlName="email" type="email" name="email" id="email" autocomplete="email" required
|
<input
|
||||||
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">
|
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>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center justify-between">
|
<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>
|
||||||
<div class="mt-2">
|
<div class="mt-2">
|
||||||
<input formControlName="password" type="password" name="password" id="password"
|
<input
|
||||||
autocomplete="current-password" required
|
formControlName="password"
|
||||||
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">
|
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>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button (click)="submit()" type="submit"
|
<button
|
||||||
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
|
(click)="submit()"
|
||||||
in</button>
|
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>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('LoginComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [LoginComponent]
|
imports: [LoginComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(LoginComponent);
|
fixture = TestBed.createComponent(LoginComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -8,14 +8,14 @@ import { Router } from '@angular/router';
|
||||||
selector: 'app-login',
|
selector: 'app-login',
|
||||||
imports: [ReactiveFormsModule],
|
imports: [ReactiveFormsModule],
|
||||||
templateUrl: './login.component.html',
|
templateUrl: './login.component.html',
|
||||||
styleUrl: './login.component.css'
|
styleUrl: './login.component.css',
|
||||||
})
|
})
|
||||||
export class LoginComponent {
|
export class LoginComponent {
|
||||||
public loginForm!: FormGroup;
|
public loginForm!: FormGroup;
|
||||||
public invalidCredentials = false;
|
public invalidCredentials = false;
|
||||||
private pb = new PocketBase(environment.POCKETBASE);
|
private pb = new PocketBase(environment.POCKETBASE);
|
||||||
|
|
||||||
constructor(private router: Router) { };
|
constructor(private router: Router) {}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.loginForm = new FormGroup({
|
this.loginForm = new FormGroup({
|
||||||
|
@ -29,13 +29,17 @@ export class LoginComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.pb.collection("users").authWithPassword(
|
this.pb
|
||||||
this.loginForm.get('email')?.value,
|
.collection('users')
|
||||||
this.loginForm.get('password')?.value
|
.authWithPassword(
|
||||||
).then(() => {
|
this.loginForm.get('email')?.value,
|
||||||
|
this.loginForm.get('password')?.value,
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
this.router.navigate(['dashboard']);
|
this.router.navigate(['dashboard']);
|
||||||
}).catch(() => {
|
})
|
||||||
this.invalidCredentials = true;
|
.catch(() => {
|
||||||
});
|
this.invalidCredentials = true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export interface ConfirmationModalDto {
|
export interface ConfirmationModalDto {
|
||||||
title: string,
|
title: string;
|
||||||
description: string,
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('NavbarComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [NavbarComponent]
|
imports: [NavbarComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(NavbarComponent);
|
fixture = TestBed.createComponent(NavbarComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -7,6 +7,4 @@ import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
styleUrl: './navbar.component.css',
|
styleUrl: './navbar.component.css',
|
||||||
encapsulation: ViewEncapsulation.None,
|
encapsulation: ViewEncapsulation.None,
|
||||||
})
|
})
|
||||||
export class NavbarComponent {
|
export class NavbarComponent {}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,20 +5,26 @@ import {
|
||||||
GuardResult,
|
GuardResult,
|
||||||
MaybeAsync,
|
MaybeAsync,
|
||||||
Router,
|
Router,
|
||||||
RouterStateSnapshot
|
RouterStateSnapshot,
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import PocketBase from 'pocketbase';
|
import PocketBase from 'pocketbase';
|
||||||
import { environment } from '../../environments/environment';
|
import { environment } from '../../environments/environment';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AuthGuard implements CanActivate {
|
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);
|
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) {
|
if (pb.authStore.isValid) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import { Injectable } from "@angular/core";
|
import { Injectable } from '@angular/core';
|
||||||
import { environment } from "../../environments/environment";
|
import { environment } from '../../environments/environment';
|
||||||
import PocketBase, { RecordModel } from 'pocketbase';
|
import PocketBase, { RecordModel } from 'pocketbase';
|
||||||
import { Link } from "../models/link";
|
import { Link } from '../models/link';
|
||||||
|
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class LinkService {
|
export class LinkService {
|
||||||
private pb = new PocketBase(environment.POCKETBASE);
|
private pb = new PocketBase(environment.POCKETBASE);
|
||||||
|
@ -24,9 +23,9 @@ export class LinkService {
|
||||||
|
|
||||||
createLink(link: any): Promise<RecordModel> {
|
createLink(link: any): Promise<RecordModel> {
|
||||||
return this.pb.collection('links').create({
|
return this.pb.collection('links').create({
|
||||||
'name': link.name,
|
name: link.name,
|
||||||
'link': link.link,
|
link: link.link,
|
||||||
'owner': this.pb.authStore.record?.id,
|
owner: this.pb.authStore.record?.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
<p>Your are being redirected.</p>
|
<p>Your are being redirected.</p>
|
||||||
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5944102294748899"
|
<script
|
||||||
crossorigin="anonymous"></script>
|
async
|
||||||
|
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5944102294748899"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
></script>
|
||||||
|
|
|
@ -8,9 +8,8 @@ describe('ViewLinkComponent', () => {
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await TestBed.configureTestingModule({
|
await TestBed.configureTestingModule({
|
||||||
imports: [ViewLinkComponent]
|
imports: [ViewLinkComponent],
|
||||||
})
|
}).compileComponents();
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(ViewLinkComponent);
|
fixture = TestBed.createComponent(ViewLinkComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
|
|
|
@ -6,14 +6,20 @@ import { ActivatedRoute, Router } from '@angular/router';
|
||||||
selector: 'app-view-link',
|
selector: 'app-view-link',
|
||||||
imports: [],
|
imports: [],
|
||||||
templateUrl: './view-link.component.html',
|
templateUrl: './view-link.component.html',
|
||||||
styleUrl: './view-link.component.css'
|
styleUrl: './view-link.component.css',
|
||||||
})
|
})
|
||||||
export class ViewLinkComponent {
|
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 {
|
ngOnInit(): void {
|
||||||
this.linkService.getLink(this.route.snapshot.params['link']).then(link => {
|
this.linkService
|
||||||
window.location.href = link.link;
|
.getLink(this.route.snapshot.params['link'])
|
||||||
});
|
.then((link) => {
|
||||||
|
window.location.href = link.link;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export const environment = {
|
export const environment = {
|
||||||
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de'
|
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
export const environment = {
|
export const environment = {
|
||||||
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de'
|
POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,15 +1,21 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html class="h-full" lang="en" data-theme="light">
|
<html class="h-full" lang="en" data-theme="light">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<title>Jklink</title>
|
<title>Jklink</title>
|
||||||
<base href="/">
|
<base href="/" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
<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
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
|
||||||
</head>
|
rel="stylesheet"
|
||||||
<body class="h-full base-100 mat-typography" >
|
/>
|
||||||
<app-root></app-root>
|
<link
|
||||||
</body>
|
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>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -2,5 +2,6 @@ import { bootstrapApplication } from '@angular/platform-browser';
|
||||||
import { appConfig } from './app/app.config';
|
import { appConfig } from './app/app.config';
|
||||||
import { AppComponent } from './app/app.component';
|
import { AppComponent } from './app/app.component';
|
||||||
|
|
||||||
bootstrapApplication(AppComponent, appConfig)
|
bootstrapApplication(AppComponent, appConfig).catch((err) =>
|
||||||
.catch((err) => console.error(err));
|
console.error(err),
|
||||||
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@use '@angular/material' as mat;
|
@use "@angular/material" as mat;
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
content: [
|
content: ["./src/**/*.{html,ts}"],
|
||||||
"./src/**/*.{html,ts}",
|
|
||||||
],
|
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
|
@ -10,5 +8,4 @@ module.exports = {
|
||||||
preflight: false,
|
preflight: false,
|
||||||
},
|
},
|
||||||
plugins: [],
|
plugins: [],
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,6 @@
|
||||||
"outDir": "./out-tsc/app",
|
"outDir": "./out-tsc/app",
|
||||||
"types": []
|
"types": []
|
||||||
},
|
},
|
||||||
"files": [
|
"files": ["src/main.ts"],
|
||||||
"src/main.ts"
|
"include": ["src/**/*.d.ts"]
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,7 @@
|
||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./out-tsc/spec",
|
"outDir": "./out-tsc/spec",
|
||||||
"types": [
|
"types": ["jasmine"]
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
|
||||||
"src/**/*.spec.ts",
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue