Rename and begin implementing views

I get an error whenever CSS is loaded, not sure what to do about that yet. Doesn't seem to impact anything, but I should probably be using a different way of getting the id from an entity. Also need to think about deleting the functions I don't need.
This commit is contained in:
mitteneer 2025-03-04 11:17:47 -05:00
parent d1d5c08f9a
commit a55f4e7bc0
33 changed files with 192 additions and 28 deletions

View file

@ -1,8 +1,9 @@
.{
.name = "zuletzt",
.name = .zuletzt,
// This is a [Semantic Version](https://semver.org/).
// In a future version of Zig it will be used for package deduplication.
.version = "0.0.0",
.fingerprint = 0xfe1b5c182b3fe5f,
// This field is optional.
// This is currently advisory only; Zig does not yet do anything
@ -16,8 +17,8 @@
// internet connectivity.
.dependencies = .{
.jetzig = .{
.url = "https://github.com/jetzig-framework/jetzig/archive/8a4f91f26a5d6a9b34a47011e63e779280590bc2.tar.gz",
.hash = "1220dac633f4b6a3c40d2b8d5a3cb2fdd513601eb762ccb15c418e0646923d42cfe9",
.url = "https://github.com/jetzig-framework/jetzig/archive/d3157e4247211091127daba88a2552af3be8f5ed.tar.gz",
.hash = "jetzig-0.0.0-IpAgLe0QDwC-6XH_ElHKUmPGxGxr1XdgiLeHEalerM7B",
},
.zeit = .{
.url = "https://github.com/rockorager/zeit/archive/refs/heads/main.tar.gz",
@ -31,10 +32,12 @@
// in the same contents hash.
"",
// For example...
//"build.zig",
//"build.zig.zon",
//"src",
//"LICENSE",
//"README.md",
"build.zig",
"build.zig.zon",
"src",
"LICENSE",
"README.md",
"public",
"config",
},
}

View file

@ -1,7 +1,3 @@
> [!note] Notice
> Queries involving artists are likely inaccurate due to database structure and
> limitations of scrobbles. Specifics and fixes are being planned.
Get all albums from specified artist:
```sql
SELECT artists.name, albums.name
@ -95,3 +91,61 @@ WHERE "Scrobbleartists".artist_id = artists.id
GROUP BY artists.id
ORDER BY scount DESC;
```
Sort all artists by alphabetical order, and include the first time you listened to that artist:
```sql
SELECT artists.name, MIN(scrobbles.date)
FROM "Scrobbleartists"
INNER JOIN artists
ON "Scrobbleartists".artist_id = artists.id
INNER JOIN scrobbles
ON "Scrobbleartists".scrobble_id = scrobbles.id
GROUP BY artists.name
ORDER BY artists.name ASC;
```
Sort all songs by alphabetical order, and include the first time you listened to that song:
```sql
SELECT songs.name, MIN(scrobbles.date)
FROM scrobbles
INNER JOIN songs
ON scrobbles.song_id = songs.id
GROUP BY songs.name
ORDER BY songs.name ASC;
```
Sort all albums by alphabetical order, and include the first time you listened to that album:
```sql
SELECT albums.name, MIN(scrobbles.date)
FROM scrobbles
INNER JOIN albums
ON scrobbles.album_id = albums.id
GROUP BY albums.name
ORDER BY albums.name ASC;
```
Select all songs by specified artists, include the number of plays of each song, and sort by plays:
```sql
SELECT songs.name, COUNT(scrobbles.song_id) as count
FROM songs, "Scrobbleartists"
INNER JOIN artists
ON "Scrobbleartists".artist_id = artists.id
INNER JOIN scrobbles
ON "Scrobbleartists".scrobble_id = scrobbles.id
WHERE songs.id = scrobbles.song_id AND artists.name = {ARTIST}
GROUP BY songs.name
ORDER BY count DESC;
```
Select all albums by specified artist, include the number of plays of each album, and sort by plays:
```sql
SELECT albums.name, COUNT(scrobbles.song_id) as count
FROM albums, "Scrobbleartists"
INNER JOIN artists
ON "Scrobbleartists".artist_id = artists.id
INNER JOIN scrobbles
ON "Scrobbleartists".scrobble_id = scrobbles.id
WHERE albums.id = scrobbles.album_id AND artists.name = {ARTIST}
GROUP BY albums.name
ORDER BY count DESC;
```

View file

@ -1,12 +1,31 @@
const std = @import("std");
const jetzig = @import("jetzig");
const jetquery = @import("jetzig").jetquery;
pub fn index(request: *jetzig.Request) !jetzig.View {
var root = try request.data(.object);
var albums_view = try root.put("albums", .array);
const query = jetzig.database.Query(.Album).select(.{}).orderBy(.{ .name = .asc });
const albums = try request.repo.all(query);
for (albums) |album| {
var album_view = try albums_view.append(.object);
try album_view.put("name", album.name);
try album_view.put("url", album.id);
}
return request.render(.ok);
}
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
_ = id;
var root = try request.data(.object);
try root.put("album_id", id);
var songs_view = try root.put("songs", .array);
const query = jetzig.database.Query(.Albumsong).include(.song, .{ .select = .{ .name, .id } }).join(.inner, .album).where(.{ .album = .{ .id = id } });
const songs = try request.repo.all(query);
for (songs) |song| {
var song_view = try songs_view.append(.object);
try song_view.put("name", song.song.name);
try song_view.put("url", song.song.id);
}
return request.render(.ok);
}
@ -38,7 +57,6 @@ pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
return request.render(.ok);
}
test "index" {
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
defer app.deinit();

View file

@ -0,0 +1,19 @@
<html>
<head>
<link rel="stylesheet" href="styles.css">
<meta charset="UTF-8">
</head>
<body>
@partial partials/header
<h1>no one lol</h1>
<table>
<tr>
<th>Name</th>
@for (.songs) |song| {
<tr>
<td class=cell><a href="/songs/{{song.url}}">{{song.name}}</a></td>
</tr>
}
</table>
</body>
</html>

View file

@ -0,0 +1,19 @@
<html>
<head>
<link rel="stylesheet" href="styles.css">
<meta charset="UTF-8">
</head>
<body>
@partial partials/header
<h1> Artists</h1>
<table>
<tr>
<th>Name</th>
@for (.artists) |artist| {
<tr>
<td class=cell><a href="/artists/{{artist.url}}">{{artist.name}}</a></td>
</tr>
}
</table>
</body>
</html>

View file

@ -1,3 +0,0 @@
<div>
<span>Content goes here</span>
</div>

View file

@ -1,3 +0,0 @@
<div>
<span>Content goes here</span>
</div>

View file

@ -1,12 +1,38 @@
const std = @import("std");
const jetzig = @import("jetzig");
const jetquery = @import("jetzig").jetquery;
pub fn index(request: *jetzig.Request) !jetzig.View {
var root = try request.data(.object);
var artists_view = try root.put("artists", .array);
const query = jetzig.database.Query(.Artist).select(.{}).orderBy(.{ .name = .asc });
const artists = try request.repo.all(query);
for (artists) |artist| {
var artist_view = try artists_view.append(.object);
//const output = try request.allocator.dupe(u8, artist.name);
//std.mem.replaceScalar(u8, output, ' ', '_');
try artist_view.put("name", artist.name);
try artist_view.put("url", artist.id);
}
return request.render(.ok);
}
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
_ = id;
//const artist_name = jetzig.database.Query(.Artist).find().select(.{.name}).execute(request.repo);
std.log.debug("page: {s}", .{id});
var root = try request.data(.object);
//try root.put("artist", artist_name);
try root.put("artist_id", id);
var albums_view = try root.put("albums", .array);
const query = jetzig.database.Query(.Albumartist).include(.album, .{ .select = .{ .name, .id } }).join(.inner, .artist).where(.{ .artist = .{ .id = id } });
const albums = try request.repo.all(query);
for (albums) |album| {
var album_view = try albums_view.append(.object);
try album_view.put("name", album.album.name);
try album_view.put("url", album.album.id);
//std.log.debug("{s}", .{album.album.name});
}
return request.render(.ok);
}
@ -38,7 +64,6 @@ pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
return request.render(.ok);
}
test "index" {
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
defer app.deinit();

View file

@ -0,0 +1,19 @@
<html>
<head>
<link rel="stylesheet" href="styles.css">
<meta charset="UTF-8">
</head>
<body>
@partial partials/header
<h1>no one lol</h1>
<table>
<tr>
<th>Name</th>
@for (.albums) |album| {
<tr>
<td class=cell><a href="/albums/{{album.url}}">{{album.name}}</a></td>
</tr>
}
</table>
</body>
</html>

View file

@ -0,0 +1,19 @@
<html>
<head>
<link rel="stylesheet" href="styles.css">
<meta charset="UTF-8">
</head>
<body>
@partial partials/header
<h1> Artists</h1>
<table>
<tr>
<th>Name</th>
@for (.artists) |artist| {
<tr>
<td class=cell><a href="/artists/{{artist.url}}">{{artist.name}}</a></td>
</tr>
}
</table>
</body>
</html>

View file

@ -1,3 +0,0 @@
<div>
<span>Content goes here</span>
</div>

View file

@ -1,3 +0,0 @@
<div>
<span>Content goes here</span>
</div>