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.
|
||||
.dependencies = .{
|
||||
.jetzig = .{
|
||||
.url = "https://github.com/jetzig-framework/jetzig/archive/1feb18fb74e626fe068ec67532318640a9cb83be.tar.gz",
|
||||
.hash = "jetzig-0.0.0-IpAgLfMzDwDyAqZ05btcLDd9dfE_bxUbfOI_Wx7a19ed",
|
||||
.url = "https://github.com/jetzig-framework/jetzig/archive/a298192bb0cddf9c45d7d0d976a9852804457de2.tar.gz",
|
||||
.hash = "jetzig-0.0.0-IpAgLf5aDwB4UOKMhIjtK22zBsPfbWEwCYgHT0hayyT-",
|
||||
},
|
||||
.zeit = .{
|
||||
.url = "https://github.com/rockorager/zeit/archive/refs/heads/main.tar.gz",
|
||||
.hash = "zeit-0.6.0-5I6bk5daAgC-P60TjxRqW0bYknfCGxJp-03eS9UjGrO7",
|
||||
.url = "https://github.com/rockorager/zeit/archive/refs/tags/v0.6.0.tar.gz",
|
||||
.hash = "zeit-0.0.0-5I6bk_pZAgB03N1p1GmVOZ--gOFwwQSRKj1UXb5tnaKS",
|
||||
},
|
||||
},
|
||||
.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) {
|
||||
var artist_info = try prev_artist_infos.?.append(.object);
|
||||
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;
|
||||
}
|
||||
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_info = try artist_infos.append(.object);
|
||||
try artist_info.put("name", album.artist_name);
|
||||
try artist_info.put("url", album.artist_id);
|
||||
|
||||
try album_view.put("name", album.name);
|
||||
try album_view.put("url", album.id);
|
||||
try album_view.put("scrobbles", album.scrobbles);
|
||||
try artist_info.put("id", album.artist_id);
|
||||
|
||||
prev_artist_infos = artist_infos;
|
||||
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 });
|
||||
var song_view = try songs_view.append(.object);
|
||||
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);
|
||||
}
|
||||
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>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
|
@ -5,15 +10,6 @@
|
|||
<body>
|
||||
@partial partials/header
|
||||
<h1>{{.album}}</h1>
|
||||
<table>
|
||||
<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>
|
||||
@partial partials/newtable(T: ColumnChoices, table_data: .songs, columns: columns)
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,40 +1,15 @@
|
|||
@zig {
|
||||
const ColumnChoices = []const enum{song, album, artist, artistlist, scrobbles, date};
|
||||
const columns: ColumnChoices = &.{.album, .artistlist, .scrobbles};
|
||||
}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" rel="stylesheet" type="text/css">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
@partial partials/header
|
||||
<h1>Albums</h1>
|
||||
<table id="myTable">
|
||||
<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>
|
||||
@partial partials/newtable(T: ColumnChoices, table_data: .albums, columns: columns)
|
||||
</body>
|
||||
</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();
|
||||
|
||||
// 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| {
|
||||
const last_song = try last_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
||||
try root.put("last_song_name", last_song.name);
|
||||
try root.put("last_song_id", last_song.id);
|
||||
try root.put("last_song_date", (try dateFmt(request.allocator, last_song.date)));
|
||||
}
|
||||
try last_song_view.put("name", last_song.name);
|
||||
try last_song_view.put("id", last_song.id);
|
||||
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| {
|
||||
const first_song = try first_song_row.to(ScrobbleResult, .{ .dupe = true, .allocator = request.allocator });
|
||||
try root.put("first_song_name", first_song.name);
|
||||
try root.put("first_song_id", first_song.id);
|
||||
try root.put("first_song_date", (try dateFmt(request.allocator, first_song.date)));
|
||||
}
|
||||
try first_song_view.put("name", first_song.name);
|
||||
try first_song_view.put("id", first_song.id);
|
||||
try first_song_view.put("date", (try dateFmt(request.allocator, first_song.date)));
|
||||
} else unreachable;
|
||||
|
||||
try first_last_songs_jq_result.drain();
|
||||
|
||||
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>
|
||||
<head>
|
||||
<link href="https://cdn.jsdelivr.net/npm/simple-datatables@latest/dist/style.css" rel="stylesheet" type="text/css">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
<body>
|
||||
@partial partials/header
|
||||
<h1>{{.artist.name}}</h1>
|
||||
{{.artist.scrobbles}} scrobbles ({{.artist.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}})
|
||||
@partial partials/firstlast_listens(scrobbles: .artist.scrobbles, rank: .artist.rank, last_song: .last, first_song: .first)
|
||||
|
||||
<h2>Albums</h2>
|
||||
<table id="myTable">
|
||||
<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>
|
||||
@partial partials/newtable(T: ColumnChoices, table_data: .albums, columns: columns)
|
||||
|
||||
<h2>Albums Featured On</h2>
|
||||
<table id="myTable">
|
||||
<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>
|
||||
@partial partials/newtable(T: ColumnChoices, table_data: .appears, columns: columns)
|
||||
|
||||
</body>
|
||||
</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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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 {
|
||||
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 {
|
||||
const params = try request.params();
|
||||
|
||||
|
|
@ -54,82 +39,3 @@ 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, "/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);
|
||||
}
|
||||
|
||||
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 {
|
||||
var root = try request.data(.object);
|
||||
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 =
|
||||
\\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_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);
|
||||
}
|
||||
|
||||
|
|
@ -77,95 +53,3 @@ 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, "/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);
|
||||
}
|
||||
|
||||
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 {
|
||||
var root = try request.data(.object);
|
||||
|
||||
|
|
@ -166,21 +160,3 @@ pub fn post(request: *jetzig.Request) !jetzig.View {
|
|||
|
||||
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 {
|
||||
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