Skip to content

Commit 23ed0c2

Browse files
authored
1016 feature request show avatars of devices if configured (#1018)
1 parent 02f06fb commit 23ed0c2

17 files changed

Lines changed: 72 additions & 32 deletions

File tree

src/main/java/com/dedicatedcode/reitti/controller/TimelineController.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ private UserTimelineData createUserTimeLineData(User user, List<String> authorit
130130
d.name(),
131131
this.avatarService.getAvatarDeviceId(user.getId(), d.id()).map(data -> "/avatars/" + user.getId() + "/" + d.id() + "?ts=" + data.updatedAt()).orElse(null),
132132
this.avatarService.generateInitials(d.name()),
133+
d.enabled(),
133134
d.color(),
134135
String.format("/api/v2/locations/metadata/%d/device/%d?start=%s&end=%s&timezone=%s", user.getId(), d.id(), startDate, endDate, timezone.getId()),
135136
String.format("/api/v2/locations/stream/%d/device/%d?start=%s&end=%s&timezone=%s", user.getId(), d.id(),startDate, endDate, timezone.getId())))

src/main/java/com/dedicatedcode/reitti/controller/settings/DeviceSettingsController.java

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public String getPage(@AuthenticationPrincipal User user,
6565
model.addAttribute("defaultAvatars", DEFAULT_AVATARS);
6666
model.addAttribute("devices", deviceJdbcService.getAll(user).stream()
6767
.map(d -> new DeviceDTO(d.id(), d.name(), d.color(),
68-
createAvatarUrl(user, d), avatarService.generateInitials(d.name()), d.enabled(), d.showOnMap(), d.defaultDevice(),
68+
createAvatarUrl(user, d), avatarService.generateInitials(d.name()), d.enabled(), d.showOnMap(), d.showAvatarOnMap(), d.defaultDevice(),
6969
adjustInstant(d.createdAt(), timezone), adjustInstant(d.updatedAt(), timezone)))
7070
.toList());
7171
return "settings/devices";
@@ -88,7 +88,7 @@ public String editDevice(@PathVariable Long deviceId,
8888
model.addAttribute("device",
8989
new DeviceDTO(device.id(), device.name(), device.color(),
9090
createAvatarUrl(user, device), avatarService.generateInitials(device.name()),
91-
device.enabled(), device.showOnMap(), device.defaultDevice(),
91+
device.enabled(), device.showOnMap(), device.showAvatarOnMap(), device.defaultDevice(),
9292
adjustInstant(device.createdAt(), timezone), adjustInstant(device.updatedAt(), timezone)));
9393
boolean hasAvatar = this.avatarService.getInfo(user.getId(), device.id()).isPresent();
9494
model.addAttribute("hasAvatar", hasAvatar);
@@ -102,8 +102,8 @@ public String createDevice(@AuthenticationPrincipal User user,
102102
@RequestParam String color,
103103
@RequestParam(required = false, defaultValue = "false") boolean enabled,
104104
@RequestParam(required = false, defaultValue = "false") boolean showOnMap,
105+
@RequestParam(required = false, defaultValue = "false") boolean showAvatarOnMap,
105106
@RequestParam(required = false) String defaultAvatar,
106-
@RequestParam(required = false) String removeAvatar,
107107
@RequestParam(required = false) MultipartFile avatar,
108108
@RequestParam(required = false, defaultValue = "UTC") ZoneId timezone,
109109
Model model) {
@@ -114,6 +114,7 @@ public String createDevice(@AuthenticationPrincipal User user,
114114
name,
115115
enabled,
116116
showOnMap,
117+
showAvatarOnMap,
117118
color,
118119
false,
119120
now,
@@ -148,6 +149,7 @@ public String updateDevice(@PathVariable Long deviceId,
148149
@RequestParam String color,
149150
@RequestParam(required = false, defaultValue = "false") boolean enabled,
150151
@RequestParam(required = false, defaultValue = "false") boolean showOnMap,
152+
@RequestParam(required = false, defaultValue = "false") boolean showAvatarOnMap,
151153
@RequestParam(required = false) String defaultAvatar,
152154
@RequestParam(required = false) String removeAvatar,
153155
@RequestParam(required = false) MultipartFile avatar,
@@ -165,6 +167,7 @@ public String updateDevice(@PathVariable Long deviceId,
165167
name,
166168
enabled,
167169
showOnMap,
170+
showAvatarOnMap,
168171
color,
169172
existingDevice.defaultDevice(),
170173
existingDevice.createdAt(),
@@ -205,6 +208,7 @@ public String toggleDevice(@PathVariable Long deviceId,
205208
device.name(),
206209
!device.enabled(),
207210
device.showOnMap(),
211+
device.showAvatarOnMap(),
208212
device.color(),
209213
device.defaultDevice(),
210214
device.createdAt(),
@@ -335,15 +339,17 @@ private boolean isAllowedContentType(String contentType) {
335339
}
336340

337341
public record DeviceDTO(Long id, String name, String color, String avatarUrl, String avatarFallback,
338-
boolean enabled, boolean showOnMap,
342+
boolean enabled,
343+
boolean showOnMap,
344+
boolean showAvatar,
339345
boolean defaultDevice,
340346
LocalDateTime createdAt, LocalDateTime updatedAt) {
341347
}
342348

343349
private void addDevicesToModel(User user, ZoneId timezone, Model model) {
344350
List<Device> devices = deviceJdbcService.getAll(user);
345351
model.addAttribute("devices", devices.stream()
346-
.map(d -> new DeviceDTO(d.id(), d.name(), d.color(), createAvatarUrl(user, d), avatarService.generateInitials(d.name()), d.enabled(), d.showOnMap(), d.defaultDevice(),
352+
.map(d -> new DeviceDTO(d.id(), d.name(), d.color(), createAvatarUrl(user, d), avatarService.generateInitials(d.name()), d.enabled(), d.showOnMap(), d.showAvatarOnMap(), d.defaultDevice(),
347353
adjustInstant(d.createdAt(), timezone), adjustInstant(d.updatedAt(), timezone)))
348354
.toList());
349355
model.addAttribute("defaultColors", getDefaultColors());
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
package com.dedicatedcode.reitti.dto.timeline;
22

3-
public record DeviceTimelineData(Long id, String name, String avatarUrl, String avatarFallback, String color, String metadataUrl, String streamUrl) {
3+
public record DeviceTimelineData(Long id, String name, String avatarUrl, String avatarFallback, boolean showAvatarOnMap, String color, String metadataUrl, String streamUrl) {
44
}

src/main/java/com/dedicatedcode/reitti/model/devices/Device.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import java.io.Serializable;
44
import java.time.Instant;
55

6-
public record Device(Long id, String name, boolean enabled, boolean showOnMap, String color, boolean defaultDevice, Instant createdAt,
6+
public record Device(Long id, String name, boolean enabled, boolean showOnMap, boolean showAvatarOnMap, String color, boolean defaultDevice, Instant createdAt,
77
Instant updatedAt, Long version) implements Serializable {
88

99
public Device withDefaultDevice(boolean defaultDevice) {
10-
return new Device(id, name, enabled, showOnMap, color, defaultDevice, createdAt, updatedAt, version);
10+
return new Device(id, name, enabled, showOnMap, showAvatarOnMap, color, defaultDevice, createdAt, updatedAt, version);
1111
}
1212
}

src/main/java/com/dedicatedcode/reitti/repository/ApiTokenJdbcService.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public Optional<ApiToken> findByToken(String token) {
2929
String sql = """
3030
SELECT at.id, at.token, at.name, at.device_id, at.created_at, at.last_used_at,
3131
u.id as user_id, u.username, u.password, u.display_name, u.profile_url, u.external_id, u.role, u.version as user_version,
32-
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
32+
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.show_avatar_on_map as device_show_avatar_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
3333
FROM api_tokens at
3434
JOIN users u ON at.user_id = u.id
3535
LEFT JOIN devices d ON at.device_id = d.id
@@ -47,7 +47,7 @@ public List<ApiToken> findByUser(User user) {
4747
String sql = """
4848
SELECT at.id, at.token, at.name, at.device_id, at.created_at, at.last_used_at,
4949
u.id as user_id, u.username, u.password, u.display_name, u.profile_url, u.external_id, u.role, u.version as user_version,
50-
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
50+
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.show_avatar_on_map as device_show_avatar_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
5151
FROM api_tokens at
5252
JOIN users u ON at.user_id = u.id
5353
LEFT JOIN devices d ON at.device_id = d.id
@@ -61,7 +61,7 @@ public Optional<ApiToken> findById(Long id) {
6161
String sql = """
6262
SELECT at.id, at.token, at.name, at.device_id, at.created_at, at.last_used_at,
6363
u.id as user_id, u.username, u.password, u.display_name, u.profile_url, u.external_id, u.role, u.version as user_version,
64-
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
64+
d.id as device_id, d.name as device_name, d.default_device as default_device, d.enabled as device_enabled, d.color as device_color, d.show_on_map as device_show_on_map, d.show_avatar_on_map as device_show_avatar_on_map, d.version as device_version, d.created_at as device_created_at, d.updated_at as device_updated_at, d.version as device_version
6565
FROM api_tokens at
6666
JOIN users u ON at.user_id = u.id
6767
LEFT JOIN devices d ON at.device_id = d.id
@@ -156,6 +156,7 @@ private ApiToken mapRowToApiToken(ResultSet rs, int rowNum) throws SQLException
156156
rs.getString("device_name"),
157157
rs.getBoolean("device_enabled"),
158158
rs.getBoolean("device_show_on_map"),
159+
rs.getBoolean("device_show_avatar_on_map"),
159160
rs.getString("device_color"),
160161
rs.getBoolean("default_device"),
161162
rs.getTimestamp("device_created_at").toInstant(),

src/main/java/com/dedicatedcode/reitti/repository/DeviceJdbcService.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public class DeviceJdbcService {
2727
rs.getString("name"),
2828
rs.getBoolean("enabled"),
2929
rs.getBoolean("show_on_map"),
30+
rs.getBoolean("show_avatar_on_map"),
3031
rs.getString("color"),
3132
rs.getBoolean("default_device"),
3233
rs.getTimestamp("created_at").toInstant(),
@@ -44,19 +45,20 @@ public Device save(Device device, User user) {
4445

4546
jdbcTemplate.update(connection -> {
4647
PreparedStatement ps = connection.prepareStatement(
47-
"INSERT INTO devices (user_id, name, color, enabled, show_on_map, default_device, created_at, updated_at, version) " +
48-
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
48+
"INSERT INTO devices (user_id, name, color, enabled, show_on_map, show_avatar_on_map, default_device, created_at, updated_at, version) " +
49+
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING id",
4950
Statement.RETURN_GENERATED_KEYS
5051
);
5152
ps.setLong(1, user.getId());
5253
ps.setString(2, device.name());
5354
ps.setString(3, device.color());
5455
ps.setBoolean(4, device.enabled());
5556
ps.setBoolean(5, device.showOnMap());
56-
ps.setBoolean(6, device.defaultDevice());
57-
ps.setTimestamp(7, Timestamp.from(device.createdAt()));
58-
ps.setTimestamp(8, Timestamp.from(device.updatedAt()));
59-
ps.setLong(9, 1L);
57+
ps.setBoolean(6, device.showAvatarOnMap());
58+
ps.setBoolean(7, device.defaultDevice());
59+
ps.setTimestamp(8, Timestamp.from(device.createdAt()));
60+
ps.setTimestamp(9, Timestamp.from(device.updatedAt()));
61+
ps.setLong(10, 1L);
6062
return ps;
6163
}, keyHolder);
6264

@@ -66,6 +68,7 @@ public Device save(Device device, User user) {
6668
device.name(),
6769
device.enabled(),
6870
device.showOnMap(),
71+
device.showAvatarOnMap(),
6972
device.color(),
7073
device.defaultDevice(),
7174
device.createdAt(),
@@ -77,13 +80,14 @@ public Device save(Device device, User user) {
7780
@CacheEvict(value = "devices", allEntries = true)
7881
public Device update(Device device, User user) {
7982
int updated = jdbcTemplate.update(
80-
"UPDATE devices SET name = ?, color = ?, default_device = ?, enabled = ?, show_on_map = ?, updated_at = ?, version = version + 1 " +
83+
"UPDATE devices SET name = ?, color = ?, default_device = ?, enabled = ?, show_on_map = ?, show_avatar_on_map = ?, updated_at = ?, version = version + 1 " +
8184
"WHERE id = ? AND user_id = ?",
8285
device.name(),
8386
device.color(),
8487
device.defaultDevice(),
8588
device.enabled(),
8689
device.showOnMap(),
90+
device.showAvatarOnMap(),
8791
Timestamp.from(Instant.now()),
8892
device.id(),
8993
user.getId()
@@ -98,6 +102,7 @@ public Device update(Device device, User user) {
98102
device.name(),
99103
device.enabled(),
100104
device.showOnMap(),
105+
device.showAvatarOnMap(),
101106
device.color(),
102107
device.defaultDevice(),
103108
device.createdAt(),

src/main/java/com/dedicatedcode/reitti/service/UserService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ public User createNewUser(String username,
9393

9494
private void createDefaultDeviceForUser(User createdUser) {
9595
ApiToken token = this.apiTokenService.createToken(createdUser, "Default");
96-
Device saved = this.deviceJdbcService.save(new Device(null, "Default", true, true, "#f1ba63", true, Instant.now(), Instant.now(), 0L), createdUser);
96+
Device saved = this.deviceJdbcService.save(new Device(null, "Default", true, true, true, "#f1ba63", true, Instant.now(), Instant.now(), 0L), createdUser);
9797
token = token.withDevice(saved);
9898
this.apiTokenJdbcService.save(token);
9999
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE devices ADD COLUMN show_avatar_on_map BOOLEAN DEFAULT TRUE;

src/main/resources/messages.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1779,6 +1779,7 @@ devices.name.placeholder=Enter device name
17791779
devices.color.label=Color
17801780
devices.enabled.label=Enabled
17811781
devices.showOnMap.label=Show on Map
1782+
devices.showAvatar.label=Show Avatar on Map
17821783
devices.delete.confirm=Are you sure you want to delete this device?
17831784
devices.default.confirm=Are you sure you want to set this device as the default?
17841785
devices.status.default=Your default device
@@ -1800,7 +1801,7 @@ message.error.device.creation=Error creating device: {0}
18001801
message.success.device.updated=Device update successfully
18011802
message.error.device.update=Error updating the device: {0}
18021803
message.success.device.deleted=Device deleted successfully
1803-
message.error.device.deletion=Error deleting device: {0}
1804+
message.error.device.deletion=Error deleting a device: {0}
18041805
message.error.device.deletion.default=Your default device cannot be deleted. Please create a new device before deleting this one or switch to a different default device.
18051806
message.success.device.toggled=Device toggled successfully
18061807
message.success.device.default-device=Default device set to {0} successfully. Verify your integration settings to ensure the new default device is used.

src/main/resources/static/js/map-renderer.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ class MapRenderer {
630630
}
631631
}
632632

633-
if (latestLocation && userConfig) {
633+
if (latestLocation && userConfig?.showAvatar) {
634634
this.addAvatarMarker(
635635
manager.id, // Add user ID
636636
latestLocation.latitude,
@@ -1574,7 +1574,6 @@ class MapRenderer {
15741574
*/
15751575
updateAvatarPositions() {
15761576
const activeUserIds = new Set();
1577-
15781577
// Update existing markers or create new ones
15791578
this.gpsDataManagers.forEach(manager => {
15801579
const userConfig = manager.config;

0 commit comments

Comments
 (0)