Source code for timApp.document.editing.editrequest

from dataclasses import dataclass, field
from typing import Optional

from timApp.auth.accesshelper import has_view_access
from timApp.document.docentry import DocEntry
from timApp.document.docparagraph import DocParagraph
from timApp.document.document import Document
from timApp.document.exceptions import ValidationException
from timApp.document.version import Version
from timApp.document.viewcontext import ViewRoute, viewroute_from_str
from timApp.util.flask.requesthelper import verify_json_params


[docs]@dataclass class EditRequest: doc: Document area_start: str | None = None area_end: str | None = None par: str | None = None text: str | None = None next_par_id: str | None = None preview: bool = False forced_classes: list[str] = field(default_factory=list) mark_translated: bool | None = None viewname: ViewRoute | None = None old_doc_version: Version = field(init=False) editor_pars: list[DocParagraph] | None = field(init=False) original_par: DocParagraph | None = field(init=False) context_par: DocParagraph | None = field(init=False) def __post_init__(self): self.old_doc_version = self.doc.get_version() self.editor_pars = None self.original_par = ( self.doc.get_paragraph(self.par) if not self.editing_area and self.par is not None and not self.is_adding else None ) self.context_par = self.get_context_par() @property def is_adding(self): return self.par in ("HELP_PAR",) or self.par is None @property def editing_area(self) -> bool: return self.area_start is not None and self.area_end is not None
[docs] def get_original_par(self) -> DocParagraph | None: return self.original_par
[docs] def get_last_of_preamble(self) -> DocParagraph | None: preamble = self.doc.insert_preamble_pars() # TODO could be optimized return preamble[-1] if preamble else None
[docs] def get_context_par(self) -> DocParagraph: doc = self.doc if self.editing_area: context_par = doc.get_previous_par_by_id(self.area_start) elif not self.is_adding: context_par = doc.get_previous_par_by_id(self.par) if context_par is None: return self.get_last_of_preamble() elif self.next_par_id: context_par = doc.get_previous_par_by_id(self.next_par_id) if context_par is None: return self.get_last_of_preamble() else: context_par = doc.get_last_par() return context_par
[docs] def get_pars(self, skip_access_check: bool = False): if self.editor_pars is None: self.editor_pars = get_pars_from_editor_text( self.doc, self.text, break_on_elements=self.editing_area, skip_access_check=skip_access_check, ) for c in self.forced_classes: for p in self.editor_pars: p.add_class(c) return self.editor_pars
[docs] @staticmethod def from_request( doc: Document, text: str | None = None, preview: bool = False ) -> "EditRequest": if text is None: (text,) = verify_json_params("text") ( area_start, area_end, par, par_next, forced_classes, tags, view, ) = verify_json_params( "area_start", "area_end", "par", "par_next", "forced_classes", "tags", "view", require=False, ) mark_translated = tags.get("marktranslated") if tags else None return EditRequest( doc=doc, text=text, area_start=area_start, area_end=area_end, par=par, next_par_id=par_next, preview=preview, forced_classes=forced_classes or [], mark_translated=mark_translated, viewname=viewroute_from_str(view) if view else None, )
[docs]def get_pars_from_editor_text( doc: Document, text: str, break_on_elements: bool = False, skip_access_check: bool = False, ) -> list[DocParagraph]: blocks, _ = doc.text_to_paragraphs(text, break_on_elements) for p in blocks: if p.is_reference(): try: refdoc = int(p.get_attr("rd")) except (ValueError, TypeError): continue d = DocEntry.find_by_id(refdoc) if not skip_access_check and d and not has_view_access(d): raise ValidationException( f"You don't have view access to document {refdoc}" ) return blocks