import flet as ft import flet_fastapi from flet import * import requests import json import pandas as pd import elasticsearch_serverless import re import os import pickle def remove_arabic_diacritics(text): diacritics_pattern = re.compile(r'[\u064B-\u065F\u0670\u06D6-\u06ED]') no_diacritics_text = re.sub(diacritics_pattern, '', text) return no_diacritics_text diacritics = re.compile(""" ّ | # Tashdid َ | # Fatha ً | # Tanwin Fath ُ | # Damma ٌ | # Tanwin Damm ِ | # Kasra ٍ | # Tanwin Kasr ْ | # Sukun ـ # Tatwil/Kashida """, re.VERBOSE) def normalize_arabic(text): text = diacritics.sub('', text) text = text.replace('أ', 'ا') text = text.replace('إ', 'ا') text = text.replace('آ', 'ا') text = text.replace('ة', 'ه') text = text.replace('ى', 'ي') return text book_selected = False first_run = 0 client = elasticsearch_serverless.Elasticsearch( "https://e790c240926f48a78eec48ccb79ddcd1.us-central1.gcp.cloud.es.io:443", api_key="MmY2VlpZOEJtVVZGLVJjNHpzRTM6akFlVmM2bHhSVmU1M25qRTIyZy1kUQ" ) with open('books_list.pkl', 'rb') as file: books_list = pickle.load(file) def e_search(query): query = remove_arabic_diacritics(query) query = normalize_arabic(query) j_query = { "size": 500, "query": { "match": { "Text": query } } } response_search = client.search(index="books_jsons_01", body=j_query) unique_books = {} for hit in response_search['hits']['hits']: book = hit['_source']['Book'] page = hit['_source']['Page'] score = hit['_score'] if book not in unique_books: unique_books[book] = {'Pages': {page: score}, 'Count': 1} else: if page not in unique_books[book]['Pages']: unique_books[book]['Pages'][page] = score unique_books[book]['Count'] += 1 book_data = [] for book, info in unique_books.items(): pages = sorted(info['Pages'].items()) book_data.append({'Book': book, 'Pages': [page for page, _ in pages], 'Scores': [score for _, score in pages], 'Count': info['Count']}) df = pd.DataFrame(book_data) df = df.head(12) def get_top_two(row): sorted_row = sorted(zip(row['Pages'], row['Scores']), key=lambda x: x[1], reverse=True) return [page for page, score in sorted_row[:2]] try: df['Top Two Pages'] = df.apply(get_top_two, axis=1) except: pass return df async def main(page: ft.Page): async def e_search_book(query): book_name = book_btn.text query = remove_arabic_diacritics(query) query = normalize_arabic(query) j_query = { "size": 10, "query": { "bool": { "must": [ {"match": {"Text": query}}, {"match": {"Book": book_name}} ] } } } response_search = client.search(index="books_jsons_01", body=j_query) data = [] for hit in response_search['hits']['hits']: book = hit['_source']['Book'] page = hit['_source']['Page'] score = hit['_score'] text = hit['_source']['Text'] data.append({ "Book": book, "Page": page, "Score": score, "Text": text }) df = pd.DataFrame(data) return df async def printer(e, name): query_feild.value = name await page.update_async() async def query_feild_changed(e): datatable_row.visible = False listview.visible = True query_list = books_list list_items_list = [] for book in books_list: if book in query_feild.value: list_items_list.append(ListTile( title=Text(book), leading=Icon(icons.ARROW_RIGHT_SHARP), on_click=printer(e, book) )) # list_items = { # name: ListTile( # title=Text(name), # leading=Icon(icons.ARROW_RIGHT_SHARP), # on_click=lambda e, name=name: printer(e, name) # Capture current value of name # ) # for name in query_list # } str_lower = normalize_arabic(e.control.value) listview.controls = [ list_items_list.get(n) for n in query_list if str_lower in normalize_arabic(n) ] if str_lower else [] await page.update_async() async def send_button(e): global first_run datatable_row.visible = True listview.visible = False if first_run >= 1: res_dt.columns.clear() res_dt.rows.clear() first_run = 1 if not book_selected: e_search_df = e_search(query_feild.value) for i in range(len(e_search_df.columns)): res_dt.columns.append(DataColumn(Text(e_search_df.columns[i]))) for i in range(e_search_df.shape[0]): res_dt.rows.append(DataRow(cells=[ DataCell(Text(e_search_df['Book'][i], width=450)), DataCell(Text(e_search_df['Pages'][i], width=180)), DataCell(Text(e_search_df['Scores'][i], width=180)), DataCell(Text(e_search_df['Count'][i], width=120)), DataCell(Text(e_search_df['Top Two Pages'][i], width=200)) ])) else: e_search_df = await e_search_book(query_feild.value) for i in range(len(e_search_df.columns)): res_dt.columns.append(DataColumn(Text(e_search_df.columns[i]))) for i in range(e_search_df.shape[0]): txt = e_search_df['Text'][i][:80].replace("\n", " ") res_dt.rows.append(DataRow(cells=[ DataCell(Text(e_search_df['Book'][i], width=450)), DataCell(Text(e_search_df['Page'][i], width=180)), DataCell(Text(e_search_df['Score'][i], width=180)), DataCell(Row([Text(f"{txt}...", width=400), IconButton(icon=icons.ARROW_RIGHT_OUTLINED, height=50, on_click=show_book_text)])) ])) await page.update_async() async def book_btn_filter(e): global book_selected book_value = query_feild.value if book_value in books_list: book_btn.text = query_feild.value book_btn.bgcolor = colors.GREEN book_selected = True else: book_btn.text = "No Book Found" book_btn.bgcolor = colors.CYAN book_selected = False await page.update_async() def show_book_text(e): pass res_dt = DataTable( border=border.all(2, "blue"), border_radius=10, column_spacing=10, ) datatable_row = Row([res_dt], alignment=MainAxisAlignment.CENTER) datatable_row.visible = False query_feild = TextField(label="Inquiry", hint_text="Please write your inquiry", expand=True, on_change=query_feild_changed) query_send = FloatingActionButton(icon=icons.SEND, on_click=send_button) book_btn = ElevatedButton(text="Book Filter", height=55, width=180, icon=icons.FILTER, on_click=book_btn_filter, bgcolor=colors.CYAN, color=colors.WHITE, style=ButtonStyle(shape=RoundedRectangleBorder(radius=10))) listview = ListView(expand=1, spacing=10, padding=20) Query_row = Row(controls=[query_feild, book_btn, query_send]) await page.add_async(Query_row, listview, datatable_row) app = flet_fastapi.app(main)