| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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() | 
					
						
							|  |  |  |             }) | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |         ) | 
					
						
							| 
									
										
										
										
											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-09-08 21:40:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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) => { | 
					
						
							| 
									
										
										
										
											2022-06-28 03:21:18 +02:00
										 |  |  |                 const ac = a.cells[col]?.textContent?.toLowerCase() | 
					
						
							|  |  |  |                 const bc = b.cells[col]?.textContent?.toLowerCase() | 
					
						
							| 
									
										
										
										
											2022-03-29 00:20:10 +02:00
										 |  |  |                 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 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |