From 00a7688ef9bc86f0cc707343123a62d8c7db1181 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Mon, 20 Jan 2025 15:11:46 +0100 Subject: [PATCH 1/8] feat(create-link): add create link component and routing --- src/app/app.routes.ts | 6 +++ src/app/create-link/create-link.component.css | 0 .../create-link/create-link.component.html | 29 +++++++++++++++ .../create-link/create-link.component.spec.ts | 23 ++++++++++++ src/app/create-link/create-link.component.ts | 37 +++++++++++++++++++ src/app/dashboard/dashboard.component.html | 5 +++ src/app/dashboard/dashboard.component.ts | 14 ++++++- src/app/service/link.service.ts | 12 ++++++ 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 src/app/create-link/create-link.component.css create mode 100644 src/app/create-link/create-link.component.html create mode 100644 src/app/create-link/create-link.component.spec.ts create mode 100644 src/app/create-link/create-link.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index b66a2af..f710735 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -2,6 +2,7 @@ import { Routes } from '@angular/router'; import { LoginComponent } from './login/login.component'; import { DashboardComponent } from './dashboard/dashboard.component'; import { AuthGuard } from './service/auth.service'; +import { CreateLinkComponent } from './create-link/create-link.component'; export const routes: Routes = [ { @@ -13,6 +14,11 @@ export const routes: Routes = [ component: DashboardComponent, canActivate: [AuthGuard], }, + { + path: 'create-link', + component: CreateLinkComponent, + canActivate: [AuthGuard], + }, { path: "**", redirectTo: "", diff --git a/src/app/create-link/create-link.component.css b/src/app/create-link/create-link.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/create-link/create-link.component.html b/src/app/create-link/create-link.component.html new file mode 100644 index 0000000..73a1d3f --- /dev/null +++ b/src/app/create-link/create-link.component.html @@ -0,0 +1,29 @@ +
+ +
+ +
+
+

Create link

+ @if (requestFailed) { + + } +
+ + +
+
+ +
+
+
+
+
diff --git a/src/app/create-link/create-link.component.spec.ts b/src/app/create-link/create-link.component.spec.ts new file mode 100644 index 0000000..b706423 --- /dev/null +++ b/src/app/create-link/create-link.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CreateLinkComponent } from './create-link.component'; + +describe('CreateLinkComponent', () => { + let component: CreateLinkComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [CreateLinkComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(CreateLinkComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/create-link/create-link.component.ts b/src/app/create-link/create-link.component.ts new file mode 100644 index 0000000..7ba3c72 --- /dev/null +++ b/src/app/create-link/create-link.component.ts @@ -0,0 +1,37 @@ +import { Component } from '@angular/core'; +import { NavbarComponent } from '../navbar/navbar.component'; +import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms'; +import { LinkService } from '../service/link.service'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-create-link', + imports: [NavbarComponent, ReactiveFormsModule], + templateUrl: './create-link.component.html', + styleUrl: './create-link.component.css' +}) +export class CreateLinkComponent { + public createLinkForm!: FormGroup; + public requestFailed: boolean = false; + + constructor(private linkService: LinkService, private router: Router) { } + + ngOnInit(): void { + this.createLinkForm = new FormGroup({ + name: new FormControl(''), + link: new FormControl(''), + }); + } + + submit() { + this.requestFailed = false; + this.linkService.createLink({ + name: this.createLinkForm.get('name')?.value, + link: this.createLinkForm.get('link')?.value, + }).catch(() => this.requestFailed = true).finally(() => { + if (!this.requestFailed) { + this.router.navigate(['dashboard']); + } + }); + } +} diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index d6c8733..2caa0c5 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -1,6 +1,7 @@
+ @@ -9,6 +10,7 @@ + @@ -19,6 +21,9 @@ + } diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index 09f1a42..ab639a2 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { LinkService } from '../service/link.service'; import { RecordModel } from 'pocketbase'; import { NavbarComponent } from '../navbar/navbar.component'; +import { Router, RouterLink } from '@angular/router'; @Component({ selector: 'app-dashboard', @@ -12,11 +13,22 @@ import { NavbarComponent } from '../navbar/navbar.component'; export class DashboardComponent { public links: any[] = []; - constructor(private linkService: LinkService) { }; + constructor(private linkService: LinkService, private router: Router) { }; ngOnInit(): void { this.linkService.getLinks().then(links => { this.links = links; }); } + + createLink() { + this.router.navigate(['create-link']); + } + + deleteLink(id: string) { + this.linkService.deleteLink(id); // TODO Check if something went wrong + this.links = this.links.filter(link => { + return link.id != id; + }); + } } diff --git a/src/app/service/link.service.ts b/src/app/service/link.service.ts index 51eb8d8..fa08a5a 100644 --- a/src/app/service/link.service.ts +++ b/src/app/service/link.service.ts @@ -12,4 +12,16 @@ export class LinkService { getLinks(): Promise { return this.pb.collection('links').getFullList(); } + + deleteLink(id: string) { + this.pb.collection('links').delete(id); + } + + createLink(link: any): Promise { + return this.pb.collection('links').create({ + 'name': link.name, + 'link': link.link, + 'owner': this.pb.authStore.record?.id, + }); + } } From 6317c97d96ae28bd8f3cb9e63abffd6e2747532e Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 09:31:43 +0100 Subject: [PATCH 2/8] feat: add Angular Material and refactor UI components --- angular.json | 4 +- package-lock.json | 41 ++++++++++- package.json | 4 +- src/app/app.config.ts | 3 +- .../create-link/create-link.component.html | 44 +++++------- src/app/create-link/create-link.component.ts | 45 ++++++++++-- src/app/dashboard/dashboard.component.html | 72 ++++++++++++------- src/app/dashboard/dashboard.component.ts | 9 ++- src/app/models/link.ts | 6 ++ src/app/navbar/navbar.component.html | 52 -------------- src/app/service/link.service.ts | 5 +- src/index.html | 4 +- src/styles.css | 3 - src/styles.scss | 22 ++++++ tailwind.config.js | 11 +-- 15 files changed, 194 insertions(+), 131 deletions(-) create mode 100644 src/app/models/link.ts delete mode 100644 src/styles.css create mode 100644 src/styles.scss diff --git a/angular.json b/angular.json index f2cd277..3f41ec4 100644 --- a/angular.json +++ b/angular.json @@ -27,7 +27,8 @@ } ], "styles": [ - "src/styles.css" + "@angular/material/prebuilt-themes/azure-blue.css", + "src/styles.scss" ], "scripts": [] }, @@ -97,6 +98,7 @@ } ], "styles": [ + "@angular/material/prebuilt-themes/azure-blue.css", "src/styles.css" ], "scripts": [] diff --git a/package-lock.json b/package-lock.json index d6e2024..6a63114 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,12 @@ "version": "0.0.0", "dependencies": { "@angular/animations": "^19.0.0", + "@angular/cdk": "^19.1.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", + "@angular/material": "^19.1.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", @@ -390,6 +392,23 @@ } } }, + "node_modules/@angular/cdk": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/cdk/-/cdk-19.1.0.tgz", + "integrity": "sha512-h7VSaMA/vFHb7u1bwoHKl3L3mZLIcXNZw6v7Nei9ITfEo1PfSKbrYhleeqpNikzE+LxNDKJrbZtpAckSYHblmA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "optionalDependencies": { + "parse5": "^7.1.2" + }, + "peerDependencies": { + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@angular/cli": { "version": "19.1.2", "resolved": "https://registry.npmjs.org/@angular/cli/-/cli-19.1.2.tgz", @@ -517,6 +536,24 @@ "rxjs": "^6.5.3 || ^7.4.0" } }, + "node_modules/@angular/material": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@angular/material/-/material-19.1.0.tgz", + "integrity": "sha512-LTQBWtuRGjNpA7ceQu9PyiUUq0KLfBP8LvL04hLFbEsZ0fIPQ/OO/Otn67/7TMtnHRFnPeezYPHcAHBhiNlR4A==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "peerDependencies": { + "@angular/animations": "^19.0.0 || ^20.0.0", + "@angular/cdk": "19.1.0", + "@angular/common": "^19.0.0 || ^20.0.0", + "@angular/core": "^19.0.0 || ^20.0.0", + "@angular/forms": "^19.0.0 || ^20.0.0", + "@angular/platform-browser": "^19.0.0 || ^20.0.0", + "rxjs": "^6.5.3 || ^7.4.0" + } + }, "node_modules/@angular/platform-browser": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/@angular/platform-browser/-/platform-browser-19.1.1.tgz", @@ -6663,7 +6700,7 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.12" }, @@ -10387,7 +10424,7 @@ "version": "7.2.1", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", - "dev": true, + "devOptional": true, "dependencies": { "entities": "^4.5.0" }, diff --git a/package.json b/package.json index fb2e239..86546d4 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,12 @@ "private": true, "dependencies": { "@angular/animations": "^19.0.0", + "@angular/cdk": "^19.1.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", + "@angular/material": "^19.1.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", @@ -41,4 +43,4 @@ "tailwindcss": "^3.4.17", "typescript": "~5.6.2" } -} +} \ No newline at end of file diff --git a/src/app/app.config.ts b/src/app/app.config.ts index a1e7d6f..96116fd 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -2,7 +2,8 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; +import { provideAnimationsAsync } from '@angular/platform-browser/animations/async'; export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)] + providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideAnimationsAsync()] }; diff --git a/src/app/create-link/create-link.component.html b/src/app/create-link/create-link.component.html index 73a1d3f..6bc479c 100644 --- a/src/app/create-link/create-link.component.html +++ b/src/app/create-link/create-link.component.html @@ -1,29 +1,19 @@ -
+
-
- -
-
-

Create link

- @if (requestFailed) { - - } -
- - - -
- -
-
-
-
+ + +
+ + {{errorMessages['name']}} + Name + + + + {{errorMessages['link']}} + Link + + + + +
diff --git a/src/app/create-link/create-link.component.ts b/src/app/create-link/create-link.component.ts index 7ba3c72..76c3dcf 100644 --- a/src/app/create-link/create-link.component.ts +++ b/src/app/create-link/create-link.component.ts @@ -1,29 +1,66 @@ import { Component } from '@angular/core'; import { NavbarComponent } from '../navbar/navbar.component'; -import { FormControl, FormGroup, ReactiveFormsModule } 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'; +import { MatInputModule, MatLabel } from '@angular/material/input'; +import { MatFormFieldModule } from '@angular/material/form-field'; +import { MatButtonModule } from '@angular/material/button'; +import { debounceTime } from 'rxjs'; @Component({ selector: 'app-create-link', - imports: [NavbarComponent, ReactiveFormsModule], + imports: [NavbarComponent, ReactiveFormsModule, MatCardModule, MatFormFieldModule, MatInputModule, MatButtonModule], templateUrl: './create-link.component.html', styleUrl: './create-link.component.css' }) export class CreateLinkComponent { public createLinkForm!: FormGroup; public requestFailed: boolean = false; + public errorMessages: Record = {}; constructor(private linkService: LinkService, private router: Router) { } + private validationErrorMessages: Record = { + required: "This field is required", + pattern: "This must be a valid url", + }; + + updateErrorMessages(): void { + this.errorMessages = {}; + + 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}`) + .join(' '); + } + }); + } + + back() { + this.router.navigate(['dashboard']); + } + ngOnInit(): void { this.createLinkForm = new FormGroup({ - name: new FormControl(''), - link: new FormControl(''), + 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]*))?)/)]), + }); + this.createLinkForm.valueChanges.subscribe(() => { + this.updateErrorMessages(); }); } submit() { + + if (!this.createLinkForm.valid) { + return; + } + this.requestFailed = false; this.linkService.createLink({ name: this.createLinkForm.get('name')?.value, diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index 2caa0c5..66e4837 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -1,32 +1,50 @@
- -
Name Url Short UrlActions
{{link.name}} {{link.link}} ndy + +
- - - - - - - - - - - - - @for (link of links; track link) { - - - - - - - - } - -
NameUrlShort UrlActions
{{link.id}}{{link.name}}{{link.link}}ndy - -
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ID {{element.id}} Name {{element.name}} Link {{element.link}} Short Url ndy Actions + +
+
+
diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index ab639a2..f792206 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -3,15 +3,20 @@ import { LinkService } from '../service/link.service'; import { RecordModel } from 'pocketbase'; import { NavbarComponent } from '../navbar/navbar.component'; import { Router, RouterLink } from '@angular/router'; +import { MatRow, MatTableModule } from '@angular/material/table'; +import { MatCardModule } from '@angular/material/card'; +import { Link } from '../models/link'; +import { MatButtonModule } from '@angular/material/button'; @Component({ selector: 'app-dashboard', - imports: [NavbarComponent], + imports: [NavbarComponent, MatTableModule, MatCardModule, MatButtonModule], templateUrl: './dashboard.component.html', styleUrl: './dashboard.component.css' }) export class DashboardComponent { - public links: any[] = []; + public links: Link[] = []; + displayedColumns: string[] = ['id', 'name', 'link', 'symbol', 'actions']; constructor(private linkService: LinkService, private router: Router) { }; diff --git a/src/app/models/link.ts b/src/app/models/link.ts new file mode 100644 index 0000000..0f961c3 --- /dev/null +++ b/src/app/models/link.ts @@ -0,0 +1,6 @@ +export interface Link { + id: string; + link: string; + name: string; + owner: string; +} diff --git a/src/app/navbar/navbar.component.html b/src/app/navbar/navbar.component.html index 1d6d14c..e69de29 100644 --- a/src/app/navbar/navbar.component.html +++ b/src/app/navbar/navbar.component.html @@ -1,52 +0,0 @@ - diff --git a/src/app/service/link.service.ts b/src/app/service/link.service.ts index fa08a5a..fcd0537 100644 --- a/src/app/service/link.service.ts +++ b/src/app/service/link.service.ts @@ -1,6 +1,7 @@ import { Injectable } from "@angular/core"; import { environment } from "../../environments/environment"; import PocketBase, { RecordModel } from 'pocketbase'; +import { Link } from "../models/link"; @Injectable({ @@ -9,8 +10,8 @@ import PocketBase, { RecordModel } from 'pocketbase'; export class LinkService { private pb = new PocketBase(environment.POCKETBASE); - getLinks(): Promise { - return this.pb.collection('links').getFullList(); + getLinks(): Promise { + return this.pb.collection('links').getFullList(); } deleteLink(id: string) { diff --git a/src/index.html b/src/index.html index c660faa..5ab9cdc 100644 --- a/src/index.html +++ b/src/index.html @@ -6,8 +6,10 @@ + + - + diff --git a/src/styles.css b/src/styles.css deleted file mode 100644 index b5c61c9..0000000 --- a/src/styles.css +++ /dev/null @@ -1,3 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; diff --git a/src/styles.scss b/src/styles.scss new file mode 100644 index 0000000..2b30ff0 --- /dev/null +++ b/src/styles.scss @@ -0,0 +1,22 @@ +@use '@angular/material' as mat; +@tailwind base; +@tailwind components; +@tailwind utilities; + +$theme: mat.define-theme(); + +html { + @include mat.all-component-themes($theme); + // This line allows you to use color="..." for your toolbar. + @include mat.color-variants-backwards-compatibility($theme); +} + +html, +body { + height: 100%; +} + +body { + margin: 0; + font-family: Roboto, "Helvetica Neue", sans-serif; +} diff --git a/tailwind.config.js b/tailwind.config.js index a57d5cf..f24e856 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -6,14 +6,9 @@ module.exports = { theme: { extend: {}, }, - daisyui: { - styled: true, - themes: true, - base: true, - utils: true, - logs: true, - rtl: false + corePlugins: { + preflight: false, }, - plugins: [require("@tailwindcss/typography"), require("daisyui")], + plugins: [], } From 79fc66ef6b4bb0edf62531d46d325c33b05dbcdd Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 10:32:55 +0100 Subject: [PATCH 3/8] feat(view-link): add ViewLink component and routing logic --- src/app/app.routes.ts | 5 ++++ src/app/service/link.service.ts | 4 ++++ src/app/view-link/view-link.component.css | 0 src/app/view-link/view-link.component.html | 1 + src/app/view-link/view-link.component.spec.ts | 23 +++++++++++++++++++ src/app/view-link/view-link.component.ts | 19 +++++++++++++++ 6 files changed, 52 insertions(+) create mode 100644 src/app/view-link/view-link.component.css create mode 100644 src/app/view-link/view-link.component.html create mode 100644 src/app/view-link/view-link.component.spec.ts create mode 100644 src/app/view-link/view-link.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index f710735..4c2ca33 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -3,6 +3,7 @@ import { LoginComponent } from './login/login.component'; import { DashboardComponent } from './dashboard/dashboard.component'; import { AuthGuard } from './service/auth.service'; import { CreateLinkComponent } from './create-link/create-link.component'; +import { ViewLinkComponent } from './view-link/view-link.component'; export const routes: Routes = [ { @@ -19,6 +20,10 @@ export const routes: Routes = [ component: CreateLinkComponent, canActivate: [AuthGuard], }, + { + path: ':link', + component: ViewLinkComponent, + }, { path: "**", redirectTo: "", diff --git a/src/app/service/link.service.ts b/src/app/service/link.service.ts index fcd0537..89b9329 100644 --- a/src/app/service/link.service.ts +++ b/src/app/service/link.service.ts @@ -14,6 +14,10 @@ export class LinkService { return this.pb.collection('links').getFullList(); } + getLink(id: string): Promise { + return this.pb.collection('links').getOne(id); + } + deleteLink(id: string) { this.pb.collection('links').delete(id); } diff --git a/src/app/view-link/view-link.component.css b/src/app/view-link/view-link.component.css new file mode 100644 index 0000000..e69de29 diff --git a/src/app/view-link/view-link.component.html b/src/app/view-link/view-link.component.html new file mode 100644 index 0000000..061042f --- /dev/null +++ b/src/app/view-link/view-link.component.html @@ -0,0 +1 @@ +

Your are being redirected.

diff --git a/src/app/view-link/view-link.component.spec.ts b/src/app/view-link/view-link.component.spec.ts new file mode 100644 index 0000000..1d509b7 --- /dev/null +++ b/src/app/view-link/view-link.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewLinkComponent } from './view-link.component'; + +describe('ViewLinkComponent', () => { + let component: ViewLinkComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ViewLinkComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ViewLinkComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/view-link/view-link.component.ts b/src/app/view-link/view-link.component.ts new file mode 100644 index 0000000..21951c3 --- /dev/null +++ b/src/app/view-link/view-link.component.ts @@ -0,0 +1,19 @@ +import { Component } from '@angular/core'; +import { LinkService } from '../service/link.service'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'app-view-link', + imports: [], + templateUrl: './view-link.component.html', + styleUrl: './view-link.component.css' +}) +export class ViewLinkComponent { + constructor(private linkService: LinkService, private route: ActivatedRoute, private router: Router) { } + + ngOnInit(): void { + this.linkService.getLink(this.route.snapshot.params['link']).then(link => { + window.location.href = link.link; + }); + } +} From 50cb62e56d0f68320f2aea93cb0571398c314e05 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 10:54:12 +0100 Subject: [PATCH 4/8] feat(dashboard): add copy link button to dashboard table --- src/app/dashboard/dashboard.component.html | 5 ++++- src/app/dashboard/dashboard.component.ts | 4 ++++ src/app/view-link/view-link.component.html | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index 66e4837..6ab4fff 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -13,7 +13,10 @@ ID - {{element.id}} + + {{element.id}} + + diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index f792206..dbb31e0 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -20,6 +20,10 @@ export class DashboardComponent { constructor(private linkService: LinkService, private router: Router) { }; + copyLink(id: string) { + navigator.clipboard.writeText(window.location.hostname + '/' + id); + } + ngOnInit(): void { this.linkService.getLinks().then(links => { this.links = links; diff --git a/src/app/view-link/view-link.component.html b/src/app/view-link/view-link.component.html index 061042f..a80c841 100644 --- a/src/app/view-link/view-link.component.html +++ b/src/app/view-link/view-link.component.html @@ -1 +1,3 @@

Your are being redirected.

+ From 6a19671fb4c036ab40319d30963a14d24ac573b8 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 11:04:43 +0100 Subject: [PATCH 5/8] chore: update Pocketbase URL in environment files --- src/environments/environment.development.ts | 2 +- src/environments/environment.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/environments/environment.development.ts b/src/environments/environment.development.ts index 1ef1662..4dd998c 100644 --- a/src/environments/environment.development.ts +++ b/src/environments/environment.development.ts @@ -1,3 +1,3 @@ export const environment = { - POCKETBASE: 'http://pocketbase-yocs0oko0o8cws44kw8gk8g8.192.168.178.105.sslip.io/' + POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de' }; diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 1ef1662..4dd998c 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -1,3 +1,3 @@ export const environment = { - POCKETBASE: 'http://pocketbase-yocs0oko0o8cws44kw8gk8g8.192.168.178.105.sslip.io/' + POCKETBASE: 'https://jklink-pocketbase-test.intern.kjan.de' }; From 50fa637a3532bfbdfc79b7385949d809f8d4cc4e Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 11:12:34 +0100 Subject: [PATCH 6/8] refactor(dashboard): rename column and update button label --- src/app/dashboard/dashboard.component.html | 9 +++++---- src/app/dashboard/dashboard.component.ts | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index 6ab4fff..e47f465 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -15,7 +15,6 @@ ID {{element.id}} - @@ -32,9 +31,11 @@ - - Short Url - ndy + + Short link + + + diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index dbb31e0..20fce72 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -16,7 +16,7 @@ import { MatButtonModule } from '@angular/material/button'; }) export class DashboardComponent { public links: Link[] = []; - displayedColumns: string[] = ['id', 'name', 'link', 'symbol', 'actions']; + displayedColumns: string[] = ['id', 'name', 'link', 'shortLink', 'actions']; constructor(private linkService: LinkService, private router: Router) { }; From 8302387aa73dfa0411f81c26dcc1fd0467209f87 Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 11:19:48 +0100 Subject: [PATCH 7/8] feat(dashboard): add links to element IDs in dashboard table --- src/app/dashboard/dashboard.component.html | 4 +++- src/app/dashboard/dashboard.component.ts | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/app/dashboard/dashboard.component.html b/src/app/dashboard/dashboard.component.html index e47f465..d797e70 100644 --- a/src/app/dashboard/dashboard.component.html +++ b/src/app/dashboard/dashboard.component.html @@ -14,7 +14,9 @@ ID - {{element.id}} + + {{element.id}} + diff --git a/src/app/dashboard/dashboard.component.ts b/src/app/dashboard/dashboard.component.ts index 20fce72..428b89f 100644 --- a/src/app/dashboard/dashboard.component.ts +++ b/src/app/dashboard/dashboard.component.ts @@ -21,7 +21,11 @@ export class DashboardComponent { constructor(private linkService: LinkService, private router: Router) { }; copyLink(id: string) { - navigator.clipboard.writeText(window.location.hostname + '/' + id); + navigator.clipboard.writeText(this.getShortLink(id)); + } + + getShortLink(id: string): string { + return window.location.hostname + '/' + id; } ngOnInit(): void { From 74d6cd832964e0360c61a1d2c55ce182b703193e Mon Sep 17 00:00:00 2001 From: Jan Klattenhoff Date: Tue, 21 Jan 2025 11:25:23 +0100 Subject: [PATCH 8/8] build: add release workflow configuration file --- .gitea/workflows/release.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .gitea/workflows/release.yml diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..f717de7 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,32 @@ +name: Release +on: + push: + branches: + - prod + +env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + +permissions: + contents: read # for checkout + +concurrency: + group: ${{ github.ref }} # Ensure each branch has its own group + cancel-in-progress: false # Prevent new runs from canceling in-progress runs + +jobs: + release: + name: Release + runs-on: ubuntu-latest + permissions: + contents: write # to be able to publish a GitHub release + issues: write # to be able to comment on released issues + pull-requests: write # to be able to comment on released pull requests + id-token: write # to enable use of OIDC for npm provenance + steps: + - name: Create Release + uses: https://git.kjan.de/actions/semantic-release@main + with: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} +