Add created/updated at

This commit is contained in:
2026-01-07 12:34:31 +01:00
parent bce24514dc
commit 233a745bd5
7 changed files with 94 additions and 7 deletions

View File

@@ -29,9 +29,12 @@ public class Asset {
@Column(columnDefinition = "TEXT", nullable = false) @Column(columnDefinition = "TEXT", nullable = false)
private String preview; private String preview;
@Column(nullable = false) @Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt; private Instant createdAt;
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
private double x; private double x;
private double y; private double y;
private double width; private double width;
@@ -66,17 +69,20 @@ public class Asset {
this.zIndex = 1; this.zIndex = 1;
this.hidden = true; this.hidden = true;
this.createdAt = Instant.now(); this.createdAt = Instant.now();
this.updatedAt = this.createdAt;
} }
@PrePersist @PrePersist
@PreUpdate @PreUpdate
public void prepare() { public void prepare() {
Instant now = Instant.now();
if (this.id == null) { if (this.id == null) {
this.id = UUID.randomUUID().toString(); this.id = UUID.randomUUID().toString();
} }
if (this.createdAt == null) { if (this.createdAt == null) {
this.createdAt = Instant.now(); this.createdAt = now;
} }
this.updatedAt = now;
this.broadcaster = normalize(broadcaster); this.broadcaster = normalize(broadcaster);
if (this.name == null || this.name.isBlank()) { if (this.name == null || this.name.isBlank()) {
this.name = this.id; this.name = this.id;
@@ -235,6 +241,14 @@ public class Asset {
this.createdAt = createdAt; this.createdAt = createdAt;
} }
public Instant getUpdatedAt() {
return updatedAt;
}
public void setUpdatedAt(Instant updatedAt) {
this.updatedAt = updatedAt;
}
public Integer getZIndex() { public Integer getZIndex() {
return zIndex == null ? 1 : Math.max(1, zIndex); return zIndex == null ? 1 : Math.max(1, zIndex);
} }

View File

@@ -25,7 +25,8 @@ public record AssetView(
Double audioVolume, Double audioVolume,
boolean hidden, boolean hidden,
boolean hasPreview, boolean hasPreview,
Instant createdAt Instant createdAt,
Instant updatedAt
) { ) {
public static AssetView from(String broadcaster, Asset asset) { public static AssetView from(String broadcaster, Asset asset) {
return new AssetView( return new AssetView(
@@ -53,7 +54,8 @@ public record AssetView(
asset.getAudioVolume(), asset.getAudioVolume(),
asset.isHidden(), asset.isHidden(),
asset.getPreview() != null && !asset.getPreview().isBlank(), asset.getPreview() != null && !asset.getPreview().isBlank(),
asset.getCreatedAt() asset.getCreatedAt(),
asset.getUpdatedAt()
); );
} }
} }

View File

@@ -12,6 +12,7 @@ import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.time.Instant;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -32,6 +33,12 @@ public class Channel {
private double canvasHeight = 1080; private double canvasHeight = 1080;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
public Channel() {} public Channel() {}
public Channel(String broadcaster) { public Channel(String broadcaster) {
@@ -75,6 +82,11 @@ public class Channel {
@PrePersist @PrePersist
@PreUpdate @PreUpdate
public void normalizeFields() { public void normalizeFields() {
Instant now = Instant.now();
if (createdAt == null) {
createdAt = now;
}
updatedAt = now;
this.broadcaster = normalize(broadcaster); this.broadcaster = normalize(broadcaster);
this.admins = admins.stream().map(Channel::normalize).collect(Collectors.toSet()); this.admins = admins.stream().map(Channel::normalize).collect(Collectors.toSet());
if (canvasWidth <= 0) { if (canvasWidth <= 0) {
@@ -85,6 +97,14 @@ public class Channel {
} }
} }
public Instant getCreatedAt() {
return createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
private static String normalize(String value) { private static String normalize(String value) {
return value == null ? null : value.toLowerCase(Locale.ROOT); return value == null ? null : value.toLowerCase(Locale.ROOT);
} }

View File

@@ -3,7 +3,10 @@ package dev.kruhlmann.imgfloat.model;
import jakarta.persistence.Column; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import java.time.Instant;
@Entity @Entity
@Table(name = "settings") @Table(name = "settings")
@@ -37,6 +40,12 @@ public class Settings {
@Column(nullable = false) @Column(nullable = false)
private int canvasFramesPerSecond; private int canvasFramesPerSecond;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
protected Settings() {} protected Settings() {}
public static Settings defaults() { public static Settings defaults() {
@@ -123,4 +132,26 @@ public class Settings {
public void setCanvasFramesPerSecond(int canvasFramesPerSecond) { public void setCanvasFramesPerSecond(int canvasFramesPerSecond) {
this.canvasFramesPerSecond = canvasFramesPerSecond; this.canvasFramesPerSecond = canvasFramesPerSecond;
} }
@PrePersist
public void initializeTimestamps() {
Instant now = Instant.now();
if (createdAt == null) {
createdAt = now;
}
updatedAt = now;
}
@PreUpdate
public void updateTimestamp() {
updatedAt = Instant.now();
}
public Instant getCreatedAt() {
return createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
} }

View File

@@ -7,6 +7,7 @@ import jakarta.persistence.PrePersist;
import jakarta.persistence.PreUpdate; import jakarta.persistence.PreUpdate;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint; import jakarta.persistence.UniqueConstraint;
import java.time.Instant;
import java.util.Locale; import java.util.Locale;
import java.util.UUID; import java.util.UUID;
@@ -20,6 +21,12 @@ public class SystemAdministrator {
@Column(name = "twitch_username", nullable = false) @Column(name = "twitch_username", nullable = false)
private String twitchUsername; private String twitchUsername;
@Column(name = "created_at", nullable = false, updatable = false)
private Instant createdAt;
@Column(name = "updated_at", nullable = false)
private Instant updatedAt;
public SystemAdministrator() {} public SystemAdministrator() {}
public SystemAdministrator(String twitchUsername) { public SystemAdministrator(String twitchUsername) {
@@ -29,9 +36,14 @@ public class SystemAdministrator {
@PrePersist @PrePersist
@PreUpdate @PreUpdate
public void prepare() { public void prepare() {
Instant now = Instant.now();
if (this.id == null) { if (this.id == null) {
this.id = UUID.randomUUID().toString(); this.id = UUID.randomUUID().toString();
} }
if (this.createdAt == null) {
this.createdAt = now;
}
this.updatedAt = now;
twitchUsername = twitchUsername.toLowerCase(Locale.ROOT); twitchUsername = twitchUsername.toLowerCase(Locale.ROOT);
} }
@@ -46,4 +58,12 @@ public class SystemAdministrator {
public void setTwitchUsername(String twitchUsername) { public void setTwitchUsername(String twitchUsername) {
this.twitchUsername = twitchUsername; this.twitchUsername = twitchUsername;
} }
public Instant getCreatedAt() {
return createdAt;
}
public Instant getUpdatedAt() {
return updatedAt;
}
} }

View File

@@ -85,7 +85,7 @@ public class ChannelDirectoryService {
Channel channel = getOrCreateChannel(broadcaster); Channel channel = getOrCreateChannel(broadcaster);
boolean added = channel.addAdmin(username); boolean added = channel.addAdmin(username);
if (added) { if (added) {
channelRepository.save(channel); channelRepository.saveAndFlush(channel);
messagingTemplate.convertAndSend(topicFor(broadcaster), "Admin added: " + username); messagingTemplate.convertAndSend(topicFor(broadcaster), "Admin added: " + username);
} }
return added; return added;
@@ -95,7 +95,7 @@ public class ChannelDirectoryService {
Channel channel = getOrCreateChannel(broadcaster); Channel channel = getOrCreateChannel(broadcaster);
boolean removed = channel.removeAdmin(username); boolean removed = channel.removeAdmin(username);
if (removed) { if (removed) {
channelRepository.save(channel); channelRepository.saveAndFlush(channel);
messagingTemplate.convertAndSend(topicFor(broadcaster), "Admin removed: " + username); messagingTemplate.convertAndSend(topicFor(broadcaster), "Admin removed: " + username);
} }
return removed; return removed;

View File

@@ -85,7 +85,7 @@ function renderSuggestedAdmins(list) {
const addBtn = document.createElement("button"); const addBtn = document.createElement("button");
addBtn.type = "button"; addBtn.type = "button";
addBtn.className = "ghost"; addBtn.className = "ghost";
addBtn.textContent = "Add as admin"; addBtn.textContent = "Add channel admin";
addBtn.addEventListener("click", () => addAdmin(admin.login)); addBtn.addEventListener("click", () => addAdmin(admin.login));
actions.appendChild(addBtn); actions.appendChild(addBtn);