Kaynağa Gözat

WIP - add filter form to tables pages

Daniel Sheffield 1 yıl önce
ebeveyn
işleme
2610663495

+ 27 - 26
app/rest/form.py

@@ -15,7 +15,12 @@ def get_option_groups(
     k: str, g: str, _type: str
 ):
     in_chart = data['$/unit'].apply(lambda x: (x or False) and True)
-    groups = sorted(set(data[g] if g is not None else []))
+    if k in data:
+        k_data_in_chart = chain(*data[in_chart]["tags"]) if k == "tag" else data[in_chart][k]  
+    else:
+        k_data_in_chart = []
+    
+    groups = sorted(set(data[g] if g is not None and g in data else []))
     groups.append(None)
     if _type == "exclude":
         prefix = "!"
@@ -28,43 +33,39 @@ def get_option_groups(
         if group is None:
             if _type == "include":
                 selected.extend(filter_data[k][0] - (
-                    set((chain(*data[in_chart]["tags"]) if k == "tag" else data[in_chart][k]) if g is not None else set())
+                    set(k_data_in_chart if g is not None else set())
                 ))
                 unselected.extend(((
-                    set((chain(*data[in_chart]["tags"]) if k == "tag" else data[in_chart][k]) if g is None else set())
+                    set(k_data_in_chart if g is None else set())
                 ) | filter_data[k][1]) - filter_data[k][0])
             else:
                 selected.extend(filter_data[k][1])
                 unselected.extend((
-                    set((chain(*data[in_chart]["tags"]) if k == "tag" else data[in_chart][k]) if g is None else set())
+                    set(k_data_in_chart if g is None else set())
                 ) | (
-                    filter_data[k][0] - set(chain(*data[in_chart]["tags"]) if k == "tag" else data[in_chart][k]) - filter_data[k][1]
+                    filter_data[k][0] - set(k_data_in_chart) - filter_data[k][1]
                 ))
         else:
+            k_grouped_data_in_chart = set(data[in_chart & (data[g].apply(lambda x,axis=None: x == group))][k]) if k in data else set()
             if _type == "include":
-                selected.extend(filter_data[k][0] & set(
-                    data[in_chart & (data[g].apply(lambda x,axis=None: x == group))][k]
-                ))
-                unselected.extend(set(
-                    data[in_chart & (data[g].apply(lambda x,axis=None: x == group))][k]
-                ) - filter_data[k][0])
+                selected.extend(filter_data[k][0] & set(k_grouped_data_in_chart))
+                unselected.extend(k_grouped_data_in_chart - filter_data[k][0])
             else:
-                unselected.extend(set(
-                    data[in_chart & (data[g].apply(lambda x,axis=None: x == group))][k]
-                ))
+                unselected.extend(set(k_grouped_data_in_chart))
         assert set(selected) - set(unselected) == set(selected), f"{set(selected)} {set(unselected)}"
-        
-        yield {
-            "optgroup": group,
-            "options": sorted(map(lambda x: {
-                "selected": x[0],
-                "value": f"{prefix}{x[1]}",
-                "display": x[1]  
-            }, chain(
-                map(lambda x: (True, x), set(selected)),
-                map(lambda x: (False, x), set(unselected)),
-            )), key=lambda x: x["display"] if "display" in x else x["value"])
-        }
+        options = sorted(map(lambda x: {
+            "selected": x[0],
+            "value": f"{prefix}{x[1]}",
+            "display": x[1]  
+        }, chain(
+            map(lambda x: (True, x), set(selected)),
+            map(lambda x: (False, x), set(unselected)),
+        )), key=lambda x: x["display"] if "display" in x else x["value"])
+        if len(options) > 0:
+            yield {
+                "optgroup": group,
+                "options": options,
+            }
 
 
 def get_form(action: str, method: str, filter_data, data: DataFrame):

+ 45 - 17
app/rest/pyapi.py

@@ -15,15 +15,20 @@ from bottle import (
     template,
     static_file,
 )
+from pandas import DataFrame
 from psycopg import connect
 from psycopg.sql import SQL, Literal
 from threading import Thread
 
+from app.data.QueryManager import QueryManager, get_data
+
 from ..data.filter import(
     get_filter,
     get_query_param,
 )
-
+from .form import (
+    get_form,
+)
 from ..data.util import(
     get_where_include_exclude
 )
@@ -71,7 +76,6 @@ ORDER BY "Product", "Category", "Group"
 """).format(having=having) if having else SQL('')
     ])
 
-
 def normalize_query(query: FormsDict, allow: Iterable[str] = None) -> str:
     param = get_filter(query, allow=allow)
     return urlencode([
@@ -123,24 +127,29 @@ def trend():
 @normalize
 def groups():
     filters = get_filter(request.query, allow=('group', 'category', 'product'))
-    form = template('form-nav', action='groups', method='get', params=[
-        {'name': k, 'value': request.params[k]} for k in request.params if k in PARAMS
-    ])
+    _filter = get_filter(request.query, allow=PARAMS)
     try:
         with conn.cursor() as cur:
             inner = get_product_rollup_statement(
                 filters,
                 having=SQL("c.name IS NULL")
             )
-            xml = cur.execute(SQL("""
-SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
-""").format(q=Literal(SQL("""SELECT
+            query = SQL("""
+SELECT
     "Products",
     "Categories",
     COALESCE("Group", "Groups"||'') "Group"
 FROM (
 {inner}
-) q""").format(inner=inner).as_string(cur)))).fetchone()[0]
+) q
+""").format(inner=inner)
+            data = DataFrame(list(get_data(cur, query))[:-1])
+            data['$/unit'] = 1
+            data['group'] = data['Group']
+            form = get_form(request.path.split('/')[-1], 'get', _filter, data)
+            xml = cur.execute(SQL("""
+SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
+""").format(q=Literal(query.as_string(cur)))).fetchone()[0]
     finally:
         conn.commit()
     response.content_type = 'application/xhtml+xml; charset=utf-8'
@@ -150,6 +159,7 @@ FROM (
 @normalize
 def categories():
     filters = get_filter(request.query, allow=('group', 'category', 'product'))
+    _filter = get_filter(request.query, allow=PARAMS)
     form = template('form-nav', action='categories', method='get', params=[
         {'name': k, 'value': request.params[k]} for k in request.params if k in PARAMS
     ])
@@ -159,15 +169,23 @@ def categories():
                 filters,
                 having=SQL("p.name IS NULL AND (c.name IS NOT NULL OR g.name IS NULL)")
             )
-            xml = cur.execute(SQL("""
-SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
-""").format(q=Literal(SQL("""SELECT
+            query = SQL("""
+SELECT
     "Products",
     COALESCE("Category", "Categories"||'') "Category",
     COALESCE("Group", "Groups"||'') "Group"
 FROM (
 {inner}
-) q""").format(inner=inner).as_string(cur)))).fetchone()[0]
+) q
+""").format(inner=inner)
+            data = DataFrame(list(get_data(cur, query))[:-1])
+            data['$/unit'] = 1
+            data['group'] = data['Group']
+            data['category'] = data['Category']
+            form = get_form(request.path.split('/')[-1], 'get', _filter, data)
+            xml = cur.execute(SQL("""
+SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
+""").format(q=Literal(query.as_string(cur)))).fetchone()[0]
     finally:
         conn.commit()
     response.content_type = 'application/xhtml+xml; charset=utf-8'
@@ -177,6 +195,7 @@ FROM (
 @normalize
 def products():
     filters = get_filter(request.query, allow=('group', 'category', 'product'))
+    _filter = get_filter(request.query, allow=PARAMS)
     form = template('form-nav', action='products', method='get', params=[
         {'name': k, 'value': request.params[k]} for k in request.params if k in PARAMS
     ])
@@ -186,16 +205,25 @@ def products():
                 filters,
                 having=SQL("p.name IS NOT NULL OR g.name IS NULL")
             )
-            xml = cur.execute(SQL("""
-SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
-""").format(q=Literal(SQL("""SELECT
+            query = SQL("""
+SELECT
     --"Transactions",
     COALESCE("Product", "Products"||'') "Product",
     COALESCE("Category", "Categories"||'') "Category",
     COALESCE("Group", "Groups"||'') "Group"
 FROM (
 {inner}
-) q""").format(inner=inner).as_string(cur)))).fetchone()[0]
+) q
+""").format(inner=inner)
+            data = DataFrame(list(get_data(cur, query))[:-1])
+            data['$/unit'] = 1
+            data['product'] = data['Product']
+            data['group'] = data['Group']
+            data['category'] = data['Category']
+            form = get_form(request.path.split('/')[-1], 'get', _filter, data)
+            xml = cur.execute(SQL("""
+SELECT query_to_xml_and_xmlschema({q}, false, false, ''::text)
+""").format(q=Literal(query.as_string(cur)))).fetchone()[0]
     finally:
         conn.commit()
     response.content_type = 'application/xhtml+xml; charset=utf-8'

+ 19 - 0
app/rest/templates/form-filter.tpl

@@ -1,5 +1,24 @@
 % from app.data.filter import get_query_param
 <form id="filter" method="{{ method }}" action="{{ action }}">
+  <style>
+  select::-webkit-scrollbar {
+  width: 11px;
+}
+select {
+  color: #cccccc;
+  background-color: #080808;
+  scrollbar-width: thin;
+  scrollbar-color: var(--thumbBG) var(--scrollbarBG);
+}
+select::-webkit-scrollbar-track {
+  background: var(--scrollbarBG);
+}
+select::-webkit-scrollbar-thumb {
+  background-color: var(--thumbBG) ;
+  border-radius: 6px;
+  border: 3px solid var(--scrollbarBG);
+}
+  </style>
   % include('button-style')
   % include('button-nav', action=action)
   <details style="padding: 1em 0">

+ 2 - 2
app/rest/templates/select.tpl

@@ -1,11 +1,11 @@
 % from bottle import template
-% multiple = (get("multiple", False) and "multiple") or ""
+% multiple = (get("multiple", False) and 'multiple="true"') or ""
 <div class="pure-u-1">
 %  if defined("label"):
 %    include('label', id=id, label=label)
 %  end
 
-<select id="{{id}}" name="{{name}}" size=10 {{multiple}} style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="{{id}}" name="{{name}}" size="10" {{!multiple}} style="width: calc(100% - 1em); margin: 0 1em 1em">
 %  if defined("hint"):
 %    include('option', value=hint, disabled=True)
 %  end

+ 0 - 17
app/rest/templates/trend.tpl

@@ -10,23 +10,6 @@ body {
   background-color: #080808;
   color: #cccccc;
 }
-select::-webkit-scrollbar {
-  width: 11px;
-}
-select {
-  color: #cccccc;
-  background-color: #080808;
-  scrollbar-width: thin;
-  scrollbar-color: var(--thumbBG) var(--scrollbarBG);
-}
-select::-webkit-scrollbar-track {
-  background: var(--scrollbarBG);
-}
-select::-webkit-scrollbar-thumb {
-  background-color: var(--thumbBG) ;
-  border-radius: 6px;
-  border: 3px solid var(--scrollbarBG);
-}
 
 svg {
   max-height: min(100vh, calc(100vw * 9 / 16));

+ 2 - 2
test/rest/templates/test_include-exclude.py

@@ -12,7 +12,7 @@ from bottle import template
     </div>
 <div class="pure-u-1">
 
-<select id="item-include" name="item" size=10 multiple style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="item-include" name="item" size="10" multiple="true" style="width: calc(100% - 1em); margin: 0 1em 1em">
   <option value="Include" disabled="true" >Include</option>
 
   <option value="val1-to-backend"  >val1</option>
@@ -21,7 +21,7 @@ from bottle import template
 </div>
 <div class="pure-u-1">
 
-<select id="item-exclude" name="item" size=10 multiple style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="item-exclude" name="item" size="10" multiple="true" style="width: calc(100% - 1em); margin: 0 1em 1em">
   <option value="Exclude" disabled="true" >Exclude</option>
 
   <option value="val1-to-backend"  >val1</option>

+ 1 - 1
test/rest/templates/test_select-one.py

@@ -12,7 +12,7 @@ from bottle import template
   </div>
 <div class="pure-u-1">
 
-<select id="unit-select-one" name="unit" size=10  style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="unit-select-one" name="unit" size="10"  style="width: calc(100% - 1em); margin: 0 1em 1em">
 
 
   <option value="Bags"  >Bags</option>

+ 3 - 3
test/rest/templates/test_select.py

@@ -5,7 +5,7 @@ from bottle import template
 @mark.parametrize('expected, params', [
     ("""<div class="pure-u-1">
 <label for="select-id">Choose: </label>
-<select id="select-id" name="select-name" size=10 multiple style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="select-id" name="select-name" size="10" multiple="true" style="width: calc(100% - 1em); margin: 0 1em 1em">
   <option value="hint" disabled="true" >hint</option>
 <optgroup label="Group">
   <option value="val1-to-backend"  >val1</option>
@@ -25,7 +25,7 @@ from bottle import template
     }, ]}, ]}),
     ("""<div class="pure-u-1">
 
-<select id="select-unit-id" name="unit" size=10  style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="select-unit-id" name="unit" size="10"  style="width: calc(100% - 1em); margin: 0 1em 1em">
 
 
   <option value="val1"  >val1</option>
@@ -42,7 +42,7 @@ from bottle import template
     }, ]}, ]}),
     ("""<div class="pure-u-1">
 <label for="select-id">Choose: </label>
-<select id="select-id" name="select-name" size=10 multiple style="width: calc(100% - 1em); margin: 0 1em 1em">
+<select id="select-id" name="select-name" size="10" multiple="true" style="width: calc(100% - 1em); margin: 0 1em 1em">
   <option value="hint" disabled="true" >hint</option>
 <optgroup label="Group">
   <option value="val1-to-backend"  >val1</option>