From 32c89bc12cf6b205ffd0a9c2a0c7720194f251a4 Mon Sep 17 00:00:00 2001 From: mitteneer Date: Mon, 25 Nov 2024 12:23:36 -0500 Subject: [PATCH] Update upload page --- build.zig.zon | 4 +- public/styles.css | 5 ++ src/app/database/Schema.zig | 61 +++++++++++++------ ...24-11-25_15-32-40_create_raw_scrobbles.zig | 22 +++++++ src/app/jobs/process_scrobbles.zig | 18 ++++++ src/app/views/partials/_table.zmpl | 18 ++++++ src/app/views/upload.zig | 52 ++++++++++++---- src/app/views/upload/index.zmpl | 5 +- src/app/views/upload/post.zmpl | 18 +++++- 9 files changed, 166 insertions(+), 37 deletions(-) create mode 100644 src/app/database/migrations/2024-11-25_15-32-40_create_raw_scrobbles.zig create mode 100644 src/app/jobs/process_scrobbles.zig diff --git a/build.zig.zon b/build.zig.zon index c7e8caf..7a4efa2 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -16,8 +16,8 @@ // internet connectivity. .dependencies = .{ .jetzig = .{ - .url = "https://github.com/jetzig-framework/jetzig/archive/b1becfd6ec3bde7e0fe69ae03690dde6ef55e483.tar.gz", - .hash = "12201b18d05071a10de4b5cdb12712b6bae5f3d88b54e4d4950cb38f86869b6fc310", + .url = "https://github.com/jetzig-framework/jetzig/archive/4e1a26a5f982a0af212fe15eaffc8d7d7ea2aab6.tar.gz", + .hash = "12206bec5c95058be1d0af92cc69c48e7dd9fc19c444736f9debd7e53d10e25c22c6", }, }, .paths = .{ diff --git a/public/styles.css b/public/styles.css index afdbce9..03416fd 100644 --- a/public/styles.css +++ b/public/styles.css @@ -4,6 +4,7 @@ * */ @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap'); + @import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap'); .title { font-family: 'Roboto'; @@ -20,6 +21,10 @@ margin-right: 20px; } +.cell { + font-family: 'Noto Sans' +} + #replaceMe{ font-family:'Courier New'; } diff --git a/src/app/database/Schema.zig b/src/app/database/Schema.zig index 764a544..1804ff0 100644 --- a/src/app/database/Schema.zig +++ b/src/app/database/Schema.zig @@ -131,27 +131,52 @@ pub const Song = jetquery.Model( }, ); -pub const Alias = jetquery.Model(@This(), "aliases", struct { - id: i32, - reference_id: i32, - alias: []const u8, - created_at: jetquery.DateTime, - updated_at: jetquery.DateTime, -}, .{}); +pub const Alias = jetquery.Model( + @This(), + "aliases", + struct { + id: i32, + reference_id: i32, + alias: []const u8, + created_at: jetquery.DateTime, + updated_at: jetquery.DateTime, + }, + .{}, +); -pub const Concert = jetquery.Model(@This(), "concerts", struct { - id: i32, - location: []const u8, - date: jetquery.DateTime, - created_at: jetquery.DateTime, - updated_at: jetquery.DateTime, -}, .{}); +pub const Concert = jetquery.Model( + @This(), + "concerts", + struct { + id: i32, + location: []const u8, + date: jetquery.DateTime, + created_at: jetquery.DateTime, + updated_at: jetquery.DateTime, + }, + .{}, +); -pub const Rating = jetquery.Model(@This(), "ratings", struct { +pub const Rating = jetquery.Model( + @This(), + "ratings", + struct { + id: i32, + reference_id: i32, + score: f64, + date: jetquery.DateTime, + created_at: jetquery.DateTime, + updated_at: jetquery.DateTime, + }, + .{}, +); + +pub const RawScrobble = jetquery.Model(@This(), "raw_scrobbles", struct { id: i32, - reference_id: i32, - score: f64, - date: jetquery.DateTime, + track: []const u8, + artist: []const u8, + album: []const u8, + date: i32, created_at: jetquery.DateTime, updated_at: jetquery.DateTime, }, .{}); diff --git a/src/app/database/migrations/2024-11-25_15-32-40_create_raw_scrobbles.zig b/src/app/database/migrations/2024-11-25_15-32-40_create_raw_scrobbles.zig new file mode 100644 index 0000000..12f307d --- /dev/null +++ b/src/app/database/migrations/2024-11-25_15-32-40_create_raw_scrobbles.zig @@ -0,0 +1,22 @@ +const std = @import("std"); +const jetquery = @import("jetquery"); +const t = jetquery.schema.table; + +pub fn up(repo: anytype) !void { + try repo.createTable( + "raw_scrobbles", + &.{ + t.primaryKey("id", .{}), + t.column("track", .string, .{}), + t.column("artist", .string, .{}), + t.column("album", .string, .{}), + t.column("date", .integer, .{}), + t.timestamps(.{}), + }, + .{}, + ); +} + +pub fn down(repo: anytype) !void { + try repo.dropTable("raw_scrobbles", .{}); +} diff --git a/src/app/jobs/process_scrobbles.zig b/src/app/jobs/process_scrobbles.zig new file mode 100644 index 0000000..3f0c191 --- /dev/null +++ b/src/app/jobs/process_scrobbles.zig @@ -0,0 +1,18 @@ +const std = @import("std"); +const jetzig = @import("jetzig"); + +// The `run` function for a job is invoked every time the job is processed by a queue worker +// (or by the Jetzig server if the job is processed in-line). +// +// Arguments: +// * allocator: Arena allocator for use during the job execution process. +// * params: Params assigned to a job (from a request, any values added to `data`). +// * env: Provides the following fields: +// - logger: Logger attached to the same stream as the Jetzig server. +// - environment: Enum of `{ production, development }`. +pub fn run(allocator: std.mem.Allocator, params: *jetzig.data.Value, env: jetzig.jobs.JobEnv) !void { + _ = allocator; + _ = params; + // Job execution code goes here. Add any code that you would like to run in the background. + try env.logger.INFO("Running a job.", .{}); +} diff --git a/src/app/views/partials/_table.zmpl b/src/app/views/partials/_table.zmpl index e69de29..8ea394d 100644 --- a/src/app/views/partials/_table.zmpl +++ b/src/app/views/partials/_table.zmpl @@ -0,0 +1,18 @@ +@args table_data: *ZmplValue, table_headers: *ZmplValue + + + +@for (table_headers) |text| { + +} + + + @for (table_data) |value| { + + + + + + + } +
{{text}}
{{value.track}}{{value.artist}}{{value.album}}{{value.date}}
\ No newline at end of file diff --git a/src/app/views/upload.zig b/src/app/views/upload.zig index 491579c..34df03d 100644 --- a/src/app/views/upload.zig +++ b/src/app/views/upload.zig @@ -4,17 +4,6 @@ const jetquery = @import("jetzig").jetquery; pub fn index(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { _ = data; - try request.repo.insert(.Artist, .{ - .id = 123, - .name = "wilco", - .album_num = 10, - .song_num = 200, - .play_count = 2700, - .avg_album_score = 10.0, - .avg_song_score = 10.0, - .url = "/wilco", - .aliased = false, - }); return request.render(.ok); } @@ -24,8 +13,45 @@ pub fn get(id: []const u8, request: *jetzig.Request, data: *jetzig.Data) !jetzig return request.render(.ok); } -pub fn post(request: *jetzig.Request, data: *jetzig.Data) !jetzig.View { - _ = data; +pub fn post(request: *jetzig.Request) !jetzig.View { + const Scrobble = struct { + track: []u8, + artist: []u8, + album: []u8, + date: i64, + }; + + const lastfm = struct { + username: []u8, + scrobbles: []Scrobble, + }; + + var root = try request.data(.object); + + if (try request.file("upload")) |file| { + const parsed = try std.json.parseFromSlice(lastfm, request.allocator, file.content, .{}); + + const history = parsed.value; + + //std.debug.print("{s}", .{history.scrobbles[19].artist}); + + var scrobbles = try root.put("scrobbles", .array); + for (history.scrobbles) |scrobble| { + try scrobbles.append(scrobble); + + const database_update = jetzig.database.Query(.RawScrobble) + .insert(.{ .track = scrobble.track, .album = scrobble.album, .artist = scrobble.artist, .date = @divFloor(scrobble.date, 1000) }); + + try request.repo.execute(database_update); + } + } + + var upload_table = try root.put("upload_table", .array); + try upload_table.append("Track"); + try upload_table.append("Artist"); + try upload_table.append("Album"); + try upload_table.append("Date"); + return request.render(.created); } diff --git a/src/app/views/upload/index.zmpl b/src/app/views/upload/index.zmpl index 66a79f1..5048944 100644 --- a/src/app/views/upload/index.zmpl +++ b/src/app/views/upload/index.zmpl @@ -1,10 +1,13 @@ + + + @partial partials/header
Upload Last.fm or Spotify history file here (in json format).
-
+ diff --git a/src/app/views/upload/post.zmpl b/src/app/views/upload/post.zmpl index 76457d0..176f094 100644 --- a/src/app/views/upload/post.zmpl +++ b/src/app/views/upload/post.zmpl @@ -1,3 +1,15 @@ -
- Content goes here -
+ + + + + + +@partial partials/header +

File Uploaded Successfully

+ +

Scrobbles Added

+ +@partial partials/table(table_data: .scrobbles, table_headers: .upload_table, table_context: .context) + + + \ No newline at end of file