+ }
diff --git a/src/app/components/items/level-statistics.component.ts b/src/app/components/items/level-statistics.component.ts
index ce015014..cee7ccb1 100644
--- a/src/app/components/items/level-statistics.component.ts
+++ b/src/app/components/items/level-statistics.component.ts
@@ -2,24 +2,32 @@ import {Component, Input} from '@angular/core';
import {Level} from "../../api/types/levels/level";
import {faHeart, faPlay, faStar, faThumbsDown, faThumbsUp} from "@fortawesome/free-solid-svg-icons";
import {StatisticComponent} from "../ui/info/statistic.component";
+import { getFormattedDateTime, getShortDateTime } from '../../helpers/date-time';
+import { LevelTeamPickStatusComponent } from "./level-team-pick-status.component";
@Component({
selector: 'app-level-statistics',
imports: [
- StatisticComponent
- ],
+ StatisticComponent,
+ LevelTeamPickStatusComponent
+],
template: `
-
+
+ @if (level.teamPicked) {
+
+ }
`
})
export class LevelStatisticsComponent {
@Input({required: true}) level: Level = undefined!;
+ @Input() short: boolean = false;
+
protected readonly faThumbsUp = faThumbsUp;
protected readonly faThumbsDown = faThumbsDown;
protected readonly faHeart = faHeart;
diff --git a/src/app/components/items/level-team-pick-status.component.ts b/src/app/components/items/level-team-pick-status.component.ts
new file mode 100644
index 00000000..7ddd8358
--- /dev/null
+++ b/src/app/components/items/level-team-pick-status.component.ts
@@ -0,0 +1,43 @@
+import {Component, Input} from '@angular/core';
+import {Level} from "../../api/types/levels/level";
+import {faCircleCheck} from "@fortawesome/free-solid-svg-icons";
+import { FaIconComponent } from "@fortawesome/angular-fontawesome";
+import { TooltipComponent } from "../ui/text/tooltip.component";
+import { getFormattedDateTime, getShortDateTime } from '../../helpers/date-time';
+
+@Component({
+ selector: 'app-level-team-pick-status',
+ imports: [
+ FaIconComponent,
+ TooltipComponent
+],
+ template: `
+
+
+
+
+ @if (!short) {
+
team picked {{this.shortTime}}
+ }
+
+
+
+ `
+})
+export class LevelTeamPickStatusComponent {
+ @Input({required: true}) level: Level = undefined!;
+ @Input() short: boolean = false;
+
+ protected formattedTime: string = "unknown";
+ protected shortTime: string = "";
+
+ ngOnInit() {
+ if (this.level.dateTeamPicked != null) {
+ this.level.dateTeamPicked = new Date(this.level.dateTeamPicked);
+ this.shortTime = getShortDateTime(this.level.dateTeamPicked);
+ this.formattedTime = getFormattedDateTime(this.level.dateTeamPicked);
+ }
+ }
+
+ protected readonly faCircleCheck = faCircleCheck;
+}
diff --git a/src/app/components/ui/info/date.component.ts b/src/app/components/ui/info/date.component.ts
index 94c20148..6dcfcbb9 100644
--- a/src/app/components/ui/info/date.component.ts
+++ b/src/app/components/ui/info/date.component.ts
@@ -11,6 +11,7 @@ import {
} from '@angular/core';
import {TooltipComponent} from "../text/tooltip.component";
import {isPlatformBrowser} from "@angular/common";
+import { getFormattedDateTime, getShortDateTime } from '../../../helpers/date-time';
@Component({
selector: 'app-date',
@@ -44,8 +45,6 @@ export class DateComponent implements OnInit, OnDestroy {
return isPlatformBrowser(this.platformId);
}
- protected recentText = "just now";
-
// this setter is actually required to be here; this is not a hold-over from the old site
// for some reason, javascript's date parser doesn't create a full Date object.
// so we need to do this horse-shit.
@@ -55,36 +54,11 @@ export class DateComponent implements OnInit, OnDestroy {
}
get moment(): string {
- const now = new Date();
- const totalSeconds = Math.floor((now.getTime() - this._date.getTime()) / 1000);
-
- const intervals: { [key: string]: number } = {
- year: 31536000,
- month: 2592000,
- week: 604800,
- day: 86400,
- hour: 3600,
- minute: 60,
- second: 1,
- };
-
- if (totalSeconds < 20)
- return this.recentText;
-
- for (const interval in intervals) {
- const time = Math.floor(totalSeconds / intervals[interval]);
- if (time > 1) {
- return `${time} ${interval}s ago`;
- } else if (time == 1) {
- return `a${interval == "hour" ? 'n' : ''} ${interval} ago`;
- }
- }
-
- return this.recentText;
+ return getShortDateTime(this._date);
}
get formattedDate(): string {
- return `${this._date.toLocaleDateString()} @ ${this._date.toLocaleTimeString()}`;
+ return getFormattedDateTime(this._date);
}
ngOnDestroy() {
diff --git a/src/app/components/ui/info/larger-label.component.ts b/src/app/components/ui/info/larger-label.component.ts
new file mode 100644
index 00000000..24e3818c
--- /dev/null
+++ b/src/app/components/ui/info/larger-label.component.ts
@@ -0,0 +1,17 @@
+import {Component, Input} from '@angular/core';
+import {NgClass} from "@angular/common";
+
+@Component({
+ selector: 'app-larger-label',
+ imports: [
+ NgClass
+ ],
+ template: `
+
+
+
+ `
+})
+export class LargerLabelComponent {
+ @Input() primary: boolean = false;
+}
diff --git a/src/app/components/ui/layouts/fancy-header-buttons.component.ts b/src/app/components/ui/layouts/fancy-header-buttons.component.ts
index e6266145..4c4ce341 100644
--- a/src/app/components/ui/layouts/fancy-header-buttons.component.ts
+++ b/src/app/components/ui/layouts/fancy-header-buttons.component.ts
@@ -19,7 +19,7 @@ import {faEllipsisV} from "@fortawesome/free-solid-svg-icons";
-
+
-
+
+
+
`
})
diff --git a/src/app/components/ui/text/links/original-publisher-router-link.component.ts b/src/app/components/ui/text/links/original-publisher-router-link.component.ts
new file mode 100644
index 00000000..bab91d7a
--- /dev/null
+++ b/src/app/components/ui/text/links/original-publisher-router-link.component.ts
@@ -0,0 +1,21 @@
+import {Component, Input} from '@angular/core';
+import {RouterLink} from "@angular/router";
+import { Level } from '../../../../api/types/levels/level';
+
+@Component({
+ selector: 'app-original-publisher-router-link',
+ imports: [
+ RouterLink
+ ],
+ template: `
+
+ {{level.originalPublisher ?? this.unknownName}}
+
+
+ `
+})
+export class OriginalPublisherRouterLink {
+ @Input({required: true}) public level: Level = undefined!;
+ protected unknownName: string = "Unknown";
+}
diff --git a/src/app/helpers/date-time.ts b/src/app/helpers/date-time.ts
new file mode 100644
index 00000000..b709ed85
--- /dev/null
+++ b/src/app/helpers/date-time.ts
@@ -0,0 +1,33 @@
+export function getFormattedDateTime(date: Date) {
+ return `${date.toLocaleDateString()} @ ${date.toLocaleTimeString()}`;
+}
+
+export function getShortDateTime(date: Date) {
+ const recentText = "just now";
+ const now = new Date();
+ const totalSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
+
+ if (totalSeconds < 20)
+ return recentText;
+
+ for (const interval in timeIntervals) {
+ const time = Math.floor(totalSeconds / timeIntervals[interval]);
+ if (time > 1) {
+ return `${time} ${interval}s ago`;
+ } else if (time == 1) {
+ return `a${interval == "hour" ? 'n' : ''} ${interval} ago`;
+ }
+ }
+
+ return recentText;
+}
+
+export const timeIntervals: { [key: string]: number } = {
+ year: 31536000,
+ month: 2592000,
+ week: 604800,
+ day: 86400,
+ hour: 3600,
+ minute: 60,
+ second: 1,
+};
\ No newline at end of file
diff --git a/src/app/pages/level/level.component.html b/src/app/pages/level/level.component.html
index 44cf539f..cc3fdc7f 100644
--- a/src/app/pages/level/level.component.html
+++ b/src/app/pages/level/level.component.html
@@ -2,18 +2,55 @@
-
- by
-
+ @if (level.isReUpload) {
+
+
originally by ,
+
uploaded by
+
+ }
+ @else {
+
+ by
+
+ }
-
- Published for {{level.gameVersion | game: isMobile}}
-
- @if(level.updateDate) {,
- updated
-
+
+
+
+
+ {{level.gameVersion | game: isMobile}}
+
+
+ @if (level.isModded) {
+
+ Modded
+
}
+
+ @if (!isMobile) {
+
+
+
+ @if(level.updateDate != level.publishDate) {
+
+ }
+
+ }
+ @else {
+
+ published
+
+ @if(level.updateDate != level.publishDate) {,
+ updated
+ }
+
+ }
+
@if(relations && !isMobile) {
diff --git a/src/app/pages/level/level.component.ts b/src/app/pages/level/level.component.ts
index e7272f92..619bff6d 100644
--- a/src/app/pages/level/level.component.ts
+++ b/src/app/pages/level/level.component.ts
@@ -3,7 +3,7 @@ import {Level} from "../../api/types/levels/level";
import {ClientService} from "../../api/client.service";
import {ActivatedRoute, RouterLink} from "@angular/router";
import {SlugPipe} from "../../pipes/slug.pipe";
-import { AsyncPipe, isPlatformBrowser, } from "@angular/common";
+import { AsyncPipe, isPlatformBrowser } from "@angular/common";
import {LevelStatisticsComponent} from "../../components/items/level-statistics.component";
import {DefaultPipe} from "../../pipes/default.pipe";
import {LevelAvatarComponent} from "../../components/ui/photos/level-avatar.component";
@@ -26,6 +26,9 @@ import {AuthenticationService} from "../../api/authentication.service";
import { ExtendedUser } from '../../api/types/users/extended-user';
import { FancyHeaderLevelButtonsComponent } from '../../components/ui/layouts/fancy-header-level-buttons.component';
import { LevelRelations } from '../../api/types/levels/level-relations';
+import { OriginalPublisherRouterLink } from "../../components/ui/text/links/original-publisher-router-link.component";
+import { LargerLabelComponent } from "../../components/ui/info/larger-label.component";
+import { TooltipComponent } from "../../components/ui/text/tooltip.component";
@Component({
@@ -47,7 +50,10 @@ import { LevelRelations } from '../../api/types/levels/level-relations';
PaneTitleComponent,
EventPageComponent,
RouterLink,
- SlugPipe
+ SlugPipe,
+ OriginalPublisherRouterLink,
+ LargerLabelComponent,
+ TooltipComponent
],
providers: [
SlugPipe