| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import csv
- from dataclasses import dataclass, field
- from urllib.parse import quote, unquote
- EMPTY_FILTER_VALUE = "__empty__"
- EMPTY_FILTER_LABEL = "Ohne Wert"
- def decode_filter_values(value: str | None) -> list[str]:
- """Split the GET-decoded parameter before decoding individual values."""
- return list(dict.fromkeys(decoded for part in (value or "").split(",") if (decoded := unquote(part).strip())))
- def encode_filter_values(values) -> str:
- return ",".join(quote(value, safe="") for value in dict.fromkeys(str(value).strip() for value in values) if value)
- def filter_clauses(config, params, exclude=None):
- clauses, values = [], {}
- for f in config:
- current = params.get(f.name, f.default_value)
- if f.name == exclude or f.filter_type == "hidden" or not current:
- continue
- parameter = f"filter_{f.name.lower()}"
- if f.filter_type == "date":
- operator = "<=" if "bis" in f.name.lower() else ">="
- clauses.append(f"F.[{f.key_column}] {operator} :{parameter}")
- values[parameter] = current
- continue
- parts = decode_filter_values(current)
- terms = []
- for index, part in enumerate(parts):
- key = parameter if len(parts) == 1 else f"{parameter}_{index}"
- if part == EMPTY_FILTER_VALUE:
- terms.append(f"NULLIF(F.[{f.key_column}], '') IS NULL")
- continue
- operator = "=" if f.filter_type == "select" else "LIKE"
- terms.append(f"F.[{f.key_column}] {operator} :{key}")
- values[key] = part if f.filter_type == "select" else f"%{part}%"
- if terms:
- clauses.append("(" + " OR ".join(terms) + ")")
- return clauses, values
- @dataclass
- class FilterConfig:
- name: str
- text: str
- filter_type: str
- width: str
- key_column: str
- value_column: str
- sort_column: str
- visible: bool = True
- default_value: str = ""
- options: dict[str, str] | None = field(default_factory=dict)
- current_value: str | None = None
- @property
- def selected_values(self) -> list[str]:
- return decode_filter_values(self.current_value)
- @property
- def selected_items(self) -> list[dict[str, str]]:
- options = {str(key): str(value) for key, value in (self.options or {}).items()}
- options[EMPTY_FILTER_VALUE] = EMPTY_FILTER_LABEL
- return [{"value": value, "label": options.get(value, value)} for value in self.selected_values]
- @property
- def query_param(self) -> str:
- if self.current_value is None or self.current_value == "":
- if self.default_value is None or self.default_value == "":
- return None
- self.current_value = self.default_value
- if self.filter_type == "date":
- if "bis" in self.name.lower():
- return f" F.[{self.key_column}] <= '{self.current_value}' "
- return f" F.[{self.key_column}] >= '{self.current_value}' "
- # if self.filter_type == "select":
- # return f"{self.key_column} IN ({self.current_value})"
- return f" F.[{self.key_column}] LIKE '%{self.current_value}%' "
- @staticmethod
- def from_dict(
- name: str,
- filter_type: str,
- width: str,
- text: str,
- key_column: str,
- value_column: str,
- sort_column: str,
- default_value: str,
- ) -> "FilterConfig":
- if filter_type not in ["text", "select", "date", "hidden"]:
- filter_type = "text"
- if width not in ["1", "2", "3", "4"]:
- width = "2"
- if not text:
- text = name
- if not key_column:
- key_column = name
- if not value_column:
- value_column = key_column
- if not sort_column:
- sort_column = key_column
- if not default_value:
- default_value = ""
- return FilterConfig(
- name=name,
- text=text,
- filter_type=filter_type,
- width=width,
- key_column=key_column,
- value_column=value_column,
- sort_column=sort_column,
- default_value=default_value,
- )
- filter_type_option = {
- "text": "text",
- "select": "selectedOptionValue",
- "date": "selectedDate",
- "hidden": "selectedOptionValue",
- }
- def import_filter_config(area: str) -> list[FilterConfig]:
- res = []
- with open(f"templates\\{area}\\liste\\config\\liste_filter.csv", "r", newline="", encoding="latin-1") as csvfile:
- reader = csv.DictReader(csvfile, delimiter=";")
- for row in reader:
- config = FilterConfig.from_dict(*row.values())
- res.append(config)
- return res
|