@rmdes/indiekit-endpoint-blogroll 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +3 -0
- package/lib/controllers/sources.js +58 -0
- package/lib/storage/sources.js +6 -2
- package/lib/sync/feedland.js +139 -0
- package/lib/sync/scheduler.js +4 -1
- package/locales/de.json +20 -11
- package/locales/en.json +20 -11
- package/locales/es-419.json +20 -11
- package/locales/es.json +20 -11
- package/locales/fr.json +20 -11
- package/locales/hi.json +20 -11
- package/locales/id.json +20 -11
- package/locales/it.json +20 -11
- package/locales/nl.json +20 -11
- package/locales/pl.json +20 -11
- package/locales/pt-BR.json +20 -11
- package/locales/pt.json +20 -11
- package/locales/sr.json +20 -11
- package/locales/sv.json +20 -11
- package/locales/zh-Hans-CN.json +20 -11
- package/package.json +1 -1
- package/views/blogroll-source-edit.njk +92 -0
package/locales/sr.json
CHANGED
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
"sync": {
|
|
30
|
-
"success": "Synced
|
|
31
|
-
"error": "Sync failed:
|
|
30
|
+
"success": "Synced {{blogs}} blogs, added {{items}} items.",
|
|
31
|
+
"error": "Sync failed: {{error}}",
|
|
32
32
|
"already_running": "A sync is already in progress.",
|
|
33
|
-
"cleared_success": "Cleared and re-synced
|
|
33
|
+
"cleared_success": "Cleared and re-synced {{blogs}} blogs, added {{items}} items."
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
"errors": {
|
|
37
37
|
"title": "Блогови са грешкама",
|
|
38
|
-
"seeAll": "Погледај свих
|
|
38
|
+
"seeAll": "Погледај свих {{count}} блогова са грешкама"
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
"sources": {
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"save": "Сачувај",
|
|
49
49
|
"empty": "Нема конфигурисаних OPML извора. Користите ово за масовни увоз блогова из FreshRSS или других читача довода.",
|
|
50
50
|
"recent": "OPML извори",
|
|
51
|
-
"interval": "Сваких
|
|
51
|
+
"interval": "Сваких {{minutes}} мин",
|
|
52
52
|
"lastSync": "Последња синхронизација",
|
|
53
53
|
"deleteConfirm": "Обрисати овај OPML извор? Блогови увезени из њега ће остати.",
|
|
54
54
|
"created": "OPML извор успешно креиран.",
|
|
55
55
|
"created_synced": "OPML извор успешно креиран и синхронизован.",
|
|
56
|
-
"created_sync_failed": "OPML извор креиран, али синхронизација није успела:
|
|
56
|
+
"created_sync_failed": "OPML извор креиран, али синхронизација није успела: {{error}}",
|
|
57
57
|
"updated": "OPML извор успешно ажуриран.",
|
|
58
58
|
"deleted": "OPML извор успешно обрисан.",
|
|
59
|
-
"synced": "Успешно синхронизовано. Додато:
|
|
59
|
+
"synced": "Успешно синхронизовано. Додато: {{added}}, Ажурирано: {{updated}}",
|
|
60
60
|
"form": {
|
|
61
61
|
"name": "Назив",
|
|
62
62
|
"type": "Тип увоза",
|
|
@@ -70,7 +70,16 @@
|
|
|
70
70
|
"microsubChannel": "Microsub Channel",
|
|
71
71
|
"microsubChannelHint": "Sync feeds from a specific channel, or all channels",
|
|
72
72
|
"categoryPrefix": "Category Prefix",
|
|
73
|
-
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')"
|
|
73
|
+
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')",
|
|
74
|
+
"feedlandInstance": "FeedLand Instance URL",
|
|
75
|
+
"feedlandInstanceHint": "FeedLand instance URL (feedland.com or self-hosted)",
|
|
76
|
+
"feedlandUsername": "FeedLand Username",
|
|
77
|
+
"feedlandUsernameHint": "Your FeedLand screen name",
|
|
78
|
+
"feedlandCategory": "FeedLand Category",
|
|
79
|
+
"feedlandCategoryAll": "All subscriptions",
|
|
80
|
+
"feedlandCategoryHint": "Optional: sync only feeds from a specific category",
|
|
81
|
+
"feedlandLoadCategories": "Load",
|
|
82
|
+
"feedlandRequired": "FeedLand instance URL and username are required"
|
|
74
83
|
}
|
|
75
84
|
},
|
|
76
85
|
|
|
@@ -96,11 +105,11 @@
|
|
|
96
105
|
"clearFilters": "Обриши филтере",
|
|
97
106
|
"deleteConfirm": "Обрисати овај блог и све његове кеширане ставке?",
|
|
98
107
|
"created": "Блог успешно додат.",
|
|
99
|
-
"created_synced": "Блог додат и синхронизован. Преузето
|
|
100
|
-
"created_sync_failed": "Блог додат, али почетно преузимање није успело:
|
|
108
|
+
"created_synced": "Блог додат и синхронизован. Преузето {{items}} ставки.",
|
|
109
|
+
"created_sync_failed": "Блог додат, али почетно преузимање није успело: {{error}}",
|
|
101
110
|
"updated": "Блог успешно ажуриран.",
|
|
102
111
|
"deleted": "Блог успешно обрисан.",
|
|
103
|
-
"refreshed": "Блог освежен. Додато
|
|
112
|
+
"refreshed": "Блог освежен. Додато {{items}} нових ставки.",
|
|
104
113
|
"form": {
|
|
105
114
|
"discoverUrl": "URL веб-сајта",
|
|
106
115
|
"discover": "Открий довод",
|
package/locales/sv.json
CHANGED
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
"sync": {
|
|
30
|
-
"success": "Synced
|
|
31
|
-
"error": "Sync failed:
|
|
30
|
+
"success": "Synced {{blogs}} blogs, added {{items}} items.",
|
|
31
|
+
"error": "Sync failed: {{error}}",
|
|
32
32
|
"already_running": "A sync is already in progress.",
|
|
33
|
-
"cleared_success": "Cleared and re-synced
|
|
33
|
+
"cleared_success": "Cleared and re-synced {{blogs}} blogs, added {{items}} items."
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
"errors": {
|
|
37
37
|
"title": "Bloggar med fel",
|
|
38
|
-
"seeAll": "Se alla
|
|
38
|
+
"seeAll": "Se alla {{count}} bloggar med fel"
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
"sources": {
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"save": "Spara",
|
|
49
49
|
"empty": "Inga OPML-källor konfigurerade. Använd detta för att massimportera bloggar från FreshRSS eller andra flödesläsare.",
|
|
50
50
|
"recent": "OPML-källor",
|
|
51
|
-
"interval": "Varje
|
|
51
|
+
"interval": "Varje {{minutes}} min",
|
|
52
52
|
"lastSync": "Senast synkroniserad",
|
|
53
53
|
"deleteConfirm": "Ta bort denna OPML-källa? Bloggar importerade från den kommer att finnas kvar.",
|
|
54
54
|
"created": "OPML-källa skapad.",
|
|
55
55
|
"created_synced": "OPML-källa skapad och synkroniserad.",
|
|
56
|
-
"created_sync_failed": "OPML-källa skapad, men synkronisering misslyckades:
|
|
56
|
+
"created_sync_failed": "OPML-källa skapad, men synkronisering misslyckades: {{error}}",
|
|
57
57
|
"updated": "OPML-källa uppdaterad.",
|
|
58
58
|
"deleted": "OPML-källa borttagen.",
|
|
59
|
-
"synced": "Synkronisering lyckades. Tillagda:
|
|
59
|
+
"synced": "Synkronisering lyckades. Tillagda: {{added}}, Uppdaterade: {{updated}}",
|
|
60
60
|
"form": {
|
|
61
61
|
"name": "Namn",
|
|
62
62
|
"type": "Importtyp",
|
|
@@ -70,7 +70,16 @@
|
|
|
70
70
|
"microsubChannel": "Microsub Channel",
|
|
71
71
|
"microsubChannelHint": "Sync feeds from a specific channel, or all channels",
|
|
72
72
|
"categoryPrefix": "Category Prefix",
|
|
73
|
-
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')"
|
|
73
|
+
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')",
|
|
74
|
+
"feedlandInstance": "FeedLand Instance URL",
|
|
75
|
+
"feedlandInstanceHint": "FeedLand instance URL (feedland.com or self-hosted)",
|
|
76
|
+
"feedlandUsername": "FeedLand Username",
|
|
77
|
+
"feedlandUsernameHint": "Your FeedLand screen name",
|
|
78
|
+
"feedlandCategory": "FeedLand Category",
|
|
79
|
+
"feedlandCategoryAll": "All subscriptions",
|
|
80
|
+
"feedlandCategoryHint": "Optional: sync only feeds from a specific category",
|
|
81
|
+
"feedlandLoadCategories": "Load",
|
|
82
|
+
"feedlandRequired": "FeedLand instance URL and username are required"
|
|
74
83
|
}
|
|
75
84
|
},
|
|
76
85
|
|
|
@@ -96,11 +105,11 @@
|
|
|
96
105
|
"clearFilters": "Rensa filter",
|
|
97
106
|
"deleteConfirm": "Ta bort denna blogg och alla dess cachade poster?",
|
|
98
107
|
"created": "Blogg tillagd.",
|
|
99
|
-
"created_synced": "Blogg tillagd och synkroniserad. Hämtade
|
|
100
|
-
"created_sync_failed": "Blogg tillagd, men initial hämtning misslyckades:
|
|
108
|
+
"created_synced": "Blogg tillagd och synkroniserad. Hämtade {{items}} poster.",
|
|
109
|
+
"created_sync_failed": "Blogg tillagd, men initial hämtning misslyckades: {{error}}",
|
|
101
110
|
"updated": "Blogg uppdaterad.",
|
|
102
111
|
"deleted": "Blogg borttagen.",
|
|
103
|
-
"refreshed": "Blogg uppdaterad. Lade till
|
|
112
|
+
"refreshed": "Blogg uppdaterad. Lade till {{items}} nya poster.",
|
|
104
113
|
"form": {
|
|
105
114
|
"discoverUrl": "Webbplats-URL",
|
|
106
115
|
"discover": "Upptäck flöde",
|
package/locales/zh-Hans-CN.json
CHANGED
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
},
|
|
28
28
|
|
|
29
29
|
"sync": {
|
|
30
|
-
"success": "Synced
|
|
31
|
-
"error": "Sync failed:
|
|
30
|
+
"success": "Synced {{blogs}} blogs, added {{items}} items.",
|
|
31
|
+
"error": "Sync failed: {{error}}",
|
|
32
32
|
"already_running": "A sync is already in progress.",
|
|
33
|
-
"cleared_success": "Cleared and re-synced
|
|
33
|
+
"cleared_success": "Cleared and re-synced {{blogs}} blogs, added {{items}} items."
|
|
34
34
|
},
|
|
35
35
|
|
|
36
36
|
"errors": {
|
|
37
37
|
"title": "有错误的博客",
|
|
38
|
-
"seeAll": "查看所有
|
|
38
|
+
"seeAll": "查看所有 {{count}} 个有错误的博客"
|
|
39
39
|
},
|
|
40
40
|
|
|
41
41
|
"sources": {
|
|
@@ -48,15 +48,15 @@
|
|
|
48
48
|
"save": "保存",
|
|
49
49
|
"empty": "未配置 OPML 源。使用此功能从 FreshRSS 或其他订阅阅读器批量导入博客。",
|
|
50
50
|
"recent": "OPML 源",
|
|
51
|
-
"interval": "每
|
|
51
|
+
"interval": "每 {{minutes}} 分钟",
|
|
52
52
|
"lastSync": "最后同步",
|
|
53
53
|
"deleteConfirm": "删除此 OPML 源?从中导入的博客将保留。",
|
|
54
54
|
"created": "OPML 源创建成功。",
|
|
55
55
|
"created_synced": "OPML 源创建并同步成功。",
|
|
56
|
-
"created_sync_failed": "OPML
|
|
56
|
+
"created_sync_failed": "OPML 源已创建,但同步失败:{{error}}",
|
|
57
57
|
"updated": "OPML 源更新成功。",
|
|
58
58
|
"deleted": "OPML 源删除成功。",
|
|
59
|
-
"synced": "
|
|
59
|
+
"synced": "同步成功。已添加:{{added}},已更新:{{updated}}",
|
|
60
60
|
"form": {
|
|
61
61
|
"name": "名称",
|
|
62
62
|
"type": "导入类型",
|
|
@@ -70,7 +70,16 @@
|
|
|
70
70
|
"microsubChannel": "Microsub Channel",
|
|
71
71
|
"microsubChannelHint": "Sync feeds from a specific channel, or all channels",
|
|
72
72
|
"categoryPrefix": "Category Prefix",
|
|
73
|
-
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')"
|
|
73
|
+
"categoryPrefixHint": "Optional prefix for blog categories (e.g., 'Following: ')",
|
|
74
|
+
"feedlandInstance": "FeedLand Instance URL",
|
|
75
|
+
"feedlandInstanceHint": "FeedLand instance URL (feedland.com or self-hosted)",
|
|
76
|
+
"feedlandUsername": "FeedLand Username",
|
|
77
|
+
"feedlandUsernameHint": "Your FeedLand screen name",
|
|
78
|
+
"feedlandCategory": "FeedLand Category",
|
|
79
|
+
"feedlandCategoryAll": "All subscriptions",
|
|
80
|
+
"feedlandCategoryHint": "Optional: sync only feeds from a specific category",
|
|
81
|
+
"feedlandLoadCategories": "Load",
|
|
82
|
+
"feedlandRequired": "FeedLand instance URL and username are required"
|
|
74
83
|
}
|
|
75
84
|
},
|
|
76
85
|
|
|
@@ -96,11 +105,11 @@
|
|
|
96
105
|
"clearFilters": "清除筛选",
|
|
97
106
|
"deleteConfirm": "删除此博客及其所有缓存条目?",
|
|
98
107
|
"created": "博客添加成功。",
|
|
99
|
-
"created_synced": "博客已添加并同步。获取了
|
|
100
|
-
"created_sync_failed": "
|
|
108
|
+
"created_synced": "博客已添加并同步。获取了 {{items}} 个条目。",
|
|
109
|
+
"created_sync_failed": "博客已添加,但初始获取失败:{{error}}",
|
|
101
110
|
"updated": "博客更新成功。",
|
|
102
111
|
"deleted": "博客删除成功。",
|
|
103
|
-
"refreshed": "博客已刷新。添加了
|
|
112
|
+
"refreshed": "博客已刷新。添加了 {{items}} 个新条目。",
|
|
104
113
|
"form": {
|
|
105
114
|
"discoverUrl": "网站 URL",
|
|
106
115
|
"discover": "发现订阅源",
|
package/package.json
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
{% if microsubAvailable %}
|
|
16
16
|
<option value="microsub" {% if source.type == 'microsub' %}selected{% endif %}>Microsub Subscriptions</option>
|
|
17
17
|
{% endif %}
|
|
18
|
+
<option value="feedland" {% if source.type == 'feedland' %}selected{% endif %}>FeedLand</option>
|
|
18
19
|
</select>
|
|
19
20
|
<span class="hint">{{ __("blogroll.sources.form.typeHint") }}</span>
|
|
20
21
|
</div>
|
|
@@ -48,6 +49,32 @@
|
|
|
48
49
|
<span class="hint">{{ __("blogroll.sources.form.categoryPrefixHint") | default("Optional prefix for blog categories (e.g., 'Following: ')") }}</span>
|
|
49
50
|
</div>
|
|
50
51
|
|
|
52
|
+
<div class="blogroll-field" id="feedlandInstanceField" style="display: none;">
|
|
53
|
+
<label class="label" for="feedlandInstance">{{ __("blogroll.sources.form.feedlandInstance") | default("FeedLand Instance URL") }}</label>
|
|
54
|
+
<input class="input" type="url" id="feedlandInstance" name="feedlandInstance" value="{{ source.feedlandInstance if source else 'https://feedland.com' }}" placeholder="https://feedland.com">
|
|
55
|
+
<span class="hint">{{ __("blogroll.sources.form.feedlandInstanceHint") | default("FeedLand instance URL (feedland.com or self-hosted)") }}</span>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="blogroll-field" id="feedlandUsernameField" style="display: none;">
|
|
59
|
+
<label class="label" for="feedlandUsername">{{ __("blogroll.sources.form.feedlandUsername") | default("FeedLand Username") }}</label>
|
|
60
|
+
<input class="input" type="text" id="feedlandUsername" name="feedlandUsername" value="{{ source.feedlandUsername if source else '' }}" placeholder="e.g., davewiner">
|
|
61
|
+
<span class="hint">{{ __("blogroll.sources.form.feedlandUsernameHint") | default("Your FeedLand screen name") }}</span>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<div class="blogroll-field" id="feedlandCategoryField" style="display: none;">
|
|
65
|
+
<label class="label" for="feedlandCategory">{{ __("blogroll.sources.form.feedlandCategory") | default("FeedLand Category") }}</label>
|
|
66
|
+
<div style="display: flex; gap: 0.5rem; align-items: flex-start;">
|
|
67
|
+
<select class="select" id="feedlandCategory" name="feedlandCategory" style="flex: 1;">
|
|
68
|
+
<option value="">{{ __("blogroll.sources.form.feedlandCategoryAll") | default("All subscriptions") }}</option>
|
|
69
|
+
{% if source.feedlandCategory %}
|
|
70
|
+
<option value="{{ source.feedlandCategory }}" selected>{{ source.feedlandCategory }}</option>
|
|
71
|
+
{% endif %}
|
|
72
|
+
</select>
|
|
73
|
+
<button type="button" class="button button--secondary" onclick="loadFeedlandCategories()" id="feedlandLoadBtn">{{ __("blogroll.sources.form.feedlandLoadCategories") | default("Load") }}</button>
|
|
74
|
+
</div>
|
|
75
|
+
<span class="hint" id="feedlandCategoryHint">{{ __("blogroll.sources.form.feedlandCategoryHint") | default("Optional: sync only feeds from a specific category") }}</span>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
51
78
|
<div class="blogroll-field">
|
|
52
79
|
<label class="label" for="syncInterval">{{ __("blogroll.sources.form.syncInterval") }}</label>
|
|
53
80
|
<select class="select" id="syncInterval" name="syncInterval">
|
|
@@ -78,12 +105,18 @@ function toggleTypeFields() {
|
|
|
78
105
|
const opmlContentField = document.getElementById('opmlContentField');
|
|
79
106
|
const microsubChannelField = document.getElementById('microsubChannelField');
|
|
80
107
|
const categoryPrefixField = document.getElementById('categoryPrefixField');
|
|
108
|
+
const feedlandInstanceField = document.getElementById('feedlandInstanceField');
|
|
109
|
+
const feedlandUsernameField = document.getElementById('feedlandUsernameField');
|
|
110
|
+
const feedlandCategoryField = document.getElementById('feedlandCategoryField');
|
|
81
111
|
|
|
82
112
|
// Hide all type-specific fields first
|
|
83
113
|
urlField.style.display = 'none';
|
|
84
114
|
opmlContentField.style.display = 'none';
|
|
85
115
|
if (microsubChannelField) microsubChannelField.style.display = 'none';
|
|
86
116
|
if (categoryPrefixField) categoryPrefixField.style.display = 'none';
|
|
117
|
+
if (feedlandInstanceField) feedlandInstanceField.style.display = 'none';
|
|
118
|
+
if (feedlandUsernameField) feedlandUsernameField.style.display = 'none';
|
|
119
|
+
if (feedlandCategoryField) feedlandCategoryField.style.display = 'none';
|
|
87
120
|
|
|
88
121
|
// Show fields based on type
|
|
89
122
|
if (type === 'opml_url') {
|
|
@@ -93,7 +126,66 @@ function toggleTypeFields() {
|
|
|
93
126
|
} else if (type === 'microsub') {
|
|
94
127
|
if (microsubChannelField) microsubChannelField.style.display = 'flex';
|
|
95
128
|
if (categoryPrefixField) categoryPrefixField.style.display = 'flex';
|
|
129
|
+
} else if (type === 'feedland') {
|
|
130
|
+
if (feedlandInstanceField) feedlandInstanceField.style.display = 'flex';
|
|
131
|
+
if (feedlandUsernameField) feedlandUsernameField.style.display = 'flex';
|
|
132
|
+
if (feedlandCategoryField) feedlandCategoryField.style.display = 'flex';
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function loadFeedlandCategories() {
|
|
137
|
+
const instance = document.getElementById('feedlandInstance').value;
|
|
138
|
+
const username = document.getElementById('feedlandUsername').value;
|
|
139
|
+
const select = document.getElementById('feedlandCategory');
|
|
140
|
+
const btn = document.getElementById('feedlandLoadBtn');
|
|
141
|
+
const hint = document.getElementById('feedlandCategoryHint');
|
|
142
|
+
const currentValue = select.value;
|
|
143
|
+
|
|
144
|
+
if (!instance || !username) {
|
|
145
|
+
hint.textContent = 'Please enter instance URL and username first';
|
|
146
|
+
return;
|
|
96
147
|
}
|
|
148
|
+
|
|
149
|
+
btn.disabled = true;
|
|
150
|
+
btn.textContent = '...';
|
|
151
|
+
hint.textContent = 'Loading categories...';
|
|
152
|
+
|
|
153
|
+
const baseUrl = '{{ baseUrl }}';
|
|
154
|
+
const url = baseUrl + '/api/feedland-categories?instance=' + encodeURIComponent(instance) + '&username=' + encodeURIComponent(username);
|
|
155
|
+
|
|
156
|
+
fetch(url, { credentials: 'same-origin' })
|
|
157
|
+
.then(function(r) { return r.json(); })
|
|
158
|
+
.then(function(data) {
|
|
159
|
+
if (data.error) {
|
|
160
|
+
hint.textContent = 'Error: ' + data.error;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Clear existing options and rebuild safely using DOM methods
|
|
165
|
+
while (select.options.length > 0) select.remove(0);
|
|
166
|
+
var allOpt = document.createElement('option');
|
|
167
|
+
allOpt.value = '';
|
|
168
|
+
allOpt.textContent = '{{ __("blogroll.sources.form.feedlandCategoryAll") | default("All subscriptions") }}';
|
|
169
|
+
select.appendChild(allOpt);
|
|
170
|
+
|
|
171
|
+
var cats = data.categories || [];
|
|
172
|
+
cats.forEach(function(cat) {
|
|
173
|
+
var opt = document.createElement('option');
|
|
174
|
+
opt.value = cat;
|
|
175
|
+
opt.textContent = cat;
|
|
176
|
+
if (cat === currentValue) opt.selected = true;
|
|
177
|
+
select.appendChild(opt);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
hint.textContent = cats.length + ' categories found' + (data.screenname ? ' for ' + data.screenname : '');
|
|
181
|
+
})
|
|
182
|
+
.catch(function(err) {
|
|
183
|
+
hint.textContent = 'Failed to load: ' + err.message;
|
|
184
|
+
})
|
|
185
|
+
.finally(function() {
|
|
186
|
+
btn.disabled = false;
|
|
187
|
+
btn.textContent = '{{ __("blogroll.sources.form.feedlandLoadCategories") | default("Load") }}';
|
|
188
|
+
});
|
|
97
189
|
}
|
|
98
190
|
|
|
99
191
|
// Initialize on load
|