LIST / GRAPH FILTERING SORTING AND PAGING

This all applies equally to a report or a list or a graph so all work basically the same but will refer only to "list" for simplicity:

At client user can view a list and select from a dropdown of saved filters for that type of list which corresponds to an api route.
User creates filters in separate UI from the actual list, i.e. clicks on the filter button above a list to make or edit filter.
Two types of filters Named or Default:
    User can save a filter with a name for later selection or it will always default to "Default" (localized) if not edited but will always require saving to server.
    Generic "default" filter is always personal, not public / shared
    - This is a client issue, Server doesn't care what the filters are called adn has no special processing for default filters
Named filters can be made public or personal.  If public then all users with rights to that object can see them, personal are always only personal.
Filter is constructed from an FILTEROPTIONS object fetched from the server list route that has a list type name which is unique to that list route 
and also lists all the fields filterable, their type and the locale key to display it
    - e.g.: {ListKey:"widget",fields:[{fld:"name",lt:"WidgetName",type:"text"},{fld:"dollarAmount",lt:"WidgetDollarAmount",type:"currency"}]}
    - List key 
Certain types have extended abilities, for example dates have the classic floating AyaNova date ranges pre-defined or specific dates
Filters are saved to the database:
    - Filter: Name, UserId, Public, ListKey, Filter (Json string) 
        - ListKey is always lower case to match biz object list key name
        - Filter format:
            - Array [{fld:"fieldname",op:"See filtercomparisonoperator class",value:"compareValue"},...] these are all AND in sql, no OR 
            - fld=name of field to filter by
                - always all lower case 
                - Straight up field name like "name"
                - Could be compound for joins like "table.name" (no a prepends the table name)
                - Special indirect values such as "[TAGS]" which means cross filter with tags
            - op=one of the values specified in the FilterComparisonOperator class in Biz namespace
                - Note: no Like on purpose, that would require input, better to hard code a starts with, ends with, contains and not bothering with the negative of those three as I don't see it being widely used
            - value = string version of direct comparison value or could be a special token meaning more
                - Never an empty string, empty string is invalid value
                - All Tokens are a value surrounded by this fragment: "{[XXX]}" where XXX is the token
                - if empty or null then will be a token "{[null]}" 
                - If string then a string fragment, case is sensitive
                - If date then iso style date //RAVEN NOTE: it is my intention that dates come in iso8601 UTC format from the client
                - could be whole number or decimal number
                - Could be a special "macro" filter value like "{[THIS_MONTH]}" 
                - Could be a series of id values like this "[23,45,56,123]" as in tag id's or something related to that case.
   
Upon user selecting a filter to use the list query string has the regular paging info but also the filter id as a query parameter 
    - Server loads the filter if it's public or has the user ID if it's personal only
    - If list not found then it will return a 404 instead of the list    
    - server loads the filter, generates the sql based on the stored filter, adds the sort by and offset / page, runs the query and then returns the data as json collection to the client

--------------------------------------------------------
NOTES ABOUT WHY I DID THE FILTEROPTIONS LIKE I DID:
//Need a collection of fields and types and locale keys for
    //  - Client fetching filteroptions via list class
    //      - Just a static list of items localized and sent to the client
    //  - DataFilter validation via list class
    //      - static list of items to compare against
    //  - ToSql from DataFilter validation and query building via list class
    //      - Static list of filter options so that it can build sql fragment (needs to know type, possibly the field name [or that is inferred probably])
    //      - Ideally each list object will have it's own chunk of code to handle it's shit with tosql just making the fragments of sql like in v7
    //      - Again, a static list of items to check against



    //Where to store that?
    //all cases are via list class so really the whole thing is self contained and no need for an interface at all
--------------------------------------------------


SORTING
=-=-=-=-
Sorting is done same as filtering but property on datafilter is called Sort and it's also a json Array
Fields are: "fld" which is the same column name as in a datafilter and "dir" for direction which will contain a single character either a "-" or a "+" for descending and ascending respectively
If no Sort is defined the default will be by ID number descending meaning the most recent records in that table will be first

