| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  | import BaseUIElement from "../BaseUIElement"; | 
					
						
							|  |  |  | import {Utils} from "../../Utils"; | 
					
						
							|  |  |  | import Translations from "../i18n/Translations"; | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  | import {UIEventSource} from "../../Logic/UIEventSource"; | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class Table extends BaseUIElement { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     private readonly _header: BaseUIElement[]; | 
					
						
							|  |  |  |     private readonly _contents: BaseUIElement[][]; | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |     private readonly _contentStyle: string[][]; | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |     private readonly _sortable: boolean; | 
					
						
							|  |  |  |      | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |     constructor(header: (BaseUIElement | string)[], | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |                 contents: (BaseUIElement | string)[][], | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |                 options?: { | 
					
						
							|  |  |  |                     contentStyle?: string[][], | 
					
						
							|  |  |  |                     sortable?: false | boolean | 
					
						
							|  |  |  |                 }) { | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |         super(); | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |         this._contentStyle = options?.contentStyle ?? [["min-width: 9rem"]]; | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |         this._header = header?.map(Translations.W); | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |         this._contents = contents.map(row => row.map(Translations.W)); | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |         this._sortable = options?.sortable ?? false | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |     AsMarkdown(): string { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const headerMarkdownParts = this._header.map(hel => hel?.AsMarkdown() ?? " ") | 
					
						
							|  |  |  |         const header = headerMarkdownParts.join(" | "); | 
					
						
							| 
									
										
										
										
											2021-06-21 03:37:00 +02:00
										 |  |  |         const headerSep = headerMarkdownParts.map(part => '-'.repeat(part.length + 2)).join(" | ") | 
					
						
							|  |  |  |         const table = this._contents.map(row => row.map(el => el.AsMarkdown() ?? " ").join(" | ")).join("\n") | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 03:37:00 +02:00
										 |  |  |         return "\n\n" + [header, headerSep, table, ""].join("\n") | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |     protected InnerConstructElement(): HTMLElement { | 
					
						
							|  |  |  |         const table = document.createElement("table") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |         /** | 
					
						
							|  |  |  |          * Sortmode: i: sort column i ascending;  | 
					
						
							|  |  |  |          * if i is negative : sort column (-i - 1) descending | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         const sortmode = new UIEventSource<number>(undefined); | 
					
						
							|  |  |  |         const self = this; | 
					
						
							|  |  |  |         const headerElems = Utils.NoNull((this._header ?? []).map((elem, i) => { | 
					
						
							|  |  |  |             if(self._sortable){ | 
					
						
							|  |  |  |                 elem.onClick(() => { | 
					
						
							|  |  |  |                     const current = sortmode.data | 
					
						
							|  |  |  |                     if(current == i){ | 
					
						
							|  |  |  |                         sortmode.setData(- 1 - i ) | 
					
						
							|  |  |  |                     }else{ | 
					
						
							|  |  |  |                         sortmode.setData(i) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return elem.ConstructElement(); | 
					
						
							|  |  |  |         })) | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |         if (headerElems.length > 0) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |             const thead = document.createElement("thead") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |             const tr = document.createElement("tr"); | 
					
						
							|  |  |  |             headerElems.forEach(headerElem => { | 
					
						
							|  |  |  |                 const td = document.createElement("th") | 
					
						
							|  |  |  |                 td.appendChild(headerElem) | 
					
						
							|  |  |  |                 tr.appendChild(td) | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |             thead.appendChild(tr) | 
					
						
							|  |  |  |             table.appendChild(thead) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |         for (let i = 0; i < this._contents.length; i++) { | 
					
						
							| 
									
										
										
										
											2021-06-16 14:23:53 +02:00
										 |  |  |             let row = this._contents[i]; | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |             const tr = document.createElement("tr") | 
					
						
							| 
									
										
										
										
											2021-06-21 03:13:05 +02:00
										 |  |  |             for (let j = 0; j < row.length; j++) { | 
					
						
							| 
									
										
										
										
											2021-08-23 15:48:42 +02:00
										 |  |  |                 try { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let elem = row[j]; | 
					
						
							|  |  |  |                     const htmlElem = elem?.ConstructElement() | 
					
						
							|  |  |  |                     if (htmlElem === undefined) { | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     let style = undefined; | 
					
						
							|  |  |  |                     if (this._contentStyle !== undefined && this._contentStyle[i] !== undefined && this._contentStyle[j] !== undefined) { | 
					
						
							|  |  |  |                         style = this._contentStyle[i][j] | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     const td = document.createElement("td") | 
					
						
							|  |  |  |                     td.style.cssText = style; | 
					
						
							|  |  |  |                     td.appendChild(htmlElem) | 
					
						
							|  |  |  |                     tr.appendChild(td) | 
					
						
							|  |  |  |                 } catch (e) { | 
					
						
							|  |  |  |                     console.error("Could not render an element in a table due to", e, row[j]) | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             table.appendChild(tr) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |          | 
					
						
							|  |  |  |         sortmode.addCallback(sortCol => { | 
					
						
							|  |  |  |             if(sortCol === undefined){ | 
					
						
							|  |  |  |                 return | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             const descending = sortCol < 0 | 
					
						
							|  |  |  |             const col = descending ?  - sortCol - 1: sortCol; | 
					
						
							|  |  |  |             let rows: HTMLTableRowElement[] = Array.from(table.rows) | 
					
						
							|  |  |  |             rows.splice(0,1) // remove header row
 | 
					
						
							|  |  |  |             rows = rows.sort((a, b) => { | 
					
						
							|  |  |  |                 const ac = a.cells[col]?.innerText?.toLowerCase() | 
					
						
							|  |  |  |                 const bc = b.cells[col]?.innerText?.toLowerCase() | 
					
						
							|  |  |  |                 if(ac === bc){ | 
					
						
							|  |  |  |                     return 0 | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return( ac < bc !== descending) ? -1 : 1; | 
					
						
							|  |  |  |             }) | 
					
						
							|  |  |  |             for (let j = rows.length ; j > 1; j--) { | 
					
						
							|  |  |  |                 table.deleteRow(j) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             for (const row of rows) { | 
					
						
							|  |  |  |                 table.appendChild(row) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       | 
					
						
							| 
									
										
										
										
											2021-06-15 00:55:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return table; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } |