refactor: rename Sources to OPML Sync, remove Manual type

- Remove 'Manual' source type (redundant with Blogs management)
- Rename 'Sources' to 'OPML Sync' for clarity
- Update labels to clarify URL syncs periodically, File is one-time import
- Fix date conversion in sources list controller

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ricardo
2026-02-07 17:38:19 +01:00
parent 4a53f74bbc
commit 87ebebfb7a
4 changed files with 44 additions and 44 deletions
+11 -7
View File
@@ -20,7 +20,17 @@ async function list(request, response) {
const { application } = request.app.locals; const { application } = request.app.locals;
try { try {
const sources = await getSources(application); const rawSources = await getSources(application);
// Convert Date objects to ISO strings for template date filter compatibility
const sources = rawSources.map((source) => ({
...source,
lastSyncAt: source.lastSyncAt
? (source.lastSyncAt instanceof Date
? source.lastSyncAt.toISOString()
: source.lastSyncAt)
: null,
}));
response.render("blogroll-sources", { response.render("blogroll-sources", {
title: request.__("blogroll.sources.title"), title: request.__("blogroll.sources.title"),
@@ -83,7 +93,6 @@ async function create(request, response) {
}); });
// Trigger initial sync for OPML sources // Trigger initial sync for OPML sources
if (source.type === "opml_url" || source.type === "opml_file") {
try { try {
await syncOpmlSource(application, source); await syncOpmlSource(application, source);
request.session.messages = [ request.session.messages = [
@@ -99,11 +108,6 @@ async function create(request, response) {
}, },
]; ];
} }
} else {
request.session.messages = [
{ type: "success", content: request.__("blogroll.sources.created") },
];
}
response.redirect(`${request.baseUrl}/sources`); response.redirect(`${request.baseUrl}/sources`);
} catch (error) { } catch (error) {
+18 -18
View File
@@ -32,30 +32,30 @@
}, },
"sources": { "sources": {
"title": "Sources", "title": "OPML Sync",
"manage": "Manage Sources", "manage": "OPML Sync",
"add": "Add Source", "add": "Add OPML Source",
"new": "New Source", "new": "New OPML Source",
"edit": "Edit Source", "edit": "Edit OPML Source",
"create": "Create Source", "create": "Create",
"save": "Save Source", "save": "Save",
"empty": "No sources configured yet.", "empty": "No OPML sources configured. Use this to bulk-import blogs from FreshRSS or other feed readers.",
"recent": "Recent Sources", "recent": "OPML Sources",
"interval": "Every %{minutes} min", "interval": "Every %{minutes} min",
"lastSync": "Last synced", "lastSync": "Last synced",
"deleteConfirm": "Delete this source? Blogs imported from it will remain.", "deleteConfirm": "Delete this OPML source? Blogs imported from it will remain.",
"created": "Source created successfully.", "created": "OPML source created successfully.",
"created_synced": "Source created and synced successfully.", "created_synced": "OPML source created and synced successfully.",
"created_sync_failed": "Source created, but sync failed: %{error}", "created_sync_failed": "OPML source created, but sync failed: %{error}",
"updated": "Source updated successfully.", "updated": "OPML source updated successfully.",
"deleted": "Source deleted successfully.", "deleted": "OPML source deleted successfully.",
"synced": "Synced successfully. Added: %{added}, Updated: %{updated}", "synced": "Synced successfully. Added: %{added}, Updated: %{updated}",
"form": { "form": {
"name": "Name", "name": "Name",
"type": "Type", "type": "Import Type",
"typeHint": "How to import blogs from this source", "typeHint": "URL syncs periodically, File is a one-time import",
"url": "OPML URL", "url": "OPML URL",
"urlHint": "URL of the OPML file to import", "urlHint": "URL to your OPML file (e.g., FreshRSS export URL)",
"opmlContent": "OPML Content", "opmlContent": "OPML Content",
"opmlContentHint": "Paste the full OPML XML content here", "opmlContentHint": "Paste the full OPML XML content here",
"syncInterval": "Sync Interval", "syncInterval": "Sync Interval",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@rmdes/indiekit-endpoint-blogroll", "name": "@rmdes/indiekit-endpoint-blogroll",
"version": "1.0.4", "version": "1.0.5",
"description": "Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.", "description": "Blogroll endpoint for Indiekit. Aggregates blog feeds from OPML, JSON feeds, or manual entry.",
"keywords": [ "keywords": [
"indiekit", "indiekit",
+2 -6
View File
@@ -78,9 +78,8 @@
<div class="br-field"> <div class="br-field">
<label for="type">{{ __("blogroll.sources.form.type") }}</label> <label for="type">{{ __("blogroll.sources.form.type") }}</label>
<select id="type" name="type" required onchange="toggleTypeFields()"> <select id="type" name="type" required onchange="toggleTypeFields()">
<option value="opml_url" {% if source.type == 'opml_url' %}selected{% endif %}>OPML URL</option> <option value="opml_url" {% if source.type == 'opml_url' %}selected{% endif %}>OPML URL (auto-sync)</option>
<option value="opml_file" {% if source.type == 'opml_file' %}selected{% endif %}>OPML File (paste content)</option> <option value="opml_file" {% if source.type == 'opml_file' %}selected{% endif %}>OPML File (one-time import)</option>
<option value="manual" {% if source.type == 'manual' %}selected{% endif %}>Manual (add blogs individually)</option>
</select> </select>
<span class="br-field-hint">{{ __("blogroll.sources.form.typeHint") }}</span> <span class="br-field-hint">{{ __("blogroll.sources.form.typeHint") }}</span>
</div> </div>
@@ -134,9 +133,6 @@ function toggleTypeFields() {
} else if (type === 'opml_file') { } else if (type === 'opml_file') {
urlField.style.display = 'none'; urlField.style.display = 'none';
opmlContentField.style.display = 'flex'; opmlContentField.style.display = 'flex';
} else {
urlField.style.display = 'none';
opmlContentField.style.display = 'none';
} }
} }