MAIN GRID SPECS

OVERVIEW
Main grids show all the stuff people have entered in Raven and are used for selection to edit/ view, filter and sort for reporting and mass operations.
Proposed system is a hybrid grid system that has two modes to take into account the width of the display device:
    - MINI mode (XS ) < 600 pixels wide (my Pixel 3a phone is 393px)
        - In this mode only one column shows and it's formatted according to the Display Format Template
        - DisplayFormatTemplate is specd in the core-display-format-template-system.txt doc
        - So the user chooses which columns to show in a small factor themselves, default is name only or equivalent
        - As the client already does all the presentation and translation formatting it will also handle mini column concatenation
        - The server's responsibility for mini is to use the mini format template which may well have different columns defined than the full
          - Return the data just the same as for the wide template but it's very likely different data


CASES
None that are intrinsically grid related really, just 3 or so regarding specfic fields to add to grids


REQUIREMENTS

Client
    - Client needs to tell the server which list template is required, i.e. it's client window size when fetching a list    
		- HYBRID BIMODAL: MINI or default which is large (for now but consider maybe a medium down the road in planning)
			- in MINI mode
				- the client sends "mini=true" to the client with the grid data request
				- Client receives two field list back (id and display field), displays the single field
			- in large mode
				- the client sends no mini= parameter as it's optional and understood to be full size
        
				- DATA the data object in the return contains the list of rows
          - Each row contains a bunch of row objects
            - Each column from the db is converted to an object and is formatted like this:
              - {v:[field value],id:42[optional id value if openable]}, {v:[field value],id:42[optional id value if openable]}...etc
            - rid flag: (was df)
              - A column with a flag of rid:true means it's the RowId column or IsRowId and must be visible to user at client
              - rid is not required because some datalists won't need one to open a record or have a practical row id due to the nature of the data
                - for example ones used for REPORTING


        - COLUMNS the list comes back as an object with not only the actual columns but also a separate property listing the set of columns in order to be displayed 
                    - Also their data type 
                    - Also need what type of object if openable with an url
					- Client expects an arbitrary set of columns in an arbitrary order defined by server so doesn't have a pre-ordained set of things.						
              - The client needs to be able to handle more columns than fit horizontally
              - The client needs to not wrap any column vertically but ellipse.. it instead
        - Client accepts a list of fields and types etc and generates the grid and populates the data dynamically
            - This means that I can make a general purpose Vue grid component, plunk it down on a form and then wrap it with what is unique about that form

Server
    - Server needs to accept a parameter from the client when a grid list is fetched that tells it if it needs to send a single column templated list 
        - vp="XS" I think would be sufficient (ViewPort = Extra Small)
    - Grid lists need to know what their template is as more than one list might use the same template?
    - SERVER SENDS LIST OF COLUMNS
			- The server needs to tell the client which columns are coming back with the list and what types etc so the client can just adapt to any template setting 
            - column list has type of object behind each column if applicable and user has rights to open so client can make hyperlinks
             - RID flagged column in column list is always the default RowID column corresponding to the underlying object and ID in the datalist
                - rid column must have an id and an object type to be valid rid column
    - SERVER SENDS DATA
        - Data in a standard format all grid lists json format, not based on set objects (I think I can do that, probably a hybrid object with JSON data)
            - Each row has each column as a object comprising of:
                - Display value (the data to show, not formatted yet, that's up to the client)
                - Optional: ID value (if the object is openable **** MUST CHECK RIGHTS ALSO HERE **** then this is the id to open for the client to put a hyperlink on that column)
                - To save bandwidth abbreviations are used in the column definitions:
                  - ColumnsJSON=@"""columns"":[ {""cm"":""Widget"",""dt"":""text"",""ay"":"+ AyaType.Widget.ToString()+ "}]";
                  - cm=column name translation key, dt=AyDataType, ay=AyaType to open on click of that column field (optional, not present if not openable)
                - rid flagged column in each row is *ALWAYS* the rowID column specified in objectfields with it's sql attributes
    - For example (wide list):
        data:{
            columns:{[ {cm:"lt_client_name",dt:text,ay:2},{cm:"lt_client_notes",dt:text},{cm:"lt_last_workorder",dt:number,ay:workorder}]}
            rows:{[ {},{v:"Green mechanics",id:32},"...notes...",{v:"42",id:42}, ...thousands more etc.... ]}
            }
    - For example (XS list)
        data:{
            columns:{[ {cm:"lt_client",dt:text,ay:client}]}
            rows:{ {display:"Green mechanics",id:32}, ...thousands more etc.... }
            }

        - has separate property defining all columns in list, their datatype and ayatype if openable

			

Back AND front end
   

OLD EF GRID QUERIES FOR REFERENCE
/*
This code 
// #pragma warning disable EF1000

            //             //GET THE FULL LIST OF ITEMS
            //             var items = await ct.Widget
            //                                         .FromSqlRaw(q)
            //                                         .AsNoTracking()
            //                                         .Skip(listOptions.Offset.Value)
            //                                         .Take(listOptions.Limit.Value)
            //                                         .ToArrayAsync();
            //             //GET THE RECORD COUNT
            //             var totalRecordCount = await ct.Widget
            //                                                     .FromSqlRaw(q)
            //                                                     .AsNoTracking()
            //                                                     .CountAsync();
            // #pragma warning restore EF1000

Resulted in these queries:

            "SELECT id AS df, name, serial, dollaramount, roles, startdate, active FROM AWIDGET ORDER BY ID DESC LIMIT 2 OFFSET 1"
            //PAGED FETCH LIST QUERY
            SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags
            FROM (
                SELECT *, xmin FROM AWIDGET  ORDER BY ID DESC
            ) AS a
            ORDER BY (SELECT 1)
            LIMIT @__p_2 OFFSET @__p_1
            2020-01-16 10:10:28.8786|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[@__p_2='2', @__p_1='1'], CommandType='Text', CommandTimeout='30']
            SELECT a.id, a.active, a.xmin, a.count, a.customfields, a.dollaramount, a.enddate, a.name, a.notes, a.roles, a.serial, a.startdate, a.tags
            FROM (
                SELECT *, xmin FROM AWIDGET  ORDER BY ID DESC
            ) AS a
            ORDER BY (SELECT 1)
            LIMIT @__p_2 OFFSET @__p_1

            //COUNT QUERY
                        SELECT COUNT(*)::INT
            FROM (
                SELECT *, xmin FROM AWIDGET  ORDER BY ID DESC
            ) AS a
            2020-01-16 10:10:28.8991|INFO|Microsoft.EntityFrameworkCore.Database.Command|Executed DbCommand (1ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
            SELECT COUNT(*)::INT
            FROM (
                SELECT *, xmin FROM AWIDGET  ORDER BY ID DESC
            ) AS a
            */

And this response:
{
  "data": [
    {
      "id": 99,
      "concurrency": 4125297,
      "name": "Gorgeous Wooden Chips 123",
      "serial": 99,
      "dollarAmount": 141.04,
      "active": true,
      "roles": 65536,
      "startDate": "2020-01-16T20:31:02.427985Z",
      "endDate": "2020-01-16T21:42:59.036309Z",
      "notes": "Magnam rem soluta consequatur ut voluptas sit repellat. Vel veniam voluptatem aliquam. Dolor facilis aliquid qui quos amet.\n\nEst in eligendi cumque ut in repellat sed ut tempore. Accusantium deserunt odio voluptates quia. Est eveniet exercitationem autem quam. Delectus vel pariatur voluptatem sit velit nisi est voluptates. Voluptatem qui aut cum provident dolores dolor repellat quidem deleniti. Quo incidunt aut nisi minus qui velit.\n\nError natus incidunt maxime est. Esse vitae libero laboriosam iste. In eos ad. Aut provident repellendus adipisci sed ullam id. Eius aliquam voluptatem quae reiciendis mollitia illo recusandae nulla dolorum. Omnis deserunt ea hic non.",
      "count": null,
      "customFields": "{\"c1\":\"2019-09-15T10:18:56.8261768Z\",\"c2\":\"Qui ipsam explicabo provident est molestiae est et est ipsum. Qui quis non rem ipsum. Odit quasi veniam fuga dolor. Illum excepturi voluptatem ducimus qui sunt fugit quam delectus.\",\"c3\":43969672,\"c4\":true,\"c5\":0.634534356945443}",
      "tags": [
        "zone-1"
      ]
    },
    {
      "id": 98,
      "concurrency": 4125290,
      "name": "Tasty Rubber Towels 122",
      "serial": 98,
      "dollarAmount": 736.05,
      "active": true,
      "roles": 131071,
      "startDate": "2020-01-16T20:42:08.10882Z",
      "endDate": "2020-01-16T22:52:54.031664Z",
      "notes": "Quo esse at esse quia. Est placeat voluptas. Velit fugit est quis nemo officia culpa officia et nam. Consequatur mollitia laboriosam tempora. Optio aut est quam fuga illum non mollitia quis.\n\nQui accusantium placeat voluptas eum. Voluptatem excepturi enim qui sunt. Delectus sequi illum libero repellat. Impedit illum sint consectetur.\n\nCum voluptatem nihil quis mollitia ut. Alias alias quis. Natus voluptatem ut omnis. In dolorem a et quia minus omnis ut. Ratione non velit nam corrupti repellendus quia voluptatum ut.",
      "count": null,
      "customFields": "{\"c1\":\"2020-11-08T09:13:34.4131282Z\",\"c2\":\"Consequatur ab sunt minima soluta aut quaerat aliquid aspernatur nihil. Et est incidunt. Minima rerum voluptatem sequi deleniti ducimus est soluta laboriosam excepturi. Aut vitae ut vel ea est. Voluptates officia in omnis blanditiis beatae exercitationem unde quibusdam.\",\"c3\":11364789,\"c4\":false,\"c5\":0.635780450718375}",
      "tags": [
        "silver"
      ]
    }
  ],
  "paging": {
    "count": 100,
    "offset": 1,
    "limit": 2,
    "first": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=1&pageSize=2",
    "previous": null,
    "next": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=2&pageSize=2",
    "last": "http://test.helloayanova.com/api/v8/Widget/ListWidgets?pageNo=50&pageSize=2"
  }
}


=========================================================== SCRATCH AREA ===============================================================
sample current response for widget list:
se body
Download

{
  "data": [
    {
      "id": 99,
      "concurrency": 3902247,
      "name": "Awesome Wooden Shirt 123",
      "serial": 99,
      "dollarAmount": 630.45,
      "active": true,
      "roles": 8,
      "startDate": "2020-01-08T15:29:39.626944Z",
      "endDate": "2020-01-08T17:37:12.605146Z",
      "notes": "Praesentium quisquam sit deserunt. Perferendis explicabo ipsam odit ab sequi mollitia ut. Sunt sint natus nihil quas quas est ut et. Non sed enim ut enim ut sed nisi reprehenderit.\n\nUt distinctio non. Rerum quam beatae illo qui fugiat fugiat totam. Vitae eveniet provident et consequuntur maxime perspiciatis et. Dolores veritatis sunt. Quia quae quo pariatur consequatur quia qui dolor. Vero aliquid voluptatem eos dicta provident atque eum.\n\nEt culpa rerum quis minus cumque eius facilis. Neque ad neque ratione. Eveniet exercitationem doloremque. Aut accusantium et voluptas. Laboriosam ipsa sit voluptatum voluptatem distinctio aut iusto et et. Et dolorem labore tempore odit.",
      "count": null,
      "customFields": "{\"c1\":\"2020-02-21T02:43:22.9011395Z\",\"c2\":\"Totam eligendi sed repudiandae delectus autem quas. At ut quasi quia tempore. Sit omnis modi a maiores quia est. Nam dolor amet. Inventore ea aut eum iusto quasi in nostrum. Aliquid voluptatibus error exercitationem accusamus molestias dolorem reprehenderit non.\",\"c3\":29779562,\"c4\":false,\"c5\":0.494726251109841}",
      "tags": [
        "xanthic"
      ]
    },
    {
      "id": 98,
      "concurrency": 3902238,
      "name": "Awesome Cotton Keyboard 122",
      "serial": 98,
      "dollarAmount": 926.28,
      "active": true,
      "roles": 65536,
      "startDate": "2020-01-08T15:51:11.298854Z",
      "endDate": "2020-01-08T16:57:08.492466Z",
      "notes": "Qui inventore dicta. In sit non ducimus doloremque iste quos aut dicta. At et impedit et. Nesciunt saepe voluptatem debitis sed.\n\nQuisquam rerum expedita omnis in sit eos itaque. Libero temporibus voluptatum laborum dolorem optio voluptas voluptates. Impedit voluptatem qui. Natus dolores maxime in harum.\n\nLibero dolor delectus. Molestiae praesentium quis autem ut. Neque dolore voluptatem omnis. Quo ut consequatur rem.",
      "count": null,
      "customFields": "{\"c1\":\"2019-11-05T04:23:27.6063023Z\",\"c2\":\"Commodi vitae neque sit alias cumque cupiditate. A quos dolorem qui est commodi voluptate aut facilis. Perspiciatis quasi doloribus aut autem expedita excepturi qui nesciunt officiis.\",\"c3\":98808200,\"c4\":true,\"c5\":0.369711980861478}",
      "tags": [
        "green",
        "brown",
        "zone-4"
      ]
    },
    {
      "id": 97,
      "concurrency": 3902230,
      "name": "Rustic Granite Pizza 121",
      "serial": 97,
      "dollarAmount": 742.41,
      "active": true,
      "roles": 4,
      "startDate": "2020-01-08T15:45:02.554965Z",
      "endDate": "2020-01-08T17:38:51.771714Z",
      "notes": "Maiores rerum consequatur eligendi. Mollitia error consequuntur quis vitae. Itaque totam quae quisquam est autem. Sunt et id non cum aperiam doloremque et qui. Qui est dolores officia et dolorem consequuntur molestias blanditiis nostrum.\n\nItaque tenetur cupiditate tempora exercitationem rerum sunt. Vel sit reiciendis. Dolorem vero velit praesentium enim. Nam soluta sed et tempore sint officia at doloremque facilis. Numquam ut dicta aut alias et repellendus consequatur ducimus quod. Natus quis aspernatur ut quibusdam dolores.\n\nVelit libero labore. Fuga quasi quis veniam minima aut. Odio est ducimus consectetur mollitia hic necessitatibus quaerat. Asperiores et qui qui.",
      "count": null,
      "customFields": "{\"c1\":\"2020-11-09T04:44:19.7102148Z\",\"c2\":\"Quisquam qui iusto voluptatibus incidunt dolore. Placeat praesentium aperiam harum culpa quas repellat aut corporis dolor. Explicabo et voluptatem. Debitis aliquam illo dolor eius esse quaerat aliquid rerum qui. Officiis quis consectetur consequatur fuga numquam earum fuga.\",\"c3\":20027131,\"c4\":true,\"c5\":0.225979427446602}",
      "tags": [
        "brown",
        "blue"
      ]
    }
  ],
  "paging": {
    "count": 100,
    "offset": 1,
    "limit": 3,
    "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=3",
    "previous": null,
    "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=2&pageSize=3",
    "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=34&pageSize=3"
  },
  "columns":[ 
      {name:"lt_client_name",datatype:text,ayatype:client},{name:"lt_client_notes",datatype:text},{name:"lt_last_workorder",datatype:number,ayatype:workorder}
  ]
}


{
  "data": [
   ...all rows here ...
      ]
    }
  ],
  "paging": {
   ...paging data...
  },
  "columns":{ 
     ...column definitions ....
    }
}


=-=-=-=-=-=-
PICKLIST FORMAT:
{ 
  "data": [
    {
      "id": 93,
      "name": "Awesome Cotton Sausages 117"
    }
  ],
  "paging": {
    "count": 100,
    "offset": 0,
    "limit": 1,
    "first": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1",
    "previous": null,
    "next": "http://localhost:7575/api/v8/Widget/PickList?pageNo=1&pageSize=1",
    "last": "http://localhost:7575/api/v8/Widget/PickList?pageNo=100&pageSize=1"
  }
}

...

LIST format:

	
Response body
Download

{
  "data": [
    {
      "id": 100,
      "concurrency": 3903699,
      "name": "Licensed Granite Cheese 124",
      "serial": 100,
      "dollarAmount": 764.57,
      "active": true,
      "roles": 8,
      "startDate": "2020-01-13T11:54:35.30427Z",
      "endDate": "2020-01-13T13:32:24.675256Z",
      "notes": "Consequuntur odio itaque quaerat et aspernatur rerum quis. Nam et ex assumenda deleniti. Vel est eum non exercitationem doloremque eos. Nesciunt voluptas et.\n\nCupiditate voluptatem pariatur. Totam et velit labore fugiat repudiandae. Harum consequatur quaerat ducimus animi dolores repellat dolorum. Necessitatibus sapiente non eveniet fugiat. Soluta voluptatem nihil omnis. Quasi et saepe nulla alias illum dolorem necessitatibus ut veniam.\n\nId est ullam quis est velit esse accusantium voluptas consequatur. Nesciunt error ab hic officia ullam sit. Vel inventore voluptatibus nam iure aut velit ducimus repellendus enim. Quisquam consequatur unde.",
      "count": null,
      "customFields": "{\"c1\":\"2020-09-27T12:59:50.4196015Z\",\"c2\":\"Id voluptatem cum id veniam hic accusamus labore deserunt. Ut non et possimus maiores repudiandae quia ea. Harum quo eius dicta iste laborum culpa in cumque illo.\",\"c3\":41534342,\"c4\":true,\"c5\":0.081620920487503}",
      "tags": [
        "jade",
        "brown",
        "quince",
        "zone-6",
        "zone-7"
      ]
    }
  ],
  "paging": {
    "count": 100,
    "offset": 0,
    "limit": 1,
    "first": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1",
    "previous": null,
    "next": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=1&pageSize=1",
    "last": "http://localhost:7575/api/v8/Widget/ListWidgets?pageNo=100&pageSize=1"
  }
}