Dmitry Beresnev commited on
Commit
535bdb9
·
1 Parent(s): a8aef2e

fix news UI

Browse files
Files changed (1) hide show
  1. app/components/news.py +64 -40
app/components/news.py CHANGED
@@ -161,8 +161,8 @@ def display_scrollable_news_section(df: pd.DataFrame, section_title: str, sectio
161
  """, unsafe_allow_html=True)
162
  return
163
 
164
- # Section header
165
- st.markdown(f"""
166
  <div style="
167
  background: linear-gradient(135deg, #2A2E39 0%, #1E222D 100%);
168
  border: 1px solid #363A45;
@@ -172,33 +172,67 @@ def display_scrollable_news_section(df: pd.DataFrame, section_title: str, sectio
172
  ">
173
  <div style="display: flex; justify-content: space-between; align-items: center;">
174
  <div>
175
- <h3 style="
176
- color: #D1D4DC;
177
- margin: 0;
178
- font-size: 18px;
179
- font-weight: 600;
180
- font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif;
181
- ">{section_icon} {section_title}</h3>
182
- <p style="
183
- color: #787B86;
184
- margin: 4px 0 0 0;
185
- font-size: 12px;
186
- ">{section_subtitle}</p>
187
  </div>
188
- <div style="
189
- background: rgba(56, 97, 251, 0.15);
190
- color: #3861FB;
191
- padding: 6px 12px;
192
- border-radius: 6px;
193
- font-size: 13px;
194
- font-weight: 600;
195
- ">{len(df.head(max_items))} stories</div>
196
  </div>
197
  </div>
198
- """, unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
- # Scrollable container with TradingView-style scrollbar
201
- st.markdown(f"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  <style>
203
  .news-scroll-container {{
204
  height: {height};
@@ -209,37 +243,27 @@ def display_scrollable_news_section(df: pd.DataFrame, section_title: str, sectio
209
  border-radius: 0 0 8px 8px;
210
  padding: 16px;
211
  }}
212
-
213
- /* TradingView-style scrollbar */
214
  .news-scroll-container::-webkit-scrollbar {{
215
  width: 8px;
216
  }}
217
-
218
  .news-scroll-container::-webkit-scrollbar-track {{
219
  background: #1E222D;
220
  border-radius: 4px;
221
  }}
222
-
223
  .news-scroll-container::-webkit-scrollbar-thumb {{
224
  background: #363A45;
225
  border-radius: 4px;
226
  }}
227
-
228
  .news-scroll-container::-webkit-scrollbar-thumb:hover {{
229
  background: #434651;
230
  }}
231
  </style>
232
- """, unsafe_allow_html=True)
233
-
234
- # Start scrollable container
235
- st.markdown('<div class="news-scroll-container">', unsafe_allow_html=True)
236
-
237
- # Display news items
238
- for idx, row in df.head(max_items).iterrows():
239
- display_tradingview_news_card(row.to_dict())
240
 
241
- # End scrollable container
242
- st.markdown('</div>', unsafe_allow_html=True)
243
 
244
 
245
  def display_news_feed(df: pd.DataFrame, max_items: int = 20):
 
161
  """, unsafe_allow_html=True)
162
  return
163
 
164
+ # Build header HTML
165
+ header_html = f"""
166
  <div style="
167
  background: linear-gradient(135deg, #2A2E39 0%, #1E222D 100%);
168
  border: 1px solid #363A45;
 
172
  ">
173
  <div style="display: flex; justify-content: space-between; align-items: center;">
174
  <div>
175
+ <h3 style="color: #D1D4DC; margin: 0; font-size: 18px; font-weight: 600;">{section_icon} {section_title}</h3>
176
+ <p style="color: #787B86; margin: 4px 0 0 0; font-size: 12px;">{section_subtitle}</p>
 
 
 
 
 
 
 
 
 
 
177
  </div>
178
+ <div style="background: rgba(56, 97, 251, 0.15); color: #3861FB; padding: 6px 12px; border-radius: 6px; font-size: 13px; font-weight: 600;">{len(df.head(max_items))} stories</div>
 
 
 
 
 
 
 
179
  </div>
180
  </div>
181
+ """
182
+
183
+ # Render header
184
+ st.markdown(header_html, unsafe_allow_html=True)
185
+
186
+ # Build all news cards HTML
187
+ news_cards_html = ""
188
+ for idx, row in df.head(max_items).iterrows():
189
+ news_item = row.to_dict()
190
+
191
+ # Calculate time ago
192
+ time_diff = datetime.now() - news_item['timestamp']
193
+ if time_diff.seconds < 60:
194
+ time_ago = f"{time_diff.seconds}s ago"
195
+ elif time_diff.seconds < 3600:
196
+ time_ago = f"{time_diff.seconds // 60}m ago"
197
+ else:
198
+ hours = time_diff.seconds // 3600
199
+ time_ago = f"{hours}h ago" if hours < 24 else f"{time_diff.days}d ago"
200
+
201
+ # Impact and sentiment colors
202
+ impact_colors = {'high': '#F23645', 'medium': '#FF9800', 'low': '#089981'}
203
+ sentiment_colors = {'positive': '#089981', 'negative': '#F23645', 'neutral': '#787B86'}
204
 
205
+ impact_color = impact_colors.get(news_item['impact'], '#787B86')
206
+ sentiment_color = sentiment_colors.get(news_item['sentiment'], '#787B86')
207
+
208
+ # Escape HTML
209
+ summary = html_module.escape(news_item.get('summary', '').strip())
210
+ source = html_module.escape(news_item['source'])
211
+ category = html_module.escape(news_item['category'])
212
+ url = html_module.escape(news_item['url'])
213
+
214
+ sentiment_symbol = '▲' if news_item['sentiment'] == 'positive' else '▼' if news_item['sentiment'] == 'negative' else '●'
215
+
216
+ # Build card HTML
217
+ news_cards_html += f"""
218
+ <div style="background: linear-gradient(135deg, #1E222D 0%, #131722 100%); border: 1px solid #2A2E39; border-radius: 8px; padding: 16px; margin-bottom: 12px; transition: all 0.2s ease; cursor: pointer; position: relative; overflow: hidden;" onmouseover="this.style.borderColor='#3861FB'; this.style.transform='translateY(-2px)'; this.style.boxShadow='0 4px 12px rgba(56, 97, 251, 0.15)';" onmouseout="this.style.borderColor='#2A2E39'; this.style.transform='translateY(0)'; this.style.boxShadow='none';">
219
+ <div style="position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: {impact_color};"></div>
220
+ <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; margin-left: 8px;">
221
+ <div style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
222
+ <span style="color: #3861FB; font-weight: 600; font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif;">{source}</span>
223
+ <span style="background: {impact_color}; color: white; padding: 2px 8px; border-radius: 4px; font-size: 10px; font-weight: 700; letter-spacing: 0.5px;">{news_item['impact'].upper()}</span>
224
+ <span style="color: {sentiment_color}; font-size: 11px; font-weight: 600; padding: 2px 6px; border: 1px solid {sentiment_color}; border-radius: 4px;">{sentiment_symbol} {news_item['sentiment'].upper()}</span>
225
+ <span style="color: #787B86; font-size: 11px; background: rgba(120, 123, 134, 0.1); padding: 2px 6px; border-radius: 4px;">#{category}</span>
226
+ </div>
227
+ <span style="color: #787B86; font-size: 11px; white-space: nowrap;">{time_ago}</span>
228
+ </div>
229
+ <div style="color: #D1D4DC; font-size: 14px; line-height: 1.5; margin-bottom: 8px; margin-left: 8px; font-family: -apple-system, BlinkMacSystemFont, 'Trebuchet MS', Roboto, Ubuntu, sans-serif;">{summary}</div>
230
+ <a href="{url}" target="_blank" style="color: #3861FB; font-size: 12px; text-decoration: none; margin-left: 8px; display: inline-flex; align-items: center; gap: 4px; font-weight: 500;" onmouseover="this.style.color='#5880FF';" onmouseout="this.style.color='#3861FB';">Read Full Story →</a>
231
+ </div>
232
+ """
233
+
234
+ # Render scrollable container with all news cards using st.markdown
235
+ scrollable_html = f"""
236
  <style>
237
  .news-scroll-container {{
238
  height: {height};
 
243
  border-radius: 0 0 8px 8px;
244
  padding: 16px;
245
  }}
 
 
246
  .news-scroll-container::-webkit-scrollbar {{
247
  width: 8px;
248
  }}
 
249
  .news-scroll-container::-webkit-scrollbar-track {{
250
  background: #1E222D;
251
  border-radius: 4px;
252
  }}
 
253
  .news-scroll-container::-webkit-scrollbar-thumb {{
254
  background: #363A45;
255
  border-radius: 4px;
256
  }}
 
257
  .news-scroll-container::-webkit-scrollbar-thumb:hover {{
258
  background: #434651;
259
  }}
260
  </style>
261
+ <div class="news-scroll-container">
262
+ {news_cards_html}
263
+ </div>
264
+ """
 
 
 
 
265
 
266
+ st.markdown(scrollable_html, unsafe_allow_html=True)
 
267
 
268
 
269
  def display_news_feed(df: pd.DataFrame, max_items: int = 20):