mirror of https://github.com/gmbrax/Pilgrim.git
Finished The basic Reference System it now parses the references added by the sidebar or written but only saves if the reference is valid
This commit is contained in:
parent
0ec480a851
commit
e492e2c248
|
|
@ -3,32 +3,39 @@ from typing import List
|
||||||
|
|
||||||
from ..models.entry import Entry
|
from ..models.entry import Entry
|
||||||
from ..models.travel_diary import TravelDiary
|
from ..models.travel_diary import TravelDiary
|
||||||
|
from ..models.photo import Photo # ✨ Importe o modelo Photo
|
||||||
|
|
||||||
|
|
||||||
class EntryService:
|
class EntryService:
|
||||||
def __init__(self,session):
|
def __init__(self, session):
|
||||||
self.session = session
|
self.session = session
|
||||||
|
|
||||||
def create(self, travel_diary_id:int, title: str, text: str, date: datetime, ):
|
# ✨ Modifique a assinatura para aceitar a lista de fotos
|
||||||
|
def create(self, travel_diary_id: int, title: str, text: str, date: datetime, photos: List[Photo]):
|
||||||
travel_diary = self.session.query(TravelDiary).filter(TravelDiary.id == travel_diary_id).first()
|
travel_diary = self.session.query(TravelDiary).filter(TravelDiary.id == travel_diary_id).first()
|
||||||
if not travel_diary:
|
if not travel_diary:
|
||||||
return None
|
return None
|
||||||
new_entry = Entry(title,text,date,travel_diary_id)
|
|
||||||
|
new_entry = Entry(title, text, date, travel_diary_id,photos=photos)
|
||||||
|
|
||||||
|
# ✨ Atribua a relação ANTES de adicionar e fazer o commit
|
||||||
|
new_entry.photos = photos
|
||||||
|
|
||||||
self.session.add(new_entry)
|
self.session.add(new_entry)
|
||||||
self.session.commit()
|
self.session.commit()
|
||||||
self.session.refresh(new_entry)
|
self.session.refresh(new_entry)
|
||||||
return new_entry
|
return new_entry
|
||||||
|
|
||||||
def read_by_id(self,entry_id:int)->Entry:
|
def read_by_id(self, entry_id: int) -> Entry:
|
||||||
entry = self.session.query(Entry).filter(Entry.id == entry_id).first()
|
entry = self.session.query(Entry).filter(Entry.id == entry_id).first()
|
||||||
return entry
|
return entry
|
||||||
|
|
||||||
def read_all(self)-> List[Entry]:
|
def read_all(self) -> List[Entry]:
|
||||||
entries = self.session.query(Entry).all()
|
entries = self.session.query(Entry).all()
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
def update(self,entry_src:Entry,entry_dst:Entry) -> Entry | None:
|
def update(self, entry_src: Entry, entry_dst: Entry) -> Entry | None:
|
||||||
original:Entry = self.read_by_id(entry_src.id)
|
original: Entry = self.read_by_id(entry_src.id)
|
||||||
if original:
|
if original:
|
||||||
original.title = entry_dst.title
|
original.title = entry_dst.title
|
||||||
original.text = entry_dst.text
|
original.text = entry_dst.text
|
||||||
|
|
@ -40,7 +47,7 @@ class EntryService:
|
||||||
return original
|
return original
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def delete(self,entry_src:Entry)-> Entry | None:
|
def delete(self, entry_src: Entry) -> Entry | None:
|
||||||
excluded = self.read_by_id(entry_src.id)
|
excluded = self.read_by_id(entry_src.id)
|
||||||
if excluded is not None:
|
if excluded is not None:
|
||||||
self.session.delete(excluded)
|
self.session.delete(excluded)
|
||||||
|
|
|
||||||
|
|
@ -644,7 +644,7 @@ class EditEntryScreen(Screen):
|
||||||
text = self.text_entry.text
|
text = self.text_entry.text
|
||||||
pattern = r"\[\[photo::(\w{8})\]\]"
|
pattern = r"\[\[photo::(\w{8})\]\]"
|
||||||
short_hashes_in_text = set(re.findall(pattern, text))
|
short_hashes_in_text = set(re.findall(pattern, text))
|
||||||
|
self._load_photos_for_diary(self.diary_id)
|
||||||
if not short_hashes_in_text:
|
if not short_hashes_in_text:
|
||||||
return [] # Nenhuma referência, operação válida.
|
return [] # Nenhuma referência, operação válida.
|
||||||
|
|
||||||
|
|
@ -655,7 +655,7 @@ class EditEntryScreen(Screen):
|
||||||
if len(found_photos) == 1:
|
if len(found_photos) == 1:
|
||||||
linked_photos.append(found_photos[0])
|
linked_photos.append(found_photos[0])
|
||||||
else:
|
else:
|
||||||
self.notify(f"❌ Erro: Referência '[{short_hash}]' é inválida ou ambígua!", severity="error", timeout=10)
|
self.notify(f"❌ Erro: Referência '\[{short_hash}\\]' é inválida ou ambígua!", severity="error", timeout=10)
|
||||||
return None # Aborta a operação
|
return None # Aborta a operação
|
||||||
|
|
||||||
return linked_photos
|
return linked_photos
|
||||||
|
|
@ -832,37 +832,42 @@ class EditEntryScreen(Screen):
|
||||||
self._update_sub_header()
|
self._update_sub_header()
|
||||||
|
|
||||||
def action_save(self) -> None:
|
def action_save(self) -> None:
|
||||||
"""Saves the current entry"""
|
"""Salva a entrada após validar e coletar as fotos referenciadas."""
|
||||||
self._get_all_references()
|
photos_to_link = self._get_linked_photos_from_text()
|
||||||
self._validate_references()
|
|
||||||
|
if photos_to_link is None:
|
||||||
|
self.notify("⚠️ Salvamento cancelado. Corrija as referências de fotos.", severity="error")
|
||||||
|
return
|
||||||
|
|
||||||
|
content = self.text_entry.text.strip()
|
||||||
if self.is_new_entry:
|
if self.is_new_entry:
|
||||||
content = self.text_entry.text.strip()
|
|
||||||
if not content:
|
if not content:
|
||||||
self.notify("Empty entry cannot be saved")
|
self.notify("Empty entry cannot be saved")
|
||||||
return
|
return
|
||||||
|
# Passe a lista de fotos para o método de criação
|
||||||
# Schedule async creation
|
self.call_later(self._async_create_entry, content, photos_to_link)
|
||||||
self.call_later(self._async_create_entry, content)
|
|
||||||
else:
|
else:
|
||||||
# Schedule async update
|
# Passe a lista de fotos para o método de atualização
|
||||||
self.call_later(self._async_update_entry)
|
self.call_later(self._async_update_entry, content, photos_to_link)
|
||||||
|
|
||||||
async def _async_create_entry(self, content: str):
|
async def _async_create_entry(self, content: str, photos_to_link: List[Photo]):
|
||||||
"""Creates a new entry asynchronously"""
|
"""Cria uma nova entrada e associa as fotos referenciadas."""
|
||||||
|
service_manager = self.app.service_manager
|
||||||
|
db_session = service_manager.get_db_session()
|
||||||
try:
|
try:
|
||||||
service_manager = self.app.service_manager
|
|
||||||
entry_service = service_manager.get_entry_service()
|
entry_service = service_manager.get_entry_service()
|
||||||
|
|
||||||
current_date = datetime.now()
|
# O service.create deve criar o objeto em memória, mas NÃO fazer o commit ainda.
|
||||||
|
|
||||||
new_entry = entry_service.create(
|
new_entry = entry_service.create(
|
||||||
travel_diary_id=self.diary_id,
|
travel_diary_id=self.diary_id,
|
||||||
title=self.new_entry_title,
|
title=self.new_entry_title,
|
||||||
text=content,
|
text=content,
|
||||||
date=current_date
|
date=datetime.now(),
|
||||||
|
photos=photos_to_link
|
||||||
)
|
)
|
||||||
|
|
||||||
if new_entry:
|
if new_entry:
|
||||||
|
# A partir daqui, é só atualizar a UI como você já fazia
|
||||||
self.entries.append(new_entry)
|
self.entries.append(new_entry)
|
||||||
self.entries.sort(key=lambda x: x.id)
|
self.entries.sort(key=lambda x: x.id)
|
||||||
|
|
||||||
|
|
@ -873,74 +878,47 @@ class EditEntryScreen(Screen):
|
||||||
|
|
||||||
self.is_new_entry = False
|
self.is_new_entry = False
|
||||||
self.has_unsaved_changes = False
|
self.has_unsaved_changes = False
|
||||||
self._original_content = new_entry.text
|
self._original_content = new_entry.text # Pode ser o texto com hashes curtos
|
||||||
self.new_entry_title = "New Entry"
|
self.new_entry_title = "New Entry"
|
||||||
self.next_entry_id = max(entry.id for entry in self.entries) + 1
|
self.next_entry_id = max(entry.id for entry in self.entries) + 1
|
||||||
|
|
||||||
self._update_entry_display()
|
self._update_entry_display()
|
||||||
self.notify(f"New entry '{new_entry.title}' saved successfully!")
|
self.notify(f"✅ Nova entrada '{new_entry.title}' salva com sucesso!")
|
||||||
else:
|
else:
|
||||||
self.notify("Error creating entry")
|
self.notify("❌ Erro ao criar entrada")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.notify(f"Error creating entry: {str(e)}")
|
self.notify(f"❌ Erro ao criar entrada: {str(e)}")
|
||||||
|
|
||||||
|
async def _async_update_entry(self, updated_content: str, photos_to_link: List[Photo]):
|
||||||
|
"""Atualiza uma entrada existente e sua associação de fotos."""
|
||||||
|
service_manager = self.app.service_manager
|
||||||
|
|
||||||
async def _async_update_entry(self):
|
|
||||||
"""Updates the current entry asynchronously"""
|
|
||||||
try:
|
try:
|
||||||
if not self.entries:
|
if not self.entries:
|
||||||
self.notify("No entry to update")
|
self.notify("Nenhuma entrada para atualizar")
|
||||||
return
|
return
|
||||||
|
entry_service = service_manager.get_entry_service()
|
||||||
current_entry = self.entries[self.current_entry_index]
|
current_entry = self.entries[self.current_entry_index]
|
||||||
updated_content = self.text_entry.text
|
entry_result : Entry = Entry(
|
||||||
|
|
||||||
updated_entry = Entry(
|
|
||||||
title=current_entry.title,
|
title=current_entry.title,
|
||||||
text=updated_content,
|
text=updated_content,
|
||||||
|
photos=photos_to_link,
|
||||||
date=current_entry.date,
|
date=current_entry.date,
|
||||||
travel_diary_id=current_entry.fk_travel_diary_id,
|
travel_diary_id=self.diary_id
|
||||||
id=current_entry.id
|
|
||||||
)
|
)
|
||||||
|
entry_service.update(current_entry, entry_result)
|
||||||
|
|
||||||
service_manager = self.app.service_manager
|
# A partir daqui, é só atualizar a UI
|
||||||
entry_service = service_manager.get_entry_service()
|
self.has_unsaved_changes = False
|
||||||
|
self._original_content = updated_content # Pode ser o texto com hashes curtos
|
||||||
result = entry_service.update(current_entry, updated_entry)
|
self._update_sub_header()
|
||||||
|
self.notify(f"✅ Entrada '{current_entry.title}' salva com sucesso!")
|
||||||
if result:
|
|
||||||
current_entry.text = updated_content
|
|
||||||
self.has_unsaved_changes = False
|
|
||||||
self._original_content = updated_content
|
|
||||||
self._update_sub_header()
|
|
||||||
self.notify(f"Entry '{current_entry.title}' saved successfully!")
|
|
||||||
else:
|
|
||||||
self.notify("Error updating entry")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.notify(f"Error updating entry: {str(e)}")
|
# Desfaz as mudanças em caso de erro
|
||||||
def _get_all_references(self):
|
self.notify(f"❌ Erro ao atualizar entrada: {str(e)}")
|
||||||
|
|
||||||
text_content = self.text_entry.text
|
|
||||||
matches = re.findall("(\[\[photo::?(?:\w|\s)*\]\])", text_content)
|
|
||||||
for match in matches:
|
|
||||||
if re.match(r"\[\[photo::\w+\]\]", match):
|
|
||||||
if {'type': 'hash','value':match.replace("[[photo::", "").replace("]]", "").strip()} not in self.references:
|
|
||||||
self.references.append(
|
|
||||||
{'type': 'hash', 'value': match.replace("[[photo::", "").replace("]]", "").strip()})
|
|
||||||
elif re.match(r"\[\[photo:\w+\]\]", match):
|
|
||||||
if {'type': 'name', 'value': match.replace("[[photo:", "").replace("]]", "").strip()} not in self.references:
|
|
||||||
self.references.append(
|
|
||||||
{'type': 'name', 'value': match.replace("[[photo:", "").replace("]]", "").strip()})
|
|
||||||
else:
|
|
||||||
self.references.append({'type': 'unknown', 'value': match})
|
|
||||||
self.notify(f"🔍 Referências encontradas: {str(self.references)}", markup=False)
|
|
||||||
|
|
||||||
def _validate_references(self):
|
|
||||||
photo_service = self.app.service_manager.get_photo_service()
|
|
||||||
for reference in self.references:
|
|
||||||
if reference['type'] == 'hash':
|
|
||||||
pass
|
|
||||||
|
|
||||||
def on_key(self, event):
|
def on_key(self, event):
|
||||||
print("DEBUG: on_key called with", event.key, "sidebar_focused:", self.sidebar_focused, "sidebar_visible:", self.sidebar_visible)
|
print("DEBUG: on_key called with", event.key, "sidebar_focused:", self.sidebar_focused, "sidebar_visible:", self.sidebar_visible)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue