@cellaware/utils 8.3.17 → 8.3.19

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.
@@ -8,6 +8,7 @@ export interface DatagridStateBase {
8
8
  export interface DatagridState extends DatagridStateBase {
9
9
  adjRowData: any[];
10
10
  chartRowData: any[];
11
+ html: string;
11
12
  }
12
13
  export declare function initDatagridState(): DatagridState;
13
14
  export type ColumnState = {
@@ -126,8 +127,4 @@ export declare function codifyCondition(condition: DatagridCondition): string;
126
127
  */
127
128
  export declare function stripNumericValueFormat(value: string | number | undefined): any;
128
129
  export declare function transformDatagrid(rows: any[], datagridState: DatagridStateBase, locale: string, condition?: DatagridCondition): DatagridState;
129
- export declare function datagridToString(datagridState: DatagridState, rowCnt?: number): {
130
- html: string;
131
- markdown: string;
132
- };
133
130
  export {};
@@ -3,7 +3,8 @@ import { CHATWMS_DEFAULT_LANGUAGE } from "./user.js";
3
3
  export function initDatagridState() {
4
4
  return {
5
5
  adjRowData: [],
6
- chartRowData: []
6
+ chartRowData: [],
7
+ html: ''
7
8
  };
8
9
  }
9
10
  export const DEFAULT_VALUE_FORMAT_VALUE = 'none';
@@ -756,6 +757,64 @@ function sortRows(data, sortModel) {
756
757
  return 0;
757
758
  });
758
759
  }
760
+ function processHtmlStyles(value, columnFormat, rowStyles, columnStyles) {
761
+ let columnStyle = {
762
+ columnName: '',
763
+ styles: []
764
+ };
765
+ // Reminder: Value Formatting is performed **before** Conditional Formatting.
766
+ // https://chatwms.io/user-manual/concepts/column-formatting#conditional-formatting
767
+ for (const condFmt of columnFormat.conditionalFormats.slice().reverse()) {
768
+ // `conditionalFormats` has already been sorted by `sequence`.
769
+ // NOTE: need to reverse the array for sequence to be correctly applied.
770
+ // NOTE: using `slice` to make shallow copy of array since `reverse` does so in place.
771
+ if (evaluateConditionalFormat(condFmt, columnFormat.type, formatNumberEnabled(columnFormat.valueFormat) ? stripNumericValueFormat(value) : value)) {
772
+ if (condFmt.row) {
773
+ rowStyles.push(condFmt.style);
774
+ }
775
+ else {
776
+ columnStyle.styles.push(condFmt.style);
777
+ }
778
+ }
779
+ }
780
+ columnStyles.push(columnStyle);
781
+ return [rowStyles, columnStyles];
782
+ }
783
+ function buildHtmlTableHeader(columnNames) {
784
+ let buf = '<table>\n\t<thead>\n\t\t<tr>';
785
+ for (const columnName of columnNames) {
786
+ buf += `\n\t\t\t<th>${columnName}</th>`;
787
+ }
788
+ buf += '\n\t\t</tr>\n\t</thead>';
789
+ buf += '\n\t<tbody>';
790
+ return buf;
791
+ }
792
+ function buildHtmlTableFooter() {
793
+ return '\n\t</tbody>\n</table>';
794
+ }
795
+ function buildHtmlRow(rowValues, rowStyles, columnStyles) {
796
+ let buf = '';
797
+ // Apply row styles.
798
+ if (rowStyles.length > 0) {
799
+ buf += `\n\t\t<tr class="${rowStyles.join(' ')}">`;
800
+ }
801
+ else {
802
+ buf += '\n\t\t<tr>';
803
+ }
804
+ // Write cell values with styles.
805
+ let colIdx = 0;
806
+ for (const rowValue of rowValues) {
807
+ if (columnStyles[colIdx].styles.length > 0) {
808
+ buf += `\n\t\t\t<td class="${columnStyles[colIdx].styles.join(' ')}">${rowValue}</td>`;
809
+ }
810
+ else {
811
+ buf += `\n\t\t\t<td>${rowValue}</td>`;
812
+ }
813
+ colIdx++;
814
+ }
815
+ buf += '\n\t\t</tr>';
816
+ return buf;
817
+ }
759
818
  export function transformDatagrid(rows, datagridState, locale, condition) {
760
819
  const columnState = datagridState.columnState ?? [];
761
820
  const filterModel = datagridState.filterModel ?? {};
@@ -764,6 +823,8 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
764
823
  const { rowGroupCols, pivotCols, valueCols, sortModel } = parseColumnState(columnState);
765
824
  rows = filterRows(rows, filterModel);
766
825
  const chartRowData = [];
826
+ let htmlBuf = '';
827
+ const htmlColumnNames = [];
767
828
  // IMPORTANT: we evaluate the datagrid condition AFTER we are done with all transformations.
768
829
  // NOTE: we do not need any pivot columns for pivot mode to be valid.
769
830
  // https://chatwms.io/user-manual/chatwms/faq#q-do-i-have-to-have-a-group-column-to-just-display-a-count-in-the-datagrid
@@ -773,14 +834,23 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
773
834
  rows = sortModel.length > 0 ? sortRows(rows, sortModel) : rows;
774
835
  let mappedDisplayColumnNames = new Map();
775
836
  // Should not need to do hidden/visible column analysis -- pivoting creates new results with only the necessary columns.
837
+ let rowIdx = 0;
776
838
  rows.forEach(row => {
777
839
  let chartRow = {};
840
+ let htmlRowValues = [];
841
+ let htmlRowStyles = [];
842
+ let htmlColumnStyles = [];
778
843
  columnFormats.forEach(columnFormat => {
779
844
  if (columnFormat.name in row) {
780
845
  const value = row[columnFormat.name];
781
846
  const formattedValue = evaluateValueFormat(columnFormat, row[columnFormat.name], locale);
782
847
  row[columnFormat.displayName] = formattedValue;
783
848
  chartRow[columnFormat.displayName] = formatNumberEnabled(columnFormat.valueFormat) ? value : formattedValue;
849
+ htmlRowValues.push(formattedValue);
850
+ [htmlRowStyles, htmlColumnStyles] = processHtmlStyles(formattedValue, columnFormat, htmlRowStyles, htmlColumnStyles);
851
+ if (rowIdx === 0) {
852
+ htmlColumnNames.push(columnFormat.displayName);
853
+ }
784
854
  // Remove name in favor of display name.
785
855
  if (columnFormat.displayName !== columnFormat.name) {
786
856
  delete row[columnFormat.name];
@@ -797,6 +867,11 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
797
867
  const formattedValue = evaluateValueFormat(columnFormat, row[mappedColumnName], locale);
798
868
  row[adjDisplayName] = formattedValue;
799
869
  chartRow[adjDisplayName] = formatNumberEnabled(columnFormat.valueFormat) ? value : formattedValue;
870
+ htmlRowValues.push(formattedValue);
871
+ [htmlRowStyles, htmlColumnStyles] = processHtmlStyles(formattedValue, columnFormat, htmlRowStyles, htmlColumnStyles);
872
+ if (rowIdx === 0) {
873
+ htmlColumnNames.push(columnFormat.displayName);
874
+ }
800
875
  // Remove name in favor of display name.
801
876
  if (adjDisplayName !== mappedColumnName) {
802
877
  delete row[mappedColumnName];
@@ -815,6 +890,8 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
815
890
  }
816
891
  });
817
892
  chartRowData.push(chartRow);
893
+ htmlBuf += buildHtmlRow(htmlRowValues, htmlRowStyles, htmlColumnStyles);
894
+ rowIdx++;
818
895
  });
819
896
  if (!!condition) {
820
897
  rows = evaluatePivotDatagridCondition(rows, condition, mappedDisplayColumnNames);
@@ -827,8 +904,12 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
827
904
  rows = sortModel.length > 0 ? sortRows(rows, sortModel) : rows;
828
905
  const hiddenColumnNames = columnState.filter(column => !!column.hide && !column.rowGroup).map(column => column.colId) ?? [];
829
906
  const visibleColumnFormats = columnFormats.filter(column => !hiddenColumnNames.includes(column.name)) ?? [];
907
+ let rowIdx = 0;
830
908
  rows.forEach(row => {
831
909
  let chartRow = {};
910
+ let htmlRowValues = [];
911
+ let htmlRowStyles = [];
912
+ let htmlColumnStyles = [];
832
913
  hiddenColumnNames.forEach(columnName => {
833
914
  delete row[columnName];
834
915
  });
@@ -837,124 +918,28 @@ export function transformDatagrid(rows, datagridState, locale, condition) {
837
918
  const formattedValue = evaluateValueFormat(columnFormat, row[columnFormat.name], locale);
838
919
  row[columnFormat.displayName] = formattedValue;
839
920
  chartRow[columnFormat.displayName] = formatNumberEnabled(columnFormat.valueFormat) ? value : formattedValue;
921
+ htmlRowValues.push(formattedValue);
922
+ [htmlRowStyles, htmlColumnStyles] = processHtmlStyles(formattedValue, columnFormat, htmlRowStyles, htmlColumnStyles);
923
+ if (rowIdx === 0) {
924
+ htmlColumnNames.push(columnFormat.displayName);
925
+ }
840
926
  // Remove name in favor of display name.
841
927
  if (columnFormat.displayName !== columnFormat.name) {
842
928
  delete row[columnFormat.name];
843
929
  }
844
930
  });
845
931
  chartRowData.push(chartRow);
932
+ htmlBuf += buildHtmlRow(htmlRowValues, htmlRowStyles, htmlColumnStyles);
933
+ rowIdx++;
846
934
  });
847
935
  if (!!condition) {
848
936
  rows = evaluateDatagridCondition(rows, condition);
849
937
  }
850
938
  }
851
- return { ...datagridState, adjRowData: rows, chartRowData };
852
- }
853
- export function datagridToString(datagridState, rowCnt) {
854
- let htmlBuf = '';
855
- let markdownBuf = '';
856
- if (datagridState.adjRowData.length === 0) {
857
- return {
858
- html: htmlBuf,
859
- markdown: markdownBuf
860
- };
861
- }
862
- const columnFormats = datagridState.columnFormats ?? [];
863
- if (columnFormats.length === 0) {
864
- return {
865
- html: htmlBuf,
866
- markdown: markdownBuf
867
- };
868
- }
869
- const totalRowCnt = datagridState.adjRowData.length;
870
- rowCnt = rowCnt ?? totalRowCnt;
871
- if (rowCnt < totalRowCnt) {
872
- const message = `Displaying the first ${rowCnt} rows.`;
873
- htmlBuf += `<p style="font-style: italic;">${message}</p>`;
874
- markdownBuf += `\n*${message}*\n\n`;
875
- }
876
- // Header:
877
- htmlBuf += '<table>\n\t<thead>\n\t\t<tr>';
878
- let columns = [];
879
- for (const key in datagridState.adjRowData[0]) {
880
- columns.push(key);
881
- htmlBuf += `\n\t\t\t<th>${key}</th>`;
882
- markdownBuf += `| ${key} `;
883
- }
884
- markdownBuf += '|\n';
885
- for (const _ of columns) {
886
- markdownBuf += `| ----- `;
887
- }
888
- markdownBuf += '|\n';
889
- htmlBuf += '\n\t\t</tr>\n\t</thead>';
890
- // Rows:
891
- htmlBuf += '\n\t<tbody>';
892
- let rowIdx = 0;
893
- for (const row of datagridState.adjRowData) {
894
- if (rowIdx >= rowCnt) {
895
- break;
896
- }
897
- let colIdx = 0;
898
- const rowStyles = [];
899
- const colStyles = [];
900
- let cellValues = [];
901
- // Extract cell values and row/column styles first, then write to html & markdown.
902
- for (const key in row) {
903
- let val = row[key];
904
- if (val instanceof Date) {
905
- const dteStr = val.toISOString();
906
- val = dteStr.substring(0, dteStr.lastIndexOf('.'));
907
- }
908
- cellValues.push(val);
909
- let colStyle = {
910
- columnName: '',
911
- styles: []
912
- };
913
- // Reminder: Value Formatting is performed **before** Conditional Formatting.
914
- // https://chatwms.io/user-manual/concepts/column-formatting#conditional-formatting
915
- const colFmt = columnFormats[colIdx];
916
- for (const condFmt of colFmt.conditionalFormats.slice().reverse()) {
917
- // `conditionalFormats` has already been sorted by `sequence`.
918
- // NOTE: need to reverse the array for sequence to be correctly applied.
919
- // NOTE: using `slice` to make shallow copy of array since `reverse` does so in place.
920
- if (evaluateConditionalFormat(condFmt, colFmt.type, formatNumberEnabled(colFmt.valueFormat) ? stripNumericValueFormat(val) : val)) {
921
- if (condFmt.row) {
922
- rowStyles.push(condFmt.style);
923
- }
924
- else {
925
- colStyle.styles.push(condFmt.style);
926
- }
927
- }
928
- }
929
- colStyles.push(colStyle);
930
- colIdx++;
931
- }
932
- // Apply row styles.
933
- if (rowStyles.length > 0) {
934
- htmlBuf += `\n\t\t<tr class="${rowStyles.join(' ')}">`;
935
- }
936
- else {
937
- htmlBuf += '\n\t\t<tr>';
938
- }
939
- // Write cell values with styles.
940
- colIdx = 0;
941
- for (const rowValue of cellValues) {
942
- if (colStyles[colIdx].styles.length > 0) {
943
- htmlBuf += `\n\t\t\t<td class="${colStyles[colIdx].styles.join(' ')}">${rowValue}</td>`;
944
- }
945
- else {
946
- htmlBuf += `\n\t\t\t<td>${rowValue}</td>`;
947
- }
948
- markdownBuf += `| ${rowValue} `;
949
- colIdx++;
950
- }
951
- htmlBuf += '\n\t\t</tr>';
952
- markdownBuf += '|\n';
953
- rowIdx++;
954
- }
955
- htmlBuf += '\n\t</tbody>\n</table>';
956
939
  return {
957
- html: htmlBuf,
958
- markdown: markdownBuf
940
+ ...datagridState,
941
+ adjRowData: rows,
942
+ chartRowData,
943
+ html: `${buildHtmlTableHeader(htmlColumnNames)}${htmlBuf}${buildHtmlTableFooter()}`
959
944
  };
960
945
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cellaware/utils",
3
- "version": "8.3.17",
3
+ "version": "8.3.19",
4
4
  "description": "Cellaware Utilities for Node.js",
5
5
  "author": "Cellaware Technologies",
6
6
  "type": "module",