From ad46a10ce6700381163d9bc693fc7a5215358dd0 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Sun, 12 Apr 2026 09:04:49 -0500 Subject: [PATCH] Bug Fix: Uploading a local M3U file with no expiration date set sending the string `"null"` as the `exp_date` field in the `FormData` request, causing a 400 validation error from the API. Null/undefined values are now skipped when building the `FormData` body, matching the behaviour already present in the update path. --- CHANGELOG.md | 1 + frontend/src/api.js | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 658fbfee..d91965c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed +- Fixed uploading a local M3U file with no expiration date set sending the string `"null"` as the `exp_date` field in the `FormData` request, causing a 400 validation error from the API. Null/undefined values are now skipped when building the `FormData` body, matching the behaviour already present in the update path. - Fixed `PATCH /api/channels/channels/edit/bulk/` returning a 500 error when the request body included a `streams` list. The bulk edit handler was iterating `validated_data` directly and calling `setattr(channel, "streams", value)`, which Django prohibits on ManyToMany fields. Also added an `@extend_schema` decorator so the Swagger UI correctly documents the endpoint as accepting a JSON array and shows the `streams` field. (Fixes #883) - Fixed several incorrect or incomplete OpenAPI (`@extend_schema`) schemas across the API: - `POST /api/epg/import/` — request body was undocumented; now correctly shows the `id` field. Description updated from "import" to "refresh" to match frontend and backend terminology. diff --git a/frontend/src/api.js b/frontend/src/api.js index 0e1ae8f9..79d6c435 100644 --- a/frontend/src/api.js +++ b/frontend/src/api.js @@ -1193,6 +1193,7 @@ export default class API { if (values.file) { body = new FormData(); for (const prop in values) { + if (values[prop] === null || values[prop] === undefined) continue; body.append(prop, values[prop]); } } else { @@ -2050,9 +2051,7 @@ export default class API { static async getAvailablePlugins() { try { - const response = await request( - `${host}/api/plugins/repos/available/` - ); + const response = await request(`${host}/api/plugins/repos/available/`); return response.plugins || []; } catch (e) { errorNotification('Failed to retrieve available plugins', e);