diff --git a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py index 87cd7aeb..457c9fc1 100644 --- a/kdb-bot/src/bot_data/model/user_joined_voice_channel.py +++ b/kdb-bot/src/bot_data/model/user_joined_voice_channel.py @@ -45,6 +45,10 @@ class UserJoinedVoiceChannel(TableABC): def user(self) -> User: return self._user + @property + def time(self) -> float: + return round((self.leaved_on - self.joined_on).total_seconds() / 3600, 2) + @property def joined_on(self) -> datetime: return self._joined_on diff --git a/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql index d49f8c9e..7fb983b5 100644 --- a/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql +++ b/kdb-bot/src/bot_graphql/model/userJoinedVoiceChannel.gql @@ -3,6 +3,7 @@ type UserJoinedVoiceChannel implements TableQuery { channelId: String channelName: String user: User + time: Float joinedOn: String leavedOn: String diff --git a/kdb-bot/src/bot_graphql/mutations/user_mutation.py b/kdb-bot/src/bot_graphql/mutations/user_mutation.py index 4a31a615..9356965b 100644 --- a/kdb-bot/src/bot_graphql/mutations/user_mutation.py +++ b/kdb-bot/src/bot_graphql/mutations/user_mutation.py @@ -37,12 +37,12 @@ class UserMutation(QueryABC): user = self._users.get_user_by_id(input["id"]) self._can_user_mutate_data(user.server, UserRoleEnum.moderator) - user.xp = input["xp"] if "xp" in input else user.xp - if "levelId" in input: level = self._levels.get_level_by_id(input["levelId"]) user.xp = level.min_xp + user.xp = input["xp"] if "xp" in input else user.xp + self._users.update_user(user) self._db.save_changes() self._level_service.set_level(user) diff --git a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py index 333fbfa5..2640307d 100644 --- a/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py +++ b/kdb-bot/src/bot_graphql/queries/user_joined_voice_channel_query.py @@ -14,6 +14,7 @@ class UserJoinedVoiceChannelQuery(DataQueryABC): self.set_field("channelId", self.resolve_channel_id) self.set_field("channelName", self.resolve_channel_name) self.set_field("user", self.resolve_user) + self.set_field("time", self.resolve_time) self.set_field("joinedOn", self.resolve_joined_on) self.set_field("leavedOn", self.resolve_leaved_on) @@ -33,6 +34,10 @@ class UserJoinedVoiceChannelQuery(DataQueryABC): def resolve_user(x: UserJoinedVoiceChannel, *_): return x.user + @staticmethod + def resolve_time(x: UserJoinedVoiceChannel, *_): + return x.time + @staticmethod def resolve_joined_on(x: UserJoinedVoiceChannel, *_): return x.joined_on diff --git a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py index 8ff32383..c2a25a32 100644 --- a/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py +++ b/kdb-bot/src/modules/base/events/base_on_voice_state_update_event.py @@ -72,10 +72,8 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): join = self._user_joins_vc.get_active_user_joined_voice_channel_by_user_id(user.id) join.leaved_on = datetime.now() - # ontime as hours - ontime = round((join.leaved_on - join.joined_on).total_seconds() / 3600, 2) old_xp = user.xp - user.xp += round(ontime * settings.xp_per_ontime_hour) + user.xp += round(join.time * settings.xp_per_ontime_hour) self._user_joins_vc.update_user_joined_voice_channel(join) self._users.update_user(user) @@ -83,7 +81,7 @@ class BaseOnVoiceStateUpdateEvent(OnVoiceStateUpdateABC): self._logger.debug( __name__, - f"User {user} leaved_on {join.leaved_on}. Ontime: {ontime}h | xp: from {old_xp} to {user.xp}", + f"User {user} leaved_on {join.leaved_on}. Ontime: {join.time}h | xp: from {old_xp} to {user.xp}", ) except Exception as e: self._logger.error(__name__, f"Ontime validation failed", e) diff --git a/kdb-web/package.json b/kdb-web/package.json index 498f6a0f..a3642281 100644 --- a/kdb-web/package.json +++ b/kdb-web/package.json @@ -50,4 +50,4 @@ "tslib": "^2.4.1", "typescript": "~4.9.5" } -} +} \ No newline at end of file diff --git a/kdb-web/src/app/models/data/user.model.ts b/kdb-web/src/app/models/data/user.model.ts index 494ec567..385e6c6c 100644 --- a/kdb-web/src/app/models/data/user.model.ts +++ b/kdb-web/src/app/models/data/user.model.ts @@ -1,6 +1,8 @@ import { Data } from "./data.model"; import { Level, LevelFilter } from "./level.model"; import { Server, ServerFilter } from "./server.model"; +import { UserJoinedServer } from "./user_joined_server.model"; +import { UserJoinedVoiceChannel } from "./user_joined_voice_channel.model"; export interface User extends Data { id?: number; @@ -14,10 +16,10 @@ export interface User extends Data { leftServer?: boolean; joinedServerCount?: number; - joinedServers?: []; + joinedServers?: UserJoinedServer[]; joinedVoiceChannelCount?: number; - joinedVoiceChannels?: []; + joinedVoiceChannels?: UserJoinedVoiceChannel[]; userJoinedGameServerCount?: number; userJoinedGameServers?: []; diff --git a/kdb-web/src/app/models/data/user_joined_server.model.ts b/kdb-web/src/app/models/data/user_joined_server.model.ts new file mode 100644 index 00000000..7828dece --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_server.model.ts @@ -0,0 +1,9 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedServer extends Data { + id: number; + user: User; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts new file mode 100644 index 00000000..9c49ff2e --- /dev/null +++ b/kdb-web/src/app/models/data/user_joined_voice_channel.model.ts @@ -0,0 +1,12 @@ +import { Data } from "./data.model"; +import { User } from "./user.model"; + +export interface UserJoinedVoiceChannel extends Data { + id: number; + channelId: string; + channelName: string; + user: User; + time: number; + joinedOn: string; + leavedOn: string; +} diff --git a/kdb-web/src/app/models/graphql/queries.model.ts b/kdb-web/src/app/models/graphql/queries.model.ts index 4fe54101..44756d56 100644 --- a/kdb-web/src/app/models/graphql/queries.model.ts +++ b/kdb-web/src/app/models/graphql/queries.model.ts @@ -78,4 +78,53 @@ export class Queries { } } `; + + static singleUserQuery = ` + query singleUserQuery($filter: UserFilter) { + users(filter: $filter) { + id + discordId + name + xp + ontime + level { + id + name + } + leftServer + server { + id + name + } + + joinedServerCount + joinedServers { + id + joinedOn + leavedOn + } + + joinedVoiceChannelCount + joinedVoiceChannels { + id + channelId + channelName + time + joinedOn + leavedOn + } + + userJoinedGameServerCount + userJoinedGameServers { + id + gameServer + joinedOn + leavedOn + } + + createdAt + modifiedAt + } + } + `; } diff --git a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html index 29e5916b..bcb77b39 100644 --- a/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html +++ b/kdb-web/src/app/modules/admin/auth-users/components/auth-user/auth-user.component.html @@ -70,6 +70,18 @@ + +
+
{{'common.created_at' | translate}}
+
+ + + +
+
{{'common.modified_at' | translate}}
+
+ +
{{'admin.auth_users.headers.actions' | translate}}
@@ -177,7 +189,7 @@ - {{user.createdAt}} + {{user.createdAt | date:'dd.MM.yy HH:mm'}} {{user.createdAt | date:'dd.MM.yy HH:mm'}} @@ -187,7 +199,7 @@ - {{user.modifiedAt}} + {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} {{user.modifiedAt | date:'dd.MM.yy HH:mm'}} diff --git a/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts b/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts index fc2d54cf..acfbc034 100644 --- a/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts +++ b/kdb-web/src/app/modules/shared/pipes/bool.pipe.ts @@ -10,11 +10,15 @@ export class BoolPipe implements PipeTransform { private translate: TranslateService ) {} - transform(value: boolean): string { - if (value === true) { + transform(value?: boolean): string { + if (value === undefined || value === null) { + return ''; + } + + if (value) { return this.translate.instant('common.bool_as_string.true'); } - + return this.translate.instant('common.bool_as_string.false'); } diff --git a/kdb-web/src/app/modules/view/server/members/members.component.ts b/kdb-web/src/app/modules/view/server/members/members.component.ts index 112adf62..99f4dbef 100644 --- a/kdb-web/src/app/modules/view/server/members/members.component.ts +++ b/kdb-web/src/app/modules/view/server/members/members.component.ts @@ -10,7 +10,7 @@ import { LazyLoadEvent, MenuItem } from "primeng/api"; import { Table } from "primeng/table"; import { User, UserFilter } from "../../../../models/data/user.model"; import { Queries } from "../../../../models/graphql/queries.model"; -import { LevelListQuery, Query, UserListQuery } from "../../../../models/graphql/query.model"; +import { LevelListQuery, UserListQuery } from "../../../../models/graphql/query.model"; import { DataService } from "../../../../services/data/data.service"; import { Page } from "../../../../models/graphql/filter/page.model"; import { Sort, SortDirection } from "../../../../models/graphql/filter/sort.model"; @@ -18,8 +18,7 @@ import { SidebarService } from "../../../../services/sidebar/sidebar.service"; import { Mutations } from "../../../../models/graphql/mutations.model"; import { throwError } from "rxjs"; import { UpdateUserMutationResult } from "../../../../models/graphql/result.model"; -import { Server } from "../../../../models/data/server.model"; -import { ActivatedRoute, Router } from "@angular/router"; +import { ActivatedRoute } from "@angular/router"; @Component({ selector: "app-members", @@ -88,30 +87,11 @@ export class MembersComponent { private data: DataService, private sidebar: SidebarService, private route: ActivatedRoute, - private router: Router, ) { } ngOnInit(): void { - - this.spinner.showSpinner(); - if (!this.route.snapshot.params["serverId"]) { - this.spinner.hideSpinner(); - this.router.navigate(['/dashboard']); - return; - } - - this.data.query(Queries.serversQuery, { - filter: { id: this.route.snapshot.params["serverId"] } - }, - function(data: Query) { - return data.servers.length > 0 ? data.servers[0] : null; - } - ).subscribe(server => { - this.sidebar.setServer(server); - this.spinner.hideSpinner(); - }); - + this.data.getServerFromRoute(this.route); this.spinner.showSpinner(); this.data.query(Queries.levelQuery, { diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.html b/kdb-web/src/app/modules/view/server/profile/profile.component.html index 9df0576d..2dda2775 100644 --- a/kdb-web/src/app/modules/view/server/profile/profile.component.html +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.html @@ -1 +1,115 @@ -

profile works!

+

+ {{'view.server.profile.header' | translate}} +

+
+
+

+ {{user.name}} +

+
+ +
+
+
+
{{'view.server.profile.id' | translate}}:
+
{{user.id}}
+
+
+
{{'view.server.profile.discord_id' | translate}}:
+
{{user.discordId}}
+
+
+ +
+
+
{{'view.server.profile.name' | translate}}:
+
{{user.name}}
+
+
+ +
+
+
{{'view.server.profile.xp' | translate}}:
+
{{user.xp}}
+
+
+ +
+
+
{{'view.server.profile.ontime' | translate}}:
+
{{user.ontime}}
+
+
+ +
+
+
{{'view.server.profile.level' | translate}}:
+
{{user.level?.name}}
+
+
+ +
+
+
{{'view.server.profile.left_server' | translate}}:
+
{{user.leftServer | bool}}
+
+
+ +
+
+
{{'common.created_at' | translate}}:
+
{{user.createdAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+
+
{{'common.modified_at' | translate}}:
+
{{user.modifiedAt | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+ +
+
+

{{'view.server.profile.joined_voice_channel.header' | translate}}

+
+ +
+
+
+
{{'view.server.profile.joined_voice_channel.time' | translate}}:
+
{{join.time}} {{'general.hours' | translate}}
+
+ +
+
{{'view.server.profile.joined_voice_channel.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'view.server.profile.joined_voice_channel.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+ +
+
+

{{'view.server.profile.joined_server.header' | translate}}

+
+ +
+
+
+
{{'view.server.profile.joined_server.joined_at' | translate}}:
+
{{join.joinedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+ +
+
{{'view.server.profile.joined_server.leaved_at' | translate}}:
+
{{join.leavedOn | date:'dd.MM.yyyy HH:mm:ss'}}
+
+
+
+
+
diff --git a/kdb-web/src/app/modules/view/server/profile/profile.component.ts b/kdb-web/src/app/modules/view/server/profile/profile.component.ts index fe55ba14..23f62959 100644 --- a/kdb-web/src/app/modules/view/server/profile/profile.component.ts +++ b/kdb-web/src/app/modules/view/server/profile/profile.component.ts @@ -1,11 +1,10 @@ import { Component, OnInit } from "@angular/core"; import { ActivatedRoute, Router } from "@angular/router"; -import { Server } from "../../../../models/data/server.model"; import { Queries } from "../../../../models/graphql/queries.model"; -import { Query } from "../../../../models/graphql/query.model"; +import { UserListQuery } from "../../../../models/graphql/query.model"; import { SpinnerService } from "../../../../services/spinner/spinner.service"; import { DataService } from "../../../../services/data/data.service"; -import { SidebarService } from "../../../../services/sidebar/sidebar.service"; +import { User } from "../../../../models/data/user.model"; @Component({ selector: "app-profile", @@ -14,31 +13,38 @@ import { SidebarService } from "../../../../services/sidebar/sidebar.service"; }) export class ProfileComponent implements OnInit { + user!: User; + constructor( private route: ActivatedRoute, private router: Router, private spinner: SpinnerService, - private data: DataService, - private sidebar: SidebarService + private data: DataService ) { } ngOnInit() { + this.data.getServerFromRoute(this.route); + this.spinner.showSpinner(); - if (!this.route.snapshot.params["serverId"]) { + if (!this.route.snapshot.params["memberId"]) { this.spinner.hideSpinner(); - this.router.navigate(['/dashboard']); + this.router.navigate(["/dashboard"]); return; } - this.data.query(Queries.serversQuery, { - filter: { id: this.route.snapshot.params["serverId"] } + this.data.query(Queries.singleUserQuery, { + filter: { + id: this.route.snapshot.params["memberId"], + leftServer: false + } }, - function(data: Query) { - return data.servers.length > 0 ? data.servers[0] : null; + function(data: UserListQuery) { + return data.users.length > 0 ? data.users[0] : null; } - ).subscribe(server => { - this.sidebar.setServer(server); + ).subscribe(user => { + this.user = user; + console.log(this.user); this.spinner.hideSpinner(); }); } diff --git a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts index d0e15616..651b8d56 100644 --- a/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts +++ b/kdb-web/src/app/modules/view/server/server-dashboard/server-dashboard.component.ts @@ -3,8 +3,6 @@ import { ActivatedRoute, Router } from "@angular/router"; import { Server } from "src/app/models/data/server.model"; import { DataService } from "src/app/services/data/data.service"; import { SpinnerService } from "src/app/services/spinner/spinner.service"; -import { Queries } from "../../../../models/graphql/queries.model"; -import { Query } from "../../../../models/graphql/query.model"; import { SidebarService } from "../../../../services/sidebar/sidebar.service"; @Component({ @@ -27,23 +25,13 @@ export class ServerDashboardComponent implements OnInit { } ngOnInit(): void { - this.spinner.showSpinner(); - if (!this.route.snapshot.params["serverId"]) { - this.spinner.hideSpinner(); - this.router.navigate(['/dashboard']); - return; - } + this.data.getServerFromRoute(this.route); - this.data.query(Queries.serversQuery, { - filter: { id: this.route.snapshot.params["serverId"] } - }, - function(data: Query) { - return data.servers.length > 0 ? data.servers[0] : null; + this.sidebar.server$.subscribe(server => { + if (!server) { + return; } - ).subscribe(server => { this.server = server; - this.sidebar.setServer(server); - this.spinner.hideSpinner(); }); } diff --git a/kdb-web/src/app/modules/view/server/server-routing.module.ts b/kdb-web/src/app/modules/view/server/server-routing.module.ts index 0b732e97..d4de8413 100644 --- a/kdb-web/src/app/modules/view/server/server-routing.module.ts +++ b/kdb-web/src/app/modules/view/server/server-routing.module.ts @@ -6,8 +6,8 @@ import { MembersComponent } from "./members/members.component"; const routes: Routes = [ { path: '', component: ServerDashboardComponent }, - { path: 'profile', component: ProfileComponent }, { path: 'members', component: MembersComponent }, + { path: 'members/:memberId', component: ProfileComponent }, ]; @NgModule({ diff --git a/kdb-web/src/app/services/data/data.service.ts b/kdb-web/src/app/services/data/data.service.ts index c0b516a7..79e9d401 100644 --- a/kdb-web/src/app/services/data/data.service.ts +++ b/kdb-web/src/app/services/data/data.service.ts @@ -3,6 +3,12 @@ import { Injectable } from "@angular/core"; import { SettingsService } from "../settings/settings.service"; import { map, Observable } from "rxjs"; import { Variables } from "../../models/graphql/variables.model"; +import { ActivatedRoute, Router } from "@angular/router"; +import { Server } from "../../models/data/server.model"; +import { Queries } from "../../models/graphql/queries.model"; +import { Query } from "../../models/graphql/query.model"; +import { SidebarService } from "../sidebar/sidebar.service"; +import { SpinnerService } from "../spinner/spinner.service"; @Injectable({ providedIn: "root" @@ -11,10 +17,33 @@ export class DataService { constructor( private appsettings: SettingsService, - private http: HttpClient + private http: HttpClient, + private sidebar: SidebarService, + private spinner: SpinnerService, + private router: Router, ) { } + public getServerFromRoute(route: ActivatedRoute) { + this.spinner.showSpinner(); + if (!route.snapshot.params["serverId"]) { + this.spinner.hideSpinner(); + this.router.navigate(['/dashboard']); + return; + } + + this.query(Queries.serversQuery, { + filter: { id: route.snapshot.params["serverId"] } + }, + function(data: Query) { + return data.servers.length > 0 ? data.servers[0] : null; + } + ).subscribe(server => { + this.sidebar.setServer(server); + this.spinner.hideSpinner(); + }); + } + // query(query: string, variables: object = {}): Observable { // return this.http.post(`${this.appsettings.getApiURL()}/api/graphql`, // JSON.stringify({ diff --git a/kdb-web/src/app/services/sidebar/sidebar.service.ts b/kdb-web/src/app/services/sidebar/sidebar.service.ts index bc6691c6..d3e7624c 100644 --- a/kdb-web/src/app/services/sidebar/sidebar.service.ts +++ b/kdb-web/src/app/services/sidebar/sidebar.service.ts @@ -59,20 +59,28 @@ export class SidebarService { { label: this.isSidebarOpen ? this.translateService.instant("sidebar.dashboard") : "", icon: "pi pi-th-large", routerLink: "dashboard" } ]; + let authUser = await this.authService.getLoggedInUser(); + let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server$.value?.id) ?? null; const serverMenu = { label: this.isSidebarOpen ? this.server$.value?.name : "", icon: "pi pi-server", items: [ { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.dashboard") : "", icon: "pi pi-th-large", routerLink: `server/${this.server$.value?.id}` }, - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.profile") : "", icon: "pi pi-user", routerLink: `server/${this.server$.value?.id}/profile` } + { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.profile") : "", + icon: "pi pi-user", + routerLink: `server/${this.server$.value?.id}/members/${user?.id}` + } // { label: this.isSidebarOpen ? this.translateService.instant("sidebar.members") : "", icon: "pi pi-users", routerLink: "server/members" } ] }; - if (this.server$.value) { - let authUser = await this.authService.getLoggedInUser(); - let user: UserDTO | null = authUser?.users?.find(u => u.server == this.server$.value?.id) ?? null; + if (this.server$.value) { if (user?.isAdmin) { serverMenu.items.push( - { label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.members") : "", icon: "pi pi-users", routerLink: `server/${this.server$.value?.id}/members` } + { + label: this.isSidebarOpen ? this.translateService.instant("sidebar.server.members") : "", + icon: "pi pi-users", + routerLink: `server/${this.server$.value?.id}/members` + } ); } diff --git a/kdb-web/src/assets/config.json b/kdb-web/src/assets/config.json index 7ffcfbef..7af5781a 100644 --- a/kdb-web/src/assets/config.json +++ b/kdb-web/src/assets/config.json @@ -23,4 +23,4 @@ "Name": "sh-edraft-dark-theme" } ] -} +} \ No newline at end of file diff --git a/kdb-web/src/assets/i18n/de.json b/kdb-web/src/assets/i18n/de.json index a2f6b194..c43a6173 100644 --- a/kdb-web/src/assets/i18n/de.json +++ b/kdb-web/src/assets/i18n/de.json @@ -69,9 +69,7 @@ "active": "Aktiv", "role": "Rolle", "password": "Passwort", - "actions": "Aktionen", - "created_at": "Erstellt am", - "modified_at": "Bearbeitet am" + "actions": "Aktionen" }, "no_entries_found": "Keine Einträge gefunden", "message": { @@ -162,6 +160,28 @@ "dashboard": { "header": "Server dashboard" }, + "profile": { + "header": "Dein Profil", + "id": "Id", + "discord_id": "Discord Id", + "name": "Name", + "xp": "XP", + "ontime": "Ontime", + "level": "Level", + "left_server": "Hat Server verlassen", + "joined_voice_channel": { + "header": "Sprachkanal-beitritte", + "time": "Zeit", + "joined_at": "Beigetreten am", + "leaved_at": "Verlassen am" + }, + "joined_server": { + "header": "Server-beitritte", + "time": "Zeit", + "joined_at": "Beigetreten am", + "leaved_at": "Verlassen am" + } + }, "members": { "header": "Mitglieder", "of": "von", @@ -233,9 +253,12 @@ }, "general": { "days": "Tage", - "minutes": "Minuten" + "minutes": "Minuten", + "hours": "Stunden" }, "common": { + "created_at": "Erstellt am", + "modified_at": "Bearbeitet am", "bool_as_string": { "true": "Ja", "false": "Nein" diff --git a/kdb-web/src/styles.scss b/kdb-web/src/styles.scss index ba48341f..bf4051d7 100644 --- a/kdb-web/src/styles.scss +++ b/kdb-web/src/styles.scss @@ -122,7 +122,7 @@ header { display: flex; flex-direction: row; flex: 1; - margin: 1.5px 0; + margin: 5px 0; } .content-column {