@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.
- package/dist/chatwms/datagrid.d.ts +1 -4
- package/dist/chatwms/datagrid.js +93 -108
- package/package.json +1 -1
|
@@ -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 {};
|
package/dist/chatwms/datagrid.js
CHANGED
|
@@ -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
|
-
|
|
958
|
-
|
|
940
|
+
...datagridState,
|
|
941
|
+
adjRowData: rows,
|
|
942
|
+
chartRowData,
|
|
943
|
+
html: `${buildHtmlTableHeader(htmlColumnNames)}${htmlBuf}${buildHtmlTableFooter()}`
|
|
959
944
|
};
|
|
960
945
|
}
|