Skip to content

Commit

Permalink
feat(filtering): add backend and frontend functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
parissak authored Jun 13, 2024
1 parent a58f66c commit 047b970
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
51 changes: 51 additions & 0 deletions client/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react';
import { getAllFeedUrls, sendAllFeedUrls } from './services/feed_urls';
import { keepFetching, stopFetching } from './services/fetching-news';
import { sendSearchQuery } from './services/database_queries';
import axios from 'axios';
import './css/index.css';
import {
Expand All @@ -13,12 +14,18 @@ import {
import { Button } from '@/components/ui/button';
import { toast } from 'sonner';
import { ThemeProvider } from './components/ui/theme-provider';
import { Textarea } from './components/ui/textarea';

import QuestionsAccordion from './components/questions-accordion';
import Footer from './components/footer';
import RssInput from './components/rss-input';
import Header from './components/header';

type Article = {
time: string;
url: string;
};

// eslint-disable-next-line react-refresh/only-export-components
export const serverUrl = import.meta.env.PROD
? 'http://localhost:4000'
Expand All @@ -28,13 +35,21 @@ function App() {
const [feedUrls, setFeedUrls] = useState('');
const [isDisabled, setIsDisabled] = useState(false);
const [isFetching, setIsFetching] = useState(false);
const [searchData, setSearchData] = useState<Article[]>([]);
const [searchQuery, setSearchQuery] = useState('');

const handleInputChange = (event: {
target: { value: React.SetStateAction<string> };
}) => {
setFeedUrls(event.target.value);
};

const handleFilterInputChange = (event: {
target: { value: React.SetStateAction<string> };
}) => {
setSearchQuery(event.target.value);
};

const handleSubmit = async () => {
toast.dismiss();
const rssFeeds = feedUrls
Expand Down Expand Up @@ -118,6 +133,11 @@ function App() {
}, toastOptions);
};

const handleSearchQuery = async () => {
const data = await sendSearchQuery(searchQuery);
setSearchData(data);
};

useEffect(() => {
const fetchFeedUrls = async () => {
const feedUrls = await getAllFeedUrls();
Expand Down Expand Up @@ -181,6 +201,37 @@ function App() {
</div>
</Button>

<Textarea
className="h-10 w-full px-3 py-2"
onChange={handleFilterInputChange}
placeholder="Insert search query..."
value={searchQuery}
></Textarea>

<Button
className="p-6 text-base"
variant="outline"
onClick={handleSearchQuery}
>
{' '}
Search
</Button>

<div className="col-span-2">
<ul>
{searchData.map((item, index) => (
<li key={index} className="rounded-md bg-gray-100 px-4 py-2">
<p>
<strong>Time:</strong> {item.time}
</p>
<p>
<strong>URL:</strong> <a href={item.url}>{item.url}</a>
</p>
</li>
))}
</ul>
</div>

<div className="col-span-2 mt-16">
<QuestionsAccordion />
</div>
Expand Down
11 changes: 11 additions & 0 deletions client/src/services/database_queries.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import axios from 'axios';
import { serverUrl } from '../App';

const sendSearchQuery = async (searchQuery: string) => {
const response = await axios.get(`${serverUrl}/api/articles/search`, {
params: { searchQuery: searchQuery }
});
return response.data
};

export { sendSearchQuery };
20 changes: 20 additions & 0 deletions server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
import subprocess
from datetime import datetime

from sqlalchemy import create_engine, MetaData, text

os.makedirs("./rss-fetcher/", exist_ok=True)
engine = create_engine(f'sqlite:///./rss-fetcher/data.db', echo=False)
meta = MetaData()
connection = engine.connect()

app = Flask(__name__, static_folder='static')
CORS(app, resources={r"/*": {"origins": "*"}})

Expand Down Expand Up @@ -69,6 +76,19 @@ def download_articles():
print("Running process and export resulted in failure")
print("Error: ", e.stderr)

@app.route('/api/articles/search', methods=['GET'])
def search_articles():
try:
search_query = request.args.get('searchQuery', '')
stmt = text("SELECT time, url FROM articles WHERE full_text LIKE :word")
stmt = stmt.bindparams(word=f'%{search_query}%')
result = connection.execute(stmt)
rows = result.fetchall()
data = [{"time": time, "url": url} for time, url in rows]
return jsonify(data), 200
except Exception as e:
print("Error: ", e)
return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

0 comments on commit 047b970

Please sign in to comment.