ngx-deebodata 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +37 -2
  2. package/fesm2022/ngx-deebodata.mjs +6969 -0
  3. package/fesm2022/ngx-deebodata.mjs.map +1 -0
  4. package/package.json +41 -18
  5. package/types/ngx-deebodata.d.ts +460 -0
  6. package/ng-package.json +0 -7
  7. package/src/lib/data-table/charts/bar-graph-component/bar-graph-component.css +0 -148
  8. package/src/lib/data-table/charts/bar-graph-component/bar-graph-component.html +0 -29
  9. package/src/lib/data-table/charts/bar-graph-component/bar-graph-component.spec.ts +0 -23
  10. package/src/lib/data-table/charts/bar-graph-component/bar-graph-component.ts +0 -282
  11. package/src/lib/data-table/charts/charts-and-graphs/charts-and-graphs.css +0 -27
  12. package/src/lib/data-table/charts/charts-and-graphs/charts-and-graphs.html +0 -53
  13. package/src/lib/data-table/charts/charts-and-graphs/charts-and-graphs.spec.ts +0 -23
  14. package/src/lib/data-table/charts/charts-and-graphs/charts-and-graphs.ts +0 -214
  15. package/src/lib/data-table/charts/column-chart/column-chart.css +0 -19
  16. package/src/lib/data-table/charts/column-chart/column-chart.html +0 -47
  17. package/src/lib/data-table/charts/column-chart/column-chart.spec.ts +0 -23
  18. package/src/lib/data-table/charts/column-chart/column-chart.ts +0 -178
  19. package/src/lib/data-table/charts/line-graph-component/line-graph-component.css +0 -25
  20. package/src/lib/data-table/charts/line-graph-component/line-graph-component.html +0 -59
  21. package/src/lib/data-table/charts/line-graph-component/line-graph-component.spec.ts +0 -23
  22. package/src/lib/data-table/charts/line-graph-component/line-graph-component.ts +0 -661
  23. package/src/lib/data-table/charts/num-value-distro-component/num-value-distro-component.css +0 -53
  24. package/src/lib/data-table/charts/num-value-distro-component/num-value-distro-component.html +0 -27
  25. package/src/lib/data-table/charts/num-value-distro-component/num-value-distro-component.spec.ts +0 -23
  26. package/src/lib/data-table/charts/num-value-distro-component/num-value-distro-component.ts +0 -210
  27. package/src/lib/data-table/charts/pie-graph-component/pie-graph-component.css +0 -0
  28. package/src/lib/data-table/charts/pie-graph-component/pie-graph-component.html +0 -15
  29. package/src/lib/data-table/charts/pie-graph-component/pie-graph-component.spec.ts +0 -23
  30. package/src/lib/data-table/charts/pie-graph-component/pie-graph-component.ts +0 -197
  31. package/src/lib/data-table/data-table-module/data-cell/data-cell.css +0 -0
  32. package/src/lib/data-table/data-table-module/data-cell/data-cell.html +0 -6
  33. package/src/lib/data-table/data-table-module/data-cell/data-cell.spec.ts +0 -23
  34. package/src/lib/data-table/data-table-module/data-cell/data-cell.ts +0 -298
  35. package/src/lib/data-table/data-table-module/data-table-header/data-table-header.css +0 -25
  36. package/src/lib/data-table/data-table-module/data-table-header/data-table-header.html +0 -55
  37. package/src/lib/data-table/data-table-module/data-table-header/data-table-header.spec.ts +0 -23
  38. package/src/lib/data-table/data-table-module/data-table-header/data-table-header.ts +0 -261
  39. package/src/lib/data-table/data-table-module/data-table-paginator/data-table-paginator.css +0 -61
  40. package/src/lib/data-table/data-table-module/data-table-paginator/data-table-paginator.html +0 -24
  41. package/src/lib/data-table/data-table-module/data-table-paginator/data-table-paginator.spec.ts +0 -23
  42. package/src/lib/data-table/data-table-module/data-table-paginator/data-table-paginator.ts +0 -125
  43. package/src/lib/data-table/data-table-module/export-component/export-component.css +0 -83
  44. package/src/lib/data-table/data-table-module/export-component/export-component.html +0 -16
  45. package/src/lib/data-table/data-table-module/export-component/export-component.spec.ts +0 -23
  46. package/src/lib/data-table/data-table-module/export-component/export-component.ts +0 -206
  47. package/src/lib/data-table/data-table-module/ngx-deebodata/ngx-deebodata.css +0 -92
  48. package/src/lib/data-table/data-table-module/ngx-deebodata/ngx-deebodata.html +0 -194
  49. package/src/lib/data-table/data-table-module/ngx-deebodata/ngx-deebodata.spec.ts +0 -23
  50. package/src/lib/data-table/data-table-module/ngx-deebodata/ngx-deebodata.ts +0 -2255
  51. package/src/lib/data-table/data-table-module/row-group-menu/row-group-menu.css +0 -14
  52. package/src/lib/data-table/data-table-module/row-group-menu/row-group-menu.html +0 -27
  53. package/src/lib/data-table/data-table-module/row-group-menu/row-group-menu.spec.ts +0 -23
  54. package/src/lib/data-table/data-table-module/row-group-menu/row-group-menu.ts +0 -58
  55. package/src/lib/data-table/data-table-module/row-group-panel/row-group-panel.css +0 -15
  56. package/src/lib/data-table/data-table-module/row-group-panel/row-group-panel.html +0 -48
  57. package/src/lib/data-table/data-table-module/row-group-panel/row-group-panel.spec.ts +0 -23
  58. package/src/lib/data-table/data-table-module/row-group-panel/row-group-panel.ts +0 -599
  59. package/src/lib/data-table/data-table-module/worker.worker.ts +0 -44
  60. package/src/lib/interfaces/cell-edit.ts +0 -7
  61. package/src/lib/interfaces/column-header.ts +0 -10
  62. package/src/lib/interfaces/column-styles.ts +0 -14
  63. package/src/lib/interfaces/column-symbol.ts +0 -4
  64. package/src/lib/interfaces/data-cell.ts +0 -14
  65. package/src/lib/interfaces/data-row.ts +0 -11
  66. package/src/lib/interfaces/row-number.ts +0 -4
  67. package/src/lib/services/common-service.spec.ts +0 -16
  68. package/src/lib/services/common-service.ts +0 -336
  69. package/src/lib/services/data-table-service.spec.ts +0 -16
  70. package/src/lib/services/data-table-service.ts +0 -605
  71. package/src/lib/services/table-drag-service.spec.ts +0 -16
  72. package/src/lib/services/table-drag-service.ts +0 -347
  73. package/src/lib/styles.css +0 -1068
  74. package/src/public-api.ts +0 -8
  75. package/tsconfig.lib.json +0 -17
  76. package/tsconfig.lib.prod.json +0 -11
  77. package/tsconfig.spec.json +0 -15
@@ -1,661 +0,0 @@
1
- import { Component, ElementRef, EventEmitter, HostListener, Input, NgZone, Output, signal, ViewChild } from '@angular/core';
2
- import { CommonService } from '../../../services/common-service';
3
- import { DataTableService } from '../../../services/data-table-service';
4
- import { CommonModule } from '@angular/common';
5
- import { FormsModule } from '@angular/forms';
6
-
7
- @Component({
8
- selector: 'app-line-graph-component',
9
- imports: [ CommonModule, FormsModule ],
10
- templateUrl: './line-graph-component.html',
11
- styleUrls: ['./line-graph-component.css', '../bar-graph-component/bar-graph-component.css', '../../../styles.css']
12
- })
13
- export class LineGraphComponent {
14
-
15
- @HostListener('window:resize', ['$event'])
16
- onWindowResize(e: Event) {
17
- this.handleStatChange(this.selStat, true)
18
- }
19
-
20
- alloneyr: boolean = false
21
- lblTxt: string = ""
22
- naddedtks = signal<any[]>([])
23
- nmrks: any[] = []
24
- dtmrks: any[] = []
25
- dtmrksH: any[] = []
26
- plots = signal<any[]>([])
27
- contScrollHgt: number = 0
28
- buildingStat: boolean = false
29
- maxYVal: string = "0";
30
- statData: any[] = []
31
- valOpts = signal<any[]>([])
32
- selStat: string = "avg"
33
- statBtnWid: string = "30px"
34
- titleTrail: string = ""
35
- useData: any[] = []
36
- uDates: any[] = []
37
- selDdVal: string = ""
38
- selTDOpt: number = -1
39
- numYPlots: number = 5
40
- bgDepVarHgt: number = 70//height of y ticks
41
- totalHgt: number = 297;
42
- graphMsg: string = "Loading..."
43
- currentDelta: string = ""
44
- currentDeltaCls: string = "neutral"
45
- timeDiffOpts: any[] = []
46
- statOpts: string[] = ["avg", "min", "max", "mode", "median", "sum"]
47
- @Input() data: any[] = []
48
- @Input() numCol: string = ""
49
- @Input() column: string = ""
50
- @Output("title") title: EventEmitter<string> = new EventEmitter();
51
- @ViewChild("yAxis", { static: true }) yAxis!: ElementRef<HTMLDivElement>;
52
- @ViewChild("lineGraph", { static: true }) lineGraph!: ElementRef<HTMLDivElement>;
53
- @ViewChild("lgContain", { static: true }) lgContain!: ElementRef<HTMLDivElement>;
54
- @ViewChild("auxOptsCont", { static: true }) auxOptsCont!: ElementRef<HTMLDivElement>;
55
- @ViewChild("statOptsCont", { static: true }) statOptsCont!: ElementRef<HTMLDivElement>;
56
- @ViewChild("lgCanvas", { static: true }) lgCanvas!: ElementRef<HTMLCanvasElement>;
57
-
58
- constructor(public common: CommonService,
59
- public dataTableService: DataTableService,
60
- private _zone: NgZone,)
61
- {}
62
-
63
- ngOnInit() {
64
- const cols = this.column.split(this.dataTableService.bgSep)
65
- this.totalHgt = ((this.bgDepVarHgt*(this.numYPlots-1))+17);
66
- if(cols.length === 3){
67
- this.titleTrail = this.common.titleCase(cols[1]) + " by " + this.common.titleCase(cols[0]);
68
- } else {
69
- if(this.numCol)
70
- this.titleTrail = this.common.titleCase(this.numCol) + " by " + this.common.titleCase(cols[0]);
71
- }
72
- }
73
-
74
- ngAfterContentInit() {
75
- this.buildLg()
76
- }
77
-
78
- buildLg() {
79
- let valData: any[] = []
80
- const strODtCol = this.column.split(this.dataTableService.bgSep)[0]
81
- if(this.dataTableService.dataFilSrtTracker[strODtCol].selDDVals && this.dataTableService.dataFilSrtTracker[strODtCol].selDDVals.length){
82
- const vals = this.dataTableService.dataFilSrtTracker[strODtCol].selDDVals?.filter( (g: any) => g.checked && g.value !== "(Select All)")
83
- this.valOpts.set(vals.map( (v: any) => v.value))
84
- if(!this.selDdVal)
85
- this.selDdVal = vals[0].value
86
- valData = this.data.filter( d => d["strColumn"] === this.selDdVal)
87
- } else {
88
- valData = this.data.filter( d => true)
89
- }
90
- if(this.selTDOpt > -1){//not all time
91
- try{
92
- const oneDay = (1000*60*60*24);
93
- let oData = valData.filter( v => v && v["dtColumn"] && this.common.isADateObject(v["dtColumn"]) && v["dtColumn"].toString() !== "Invalid Date").
94
- sort( (a, b) => a["dtColumn"] > b["dtColumn"] ? 1 : -1 );
95
- const vlen = oData.length
96
- const lastDate = oData[(vlen-1)].dtColumn.getTime()
97
- const cutoff = (lastDate-(this.selTDOpt*oneDay))
98
- valData = oData.filter( v => v["dtColumn"].getTime() >= cutoff )
99
- }catch(e){}
100
- }
101
- const dSet = new Set(valData.filter( v => true).sort( (a, b) => a["dtColumn"] > b["dtColumn"] ? 1 : -1 ).map( (d) => JSON.stringify(d["dtColumn"]) ))//unique dates
102
- dSet.forEach( (v) => {
103
- const pdt = JSON.parse(v)
104
- if(typeof pdt === "string")
105
- this.uDates.push(this.common.coerceDate(pdt))
106
- else
107
- this.uDates.push(pdt)
108
- });
109
- this.setUseableData(valData, this.selStat)
110
- setTimeout( () => {
111
- this.drawLineGraph(this.useData);
112
- this._zone.run( () => { this.buildingStat = false } );
113
- })
114
- }
115
-
116
- getYTDNumDays(dtmax: any) {
117
- try{
118
- const dt = new Date()
119
- const yr = dt.getFullYear()
120
- const oneDay = (1000*60*60*24);
121
- const jan1 = new Date("January 1, "+ yr +" 00:01:00")
122
- const gap = Math.floor((dtmax.getTime() - jan1.getTime()) / oneDay)
123
- return gap > 0 ? gap : null;
124
- } catch(e){ return null}
125
- }
126
-
127
- findTimeDiffOpts(milRange: number, dtmax: any) {
128
- let i = 0
129
- this.timeDiffOpts = []
130
- // const oneDay = (1000*60*60*24);
131
- // const range = Math.floor(milRange/oneDay)
132
- const ytd = "YTD"
133
- const ytdNum = this.getYTDNumDays(dtmax)
134
- let avail: any[] = [{text: "1D", val: 1}, {text: "5D", val: 5},{text: "1M", val: 31},
135
- {text: "6M", val: Math.ceil(365/2)},{text: "1Y", val: 365}, {text: ytd, val: ytdNum},
136
- {text: "5Y", val: ((365*5)+1)}];
137
- if(!ytdNum)
138
- avail = avail.filter( a => a.text !== ytd)
139
- const len = avail.length
140
- for(i; i < len; i++){
141
- const av = avail[i]
142
- // if(range > av.val)
143
- this.timeDiffOpts.push(av)
144
- }
145
- }
146
-
147
- handleStatChange(stat: string, resize?: boolean) {
148
- if(this.selStat === stat && !resize)
149
- return;
150
- this.killPlots("Loading...")
151
- this.buildingStat = true
152
- this.maxYVal = "0"
153
- this.selStat = stat
154
- if(!resize)
155
- this.title.emit(this.common.titleCase(stat) + " " + this.titleTrail);
156
- setTimeout( () => { this.buildLg() })
157
- }
158
-
159
- handleValSelChange(selVal: string) {
160
- this.killPlots("Loading...")
161
- this.buildingStat = true
162
- this.selDdVal = selVal
163
- this.maxYVal = "0"
164
- setTimeout( () => { this.buildLg() })
165
- }
166
-
167
- handleTimeDiffChange(topt: number) {
168
- this.killPlots("Loading...")
169
- this.buildingStat = true
170
- this.selTDOpt = topt
171
- this.maxYVal = "0"
172
- setTimeout( () => { this.buildLg() })
173
- }
174
-
175
- setUseableData(valArr: any[], stat: string) {
176
- const dlen = this.uDates.length
177
- this.useData = []
178
- let d = 0;
179
- for(d; d < dlen; d++){
180
- let obj = {}
181
- const dt = this.uDates[d]
182
- const justVal = valArr.filter( (d) => {
183
- return d && d[("dtColumn")] && this.common.isADateObject(d[("dtColumn")]) && d["dtColumn"].toString() !== "Invalid Date" &&
184
- this.common.isADateObject(dt) && dt.toString() !== "Invalid Date" && d[("dtColumn")].getTime() === dt.getTime()} ).
185
- map( function(d) {return d[("numColumn")]} )
186
- const jlen = justVal.length
187
- if(jlen){
188
- switch(stat){
189
- case "avg":
190
- obj = { dtColumn: dt, numColumn: (justVal.reduce( (acc, curr) => (acc += curr) , 0)/jlen) }
191
- break;
192
- case "min":
193
- obj = { dtColumn: dt, numColumn: (Math.min(...justVal)) }
194
- break;
195
- case "max":
196
- obj = { dtColumn: dt, numColumn: (Math.max(...justVal)) }
197
- break;
198
- case "sum":
199
- obj = { dtColumn: dt, numColumn: justVal.reduce( (acc, curr) => (acc += curr) , 0) }
200
- break;
201
- case "median":
202
- obj = { dtColumn: dt, numColumn: this.findDataMedian(justVal, jlen) }
203
- break;
204
- case "mode":
205
- obj = { dtColumn: dt, numColumn: this.findDataMode(justVal) }
206
- break;
207
- default: "avg"
208
- obj = { dtColumn: dt, numColumn: (justVal.reduce( (acc, curr) => (acc += curr) , 0)/jlen) };
209
- }
210
- this.useData.push(obj)
211
- }
212
- }
213
- }
214
-
215
- sizeUpBgDims() {
216
- const bgWid = this.lgContain.nativeElement.getBoundingClientRect().width
217
- const yWid = this.yAxis.nativeElement.getBoundingClientRect().width
218
- const offY = Math.ceil(yWid+5)
219
- this.statBtnWid = Math.floor((bgWid-offY)/this.statOpts.length) + "px";
220
- this.statOptsCont.nativeElement.style.marginLeft = offY + "px";
221
- this.auxOptsCont.nativeElement.style.marginLeft = offY + "px";
222
- }
223
-
224
- drawLineGraph(data: any[]): any {
225
- if(data && data.length){
226
- try{
227
- const lmarg = 60
228
- const dlen = data.length
229
- const lg = this.lineGraph.nativeElement
230
- const par = this.lgContain.nativeElement
231
- const canvas = this.lgCanvas.nativeElement
232
- lg.style.width = ((par.getBoundingClientRect().width*0.92) -lmarg) + "px";
233
- canvas.width = ((par.getBoundingClientRect().width*0.92) -lmarg)
234
- const dtopts = {year: "2-digit",month: "2-digit", day: "numeric"}
235
- const numCol = this.numCol || this.column.split(this.dataTableService.bgSep)[1]
236
- let lbly = this.common.sanitizeUi(numCol)
237
- const sym = this.dataTableService.dataFilSrtTracker[numCol].colCellSymbol
238
- if(sym)
239
- lbly += " ("+sym+")";
240
- par.setAttribute("data-yaxis", lbly)
241
-
242
- //numbers
243
- const numArr = data.map( (d) => d["numColumn"] ).
244
- filter( (a) => !!a && a >= 0 ).sort( (a, b) => (a - b)*-1 );
245
- if(numArr.length < 2 || !numArr.some( (n) => n > 0 ))
246
- return this.killPlots("Not enough data for a graph")
247
- const nlen = numArr.length;
248
- const nmmin = numArr[(nlen-1)]
249
- const nmmax = numArr[0]
250
- const nmrange = nmmax - nmmin;
251
- const nqtrdts = (nmrange/4) + nmmin
252
- const nhalfdts = (nmrange/2) + nmmin
253
- const nthrqtrdts = (nmrange*0.75) + nmmin
254
- const nokTickVal = [nmmax, nthrqtrdts, nhalfdts, nqtrdts, nmmin]//desc order!
255
- const ntklen = nokTickVal.length
256
- let nadded = [];
257
- let mckNaTs: any[] = []
258
- let t = 0
259
- this.maxYVal = nmmax < 1000 ? nmmax.toLocaleString(undefined, {maximumFractionDigits: 0}) : this.common.doBigData(nmmax);
260
- for(t; t < ntklen; t++){
261
- const val = nokTickVal[t]
262
- const ntkval: string = val < 1000 ? val.toLocaleString(undefined, {maximumFractionDigits: 0}) : this.common.doBigData(val);
263
- if(mckNaTs.map( n => n.value).indexOf(ntkval) > -1)
264
- continue
265
- mckNaTs.push({value: ntkval, visible: false})
266
- }
267
- this.naddedtks.set([...mckNaTs])
268
- let i = 0
269
- for(i; i < nlen; i++){//not seen but heard
270
- const unum = numArr[i]
271
- if(nadded.indexOf(unum) > -1)
272
- continue
273
- const pct = (Math.max(1, unum-nmmin) / Math.max(1, nmrange))
274
- const usenval = unum?.toLocaleString(undefined, {maximumFractionDigits: 2});
275
- this.nmrks.push({value: usenval, percent: pct.toFixed(2), visible: false})
276
- nadded.push(usenval)
277
- }
278
- //numbers
279
-
280
- //dates
281
- let arrFrmSet: any[] = []
282
- const dSet = new Set(data.map( (d) => d["dtColumn"] ))//unique dates
283
- dSet.forEach( (v) => { arrFrmSet.push(v) });
284
- if(arrFrmSet.length < 2)
285
- return this.killPlots("Not enough data for a graph");
286
- const dttype = typeof arrFrmSet[0];
287
- const ordDts = arrFrmSet.filter( (a) => !!a ).sort( (a, b) => {
288
- return (dttype !== "object" ? (parseInt(a.toString()) - parseInt(b.toString())) : ( a.getTime() - b.getTime() ))
289
- })
290
- let m = 0
291
- let added = []
292
- const olen = ordDts.length
293
- const yearvals = ordDts.map( (o) => typeof o !== "object" ? o : o.getFullYear() )
294
- this.alloneyr = (new Set(yearvals.filter( (d) => true )).size < 2) ? true : false;//unique years
295
- // let yrReg = new RegExp("sjdkgf", "g")//not gonna replace anything
296
- // if(this.alloneyr)
297
- // yrReg = new RegExp("\/" + yearvals[0], "g")
298
- let dtrange
299
- let dtmin: any; let dtmax: any;
300
- if(typeof ordDts[0] === "object"){
301
- dtmin = ordDts[0]
302
- dtmax = ordDts[(ordDts.length-1)]
303
- }
304
- if(typeof ordDts[0] === "number"){
305
- dtmin = ordDts[0]
306
- dtmax = ordDts[(ordDts.length-1)]
307
- }
308
- if(typeof ordDts[0] === "string" && !isNaN(parseInt(ordDts[0])) && !isNaN(parseInt(ordDts[(ordDts.length-1)]))){
309
- dtmin = parseInt(ordDts[0]);
310
- dtmax = parseInt(ordDts[(ordDts.length-1)])
311
- }
312
- dtrange = typeof ordDts[0] === "object" ? (dtmax.getTime() - dtmin.getTime()) : (dtmax - dtmin)
313
- if(!dtrange || typeof dtrange !== "number")
314
- return this.killPlots("Not enough data for a graph");
315
- if(this.selTDOpt === -1)
316
- setTimeout( () => { this.findTimeDiffOpts(dtrange, dtmax) }, 500)
317
- const figureDtTicks = (val: number) => (typeof dtmin === "object" ? new Date(val+dtmin.getTime()) : (val+dtmin))
318
- const halfdts = figureDtTicks(Math.ceil(dtrange/2))
319
- const okDtTks = [dtmin, halfdts, dtmax];
320
- let de = 0
321
- const dtklen = okDtTks.length
322
- for(de; de < dtklen; de++){
323
- const tval = okDtTks[de]
324
- const useDVal = this.common.isADateObject(tval) ? tval.toLocaleDateString('en-US', dtopts)/*.replace(yrReg, "")*/ : tval
325
- if(this.dtmrks.find( d => d.value === useDVal))
326
- continue;
327
- this.dtmrks.push({value: useDVal, left: 0, visible: false})
328
- }
329
- const oZ = ordDts[0].getTime()
330
- for(m; m < olen; m++){
331
- const oval = ordDts[m]
332
- const useDVal = this.common.isADateObject(oval) ? oval.toLocaleDateString('en-US', dtopts)/*.replace(yrReg, "")*/ : oval
333
- if(added.indexOf(useDVal) > -1)
334
- continue
335
- let pct: number = 0
336
- if(typeof ordDts[0] === "object")
337
- pct = ((ordDts[m].getTime()-oZ) / dtrange)
338
- if(typeof ordDts[0] === "number")
339
- pct = ((ordDts[m]-ordDts[0]) / dtrange)
340
- if(typeof ordDts[0] === "string")
341
- pct = ((parseInt(ordDts[m])-parseInt(ordDts[0])) / dtrange)
342
- this.dtmrksH.push({ value: useDVal, percent: pct, left: 0, visible: false })
343
- added.push(useDVal)
344
- }//space out the markers
345
- //dates
346
- //set graph dims
347
- setTimeout( (): any => {
348
- let r =0
349
- let hd =0
350
- const halfPlot = 2
351
- let lgbds = lg.getBoundingClientRect()
352
- const mrks = document.querySelectorAll("#" + par.id + " .lg-dt-marker")
353
- const mrlen = mrks.length
354
- const hmrlen = this.dtmrksH.length
355
- // const lastdtdv = mrks[mrlen-1].getBoundingClientRect()
356
- const space = lgbds.width//(lgbds.right - (lastdtdv.right/*-lmarg*/)) - halfPlot
357
- const divby = Math.max(1, (mrlen-1))
358
- const mrrgt = Math.ceil(space/divby)//divide space up by count-1 because last gets no marg right
359
- for(r; r < mrlen; r++){
360
- const dtmrk = this.dtmrks[r]
361
- if(dtmrk)
362
- dtmrk.left = (Math.floor(mrrgt*r)-halfPlot) + "px";
363
- }
364
- setTimeout( () => {
365
- lgbds = lg.getBoundingClientRect()
366
- const xrange = space
367
- for(hd; hd < hmrlen; hd++){
368
- const hmrk = this.dtmrksH[hd]
369
- if(hmrk)
370
- hmrk.left = Math.floor((hmrk.percent*xrange)) + "px";
371
- }
372
-
373
- const nmrks = document.querySelectorAll("#" + par.id + " .bg-dep-var")
374
- const nmrlen = nmrks.length
375
- const hnmrks = this.nmrks
376
- const hnmrlen = hnmrks.length
377
- //set graph dims
378
- //add x label
379
- let colsspl = this.column.split(this.dataTableService.bgSep)
380
- const useCol = colsspl.length === 3 ? colsspl[2] : colsspl[0]
381
- const pretXlbl = this.common.sanitizeUi(this.common.titleCase(useCol))
382
- this.lblTxt = pretXlbl
383
- if(this.alloneyr)
384
- this.lblTxt = yearvals[0] + " " + pretXlbl
385
- //add x label
386
- setTimeout( () => {
387
- //add plots
388
- lgbds = lg.getBoundingClientRect()
389
- const maxPtLft = xrange - halfPlot
390
- const maxPtBot = lgbds.height - (halfPlot*6) - 1;
391
- // const dtmrWid =mrks[0].getBoundingClientRect().width
392
- const findDtLft = (dt: any) => {
393
- let q = 0; let k = 0
394
- const ptval = this.common.isADateObject(dt) ? dt.toLocaleDateString('en-US', dtopts)/*.replace(yrReg, "")*/ : dt
395
- for(q; q < mrlen; q++){
396
- const dtmrk = this.dtmrks[q]
397
- if(dtmrk){
398
- const dttxt = dtmrk.value
399
- if(ptval === dttxt)
400
- return (parseFloat(dtmrk.left.replace(/[ ]?(px|\%)/g, "")) || 0)/* + (dtmrWid/2)*/ - halfPlot
401
- }
402
- }
403
-
404
- for(k; k < hmrlen; k++){
405
- const hm = this.dtmrksH[k]
406
- const dttxt = hm.value
407
- if(ptval === dttxt)
408
- return Math.min(maxPtLft, ((parseFloat(hm.left.replace(/[ ]?(px|\%)/g, "")) || 0))) - halfPlot
409
- }
410
- return 0;
411
- }
412
-
413
- const nmrHgt = (nmrks[0]?.getBoundingClientRect().height || 17)
414
- const lbot = lgbds.bottom
415
- const findNBot = (num: number) => {
416
- let q = 0; let k = 0
417
- const ptval = num?.toLocaleString(undefined, {maximumFractionDigits: 2});
418
- for(q; q < nmrlen; q++){
419
- const nmrk = this.naddedtks()[q]
420
- if(nmrk){
421
- const dttxt = nmrk.value
422
- if(ptval === dttxt)
423
- return Math.floor(lbot - nmrks[q].getBoundingClientRect().bottom) + (nmrHgt/2) - halfPlot/*halfPlot is half the dot*/
424
- }
425
- }
426
- for(k; k < hnmrlen; k++){
427
- const hnmrk = hnmrks[k]
428
- const dttxt = hnmrk.value
429
- if((ptval === dttxt) && hnmrk.percent){
430
- const totalh = Math.floor(lgbds.height*(hnmrk.percent || 0)) + (nmrHgt/2) - halfPlot
431
- return Math.min(maxPtBot, Math.ceil(totalh))/*halfPlot is half the dot*/
432
- }
433
- }
434
- return 0;
435
- }
436
- let p = 0;
437
- let skipped = 0
438
- let plots: any[] = []
439
- let lgColor: string = "#00a8f3"
440
- let lgUndColor: string = ""
441
- const ctx = canvas.getContext("2d")
442
- if(ctx){
443
- let mkPlts: any[] = []
444
- const whiteTxt = ["white", "#FFFFFF", "#ffffff", "rgb(255, 255, 255)", "rgb(255,255,255)"];
445
- if(this.dataTableService.themeColor1 && whiteTxt.indexOf(this.dataTableService.themeColor1) < 0)
446
- lgColor = this.dataTableService.themeColor1;
447
- let useCol: any = lgColor
448
- if(lgColor.startsWith("#"))
449
- useCol = this.common.hexToRgb(lgColor)
450
- else
451
- useCol = this.common.getRgbParts(lgColor)
452
- if(useCol && typeof useCol === "object")
453
- lgUndColor = "rgba("+useCol.r+", "+useCol.g+", "+useCol.b+", 0.2)";
454
- const bSym = ((sym && ["$","€","£","¥","₣","₹"].indexOf(sym) > -1) ? sym : "");
455
- const aSym = ((!sym || sym && ["$","€","£","¥","₣","₹"].indexOf(sym) > -1) ? "" : sym);
456
- const minFrac = bSym ? 2 : 0;//currency
457
- for(p; p < dlen; p++){
458
- try{
459
- const dval = data[p]
460
- if(!dval["dtColumn"] || (typeof dval["numColumn"] !== "number"))
461
- continue;
462
- const plft = Math.max(0, findDtLft(dval["dtColumn"]))
463
- const pbot = Math.max(0, findNBot(dval["numColumn"]))
464
- if(typeof plft !== "number" || typeof pbot !== "number")
465
- continue
466
- const usedval = this.common.isADateObject(dval["dtColumn"]) ? dval["dtColumn"].toLocaleDateString('en-US', dtopts)/*.replace(yrReg, "")*/ : dval["dtColumn"]
467
- let pt = {
468
- date: usedval,
469
- number: (bSym + dval["numColumn"].toLocaleString(undefined, {maximumFractionDigits: 2, minimumFractionDigits: minFrac}) + aSym),
470
- left: plft > 0 ? (plft+halfPlot) : plft,
471
- bottom: (pbot+(halfPlot*2)),
472
- }
473
- const plen = plots.push(pt)
474
- const ptBef = plots[plen-(2+skipped)]
475
- if(ptBef){
476
- const dx = pt.left - ptBef.left;
477
- const dy = (lgbds.height-pt.bottom) - (lgbds.height-ptBef.bottom);
478
- if(dx <= 20 && (p < (dlen-1))){
479
- if(!nokTickVal.includes(dval["numColumn"])){
480
- skipped += 1;
481
- continue
482
- }
483
- }
484
- skipped = 0
485
- this.drawCanvasLineGraph(ctx, dx, dy, ptBef.left, (lgbds.height-ptBef.bottom), lgColor, lgUndColor)
486
- }
487
- mkPlts.push(pt)
488
- }catch(e){}
489
- }
490
- this.plots.set(mkPlts)
491
- }
492
- //add plots
493
- this.sizeUpBgDims()
494
- this.calcCurrChangeOverTime()
495
- }, 100)
496
- })
497
- }, 250)
498
- }catch(e){}
499
- }
500
- }
501
-
502
- drawCanvasLineGraph(ctx: CanvasRenderingContext2D, sideA: number, sideB: number, xb: number, yb: number, color: string, ucolor: string) {
503
- // Define the vertices of the right triangle
504
- // Assuming the right angle is at (x1, y2)
505
- let x2 = xb + sideA;
506
- let y2 = yb + sideB; // Top-right vertex
507
-
508
- // Draw the hypotenuse
509
- ctx.beginPath();
510
- ctx.moveTo(xb, yb); // Start at one end of the hypotenuse
511
- ctx.lineTo(x2, y2); // Draw to the other end of the hypotenuse
512
- ctx.strokeStyle = color; // Make hypotenuse red for distinction
513
- ctx.lineWidth = 1;
514
- ctx.stroke();
515
-
516
- // Close the path to the bottom of the canvas for filling
517
- ctx.lineTo(x2, this.totalHgt); // Down to the bottom at the last x-coordinate
518
- ctx.lineTo(xb, this.totalHgt); // Across to the bottom at the first x-coordinate
519
- ctx.closePath(); // Connects back to the starting point (50, 100)
520
-
521
- ctx.fillStyle = ucolor || color; // Set the fill color
522
- ctx.fill(); // Fill the enclosed area
523
- }
524
-
525
- calcCurrChangeOverTime() {
526
- const dttype = typeof this.useData[0].dtColumn;
527
- const srtData = this.useData.filter( (a) => !!a.dtColumn ).sort( (a, b) => {
528
- return (dttype !== "object" ? (parseInt(a.dtColumn.toString()) - parseInt(b.dtColumn.toString())) : ( a.dtColumn.getTime() - b.dtColumn.getTime() ))
529
- })
530
- const srtLen = srtData.length
531
- const firstVal = srtData[0].numColumn
532
- const diff = srtData[srtLen-1].numColumn - firstVal
533
- this.currentDelta = (((diff > 0) ? "&plus; " : "") + ((diff/firstVal)*100).toLocaleString(undefined, { maximumFractionDigits: 2 }) + "%");
534
- this.currentDeltaCls = diff === 0 ? "neutral" : (diff > 0 ? "success" : "error-message");
535
- }
536
-
537
- findDataMedian(data: number[], len: number): number {
538
- if(len === 1)
539
- return data[0]
540
- if(len === 2)
541
- return (data[0]+data[1])/2
542
- const isOdd = len%2 !== 0
543
- if(isOdd){
544
- return data[Math.ceil(len/2)]
545
- } else {
546
- const loMed = data[len/2]
547
- const hiMed = data[len/2] + 1
548
- return (loMed+hiMed)/2
549
- }
550
- }
551
-
552
- getColumnValueCounts(data: any[]) {
553
- let i = 0
554
- let count: any = {}
555
- const len = data.length
556
- for(i; i < len; i++){
557
- const d = data[i]
558
- const val = "v" + d
559
- if(!count[val] || typeof count[val] === "undefined")
560
- count[val] = 1
561
- else
562
- count[val] += 1
563
- }
564
- return count;
565
- }
566
-
567
- findDataMode(data: any[]): number {
568
- const count = this.getColumnValueCounts(data)
569
- let most = null
570
- for(const prop in count){
571
- if(!most)
572
- most = {text: prop, amount: count[prop]}
573
- if(count[prop] > most.amount)
574
- most = {text: prop, amount: count[prop]}
575
- }
576
- if(most)
577
- return parseInt(most?.text.replace("v", ""))
578
- return 0;
579
- }
580
-
581
- showDotPlotInfo(dt: any, num: any): any {
582
- const mrlen = this.dtmrks.length
583
- const hmrlen = this.dtmrksH.length
584
- let q = 0; let k = 0
585
- for(q; q < mrlen; q++){
586
- const dttxt = this.dtmrks[q].value
587
- if(dt === dttxt)
588
- return this.dtmrks[q].visible = true
589
- }
590
-
591
- for(k; k < hmrlen; k++){
592
- const dttxt = this.dtmrksH[k].value
593
- if(dt === dttxt)
594
- return this.dtmrksH[k].visible = true
595
- }
596
-
597
- q = 0;
598
- k = 0;
599
- const nmrlen = this.naddedtks().length
600
- const hnmrlen = this.nmrks.length
601
- const ptval = num?.toLocaleString(undefined, {maximumFractionDigits: 2});
602
- for(q; q < nmrlen; q++){
603
- const dttxt = this.naddedtks()[q].value
604
- if(ptval === dttxt)
605
- this.naddedtks()[q].visible = true
606
- }
607
-
608
- for(k; k < hnmrlen; k++){
609
- const dttxt = this.nmrks[k].value
610
- if(ptval === dttxt)
611
- return this.nmrks[k].visible = true
612
- }
613
- }
614
-
615
- hideDotPlotInfo() {
616
- this.dtmrks = this.dtmrks.map( n => {
617
- n.visible = false
618
- return n
619
- })
620
- this.dtmrksH = this.dtmrksH.map( n => {
621
- n.visible = false
622
- return n
623
- })
624
- this.naddedtks.set(this.naddedtks().map( n => {
625
- n.visible = false
626
- return n
627
- }))
628
- this.nmrks = this.nmrks.map( n => {
629
- n.visible = false
630
- return n
631
- })
632
- }
633
-
634
- killPlots(msg?: string) {
635
- this.lblTxt = ""
636
- if(msg)
637
- this.graphMsg = msg
638
- this.selTDOpt = -1
639
- this.plots.set([])
640
- this.nmrks = []
641
- this.dtmrks = []
642
- this.uDates = []
643
- this.dtmrksH = []
644
- this.naddedtks.set([])
645
- this.useData = []
646
- this.currentDelta = ""
647
- this.clearCanvas()
648
- if(msg && /enough/g.test(msg))
649
- this.sizeUpBgDims()
650
- }
651
-
652
- clearCanvas() {
653
- const canvas = this.lgCanvas.nativeElement
654
- if(canvas){
655
- canvas.getContext("2d")?.clearRect(0, 0, canvas.width, canvas.height)
656
- }
657
- }
658
- ngOnDestroy() {
659
- this.killPlots()
660
- }
661
- }