Compare commits
6 commits
3345b20f1f
...
153ea869e0
| Author | SHA1 | Date | |
|---|---|---|---|
| 153ea869e0 | |||
| 4758885c68 | |||
| 9ffc45b207 | |||
| 94cc6e3bd5 | |||
| c574885f8d | |||
| 762a4fd51e |
78 changed files with 135 additions and 1129 deletions
|
|
@ -17,12 +17,12 @@
|
||||||
// internet connectivity.
|
// internet connectivity.
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.jetzig = .{
|
.jetzig = .{
|
||||||
.url = "https://github.com/jetzig-framework/jetzig/archive/1feb18fb74e626fe068ec67532318640a9cb83be.tar.gz",
|
.url = "https://github.com/jetzig-framework/jetzig/archive/a298192bb0cddf9c45d7d0d976a9852804457de2.tar.gz",
|
||||||
.hash = "jetzig-0.0.0-IpAgLfMzDwDyAqZ05btcLDd9dfE_bxUbfOI_Wx7a19ed",
|
.hash = "jetzig-0.0.0-IpAgLf5aDwB4UOKMhIjtK22zBsPfbWEwCYgHT0hayyT-",
|
||||||
},
|
},
|
||||||
.zeit = .{
|
.zeit = .{
|
||||||
.url = "https://github.com/rockorager/zeit/archive/refs/heads/main.tar.gz",
|
.url = "https://github.com/rockorager/zeit/archive/refs/tags/v0.6.0.tar.gz",
|
||||||
.hash = "zeit-0.6.0-5I6bk5daAgC-P60TjxRqW0bYknfCGxJp-03eS9UjGrO7",
|
.hash = "zeit-0.0.0-5I6bk_pZAgB03N1p1GmVOZ--gOFwwQSRKj1UXb5tnaKS",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.paths = .{
|
.paths = .{
|
||||||
|
|
|
||||||
|
|
@ -1,164 +0,0 @@
|
||||||
Get all albums from specified artist:
|
|
||||||
```sql
|
|
||||||
SELECT artists.name, albums.name
|
|
||||||
FROM "Albumartists"
|
|
||||||
INNER JOIN artists
|
|
||||||
ON "Albumartists".artist_id = artists.id
|
|
||||||
INNER JOIN albums
|
|
||||||
ON "Albumartists".album_id = albums.id
|
|
||||||
WHERE artists.name = {ARTIST};
|
|
||||||
```
|
|
||||||
|
|
||||||
Get all songs from specified artist:
|
|
||||||
```sql
|
|
||||||
SELECT artists.name, songs.name
|
|
||||||
FROM "Songartists"
|
|
||||||
INNER JOIN artists
|
|
||||||
ON "Songartists".artist_id = artists.id
|
|
||||||
INNER JOIN songs
|
|
||||||
ON "Songartists".song_id = songs.id
|
|
||||||
WHERE artists.name = {ARTIST};
|
|
||||||
```
|
|
||||||
|
|
||||||
Get all songs from any album of the specified name:
|
|
||||||
```sql
|
|
||||||
SELECT songs.name
|
|
||||||
FROM "Albumsongs"
|
|
||||||
INNER JOIN albums
|
|
||||||
ON "Albumsongs".album_id = albums.id
|
|
||||||
INNER JOIN songs
|
|
||||||
ON "Albumsongs".song_id = songs.id
|
|
||||||
WHERE albums.name = {ALBUM};
|
|
||||||
```
|
|
||||||
|
|
||||||
Sort all songs by plays (does not list artist or album):
|
|
||||||
```sql
|
|
||||||
SELECT songs.name, COUNT(scrobbles.song_id) AS scount
|
|
||||||
FROM songs, scrobbles
|
|
||||||
WHERE songs.id = scrobbles.song_id
|
|
||||||
GROUP BY songs.id
|
|
||||||
ORDER BY scount DESC;
|
|
||||||
```
|
|
||||||
|
|
||||||
Sort all songs by plays, and include artist:
|
|
||||||
```sql
|
|
||||||
SELECT songs.name, artists.name, COUNT(scrobbles.song_id) AS scount
|
|
||||||
FROM scrobbles, "Songartists"
|
|
||||||
INNER JOIN artists
|
|
||||||
ON "Songartists".artist_id = artists.id
|
|
||||||
INNER JOIN songs
|
|
||||||
ON "Songartists".song_id = songs.id
|
|
||||||
WHERE songs.id = scrobbles.song_id
|
|
||||||
GROUP BY songs.id, artists.id
|
|
||||||
ORDER BY scount DESC;
|
|
||||||
```
|
|
||||||
|
|
||||||
Sort all songs by plays, and include artist and album:
|
|
||||||
```sql
|
|
||||||
SELECT songs.name, artists.name, albums.name, COUNT(scrobbles.song_id) AS scount
|
|
||||||
FROM scrobbles CROSS JOIN "Songartists" CROSS JOIN "Albumsongs"
|
|
||||||
INNER JOIN artists
|
|
||||||
ON "Songartists".artist_id = artists.id
|
|
||||||
INNER JOIN songs
|
|
||||||
ON "Songartists".song_id = songs.id AND "Albumsongs".song_id = songs.id
|
|
||||||
INNER JOIN albums
|
|
||||||
ON "Albumsongs".album_id = albums.id
|
|
||||||
WHERE songs.id = scrobbles.song_id
|
|
||||||
GROUP BY songs.id, artists.id, albums.id
|
|
||||||
ORDER BY scount DESC;
|
|
||||||
```
|
|
||||||
|
|
||||||
Sort all albums by plays, and include artist:
|
|
||||||
```sql
|
|
||||||
SELECT albums.name, artists.name, COUNT(scrobbles.album_id) AS scount
|
|
||||||
FROM scrobbles, "Albumartists"
|
|
||||||
INNER JOIN albums
|
|
||||||
ON "Albumartists".album_id = albums.id
|
|
||||||
INNER JOIN artists
|
|
||||||
ON "Albumartists".artist_id = artists.id
|
|
||||||
WHERE albums.id = scrobbles.album_id
|
|
||||||
GROUP BY artists.id, albums.id
|
|
||||||
ORDER BY scount DESC;
|
|
||||||
```
|
|
||||||
|
|
||||||
Sort all artists by plays:
|
|
||||||
```sql
|
|
||||||
SELECT artists.name, COUNT(scrobbles.id) AS scount
|
|
||||||
FROM artists, "Scrobbleartists"
|
|
||||||
INNER JOIN scrobbles
|
|
||||||
ON scrobbles.id = "Scrobbleartists".scrobble_id
|
|
||||||
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.id
|
|
||||||
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.id
|
|
||||||
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.id
|
|
||||||
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.id
|
|
||||||
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.id
|
|
||||||
ORDER BY count DESC;
|
|
||||||
```
|
|
||||||
|
|
||||||
Select all songs from an album specified by an ID, and sort by plays
|
|
||||||
```sql
|
|
||||||
SELECT songs.name, COUNT(scrobbles.song_id) AS count
|
|
||||||
FROM "Albumsongs"
|
|
||||||
INNER JOIN songs
|
|
||||||
ON songs.id = "Albumsongs".song_id
|
|
||||||
INNER JOIN scrobbles
|
|
||||||
ON scrobbles.song_id = "Albumsongs".song_id
|
|
||||||
WHERE "Albumsongs".album_id = {ALBUM_ID}
|
|
||||||
GROUP BY songs.id
|
|
||||||
ORDER BY count DESC;
|
|
||||||
```
|
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
/// Demo middleware. Assign middleware by declaring `pub const middleware` in the
|
|
||||||
/// `jetzig_options` defined in your application's `src/main.zig`.
|
|
||||||
///
|
|
||||||
/// Middleware is called before and after the request, providing full access to the active
|
|
||||||
/// request, allowing you to execute any custom code for logging, tracking, inserting response
|
|
||||||
/// headers, etc.
|
|
||||||
///
|
|
||||||
/// This middleware is configured in the demo app's `src/main.zig`:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// pub const jetzig_options = struct {
|
|
||||||
/// pub const middleware: []const type = &.{@import("app/middleware/DemoMiddleware.zig")};
|
|
||||||
/// };
|
|
||||||
/// ```
|
|
||||||
const std = @import("std");
|
|
||||||
const jetzig = @import("jetzig");
|
|
||||||
|
|
||||||
/// Define any custom data fields you want to store here. Assigning to these fields in the `init`
|
|
||||||
/// function allows you to access them in various middleware callbacks defined below, where they
|
|
||||||
/// can also be modified.
|
|
||||||
my_custom_value: []const u8,
|
|
||||||
|
|
||||||
const Self = @This();
|
|
||||||
|
|
||||||
/// Initialize middleware.
|
|
||||||
pub fn init(request: *jetzig.http.Request) !*Self {
|
|
||||||
var middleware = try request.allocator.create(Self);
|
|
||||||
middleware.my_custom_value = "initial value";
|
|
||||||
return middleware;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoked immediately after the request is received but before it has started processing.
|
|
||||||
/// Any calls to `request.render` or `request.redirect` will prevent further processing of the
|
|
||||||
/// request, including any other middleware in the chain.
|
|
||||||
pub fn afterRequest(self: *Self, request: *jetzig.http.Request) !void {
|
|
||||||
try request.server.logger.DEBUG(
|
|
||||||
"[DemoMiddleware:afterRequest] my_custom_value: {s}",
|
|
||||||
.{self.my_custom_value},
|
|
||||||
);
|
|
||||||
self.my_custom_value = @tagName(request.method);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoked immediately before the response renders to the client.
|
|
||||||
/// The response can be modified here if needed.
|
|
||||||
pub fn beforeResponse(self: *Self, request: *jetzig.http.Request, response: *jetzig.http.Response) !void {
|
|
||||||
try request.server.logger.DEBUG(
|
|
||||||
"[DemoMiddleware:beforeResponse] my_custom_value: {s}, response status: {s}",
|
|
||||||
.{ self.my_custom_value, @tagName(response.status_code) },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoked immediately after the response has been finalized and sent to the client.
|
|
||||||
/// Response data can be accessed for logging, but any modifications will have no impact.
|
|
||||||
pub fn afterResponse(self: *Self, request: *jetzig.http.Request, response: *jetzig.http.Response) !void {
|
|
||||||
_ = self;
|
|
||||||
_ = response;
|
|
||||||
try request.server.logger.DEBUG("[DemoMiddleware:afterResponse] response completed", .{});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Invoked after `afterResponse` is called. Use this function to do any clean-up.
|
|
||||||
/// Note that `request.allocator` is an arena allocator, so any allocations are automatically
|
|
||||||
/// freed before the next request starts processing.
|
|
||||||
pub fn deinit(self: *Self, request: *jetzig.http.Request) void {
|
|
||||||
request.allocator.destroy(self);
|
|
||||||
}
|
|
||||||
|
|
@ -29,19 +29,19 @@ pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||||
if (album.id == prev_album_id) {
|
if (album.id == prev_album_id) {
|
||||||
var artist_info = try prev_artist_infos.?.append(.object);
|
var artist_info = try prev_artist_infos.?.append(.object);
|
||||||
try artist_info.put("name", album.artist_name);
|
try artist_info.put("name", album.artist_name);
|
||||||
try artist_info.put("url", album.artist_id);
|
try artist_info.put("id", album.artist_id);
|
||||||
continue :blk;
|
continue :blk;
|
||||||
}
|
}
|
||||||
var album_view = try albums_view.append(.object);
|
var album_view = try albums_view.append(.object);
|
||||||
|
|
||||||
|
try album_view.put("name", album.name);
|
||||||
|
try album_view.put("id", album.id);
|
||||||
|
try album_view.put("scrobbles", album.scrobbles);
|
||||||
|
|
||||||
var artist_infos = try album_view.put("artist_info", .array);
|
var artist_infos = try album_view.put("artist_info", .array);
|
||||||
var artist_info = try artist_infos.append(.object);
|
var artist_info = try artist_infos.append(.object);
|
||||||
try artist_info.put("name", album.artist_name);
|
try artist_info.put("name", album.artist_name);
|
||||||
try artist_info.put("url", album.artist_id);
|
try artist_info.put("id", album.artist_id);
|
||||||
|
|
||||||
try album_view.put("name", album.name);
|
|
||||||
try album_view.put("url", album.id);
|
|
||||||
try album_view.put("scrobbles", album.scrobbles);
|
|
||||||
|
|
||||||
prev_artist_infos = artist_infos;
|
prev_artist_infos = artist_infos;
|
||||||
prev_album_id = album.id;
|
prev_album_id = album.id;
|
||||||
|
|
@ -74,100 +74,8 @@ pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||||
const song = try song_row.to(Song, .{ .dupe = true, .allocator = request.allocator });
|
const song = try song_row.to(Song, .{ .dupe = true, .allocator = request.allocator });
|
||||||
var song_view = try songs_view.append(.object);
|
var song_view = try songs_view.append(.object);
|
||||||
try song_view.put("name", song.name);
|
try song_view.put("name", song.name);
|
||||||
try song_view.put("url", song.id);
|
try song_view.put("id", song.id);
|
||||||
try song_view.put("scrobbles", song.scrobbles);
|
try song_view.put("scrobbles", song.scrobbles);
|
||||||
}
|
}
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "index" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/album", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "get" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/album/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "new" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/album/new", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "edit" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/album/example-id/edit", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "post" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.POST, "/album", .{});
|
|
||||||
try response.expectStatus(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "put" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PUT, "/album/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "patch" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PATCH, "/album/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.DELETE, "/album/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
@zig {
|
||||||
|
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||||
|
const columns: ColumnChoices = &.{.song, .scrobbles};
|
||||||
|
}
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
|
|
@ -5,15 +10,6 @@
|
||||||
<body>
|
<body>
|
||||||
@partial partials/header
|
@partial partials/header
|
||||||
<h1>{{.album}}</h1>
|
<h1>{{.album}}</h1>
|
||||||
<table>
|
@partial partials/newtable(T: ColumnChoices, table_data: .songs, columns: columns)
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
@for (.songs) |song| {
|
|
||||||
<tr>
|
|
||||||
<td class=cell><a href="/songs/{{song.url}}">{{song.name}}</a></td>
|
|
||||||
<td class=cell>{{song.scrobbles}}</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</table>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,40 +1,15 @@
|
||||||
|
@zig {
|
||||||
|
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||||
|
const columns: ColumnChoices = &.{.album, .artistlist, .scrobbles};
|
||||||
|
}
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" rel="stylesheet" type="text/css">
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@partial partials/header
|
@partial partials/header
|
||||||
<h1>Albums</h1>
|
<h1>Albums</h1>
|
||||||
<table id="myTable">
|
@partial partials/newtable(T: ColumnChoices, table_data: .albums, columns: columns)
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th>
|
|
||||||
<th>Artist(s)</th>
|
|
||||||
<th>Scrobbles</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
</tbody>
|
|
||||||
@for (.albums) |album| {
|
|
||||||
<tr>
|
|
||||||
<td class=cell><a href="/albums/{{album.url}}">{{album.name}}</a></td>
|
|
||||||
<td class=cell>
|
|
||||||
@for (album.get("artist_info").?) |ai| {
|
|
||||||
<a href="/artists/{{ai.url}}">{{ai.name}}</a>
|
|
||||||
}
|
|
||||||
</td>
|
|
||||||
<td class=cell>{{album.scrobbles}}</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" type="text/javascript"></script>
|
|
||||||
<script>
|
|
||||||
const dataTable = new simpleDatatables.DataTable("#myTable", {
|
|
||||||
searchable: false,
|
|
||||||
perPage: 50,
|
|
||||||
perPageSelect: [25,50,100],
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -138,113 +138,25 @@ pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||||
defer first_last_songs_jq_result.deinit();
|
defer first_last_songs_jq_result.deinit();
|
||||||
|
|
||||||
// These look backwards, but it's correct this way
|
// These look backwards, but it's correct this way
|
||||||
|
var last_song_view = try root.put("last", .object);
|
||||||
|
|
||||||
if (try first_last_songs_jq_result.postgresql.result.next()) |last_song_row| {
|
if (try first_last_songs_jq_result.postgresql.result.next()) |last_song_row| {
|
||||||
const last_song = try last_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
const last_song = try last_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
||||||
try root.put("last_song_name", last_song.name);
|
try last_song_view.put("name", last_song.name);
|
||||||
try root.put("last_song_id", last_song.id);
|
try last_song_view.put("id", last_song.id);
|
||||||
try root.put("last_song_date", (try dateFmt(request.allocator, last_song.date)));
|
try last_song_view.put("date", (try dateFmt(request.allocator, last_song.date)));
|
||||||
}
|
} else unreachable;
|
||||||
|
|
||||||
|
var first_song_view = try root.put("first", .object);
|
||||||
|
|
||||||
if (try first_last_songs_jq_result.postgresql.result.next()) |first_song_row| {
|
if (try first_last_songs_jq_result.postgresql.result.next()) |first_song_row| {
|
||||||
const first_song = try first_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
const first_song = try first_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
||||||
try root.put("first_song_name", first_song.name);
|
try first_song_view.put("name", first_song.name);
|
||||||
try root.put("first_song_id", first_song.id);
|
try first_song_view.put("id", first_song.id);
|
||||||
try root.put("first_song_date", (try dateFmt(request.allocator, first_song.date)));
|
try first_song_view.put("date", (try dateFmt(request.allocator, first_song.date)));
|
||||||
}
|
} else unreachable;
|
||||||
|
|
||||||
try first_last_songs_jq_result.drain();
|
try first_last_songs_jq_result.drain();
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "index" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/artist", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "get" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/artist/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "new" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/artist/new", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "edit" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/artist/example-id/edit", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "post" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.POST, "/artist", .{});
|
|
||||||
try response.expectStatus(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "put" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PUT, "/artist/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "patch" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PATCH, "/artist/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.DELETE, "/artist/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,53 +1,22 @@
|
||||||
|
@zig {
|
||||||
|
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||||
|
const columns: ColumnChoices = &.{.album, .scrobbles};
|
||||||
|
}
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" rel="stylesheet" type="text/css">
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@partial partials/header
|
@partial partials/header
|
||||||
<h1>{{.artist.name}}</h1>
|
<h1>{{.artist.name}}</h1>
|
||||||
{{.artist.scrobbles}} scrobbles ({{.artist.rank}} place)
|
@partial partials/firstlast_listens(scrobbles: .artist.scrobbles, rank: .artist.rank, last_song: .last, first_song: .first)
|
||||||
<br>
|
|
||||||
First listen: <a href="/songs/{{.first_song_id}}">{{.first_song_name}}</a> ({{.first_song_date}})
|
|
||||||
<br>
|
|
||||||
Most recent listen: <a href="/songs/{{.last_song_id}}">{{.last_song_name}}</a> ({{.last_song_date}})
|
|
||||||
<h2>Albums</h2>
|
<h2>Albums</h2>
|
||||||
<table id="myTable">
|
@partial partials/newtable(T: ColumnChoices, table_data: .albums, columns: columns)
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th><th>Scrobbles</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@for (.albums) |album| {
|
|
||||||
<tr>
|
|
||||||
<td class=cell><a href="/albums/{{album.id}}">{{album.name}}</a></td>
|
|
||||||
<td class=cell>{{album.scrobbles}}</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<h2>Albums Featured On</h2>
|
<h2>Albums Featured On</h2>
|
||||||
<table id="myTable">
|
@partial partials/newtable(T: ColumnChoices, table_data: .appears, columns: columns)
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Name</th><th>Scrobbles</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@for (.appears) |album| {
|
|
||||||
<tr>
|
|
||||||
<td class=cell><a href="/albums/{{album.id}}">{{album.name}}</a></td>
|
|
||||||
<td class=cell>{{album.scrobbles}}</td>
|
|
||||||
</tr>
|
|
||||||
}
|
|
||||||
</tbody>
|
|
||||||
<table>
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/simple-datatables@latest" type="text/javascript"></script>
|
|
||||||
<script>
|
|
||||||
const dataTable = new simpleDatatables.DataTable("#myTable", {
|
|
||||||
searchable: false,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -11,26 +11,3 @@ pub fn get(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig
|
||||||
_ = id;
|
_ = id;
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -11,26 +11,3 @@ pub fn get(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig
|
||||||
_ = id;
|
_ = id;
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -16,21 +16,3 @@ pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||||
_ = data;
|
_ = data;
|
||||||
return request.render(.created);
|
return request.render(.created);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
9
src/app/views/partials/_firstlast_listens.zmpl
Normal file
9
src/app/views/partials/_firstlast_listens.zmpl
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
@args scrobbles: i64, rank: []const u8, last_song: *ZmplValue, first_song: *ZmplValue
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{{scrobbles}} scrobbles ({{rank}} place)
|
||||||
|
<br>
|
||||||
|
First listen: <a href="/songs/{{first_song.id}}">{{first_song.name}}</a> ({{first_song.date}})
|
||||||
|
<br>
|
||||||
|
Most recent listen: <a href="/songs/{{last_song.id}}">{{last_song.name}}</a> ({{last_song.date}})
|
||||||
|
</div>
|
||||||
69
src/app/views/partials/_newtable.zmpl
Normal file
69
src/app/views/partials/_newtable.zmpl
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
@args T: type, table_data: *ZmplValue, columns: T
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
@zig {
|
||||||
|
for (columns) |header| {
|
||||||
|
switch (header) {
|
||||||
|
.song => {
|
||||||
|
<th>Song</th>
|
||||||
|
},
|
||||||
|
.album => {
|
||||||
|
<th>Album</th>
|
||||||
|
},
|
||||||
|
.artist => {
|
||||||
|
<th>Artist</th>
|
||||||
|
},
|
||||||
|
.artistlist => {
|
||||||
|
<th>Artist(s)</th>
|
||||||
|
},
|
||||||
|
.scrobbles => {
|
||||||
|
<th>Scrobbles</th>
|
||||||
|
},
|
||||||
|
.date => {
|
||||||
|
<th>Date</th>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@zig {
|
||||||
|
const array = table_data.items(.array);
|
||||||
|
for (array) |ent| {
|
||||||
|
<tr>
|
||||||
|
for (columns) |header| {
|
||||||
|
switch (header) {
|
||||||
|
.song, .album, .artist => {
|
||||||
|
const path = switch (header) {
|
||||||
|
.song => "songs",
|
||||||
|
.album => "albums",
|
||||||
|
.artist => "artists",
|
||||||
|
else => unreachable
|
||||||
|
};
|
||||||
|
<td class=cell>
|
||||||
|
<a href="/{{path}}/{{ent.id}}">{{ent.name}}</a>
|
||||||
|
</td>
|
||||||
|
},
|
||||||
|
.artistlist => {
|
||||||
|
<td class=cell>
|
||||||
|
@for (ent.get("artist_info").?) |artist| {
|
||||||
|
<a href="/artists/{{artist.id}}">{{artist.name}}</a>
|
||||||
|
}
|
||||||
|
</td>
|
||||||
|
},
|
||||||
|
.scrobbles => {
|
||||||
|
<td class=cell>{{ent.scrobbles}}</td>
|
||||||
|
},
|
||||||
|
.date =>{
|
||||||
|
<td class=cell>{{ent.date}}</td>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
@ -16,21 +16,3 @@ pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||||
_ = data;
|
_ = data;
|
||||||
return request.render(.created);
|
return request.render(.created);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -4,21 +4,6 @@ const jetzig = @import("jetzig");
|
||||||
pub fn index(request: *jetzig.Request) !jetzig.View {
|
pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
pub fn post(request: *jetzig.Request) !jetzig.View {
|
||||||
const params = try request.params();
|
const params = try request.params();
|
||||||
|
|
||||||
|
|
@ -54,82 +39,3 @@ pub fn post(request: *jetzig.Request) !jetzig.View {
|
||||||
|
|
||||||
return request.render(.created);
|
return request.render(.created);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "index" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/rules", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "get" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/rules/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "new" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/rules/new", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "edit" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/rules/example-id/edit", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "post" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.POST, "/rules", .{});
|
|
||||||
try response.expectStatus(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "put" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PUT, "/rules/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "patch" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PATCH, "/rules/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.DELETE, "/rules/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -55,32 +55,3 @@ pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||||
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
_ = data;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
const jetzig = @import("jetzig");
|
|
||||||
|
|
||||||
pub fn index(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
test "index" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/search", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "get" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/search/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "new" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/search/new", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "edit" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/search/example-id/edit", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "post" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.POST, "/search", .{});
|
|
||||||
try response.expectStatus(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "put" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PUT, "/search/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "patch" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PATCH, "/search/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.DELETE, "/search/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -4,12 +4,6 @@ const jetzig = @import("jetzig");
|
||||||
pub fn index(request: *jetzig.Request) !jetzig.View {
|
pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||||
var root = try request.data(.object);
|
var root = try request.data(.object);
|
||||||
var songs_view = try root.put("songs", .array);
|
var songs_view = try root.put("songs", .array);
|
||||||
//const songs = try jetzig.database.Query(.Song)
|
|
||||||
// .select(.{ .id, .name })
|
|
||||||
// .include(.songartists, .{ .select = .{.artist_id} })
|
|
||||||
// .include(.scrobbles, .{ .select = .{.id} })
|
|
||||||
// .orderBy(.{ .name = .asc })
|
|
||||||
// .all(request.repo);
|
|
||||||
|
|
||||||
const query =
|
const query =
|
||||||
\\SELECT songs.name, songs.id, artists.name, artists.id, COUNT(scrobbles) AS scrobbles
|
\\SELECT songs.name, songs.id, artists.name, artists.id, COUNT(scrobbles) AS scrobbles
|
||||||
|
|
@ -52,24 +46,6 @@ pub fn index(request: *jetzig.Request) !jetzig.View {
|
||||||
prev_artist_infos = artist_infos;
|
prev_artist_infos = artist_infos;
|
||||||
prev_song_id = song.id;
|
prev_song_id = song.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (songs) |song| {
|
|
||||||
// var song_view = try songs_view.append(.object);
|
|
||||||
|
|
||||||
// var artist_infos = try song_view.put("artist_info", .array);
|
|
||||||
// for (song.songartists) |artist| {
|
|
||||||
// var artist_info = try artist_infos.append(.object);
|
|
||||||
// const artist_data = try jetzig.database.Query(.Artist)
|
|
||||||
// .find(artist.artist_id)
|
|
||||||
// .select(.{ .id, .name })
|
|
||||||
// .execute(request.repo);
|
|
||||||
// try artist_info.put("name", artist_data.?.name);
|
|
||||||
// try artist_info.put("id", artist_data.?.id);
|
|
||||||
// }
|
|
||||||
// try song_view.put("name", song.name);
|
|
||||||
// try song_view.put("url", song.id);
|
|
||||||
// try song_view.put("scrobbles", (song.scrobbles).len);
|
|
||||||
//}
|
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -77,95 +53,3 @@ pub fn get(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
||||||
_ = id;
|
_ = id;
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn edit(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn post(request: *jetzig.Request) !jetzig.View {
|
|
||||||
return request.render(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request) !jetzig.View {
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "index" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/song", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "get" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/song/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "new" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/song/new", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "edit" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.GET, "/song/example-id/edit", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "post" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.POST, "/song", .{});
|
|
||||||
try response.expectStatus(.created);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "put" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PUT, "/song/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "patch" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.PATCH, "/song/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "delete" {
|
|
||||||
var app = try jetzig.testing.app(std.testing.allocator, @import("routes"));
|
|
||||||
defer app.deinit();
|
|
||||||
|
|
||||||
const response = try app.request(.DELETE, "/song/example-id", .{});
|
|
||||||
try response.expectStatus(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -10,12 +10,6 @@ pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
||||||
return request.render(.ok);
|
return request.render(.ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
@ -166,21 +160,3 @@ pub fn post(request: *jetzig.Request) !jetzig.View {
|
||||||
|
|
||||||
return request.render(.created);
|
return request.render(.created);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn put(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn patch(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn delete(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig.View {
|
|
||||||
_ = data;
|
|
||||||
_ = id;
|
|
||||||
return request.render(.ok);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
<div>
|
|
||||||
<span>Content goes here</span>
|
|
||||||
</div>
|
|
||||||
|
|
@ -61,3 +61,14 @@ pub const Rule = struct {
|
||||||
pub const Rules = struct {
|
pub const Rules = struct {
|
||||||
rules: []const Rule,
|
rules: []const Rule,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Can't import types in .zmpl files, so defining this here
|
||||||
|
// doesn't really do much (except maybe in the .zig file for views?)
|
||||||
|
//pub const HeaderTypes = []enum {
|
||||||
|
// song,
|
||||||
|
// album,
|
||||||
|
// artist,
|
||||||
|
// artistlist,
|
||||||
|
// scrobbles,
|
||||||
|
// date,
|
||||||
|
//};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue