broadfield-dev commited on
Commit
72b088e
·
verified ·
1 Parent(s): 38e9099

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +88 -49
templates/index.html CHANGED
@@ -43,8 +43,11 @@
43
  <div class="category-section">
44
  <div class="category-title" onclick="toggleCategory('{{ category }}')">{{ category }} <span class="loading-spinner" id="spinner-{{ category }}" style="display: none;"></span></div>
45
  <div class="tiles" id="category-{{ category }}" data-last-update="0">
 
46
  {% for article in articles %}
47
- <div class="article-tile" data-published="{{ article.published }}" data-id="{{ loop.index }}">
 
 
48
  {% if article.image != "svg" %}
49
  <img src="{{ article.image }}" alt="Article Image">
50
  {% else %}
@@ -57,6 +60,8 @@
57
  <div class="description">{{ article.description }}</div>
58
  <div class="published">Published: {{ article.published }}</div>
59
  </div>
 
 
60
  {% endfor %}
61
  </div>
62
  <div class="tiles" id="all-{{ category }}" style="display: none;"></div>
@@ -73,6 +78,10 @@
73
  let lastUpdate = 0;
74
  let expandedCategories = new Set();
75
 
 
 
 
 
76
  function toggleCategory(category) {
77
  const spinner = document.getElementById(`spinner-${category}`);
78
  const tilesDiv = document.getElementById(`category-${category}`);
@@ -89,21 +98,28 @@
89
  spinner.style.display = 'none';
90
  if (data.articles.length > 0) {
91
  let html = '';
 
92
  data.articles.sort((a, b) => new Date(b.published) - new Date(a.published));
93
  data.articles.forEach((article, index) => {
94
- html += `
95
- <div class="article-tile" data-published="${article.published}" data-id="${index}">
96
- ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
97
- <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
98
- <rect width="100%" height="100%" fill="#e0e0e0"/>
99
- <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
100
- </svg>
101
- `}
102
- <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
103
- <div class="description">${article.description}</div>
104
- <div class="published">Published: ${article.published}</div>
105
- </div>
106
- `;
 
 
 
 
 
 
107
  });
108
  tilesDiv.style.display = 'none';
109
  allTilesDiv.innerHTML = html;
@@ -134,12 +150,14 @@
134
  if (tilesDiv) {
135
  const existingArticles = Array.from(tilesDiv.querySelectorAll('.article-tile'));
136
  let currentIds = new Set(existingArticles.map(a => a.dataset.id));
 
137
  let newHtml = '';
138
  articles.sort((a, b) => new Date(b.published) - new Date(a.published));
139
  articles.slice(0, 10).forEach((article, index) => {
140
- if (!currentIds.has(index.toString())) {
 
141
  newHtml += `
142
- <div class="article-tile" data-published="${article.published}" data-id="${index}">
143
  ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
144
  <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
145
  <rect width="100%" height="100%" fill="#e0e0e0"/>
@@ -151,6 +169,8 @@
151
  <div class="published">Published: ${article.published}</div>
152
  </div>
153
  `;
 
 
154
  }
155
  });
156
  if (newHtml) {
@@ -160,20 +180,27 @@
160
  }
161
  if (allTilesDiv.style.display === 'grid') {
162
  let allNewHtml = '';
 
163
  articles.forEach((article, index) => {
164
- allNewHtml += `
165
- <div class="article-tile" data-published="${article.published}" data-id="${index}">
166
- ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
167
- <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
168
- <rect width="100%" height="100%" fill="#e0e0e0"/>
169
- <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
170
- </svg>
171
- `}
172
- <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
173
- <div class="description">${article.description}</div>
174
- <div class="published">Published: ${article.published}</div>
175
- </div>
176
- `;
 
 
 
 
 
 
177
  });
178
  allTilesDiv.innerHTML = (Array.from(allTilesDiv.querySelectorAll('.article-tile')).map(a => a.outerHTML).join('') + allNewHtml);
179
  const allExpanded = Array.from(allTilesDiv.querySelectorAll('.article-tile'));
@@ -236,27 +263,39 @@
236
  const existingContent = document.querySelectorAll('.category-section');
237
  existingContent.forEach(section => section.remove());
238
 
239
- const categoriesHtml = Object.entries(data.categorized_articles).map(([cat, articles]) => `
240
- <div class="category-section">
241
- <div class="category-title" onclick="toggleCategory('${cat}')">${cat} <span class="loading-spinner" id="spinner-${cat}" style="display: none;"></span></div>
242
- <div class="tiles" id="category-${cat}" data-last-update="0">
243
- ${articles.map((article, index) => `
244
- <div class="article-tile" data-published="${article.published}" data-id="${index}">
245
- ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
246
- <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
247
- <rect width="100%" height="100%" fill="#e0e0e0"/>
248
- <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
249
- </svg>
250
- `}
251
- <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
252
- <div class="description">${article.description}</div>
253
- <div class="published">Published: ${article.published}</div>
254
- </div>
255
- `).join('')}
 
 
 
 
 
 
 
 
 
 
 
 
 
256
  </div>
257
- <div class="tiles" id="all-${cat}" style="display: none;"></div>
258
- </div>
259
- `).join('');
260
  document.querySelector('.search-container').insertAdjacentHTML('afterend', categoriesHtml);
261
  } else {
262
  alert('No results found.');
 
43
  <div class="category-section">
44
  <div class="category-title" onclick="toggleCategory('{{ category }}')">{{ category }} <span class="loading-spinner" id="spinner-{{ category }}" style="display: none;"></span></div>
45
  <div class="tiles" id="category-{{ category }}" data-last-update="0">
46
+ {% set seen_articles = [] %}
47
  {% for article in articles %}
48
+ {% set article_key = article.title + '|' + article.link + '|' + article.published %}
49
+ {% if article_key not in seen_articles %}
50
+ <div class="article-tile" data-published="{{ article.published }}" data-id="{{ loop.index }}" data-key="{{ article_key }}">
51
  {% if article.image != "svg" %}
52
  <img src="{{ article.image }}" alt="Article Image">
53
  {% else %}
 
60
  <div class="description">{{ article.description }}</div>
61
  <div class="published">Published: {{ article.published }}</div>
62
  </div>
63
+ {% do seen_articles.append(article_key) %}
64
+ {% endif %}
65
  {% endfor %}
66
  </div>
67
  <div class="tiles" id="all-{{ category }}" style="display: none;"></div>
 
78
  let lastUpdate = 0;
79
  let expandedCategories = new Set();
80
 
81
+ function getArticleKey(article) {
82
+ return `${article.title}|${article.link}|${article.published}`;
83
+ }
84
+
85
  function toggleCategory(category) {
86
  const spinner = document.getElementById(`spinner-${category}`);
87
  const tilesDiv = document.getElementById(`category-${category}`);
 
98
  spinner.style.display = 'none';
99
  if (data.articles.length > 0) {
100
  let html = '';
101
+ const seenKeys = new Set();
102
  data.articles.sort((a, b) => new Date(b.published) - new Date(a.published));
103
  data.articles.forEach((article, index) => {
104
+ const key = getArticleKey(article);
105
+ if (!seenKeys.has(key)) {
106
+ seenKeys.add(key);
107
+ html += `
108
+ <div class="article-tile" data-published="${article.published}" data-id="${index}" data-key="${key}">
109
+ ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
110
+ <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
111
+ <rect width="100%" height="100%" fill="#e0e0e0"/>
112
+ <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
113
+ </svg>
114
+ `}
115
+ <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
116
+ <div class="description">${article.description}</div>
117
+ <div class="published">Published: ${article.published}</div>
118
+ </div>
119
+ `;
120
+ } else {
121
+ console.warn(`Duplicate article skipped in category ${category}: ${key}`);
122
+ }
123
  });
124
  tilesDiv.style.display = 'none';
125
  allTilesDiv.innerHTML = html;
 
150
  if (tilesDiv) {
151
  const existingArticles = Array.from(tilesDiv.querySelectorAll('.article-tile'));
152
  let currentIds = new Set(existingArticles.map(a => a.dataset.id));
153
+ let currentKeys = new Set(existingArticles.map(a => a.dataset.key));
154
  let newHtml = '';
155
  articles.sort((a, b) => new Date(b.published) - new Date(a.published));
156
  articles.slice(0, 10).forEach((article, index) => {
157
+ const key = getArticleKey(article);
158
+ if (!currentKeys.has(key)) {
159
  newHtml += `
160
+ <div class="article-tile" data-published="${article.published}" data-id="${index}" data-key="${key}">
161
  ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
162
  <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
163
  <rect width="100%" height="100%" fill="#e0e0e0"/>
 
169
  <div class="published">Published: ${article.published}</div>
170
  </div>
171
  `;
172
+ } else {
173
+ console.warn(`Duplicate article skipped in update for ${category}: ${key}`);
174
  }
175
  });
176
  if (newHtml) {
 
180
  }
181
  if (allTilesDiv.style.display === 'grid') {
182
  let allNewHtml = '';
183
+ const allSeenKeys = new Set(Array.from(allTilesDiv.querySelectorAll('.article-tile')).map(a => a.dataset.key));
184
  articles.forEach((article, index) => {
185
+ const key = getArticleKey(article);
186
+ if (!allSeenKeys.has(key)) {
187
+ allSeenKeys.add(key);
188
+ allNewHtml += `
189
+ <div class="article-tile" data-published="${article.published}" data-id="${index}" data-key="${key}">
190
+ ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
191
+ <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
192
+ <rect width="100%" height="100%" fill="#e0e0e0"/>
193
+ <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
194
+ </svg>
195
+ `}
196
+ <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
197
+ <div class="description">${article.description}</div>
198
+ <div class="published">Published: ${article.published}</div>
199
+ </div>
200
+ `;
201
+ } else {
202
+ console.warn(`Duplicate article skipped in expanded view for ${category}: ${key}`);
203
+ }
204
  });
205
  allTilesDiv.innerHTML = (Array.from(allTilesDiv.querySelectorAll('.article-tile')).map(a => a.outerHTML).join('') + allNewHtml);
206
  const allExpanded = Array.from(allTilesDiv.querySelectorAll('.article-tile'));
 
263
  const existingContent = document.querySelectorAll('.category-section');
264
  existingContent.forEach(section => section.remove());
265
 
266
+ const categoriesHtml = Object.entries(data.categorized_articles).map(([cat, articles]) => {
267
+ const seenKeys = new Set();
268
+ const uniqueArticles = articles.filter(article => {
269
+ const key = getArticleKey(article);
270
+ if (seenKeys.has(key)) {
271
+ console.warn(`Duplicate article skipped in search for ${cat}: ${key}`);
272
+ return false;
273
+ }
274
+ seenKeys.add(key);
275
+ return true;
276
+ });
277
+ return `
278
+ <div class="category-section">
279
+ <div class="category-title" onclick="toggleCategory('${cat}')">${cat} <span class="loading-spinner" id="spinner-${cat}" style="display: none;"></span></div>
280
+ <div class="tiles" id="category-${cat}" data-last-update="0">
281
+ ${uniqueArticles.map((article, index) => `
282
+ <div class="article-tile" data-published="${article.published}" data-id="${index}" data-key="${getArticleKey(article)}">
283
+ ${article.image !== "svg" ? `<img src="${article.image}" alt="Article Image">` : `
284
+ <svg width="100%" height="150" xmlns="http://www.w3.org/2000/svg">
285
+ <rect width="100%" height="100%" fill="#e0e0e0"/>
286
+ <text x="50%" y="50%" text-anchor="middle" dy=".3em" fill="#666">No Image</text>
287
+ </svg>
288
+ `}
289
+ <div class="title"><a href="${article.link}" target="_blank">${article.title}</a></div>
290
+ <div class="description">${article.description}</div>
291
+ <div class="published">Published: ${article.published}</div>
292
+ </div>
293
+ `).join('')}
294
+ </div>
295
+ <div class="tiles" id="all-${cat}" style="display: none;"></div>
296
  </div>
297
+ `;
298
+ }).join('');
 
299
  document.querySelector('.search-container').insertAdjacentHTML('afterend', categoriesHtml);
300
  } else {
301
  alert('No results found.');