diff --git a/devdocs/todo.txt b/devdocs/todo.txt index 1aa80905..c62f40d0 100644 --- a/devdocs/todo.txt +++ b/devdocs/todo.txt @@ -18,13 +18,17 @@ GRID LISTS TODO NOW: - Can it just make a default template if none is found? (no they are all required) - Once both lists are working: - abstract away the commonalities into other classes - - REFACTOR: There's going to be a fair number of data source lists in routes so.. - - NOT immediate issue, but once the lists are working... + - REFACTOR: There's going to be a fair number of data source lists in routes so.. - Do I make a route for each one or user provides a key of which list they want and that goes into a single route to return the data? - What about when there are dozens of reports, do they all hang off each object type controller or is there just a central data list route for all combined? - i.e. if I want to make a widget->user->Email report and a separate user email report are they each in widget and user - Or, because they are read only lists used for many things do they just go into a central route for read only lists? + - I LIKE CENTRAL BECAUSE IT"S TASK ORIENTED and will mean the object controllers can focus on CRUD stuff - Also rights issues might affect this..? + - MAYBE it should be a single class object per list with defined properties based on an abstract LIST_DEFINITION class + - Can store rights, field names, sql from etc etc, making the actual list route code maybe into a single controller and single route working off keyed names + - Then they can all go in a single folder for all report lists etc and can just crank out more as required over the years + - With a single class that contains only the names of the keys for fetching with descriptions and object types etc so can fetch by object type or whatever - One central route with keys would simplify the client end UI certainly - Maybe all WidgetController routes are only for CRUD (and mass change) ops and not for list retrieval? - Would simplify the WidgetController and biz for sure diff --git a/server/AyaNova/Controllers/WidgetController.cs b/server/AyaNova/Controllers/WidgetController.cs index 8e2ab4e7..ec02d527 100644 --- a/server/AyaNova/Controllers/WidgetController.cs +++ b/server/AyaNova/Controllers/WidgetController.cs @@ -84,31 +84,32 @@ namespace AyaNova.Api.Controllers } - /// - /// Get list for selection / viewing - /// - /// Required roles: Any (some roles might have restrictions on exact fields that are returned) - /// - /// - /// Paging, filtering and sorting options - /// Collection with paging data - [HttpGet("List", Name = nameof(List))] - public ActionResult List([FromQuery] ListOptions pagingOptions) - { - if (serverState.IsClosed) - return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason)); +//COMMENTED OUT, FOR NOW UNTIL I GET THE FULLY WORKING TEST LIST BELOW THEN COME BACK AND LOOK AT THIS + // /// + // /// Get list for selection / viewing + // /// + // /// Required roles: Any (some roles might have restrictions on exact fields that are returned) + // /// + // /// + // /// Paging, filtering and sorting options + // /// Collection with paging data + // [HttpGet("List", Name = nameof(List))] + // public ActionResult List([FromQuery] ListOptions pagingOptions) + // { + // if (serverState.IsClosed) + // return StatusCode(503, new ApiErrorResponse(ApiErrorCode.API_CLOSED, null, serverState.Reason)); - if (!ModelState.IsValid) - return BadRequest(new ApiErrorResponse(ModelState)); + // if (!ModelState.IsValid) + // return BadRequest(new ApiErrorResponse(ModelState)); - //Instantiate the business object handler - WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext); + // //Instantiate the business object handler + // WidgetBiz biz = WidgetBiz.GetBiz(ct, HttpContext); - ApiPagedResponse pr = biz.GetList(Url, nameof(List), pagingOptions).Result; - return Ok(new ApiOkWithPagingResponse(pr)); - // string ret= biz.GetList(Url, nameof(List), pagingOptions).Result; - // return Ok(ret); - } + // ApiPagedResponse pr = biz.GetList(Url, nameof(List), pagingOptions).Result; + // return Ok(new ApiOkWithPagingResponse(pr)); + // // string ret= biz.GetList(Url, nameof(List), pagingOptions).Result; + // // return Ok(ret); + // } /// /// TEST list with relationships diff --git a/server/AyaNova/biz/WidgetBiz.cs b/server/AyaNova/biz/WidgetBiz.cs index 3a48cfcf..c4822208 100644 --- a/server/AyaNova/biz/WidgetBiz.cs +++ b/server/AyaNova/biz/WidgetBiz.cs @@ -272,135 +272,137 @@ namespace AyaNova.Biz //Generic list of widgets #region GetList - internal async Task GetList(IUrlHelper Url, string routeName, ListOptions listOptions) - { + //COMMENTED OUT, FOR NOW UNTIL I GET THE FULLY WORKING TEST LIST BELOW THEN COME BACK AND LOOK AT THIS + // internal async Task GetList(IUrlHelper Url, string routeName, ListOptions listOptions) + // { - //TODO: Get template (MOCKED FOR NOW UNTIL PROOF OF CONCEPT) - var MOCK_WIDGET_DISPLAY_TEMPLATE_JSON = @" - { - ""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetroles"",""widgetstartdate"",""active""], - ""mini"":[""widgetname"",""widgetserial""] - } - "; + // //TODO: Get template (MOCKED FOR NOW UNTIL PROOF OF CONCEPT) + // var MOCK_WIDGET_DISPLAY_TEMPLATE_JSON = @" + // { + // ""full"":[""widgetname"",""widgetserial"",""widgetdollaramount"",""widgetroles"",""widgetstartdate"",""active""], + // ""mini"":[""widgetname"",""widgetserial""] + // } + // "; - //BUILD THE QUERY + // //BUILD THE QUERY - //SELECT FRAGMENT COLUMNS FROM TEMPLATE - //"select clm,clm,clm" - var qSelectColumns = SqlSelectBuilder.Build(AyaObjectFields.WIDGET_KEY, MOCK_WIDGET_DISPLAY_TEMPLATE_JSON, listOptions.Mini); + // //SELECT FRAGMENT COLUMNS FROM TEMPLATE + // //"select clm,clm,clm" + // var qSelectColumns = SqlSelectBuilder.Build(AyaObjectFields.WIDGET_KEY, MOCK_WIDGET_DISPLAY_TEMPLATE_JSON, listOptions.Mini); - var qFrom = "FROM AWIDGET"; + // var qFrom = "FROM AWIDGET"; - //FILTERED? - DataFilter TheFilter = null; - if (listOptions.DataFilterId > 0) - { - TheFilter = await ct.DataFilter.FirstOrDefaultAsync(x => x.Id == listOptions.DataFilterId); - } + // //FILTERED? + // DataFilter TheFilter = null; + // if (listOptions.DataFilterId > 0) + // { + // TheFilter = await ct.DataFilter.FirstOrDefaultAsync(x => x.Id == listOptions.DataFilterId); + // } - //WHERE CLAUSE - FILTER - var qWhere = string.Empty; - if (listOptions.DataFilterId > 0) - { - qWhere = SqlFilterCriteriaBuilder.DataFilterToSQLCriteria(TheFilter, AyaObjectFields.ObjectFieldsList(AyaObjectFields.WIDGET_KEY), UserId); - } + // //WHERE CLAUSE - FILTER + // var qWhere = string.Empty; + // if (listOptions.DataFilterId > 0) + // { + // qWhere = SqlFilterCriteriaBuilder.DataFilterToSQLCriteria(TheFilter, AyaObjectFields.ObjectFieldsList(AyaObjectFields.WIDGET_KEY), UserId); + // } - //ORDER BY CLAUSE - SORT - var qOrderBy = string.Empty; - if (listOptions.DataFilterId > 0) - { - //BUILD ORDER BY AND APPEND IT - qOrderBy = SqlFilterOrderByBuilder.DataFilterToSQLOrderBy(TheFilter); - } + // //ORDER BY CLAUSE - SORT + // var qOrderBy = string.Empty; + // if (listOptions.DataFilterId > 0) + // { + // //BUILD ORDER BY AND APPEND IT + // qOrderBy = SqlFilterOrderByBuilder.DataFilterToSQLOrderBy(TheFilter); + // } - //LIMIT AND OFFSET CLAUSE - PAGING - listOptions.Offset = listOptions.Offset ?? ListOptions.DefaultOffset; - listOptions.Limit = listOptions.Limit ?? ListOptions.DefaultLimit; - var qLimitOffset = $"LIMIT {listOptions.Limit} OFFSET {listOptions.Offset}"; + // //LIMIT AND OFFSET CLAUSE - PAGING + // listOptions.Offset = listOptions.Offset ?? ListOptions.DefaultOffset; + // listOptions.Limit = listOptions.Limit ?? ListOptions.DefaultLimit; + // var qLimitOffset = $"LIMIT {listOptions.Limit} OFFSET {listOptions.Offset}"; - //PUT IT ALL TOGETHER - string qDataQuery = string.Empty; - string qTotalRecordsQuery = string.Empty; - if (TheFilter != null) - { - qDataQuery = $"{qSelectColumns} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}"; - qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}"; - } - else - { - qDataQuery = $"{qSelectColumns} {qFrom} {qLimitOffset}"; - qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom}"; - } + // //PUT IT ALL TOGETHER + // string qDataQuery = string.Empty; + // string qTotalRecordsQuery = string.Empty; + // if (TheFilter != null) + // { + // qDataQuery = $"{qSelectColumns} {qFrom} {qWhere} {qOrderBy} {qLimitOffset}"; + // qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom} {qWhere}"; + // } + // else + // { + // qDataQuery = $"{qSelectColumns} {qFrom} {qLimitOffset}"; + // qTotalRecordsQuery = $"SELECT COUNT(*) {qFrom}"; + // } - //RETURN OBJECTS - List items = new List(); - long totalRecordCount = 0; + // //RETURN OBJECTS + // List items = new List(); + // long totalRecordCount = 0; - //RUN THE QUERY - using (var command = ct.Database.GetDbConnection().CreateCommand()) - { + // //RUN THE QUERY + // using (var command = ct.Database.GetDbConnection().CreateCommand()) + // { - ct.Database.OpenConnection(); - command.CommandText = qDataQuery; - using (var dr = command.ExecuteReader()) - { - while (dr.Read()) - { - object[] row = new object[dr.FieldCount]; - dr.GetValues(row); - items.Add(row); - } - } + // ct.Database.OpenConnection(); + // command.CommandText = qDataQuery; + // using (var dr = command.ExecuteReader()) + // { + // while (dr.Read()) + // { + // object[] row = new object[dr.FieldCount]; + // dr.GetValues(row); + // items.Add(row); + // } + // } - command.CommandText = qTotalRecordsQuery; - using (var dr = command.ExecuteReader()) - { - if (dr.Read()) - { - totalRecordCount = dr.GetInt64(0); - } - } - } + // command.CommandText = qTotalRecordsQuery; + // using (var dr = command.ExecuteReader()) + // { + // if (dr.Read()) + // { + // totalRecordCount = dr.GetInt64(0); + // } + // } + // } - //TODO: Build the return object in a clean format - //rows:{[ {},{v:"Green mechanics",id:32},{v:"...notes..."},{v:"42",id:42}, ...thousands more etc.... ]} + // //TODO: Build the return object in a clean format + // //rows:{[ {},{v:"Green mechanics",id:32},{v:"...notes..."},{v:"42",id:42}, ...thousands more etc.... ]} - //BUILD THE PAGING LINKS PORTION - var pageLinks = new PaginationLinkBuilder(Url, routeName, null, listOptions, totalRecordCount).PagingLinksObject(); + // //BUILD THE PAGING LINKS PORTION + // var pageLinks = new PaginationLinkBuilder(Url, routeName, null, listOptions, totalRecordCount).PagingLinksObject(); - //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT - string ColumnsJSON = string.Empty; - if (listOptions.Mini) - { - ColumnsJSON = AyaObjectFields.GenerateMINIListColumnsJSON(AyaType.Widget); - } - else - { - ColumnsJSON = AyaObjectFields.GenerateListColumnsJSONFromTemplate(AyaType.Widget, AyaObjectFields.WIDGET_KEY, MOCK_WIDGET_DISPLAY_TEMPLATE_JSON); - } + // //BUILD THE COLUMNS RETURN PROPERTY JSON FRAGMENT + // string ColumnsJSON = string.Empty; + // if (listOptions.Mini) + // { + // ColumnsJSON = AyaObjectFields.GenerateMINIListColumnsJSON(AyaType.Widget); + // } + // else + // { + // ColumnsJSON = AyaObjectFields.GenerateListColumnsJSONFromTemplate(AyaType.Widget, AyaObjectFields.WIDGET_KEY, MOCK_WIDGET_DISPLAY_TEMPLATE_JSON); + // } - //TODO: BUILD THE RETURN LIST OF DATA ITEMS - //If mini format all desired columns in order into the single mini return display (and set the only other return field which is ID) + // //TODO: BUILD THE RETURN LIST OF DATA ITEMS + // //If mini format all desired columns in order into the single mini return display (and set the only other return field which is ID) - //If wide then format the fields in oder chosen (grid sort and filter template has already done that part above) + // //If wide then format the fields in oder chosen (grid sort and filter template has already done that part above) - //TODO: Genericize the above block of building return when it's working as this code needs to be central and optimized as much as possible + // //TODO: Genericize the above block of building return when it's working as this code needs to be central and optimized as much as possible - ApiPagedResponse pr = new ApiPagedResponse(items, pageLinks, ColumnsJSON); - return pr; - } + // ApiPagedResponse pr = new ApiPagedResponse(items, pageLinks, ColumnsJSON); + // return pr; + // } #endregion //TEST WIDGET->USER->EMAILADDRESS multi table list + //once this is working can replicate at will #region TestGetWidgetUserEmailList internal async Task TestGetWidgetUserEmailList(IUrlHelper Url, string routeName, ListOptions listOptions) { @@ -411,7 +413,7 @@ namespace AyaNova.Biz ""mini"":[""widgetname"",""username"",""emailaddress""] } "; - var AyaObjectFieldsKey=AyaObjectFields.TEST_WIDGET_USER_EMAIL_ADDRESS_LIST_KEY; + var AyaObjectFieldsKey = AyaObjectFields.TEST_WIDGET_USER_EMAIL_ADDRESS_LIST_KEY; //BUILD THE QUERY /* @@ -495,8 +497,11 @@ namespace AyaNova.Biz } //TODO: Build the return object in a clean format + //THIS FORMAT IS INCORRECT I THINK + //IT SHOULD BE A FULLER OBJECT WITH THE PROPERTYNAME ?! + //rows:{[ {},{v:"Green mechanics",id:32},{v:"...notes..."},{v:"42",id:42}, ...thousands more etc.... ]} - //TODO: BUILD THE RETURN LIST OF DATA ITEMS + //If mini format all desired columns in order into the single mini return display (and set the only other return field which is ID) //If wide then format the fields in order chosen (grid sort and filter template has already done that part above) @@ -521,7 +526,6 @@ namespace AyaNova.Biz } - ApiPagedResponse pr = new ApiPagedResponse(items, pageLinks, ColumnsJSON); return pr; }