Create rating interface on songs view
If no ratings are present, provide a textbox to make a rating. If a rating is present, show the rating. Eventually, there will be a button that allows an additional rating to be made, and the ability to delete ratings
This commit is contained in:
parent
996022fe5f
commit
6f6aaecb8f
6 changed files with 36 additions and 7 deletions
|
|
@ -3,9 +3,11 @@ const jetzig = @import("jetzig");
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
pub fn post(request: *jetzig.Request) !jetzig.View {
|
||||||
var root = try request.data(.object);
|
var root = try request.data(.object);
|
||||||
const params = try request.params();
|
const params = try request.params();
|
||||||
const id = params.getT(.integer, "song_id");
|
const id = params.getT(.integer, "song_id").?;
|
||||||
|
const score = if (params.getT(.integer, "score")) |score| @as(i16, @truncate(score)) else null;
|
||||||
const review = params.getT(.string, "review");
|
const review = params.getT(.string, "review");
|
||||||
try root.put("song_id", id);
|
try jetzig.database.Query(.Songrating).insert(.{ .song = id, .rating = score, .rating_text = review, .date = @divFloor(request.start_time, 1_000) }).execute(request.repo);
|
||||||
|
try root.put("score", score);
|
||||||
try root.put("review", review);
|
try root.put("review", review);
|
||||||
|
|
||||||
return request.render(.created);
|
return request.render(.created);
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
{{.song_id}}
|
<b>{{.score}}</b>: {{.review}} (Today)
|
||||||
{{.review}}
|
|
||||||
|
|
@ -59,5 +59,9 @@ pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||||
|
|
||||||
const timescale = try queries.entityQueryResult(request, queries.loadQuery(.song, .timescale), .{id_int});
|
const timescale = try queries.entityQueryResult(request, queries.loadQuery(.song, .timescale), .{id_int});
|
||||||
try root.put("yearly", timescale);
|
try root.put("yearly", timescale);
|
||||||
|
|
||||||
|
const ratings = try queries.entityQueryResult(request, queries.loadQuery(.song, .get_ratings), .{id_int});
|
||||||
|
try root.put("reviews", ratings);
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
@zig {
|
@zig {
|
||||||
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||||
const columns: ColumnChoices = &.{.song, .artistlist, .album, .date};
|
const columns: ColumnChoices = &.{.song, .artistlist, .album, .date};
|
||||||
|
const reviews = try zmpl.coerceArray(".reviews");
|
||||||
}
|
}
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
|
|
@ -25,13 +26,21 @@
|
||||||
</div>
|
</div>
|
||||||
<div style="display:flex;flex-direction:column;align-self:right">
|
<div style="display:flex;flex-direction:column;align-self:right">
|
||||||
<h2>Rating</h2>
|
<h2>Rating</h2>
|
||||||
|
<div id="review-container">
|
||||||
|
@zig {
|
||||||
|
if (reviews.len == 0) {
|
||||||
<form>
|
<form>
|
||||||
<input type="number" name="score" id="score" style="width:50px;height:30px">
|
<input type="number" name="score" id="score" style="width:50px;height:30px">
|
||||||
<textarea name="review" id="review" style="width:350px;height:100px"></textarea>
|
<textarea name="review" id="review" style="width:350px;height:100px"></textarea>
|
||||||
<button hx-post="/ratings/songs" hx-vals='{"song_id":"{{.song.song_id}}"}' hx-target="#review-container" style="width:50px;height:30px">Post</button>
|
<button hx-post="/ratings/songs" hx-vals='{"song_id":"{{.song.song_id}}"}' hx-target="#review-container" style="width:50px;height:30px">Post</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
} else {
|
||||||
<div id="review-container">No reviews</div>
|
for (reviews) |review| {
|
||||||
|
<b>{{review.score}}</b>: {{review.review}} ({{review.date}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -42,6 +42,8 @@ pub fn entityQueryResult(request: *jetzig.Request, query: GeneratedQuery, args:
|
||||||
.artistlist = if (artist_list.getLastOrNull()) |_| try artist_list.toOwnedSlice() else null,
|
.artistlist = if (artist_list.getLastOrNull()) |_| try artist_list.toOwnedSlice() else null,
|
||||||
.scrobbles = if (entity.scrobbles) |scrobbles| scrobbles else null,
|
.scrobbles = if (entity.scrobbles) |scrobbles| scrobbles else null,
|
||||||
.date = if (entity.date) |date| date else null,
|
.date = if (entity.date) |date| date else null,
|
||||||
|
.score = if (entity.score) |score| score else null,
|
||||||
|
.review = if (entity.review) |review| review else null,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +51,7 @@ pub fn entityQueryResult(request: *jetzig.Request, query: GeneratedQuery, args:
|
||||||
}
|
}
|
||||||
|
|
||||||
const EntityType = enum { scrobble, song, album, artist };
|
const EntityType = enum { scrobble, song, album, artist };
|
||||||
const QueryTypeEnum = enum { firstlast, timescale, entities, get_songs, get_albums, get_scrobbles, appears, entity_info, datestreak, entities_by_name };
|
const QueryTypeEnum = enum { firstlast, timescale, entities, get_songs, get_albums, get_scrobbles, appears, entity_info, datestreak, entities_by_name, get_ratings };
|
||||||
|
|
||||||
const GeneratedQuery = struct {
|
const GeneratedQuery = struct {
|
||||||
entity: EntityType,
|
entity: EntityType,
|
||||||
|
|
@ -66,6 +68,8 @@ const UnifiedResult = struct {
|
||||||
artist_id: ?i64 = null,
|
artist_id: ?i64 = null,
|
||||||
scrobbles: ?i64 = null,
|
scrobbles: ?i64 = null,
|
||||||
date: ?[]const u8 = null,
|
date: ?[]const u8 = null,
|
||||||
|
score: ?i16 = null,
|
||||||
|
review: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const EntityInfoResult = struct {
|
const EntityInfoResult = struct {
|
||||||
|
|
@ -435,6 +439,15 @@ pub fn loadQuery(entity: EntityType, query_type: QueryTypeEnum) GeneratedQuery {
|
||||||
,
|
,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
|
.get_ratings => switch (entity) {
|
||||||
|
.song =>
|
||||||
|
\\SELECT rating AS score, rating_text AS review, TO_CHAR(date, 'YYYY-MM-DD') AS date
|
||||||
|
\\FROM songratings
|
||||||
|
\\WHERE song = $1
|
||||||
|
\\ORDER BY date DESC;
|
||||||
|
,
|
||||||
|
else => unreachable,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,8 @@ pub const TableRow = struct {
|
||||||
artistlist: ?[]HyperlinkData = null,
|
artistlist: ?[]HyperlinkData = null,
|
||||||
scrobbles: ?i64 = null,
|
scrobbles: ?i64 = null,
|
||||||
date: ?[]const u8 = null,
|
date: ?[]const u8 = null,
|
||||||
|
score: ?i16 = null,
|
||||||
|
review: ?[]const u8 = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const HyperlinkData = struct {
|
pub const HyperlinkData = struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue